我有很多(10000多个)物品,我必须从中选择20个物品。我只能选择每个项目一次。我的商品有利润和成本,还有几个布尔属性(例如颜色)。我需要按特定顺序输出结果:特别是我需要将第一和第三项设置为蓝色,将第二和第四项设置为红色。
每个项目都表示为一个元组:
item = ('item name', cost, profit, is_blue, is_red)
作为示例
vase = ['Ming Vase', 1000, 10000, 0, 1]
plate = ['China Plate', 10, 5, 1, 0]
项目总数是一个列表列表:
items = [item1, item2, ..., itemN].
我的利润和成本也列出了:
profits = [x[2] for x in items]
costs = [x[1] for x in items]
对于每个选择的项目,它必须具有最小值,并且至少有5个项目的属性(is_blue)标志必须设置为1。
我想选择具有最高价值的20个最便宜的商品,以使其中5个的is_blue标志设置为1,而第一和第三个商品为蓝色(等)。
我在使用Google OR工具制定公式时遇到了麻烦。
from ortools.linear_solver import pywraplp
solver = pywraplp.Solver('SolveAssignmentProblemMIP',
pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING)
x = {}
for i in range(MAX_ITEMS):
x[i] = solver.BoolVar('x[%s]' % (i))
#Define the constraints
total_chosen = 20
solver.Add(solver.Sum([x[i] for i in range(MAX_ITEMS)]) == total_chosen)
blues = [x[3] for x in items]
solver.Add(solver.Sum([blues[i] * x[i] for i in .
range(MAX_ITEMS)])> = 5)
max_cost = 5.0
for i in range(MAX_ITEMS):
solver.Add(x[i] * cost[i] <= max_cost)
solver.Maximize(solver.Sum([profits[i] * x[i] for i in range(total_chosen)]))
sol = solver.Solve()
我可以得到我选择的项目集:
for i in range(MAX_ITEMS):
if x[i].solution_value() > 0:
print(item[i].item_name)
这很好用-它会选择20种商品,以便在成本约束下最大化利润,但是我坚持如何将其扩展到选择能够保证第一种商品是蓝色等的商品。
在制定约束条件和目标方面的任何帮助都会非常有帮助。谢谢!
答案 0 :(得分:2)
考虑使用清单2的域为0..MAX_ITEMS的20个IntVar,而不是使用BoolVar表示所选项目。从那里开始,做这样的事情应该相当容易:
solver.Add(chosens[0].IndexOf(all_items)[3] == 1)
solver.Add(chosens[2].IndexOf(all_items)[3] == 1)
chosens [i] .IndexOf(all_items)仅表示all_items [IndexOfChosen],即:为第I个位置选择了哪个项目。如果您采用这种方法,请不要忘记使用MakeAllDifferent!