Reputation: 195
I've been researching and learning about optimization in general, and ortools in particular, and I need help with understanding what it is I'm doing wrong with this simple problem using ortools.
The problem itself is simple (so simple that ortools should be overkill), but keep in mind this is just for learning the basics:
How to select the smallest (and largest) integer from a list of integers?
Here's the code I have.
# 1. A simple problem:
# Select the smallest number from a list of integers
from __future__ import print_function
from ortools.sat.python import cp_model
# Define data
cost_data = [
5, 4, 3, 6, 9, 12, 5, 9, 12, 14
]
num_hours = len(cost_data)
hours = range(num_hours)
# Create model
model = cp_model.CpModel()
# Create variables
cost_vars = [] # Keep variables for costs
pick_vars = [] # Keep variables for picked items (later we add a constraint for only selecting one pick)
for i in hours:
cost_vars.append(model.NewIntVar(0, 20, ''))
pick_vars.append(model.NewBoolVar(''))
# Create constraints
# Only one pick
model.Add(sum(pick_vars) == 1)
for i in hours:
model.Add(cost_vars[i] == cost_data[i]).OnlyEnforceIf(pick_vars[i])
# Set objective function
model.Minimize(sum(cost_vars)) # This works (returns 3)
# model.Maximize(sum(cost_vars)) # This doesnt work (returns 194 as objective value)
# Solve problem
solver = cp_model.CpSolver()
status = solver.Solve(model)
if status == cp_model.INFEASIBLE:
print("INFEASIBLE")
elif status == cp_model.FEASIBLE:
print("FEASIBLE")
elif status == cp_model.OPTIMAL:
print("OPTIMAL")
print("ObjectiveValue()")
print(solver.ObjectiveValue())
This example works when I use the Minimize function, but if I replace Minimize with Maximize, it somehow returns 194
as the objective value.
What am I doing wrong?
Upvotes: 2
Views: 3037
Reputation: 2766
What is happening right now is: 9*20+14 = 194
Because you are telling the solver that cost_var is only equal to your cost if it is picked, else it can be any integer between 0 and 20.
Edit: the logic that you want is:
model.Add(cost_vars[i] == cost_data[i]).OnlyEnforceIf(pick_vars[i])
model.Add(cost_vars[i] == 0).OnlyEnforceIf(pick_vars[i].Not())
You should also take a look at AddMaxEquality and AddMinEquality
Upvotes: 2