0

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

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

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 <- 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。这样我的功能列表将看起来像我在网上找到的手册和其他解决方案:

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 中这些类型问题的任何指导。

感谢您的任何帮助!

4

1 回答 1

0

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

将此更改为

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

x它返回为和的特定值返回的值parms

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

所以使用假数据:

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)nleqslvfor 例如global="none"和的参数global="gline"。您将看到纯牛顿在每次迭代中都不会降低函数标准。这只是幸运。

于 2020-05-05T06:52:16.490 回答