Pyomo 对 NoneType 使用 __round__ 方法
Posted
技术标签:
【中文标题】Pyomo 对 NoneType 使用 __round__ 方法【英文标题】:Pyomo uses __round__ method for NoneType 【发布时间】:2021-12-06 01:24:26 【问题描述】:我正在使用 Pyomo 实现一个简单的优化问题。
import pyomo
import pyomo.opt
import pyomo.environ as pe
import numpy as np
a = np.array([1,1,1,15])
b = np.array([1,2,3,4])
c = 10
P_res = 5
model = pe.ConcreteModel(name = "base optimizer")
model.M = pe.RangeSet(1,2)
model.T = pe.RangeSet(1,P_res)
model.state = pe.RangeSet(1,4)
st_lb = np.array((-1.22,) * P_res)
st_ub = np.array((1.22,) * P_res)
th_lb = np.array((0,) * P_res)
th_ub = np.array((1.0,) * P_res)
def th_b(model, i):
return (th_lb[i-1], th_ub[i-1])
model.th = pe.Var(model.T, domain=pe.Reals, bounds = th_b)
model.x = pe.Var(model.T, model.state, domain = pe.Reals)
model.z_predicate = pe.Var(model.T, model.M, domain=pe.Binary)
def obj_rule(model):
return model.th[P_res]**2
model.OBJ = pe.Objective(rule=obj_rule, sense = pe.minimize)
def init_state(model,s):
return model.x[1,s] == a[s-1]
def dynamic_1(model,t):
if t == P_res:
return pe.Constraint.Skip
return model.x[t+1,1] == model.x[t,1] + model.x[t,4] * pe.cos(model.x[t,3])
def dynamic_2(model,t):
if t == P_res:
return pe.Constraint.Skip
return model.x[t+1,2] == model.x[t,2] + model.x[t,4] * pe.sin(model.x[t,3])
def dynamic_3(model,t):
if t == P_res:
return pe.Constraint.Skip
return model.x[t+1,4] == model.x[t,4] + model.th[t]
model.InitConstraint = pe.Constraint(model.state, rule = init_state)
model.DynConstraint1 = pe.Constraint(model.T, rule=dynamic_1)
model.DynConstraint2 = pe.Constraint(model.T, rule=dynamic_2)
model.DynConstraint3 = pe.Constraint(model.T, rule=dynamic_3)
def binary_constraint(model,t):
return model.z_predicate[t,1] <= 1
model.BiConstraint = pe.Constraint(model.T,rule=binary_constraint)
solver = pyomo.opt.SolverFactory('mindtpy')
results = solver.solve(model, mip_solver='gurobi', nlp_solver='ipopt', tee=True)
但是,我收到以下错误。
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-7-d441aab4faca> in <module>
56
57 solver = pyomo.opt.SolverFactory('mindtpy')
---> 58 results = solver.solve(model, mip_solver='gurobi', nlp_solver='ipopt', tee=True)
59
60 # solver = pyomo.opt.SolverFactory('ipopt')
c:\users\hongk\appdata\local\programs\python\python36\lib\site-packages\pyomo\contrib\mindtpy\MindtPy.py in solve(self, model, **kwds)
169 # Algorithm main loop
170 with time_code(solve_data.timing, 'main loop'):
--> 171 MindtPy_iteration_loop(solve_data, config)
172 if solve_data.best_solution_found is not None:
173 # Update values in original model
c:\users\hongk\appdata\local\programs\python\python36\lib\site-packages\pyomo\contrib\mindtpy\iterate.py in MindtPy_iteration_loop(solve_data, config)
99 fixed_nlp, fixed_nlp_result, solve_data, config)
100
--> 101 if algorithm_should_terminate(solve_data, config, check_cycling=True):
102 last_iter_cuts = False
103 break
c:\users\hongk\appdata\local\programs\python\python36\lib\site-packages\pyomo\contrib\mindtpy\iterate.py in algorithm_should_terminate(solve_data, config, check_cycling)
307 if check_cycling:
308 if config.cycling_check or config.use_tabu_list:
--> 309 solve_data.curr_int_sol = get_integer_solution(solve_data.mip)
310 if config.cycling_check and solve_data.mip_iter >= 1:
311 if solve_data.curr_int_sol in set(solve_data.integer_list):
c:\users\hongk\appdata\local\programs\python\python36\lib\site-packages\pyomo\contrib\mindtpy\util.py in get_integer_solution(model, string_zero)
550 temp.append(int(round(var.value)))
551 else:
--> 552 temp.append(int(round(var.value)))
553 return tuple(temp)
554
TypeError: type NoneType doesn't define __round__ method
我试图注释掉 model.BiConstraint 并将最后两行替换为
solver = pyomo.opt.SolverFactory('ipopt')
results = solver.solve(model, tee=True)
结果很好。所以我猜错误来自model.BiConstraint。
有谁知道 Pyomo 为什么这样做?我无法从任何 Pyomo 材料中找到原因。
我的配置。 Python 3.6.13 :: Anaconda, Inc. Pyomo 6.1.2(Windows 10 上的 CPython 3.6.13) 古罗比 9.1.1 ipopt 3.11.1 mindtpy 0.1
【问题讨论】:
【参考方案1】:您的求解器设置出现了一些愚蠢的问题......我不熟悉使用 mindpy
的那种设置
这很好用:
solver = pe.SolverFactory('ipopt')
results = solver.solve(model)
print(results)
model.display()
进一步更新...
您最初的问题似乎与您的一部分 z_predicate
变量在您的模型中根本没有引用这一事实有关,特别是当 M=2 时。这导致它们“陈旧”,我认为这导致mindpy
呕吐。如果您将约束更改为:
model.BiConstraint = pe.Constraint(model.T,model.M,rule=binary_constraint)
mindpy
没问题。另请注意,此约束在您的模型中未激活,因为 z_predicate
未使用。
【讨论】:
但是 Ipopt 给出警告 `==> 警告:将 5 个二进制和 0 个整数变量视为连续变量,并且二进制变量不是 0 或 1。Ipopt 是 NLP 求解器,无法求解 MINLP。 好的。我没有仔细研究这个问题......当我调整约束以使其不会过时并且mindpy
做了它的事情时,它将它发送到 gurobi 求解器,这可能是你想要的。它在我身上吐了,因为我的 gurobi 许可证早就过期了。尝试像我上面提到的那样确定您的BiConstraint
,然后尝试一下。【参考方案2】:
@约翰史密斯
问题在于mindtpy
试图将round()
函数应用于None
值。现在,None
值实际上来自以下内容:
你正在建模model.z_predicate = pe.Var(model.T, model.M, domain=pe.Binary)
和model.M = pe.RangeSet(1,2)
问题是你没有为model.z_predicate[model.T, 2]
分配任何值,因为在你的约束中你只是在binary_constraint
中约束model.z_predicate[model.T, 1]
你可以用它做几件事:
删除model.M
的未使用索引:
model.M = pe.RangeSet(1)
使用model.z_predicate
的初始值:
model.z_predicate = pe.Var(model.T, model.M, domain=pe.Binary, initialize=0)
在这两种方式中,您都在避免 NoneType
回合问题并获得解决方案。在我的情况下(我不知道是否可以)是:
INFO: ---Starting MindtPy---
INFO: Original model has 21 constraints (8 nonlinear) and 0 disjunctions, with
28 variables, of which 5 are binary, 0 are integer, and 23 are continuous.
INFO: Objective is nonlinear. Moving it to constraint set.
INFO: rNLP is the initial strategy being used.
INFO: NLP 1: Solve relaxed integrality
INFO: NLP 1: OBJ: 0.0 LB: -inf UB: inf
INFO: ---MindtPy Master Iteration 0---
INFO: MIP 1: Solve master problem.
INFO: MIP 1: OBJ: 0.0 LB: 0.0 UB: inf
INFO: NLP 2: Solve subproblem for fixed binaries.
INFO: NLP 2: OBJ: 0.0 LB: 0.0 UB: 0.0
INFO: MindtPy exiting on bound convergence. LB: 0.0 + (tol 0.0001) >= UB: 0.0
>>>model.OBJ.expr()
1.286551594275684e-09
【讨论】:
以上是关于Pyomo 对 NoneType 使用 __round__ 方法的主要内容,如果未能解决你的问题,请参考以下文章
无法向订阅管理器注册 - “NoneType”对象没有属性“__getitem__”
TypeError:“NoneType”对象没有属性“__getitem__”
Django 'NoneType' 对象没有属性 '_meta'