Pyomo:如何在 objective 函数中包含惩罚
Pyomo: How to include a penalty in the objective function
我想尽量减少用两台机器制造产品的成本。机器 A 的成本是 30 美元/产品,机器 B 的成本是 40 美元/产品。
有两个约束:
- 我们必须满足每月 50 种产品的需求 (x+y >= 50)
- 廉价机器(A)每月只能生产40件产品(x<=40)
所以我创建了以下 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 代码实现将惩罚包含在 objective 函数中的条件。
由于 m.y
是一个 Var
,您不能对它使用 if
语句。正如 Airsquid 所说,您始终可以使用 Big M
方法使用二进制变量。通常不推荐这种方法,因为它将问题从 LP 转换为 MILP,但它是有效的。
您只需创建一个新的 Binary Var
:
model.bin_y = Var(domain=Binary)
如果 model.bin_y
为零,则约束 model.y
为零,否则为其边界之间的任何值。我在这里使用了 100 的界限,但你甚至可以使用需求:
model.bin_y_cons = Constraint(expr= model.y <= model.bin_y*100)
然后,在您的 objective 中应用新的固定值 300:
def production_cost(m):
return 30*m.x + 40*m.y + 300*model.bin_y
model.mycost = Objective(rule=production_cost, sense=minimize)
我想尽量减少用两台机器制造产品的成本。机器 A 的成本是 30 美元/产品,机器 B 的成本是 40 美元/产品。
有两个约束:
- 我们必须满足每月 50 种产品的需求 (x+y >= 50)
- 廉价机器(A)每月只能生产40件产品(x<=40)
所以我创建了以下 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 代码实现将惩罚包含在 objective 函数中的条件。
由于 m.y
是一个 Var
,您不能对它使用 if
语句。正如 Airsquid 所说,您始终可以使用 Big M
方法使用二进制变量。通常不推荐这种方法,因为它将问题从 LP 转换为 MILP,但它是有效的。
您只需创建一个新的 Binary Var
:
model.bin_y = Var(domain=Binary)
如果 model.bin_y
为零,则约束 model.y
为零,否则为其边界之间的任何值。我在这里使用了 100 的界限,但你甚至可以使用需求:
model.bin_y_cons = Constraint(expr= model.y <= model.bin_y*100)
然后,在您的 objective 中应用新的固定值 300:
def production_cost(m):
return 30*m.x + 40*m.y + 300*model.bin_y
model.mycost = Objective(rule=production_cost, sense=minimize)