如何编写add_constraint函数为solnl()的极小化问题添加约束?
为solnl()优化问题编写动态添加约束的函数
问题背景
需要实现一个独立函数add_constraint(),用来给NlcOptim包中solnl()的极小化问题动态添加等式约束。现有基础代码如下:
##### 加载依赖包 library(MASS) library(NlcOptim) ### 目标函数(极小化) objfun <- function(x){ return(x[1]^2 + x[2]^2 + 1) } ### 初始约束函数 constraint <- function(x){ f = NULL f = rbind(f, x[2] - 2) return(list(ceq = f, c= NULL)) } #### 求解 x0 = c(1,1) solnl(x0, objfun=objfun, confun=constraint)
需求目标
需要添加新约束h(x) = x[1] - 1,最终生成的约束函数要与以下代码功能完全一致:
constraint = function(x){ f = NULL f = rbind(f, x[2] - 2) f = rbind(f, x[1] - 1 ) return(list(ceq = f, c= NULL)) }
尝试的失败代码
以下代码无法实现需求,因为返回的是字符串而非计算后的数值约束:
f = paste0("x[1] - 1") h = paste0("x[2] - 2") local = rbind(f,h) # 尝试编写的添加约束函数 add_constraint = function(local){ function(x){ f= NULL for( i in 1:2) f = rbind(f, local[i]) return(list(ceq=f, c= NULL)) } } constraint = add_constraint(local)
解决方案
方案一:基于约束函数的动态添加
这种方式更安全可靠,直接传递约束函数而非字符串:
# 定义初始约束函数 initial_constraint <- function(x) { list(ceq = x[2] - 2, c = NULL) } # 编写add_constraint函数:接收现有约束和新约束函数 add_constraint <- function(existing_constr, new_constr) { function(x) { # 获取现有约束的等式约束值 existing_ceq <- existing_constr(x)$ceq # 计算新约束的数值 new_ceq <- new_constr(x) # 合并所有等式约束 combined_ceq <- c(existing_ceq, new_ceq) # 返回符合solnl要求的格式 list(ceq = combined_ceq, c = NULL) } } # 定义新约束函数 new_h <- function(x) x[1] - 1 # 生成合并后的约束函数 constraint <- add_constraint(initial_constraint, new_h) # 测试求解 x0 <- c(1,1) solnl(x0, objfun = objfun, confun = constraint)
方案二:基于字符串表达式的动态添加
如果需要用字符串传递约束表达式,需通过eval(parse())解析计算:
# 存储所有约束表达式字符串 constr_strings <- c("x[2] - 2", "x[1] - 1") # 编写处理字符串约束的函数 add_constraint_str <- function(constr_strings) { function(x) { # 逐个计算约束表达式的数值 ceq_values <- sapply(constr_strings, function(str) { eval(parse(text = str), envir = list(x = x)) }) list(ceq = ceq_values, c = NULL) } } # 生成约束函数 constraint <- add_constraint_str(constr_strings) # 测试求解 x0 <- c(1,1) solnl(x0, objfun = objfun, confun = constraint)
失败原因说明
之前的代码直接返回字符串,而solnl()要求ceq必须是数值型向量(代表等式约束h(x)=0的计算值),因此必须将字符串表达式转换为可执行代码并计算出数值结果。
内容的提问来源于stack exchange,提问作者SuperLeo
相关产品推荐
相关产品推荐

