487. Scheduling Code

from pyomo.environ import *
from pyomo.dataportal import DataPortal

model = AbstractModel()

# Sets
model.Days = Set(ordered=True)           # Days 1..7 (Mon..Sun)
model.Shifts = Set(ordered=True)         # Shifts starting on days 1..7

# Parameters
model.Demand = Param(model.Days)         # Daily staffing requirements
model.Cover = Param(model.Days, model.Shifts, within=Binary)  # Coverage matrix (1 if shift j covers day i)

# Variables
model.x = Var(model.Shifts, domain=NonNegativeReals)

# Objective: Minimize total employees hired
def obj_rule(model):
    return sum(model.x[s] for s in model.Shifts)
model.OBJ = Objective(rule=obj_rule, sense=minimize)

# Constraints: Cover daily demand
def demand_rule(model, d):
    return sum(model.Cover[d, s] * model.x[s] for s in model.Shifts) >= model.Demand[d]
model.DemandConstraint = Constraint(model.Days, rule=demand_rule)

# Load data from .dat file
data = DataPortal()
data.load(filename='data.dat', model=model)

# Create an instance of the model
instance = model.create_instance(data)

# Create solver
solver = SolverFactory('glpk')
solver.options['tmlim'] = 60

# Solve with solver timeout (optional)
results = solver.solve(instance, tee=True)

# Display results
instance.display()
set Days := Mon Tue Wed Thu Fri Sat Sun ;
set Shifts := s1 s2 s3 s4 s5 s6 s7 ;

param Demand :=
Mon 110
Tue 80
Wed 150
Thu 30
Fri 70
Sat 160
Sun 120 ;

# Each shift covers 5 consecutive days starting on the shift's day
# 1 if shift s_j covers day d_i, 0 otherwise

param Cover:
        s1 s2 s3 s4 s5 s6 s7 :=
Mon     1  0  0  1  1  1  1
Tue     1  1  0  0  1  1  1
Wed     1  1  1  0  0  1  1
Thu     1  1  1  1  0  0  1
Fri     1  1  1  1  1  0  0
Sat     0  1  1  1  1  1  0
Sun     0  0  1  1  1  1  1 ;