File size: 2,613 Bytes
30f018f
 
f572466
30f018f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
from ortools.sat.python import cp_model

def main() -> None:
    model = cp_model.CpModel()
    horizon = 48  # 24-hour day in 30-minute slots (adjust as needed)

    # Activities and durations (in 30-min increments)
    activities = {
        'breakfast': 2,    # 1 hour (prep + eat + cleanup)
        'lunch': 2,
        'dinner': 2,
        'nap': 4,          # 2-hour nap
        'laundry': 4,      # 2 hours
        'wifes_parents': 6,  # 3-hour visit
        'mom': 6,          # Friday night (fixed)
        'personal_time': 4,  # 2 hours total
        'kids_duty': 1,    # Rotating 30-min shifts
    }

    # --- Time Windows ---
    # All times are in 30-min slots from 0 (8:00 AM) to 48 (next day 8:00 AM)
    time_windows = {
        'mom': (36, 42),  # Friday 6:00 PM–9:00 PM (if Friday is day 0)
        'nap': (12, 18),  # Preferred nap window: 1:00 PM–4:00 PM
        'laundry': (20, 36),  # Flexible but avoid late-night
    }

    # --- Variables ---
    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}
    
    # Duration constraints
    for act, duration in activities.items():
        model.Add(ends[act] == starts[act] + duration)

    # --- Fixed Time Constraints ---
    model.Add(starts['mom'] == time_windows['mom'][0])  # Fixed Friday night
    
    # --- Meal Spacing (4-hour gaps) ---
    model.Add(starts['lunch'] >= starts['breakfast'] + 8)  # 8 slots = 4 hours
    model.Add(starts['dinner'] >= starts['lunch'] + 8)

    # --- Nap After Lunch ---
    model.Add(starts['nap'] >= starts['lunch'] + 2)  # At least 1 hour after lunch

    # --- Laundry During Kid-Free Time ---
    model.Add(starts['laundry'] >= 20)  # Not before 10 AM

    # --- Personal Time (flexible, but prioritize) ---
    model.AddMaxEquality(ends['personal_time'], [horizon])

    # --- Kids’ Duty Constraints ---
    # Simplified: Alternate shifts (for realism, expand to check overlaps)
    for act in ['wifes_parents', 'mom', 'personal_time']:
        model.AddNoOverlap([starts[act], ends[act], starts['kids_duty'], ends['kids_duty']])

    # --- Solve ---
    solver = cp_model.CpSolver()
    status = solver.Solve(model)

    # --- Print Schedule ---
    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()