4

I have a problem where I have a set of warehouses with a given production capacity that send some product to a list of customers at a given cost. I'm trying to minimize the total cost of sending the products so that each customer's demand is satisfied. That part is sorted.

Now I need to add a new objective (or constraint) where I try to satisfy all the clients demand at a minimum cost but also using the minimum number of warehouses possible. Say start with 5 warehouses, if the problem is impossible then try 6, 7, 8 etc. until a solution is found were I satisfy all the demand using the minimum number of warehouses possible.

How could I go about this using or-tool constraint programming module? Is it even possible? I've had a good look at the documentation but couldn't find any constraint or function that seemed to cater for this idea.

Miguel
  • 401
  • 5
  • 13

1 Answers1

10

Solve with the first objective, constraint the objective with the solution, hint and solve with the new objective.

from ortools.sat.python import cp_model

model = cp_model.CpModel()
solver = cp_model.CpSolver()
x = model.NewIntVar(0, 10, "x")
y = model.NewIntVar(0, 10, "y")

# Maximize x
model.Maximize(x)
solver.Solve(model)
print("x", solver.Value(x))
print("y", solver.Value(y))
print()

# Hint (speed up solving)
model.AddHint(x, solver.Value(x))
model.AddHint(y, solver.Value(y))

# Maximize y (and constraint prev objective)
model.Add(x == round(solver.ObjectiveValue()))  # use <= or >= if not optimal
model.Maximize(y)

solver.Solve(model)
print("x", solver.Value(x))
print("y", solver.Value(y))

Source (my blog)

Reference (github issue)

Stradivari
  • 2,626
  • 1
  • 9
  • 21
  • I can see the logic. That is a pretty smart way to look at the problem, fixing the total amount of shipped items can we now minimize the number of places we send them from. I'm implementing it now. If I may add, have you got any tips on ways to speed up performance? Maybe solvers or anything else. Thanks for your help! – Miguel Dec 31 '20 at 01:14
  • the easy one is `solver.parameters.num_search_workers=8`, reducing the domains of intvars also help – Stradivari Dec 31 '20 at 01:24