Справочная информация:
Я пытаюсь выделить клиентов Ci финансовым консультантам Pj.Каждый клиент имеет значение политики xi.Я предполагаю, что количество клиентов (n), выделенных каждому советнику, одинаково, и что один и тот же клиент не может быть назначен нескольким консультантам.Поэтому каждому партнеру будет присвоено значение политики следующим образом:
P1 = [x1, x2, x3], P2 = [x4, x5, x6], P3 = [x7, x8, x9]
Я пытаюсь найти оптимальное распределение, чтобы минимизировать разброс стоимости фонда между консультантами.Я определяю дисперсию как разницу между советником с самой высокой стоимостью фонда (z_max) и самой низкой стоимостью фонда (z_min).
Поэтому формулировка этой проблемы:
где yij = 1, если мы назначаем клиента Ci советнику Pj, 0 в противном случае
Первое ограничение говорит, что zmax должно быть больше или равно каждому значению политики;поскольку целевая функция поддерживает меньшие значения zmax, это означает, что zmax будет равно наибольшему значению политики.Аналогично, второе ограничение устанавливает zmin равным наименьшему значению политики.Третье ограничение говорит о том, что каждому клиенту должен быть назначен ровно один консультант.Четвертый говорит, что у каждого консультанта должно быть назначено n клиентов.Кредит: @ LarrySnyder610
Проблема:
При реализации этой проблемы в PulP я ожидаю, что 1740 (nxp) клиентов будут распределены по 173 консультантам на основе ограничения 3 и4. Однако 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)))
Нужно ли вносить изменения в целевую функцию / ограничения для реализации вышеуказанных уравнений?
РЕДАКТИРОВАТЬ: Ниже приведен фрагмент кода, чтобы попытаться реализовать предложенные @Erwin Kalvelagen изменения.По-прежнему имеет чрезвычайно большую длительность для более высоких значений n, p и c:
y_sum = {}
# =============================================================================
# DECISION VARIABLES
# =============================================================================
model = pulp.LpProblem("Allocation Model", pulp.LpMinimize)
y_vars = pulp.LpVariable.dicts('y_vars',((i,j) for i in set_I for j in set_J), lowBound=0, upBound = 1, cat=pulp.LpInteger)
z_max = pulp.LpVariable("Max Policy Value")
z_min = pulp.LpVariable("Min Policy Value")
for j in set_J:
y_sum[j] = pulp.lpSum([y_vars[i,j] * x[i] for i in set_I])
# =============================================================================
# OBJECTIVE FUNCTION
# =============================================================================
model += z_max - z_min
# =============================================================================
# CONSTRAINTS
# =============================================================================
for j in set_J:
model += pulp.lpSum([y_vars[i,j] for i in set_I]) == n
model += y_sum[j] <= z_max
model += y_sum[j] >= z_min
for i in set_I:
model += pulp.lpSum([y_vars[i,j] for j in set_J]) == 1