Julia中如何在JuMP目标函数内使用字典值为决策变量加权
JuMP模型中整数决策变量的字典加权实现方案
报错根源
JuMP在建模阶段会把目标函数、约束解析为求解器可识别的结构化表达式,此时决策变量仅为符号引用,还没有求解完成后的实际赋值。
你在目标函数中直接把absolute[y]作为字典的查询key,实际传入的是JuMP变量对象,和字典里存储的0-7的整数key完全不匹配,因此触发KeyError。
你设想的“等求解拿到变量实际值,再用值查询字典算权重”的逻辑,和JuMP的运行逻辑存在本质冲突:建模阶段不允许使用求解后才能获得的变量值作为索引,所有参与表达式构造的系数必须是提前确定的常数。
标准实现方案
针对取值为0-7整数的离散决策变量,最适配JuMP逻辑的方案是通过二元选择变量建立取值映射,全程用常系数参与目标构造,从根源上规避用变量当字典key的问题,实现步骤:
- 保留原有权重字典,提前计算每个可能取值对应的加权系数
- 为每个待决策的
absolute[y]定义一组二元选择变量,对应变量取0-7每个整数的可能性 - 增加约束保证每个
absolute[y]仅能选择一个取值 - 基于二元选择变量构造
absolute[y]的表达式映射,再用提前算好的常系数构造目标函数
对应的可运行代码:
# 定义原有权重字典 Dicopond = Dict(0=>1, 1=>2, 2=>4, 3=>8, 4=>16, 5=>32, 6=>64, 7=>128) # 二元选择变量:select[y,k]=1 代表第y个absolute变量取k值 @variable(model, select[y=1:10, k=0:7], Bin) # 约束:每个absolute变量仅能取一个确定值 @constraint(model, single_choice[y=1:10], sum(select[y, k] for k in 0:7) == 1) # 映射原absolute变量和二元选择变量的关系 @expression(model, absolute[y=1:10], sum(k * select[y, k] for k in 0:7)) # 构造最小化目标:所有乘子都是提前固定的常数,无变量当字典key的问题 @objective(model, Min, sum(k * Dicopond[k] * select[y, k] for y in 1:10, k in 0:7))
补充说明
- 上述方案生成标准线性MIP问题,所有主流JuMP适配的求解器(GLPK、Gurobi、CPLEX等)均可正常求解
- 因为二元选择变量的存在,映射得到的
absolute[y]会自动取0-7的整数值,不需要额外给absolute添加整数域约束,可减少求解器的冗余计算量 - 求解完成后,可通过
value.(absolute)获取每个变量的实际整数值,此时再用实际值查询字典做后续分析计算是完全合法的,只是不能将这类查询放到建模阶段的目标、约束构造流程中。
内容的提问来源于stack exchange,提问作者rox
相关产品推荐
相关产品推荐

