Pyomo: Как включить штраф в целевую функцию

0

Вопрос

Я пытаюсь минимизировать затраты на производство продукта с помощью двух машин. Стоимость машины A составляет 30 долларов США за изделие, а стоимость машины B составляет 40 долларов США за изделие.

Есть два ограничения:

  • мы должны покрывать спрос в размере 50 товаров в месяц (x+y >= 50).
  • дешевая машина (A) может производить только 40 изделий в месяц (x

Поэтому я создал следующий код Pyomo:

from pyomo.environ import *
model = ConcreteModel()
model.x = Var(domain=NonNegativeReals)
model.y = Var(domain=NonNegativeReals)

def production_cost(m):
    return 30*m.x + 40*m.y

# Objective
model.mycost = Objective(expr = production_cost, sense=minimize)

# Constraints
model.demand = Constraint(expr = model.x + model.y >= 50)
model.maxA = Constraint(expr = model.x <= 40)

# Let's solve it
results = SolverFactory('glpk').solve(model)

# Display the solution
print('Cost=', model.mycost())
print('x=', model.x())
print('y=', model.y())

Это работает нормально, с очевидным решением x=40;y=10 (стоимость = 1600)

Однако, если мы начнем использовать машину B, будет установлен штраф в размере 300 долларов сверх стоимости.

Я пытался с

def production_cost(m):
  if (m.y > 0):
    return 30*m.x + 40*m.y + 300
  else:
    return 30*m.x + 40*m.y

Но я получаю следующее сообщение об ошибке

Rule failed when generating expression for Objective mycost with index
    None: PyomoException: Cannot convert non-constant Pyomo expression (0  <
    y) to bool. This error is usually caused by using a Var, unit, or mutable
    Param in a Boolean context such as an "if" statement, or when checking
    container membership or equality. For example,
        >>> m.x = Var() >>> if m.x >= 1: ...     pass
    and
        >>> m.y = Var() >>> if m.y in [m.x, m.y]: ...     pass
    would both cause this exception.

Я не знаю, как реализовать условие включения штрафа в целевую функцию с помощью кода Pyomo.

optimization pyomo python
2021-11-22 12:46:07
1

Лучший ответ

1

С m.y это Var, вы не можете использовать if заявление с ним. Вы всегда можете использовать двоичную переменную, используя Big M подходите так, как сказал Airsquid. Такой подход обычно не рекомендуется, так как он превращает проблему из LP в MILP, но он эффективен.

Вам просто нужно создать новый Binary Var:

model.bin_y = Var(domain=Binary)

Затем ограничение model.y быть равным нулю, если model.bin_y равно нулю, или же должно быть любое значение между его границами. Я использую здесь ограничение в 100, но вы даже можете использовать требование:

model.bin_y_cons = Constraint(expr= model.y <= model.bin_y*100)   

затем в вашей цели просто примените новое фиксированное значение 300:

def production_cost(m):
    return 30*m.x + 40*m.y + 300*model.bin_y 

model.mycost = Objective(rule=production_cost, sense=minimize)
2021-11-22 15:22:41

Спасибо @pybegginer, очень хорошо объяснил :-) Я углублюсь в использование Большого М.
Hookstark

Для неограниченного Vars вам нужно использовать очень большое значение привязки, например 1E6. В такого рода проблемах вам нужно будет дважды проверить допуск решателя к двоичному коду, так как может случиться так, что bin_y составляет ок. ноль, но y по-прежнему больше нуля: например, если границы заданы как 1E6, а двоичный допуск равен 1E-6, bin_y присваивается 1E-7(очень близко к нулю), но результирующее ограничение равно y<=5 позволяя Y быть больше нуля. В любом случае, просто дважды проверьте эти значения, когда модель будет решена
pybegginer

На других языках

Эта страница на других языках

Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................