2

Im using that nurse scheduling example. I have 3 employee 2 shifts and 7 days and I have a contiditon that if an employee works in shift 1 he/she cannot work the next day on shift 0. here is my code and it does not work.

    for n in all_nurses:
      for d in all_days:
        model.Add(sum(shifts[(n, d, s)] for s in range(0,1))+sum(shifts[(n, (d+1)%6, s)] for s in range(1,2)) <= 1)

and this is the output . Nurse 2 worked on day 0 and shift 1 and next day also worked on shift1

Be Ta
  • 45
  • 11
  • - try to split your command, to many generator expression here... - if you have two shift 0 and 1 why using `for s in range(0,1)` and `for s in range(1,2)` not sure it did what you expect - your modulo should be `%7` for seven days... – Mizux Mar 12 '19 at 09:15
  • day indexes starts with 0 so Sunday is 6. and I am using for s in range(0,1) because I cant set s variable directly. when I try that I got error messages. – Be Ta Mar 12 '19 at 10:50

1 Answers1

2

According to your constraint:

for n in all_nurses:
    for d in all_days:
        model.Add(sum([shifts[(n, d, 1)], shifts[(n, (d+1)%7, 0)]]) <= 1)

A better formulation would be

for n in all_nurses:
    for d in all_days:
        model.AddBoolOr([shifts[(n, d, 1)].Not(), shifts[(n, (d + 1) % 7, 0)].Not()])

ref: https://github.com/google/or-tools/blob/aa0c6c42a523ee4c23633585b86fb6d3e090f8c8/ortools/sat/samples/bool_or_sample_sat.py#L23-L28

Mizux
  • 8,222
  • 7
  • 32
  • 48
  • Thank you very much for the response. still it did not work I tried something else. ` for n in all_nurses: for d in all_days: model.Add(sum(shifts[(n, (d-1)%6, s)] for s in range(1,2))+sum(shifts[(n, d, s)] for s in range(0,1)) <= 1) ` it worked with that and code above – Be Ta Mar 12 '19 at 10:53
  • my bad i used `sum(a+b)...` instead of `sum([a,b])...` – Mizux Mar 12 '19 at 10:58
  • `(x%7)` will range from `[0;6]` – Mizux Mar 12 '19 at 11:00
  • ok. I tried again and I got this error --> model.Add(sum(shifts[(n, d, 1)], shifts[(n, (d+1)%7, 0)]) <= 1) TypeError: 'IntVar' object is not iterable – Be Ta Mar 12 '19 at 11:40
  • 2
    Should be model.Add(shifts[(n, d, 1)] + shifts[(n, (d+1)%7, 0)] <= 1). Which is better written as model.AddBoolOr([shifts[(n, d, 1)].Not(), (shifts[(n, (d + 1) % 7, 0)].Not()]) – Laurent Perron Mar 12 '19 at 15:50
  • @BerfinTanrıverdi you missed the enclosed [] inside the sum -> 'sum([....])', otherwise python take the 2 arguments as begin/end iterators... – Mizux Mar 12 '19 at 16:08
  • @LaurentPerron thank you very very much. model.Add(shifts[(n, d, 1)] + shifts[(n, (d+1)%7, 0)] <= 1) that one worked. but model.AddBoolOr([shifts[(n, d, 1)].Not(), (shifts[(n, (d + 1) % 7, 0)].Not()]) that one got syntax error – Be Ta Mar 13 '19 at 05:00
  • @Mizux ok that one also worked. Thank you very much! – Be Ta Mar 13 '19 at 05:04
  • 1
    model.AddBoolOr([shifts[(n, d, 1)].Not(), shifts[(n, (d + 1) % 7, 0)].Not()]) – Laurent Perron Mar 13 '19 at 13:51