Julia中不使用JuMP实现带边界约束的多变量函数优化
带边界约束的Julia多变量优化实现方案
你当前使用的Optim库原生支持箱型边界约束,无需引入JuMP等第三方建模库,以下是两种可直接运行的实现方式:
方法1:使用Optim原生Fminbox约束适配(推荐)
Fminbox是Optim内置的箱型约束包装器,可以直接搭配你原来用的BFGS算法使用,无需额外引入其他依赖:
using Optim # 保留你原有的目标函数 fmin(x, a) = (1.0 - x[1])^a + 100.0 * (x[2] - x[1]^2)^a # 定义变量边界,若需要严格满足2<x[1]<5、4<x[2]<10,可微调为lower = [2.0+eps(), 4.0+eps()]、upper = [5.0-eps(),10.0-eps()] lower = [2.0, 4.0] upper = [5.0, 10.0] # 仅需在原有调用基础上增加边界参数、用Fminbox包装BFGS算法即可 # 初始点如果不在可行域内,Optim会自动投影到边界范围内,无需额外调整 r = optimize(x->fmin(x, 2), lower, upper, zeros(2), Fminbox(BFGS())) # 输出结果 ddd = r.minimizer dddd = r.minimum println("最优解:", ddd) println("最优值:", dddd)
如果你的目标函数无法提供梯度,也可以替换为无梯度算法,仅需修改算法参数为Fminbox(NelderMead())即可。
方法2:变量映射法(无约束优化功能依赖)
如果不想使用优化库的约束相关能力,也可以通过变量变换将无约束变量映射到你需要的区间内,直接用原来的无约束BFGS求解:
using Optim # sigmoid函数:将任意实数映射到(0,1)区间 σ(z) = 1/(1 + exp(-z)) # 自定义映射规则:把无约束变量z映射到(l, u)区间 map_to_range(z, l, u) = l + (u - l)*σ(z) # 原目标函数 fmin(x, a) = (1.0 - x[1])^a + 100.0 * (x[2] - x[1]^2)^a # 封装后的目标函数:自动把输入的无约束变量映射到目标区间再计算函数值 function constrained_f(z, a) x1 = map_to_range(z[1], 2.0, 5.0) x2 = map_to_range(z[2], 4.0, 10.0) return fmin([x1, x2], a) end # 直接用无约束BFGS求解,和你原来的调用逻辑完全一致 r = optimize(z->constrained_f(z, 2), zeros(2), BFGS()) # 把求解得到的无约束变量映射回原区间得到最终结果 opt_z = r.minimizer ddd = [map_to_range(opt_z[1], 2.0, 5.0), map_to_range(opt_z[2], 4.0, 10.0)] dddd = r.minimum println("最优解:", ddd) println("最优值:", dddd)
该方法天然满足严格区间约束,不依赖任何优化库的约束功能,通用性更强。
内容的提问来源于stack exchange,提问作者Yeon Jik Lee
相关产品推荐
相关产品推荐

