线性编程(Simplex LP)PuLP?

时间:2015-10-15 23:36:59

标签: python pandas dataframe linear-programming pulp

仅在Python中,并使用来自Pandas数据帧的数据,我如何使用PuLP来解决线性编程问题,就像我在Excel中一样?应在新预算栏目下为每个渠道分配多少预算,以便最大化估算成功的总数?我真的在寻找一个具体的示例来使用数据框中的数据而不是真正的高级建议。

问题数据设置

    Channel  30-day Cost  Trials  Success  Cost Min  Cost Max  New Budget
0  Channel1      1765.21    9865      812    882.61   2647.82           0
1  Channel2      2700.00   15000      900   1350.00   4050.00           0
2  Channel3      2160.00   12000      333   1080.00   3240.00           0

这是最大化问题。

目标函数是:

objective_function = sum((df['New Budget']/(df['30-day Cost']/df['Trials']))*(df['Success']/df['Trials']))

约束是:

  1. df['New Budget']的总和必须等于5000
  2. 给定频道的New Budget不能低于而不是Cost Min
  3. 给定频道的New Budget不能更高而不是Cost Max
  4. 如何使用PuLP或任何其他求解器方法转换此pandas数据帧求解器线性问题?最终结果将是您在下图中看到的结果。

    Desired result

1 个答案:

答案 0 :(得分:7)

通常,您可以创建变量字典(在本例中为x)和模型变量(在本例中为mod)。要创建目标,请使用sum对变量乘以某些标量,并将结果添加到mod。您可以通过使用>=<===再次计算变量的线性组合来构建约束,并将该约束添加到mod。最后,您使用mod.solve()来获取解决方案。

import pulp

# Create variables and model
x = pulp.LpVariable.dicts("x", df.index, lowBound=0)
mod = pulp.LpProblem("Budget", pulp.LpMaximize)

# Objective function
objvals = {idx: (1.0/(df['30-day Cost'][idx]/df['Trials'][idx]))*(df['Success'][idx]/float(df['Trials'][idx])) for idx in df.index}
mod += sum([x[idx]*objvals[idx] for idx in df.index])

# Lower and upper bounds:
for idx in df.index:
    mod += x[idx] >= df['Cost Min'][idx]
    mod += x[idx] <= df['Cost Max'][idx]

# Budget sum
mod += sum([x[idx] for idx in df.index]) == 5000.0

# Solve model
mod.solve()

# Output solution
for idx in df.index:
    print idx, x[idx].value()
# 0 2570.0
# 1 1350.0
# 2 1080.0

print 'Objective', pulp.value(mod.objective)
# Objective 1798.70495012

数据:

import numpy as np
import pandas as pd
idx = [0, 1, 2]
d = {'channel': pd.Series(['Channel1', 'Channel2', 'Channel3'], index=idx),
     '30-day Cost': pd.Series([1765.21, 2700., 2160.], index=idx),
     'Trials': pd.Series([9865, 1500, 1200], index=idx),
     'Success': pd.Series([812, 900, 333], index=idx),
     'Cost Min': pd.Series([882.61, 1350.00, 1080.00], index=idx),
     'Cost Max': pd.Series([2647.82, 4050.00, 3240.00], index=idx)}
df = pd.DataFrame(d)
df
#    30-day Cost  Cost Max  Cost Min  Success  Trials   channel
# 0      1765.21   2647.82    882.61      812    9865  Channel1
# 1      2700.00   4050.00   1350.00      900    1500  Channel2
# 2      2160.00   3240.00   1080.00      333    1200  Channel3