Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constraint optimisation with google operations research tools

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!

like image 613
Tom Kealy Avatar asked Sep 11 '18 14:09

Tom Kealy


1 Answers

I don't understand why you minimize values (cfg['items'][i][2] = value). You want the highest value.

Your model is similar to the knapsack. Only you will add extra constraints for a cost (less than total cost) and flag ( total flags greater than 5). Also, you said that you will choose 20 item. But your constraint limits to 15 item (max items).

OR tools page has detailed explanation of knapsack problem under bin packing title.

I think you edited your question. You need only one constraint for "is_blue" property. But now your model has different problems.

  1. If you list name for cost is "costs", your constraint must change, because of you use "cost" named list.

    for i in range(num_recipes): solver.Add(x[i] * costs[i] <= max_cost) Also, I understand from this constraint max_cost is defined for each item, not for sum of costs.

  2. This is your objective function.

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

    But you add only first 20 item to objective function. You need to change total_chosen with MAX_ITEMS. Such as:

    solver.Maximize(solver.Sum([profits[i] * x[i] for i in range(MAX_ITEMS)]))
    
  3. And the last is_blue constraint. I understand that you want to select at least 5 blue item.

    blues = [x[3] for x in items]
    solver.Add(solver.Sum([blues[i] * x[i] for i in range(MAX_ITEMS)]) >= 5)
    
like image 120
kur ag Avatar answered Sep 23 '22 23:09

kur ag