【问题标题】:Constrain optimisation with duplicates用重复约束优化
【发布时间】:2018-10-30 12:48:56
【问题描述】:

我有一组许多 (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)

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

【问题讨论】:

  • 首先,你需要严格制定“价值最高的k个最便宜的商品”。因为有十几个数学公式。您可以尝试优化总和、最大/最小、顺序,以对每个标准的总和或最大/最小施加约束,计算相对值划分标准等。似乎您可以从形成中排除重复约束。乍一看,如果你可以重复一个项目,你必须。所以你只需要分配前 19 个(20 个?)项目,后面的(最佳)序列应该复制前 19 个。
  • for i in range(num_recipes): solver.Add(x[i] * cost[i]

标签: python or-tools


【解决方案1】:
solver.Add(x[i] * cost[i] <= max_cost)

这个限制意味着我们根本不想拿走昂贵的物品。 因此我们可以在优化之前排除带有cost[i] &gt; 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])

【讨论】:

    【解决方案2】:

    一个想法,如果你为前 20 个对象创建一个最优解,你能重复这个模式直到序列结束吗?

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

    【讨论】:

      猜你喜欢
      • 2019-08-29
      • 2021-09-27
      • 1970-01-01
      • 1970-01-01
      • 2020-01-17
      • 2021-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多