I have a set of many (10000+) items, from which have I have to choose exactly 20 items. I can only choose each item once. My items have profits, and costs, as well as several boolean properties (such as colour).
I've read and worked through the tutorial at https://developers.google.com/optimization/mip/integer_opt_cp and https://developers.google.com/optimization/mip/integer_opt, but my constraints are slightly different than those presented there.
Each item is represented as a tuple:
item = ('item name', cost, profit, is_blue)
as an example
vase = ['Ming Vase', 1000, 10000, 0]
plate = ['China Plate', 10, 5, 1]
and the total set of items is a list of lists:
items = [item1, item2, ..., itemN].
My profits and costs are also lists:
profits = [x[2] for x in items]
costs = [x[1] for x in items]
For each item chosen, it needs to have a minimum value, and a minimum of 5 items must have the property (is_blue) flag set to 1.
I want to choose the 20 cheapest items with the highest value, such that 5 of them have the property flag set to 1.
I'm having trouble formulating this using google OR tools.
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()
I can get the set of items I've chosen by:
for i in range(MAX_ITEMS):
if x[i].solution_value() > 0:
print(item[i].item_name)
This works fine - it chooses the set of 20 items which maximise the profits subject to the cost constraint, but I'm stuck on how to extend this to choosing items with the property (is_blue) set to true or false.
Any help in formulating the constraints and objective would be really helpful. Thanks!