使用Google运营研究工具进行约束优化

时间:2018-09-11 14:45:35

标签: python mathematical-optimization constraint-programming or-tools

我有很多(10000多个)物品,我必须从中选择20个物品。我只能选择每个项目一次。我的商品有利润和成本,还有几个布尔属性(例如颜色)。

我已经阅读并完成了https://developers.google.com/optimization/mip/integer_opt_cphttps://developers.google.com/optimization/mip/integer_opt上的教程,但是我的约束与那里的约束稍有不同。

每个项目都表示为一个元组:

item = ('item name', cost, profit, is_blue)

作为示例

vase = ['Ming Vase', 1000, 10000, 0]

plate = ['China Plate', 10, 5, 1]

项目总数是一个列表列表:

items = [item1, item2, ..., itemN].

我的利润和成本也列出了:

profits = [x[2] for x in items]
costs = [x[1] for x in items]

对于每个选择的项目,它必须具有最小值,并且至少有5个项目的属性(is_blue)标志必须设置为1。

我想选择具有最高价值的20个最便宜的商品,以使其中5个商品的属性标记设置为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)

max_cost = 5.0

for i in range(num_recipes):
    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个项目的集合,这些项目将在成本约束下最大化利润,但是我一直在坚持如何将其扩展到选择属性(is_blue)设置为true或false的项目。 / p>

在制定约束条件和目标方面的任何帮助都会非常有帮助。谢谢!

2 个答案:

答案 0 :(得分:4)

我不明白为什么要最小化值(cfg ['items'] [i] [2] =值)。您想要最高的价值。

您的模型类似于背包。只有您会为成本(小于总成本)和标记(标记总数大于5)添加额外的约束。另外,您说您将选择20个项目。但是您的限制限制为15个项目(最多项目)。

OR工具页面上的装箱标题下有背包问题的详细说明。

我认为您修改了问题。 您只需为“ is_blue”属性设置一个约束。但是现在您的模型有不同的问题。

  1. 如果您列出的成本名称为“ costs”,则约束必须更改,因为您使用的是“ cost”命名清单。

    对于我在范围内(num_recipes):     solver.Add(x [i] *成本[i] <= max_cost) 另外,我从这个约束中了解到max_cost是为每个项目定义的,而不是成本的总和。

  2. 这是您的目标功能。

    solver.Maximize(solver.Sum([profits[i] * x[i] for i in range(total_chosen)])) 
    

    但是您只将前20个项目添加到目标函数中。您需要使用MAX_ITEMS更改total_chosen。如:

    solver.Maximize(solver.Sum([profits[i] * x[i] for i in range(MAX_ITEMS)]))
    
  3. 最后一个is_blue约束。我了解您要选择至少5个蓝色项目。

    blues = [x[3] for x in items]
    solver.Add(solver.Sum([blues[i] * x[i] for i in range(MAX_ITEMS)]) >= 5)
    

答案 1 :(得分:0)

因此,经过一周的思考,我知道如何回答这个问题:毕竟这真的很容易。

只需定义一个列表:

is_blue = [x[3] for x in items]

然后添加:

solver.Add(solver.Sum([x[i] * is_blue[i] for i in range(MAX_ITEMS)] == num_blue)

到约束列表。