将Excel解算器解决方案转换为Python纸浆

Bas*_*bin 3 python math mathematical-optimization linear-programming pulp

我发现很难将Excel Solver模型转换为python pulp语法.在我的模型中,我正在优化每个部门的HC和OT变量,目标是最小化OT变量的总和.约束要求HC变量总和不超过92,并且总生产(=E2*C2*D2 + F2*C2在下面的电子表格中)满足每部门要求(下面的Excel电子表格的"输入"列).下面显示的Excel求解器公式非常有效.

问题

  1. 如何在纸浆中编写目标函数(在Excel F7 = SUM(F2:F6)中)?
  2. 约束E7 <= 92
  3. 约束G2:G6> = B2:B6
  4. 我有两个决策变量HCOT.在下面的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)
Run Code Online (Sandbox Code Playgroud)

jos*_*ber 5

您发布的Pulp代码存在一些问题.

您只声明了一组变量,x但在excel公式中有两组,即HC和OT.您应该声明两组不同的变量,并对它们进行适当的命名:

HC = pulp.LpVariable.dicts("HC", df.index, lowBound=0)
OT = pulp.LpVariable.dicts("OT", df.index, lowBound=0)
Run Code Online (Sandbox Code Playgroud)

当您将目标添加为时mod += sum(df['OT']),您试图将一个数据框的列添加到模型中,这会导致错误.相反,您想要添加OT变量的总和,这可以通过以下方式实现:

mod += sum([OT[idx] for idx in df.index])
Run Code Online (Sandbox Code Playgroud)

添加约束时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]
Run Code Online (Sandbox Code Playgroud)

将所有这些放在一起产生所需的输出:

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
Run Code Online (Sandbox Code Playgroud)