Reputation: 569
I'm starting to learn ortools.sat.python
/ cp_model
and I am confused as how to use model.minimize()/maximize()
.
Let's take an example simple problem of booking meetings to timeslots and rooms:
model = cp_model.CpModel()
bookings = {}
for m in meetings:
for t in timeslots:
for r in rooms:
bookings[(m, t, r)] = model.new_bool_var(f"{m}_{t}_{r}")
# 1. each meeting shall be held once
for m in meetings:
model.add_exactly_one(bookings[(m, t, r)] for r in rooms for t in timeslots)
# 2. no overbooking: no two meetings can be booked for the same timeslot-room pair
for t in timeslots:
for r in rooms:
model.add_at_most_one(bookings[(m, t, r)] for m in meetings)
Now, what I would like to further improve, is to minimize the total number of different booked rooms. In other words, if it is possible to create the whole booking schedule using e.g. 3 rooms only (and not all 5 or 6 that are available), then such solution should be preferred.
How do I do that?
If I wanted to minimize the total number of bookings for room #1, I would simply write:
model.minimize(sum(bookings[(m, t, room_1)] for m in meetings for t in timeslots))
To calculate the total number of different booked rooms AFTER finding the solution, I would write:
total_rooms_used = 0
for r in rooms:
room_r_bookings = sum(solver.value(bookings[(m, t, r)]) for t in timeslots for m in meetings)
if room_r_bookings > 0:
total_rooms_used += 1
print(f"Total rooms used: {total_rooms_used}")
However, my problem is that I want to minimize total_rooms_used
, and I don't know how to put it in model.minimize(...)
Upvotes: 0
Views: 99
Reputation: 11014
all_rooms_used = []
for r in rooms:
room_used = model.new_bool_var(f"room_used({r})")
all_rooms_used.append(room_used)
all_bookings = []
for m in meetings:
for t in timeslots:
model.add_implication(bookings[(m, t, r)], room_used)
all_bookings.append(bookings[(m, t, r)])
model.add_bool_or(all_bookings).only_enforce_if(room_used)
# symmetry breaking
for i in range(len(all_rooms_used) - 1):
model.add_implication(~all_rooms_used[i], ~all_rooms_used[i + 1])
model.minimize(sum(all_rooms_used))
Upvotes: 1