【问题标题】:How to solve n non-linear equations in R, based on vectors/matrices如何基于向量/矩阵求解 R 中的 n 个非线性方程
【发布时间】:2020-08-18 21:51:19
【问题描述】:

我正在尝试求解 R 中的 n 个方程组。n-1 个方程是非线性的,最后一个是线性的。如果有帮助,这是一个受约束的优化问题,n-1 方程是一阶条件,最后一个是预算约束。 n-1个非线性方程可以表示为:non-linear equations

如果图像不显示,可以逐个元素地定义,例如:

v_i*epsilon_i*cos(2/pi * e_i/delta_i)-lambda=0

其中 epsilon、v、e 和 delta 是 n-1 维向量,而 lambda 是所有方程共有的标量。

最后一个方程是|e|=c 形式的简单线性方程。也就是说,e 中所有元素的总和是某个已知的 c,称为 parms[1,4] 或“预算”。

我有兴趣求解向量 e 和常数 lambda,将其他所有内容视为给定。

我尝试使用 rootSolve 的多根。为此,我定义了一个向量 X,它应该是向量 e,并附加了 lambda,以便多根求解 x,并将 n 个方程作为列表给出。所有参数都保存在一个名为“parms”的矩阵中

我先定义n-1个非线性方程

convex_focs <- function(x = numeric(),parms = numeric()){
deltas = parms[,1]
v = parms[,2]
lambda = x[1]
e = x[2:length(x)]
epsilon_2 = exp(parms[,3]) - parms[,1]
return(epsilon_2*cos((pi/2)*(e/deltas))-lambda)
}

这个等式使用矩阵表示法,并且本身就可以正常工作。 然后我定义了最后一个线性方程:

convex_budget <- function(x = numeric(),parms = numeric()){
e = x[2:length(x)]
return(sum(e)-parms[1,4])
}

然后我尝试convex_system &lt;- function(x,parms) c(convex_focs,convex_budget ) 并致电:

multiroot(f = convex_system, maxiter = 500000, start =  c(0,rep(budget/length(parms[,1]),length(parms[,1]))), parms = parms[,])

这当然行不通,因为 rootSolve 将 convex_system 识别为两个方程,但 X 识别为 n 维。

如果我放弃最后一个方程,并将 lambda 视为给定的(所以只求解非线性方程)我可以得到一个解决方案。但这当然不好,因为我不知道 lambda。

所以我的第一个问题是: 1. 如何从我的向量中生成一个 rootSolve 将识别为系统的函数列表? 我尝试使用 lapply 或使用小插图来创建convex_focs 方程的列表,向量中的每个 elememt 都有一个,但想不出一种使它起作用的方法。 2. 为什么它会将我原来的convex_focs 函数识别为方程组,但是当我添加convex_budget 时它停止工作?

然后我(绝望地......)尝试手动定义一组函数,只查看 3 个非线性函数,而不是 n-1 个函数。这样我的函数列表就会像 manualother solutions I found online

convex_system <- function(x,parms) c(F1 = 
                                     function(x =x,parms = parms){
                                       deltas = parms[1,1]
                                       v = parms[1,2]
                                       lambda = x[1]
                                       e = x[2]
                                       epsilon_2 = exp(parms[1,3]) - parms[1,1]
                                       return(v*epsilon_2*cos((pi/2)*(e/deltas))-lambda)
                                     }
                                     ,
                                   F2 = 
                                     function(x = x,parms = parms){
                                       deltas = parms[2,1]
                                       v = parms[2,2]
                                       lambda = x[1]
                                       e = x[3]
                                       epsilon_2 = exp(parms[2,3]) - parms[2,1]
                                       return(v*epsilon_2*cos((pi/2)*(e/deltas))-lambda)
                                     }
                                   ,
                                   F3 = 
                                     function(x = x,parms = parms){
                                       deltas = parms[3,1]
                                       v = parms[3,2]
                                       lambda = x[1]
                                       e = x[4]
                                       epsilon_2 = exp(parms[3,3]) - parms[3,1]
                                       return(v*epsilon_2*cos((pi/2)*(e/deltas))-lambda)
                                     }
                                     ,
                                   F_budget = function(x = x,parms = parms){
                                       e = x[2:length(x)]
                                       return(sum(e)-parms[1,4])}
                                  )

然后打电话给multiroot(f = convex_system, maxiter = 500000, start = c(0,rep(budget/length(parms[1:3,1]),length(parms[1:3,1]))), parms = parms[1:3,]) 当我运行它时,我得到了错误

stode(y, times, func, parms = parms, ...) 中的错误: REAL() 只能应用于“数字”,而不是“列表”

