resq/utils/schedule_solver/solver.py

118 lines
4 KiB
Python

from __future__ import print_function
from ortools.linear_solver import pywraplp
import sys
def main():
# get arguments
hours_string = sys.argv[1]
hours_data = hours_string.split('-')
# initialize hours
hours = [
['00', 0],
['01', 0],
['02', 0],
['03', 0],
['04', 0],
['05', 0],
['06', 0],
['07', 0],
['08', 0],
['09', 0],
['10', 0],
['11', 0],
['12', 0],
['13', 0],
['14', 0],
['15', 0],
['16', 0],
['17', 0],
['18', 0],
['19', 0],
['20', 0],
['21', 0],
['22', 0],
['23', 0]]
# set hours from argument
for i in range(0, len(hours_data)):
hours[i][1] = int(hours_data[i])
# all shifts available
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]]
# instantiate glop solver
solver = pywraplp.Solver('SolveSchedule', pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING)
# solver variables
solv_shifts = [[]] * len(shifts)
# objective
objective = solver.Objective()
# variables for shifts
for i in range(0, len(shifts)):
solv_shifts[i] = solver.IntVar(0, solver.infinity(), shifts[i][0])
# objective is to minimize number of shifts
objective.SetCoefficient(solv_shifts[i], 1)
objective.SetMinimization()
# set constraints
constraints = [0] * len(hours)
for hour_index in range(0, len(hours)):
# hour personnel should be equal or less than shift personnel that covers those hours
constraints[hour_index] = solver.Constraint(hours[hour_index][1], solver.infinity())
for shift_index in range(0, len(shifts)):
# get each shift's hour coverage
for shift_hour_index in range(1, len(shifts[shift_index])):
# check if shift covers that hour
# NOTE: this can still be optimized later via indexing
if shifts[shift_index][shift_hour_index] == hour_index:
# print('hour', hour_index, 'in shift index -', shift_index)
constraints[hour_index].SetCoefficient(solv_shifts[shift_index], 1)
# solve it!
status = solver.Solve()
if status == solver.OPTIMAL:
#print('Optimal solution found!')
#print('Number of variables =', solver.NumVariables())
#print('Number of constraints =', solver.NumConstraints())
for i in range(0, len(shifts)):
result = solv_shifts[i].solution_value()
if result > 0:
print(i, '-', int(solv_shifts[i].solution_value()), sep='')
else:
if status == solver.FEASIBLE:
print('Feasible solution found!')
else:
print('Could not solve problem.')
if __name__ == '__main__':
main()