Search code examples
optimizationconstraintslinear-programmingpulp

consecutive days constraint in linear programming


For a work shift optimization problem, I've defined a binary variable in PuLP as follows:

pulp.LpVariable.dicts('VAR', (range(D), range(N), range(T)), 0, 1, 'Binary')

where

  1. D = # days in each schedule we create (=28, or 4 weeks)
  2. N = # of workers
  3. T = types of work shift (=6)

For the 5th and 6th type of work shift (with index 4 and 5), I need to add a constraint that any worker who works these shifts must do so for seven consecutive days... and not any seven days but the seven days starting from Monday (aka a full week). I've tried defining the constraint as follows, but I'm getting an infeasible solution when I add this constraint and try to solve the problem (it worked before without it)

I know this constraint (along with the others from before) should theoretically be feasible because we manually schedule work shifts with the same set of constraints. Is there anything wrong with the way I've coded the constraint?

## looping over each worker
for j in range(N):
    ## looping for every Monday in the 28 days 
    for i in range(0,D,7):
        c = None
        ## accessing only the 5th and 6th work shift type 
        for k in range(4,T):
            c+=var[i][j][k]+var[i+1][j][k]+var[i+2][j][k]+var[i+3][j][k]+var[i+4][j][k]+var[i+5][j][k]+var[i+6][j][k]
        problem+= c==7

Solution

  • If I understand correctly then your constraint requires that each worker is required to work the 4th and 5th shift in every week. This is because of c == 7, i.e. 7 of the binaries in c must be set to 1. This does not allow any worker to work in shift 0 through 3, right?

    You need to change the constraint so that c == 7 is only enforced if the worker works any shift in that range. A very simple way to do that would be something like

    v = list()
    for k in range(4,T):
      v.extend([var[i][j][k], var[i+1][j][k], var[i+2][j][k], var[i+3][j][k], var[i+4][j][k], var[i+5][j][k], var[i+6][j][k]])
    c = sum(v)
    problem += c <= 7        # we can pick at most 7 variables from v
    for x in v:
      problem += 7 * x <= c  # if any variable in v is picked, then we must pick 7 of them
    

    This is by no means the best way to model that (indicator variables would be much better), but it should give you an idea what to do.