我真的不明白 - 函数列表怎么可能不是“列表”类? 所以我的第二个问题是:

  1. 当函数不是简单的单行函数(如上面链接中的函数)时,如何生成函数列表

最后,我非常感谢任何有关如何更好地解决 R 中此类问题的指导。

感谢您的帮助!

【问题讨论】:

    标签: r optimization vector non-linear


    【解决方案1】:

    您的方法的主要问题是函数convex_system 的规范。您编写它的方式意味着它是一个函数向量,并且没有被评估。只需尝试单个语句convex_system(start,parms) 即可查看返回值。

    改成

    convex_system <- function(x,parms) c(convex_focs(x,parms),convex_budget(x,parms) )
    

    返回为 xparms 的特定值返回的值。

    您没有为常量和变量提供任何值。所以我们不能尝试。

    所以使用假数据:

    budget <- 100
    lambda <- 5
    
    parms <- matrix(c(1,2,3,
                      2,3,4,
                      3,4,5,
                      105,0,0), ncol=4,byrow=FALSE)
    
    parms
    xstart <- c(0,rep(budget/length(parms[1:3,1]),length(parms[1:3,1])))
    

    请不要忘记显示所有相关代码,即使是library 语句。

    我尝试了两个软件包来求解非线性方程组:nleqslvrootSolve

    library(nleqslv)
    nleqslv(xstart,convex_system,parm=parms)
    

    导致

    $x
    [1] -18.07036  37.79143  34.44652  32.76205
    
    $fvec
    [1]  6.578382e-10 -4.952128e-11 -1.673328e-12  0.000000e+00
    
    $termcd
    [1] 1
    
    $message
    [1] "Function criterion near zero"
    
    $scalex
    [1] 1 1 1 1
    
    $nfcnt
    [1] 146
    
    $njcnt
    [1] 7
    
    $iter
    [1] 92
    

    以上列表元素的含义见nleqslv的文档。此外,nleqslv 在这种情况下使用了 Broyden 方法,可以节省雅可比计算。

    使用rootSolve 给出:

    library(rootSolve)
    multiroot(f = convex_system, maxiter = 500000, start = xstart, parms=parms)
    $root
    [1] -18.07036  37.79143  34.44652  32.76205
    
    $f.root
    [1] 1.650808e-06 4.383290e-08 8.365979e-08 1.250555e-11
    
    $iter
    [1] 10
    
    $estim.precis
    [1] 4.445782e-07
    

    正如您所看到的,两者都给出了相同的结果,但nleqslv 的结果对于组成函数值似乎更接近于零(比较fvecf.root)。您应该注意收敛标准的差异(请参阅文档)。

    这是否能解决您的全部问题取决于您自己。

    附录

    似乎nleqslv 需要比rootSolve 更多的迭代次数。这与使用的全局搜索方法有关。通过使用函数testnslv,可以寻找一种使用较少迭代的全局方法,像这样

    testnslv(xstart,convex_system,parm=parms)
    

    结果如下

    Call:
    testnslv(x = xstart, fn = convex_system, parm = parms)
    
    Results:
        Method Global termcd Fcnt Jcnt Iter Message     Fnorm
    1   Newton  cline      1   21   12   12   Fcrit 1.770e-24
    2   Newton  qline      1   21   12   12   Fcrit 2.652e-24
    3   Newton  gline      1   17    8    8   Fcrit 5.717e-25
    4   Newton pwldog      1   45   31   31   Fcrit 9.837e-24
    5   Newton dbldog      1   34   26   26   Fcrit 1.508e-25
    6   Newton   hook      1   65   40   40   Fcrit 2.025e-26
    7   Newton   none      1   10   10   10   Fcrit 7.208e-25
    8  Broyden  cline      1   19    2   12   Fcrit 1.775e-19
    9  Broyden  qline      1   19    2   12   Fcrit 1.768e-19
    10 Broyden  gline      1   43    3   13   Fcrit 9.725e-18
    11 Broyden pwldog      1  161    4  105   Fcrit 1.028e-19
    12 Broyden dbldog      1  168    5  111   Fcrit 9.817e-21
    13 Broyden   hook      1  121    7   67   Fcrit 5.138e-25
    14 Broyden   none      1   11    1   11   Fcrit 7.487e-22
    

    可以看到,对于method="Newton"glinenone(纯 Newton-Raphson)方法需要最少的迭代次数。并且完全没有全局搜索的 Broyden 方法需要最少的函数评估次数。

    警告

    要了解为什么某些全局方法“更好”,请指定 control=list(trace=1) 作为 nleqslv 的参数,例如global="none"global="gline"。您将看到纯牛顿在每次迭代中都不会降低函数标准。这只是幸运。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-25
      相关资源
      最近更新 更多