Multi Objective Best Solution
AnsweredThere is a steep learning curve to using Gurobi. I have been looking at documentation and examples, but still have not figured out something that appears to be a basic optimization problem.
Assuming I want to optimize and select the best option from the following list:
Option Number, Cost (minimize), Performance (minimize)
1, 10, 30
2, 20, 20
3, 20, 10
4, 30, 10
If I wanted to optimize and select the best option out of 1-4, where I wanted to minimize cost and also minimize the performance number, it seems like if option 3 would be the best (assuming equal weights), but how would I write something like that? How do I pass in option sets using code? How do I compare them?
Once I have my model, I cannot seem to add the values using addVar:
cost = m.addVar([10, 20, 20, 30], vtype=GRB.INTEGER, name="cost")
Some documentation seems to indicate I add it as a constraint, but I cannot figure out how I would do that. Any suggestions? Are there any helpful examples or videos? Is this something beyond the scope of Gurobi?
-
Hi Joseph,
Thank you for reaching out.
We recommend you look through our page about Multiple Objectives first.
Especially when you read Working With Multiple Objectives page, you can realize how Gurobi deals with multiple objectives.
Briefly, we support two approaches: blended and hierarchical.
The first one is to set weights for each objective, and another is to set priorities between objectives.
Also, you can apply both approaches together.Here are codes for building a model for your described problem.
import gurobipy as gp
from gurobipy import GRB
options, _cost, _performance = zip(
[1, 10, 30],
[2, 20, 20],
[3, 20, 10],
[4, 30, 10]
)
cost = {o: _cost[i] for i, o in enumerate(options)}
performance = {o: _performance[i] for i, o in enumerate(options)}
m = gp.Model()
x = m.addVars(options, vtype=GRB.BINARY, name='x')
m.addConstr(gp.quicksum(x) == 1, name='OneOption')
m.ModelSense = GRB.MINIMIZE
obj_cost = gp.quicksum([cost[o] * x[o] for o in options])
obj_profit = gp.quicksum([performance[o] * x[o] for o in options])
m.setObjectiveN(obj_cost, 0, priority=0, name="cost")
m.setObjectiveN(obj_profit, 1, priority=1, name="performance")
m.optimize()
assert m.Status == GRB.OPTIMAL
for o in options:
if x[o].x > 0.5:
print(f'Option {o} is the best choice')
breakThere is a constraint, OneOption, which makes Gurobi choose only one solution.
The optimal solution is Option 3, as you expected.
You can play with this model by changing 'priority' or setting 'weight'.Additionally, you can have more concise codes if you utilize multidict and tupledict.prod.
options, cost, performance = gp.multidict(
{
arr[0]: arr[1:] for arr in
[
[1, 10, 30],
[2, 20, 20],
[3, 20, 10],
[4, 30, 10],
]
}
)
...
obj_cost = x.prod(cost)
obj_performance = x.prod(performance)
...
You also can find a Python script about multi-objectives on our website or in your local drive (<installdir>/examples/python/multiobj.py).If you have any further questions, feel free to leave messages.
Best regards,
Chung-Kyun Han0
Please sign in to leave a comment.
Comments
1 comment