Выяснение причины невозможности модели Pyomo

Я получил конкретную модель с множеством переменных и ограничений.

Каким-то образом одна из переменных внутри моей модели нарушает одно ограничение, что делает мою модель неосуществимой:

WARNING: Loading a SolverResults object with a warning status into model=xxxx;
    message from solver=Model was proven to be infeasible.

Есть ли способ спросить у решателя причину невозможности?

Например, предположим, что я получил переменную xи если я определю следующие 2 ограничения, модель будет ofc. неосуществимым.

const1:
    x >= 10

const2:
    x <= 5

И чего я хочу добиться, так это указать на ограничения и переменные, которые вызывают эту невозможность, чтобы я мог это исправить. В противном случае с моей большой моделью трудно понять, что является причиной этой невозможности.

IN: write_some_comment
OUT: variable "x" cannot fulfill "const1" and "const2" at the same time.

2 ответа

Решение

Многие решатели (включая IPOPT) вернут вам значение переменных при завершении решателя, даже если проблема будет признана неосуществимой. На этом этапе у вас есть несколько вариантов.

Есть внесенный код в pyomo.util.infeasible это может помочь вам. https://github.com/Pyomo/pyomo/blob/master/pyomo/util/infeasible.py

Использование:

from pyomo.util.infeasible import log_infeasible_constraints
...
SolverFactory('your_solver').solve(model)
...
log_infeasible_constraints(model)

Я бы не стал доверять никаким числам, которые решатель загружает в модель после сообщения «невозможно». Я не думаю, что какие-либо решатели приходят с гарантиями достоверности этих чисел. Кроме того, если пакет не может угадать намерение разработчика модели, неясно, как он будет перечислять невыполнимые ограничения. Рассмотрим 2 ограничения:

      C1:  x <= 5
C2:  x >= 10

X ∈ Reals, or Integers, ...

Какое ограничение является недопустимым? Смотря как! Суть в том, что разгадать тайну на основе значений, которые пытается решить решатель, кажется невыполнимой задачей.

Возможная альтернативная стратегия: загрузить в модель то, что вы считаете допустимым решением, и протестировать резерв на ограничениях. Это «загруженное решение» может быть даже нулевым случаем, когда все обнуляется (если это имеет смысл в контексте модели). Это также может быть набор известных возможных решений, опробованных с помощью кода модульного тестирования.

Если вы можете построить то, что считаете правильным решением (забудьте об оптимальном, просто о чем-то действительном), вы можете (1) загрузить эти значения, (2) перебрать ограничения в модели, (3) оценить ограничение и посмотреть для отрицательного резерва и (4) сообщить о виновниках со значениями и выражениями

Пример:

      import pyomo.environ as pe

test_null_case = True

m = pe.ConcreteModel('sour constraints')

# SETS
m.T = pe.Set(initialize=['foo', 'bar'])

# VARS
m.X = pe.Var(m.T)
m.Y = pe.Var()

# OBJ
m.obj = pe.Objective(expr = sum(m.X[t] for t in m.T) + m.Y)

# Constraints
m.C1 = pe.Constraint(expr=sum(m.X[t] for t in m.T) <= 5)
m.C2 = pe.Constraint(expr=sum(m.X[t] for t in m.T) >= 10)
m.C3 = pe.Constraint(expr=m.Y >= 7)
m.C4 = pe.Constraint(expr=m.Y <= sum(m.X[t] for t in m.T))

if test_null_case:
    # set values of all variables to a "known good" solution...
    m.X.set_values({'foo':1, 'bar':3})  # index:value
    m.Y.set_value(2)  # scalar
    for c in m.component_objects(ctype=pe.Constraint):
        if c.slack() < 0:  # constraint is not met
            print(f'Constraint {c.name} is not satisfied')
            c.display()  # show the evaluation of c
            c.pprint()   # show the construction of c
            print()
else:
    pass
    # instantiate solver & solve, etc...

Отчеты:

      Constraint C2 is not satisfied
C2 : Size=1
    Key  : Lower : Body : Upper
    None :  10.0 :    4 :  None
C2 : Size=1, Index=None, Active=True
    Key  : Lower : Body            : Upper : Active
    None :  10.0 : X[foo] + X[bar] :  +Inf :   True

Constraint C3 is not satisfied
C3 : Size=1
    Key  : Lower : Body : Upper
    None :   7.0 :    2 :  None
C3 : Size=1, Index=None, Active=True
    Key  : Lower : Body : Upper : Active
    None :   7.0 :    Y :  +Inf :   True
Другие вопросы по тегам