144 lines
5.7 KiB
Python
144 lines
5.7 KiB
Python
from __future__ import print_function
|
|
from ortools.linear_solver import pywraplp
|
|
import sys
|
|
|
|
def main():
|
|
|
|
# days
|
|
days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
|
|
|
|
# hours
|
|
hours = [
|
|
'00',
|
|
'01',
|
|
'02',
|
|
'03',
|
|
'04',
|
|
'05',
|
|
'06',
|
|
'07',
|
|
'08',
|
|
'09',
|
|
'10',
|
|
'11',
|
|
'12',
|
|
'13',
|
|
'14',
|
|
'15',
|
|
'16',
|
|
'17',
|
|
'18',
|
|
'19',
|
|
'20',
|
|
'21',
|
|
'22',
|
|
'23']
|
|
|
|
# initialize required hours - req_hours[days][hours]
|
|
req_hours = [[0 for x in range(len(hours))] for y in range(len(days))]
|
|
|
|
# get arguments
|
|
# there will be 8 arguments, monday to sunday schedule and the shift selected
|
|
# sample argument:
|
|
# 0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0 0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0 0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0 0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0 0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0 0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0 0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0 24_7
|
|
for day_index in range(0, len(days)):
|
|
hours_string = sys.argv[day_index + 1]
|
|
hours_data = hours_string.split('-')
|
|
for hour_index in range(0, len(hours)):
|
|
req_hours[day_index][hour_index] = int(hours_data[hour_index])
|
|
|
|
argv_index = day_index + 2
|
|
# number of days is fixed at 7 so the number of shifts will be in index 8
|
|
num_shifts = sys.argv[argv_index]
|
|
|
|
hour_shifts = []
|
|
for shift_ctr in range(0, int(num_shifts)):
|
|
# form list within the list
|
|
hour_shift_item = []
|
|
|
|
shift = sys.argv[argv_index+1]
|
|
|
|
# append to list
|
|
hour_shift_item.append(shift)
|
|
|
|
# append the list to the list
|
|
hour_shifts.append(hour_shift_item)
|
|
argv_index+=1
|
|
|
|
# all possible days riders come in
|
|
day_shifts = [
|
|
['Mon - Sat', 0, 1, 2, 3, 4, 5], # Mon - Sat
|
|
['Tue - Sun', 1, 2, 3, 4, 5, 6], # Tue - Sun
|
|
['Wed - Mon', 2, 3, 4, 5, 6, 0], # Wed - Mon
|
|
['Thu - Tue', 3, 4, 5, 6, 0, 1], # Thu - Tue
|
|
['Fri - Wed', 4, 5, 6, 0, 1, 2], # Fri - Wed
|
|
['Sat - Thu', 5, 6, 0, 1, 2, 3], # Sat - Thu
|
|
['Sun - Fri', 6, 0, 1, 2, 3, 4]] # Sun - Fri
|
|
|
|
# build shift lookup index
|
|
|
|
|
|
# instantiate glop solver
|
|
solver = pywraplp.Solver('SolveSchedule', pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING)
|
|
|
|
# solver variables
|
|
solv_shifts = [[0 for x in range(len(hour_shifts))] for y in range(len(day_shifts))]
|
|
|
|
# objective
|
|
objective = solver.Objective()
|
|
|
|
# variables for shifts
|
|
for day_index in range(0, len(day_shifts)):
|
|
for hour_index in range(0, len(hour_shifts)):
|
|
solv_shifts[day_index][hour_index] = solver.IntVar(0, solver.infinity(), day_shifts[day_index][0] + ' ' + hour_shifts[hour_index][0])
|
|
# objective is to minimize number of shifts
|
|
objective.SetCoefficient(solv_shifts[day_index][hour_index], 1)
|
|
objective.SetMinimization()
|
|
|
|
# set constraints
|
|
constraints = [[0 for x in range(len(hours))] for y in range(len(days))]
|
|
# go through all days
|
|
for day_index in range(0, len(days)):
|
|
# go through all hours
|
|
for hour_index in range(0, len(hours)):
|
|
# hour personnel should be equal or less than shift personnel that covers those hours
|
|
# set the required manpower for that day + hour combo
|
|
# print('setting constraint for', day_index, '-', hour_index, '=', req_hours[day_index][hour_index])
|
|
constraints[day_index][hour_index] = solver.Constraint(req_hours[day_index][hour_index], solver.infinity())
|
|
# go through all day shifts
|
|
for shift_day in range(0, len(day_shifts)):
|
|
# go through days inside day shift
|
|
for shift_day_index in range(1, len(day_shifts[shift_day])):
|
|
# is day shift part of that day?
|
|
if day_index == day_shifts[shift_day][shift_day_index]:
|
|
# go through all hour shifts
|
|
for shift_hour in range(0, len(hour_shifts)):
|
|
# go through all hours inside hour shift
|
|
for shift_hour_index in range(1, len(hour_shifts[shift_hour])):
|
|
# is hour shift part of the hour
|
|
if hour_index == hour_shifts[shift_hour][shift_hour_index]:
|
|
# print(day_index, ' - ', hour_index, ' vs ', day_shifts[shift_day][shift_day_index], ' - ', hour_shifts[shift_hour][shift_hour_index])
|
|
# add it to constraint
|
|
constraints[day_index][hour_index].SetCoefficient(solv_shifts[shift_day][shift_hour], 1)
|
|
|
|
# solve it!
|
|
status = solver.Solve()
|
|
#print('Number of variables =', solver.NumVariables())
|
|
#print('Number of constraints =', solver.NumConstraints())
|
|
|
|
if status == solver.OPTIMAL:
|
|
#print('Optimal solution found!')
|
|
for day_index in range(0, len(day_shifts)):
|
|
for hour_index in range(0, len(hour_shifts)):
|
|
result = solv_shifts[day_index][hour_index].solution_value()
|
|
if result > 0:
|
|
print(day_index, hour_index, int(solv_shifts[day_index][hour_index].solution_value()), sep='-')
|
|
#print(day_shifts[day_index][0], ' ', hour_shifts[hour_index][0], ' = ', int(solv_shifts[day_index][hour_index].solution_value()), sep='')
|
|
else:
|
|
if status == solver.FEASIBLE:
|
|
print('Feasible solution found!')
|
|
else:
|
|
print('Could not solve problem.')
|
|
|
|
if __name__ == '__main__':
|
|
main()
|