如何修复PuLP python中分配优化的约束

时间:2019-05-29 17:23:54

标签: python pandas optimization linear-programming pulp

背景

我正在尝试将客户Ci分配给财务顾问Pj。每个客户都有一个策略值xi。我假设分配给每个顾问的客户数量(n)是相同的,并且不能将同一客户分配给多个顾问。因此,每个合作伙伴都将分配如下策略值:

P1 = [x1,x2,x3],P2 = [x4,x5,x6],P3 = [x7,x8,x9]

我正在尝试寻找最佳分配方案,以最大程度地减少顾问之间的基金价值分散。我将分散度定义为最高资金值(z_max)和最低资金值(z_min)的顾问之间的差额。

因此,此问题的公式为: equations

如果将客户Ci分配给顾问Pj,则yij = 1,否则为0

第一个约束条件要求zmax必须大于或等于每个策略值;由于目标函数鼓励使用较小的zmax值,因此这意味着zmax将等于最大策略值。类似地,第二约束将zmin设置为等于最小策略值。第三个约束条件是,必须将每个客户分配给一个顾问。第四条说,每个顾问必须分配n名客户。信用:@ LarrySnyder610

问题:

当在PulP中实现此问题时,我希望根据约束3和4在173个顾问中分配1740(n x p)个客户。但是,没有获得72036的最优分配。

import random 
import pandas as pd
import pulp 


=============================================================================
# SAMPLE DATA 
=============================================================================

n = 10 # number of customers for each financial adviser
c = 414 #number of customers 
p = 174 #number of financial adviser
policy_values = random.sample(range(1, 1000000), c)


set_I = range(c)
set_J = range(p)
set_N = range(n)
x = {i: policy_values[i] for i in set_I} #customer policy values
y = {(i,j): random.randint(0, 1) for i in set_I for j in set_J} # allocation dummies 


model = pulp.LpProblem("Allocation Model", pulp.LpMinimize)

# =============================================================================
# DECISION VARIABLES
# =============================================================================

y_vars  = {(i,j): pulp.LpVariable(cat=pulp.LpBinary, name="y_{0}_{1}".format(i,j)) for i in set_I for j in set_J}
z_max = pulp.LpVariable("Max Policy Value", 0)
z_min = pulp.LpVariable("Min Policy Value", 0)

# =============================================================================
# OBJECTIVE FUNCTION
# =============================================================================

model += z_max - z_min

# =============================================================================
# CONSTRAINTS
# =============================================================================
model += {j: pulp.lpSum(y_vars[i,j] * x[i] for i in set_I) for j in set_J} <= z_max # constraint 1
model += {j: pulp.lpSum(y_vars[i,j] * x[i] for i in set_I) for j in set_J} >= z_min # constraint 2
model += {i: pulp.lpSum(y_vars[i,j] for j in set_J) for i in set_I} == 1 # constraint 3
model += {j: pulp.lpSum(y_vars[i,j] for i in set_I) for j in set_J} == n #constraint 4

# =============================================================================
# SOLVE MODEL
# =============================================================================

model.solve()
print('Optimised model status: '+str(pulp.LpStatus[model.status]))

count=0
for v in model.variables():
    if v.varValue == 1.0:
        count+=1
        #print(v.name, "=", v.varValue)
print(count)
#>>> 72036 # expecting 1740

print('Optimal difference between highest and lowest summed policy_value: ' + str(pulp.value(model.objective)))

我是否需要更改目标函数/约束以实现上述方程式?

2 个答案:

答案 0 :(得分:2)

一些提示:

  1. 通过total调试
  2. 从一个小的数据集开始
  3. 没有正确制定约束条件。应该是这样的

    text
    1. 如果 public class ExampleAuthenticator implements Authenticator<BasicCredentials, User> { @Override public Optional<User> authenticate(BasicCredentials credentials) throws AuthenticationException { if ("secret".equals(credentials.getPassword())) { return Optional.of(new User(credentials.getUsername())); } return Optional.absent(); } }
    2. ,该模型将不可行
    3. 详细信息:我们可能应该重写约束1和2。重复长的求和将创建大量非零元素。

答案 1 :(得分:0)

我认为您不能使用该格式添加约束。尝试使用以下格式:

for j in set_J:
    model += pulp.lpSum([y_vars[i,j] * x[i] for i in set_I]) <= z_max

还要注意[...]内的lpSum(...)

最后,我认为您不能像以前那样声明变量。我通常使用LpVariable.dicts(),如下所示:

y_vars = pulp.lpVariable.dicts('y_vars', set_I, 0, 1, pulp.LpInteger)