|
|
from ortools.sat.python import cp_model |
|
|
|
|
|
def main() -> None: |
|
|
model = cp_model.CpModel() |
|
|
horizon = 48 |
|
|
|
|
|
|
|
|
activities = { |
|
|
'breakfast': 2, |
|
|
'lunch': 2, |
|
|
'dinner': 2, |
|
|
'nap': 4, |
|
|
'laundry': 4, |
|
|
'wifes_parents': 6, |
|
|
'mom': 6, |
|
|
'personal_time': 4, |
|
|
'kids_duty': 1, |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
time_windows = { |
|
|
'mom': (36, 42), |
|
|
'nap': (12, 18), |
|
|
'laundry': (20, 36), |
|
|
} |
|
|
|
|
|
|
|
|
starts = {act: model.NewIntVar(0, horizon, f'start_{act}') for act in activities} |
|
|
ends = {act: model.NewIntVar(0, horizon, f'end_{act}') for act in activities} |
|
|
|
|
|
|
|
|
for act, duration in activities.items(): |
|
|
model.Add(ends[act] == starts[act] + duration) |
|
|
|
|
|
|
|
|
model.Add(starts['mom'] == time_windows['mom'][0]) |
|
|
|
|
|
|
|
|
model.Add(starts['lunch'] >= starts['breakfast'] + 8) |
|
|
model.Add(starts['dinner'] >= starts['lunch'] + 8) |
|
|
|
|
|
|
|
|
model.Add(starts['nap'] >= starts['lunch'] + 2) |
|
|
|
|
|
|
|
|
model.Add(starts['laundry'] >= 20) |
|
|
|
|
|
|
|
|
model.AddMaxEquality(ends['personal_time'], [horizon]) |
|
|
|
|
|
|
|
|
|
|
|
for act in ['wifes_parents', 'mom', 'personal_time']: |
|
|
model.AddNoOverlap([starts[act], ends[act], starts['kids_duty'], ends['kids_duty']]) |
|
|
|
|
|
|
|
|
solver = cp_model.CpSolver() |
|
|
status = solver.Solve(model) |
|
|
|
|
|
|
|
|
if status == cp_model.OPTIMAL: |
|
|
for act in activities: |
|
|
start = solver.Value(starts[act]) |
|
|
print(f"{act}: {start//2}:{30*(start%2):02}–{(start+activities[act])//2}:{30*((start+activities[act])%2):02}") |
|
|
else: |
|
|
print("No feasible schedule found.") |
|
|
|
|
|
if __name__ == '__main__': |
|
|
main() |
|
|
|