如何使用R的nleqslv求解带多约束的非线性函数最小值问题
你遇到的报错本质上是用错了工具,nleqslv是用于求解非线性方程组的工具,要求传入的函数返回值长度和待求解变量x的长度完全相等,你的x长度为4,但函数返回了13个约束值,自然会触发长度不匹配的错误。更关键的是,你的需求是带约束的最小化优化问题,并非求解方程组,完全不需要用nleqslv。
正确求解方案
推荐使用R的nloptr包求解这类带非线性约束的优化问题,操作步骤如下:
- 首先构造你要最小化的目标函数,返回单个标量值(对应你要最小化的求和式)
- 将所有约束整理为两类:
- 等式约束:仅1条,即所有x的和等于0
- 不等式约束:所有小于等于/大于等于的约束,统一整理为
g(x) ≤ 0的形式,比如x1 ≥ 0可以写成-x1 ≤ 0,x1 ≤ scm可以写成x1 - scm ≤0
- 选择支持非线性约束的优化算法(比如
LD_SLSQP),传入初始值、目标函数、约束函数即可求解
适配你测试参数的示例代码
首先安装加载依赖包:
# 首次使用执行安装 install.packages("nloptr") library(nloptr)
定义参数和优化所需函数:
a <- c(20, 34, 22, 27) scm <- 9300 INJ <- 4650 WIT <- 4650 # 目标函数:你要最小化的求和式,这里示例为a_i * x_i²的和,可替换为你的真实目标函数 eval_f <- function(x) { return(sum(a * x^2)) } # 不等式约束函数,返回所有g(x) ≤ 0的结果 eval_g_ineq <- function(x) { c( # 前k项累计和约束 x[1] - scm, -x[1], x[1]+x[2] - scm, -(x[1]+x[2]), x[1]+x[2]+x[3] - scm, -(x[1]+x[2]+x[3]), # x_i上下界约束 x[2] * (10 * x[1] + 1) - INJ, -x[2] - log(x[1]+1)*WIT, x[3] * (10 * (x[1]+x[2]) + 1) - INJ, -x[3] - log(x[1]+x[2]+1)*WIT, x[4] * (10 * (x[1]+x[2]+x[3]) +1) - INJ, -x[4] - log(x[1]+x[2]+x[3]+1)*WIT ) } # 等式约束函数,返回所有h(x) = 0的结果 eval_g_eq <- function(x) { return(sum(x)) }
执行优化:
# 初始值 x0 <- c(4650, -4650, 4650, -4650) # 优化参数设置 opts <- list( "algorithm" = "LD_SLSQP", "xtol_rel" = 1e-8, "maxeval" = 1e4 ) # 运行优化 result <- nloptr( x0 = x0, eval_f = eval_f, lb = NULL, ub = NULL, eval_g_ineq = eval_g_ineq, eval_g_eq = eval_g_eq, opts = opts ) # 查看最优解 print(result$solution) # 查看目标函数最小值 print(result$objective)
注意事项
- 如果出现收敛问题,可以调整初始值尽量贴近可行域,或者修改
opts里的迭代次数、收敛阈值参数 - 示例中的目标函数为通用写法,如果和你的实际需求不符,替换
eval_f里的计算逻辑即可
内容的提问来源于stack exchange,提问作者user9396820
相关产品推荐
相关产品推荐

