151 lines
6.1 KiB
Python
151 lines
6.1 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 7 arguments, monday to sunday schedule
|
|
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])
|
|
|
|
# all hour shifts available
|
|
hour_shifts = [
|
|
['00 - 09', 0, 1, 2, 3, 4, 5, 6, 7, 8],
|
|
['01 - 10', 1, 2, 3, 4, 5, 6, 7, 8, 9],
|
|
['02 - 11', 2, 3, 4, 5, 6, 7, 8, 9, 10],
|
|
['03 - 12', 3, 4, 5, 6, 7, 8, 9, 10, 11],
|
|
['04 - 13', 4, 5, 6, 7, 8, 9, 10, 11, 12],
|
|
['05 - 14', 5, 6, 7, 8, 9, 10, 11, 12, 13],
|
|
['06 - 15', 6, 7, 8, 9, 10, 11, 12, 13, 14],
|
|
['07 - 16', 7, 8, 9, 10, 11, 12, 13, 14, 15],
|
|
['08 - 17', 8, 9, 10, 11, 12, 13, 14, 15, 16],
|
|
['09 - 18', 9, 10, 11, 12, 13, 14, 15, 16, 17],
|
|
['10 - 19', 10, 11, 12, 13, 14, 15, 16, 17, 18],
|
|
['11 - 20', 11, 12, 13, 14, 15, 16, 17, 18, 19],
|
|
['12 - 21', 12, 13, 14, 15, 16, 17, 18, 19, 20],
|
|
['13 - 22', 13, 14, 15, 16, 17, 18, 19, 20, 21],
|
|
['14 - 23', 14, 15, 16, 17, 18, 19, 20, 21, 22],
|
|
['15 - 00', 15, 16, 17, 18, 19, 20, 21, 22, 23],
|
|
['16 - 01', 16, 17, 18, 19, 20, 21, 22, 23, 0],
|
|
['17 - 02', 17, 18, 19, 20, 21, 22, 23, 0, 1],
|
|
['18 - 03', 18, 19, 20, 21, 22, 23, 0, 1, 2],
|
|
['19 - 04', 19, 20, 21, 22, 23, 0, 1, 2, 3],
|
|
['20 - 05', 20, 21, 22, 23, 0, 1, 2, 3, 4],
|
|
['21 - 06', 21, 22, 23, 0, 1, 2, 3, 4, 5],
|
|
['22 - 07', 22, 23, 0, 1, 2, 3, 4, 5, 6],
|
|
['23 - 08', 23, 0, 1, 2, 3, 4, 5, 6, 7]]
|
|
|
|
# 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()
|