У меня есть проблема с MINLP, которую нужно решить, и couenne вылетает, когда я пытаюсь ее оптимизировать. Мне удалось значительно уменьшить его, пока все еще происходил сбой, и я нашел возможного виновника.
Целевая функция приведенной задачи представляет собой переменный многочлен x[n] - x[n-1] + x[n-2] - ...
. Есть единственный массив переменных x[k], k=n..1
, где индекс указывает показатель степени x. Существует также массив ограничений, обеспечивающий это возведение в степень.
Для степеней больше 2:
- Если я прямо возведу в степень
x[k] = x[1]**k
, Коэнн сходит с ума. - Если я каскадирую экспоненты
x[k] = x[k-1]*x[1]
, Куэнн решает нормально.
Итак, мои вопросы: в чем разница с точки зрения решателя? Можно ли ожидать этой неудачи? Стоит ли перекомпилировать couenne с другой зависимостью?
- Моя среда - Ubuntu 18.04.
- Я использую Pyomo 5.5 (CPython 3.6.5 в Linux 4.15.0-29-generic), установленный через conda.
- Я сам скомпилировал couenne, используя флаги по умолчанию и загружая следующие зависимости (ThirdParties, все загруженные с использованием сценария wget, предоставленного репозиторием): ASL, Blas, Lapack, Metis и Mumps. Я не скачивал HSL, SCIP и SoPlex.
Вот тестовый код:
#! /usr/bin/env python3
import pyomo.environ
import pyomo.core as pc
from pyomo.opt import SolverFactory
def run(max_pow, cascade):
model = pc.ConcreteModel()
model.s = pc.RangeSet(1, max_pow)
model.x = pc.Var(model.s, bounds=(-1,1))
model.s_rest = pc.Set(initialize=list(ii for ii in model.s)[1:])
## TWO DIFFERENT WAYS OF COMPUTING POWERS ##
if cascade: # x[k] = x[k-1]*x[1]
model.x_c = pc.Constraint(model.s_rest, rule=lambda m, s: m.x[s] == m.x[1]*m.x[s-1])
else: # x[k] = x[1]**k
model.x_c = pc.Constraint(model.s_rest, rule=lambda m, s: m.x[s] == m.x[1]**s)
# Alternating objective function: x[k] - x[k-1] + x[k-2] - ....
def obj(x, s, pos=True):
result = x[s]
if s > 1:
result = result + obj(x, s-1, not pos)
if not pos:
result = -result
return result
model.objective = pc.Objective(rule=lambda m: obj(m.x, max_pow), sense=pc.maximize)
opt = SolverFactory("couenne")
results = opt.solve(model)
model.display()
# Test 3 different cases
for max_pow, cascade in [(2, False,), (3, False,), (3, True)]:
print("\nDegree: {}, cascade: {}".format(max_pow, cascade))
print("-"*25)
try:
run(max_pow, cascade)
except Exception as e:
print(e)
Вот результаты:
Degree: 2, cascade: False
-------------------------
Model unknown
Variables:
x : Size=2, Index=s
Key : Lower : Value : Upper : Fixed : Stale : Domain
1 : -1 : -1.0 : 1 : False : False : Reals
2 : -1 : 1.0 : 1 : False : False : Reals
Objectives:
objective : Size=1, Index=None, Active=True
Key : Active : Value
None : True : 2.0
Constraints:
x_c : Size=1
Key : Lower : Body : Upper
2 : 0.0 : 0.0 : 0.0
Degree: 3, cascade: False
-------------------------
ERROR: Solver (asl) returned non-zero return code (-11)
ERROR: Solver log: Couenne 0.5 -- an Open-Source solver for Mixed Integer
Nonlinear Optimization Mailing list: [email protected]
Instructions: http://www.coin-or.org/Couenne couenne:
Solver (asl) did not exit normally
Degree: 3, cascade: True
-------------------------
Model unknown
Variables:
x : Size=3, Index=s
Key : Lower : Value : Upper : Fixed : Stale : Domain
1 : -1 : -0.002154434679988468 : 1 : False : False : Reals
2 : -1 : 4.641588790337013e-06 : 1 : False : False : Reals
3 : -1 : -9.999999860147783e-09 : 1 : False : False : Reals
Objectives:
objective : Size=1, Index=None, Active=True
Key : Active : Value
None : True : 0.002149783091198271
Constraints:
x_c : Size=2
Key : Lower : Body : Upper
2 : 0.0 : 0.0 : 0.0
3 : 0.0 : 0.0 : 0.0