求解 50 个非线性方程组 - fn(par,...) 中的错误:缺少参数
Solving a system of 50 non-linear equations - error in fn(par,...) : argument is missing
我正在尝试求解一个包含 50 个非线性方程的系统,如下所示:
给定一个向量 y,它包含 49 个不同的值,我想将这 49 个值转移到另一个向量中略有不同的值,比如 x,这样:
log(x[1], y[1]) = n
...
log(x[49], y[49]) = n
x[1] + ... + x[49] = 1
为了清楚起见,在上面的等式中,y[i]
是对数的底数。
我写了下面的代码,但似乎不起作用:
library(xlsx)
rm(list=ls())
setwd("C:/Users/.../folder")
my_data <- read.xlsx("samplefile.xlsx", 1)
y <- matrix(0:0, nrow=49,ncol=1)
for(i in 1:49) {
if(my_data[i,1]!=0) {
y[i,1] = 1/my_data[i,1]
}
}
for(i in 1:49) {
fn <- function(x,n) {
dummy1 <- log(x[i],y[i])-n
dummy2 <- sum(x[1:49])-1
return(c(dummy1,dummy2))
}
}
guess <- matrix(0.5:0.5, nrow = 50, ncol = 1)
nleqslv(guess,fn)
我希望它能解决 x[i]
和 n
。但是,我收到以下错误消息:
"Error in fn(par, ...) : argument "n" 缺失,没有默认值"
编辑:格式化
有两种方法可以解决您的问题。
第一个使用 nleqslv
求解具有 50 个变量的 50 个方程组:
x[1]
到 x[49]
和 n
。 nleqslv
求解的函数必须return一个包含50个元素的向量;方程组必须是平方的。
第二个将您的问题简化为 n
中的单个方程。
第一个解决方案:
library(nleqslv)
fn <- function(z,y) {
x <- z[1:49]
n <- z[50]
f <- numeric(50)
for( k in 1:49 ) f[k] <- log(x[k],y[k]) - n
f[50] <- sum(x) - 1
f
}
为 y 生成一些值并为 x
和 n
生成一些起始值并尝试求解
y <- rep(2,49)
guess <- c( rep(.5,49), 1)
res <- nleqslv(guess,fn,y=y)
res
检查结果:
# this should sum to 1
sum(res$x[1:49])
# value of n
res$x[50]
第二种解决方案:
利用 log(a,b) = n
意味着 a <- b^n
这一事实。
所以 log(x[k],y[k])=n
等价于 x[k]=y[k]^n
。
所以 x[1:49]
可以立即计算出来。我们只需要根据x
的元素和为1的限制来确定n
。
这意味着一个简单的函数
f2 <- function(n,y) {
x <- y^n # gives values for x
sum(x) - 1
}
现在像这样使用 uniroot
,假设 n
的值介于 -10 和 10 之间,并且端点处 f2
的符号具有相反的符号。
uniroot(f2,c(-10,10), y=y)
您可以 运行 此代码,并检查 nleqslv
和 uniroot
是否为 n
提供相同的结果。
这是否适用于您的数据取决于您自己的发现。
我正在尝试求解一个包含 50 个非线性方程的系统,如下所示:
给定一个向量 y,它包含 49 个不同的值,我想将这 49 个值转移到另一个向量中略有不同的值,比如 x,这样:
log(x[1], y[1]) = n
...
log(x[49], y[49]) = n
x[1] + ... + x[49] = 1
为了清楚起见,在上面的等式中,y[i]
是对数的底数。
我写了下面的代码,但似乎不起作用:
library(xlsx)
rm(list=ls())
setwd("C:/Users/.../folder")
my_data <- read.xlsx("samplefile.xlsx", 1)
y <- matrix(0:0, nrow=49,ncol=1)
for(i in 1:49) {
if(my_data[i,1]!=0) {
y[i,1] = 1/my_data[i,1]
}
}
for(i in 1:49) {
fn <- function(x,n) {
dummy1 <- log(x[i],y[i])-n
dummy2 <- sum(x[1:49])-1
return(c(dummy1,dummy2))
}
}
guess <- matrix(0.5:0.5, nrow = 50, ncol = 1)
nleqslv(guess,fn)
我希望它能解决 x[i]
和 n
。但是,我收到以下错误消息:
"Error in fn(par, ...) : argument "n" 缺失,没有默认值"
编辑:格式化
有两种方法可以解决您的问题。
第一个使用 nleqslv
求解具有 50 个变量的 50 个方程组:
x[1]
到 x[49]
和 n
。 nleqslv
求解的函数必须return一个包含50个元素的向量;方程组必须是平方的。
第二个将您的问题简化为 n
中的单个方程。
第一个解决方案:
library(nleqslv)
fn <- function(z,y) {
x <- z[1:49]
n <- z[50]
f <- numeric(50)
for( k in 1:49 ) f[k] <- log(x[k],y[k]) - n
f[50] <- sum(x) - 1
f
}
为 y 生成一些值并为 x
和 n
生成一些起始值并尝试求解
y <- rep(2,49)
guess <- c( rep(.5,49), 1)
res <- nleqslv(guess,fn,y=y)
res
检查结果:
# this should sum to 1
sum(res$x[1:49])
# value of n
res$x[50]
第二种解决方案:
利用 log(a,b) = n
意味着 a <- b^n
这一事实。
所以 log(x[k],y[k])=n
等价于 x[k]=y[k]^n
。
所以 x[1:49]
可以立即计算出来。我们只需要根据x
的元素和为1的限制来确定n
。
这意味着一个简单的函数
f2 <- function(n,y) {
x <- y^n # gives values for x
sum(x) - 1
}
现在像这样使用 uniroot
,假设 n
的值介于 -10 和 10 之间,并且端点处 f2
的符号具有相反的符号。
uniroot(f2,c(-10,10), y=y)
您可以 运行 此代码,并检查 nleqslv
和 uniroot
是否为 n
提供相同的结果。
这是否适用于您的数据取决于您自己的发现。