重复约束优化

时间:2018-10-30 12:48:57

标签: python or-tools

我有一组(10000多个)项目,必须从这些项目中准确选择k个项目。我只能在排序约束下多次选择每个项目:如果我选择位置1的项目,则要等到位置21才能选择。我的项目有利润和成本。

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

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

作为示例

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

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

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

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

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

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

对于每个选择的项目,它必须具有最小值,并且该项目不能在接下来的19个项目中重复使用。我想选择k个价格最高的最便宜商品,但要限制它,但我很难制定它。

我在使用Google OR工具制定公式时遇到了麻烦。以下内容将获得最佳的k(在本例中为100),而没有任何其他限制

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 = 100
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)

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

2 个答案:

答案 0 :(得分:1)

solver.Add(x[i] * cost[i] <= max_cost)

这个限制意味着我们根本不想拿昂贵的东西。 这样一来,我们可以在优化之前排除带有cost[i] > max_cost的项目。

Sum([profits[i] * x[i])

如果没有其他限制,则该目标要求采取最佳项目total_chosen次。但是我们不能经常重复这些项目。因此,我们需要20个价格低于max_cost的最佳商品,并重复total_chosen/20次。

import numpy

MAX_ITEMS = 10000

cost = numpy.random.randint(1, 100, MAX_ITEMS)
profits = numpy.random.randint(1, 100, MAX_ITEMS)

total_chosen = 100
repeat = 20 
max_cost = 5.0

cheap = [i for i in range(MAX_ITEMS) if costs[i] <= max_cost]
chosen = sorted(cheap, key=lambda i: profits[i], reverse=True)[:repeat]

for _ in range(total_chosen/repeat):
  for i in chosen:
    print(i, costs[i], profits[i])

使用OR工具,它将看起来像

import numpy
from ortools.linear_solver import pywraplp

solver = pywraplp.Solver('SolveAssignmentProblemMIP',
                       pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING)

MAX_ITEMS = 10000

costs = numpy.random.randint(1,100,MAX_ITEMS)
profits = numpy.random.randint(1,100,MAX_ITEMS)

total_chosen = 100
repeat = 20

max_cost = 5.0

x = {}

for i in range(MAX_ITEMS):
  x[i] = solver.BoolVar('x[%s]' % (i))

solver.Add(solver.Sum([x[i] for i in range(MAX_ITEMS)]) == repeat)

for i in range(MAX_ITEMS):
  solver.Add(x[i] * costs[i] <= max_cost)

solver.Maximize(solver.Sum([profits[i] * x[i] for i in range(MAX_ITEMS)]))
sol = solver.Solve()

for i in range(MAX_ITEMS):
  if x[i].solution_value() > 0:
    print(i, profits[i], costs[i])

答案 1 :(得分:0)

有个主意,如果您为前20个对象创建最佳解决方案,您是否可以重复模式直到序列结束?

如果是,请按值(最好的20个)对项目进行排序,然后重复该顺序。

相关问题