r - 使用 nloptr 包进行更灵活的目标定义
问题描述
我正在使用该nloptr
软件包,一切正常。但我需要一种方法来以更快的方式定义目标函数和约束。我不能每次都手写所有的设置。
例如,我想解决这个问题:
library(nloptr)
eval_f <- function(x){
return(x[4]^2+x[7]^2+x[9]^2)
}
x0 = c(1,1,1,1,0.5,0,0.5,1,0)
hin <- function(x){
h <- numeric(6)
h[1] = x[1]+x[4]-x[2]-x[5]-0.01
h[2] = x[1]+x[4]-x[3]-x[6]-0.01
h[3] = x[2]+x[5]-x[3]-x[6]-0.01
h[4] = x[2]+x[8]-x[1]-x[7]-0.01
h[5] = x[2]+x[8]-x[3]-x[9]-0.01
h[6] = x[1]+x[7]-x[3]-x[9]-0.01
return(h)
}
heq <- function(x){
h <- numeric(1)
h[1] <- x[1]+x[2]+x[3]-3
return(h)
}
res <- slsqp(x0=x0,fn=eval_f,hin = hin,heq = heq)
一切正常。但我想以更快的方式定义目标函数。我可以以自动方式将另一个参数(索引)传递给函数吗?例如:
eval_f <- function(x,indices){
return(x[indices]^2)
}
我试过了,但我有一个错误。
解决方案
的...
参数slsqp
允许您将任意参数传递给目标函数。所以定义一个新的目标函数indices
作为参数:
eval_f2 <- function(x,indices){
return(sum(x[indices]^2))
}
...并包括indices=c(4,7,9)
(以匹配您之前的目标函数的定义):
res2 <- slsqp(x0=x0,fn=eval_f2, hin = hin,heq = heq, indices=c(4,7,9))
检查解决方案:
all.equal(res$par,res2$par) ## TRUE
工厂
更一般地说,您可以定义一个工厂- 一个返回函数的函数。这是有效的,因为函数具有可以存储变量(例如索引)的相关环境。即使在顶级函数不允许传递任意参数的情况下,这也将起作用(例如,如果您想为目标和约束函数使用不同的索引集,这可能很重要......)
eval_factory <- function(indices) {
fun <- function(x) {
return(sum(x[indices]^2))
}
return(fun)
}
res3 <- slsqp(x0=x0, fn=eval_factory(indices=c(4,7,9)),
hin = hin,heq = heq)
all.equal(res$par,res3$par) ## TRUE
欣工厂
hin_factory <- function(A,b) {
fun <- function(x) {
return((A %*% x) + b)
}
return(fun)
}
A0 <- matrix(c(1, -1, 0, 1,-1, 0, 0, 0, 0,
1, 0, -1, 1, 0, -1, 0, 0, 0,
0, 1, -1, 0, 1, -1, 0, 0, 0,
-1, 1, 0, 0, 0, 0,-1, 1, 0,
0, 1, -1, 0, 0, 0, 0, 1, -1,
1, 0, -1, 0, 0, 0, 1, 0, -1),
byrow=TRUE,ncol=9)
all.equal(c(hin_factory(A0,-0.01)(x0)),hin(x0))
res4 <- slsqp(x0=x0, fn=eval_factory(indices=c(4,7,9)),
hin = hin_factory(A0,b=-0.01), heq = heq)
all.equal(res$par, res4$par)
推荐阅读
- tabulator - Tabulator ajaxLoaderLoading 未按预期工作
- python-3.x - 我以前会如何创建一个 24/7 运行并发送电子邮件的应用程序?
- java - 如果从菜单中选择了数字,则Java菜单程序切换案例避免退出
- c++ - C++ 中具有输出限制的排列
- python - 如何使用“+”作为输入
- uml - 重塑数据框的正式 UML 表示
- linux - 如何增加子进程的数量
- javascript - 将变量从选择值传递到 document.querySelectorAll(此处为变量)
- python - 在一个范围内只使用一次函数的问题
- c# - 如何使用正则表达式从以下模式中提取数字: {"idProveedors":["73","3","67333"]} in C#