Pyomo:根据条件定义 objective 规则
Pyomo: define objective Rule based on condition
在传输问题中,我尝试将以下规则插入到 objective 函数中:
如果BC的供应量<19,000吨,那么我们将有$125/MT的罚款
我添加了一个约束来检查条件,但想在 objective 函数中应用惩罚。
我可以在 Excel Solver 中做到这一点,但是值不匹配。我已经检查了两者,并调试了代码,但我无法找出问题所在。
约束条件如下:
def bc_rule(model):
return sum(model.x[supplier, market] for supplier in model.suppliers \
for market in model.markets \
if 'BC' in supplier) >= 19000
model.bc_rules = Constraint(rule=bc_rule, doc='Minimum production')
问题出在 objective 规则中:
def objective_rule(model):
PENALTY_THRESHOLD = 19000
PENALTY_COST = 125
cost = sum(model.costs[supplier, market] * model.x[supplier, market] for supplier in model.suppliers for market in model.markets)
# what is the problem here?
bc = sum(model.x[supplier, market] for supplier in model.suppliers \
for market in model.markets \
if 'BC' in supplier)
if bc < PENALTY_THRESHOLD:
cost += (PENALTY_THRESHOLD - bc) * PENALTY_COST
return cost
model.objective = Objective(rule=objective_rule, sense=minimize, doc='Define objective function')
我得到的值比 Excel 求解器中的值低得多。
您的情况 (if
) 取决于模型中的一个变量。
通常,if
s 不应该用在数学模型中,这不仅适用于 Pyomo。即使在 Excel 中,如果公式中的语句在优化之前只是简单地转换为标量值,所以在说它是真正的最优值时我会非常小心。
好消息是 if 语句很容易转换为数学约束。
为此,您需要向模型添加一个二进制变量 (0/1)。如果bc <= PENALTY_TRESHOLD
,它将取值1。我们称这个变量为y
,定义为model.y = Var(domain=Binary)
。
您将添加 model.y * PENALTY_COST
作为 objective 函数的一项,以包含惩罚成本。
然后,对于约束,添加如下代码:
def y_big_M(model):
bigM = 10000 # Should be a big number, big enough that it will be bigger than any number in your
# model, but small enough that it will stay around the same order of magnitude. Avoid
# utterly big number like 1e12 and + if you don't need to, since having numbers too
# large causes problems.
PENALTY_TRESHOLD = 19000
return PENALTY_TRESHOLD - sum(
model.x[supplier, market]
for supplier in model.suppliers
for market in model.markets
if 'BC' in supplier
) <= model.y * bigM
model.y_big_M = Constraint(rule=y_big_M)
前面的约束确保当计算 bc
的总和小于 PENALTY_TRESHOLD
时,y 将取大于 0 的值(即 1)。此差值的任何大于 0 的值都将强制模型将 1 放入变量 y
的值中,因为如果 y=1
,约束的右侧将是 1 * bigM
, 这是一个非常大的数字,大到 bc
总是小于 bigM
.
请同时检查您的 Excel 模型,看看您的 if 语句在求解器计算期间是否真的有效。上次我检查时,Excel 求解器不会将 if 语句转换为 bigM 约束。我向您展示的建模技术绝对适用于所有编程方法,即使在 Excel.
中也是如此
在传输问题中,我尝试将以下规则插入到 objective 函数中:
如果BC的供应量<19,000吨,那么我们将有$125/MT的罚款
我添加了一个约束来检查条件,但想在 objective 函数中应用惩罚。
我可以在 Excel Solver 中做到这一点,但是值不匹配。我已经检查了两者,并调试了代码,但我无法找出问题所在。
约束条件如下:
def bc_rule(model):
return sum(model.x[supplier, market] for supplier in model.suppliers \
for market in model.markets \
if 'BC' in supplier) >= 19000
model.bc_rules = Constraint(rule=bc_rule, doc='Minimum production')
问题出在 objective 规则中:
def objective_rule(model):
PENALTY_THRESHOLD = 19000
PENALTY_COST = 125
cost = sum(model.costs[supplier, market] * model.x[supplier, market] for supplier in model.suppliers for market in model.markets)
# what is the problem here?
bc = sum(model.x[supplier, market] for supplier in model.suppliers \
for market in model.markets \
if 'BC' in supplier)
if bc < PENALTY_THRESHOLD:
cost += (PENALTY_THRESHOLD - bc) * PENALTY_COST
return cost
model.objective = Objective(rule=objective_rule, sense=minimize, doc='Define objective function')
我得到的值比 Excel 求解器中的值低得多。
您的情况 (if
) 取决于模型中的一个变量。
通常,if
s 不应该用在数学模型中,这不仅适用于 Pyomo。即使在 Excel 中,如果公式中的语句在优化之前只是简单地转换为标量值,所以在说它是真正的最优值时我会非常小心。
好消息是 if 语句很容易转换为数学约束。
为此,您需要向模型添加一个二进制变量 (0/1)。如果bc <= PENALTY_TRESHOLD
,它将取值1。我们称这个变量为y
,定义为model.y = Var(domain=Binary)
。
您将添加 model.y * PENALTY_COST
作为 objective 函数的一项,以包含惩罚成本。
然后,对于约束,添加如下代码:
def y_big_M(model):
bigM = 10000 # Should be a big number, big enough that it will be bigger than any number in your
# model, but small enough that it will stay around the same order of magnitude. Avoid
# utterly big number like 1e12 and + if you don't need to, since having numbers too
# large causes problems.
PENALTY_TRESHOLD = 19000
return PENALTY_TRESHOLD - sum(
model.x[supplier, market]
for supplier in model.suppliers
for market in model.markets
if 'BC' in supplier
) <= model.y * bigM
model.y_big_M = Constraint(rule=y_big_M)
前面的约束确保当计算 bc
的总和小于 PENALTY_TRESHOLD
时,y 将取大于 0 的值(即 1)。此差值的任何大于 0 的值都将强制模型将 1 放入变量 y
的值中,因为如果 y=1
,约束的右侧将是 1 * bigM
, 这是一个非常大的数字,大到 bc
总是小于 bigM
.
请同时检查您的 Excel 模型,看看您的 if 语句在求解器计算期间是否真的有效。上次我检查时,Excel 求解器不会将 if 语句转换为 bigM 约束。我向您展示的建模技术绝对适用于所有编程方法,即使在 Excel.
中也是如此