Пьомо (использующий коэнн) не может оптимизировать силы ›= 3

У меня есть проблема с 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

person jabozzo    schedule 02.08.2018    source источник


Ответы (1)


Pyomo имеет тенденцию отправлять модель решателю точно в том виде, в котором вы ее сформулировали, если только вы не примените какое-либо высокоуровневое преобразование (как в GDP или DAE).

Для многих решателей выражение формы x * x * x обрабатывается иначе, чем x ** 3. В некоторых системах даже x ** 2, pow(x, 2) и sqr(x) дают вам другое поведение. Хотя математически это эквивалентно, обработка ограничивающего поведения и ограничений домена может отличаться.

person Qi Chen    schedule 02.08.2018