使用Pyomo与MindtPy求解MINLP时遇KeyError问题求助
问题描述
使用Pyomo结合MindtPy求解混合整数非线性规划(MINLP)模型时,触发以下错误:
Error in py_call_impl(callable, call_args$unnamed, call_args$named) :
KeyError: "Index 'slice(None, None, None)' is not valid for indexed component 'MindtPy_utils.objective_value'"
模型参数通过R的reticulate工具传入,Ipopt可正常输出非整数解,但MindtPy求解整数解时报错,相关代码见下文。
解决方法
1. 升级Pyomo与MindtPy至最新稳定版
该错误多由旧版本MindtPy对复杂目标函数的索引处理bug导致,执行以下命令完成升级:
pip install --upgrade pyomo mindtpy
2. 重构目标函数,拆分复杂嵌套逻辑
原目标函数嵌套prod与log运算,且直接在目标规则中生成迭代项,可能导致MindtPy无法正确识别组件索引。可通过引入辅助变量拆分计算逻辑:
3. 调整MindtPy求解器选项
尝试指定求解策略或开启变量边界计算,帮助求解器更好适配模型:
opt = SolverFactory('mindtpy') results = opt.solve( M, mip_solver='cplex', nlp_solver='ipopt', strategy='OA', # OA为默认策略,稳定性较强 calc_var_bound=True, # 收紧变量边界,提升求解效率 tee=True )
修改后的完整代码
import pandas as pd import random as r import numpy as np import glpk from pyomo.environ import * from amplpy import AMPL def pyblock(pyp, pytau, pyr, pys): M = ConcreteModel() M.m = Set(initialize=list(range(int(len(pyp))))) M.e = Set(initialize=list(range(int(len(pyr))))) M.s = Set(initialize=list(range(int(pys)))) M.r = Param(M.e, initialize=pyr) M.tau = Param(M.m, initialize=pytau) M.p = Param(M.m, M.e, M.s, initialize=0) M.n = Var(M.m, M.e, M.s, domain=NonNegativeIntegers, initialize=0) # 新增辅助变量存储prod计算结果 M.prod_term = Var(M.m, domain=NonNegativeReals) def prod_term_rule(M, i): return M.prod_term[i] == prod((1 - pyp[i,j,k])**M.n[i,j,k] for j in M.e for k in M.s) M.prod_term_con = Constraint(M.m, rule=prod_term_rule) # 重构目标函数,简化计算层级 def obj(M): return sum(-log(1 - M.prod_term[i]) for i in M.m) M.obj = Objective(rule=obj, sense=minimize) def fire_rate(M, j, k): return sum(M.n[i,j,k] for i in M.m) <= M.r[j] M.fire_rate = Constraint(M.e, M.s, rule=fire_rate) opt = SolverFactory('mindtpy') results = opt.solve( M, mip_solver='cplex', nlp_solver='ipopt', strategy='OA', calc_var_bound=True, tee=True ) # results.write() return M.n.extract_values()
内容的提问来源于stack exchange,提问作者Vince Vanterpool
相关产品推荐
相关产品推荐

