def makeSchedule(content): horizon = content["horizon"] print(horizon) # Define all the players MyScenario = Scenario('manufacturing_schedule', horizon=horizon) MyResources = {} MyTasks = {} # Define the resources (manufacturing lines) manufacturing_lines = content["manufacturing_lines"] print(manufacturing_lines) for manufacturing_line in manufacturing_lines: MyResources[manufacturing_line] = MyScenario.Resource( str(manufacturing_line)) # Define tasks which are already present which must remain in the same location # Known as blocking tasks blocks = content["blocks"] print(blocks) for block in blocks: blockid = str(block["goal_name"] + "_" + str(block["sku_number"])) manufacturing_line_name = block["manufacturing_line_name"] start = block["start"] end = block["end"] # Create task and add the resource that will execute it task = MyScenario.Task(blockid, length=end - start) task += MyResources[manufacturing_line_name] # Define the bounds MyScenario += task > start, task < end # New tasks which must be scheduled tasks = content["tasks"] print(tasks) for task in tasks: taskid = str(task["goal_name"] + "_" + str(task["sku_number"])) duration = task["duration"] manufacturing_line_names = task["manufacturing_line_names"] deadline = task["deadline"] t = MyScenario.Task(taskid, length=duration, delay_cost=1) resources = MyResources[manufacturing_line_names[0]] for i in range(1, len(manufacturing_line_names)): resources = resources | MyResources[manufacturing_line_names[i]] t += resources MyScenario += t > 0, t < deadline solvers.mip.solve(MyScenario, msg=1) plotters.matplotlib.plot(MyScenario, img_filename='household.png') return MyScenario.solution()
def two_task_scenario(): S = Scenario('Scenario_1', horizon=horizon) T1 = S.Task('T1') T2 = S.Task('T2') R1 = S.Resource('R1') R2 = S.Resource('R2') S += T1 * 2 + T2 #T1 has priority to break ties return S
opts, _ = getopt.getopt(sys.argv[1:], 't:', ['test']) n_night_shifts = 5 n_day_shifts = 5 n_tasks = n_night_shifts + n_day_shifts horizon = n_tasks from pyschedule import Scenario, solvers, plotters S = Scenario('shift_bounds', horizon=horizon) R = S.Resource('P') for i in range(n_night_shifts): # added some delay cost, so without any # constraint, there would be first 5 night shifts # and then 5 day shifts T = S.Task('N%i' % i, delay_cost=2) # the shift type of night shifts is -1 T.shift_type = -1 T += R for i in range(n_day_shifts): T = S.Task('D%i' % i, delay_cost=1) # the shift type of day shifts is -1 T.shift_type = 1 T += R for i in range(horizon): # for every set of periods 1..i, make sure that # there is always at most one more night shift than # day shifts and vice versa. Each capacity constraint # limits the sum of 'shift_types' in the range S += R[:i]['shift_type'] <= 1
# read from folder import sys sys.path += ['../src','src'] import getopt opts, _ = getopt.getopt(sys.argv[1:], 't:', ['test']) from pyschedule import Scenario, solvers, plotters, Task S = Scenario('shift_bounds',horizon=8) # define two employees empl0 = S.Resource('empl0') empl1 = S.Resource('empl1') # employee 0 starts at two and ends # at most four hours later empl0_beg = S.Task('empl0_beg',completion_time_cost=2) empl0_beg += empl0 empl0_fin = S.Task('empl0_fin',completion_time_cost=2) empl0_fin += empl0 #S += 2 <= empl0_beg, empl0_fin < empl0_beg + 6 # employee 1 begins at any time and finishes # at most four hours later empl1_beg = S.Task('empl1_beg',completion_time_cost=2) empl1_beg += empl1 empl1_fin = S.Task('empl1_fin',completion_time_cost=2) empl1_fin += empl1 #S += empl1_fin < empl1_beg + 6 # interchangeable tasks that need to be finished as # by the two employees as early as possible
pierre = S.Resource('staff.pierre') val = S.Resource('staff.valentin') all_staff = (gui, pierre, val) # Weekends from dateutil.rrule import DAILY, rrule, SA def find_saturdays(start_date, end_date): return rrule(DAILY, dtstart=start_date, until=end_date, byweekday=(SA)) all_saturdays = find_saturdays(begin, until) for we_no, saturday in enumerate(all_saturdays): We = S.Task(name="We{0}".format(we_no), length=2) We += all_staff in_days = (saturday.date() - begin).days S += We <= in_days + 2, We >= in_days hide_list.append(We) # Collect unworkable days from Calendar # FIXME: Gérer les éléments de plusieurs journées # FIXME: Gérer les micro événements print("\t*Collecting calendar days...") from icalevents.icalevents import events es = events("https://calendar.google.com/", start=begin, end=until) for idx, ev in enumerate(es): if "Brassage" not in ev.summary or (ev.start.date() < today):
# test artefact for the case that pyschedule is # read from folder import sys sys.path.append('../src') import getopt opts, _ = getopt.getopt(sys.argv[1:], 't:', ['test']) horizon=10 from pyschedule import Scenario, solvers, plotters, alt S = Scenario('shift_bounds',horizon=horizon) # define two employees R = S.Resources('R',num=2) T0 = S.Task('T0',completion_time_cost=3) T0 += alt(R) T1 = S.Task('T1',completion_time_cost=1) T1 += alt(R) T1 += T0*R[0] T0 += T1*R[0] if solvers.mip.solve(S, msg=0): if ('--test','') in opts: assert(T0.start_value == 0) assert(T1.start_value == 1) print('test passed') else: plotters.matplotlib.plot(S, fig_size=(10, 5), vertical_text=True)
sys.path.append('../src') import getopt opts, _ = getopt.getopt(sys.argv[1:], 't:', ['test']) horizon = 10 from pyschedule import Scenario, solvers, plotters, alt S = Scenario('shift_bounds', horizon=horizon) # define two employees R = S.Resources('R', num=2) T0 = S.Task('T0', delay_cost=3) T0 += alt(R) T1 = S.Task('T1', delay_cost=1) T1 += alt(R) T1 += T0 * R[0] T0 += T1 * R[0] if solvers.mip.solve(S, msg=0): if ('--test', '') in opts: assert (T0.start_value == 0) assert (T1.start_value == 1) print('test passed') else: plotters.matplotlib.plot(S, fig_size=(10, 5), vertical_text=True)
from pyschedule import Scenario, solvers, plotters, alt # the planning horizon has 10 periods S = Scenario('household',horizon=10) # two resources: Alice and Bob Alice, Bob = S.Resource('Alice'), S.Resource('Bob') # three tasks: cook, wash, and clean cook = S.Task('cook',length=1,delay_cost=1) wash = S.Task('wash',length=2,delay_cost=1) clean = S.Task('clean',length=3,delay_cost=2) # every task can be done either by Alice or Bob cook += Alice | Bob wash += Alice | Bob clean += Alice | Bob # compute and print a schedule solvers.mip.solve(S,msg=1) print(S.solution()) plotters.matplotlib.plot(S,img_filename='household.png')
# Also see: https://developers.google.com/optimization/mip/integer_opt # https://towardsdatascience.com/modeling-and-optimization-of-a-weekly-workforce-with-python-and-pyomo-29484ba065bb from pyschedule import Scenario, solvers, plotters, alt, plotters from raw_data import tasks_data, workers_tasks_eligibility, workers_skills # the planning horizon has 10 periods S = Scenario("construction", horizon=10) # resources resources = {worker_id: S.Resource(worker_id, size=1) for worker_id in workers_skills} # tasks tasks = { task_id: S.Task(task_id, length=task_data["duration"], delay_cost=1) for task_id, task_data in tasks_data.items() } # for t in tasks.values(): # print(t.length) # Worker-Task eligibility. for task_id in tasks: eligible_workers = [] for worker_id, task_ids in workers_tasks_eligibility.items(): if task_id in task_ids: eligible_workers.append(resources[worker_id]) if len(eligible_workers) == 0: continue print(f"{task_id}: {eligible_workers}") for worker in eligible_workers: tasks[task_id] += alt(worker)
# Pour exécuter le fichier : # py -3.6 lenomdufichier.py from pyschedule import Scenario, solvers, plotters, alt # On crée un scénario , la période est en heures dans ce cas S = Scenario('emploiDeMaison', horizon=10) # 2 ressources: Alice et Bob Alice, Bob = S.Resource('Alice'), S.Resource('Bob') # 3 tâches: cuisiner, nettoyer, and polir cuisiner = S.Task('cuisiner', 1) nettoyer = S.Task('nettoyer', 2) polir = S.Task('polir', 3) # chaque tache peut être réalisée par Alice ou Bob cuisiner += Alice | Bob nettoyer += Alice | Bob polir += Alice | Bob # Résoudre et imprimer l'ordonnac S.use_makespan_objective() solvers.mip.solve(S, msg=1) print(S.solution()) # Dans cet exemple, nous utilisons un objectif makespan, # ce qui signifie que nous voulons minimiser le temps
# test artefact for the case that pyschedule is # read from folder import sys sys.path.append('../src') horizon = 4 import getopt opts, _ = getopt.getopt(sys.argv[1:], 't:', ['test']) from pyschedule import Scenario, solvers, plotters, alt S = Scenario('test', horizon=horizon) R = S.Resources('R', num=2) T0 = S.Task('T0', delay_cost=1) T0 += R[0] T1 = S.Task('T1', length=2, delay_cost=4) T1 += alt(R) T2 = S.Task('T2', delay_cost=3) T2 += alt(R) S += T0 < T1 * R[0] S += T0 < T2 * R[0] #S += T1 < T0*R[0] #S += T1 < T2*R[0] if solvers.mip.solve(S, msg=0): opts, _ = getopt.getopt(sys.argv[1:], 't:', ['test']) if ('--test', '') in opts:
# read from folder import sys sys.path += ['../src', 'src'] import getopt opts, _ = getopt.getopt(sys.argv[1:], 't:', ['test']) from pyschedule import Scenario, solvers, plotters, Task S = Scenario('shift_bounds', horizon=8) # define two employees empl0 = S.Resource('empl0') empl1 = S.Resource('empl1') # employee 0 starts at two and ends # at most four hours later empl0_beg = S.Task('empl0_beg', delay_cost=2) empl0_beg += empl0 empl0_fin = S.Task('empl0_fin', delay_cost=2) empl0_fin += empl0 #S += 2 <= empl0_beg, empl0_fin < empl0_beg + 6 # employee 1 begins at any time and finishes # at most four hours later empl1_beg = S.Task('empl1_beg', delay_cost=2) empl1_beg += empl1 empl1_fin = S.Task('empl1_fin', delay_cost=2) empl1_fin += empl1 #S += empl1_fin < empl1_beg + 6 # interchangeable tasks that need to be finished as # by the two employees as early as possible
# Pour exécuter le fichier : # py -3.6 lenomdufichier.py from pyschedule import Scenario, solvers, plotters, alt # On crée un scénario , la période est en heures dans ce cas S = Scenario('emploiDeMaison', horizon=10) # 2 ressources: Alice et Bob Alice, Bob = S.Resource('Alice'), S.Resource('Bob') # 3 tâches: cuisiner, nettoyer, and polir # length : durée en heure, delay_cost = cout cuisiner = S.Task('cuisiner', length=1, delay_cost=1) nettoyer = S.Task('nettoyer', length=2, delay_cost=1) polir = S.Task('polir', length=3, delay_cost=2) # chaque tache peut être réalisée par Alice ou Bob cuisiner += Alice | Bob nettoyer += Alice | Bob polir += Alice | Bob # Résoudre et imprimer l'ordonnacement des tâches solvers.mip.solve(S, msg=1) print(S.solution()) # Résultat # INFO: execution time for solving mip (sec) = 0.04697251319885254 # INFO: objective = 1.0
transfer = S.Task('transfer.{0}'.format(name), length=60) transfer += bk return mash, [mash <= sparge1, sparge1 <= sparge2, sparge2 <= boil, boil <= transfer] mash1, brew1 = make_brew("A") S += brew1 mash2, brew2 = make_brew("B") S += brew2 remove_spent_grain = S.Task('remove_spent_grain', length=20) remove_spent_grain += mt remove_spent_grain.dirty = -1 clean_mt = S.Task('clean_mt', length=30) clean_mt += mt clean_bk = S.Task('clean_bk', length=40) clean_bk += bk S += [mash1 < mash2, mash1 < remove_spent_grain, mash2 < clean_mt, mash2 < clean_bk] S += [remove_spent_grain < clean_mt,
from pyschedule import Scenario, solvers, plotters, alt S = Scenario('schedule_cost', horizon=10) R = S.Resource('R') # not setting a schedule cost will set it to None T0 = S.Task('T0', length=2, delay_cost=1) # setting the schedule cost of T1 to -1 T1 = S.Task('T1', length=2, delay_cost=1, schedule_cost=-1) T0 += R T1 += R solvers.mip.solve(S, msg=1) print(S.solution()) plotters.matplotlib.plot(S, img_filename='pyschedule_2.png')
from pyschedule import Scenario, solvers, plotters, alt S = Scenario('resource_cost', horizon=10) # assign a cost per period of 5 R = S.Resource('R', cost_per_period=5) T = S.Task('T', length=2, delay_cost=1) T += R solvers.mip.solve(S, msg=1) print(S.solution()) plotters.matplotlib.plot(S, img_filename='pyschedule_3.png')
opts, _ = getopt.getopt(sys.argv[1:], 't:', ['test']) n_night_shifts = 5 n_day_shifts = 5 n_tasks = n_night_shifts + n_day_shifts horizon = n_tasks from pyschedule import Scenario, solvers, plotters S = Scenario('shift_bounds', horizon=horizon) R = S.Resource('P') for i in range(n_night_shifts): # added some completion time cost, so without any # constraint, there would be first 5 night shifts # and then 5 day shifts T = S.Task('N%i' % i, completion_time_cost=2) # the shift type of night shifts is -1 T.shift_type = -1 T += R for i in range(n_day_shifts): T = S.Task('D%i' % i, completion_time_cost=1) # the shift type of day shifts is -1 T.shift_type = 1 T += R for i in range(horizon): # for every set of periods 1..i, make sure that # there is always at most one more night shift than # day shifts and vice versa. Each capacity constraint # limits the sum of 'shift_types' in the range S += R[:i]['shift_type'] <= 1
horizon = 20 S = Scenario('switch',horizon=horizon) # Set some colors for the tasks task_colors = dict() task_group_colors = { 'A': 'green', 'B': 'red', 'C':'blue'} R_machine = S.Resource('machine') T = dict() task_types = { 'A': 1, 'B': 2, 'C': 3} task_lengths = { 'A': 2, 'B': 3, 'C':1 } max_n_switches = 10 for i in range(max_n_switches): name = 'S_%i'%i T[name] = S.Task(name,group='switch') T[name] += R_machine T[name]['schedule_cost'] = 0.001 for task_type in task_types: setup_param = '%s_state'%task_type T[name][setup_param] = 1 for task_type in task_types: for i in range(task_types[task_type]): name = '%s_%i'%(task_type,i) setup_param = '%s_state'%task_type T[name] = S.Task(name,group=task_type,length=task_lengths[task_type]) T[name][setup_param] = 2 #T[name]['reward'] = 1 T[name] += R_machine task_colors[T[name]] = task_group_colors[task_type]
from pyschedule import plotters, Scenario, solvers S = Scenario('asdf', horizon=20) r = S.Resource('r', periods=range(20)) t2 = S.Task('CE2', length=20) t2 += r res = solvers.mip.solve_tsp(S, msg=0) print(S.solution()) print(S)
n_plays_at_home = 4 max_n_not_at_home_periods = 3 S = Scenario('sports_scheduline',horizon=n_slots) Stadiums = S.Resources('Stadium',num=n_stadiums) Teams = S.Resources('T',num=n_teams) Team2Stadium = dict(zip(Teams,Stadiums)) Games = list() for Team0 in Teams: count = 1 for Team1 in Teams: if Team0.name >= Team1.name: continue Game = S.Task('%s%s'%(Team0,Team1),completion_time_cost=2**count) Game[Team0.name] = 1 Game[Team1.name] = 1 Games.append(Game) Game += Team0, Team1 Game += Team2Stadium[Team0] | Team2Stadium[Team1] count += 1 for Team in Team2Stadium: Stadium = Team2Stadium[Team] S += Stadium[Team.name] >= n_plays_at_home S += Stadium[Team.name][0:n_slots:max_n_not_at_home_periods] >= 1 if solvers.mip.solve(S,msg=0,kind='CBC'): import getopt
# Will be created when needed teachers = {} classes = {} for cls, _ in config['tclasses'].items(): classes[cls] = scen.Resource(cls) courses = {} for course, info in config['courses'].items(): if isinstance(info, list): info = { "profs": [info[0]], "length": info[1] } courses[course] = task = scen.Task(course, info["length"]) if info["length"] == 4: task.periods = [x for x in range(0, DAYS * 5) if x % 5 == 0] elif info["length"] == 2: task.periods = [x for x in range(0, DAYS * 5) if x % 5 == 0] task.periods += [x + 2 for x in range(0, DAYS * 5) if x % 5 == 0] for teacher in info["profs"]: if (not teacher in teachers): teachers[teacher] = scen.Resource(teacher.replace(' ', '_')) # print(" - " + teacher) task += teachers[teacher] for cls, cls_courses in config['tclasses'].items(): if course in cls_courses:
# test artefact for the case that pyschedule is # read from folder import sys sys.path.append('../src') horizon = 5 import getopt opts, _ = getopt.getopt(sys.argv[1:], 't:', ['test']) from pyschedule import Scenario, solvers, plotters, alt S = Scenario('test', horizon=horizon) # define two employees R = S.Resources('R', num=2) T0 = S.Task('T0', completion_time_cost=10) T0 += alt(R) T1 = S.Task('T1', length=2, completion_time_cost=2) T1 += alt(R) T2 = S.Task('T2', length=2, completion_time_cost=1) T2 += alt(R) S += T1 * R[0] <= T0 S += T2 * R[0] <= T0 if solvers.mip.solve(S, msg=0): if ('--test', '') in opts: assert (T0.start_value == 0) assert (T1.start_value == 0) assert (T2.start_value == 2)
def solve(solver_data): # create scenario scenario = Scenario(name='scenario', horizon=int(solver_data['horizon'])) # resources list resources = {} resources_map = {} resources_mapi = {} resources_ai = 0 # tasks list tasks = {} tasks_map = {} tasks_mapi = {} tasks_ai = 0 # blocks ai blocks_ai = 0 # # enter resources print('[INFO] Importing resources...') for i, resource in enumerate(solver_data['resources']): print('[INFO] Importing resources... ({}/{})'.format( i + 1, len(solver_data['resources'])), end='\r') # convert to [name, size = 1] if not isinstance(resource, list): resource = [resource, 1] # label given to the solver backend rname = 'r' + str(resources_ai) has_parallel = False if resource[0].startswith('teacher_'): for task in solver_data['tasks']: if resource[0] in task['resources'] and task['tags'][ 'block_value'] != task['length']: has_parallel = True print('Found parallel', resource, ' ') break size = 2 if has_parallel else 1 resources[rname] = scenario.Resource(rname, size=size) resources_map[rname] = resource[0] resources_mapi[resource[0]] = rname resources_ai += 1 if has_parallel: scenario += resources[rname]['block_value'][ 0:int(solver_data['horizon']):1] <= 1 # # enter tasks print('[INFO] Importing tasks...') for task in solver_data['tasks']: tname = 't' + str(tasks_ai) tasks[tname] = scenario.Task(tname, length=task['length'], **task['tags']) tasks_map[tname] = task['label'] tasks_mapi[task['label']] = tname tasks_ai += 1 tasks[tname]['r_' + tname] = 1 if 'period' in task and task['period'] != -1: tasks[tname].periods = [task['period']] else: if task['length'] == 4: tasks[tname].periods = [ i for i in range(0, solver_data['horizon']) if i % 4 == 0 ] else: tasks[tname].periods = [ i for i in range(0, solver_data['horizon']) if i % 2 == 0 ] # add resources to task for res_name in task['resources']: tasks[tname] += resources[resources_mapi[res_name]] # # enter blocks print('[INFO] Importing blocks...') for block in solver_data['blocks']: bname = 'b' + str(blocks_ai) task = scenario.Task(bname, length=1, periods=[block["start"]], plot_color='#000000', block_value=1) task += resources[resources_mapi[block["resource"]]] blocks_ai += 1 print('[INFO] Importing sblocks...') for block in solver_data['sblocks']: bname = 'b' + str(blocks_ai) task = scenario.Task(bname, length=1, periods=[block["start"]], plot_color='#000000', schedule_cost=block["cost"], block_value=1) task += resources[resources_mapi[block["resource"]]] blocks_ai += 1 # # enter sync constraints print('[INFO] Importing sync constraints...') for constraint in solver_data['constraints']['sync']: scenario += tasks[tasks_mapi[constraint['tasks'][0]]] <= tasks[ tasks_mapi[constraint['tasks'][1]]] + tasks[tasks_mapi[ constraint['tasks'][0]]].length # # enter cap constraints print(solver_data['constraints']['cap']) # solver_data['constraints']['cap'] = [ # ['group_118', 'group_117'], ['group_118', 'group_116']] for i, constraint in enumerate(solver_data['constraints']['cap']): print('[INFO] Importing capacity constraints... ({}/{})'.format( i + 1, len(solver_data['constraints']['cap']))) for res in resources.values(): if res.size == 1: continue cond = res[constraint[0]][0:int(solver_data['horizon']):1].max for t in constraint[1:]: cond = cond + res[t][0:int(solver_data['horizon']):1].max scenario += cond <= 1 # # solve if solvers.mip.solve(scenario, msg=1): # plotters.matplotlib.plot(scenario, img_filename='out.png', fig_size=( # resources_ai / 3, resources_ai / 2)) solution = scenario.solution() real_solution = [[str(l[0]), str(l[1]), l[2], l[3]] for l in solution] for item in real_solution: if item[0][0] == 'b': continue item[0] = tasks_map[str(item[0])] item[1] = resources_map[str(item[1])] return {'solved': True, 'data': real_solution} else: return {'solved': False, 'error': 'Impossible'}
n_plays_at_home = 4 max_n_not_at_home_periods = 3 S = Scenario('sports_scheduline', horizon=n_slots) Stadiums = S.Resources('Stadium', num=n_stadiums) Teams = S.Resources('T', num=n_teams) Team2Stadium = dict(zip(Teams, Stadiums)) Games = list() for Team0 in Teams: count = 1 for Team1 in Teams: if Team0.name >= Team1.name: continue Game = S.Task('%s%s' % (Team0, Team1), delay_cost=2**count) Game[Team0.name] = 1 Game[Team1.name] = 1 Games.append(Game) Game += Team0, Team1 Game += Team2Stadium[Team0] | Team2Stadium[Team1] count += 1 for Team in Team2Stadium: Stadium = Team2Stadium[Team] S += Stadium[Team.name] >= n_plays_at_home S += Stadium[Team.name][0:n_slots:max_n_not_at_home_periods] >= 1 if solvers.mip.solve(S, msg=0, kind='CBC'): import getopt opts, _ = getopt.getopt(sys.argv[1:], 't:', ['test'])
resource_list = [] task_list = [] for i in range(len(name_list)): resource_list.append( S.Resource(name_list[i].replace(" ", ""), length=1, periods=[ getPeriodFromTime(t) for t in data['times'][i]['availableTimes'] ])) for i in range(len(name_list2)): task_list.append( S.Task(name_list2[i].replace(" ", ""), length=1, periods=[ getPeriodFromTime(t) for t in data2['times'][i]['availableTimes'] ])) name_perms = list(combinations(range(len(name_list)), 2)) final = [[S.resources()[x[0]], S.resources()[x[1]]] for x in name_perms] for t in task_list: random.shuffle(resource_list) t += alt(resource_list[:10]), alt(resource_list[10:]) # compute and print a schedule solvers.mip.solve(S, random_seed=random.randint(1, 1000)) soln = S.solution() interviewList = []