使用 R 中的 nleqslv 包求解非线性方程
Solve non-linear equation using nleqslv package in R
我是 R 的新手,我正在尝试求解一个非线性方程。该等式是 4 个变量的函数:Q
、D
、E2+z
和 y1.new
。我将 Q
、D
和 E2+z
的值存储在长度为 3364 的单个向量中。对于这些情况中的每一种,我想找到 y1.new 满足下面的等式
0 = `y1.new` + (`Q`/((`D`^2)/8)*(2*acos(1-2*`y1.new`/`D`) - sin(2*acos(1-2*`y1.new`/`D`))))^2/(2*9.81) - `E2+z`.
我设置一个函数为
target.y1.new <- function(y1.new, Q=Q,D=D,`E2+z`=`E2+z`,g=9.81)
{
y <- numeric(1)
y[1] <- `y1.new` + (`Q`/((`D`^2)/8)*(2*acos(1-2*`y1.new`/`D`) - sin(2*acos(1-2*`y1.new`/`D`))))^2/(2*`g`) - `E2+z`
}
我的初始猜测存储在一个名为 y1
的向量中,也有 3364 个值
我尝试使用函数
nleqslv(`y1`,`target.y1.new`,control=list(btol=0.01),jacobian=TRUE)
但它会导致错误
Error in fn(par, ...) :
promise already under evaluation: recursive default argument reference or earlier problems?
谁能告诉我这里做错了什么?
提前致谢,
本尼
睿说的对。您在不需要的地方使用了反引号。
简化并更正您的函数 target.y1.new
结果
target.y1.new <- function(y1.new,g=9.81)
{
y <- numeric(length(y1.new))
y <- y1.new + (Q/((D^2)/8)*(2*acos(1-2*y1.new/D) - sin(2*acos(1-2*y1.new/D))))^2/(2*g) - E2pz
y
}
你说你有长度为 3364 的向量。你的函数适用于向量。这意味着您的函数应该 return 一个长度为 3364 的向量,这就是 return 值 y
的定义应该与输入向量具有相同长度的原因。
有了一些试用值,我们可以试试这个
Q <- c(1,2)
D <- c(1,2)
E2pz <- c(1,2)
y1 <- rep(.1,2)
您现在可以执行以下操作
nleqslv(y1,target.y1.new,control=list(btol=0.01),jacobian=TRUE)
这会给你一个解决方案。
但它不是最有效的。你的方程组是对角线的,因为任何方程的输入 y
不会出现在任何其他方程中。
nleqslv
有一个指定带(包括对角线)jacobian 的选项(参见手册)。如下
nleqslv(y1,target.y1.new,control=list(btol=0.01,dsub=0,dsuper=0),
jacobian=TRUE,method="Newton")
在这种情况下,最好使用 Newton 方法,因为默认的 Broyden 方法会做太多的工作。它不适用于对角雅可比矩阵。
我是 R 的新手,我正在尝试求解一个非线性方程。该等式是 4 个变量的函数:Q
、D
、E2+z
和 y1.new
。我将 Q
、D
和 E2+z
的值存储在长度为 3364 的单个向量中。对于这些情况中的每一种,我想找到 y1.new 满足下面的等式
0 = `y1.new` + (`Q`/((`D`^2)/8)*(2*acos(1-2*`y1.new`/`D`) - sin(2*acos(1-2*`y1.new`/`D`))))^2/(2*9.81) - `E2+z`.
我设置一个函数为
target.y1.new <- function(y1.new, Q=Q,D=D,`E2+z`=`E2+z`,g=9.81)
{
y <- numeric(1)
y[1] <- `y1.new` + (`Q`/((`D`^2)/8)*(2*acos(1-2*`y1.new`/`D`) - sin(2*acos(1-2*`y1.new`/`D`))))^2/(2*`g`) - `E2+z`
}
我的初始猜测存储在一个名为 y1
的向量中,也有 3364 个值
我尝试使用函数
nleqslv(`y1`,`target.y1.new`,control=list(btol=0.01),jacobian=TRUE)
但它会导致错误
Error in fn(par, ...) :
promise already under evaluation: recursive default argument reference or earlier problems?
谁能告诉我这里做错了什么?
提前致谢,
本尼
睿说的对。您在不需要的地方使用了反引号。
简化并更正您的函数 target.y1.new
结果
target.y1.new <- function(y1.new,g=9.81)
{
y <- numeric(length(y1.new))
y <- y1.new + (Q/((D^2)/8)*(2*acos(1-2*y1.new/D) - sin(2*acos(1-2*y1.new/D))))^2/(2*g) - E2pz
y
}
你说你有长度为 3364 的向量。你的函数适用于向量。这意味着您的函数应该 return 一个长度为 3364 的向量,这就是 return 值 y
的定义应该与输入向量具有相同长度的原因。
有了一些试用值,我们可以试试这个
Q <- c(1,2)
D <- c(1,2)
E2pz <- c(1,2)
y1 <- rep(.1,2)
您现在可以执行以下操作
nleqslv(y1,target.y1.new,control=list(btol=0.01),jacobian=TRUE)
这会给你一个解决方案。
但它不是最有效的。你的方程组是对角线的,因为任何方程的输入 y
不会出现在任何其他方程中。
nleqslv
有一个指定带(包括对角线)jacobian 的选项(参见手册)。如下
nleqslv(y1,target.y1.new,control=list(btol=0.01,dsub=0,dsuper=0),
jacobian=TRUE,method="Newton")
在这种情况下,最好使用 Newton 方法,因为默认的 Broyden 方法会做太多的工作。它不适用于对角雅可比矩阵。