如何优雅初始化Julia JuMP变量与参数容器的起始值?
问题:JuMP变量容器批量初始化起始值(含@NLparameter)
作为Julia及JuMP新手,希望在创建变量容器时通过start选项批量初始化起始值,避免逐个调用set_start_value。
已定义函数与需求
自定义函数sam用于返回对应索引的起始值:
function sam(i, j) if i == "BRD" && j == "CAP" return 5 elseif i == "BRD" && j == "LAB" return 10 elseif i == "MLK" && j == "CAP" return 20 elseif i == "MLK" && j == "LAB" return 15 elseif i == "CAP" && j == "HOH" return 25 elseif i == "HOH" && j == "BRD" return 15 elseif i == "HOH" && j == "MLK" return 35 else return nothing end end
需要初始化变量容器Xᵢ[h, g](其中h = ["HOH"],g = ["BRD", "MLK"])的起始值为sam("HOH", "BRD")=15和sam("HOH", "MLK")=35,目前仅能通过逐个调用实现:
set_start_value(Xᵢ["HOH", "BRD"], sam("HOH", "BRD")) set_start_value(Xᵢ["HOH", "MLK"], sam("HOH", "MLK"))
失败的尝试写法
以下start选项写法均无法实现批量初始化:
@variable(model, 0.001 <= Xᵢ[h, g], start = sam(h, g)) # option 1 @variable(model, 0.001 <= Xᵢ[h, g], start = sam.(h, g)) # option 2 @variable(model, 0.001 <= Xᵢ[h, g], start = sam.(permute(h), g)) # option 3 @variable(model, 0.001 <= Xᵢ[h, g], start = [sam(h,g) for h in h, for g in g]) # option 4
同类问题:@NLparameter的批量初始化
同样的问题出现在@NLparameter的创建中,尝试过的写法均失败:
@NLparameter(model, 0.001 <= FFᶠ[f][h] == sam(f, h)) @NLparameter(model, 0.001 <= FFᶠ[f][h] == sam.(f, h)) @NLparameter(model, 0.001 <= FFᶠ[f][h] == sam.(permute(f), h)) @NLparameter(model, 0.001 <= FFᶠ[f][h] == [sam(f,h) for f in f, for h in h])
简化示例
给定函数f(x,y)=x²+y²及数组x=[1,2,3,4,5,6]、y=[1,2,3,4,5,6],如何编写@variable(model, v[x,y], start=f(x,y)),使v[1,2]的起始值为1²+2²=5?
解决方案
1. 匿名函数直接映射索引
JuMP的@variable和@NLparameter宏支持将start参数设置为接收索引的匿名函数,自动为每个变量匹配对应值:
# 变量容器Xᵢ的初始化 @variable(model, 0.001 <= Xᵢ[h, g], start = (i,j) -> sam(i,j)) # 简化示例的初始化 f(x,y) = x^2 + y^2 x = [1,2,3,4,5,6] y = [1,2,3,4,5,6] @variable(model, v[x,y], start = (a,b) -> f(a,b))
2. 预先生成起始值数组
先创建与索引维度匹配的起始值数组,再传给start参数:
# 变量容器Xᵢ的初始化 start_vals = [sam(i,j) for i in h, j in g] @variable(model, 0.001 <= Xᵢ[h, g], start = start_vals) # @NLparameter的初始化(注意索引格式改为f, h而非嵌套) param_vals = [sam(i,j) for i in f, j in h] @NLparameter(model, 0.001 <= FFᶠ[f, h] == param_vals)
失败原因说明
- option1:直接传入
sam(h,g)时,h和g是整个索引集合,而非单个元素,无法匹配函数的参数要求 - option2:
sam.(h,g)的广播维度不匹配(h是1元素数组,g是2元素数组) - option4:生成器中使用了与索引集合同名的循环变量(
h in h),覆盖了原变量导致错误
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

