Or-tools护士排班问题:添加连续至少工作2天约束报错求助
Hey there! Let's break down why your current code is throwing errors and how to fix the constraint properly.
Why Your Attempts Failed
Both of your tries hit issues because OR-Tools doesn't support using Python's native and operator directly in constraint conditions. Here's the breakdown:
- First try:
shifts[(n, d-1, s)]==0 and shifts[(n, d, s)]==1gets evaluated as a plain Python boolean expression (not an OR-Tools constraint object), whichAddImplicationcan't process—hence theTypeError. - Second try: The
andhere returns aBoundedLinearExpressioninstead of a valid boolean variable/index thatOnlyEnforceIfexpects, leading to theAttributeError.
Correct Implementation
To enforce "if a nurse works shift s on day d and didn't work it on day d-1, they must work it on day d+1", you need to use OR-Tools' built-in logical constraint helpers like AddBoolAnd to combine your conditions properly.
Here's the revised code:
for n in all_nurses: # Adjust the date range to avoid index out-of-bounds (d-1 and d+1 must be valid days) # Assuming your days are indexed from 0 to 6 (7 days total), use d from 1 to 5 for d in range(1, len(all_days) - 1): for s in all_shifts: # Define the two conditions as OR-Tools expressions prev_day_off = shifts[(n, d-1, s)] == 0 today_on = shifts[(n, d, s)] == 1 # Combine conditions with AddBoolAnd to create a valid boolean constraint must_work_next_day = model.AddBoolAnd([prev_day_off, today_on]) # Enforce: if the combined condition is true, next day must be on shift s model.AddImplication(must_work_next_day, shifts[(n, d+1, s)] == 1)
Handling Edge Cases
Don't forget the last day of your schedule! The above code doesn't cover if a nurse works the final day but didn't work the day before. Add this extra constraint to close that gap:
last_day = len(all_days) - 1 for n in all_nurses: for s in all_shifts: # If nurse works last day, they must have worked the previous day model.Add(shifts[(n, last_day - 1, s)] == 1).OnlyEnforceIf(shifts[(n, last_day, s)] == 1)
How This Works
AddBoolAnd([prev_day_off, today_on])creates a boolean variable that's onlyTruewhen both conditions are met.AddImplication(condition, consequence)ensures that if the condition isTrue, the consequence (working the next day) must also beTrue.- The edge case constraint prevents a single shift on the final day, fully enforcing your "at least 2 consecutive work days" rule.
内容的提问来源于stack exchange,提问作者Przemek

