将 Excel 求解器解决方案转换为 Python Pulp
Converting Excel Solver Solution to Python Pulp
我发现很难将 Excel 求解器模型转换为 python pulp 语法。
在我的模型中,我正在优化每个部门的 HC 和 OT 变量,objective 最小化 OT 变量的总和。约束条件要求 HC 变量总和不超过 92,并且总产量(下面电子表格中的 =E2*C2*D2 + F2*C2
)满足每个部门的要求(excel 的 "Input" 列下面的电子表格)。下面显示的 Excel 求解器公式非常有效。
问题
- 如何在 pulp 中编写 objective 函数(在 Excel F7
=SUM(F2:F6))?
- 约束条件 E7 <= 92
- 约束条件 G2:G6 >= B2:B6
- 我有两个决策变量 HC 和 OT。在下面的 python 代码中我只创建了一个变量。
之前
求解后
import pulp
import numpy as np
import pandas as pd
idx = [0, 1, 2, 3, 4]
d = {'Dept': pd.Series(['Receiving', 'Picking', 'PPicking', 'QC', 'Packing'], index=idx),
'Target': pd.Series([61,94,32,63,116], index=idx),
'Hrs/day': pd.Series([7.75, 7.75, 7.75, 7.75, 7.75], index=idx),
'Prod': pd.Series([11733, 13011, 2715, 13682, 14194], index=idx),
'HC': pd.Series([24,18,6,28,16], index=idx),
'OT': pd.Series([0,0,42,0,0], index=idx)}
df = pd.DataFrame(d)
# Create variables and model
x = pulp.LpVariable.dicts("x", df.index, lowBound=0)
mod = pulp.LpProblem("OTReduction", pulp.LpMinimize)
# Objective function
mod += sum(df['OT'])
# Lower and upper bounds:
for idx in df.index:
mod += x[idx] <= df['Input'][idx]
# Total HC value should be less than or equal to 92
mod += sum([x[idx] for idx in df.index]) <= 92
# Solve model
mod.solve()
# Output solution
for idx in df.index:
print idx, x[idx].value()
# Expected answer
# HC, OT
# 19, 35.795
# 18, 0
# 11, 0
# 28, 0
# ----------------
# 92, 35.795 -> **note:** SUM(HC), SUM(OT)
您发布的 Pulp 代码存在一些问题。
您只声明了一组变量,x
,但您的 excel 公式中有两组,HC 和 OT。您应该声明两组独立的变量,并适当地命名它们:
HC = pulp.LpVariable.dicts("HC", df.index, lowBound=0)
OT = pulp.LpVariable.dicts("OT", df.index, lowBound=0)
当您将 objective 添加为 mod += sum(df['OT'])
时,您试图将数据框的一列添加到模型中,这会导致错误。相反,您想添加 OT 变量的总和,这可以通过以下方式实现:
mod += sum([OT[idx] for idx in df.index])
添加约束 x[idx] <= df['Input'][idx]
时,您需要 x
变量的上限为输入数据。然而,实际上您有一个更复杂的约束——请注意,在 excel 代码中,您的输入列下限 E2*C2*D2 + F2*C2
。您在此处的约束应表现出相同的逻辑:
for idx in df.index:
mod += df['Target'][idx] * df['Hrs/day'][idx] * HC[idx] + df['Target'][idx] * OT[idx] >= df['Prod'][idx]
将所有这些放在一起会产生所需的输出:
import pulp
import pandas as pd
# Problem data
idx = [0, 1, 2, 3, 4]
d = {'Dept': pd.Series(['Receiving', 'Picking', 'PPicking', 'QC', 'Packing'], index=idx),
'Target': pd.Series([61,94,32,63,116], index=idx),
'Hrs/day': pd.Series([7.75, 7.75, 7.75, 7.75, 7.75], index=idx),
'Prod': pd.Series([11346, 13011, 2715, 13682, 14194], index=idx)}
df = pd.DataFrame(d)
# Create variables and model
HC = pulp.LpVariable.dicts("HC", df.index, lowBound=0)
OT = pulp.LpVariable.dicts("OT", df.index, lowBound=0)
mod = pulp.LpProblem("OTReduction", pulp.LpMinimize)
# Objective function
mod += sum([OT[idx] for idx in df.index])
# Lower and upper bounds:
for idx in df.index:
mod += df['Target'][idx] * df['Hrs/day'][idx] * HC[idx] + df['Target'][idx] * OT[idx] >= df['Prod'][idx]
# Total HC value should be less than or equal to 92
mod += sum([HC[idx] for idx in df.index]) <= 92
# Solve model
mod.solve()
# Output solution
for idx in df.index:
print(idx, HC[idx].value(), OT[idx].value())
# 0 24.0 0.0
# 1 13.241236 35.795316
# 2 10.947581 0.0
# 3 28.022529 0.0
# 4 15.788654 0.0
我发现很难将 Excel 求解器模型转换为 python pulp 语法。
在我的模型中,我正在优化每个部门的 HC 和 OT 变量,objective 最小化 OT 变量的总和。约束条件要求 HC 变量总和不超过 92,并且总产量(下面电子表格中的 =E2*C2*D2 + F2*C2
)满足每个部门的要求(excel 的 "Input" 列下面的电子表格)。下面显示的 Excel 求解器公式非常有效。
问题
- 如何在 pulp 中编写 objective 函数(在 Excel F7 =SUM(F2:F6))?
- 约束条件 E7 <= 92
- 约束条件 G2:G6 >= B2:B6
- 我有两个决策变量 HC 和 OT。在下面的 python 代码中我只创建了一个变量。
之前
求解后
import pulp
import numpy as np
import pandas as pd
idx = [0, 1, 2, 3, 4]
d = {'Dept': pd.Series(['Receiving', 'Picking', 'PPicking', 'QC', 'Packing'], index=idx),
'Target': pd.Series([61,94,32,63,116], index=idx),
'Hrs/day': pd.Series([7.75, 7.75, 7.75, 7.75, 7.75], index=idx),
'Prod': pd.Series([11733, 13011, 2715, 13682, 14194], index=idx),
'HC': pd.Series([24,18,6,28,16], index=idx),
'OT': pd.Series([0,0,42,0,0], index=idx)}
df = pd.DataFrame(d)
# Create variables and model
x = pulp.LpVariable.dicts("x", df.index, lowBound=0)
mod = pulp.LpProblem("OTReduction", pulp.LpMinimize)
# Objective function
mod += sum(df['OT'])
# Lower and upper bounds:
for idx in df.index:
mod += x[idx] <= df['Input'][idx]
# Total HC value should be less than or equal to 92
mod += sum([x[idx] for idx in df.index]) <= 92
# Solve model
mod.solve()
# Output solution
for idx in df.index:
print idx, x[idx].value()
# Expected answer
# HC, OT
# 19, 35.795
# 18, 0
# 11, 0
# 28, 0
# ----------------
# 92, 35.795 -> **note:** SUM(HC), SUM(OT)
您发布的 Pulp 代码存在一些问题。
您只声明了一组变量,x
,但您的 excel 公式中有两组,HC 和 OT。您应该声明两组独立的变量,并适当地命名它们:
HC = pulp.LpVariable.dicts("HC", df.index, lowBound=0)
OT = pulp.LpVariable.dicts("OT", df.index, lowBound=0)
当您将 objective 添加为 mod += sum(df['OT'])
时,您试图将数据框的一列添加到模型中,这会导致错误。相反,您想添加 OT 变量的总和,这可以通过以下方式实现:
mod += sum([OT[idx] for idx in df.index])
添加约束 x[idx] <= df['Input'][idx]
时,您需要 x
变量的上限为输入数据。然而,实际上您有一个更复杂的约束——请注意,在 excel 代码中,您的输入列下限 E2*C2*D2 + F2*C2
。您在此处的约束应表现出相同的逻辑:
for idx in df.index:
mod += df['Target'][idx] * df['Hrs/day'][idx] * HC[idx] + df['Target'][idx] * OT[idx] >= df['Prod'][idx]
将所有这些放在一起会产生所需的输出:
import pulp
import pandas as pd
# Problem data
idx = [0, 1, 2, 3, 4]
d = {'Dept': pd.Series(['Receiving', 'Picking', 'PPicking', 'QC', 'Packing'], index=idx),
'Target': pd.Series([61,94,32,63,116], index=idx),
'Hrs/day': pd.Series([7.75, 7.75, 7.75, 7.75, 7.75], index=idx),
'Prod': pd.Series([11346, 13011, 2715, 13682, 14194], index=idx)}
df = pd.DataFrame(d)
# Create variables and model
HC = pulp.LpVariable.dicts("HC", df.index, lowBound=0)
OT = pulp.LpVariable.dicts("OT", df.index, lowBound=0)
mod = pulp.LpProblem("OTReduction", pulp.LpMinimize)
# Objective function
mod += sum([OT[idx] for idx in df.index])
# Lower and upper bounds:
for idx in df.index:
mod += df['Target'][idx] * df['Hrs/day'][idx] * HC[idx] + df['Target'][idx] * OT[idx] >= df['Prod'][idx]
# Total HC value should be less than or equal to 92
mod += sum([HC[idx] for idx in df.index]) <= 92
# Solve model
mod.solve()
# Output solution
for idx in df.index:
print(idx, HC[idx].value(), OT[idx].value())
# 0 24.0 0.0
# 1 13.241236 35.795316
# 2 10.947581 0.0
# 3 28.022529 0.0
# 4 15.788654 0.0