Я изо всех сил пытаюсь понять, что я делаю неправильно в задаче оптимизации игрушек (смешанное целочисленное программирование).
Допустим, у нас есть три человека с разным количеством каких-то товаров. В настоящее время у них есть 10, 0 и 50 единиц соответственно. Им НУЖНЫ 15, 0 и 46 единиц соответственно, и я пытаюсь использовать puLP, чтобы найти оптимальные переводы между людьми, чтобы минимизировать неудовлетворенные потребности (НЕОБХОДИМО - ПОСТАВКА ПОСЛЕ ПЕРЕРАСПРЕДЕЛЕНИЯ) для всех трех человек.
Тривиальным решением здесь может быть то, что человек 3 может дать человеку 1 всего 4 единицы, так что запасы после перераспределения станут 14, 0, 46, и теперь у человека 1 есть только одна единица неудовлетворенной потребности (они хотят 15 единиц).
Когда я запускаю следующий код puLP, я получаю результат: человек 1 должен дать человеку 2 10 единиц, а человек 3 должен дать человеку 1 50 единиц.
Ясно, что я делаю что-то не так, не могли бы вы указать на мою ошибку?
Я не использовал циклы или понимание списков, потому что хотел сделать все предельно ясным и понятным, чтобы найти свою ошибку. Единственное, что у меня есть, это то, что люди не могут отдать больше единиц, чем имеют сейчас.
Спасибо!
from pulp import *
import pandas as pd
# Creates a list of the unique people
people = ['1','2','3']
# Creates a dictionary for the number of units of units currently in supply
current = {
'1': 10,
'2': 0,
'3': 50
}
# Creates a dictionary for the number of units needed
need = {
'1': 15,
'2': 0,
'3': 46
}
# Creates the prob variable to contain the problem data
prob = LpProblem("Goods redistribution problem", LpMinimize)
# Creates a list of tuples containing all the possible trades
Routes = [(s,t) for s in people for t in people]
# Remove any tuples that are self trades
Routes = [element for element in Routes if (element[0] != element[1])]
# A dictionary called route_vars is created to contain the referenced variables (the routes)
# Make sure there isn't a route to itself
route_vars = {
'1': {'2': LpVariable("1_2",0,None,LpInteger), '3': LpVariable("1_3",0,None,LpInteger)},
'2': {'1': LpVariable("2_1",0,None,LpInteger), '3': LpVariable("2_3",0,None,LpInteger)},
'3': {'1': LpVariable("3_1",0,None,LpInteger), '2': LpVariable("3_2",0,None,LpInteger)}
}
# The objective function is added to prob first
#prob += lpSum([(need[t] - (current[s] + route_vars[t][s])) for (s,t) in Routes]), "Sum of unmet need after trading"
prob += (need['1'] - (current['1'] + route_vars['2']['1'] + route_vars['3']['1'])) \
+ (need['2'] - (current['2'] + route_vars['1']['2'] + route_vars['3']['2'])) \
+ (need['3'] - (current['3'] + route_vars['1']['3'] + route_vars['2']['3'])), "Sum of unmet need after trading"
# The amount each source trades cannot exceed the amount they currently have
prob += (route_vars['1']['2'] + route_vars['1']['3']) <= current['1'], f"Can't trade more than current inventory for person 1"
prob += (route_vars['2']['1'] + route_vars['2']['3']) <= current['2'], f"Can't trade more than current inventory for person 2"
prob += (route_vars['3']['1'] + route_vars['3']['2']) <= current['3'], f"Can't trade more than current inventory for person 3"
prob.solve()
pd.Series({v: int(v.varValue) for v in prob.variables()})