用重复约束优化
Constrain optimisation with duplicates
我有一组很多(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)
在制定约束和 objective 方面的任何帮助都会非常有帮助。谢谢!
solver.Add(x[i] * cost[i] <= max_cost)
这个约束意味着我们根本不想拿昂贵的东西。
那么我们可以在优化前排除cost[i] > max_cost
的项目。
Sum([profits[i] * x[i])
如果没有其他限制,那objective次要求取最好的物品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])
一个想法,如果你为前 20 个对象创建一个最优解,你能重复这个模式直到序列结束吗?
如果是,请按价值对您的项目进行排序,即 20 项最佳,然后重复该顺序。
我有一组很多(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)
在制定约束和 objective 方面的任何帮助都会非常有帮助。谢谢!
solver.Add(x[i] * cost[i] <= max_cost)
这个约束意味着我们根本不想拿昂贵的东西。
那么我们可以在优化前排除cost[i] > max_cost
的项目。
Sum([profits[i] * x[i])
如果没有其他限制,那objective次要求取最好的物品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])
一个想法,如果你为前 20 个对象创建一个最优解,你能重复这个模式直到序列结束吗?
如果是,请按价值对您的项目进行排序,即 20 项最佳,然后重复该顺序。