def cplex_makespan_model(n: int, m: int, durations, machines) -> CpoModel: # n number of jobs, m machines # 1 line for un job with tasks on m machines naive = np.sum(durations) mdl = CpoModel() #Une variable est l'intervalle de durée pour une tache x = [[ mdl.interval_var(size=durations[i, j], name="O{}-{}".format(i, j)) for j in range(m) ] for i in range(n)] #contrainte end max d'une tache calculée avant for i in range(n): for j in range(m): mdl.add(mdl.end_of(x[i][j]) <= naive) #precedence for i in range(n): #for each job for j in range(m - 1): #taches ordonnées mdl.add(mdl.end_before_start(x[i][j], x[i][j + 1])) # une machine ne peut faire qu'une tache à la fois listtaches = [[] for k in range(m)] for i in range(n): for j in range(m): listtaches[machines[i, j]].append(x[i][j]) for k in range(m): mdl.add(mdl.no_overlap(listtaches[k])) makespan = mdl.integer_var(0, naive, name="makespan") # le makespan est le max des tps pour chaque job mdl.add(makespan == mdl.max([mdl.end_of(x[i][m - 1]) for i in range(n)])) mdl.add(mdl.minimize(makespan)) return mdl, x
def recherche_exact(instance, temps): ''' :param temps: int, temps de recherche :param instance: nom de l'instance str :return: None ''' problem_data, optimum = loader(instance) nb_machine = problem_data["nb_machine"] nb_jobs = problem_data["nb_jobs"] problem = problem_data["problem"] machine, durations = separate(problem) model = CpoModel(name='Scheduling') # Variable job_operations = [[model.interval_var(size=durations[j][m], name="O{}-{}".format(j, m)) for m in range(nb_machine)] for j in range(nb_jobs)] # chaque opération doit commencer aprés la fin de la précedente for j in range(nb_jobs): for s in range(1, nb_machine): model.add(model.end_before_start(job_operations[j][s - 1], job_operations[j][s])) # Pas d'overlap pour les operations executées sur une même machine machine_operations = [[] for m in range(nb_machine)] for j in range(nb_jobs): for s in range(0, nb_machine): machine_operations[machine[j][s]].append(job_operations[j][s]) for lops in machine_operations: model.add(model.no_overlap(lops)) # Minimiser la date de fin model.add(model.minimize(model.max([model.end_of(job_operations[i][nb_machine - 1]) for i in range(nb_jobs)]))) # Solve model print("Solving model....") msol = model.solve(TimeLimit=temps)
#----------------------------------------------------------------------------- # Build the model #----------------------------------------------------------------------------- # Create model mdl = CpoModel() # Create one interval variable per task tasks = {t['id']: mdl.interval_var(name="T{}".format(t['id'])) for t in TASKS} # Add precedence constraints for t in TASKS: for s in t['successors']: mdl.add(mdl.end_before_start(tasks[t['id']], tasks[s])) # Create one optional interval variable per task mode and add alternatives for tasks modes = {} # Map of all modes for t in TASKS: tmds = [mdl.interval_var(name=m['id'], optional=True, size=m['duration']) for m in t['modes']] mdl.add(mdl.alternative(tasks[t['id']], tmds)) for m in tmds: modes[m.name] = m # Initialize pulse functions for renewable and non renewable resources renewables = [mdl.pulse((0, 0), 0) for j in range(NB_RENEWABLE)] non_renewables = [0 for j in range(NB_NON_RENEWABLE)] for m in MODES: dren = m['demandRenewable'] dnren = m['demandNonRenewable']
#----------------------------------------------------------------------------- # Create model mdl = CpoModel() # Create one interval variable per job operation job_operations = [[ mdl.interval_var(size=JOB_DURATIONS[j][m], name="J{}-M{}".format(j, m)) for m in range(NB_MACHINES) ] for j in range(NB_JOBS)] # Force each operation to start after the end of the previous for j in range(NB_JOBS): for m in range(1, NB_MACHINES): mdl.add( mdl.end_before_start(job_operations[j][m - 1], job_operations[j][m])) # Force no overlap for operations executed on a same machine for m in range(NB_MACHINES): mdl.add(mdl.no_overlap([job_operations[j][m] for j in range(NB_JOBS)])) # Minimize termination date mdl.add( mdl.minimize( mdl.max([ mdl.end_of(job_operations[i][NB_MACHINES - 1]) for i in range(NB_JOBS) ]))) #----------------------------------------------------------------------------- # Solve the model and display the result
# Create model mdl = CpoModel() masonry = mdl.interval_var(name='masonry', size=35) carpentry = mdl.interval_var(name='carpentry', size=15) plumbing = mdl.interval_var(name='plumbing', size=40) ceiling = mdl.interval_var(name='ceiling', size=15) roofing = mdl.interval_var(name='roofing', size=5) painting = mdl.interval_var(name='painting', size=10) windows = mdl.interval_var(name='windows', size=5) facade = mdl.interval_var(name='facade', size=10) garden = mdl.interval_var(name='garden', size=5) moving = mdl.interval_var(name='moving', size=5) # Add precedence constraints mdl.add(mdl.end_before_start(masonry, carpentry)) mdl.add(mdl.end_before_start(masonry, plumbing)) mdl.add(mdl.end_before_start(masonry, ceiling)) mdl.add(mdl.end_before_start(carpentry, roofing)) mdl.add(mdl.end_before_start(ceiling, painting)) mdl.add(mdl.end_before_start(roofing, windows)) mdl.add(mdl.end_before_start(roofing, facade)) mdl.add(mdl.end_before_start(plumbing, facade)) mdl.add(mdl.end_before_start(roofing, garden)) mdl.add(mdl.end_before_start(plumbing, garden)) mdl.add(mdl.end_before_start(windows, moving)) mdl.add(mdl.end_before_start(facade, moving)) mdl.add(mdl.end_before_start(garden, moving)) mdl.add(mdl.end_before_start(painting, moving)) #-----------------------------------------------------------------------------
for i in range(len(ALL_TASKS)): ALL_TASKS[i].id = i #----------------------------------------------------------------------------- # Build the model #----------------------------------------------------------------------------- # Create model mdl = CpoModel() # Create interval variable for each building task tasks = [mdl.interval_var(size=t.duration, name=t.name) for t in ALL_TASKS] # Add precedence constraints for p, s in PRECEDENCES: mdl.add(mdl.end_before_start(tasks[p.id], tasks[s.id])) # Cost function cost = [] # List of individual costs fearliness = dict() # Task earliness cost function (for display) ftardiness = dict() # Task tardiness cost function (for display) for t in ALL_TASKS: task = tasks[t.id] if t.release_date is not None: f = CpoSegmentedFunction((-t.earliness_cost, 0), [(t.release_date, 0, 0)]) cost.append(mdl.start_eval(task, f)) fearliness[t] = f if t.due_date is not None: f = CpoSegmentedFunction((0, 0), [(t.due_date, 0, t.tardiness_cost)])
for task in SKILLS: wtasks[(house, task)] = mdl.interval_var( optional=True, name="house {} skill {}".format(house, task)) # Maximization objective of the model obj2 = mdl.sum([ s.level * mdl.presence_of(wtasks[(h, s)]) for s in SKILLS for h in HOUSES ]) mdl.add(mdl.maximize(obj2)) # Constraints of the model for h in HOUSES: # Temporal constraints for p in TASK_PRECEDENCES: mdl.add( mdl.end_before_start(tasks[(h, find_tasks(p.beforeTask))], tasks[(h, find_tasks(p.afterTask))])) # Alternative workers for t in TASKS: mdl.add( mdl.alternative( tasks[(h, t)], [wtasks[(h, s)] for s in SKILLS if (s.task == t.name)], 1)) # Continuity constraints for c in CONTINUITIES: mdl.add( mdl.presence_of(wtasks[(h, find_skills(c.worker, c.task1))]) == mdl.presence_of(wtasks[(h, find_skills(c.worker, c.task2))])) # No overlap constraint for w in WORKERS: mdl.add(
def tw_schedule(time_slot, tasks): start_time = time_slot[0] end_time = time_slot[1] mdl = CpoModel(name="generate_tw") # Create model for CP and solve for the first time to obtain initial time windows # Decision variables: time interval of each task task_vars = {} early = lambda x: "task_" + str(x) + "_early" late = lambda x: "task_" + str(x) + "_late" for id in tasks: if tasks[id].exact_time != None: # print("exact time: {}".format(tasks[id].exact_time)) task_vars[early(id)] = mdl.interval_var(start=tasks[id].exact_time, size=tasks[id].duration, name=early(id)) task_vars[late(id)] = mdl.interval_var(start=tasks[id].exact_time, size=tasks[id].duration, name=late(id)) else: task_vars[early(id)] = mdl.interval_var(size=tasks[id].duration, name=early(id)) task_vars[late(id)] = mdl.interval_var(size=tasks[id].duration, name=late(id)) slot = mdl.interval_var(start=start_time, end=end_time) # Time interval of entire time slot # Add Constraints: for id in tasks: # 1st constraint: all intervals are within start and end time mdl.add(mdl.start_before_start(slot, task_vars[early(id)])) mdl.add(mdl.end_before_end(task_vars[early(id)], slot)) mdl.add(mdl.start_before_start(slot, task_vars[late(id)])) mdl.add(mdl.end_before_end(task_vars[late(id)], slot)) # mdl.add(mdl.span(slot, task_vars.values())) if tasks[id].precedence_before != []: # Tasks that have precedence_before constraints # 2nd Constraints: end of precedence_before_task is before start of current task for id_before in tasks[id].precedence_before: mdl.add( mdl.end_before_start(task_vars[early(id_before)], task_vars[early(id)])) mdl.add( mdl.end_before_start(task_vars[late(id_before)], task_vars[late(id)])) # Add objective: obj = mdl.maximize( sum([ mdl.start_of(task_vars[late(id)]) - mdl.start_of(task_vars[early(id)]) for id in tasks ])) mdl.add(obj) # Solve model # sol = mdl.solve(TimeLimit = 10, LogVerbosity = "Verbose") sol = mdl.solve( TimeLimit=10, LogVerbosity="Quiet", agent='local', execfile= '/Applications/CPLEX_Studio201/cpoptimizer/bin/x86-64_osx/cpoptimizer') # sol = mdl.solve() if sol: # sol.write() time_window = { id: (sol.get_var_solution(task_vars[early(id)]).get_start(), sol.get_var_solution(task_vars[late(id)]).get_start()) for id in tasks } else: print("Instance not feasible - earliest start time") return {} return time_window
# about the machine costs. task_intervals_on_machines = {m['id']: [] for m in data['machines']} task_intervals = [] for machine in data['machines']: m_id = machine['id'] # Sequencing of intervals num_intervals = len(on_intervals[m_id]) for i in range(1, num_intervals): model.add( model.if_then(model.presence_of(on_intervals[m_id][i]), model.presence_of(on_intervals[m_id][i - 1]))) model.add( model.end_before_start(on_intervals[m_id][i - 1], on_intervals[m_id][i], 1)) # Bind with task intervals for on_i in on_intervals[m_id]: machine_on_off[m_id] += model.pulse(on_i, 1) model.add( model.always_constant(tasks_running_on_machines[m_id], on_i, True, True)) for task in data['tasks']: # Master task interval task_interval = model.interval_var( size=task['duration'], start=(task['earliest_start_time'], task['latest_end_time'] - task['duration']), end=(task['earliest_start_time'] + task['duration'],
tasks = {} mtasks = {} for j in range(NB_JOBS): for i,t in enumerate(Tasks[j]): # print((j,JOBS[j][2 * t],t),JOBS[j][2 * Tasks[j][-1] ]) tasks[(j,JOBS[j][2 * t],t)] = mdl.interval_var(size = Durations[j][i], name="J{}-M{}".format(j, JOBS[j][2 * t])) # print("SKILLS") for s in Skills[j]: # print((j,s),"J{}-{}".format(j, s)) mtasks[(j,s)] = mdl.interval_var(optional=True, name=str(j))#"J{}-{}".format(j, s) for j in range(NB_JOBS): # print(j) for p in Precedences: # print((j,JOBS[j][2 * p[0]]),(j,JOBS[j][2 * p[1]])) mdl.add( mdl.end_before_start(tasks[j,JOBS[j][2 * p[0]],p[0]], tasks[j,JOBS[j][2 * p[1]],p[1]]) ) #for j in range(NB_JOBS): # for t in Tasks[j]: # print( (j,JOBS[j][2 * t]), [(j,s) for s in Skills[j] if s[0][:len('M'+str(JOBS[j][2 * t])) ] == 'M'+str(JOBS[j][2 * t]) and s[0][len('M'+str(JOBS[j][2 * t])): len('M'+str(JOBS[j][2 * t]))+1] in 'e'] ) for j in range(NB_JOBS): for t in Tasks[j]: mdl.add( mdl.alternative( tasks[j,JOBS[j][2 * t],t], [mtasks[j,s] for s in Skills[j] if s[0][:len('M'+str(JOBS[j][2 * t]))] == 'M'+str(JOBS[j][2 * t]) and s[0][len('M'+str(JOBS[j][2 * t])): len('M'+str(JOBS[j][2 * t]))+1] in 'e' ] ) ) for m in Maschines:
] # ОГРАНИЧЕНИЯ # # Учтём приоритеты for i in range(NB_RESOURCES): successors_tasks = [] high_priority = [] for k, j in enumerate(TASKS): if j["rnd"] == i and j["rank"] == 1: successors_tasks.append(k) if j["rnd"] == i and j["rank"] == 0: high_priority.append(k) for s in high_priority: for m in successors_tasks: mdl.add(mdl.end_before_start(tasks[m], tasks[s])) # Учтём ресурсы (разработчиков) for r in range(NB_RESOURCES): resources = [ mdl.pulse(tasks[t], DEMANDS[t][r]) for t in range(NB_TASKS) if DEMANDS[t][r] > 0 ] mdl.add(mdl.sum(resources) <= CAPACITIES[r]) # одновременно только одна задача for i in range(NB_RESOURCES): lops = [] for k, j in enumerate(TASKS): if j["rnd"] == i: lops.append(tasks[k])
def CP_model_subsequence_restricted(params): ## NUM_COLORS, NUM_ITEMS, BIN_SIZE, DISCREPANCY, ITEM_SIZES, COLORS, NUM_BINS, Timelimit, SEED = params print("*** Running CP Subseq Restricted with instance NUM_COLORS{} NUM_ITEMS{} BIN_SIZE {} DISCREPANCY {} SEED {}".format( NUM_COLORS, NUM_ITEMS, BIN_SIZE, DISCREPANCY, SEED)) mdl = CpoModel() ITEMS = [mdl.interval_var(start=[0, sum(ITEM_SIZES)], size=ITEM_SIZES[item], optional=False, name="item_"+str(item)) for item in range(NUM_ITEMS)] ITEMS_TO_BINS = [[mdl.interval_var(start=(0, BIN_SIZE-min(ITEM_SIZES)), end=(min(ITEM_SIZES), BIN_SIZE), size=ITEM_SIZES[item], optional=True, name="item{}InBin{}".format(item, bin)) for bin in range(NUM_BINS)] for item in range(NUM_ITEMS)] ITEMS_S = mdl.sequence_var(ITEMS, types=COLORS, name="itemSequence") BIN_S = [mdl.sequence_var([ITEMS_TO_BINS[item][bin] for item in range(NUM_ITEMS)], types=[COLORS[item] for item in range(NUM_ITEMS)], name="bin{}Sequence".format(bin)) for bin in range(NUM_BINS)] # COLORS_S = [[mdl.sequence_var(ITEMS[item][bin] for item in range(NUM_ITEMS) if COLORS[item] == color)] for color in range(NUM_COLORS)] BINS_USED = [mdl.binary_var() for bin in range(NUM_BINS)] for item in range(NUM_ITEMS): # for bin in range(NUM_BINS): # mdl.add_kpi( # mdl.presence_of(ITEMS_TO_BINS[item][bin]), # "item_"+str(item)+" "+str(bin) # ) mdl.add( mdl.sum( [mdl.presence_of( ITEMS_TO_BINS[item][bin]) for bin in range(NUM_BINS)] ) == 1 ) # for item in range(NUM_ITEMS): # mdl.add( # mdl.alternative(ITEMS[item], [ITEMS_TO_BINS[item][bin] for bin in range(NUM_BINS)]) # ) for bin in range(NUM_BINS): mdl.add(mdl.no_overlap(BIN_S[bin])) for item in range(NUM_ITEMS-1): mdl.add( mdl.end_before_start(ITEMS[item], ITEMS[item+1]) ) mdl.add(mdl.no_overlap(ITEMS_S)) for bin in range(NUM_BINS): mdl.add( mdl.same_common_subsequence( ITEMS_S, BIN_S[bin], ) ) for item in range(NUM_ITEMS): for bin in range(NUM_BINS): # if (item, bin) in [(17,5), (20, 5), (29, 5)]: # mdl.add_kpi(mdl.type_of_next(BIN_S[bin], ITEMS_TO_BINS[item][bin], lastValue=-1, absentValue=-1), name="typeofnext{}_{}".format(item, bin)) # # mdl.add_kpi(mdl.type_of_prev(BIN_S[bin], ITEMS_TO_BINS[item][bin], firstValue=-1, absentValue=-1), name="typeofprev{}_{}".format(item, bin)) mdl.add( COLORS[item] != mdl.type_of_next(BIN_S[bin], ITEMS_TO_BINS[item][bin], lastValue=-1, absentValue=-1) ) mdl.add( COLORS[item] != mdl.type_of_prev(BIN_S[bin], ITEMS_TO_BINS[item][bin], firstValue=-1, absentValue=-1) ) for bin in range(NUM_BINS): mdl.add( BINS_USED[bin] == mdl.any([ mdl.presence_of(ITEMS_TO_BINS[item][bin]) for item in range(NUM_ITEMS) ]) ) for bin in range(NUM_BINS-1): mdl.add( BINS_USED[bin] >= BINS_USED[bin+1] ) mdl.add( mdl.minimize( mdl.sum( BINS_USED ) ) ) # mdl.add( # mdl.sum( # BINS_USED # ) < 48 # ) try: msol = mdl.solve(TimeLimit = Timelimit) mdl._myInstance = (NUM_COLORS, NUM_ITEMS, BIN_SIZE, DISCREPANCY, SEED) if msol: ITEMS_TO_BINS_S = [] for bin in range(NUM_BINS): b_ = [] for item in range(NUM_ITEMS): s = msol[ITEMS_TO_BINS[item][bin]] if s: b_.append(s) ITEMS_TO_BINS_S.append(b_) # return mdl seq = msol.get_var_solution(BIN_S[0]) print(ITEM_SIZES) print("CL: ",COLORS) Xs = [] for item in range(NUM_ITEMS): for bin in range(NUM_BINS): s = msol[ITEMS_TO_BINS[item][bin]] if s: # print(s) Xs.append(bin) print("Xs: ", Xs) Xs = np.array(Xs) if solution_checker(Xs, params, "restricted_cp_subsequence"): write_to_global_cp(msol, mdl, 'restricted_subsequence') except Exception as err: print(err) write_to_global_failed(params, 'restricted_cp_subsequence', is_bad_solution=False)
_name = "delivery{}".format(d + 1) itvs[(d, 2)] = mdl.interval_var(size=minutes_on_delivery[d], name=_name) #альтернатива между работниками for i in range(numdetails): for j in range(2): mdl.add( mdl.alternative(itvs[(i, j)], [itvs_3[(i, j)], itvs_2[(i, j)], itvs_1[(i, j)]])) #навесим последовательность TO DO для 1,2,3 #for h in range(numdetails): # mdl.add(mdl.end_before_start(itvs[(h, 1)], itvs[(h, 2)])) #for h in range(numdetails): # mdl.add(mdl.end_before_start(itvs[(h, 0)], itvs[(h, 1)])) #навесим последовательность жестко for h in range(numdetails): mdl.add(mdl.end_before_start(itvs[(h, 1)], itvs[(h, 2)])) for h in range(numdetails): mdl.add(mdl.end_before_start(itvs[(h, 0)], itvs[(h, 1)])) for h in range(numdetails): mdl.add(mdl.start_at_end(itvs[(h, 1)], itvs[(h, 0)])) #навесим принадлежность for h in range(numdetails): mdl.add(mdl.span(details[h], [itvs[(h, t)] for t in range(3)])) workers = {} workers1 = { "worker1": mdl.sequence_var( [itvs_1[(h, t)] for h in range(numdetails) for t in range(2)], types=[t for h in range(numdetails) for t in range(2)], name="worker1") }
#----------------------------------------------------------------------------- # Build the model #----------------------------------------------------------------------------- # Create model mdl = CpoModel() # Create task interval variables tasks = [mdl.interval_var(name="T{}".format(i + 1), size=DURATIONS[i]) for i in range(NB_TASKS)] # Add precedence constraints for t in range(NB_TASKS): for s in SUCCESSORS[t]: mdl.add(mdl.end_before_start(tasks[t], tasks[s - 1])) # Constrain capacity of resources for r in range(NB_RESOURCES): resources = [mdl.pulse(tasks[t], DEMANDS[t][r]) for t in range(NB_TASKS) if DEMANDS[t][r] > 0] mdl.add(mdl.sum(resources) <= CAPACITIES[r]) # Minimize end of all tasks mdl.add(mdl.minimize(mdl.max([mdl.end_of(t) for t in tasks]))) #----------------------------------------------------------------------------- # Solve the model and display the result #----------------------------------------------------------------------------- # Solve model
def create_model(self): mdl = CpoModel(name = "TAS Scheduling") ##################################################### # Creating interval variables for WEST module ##################################################### i = 0 MS1_vars = [] MS4_vars = [] GTW_vars = [] WEST_vars = [] table_occupied_WEST = [] kits_pulse_for_choice = [] for i in range(len(self.timeOUEST)): min_start_time = int(date_converter.convert_to_work_time(datetime.timestamp(pd.to_datetime(self.req_matOUEST.iloc[i,2])))) #print(min_start_time, self.req_matOUEST.iloc[i,2]) meca_length = int(self.timeOUEST.iloc[i, 2] / 10) qc_length = int(self.timeOUEST.iloc[i, 3] / 10) kit_interval = mdl.interval_var(start = (min_start_time, self.max_end_timestamp), name = "kitting " + self.timeOUEST.index[i]) kit_interval1mec = mdl.interval_var(start = (min_start_time, self.max_end_timestamp), length = self.kitting_time_max, name = "kitting 1 op " + self.timeOUEST.index[i], optional = True) kit_interval2mec = mdl.interval_var(start = (min_start_time, self.max_end_timestamp), length = self.kitting_time_mid, name = "kitting 2 op " + self.timeOUEST.index[i], optional = True) kit_interval3mec = mdl.interval_var(start = (min_start_time, self.max_end_timestamp), length = self.kitting_time_min, name = "kitting 3 op " + self.timeOUEST.index[i], optional = True) mdl.add(mdl.alternative(interval = kit_interval, array = [kit_interval1mec, kit_interval2mec, kit_interval3mec])) kits_pulse_for_choice += [kit_interval1mec, kit_interval2mec, kit_interval3mec] meca_interval = mdl.interval_var(start = (min_start_time, self.max_end_timestamp), length = meca_length, name = "meca " + self.timeOUEST.index[i]) qc_interval = mdl.interval_var(start = (min_start_time, self.max_end_timestamp), length = qc_length, name = "qc " + self.timeOUEST.index[i]) table_slot_occupied_interval = mdl.interval_var(start = (min_start_time, self.max_end_timestamp), length = (0, 9999999999999), name = "Table occupied " + self.timeOUEST.index[i]) table_occupied_WEST += [table_slot_occupied_interval] mdl.add(mdl.end_before_start(kit_interval, meca_interval)) mdl.add(mdl.end_before_start(meca_interval, qc_interval)) mdl.add(mdl.start_at_end(table_slot_occupied_interval, kit_interval)) mdl.add(mdl.start_at_end(meca_interval, table_slot_occupied_interval)) WEST_vars += [kit_interval] WEST_vars += [meca_interval] WEST_vars += [qc_interval] if i < 19: MS1_vars += [kit_interval] MS1_vars += [meca_interval] MS1_vars += [qc_interval] elif i >= 45: GTW_vars += [kit_interval] GTW_vars += [meca_interval] GTW_vars += [qc_interval] else: MS4_vars += [kit_interval] MS4_vars += [meca_interval] MS4_vars += [qc_interval] ###################################################### # Creating interval variables for EAST module ###################################################### FOV_vars = [] MS2_vars = [] MS3_vars = [] EAST_vars = [] table_occupied_EAST = [] for i in range(len(self.timeEST)): min_start_time = int(date_converter.convert_to_work_time(datetime.timestamp(pd.to_datetime(self.req_matOUEST.iloc[i,2])))) meca_length = int(self.timeOUEST.iloc[i, 2] / 10) qc_length = int(self.timeOUEST.iloc[i, 3] / 10) kit_interval = mdl.interval_var(start = (min_start_time, self.max_end_timestamp), name = "kitting " + self.timeEST.index[i]) kit_interval1mec = mdl.interval_var(start = (min_start_time, self.max_end_timestamp), length = self.kitting_time_max, name = "kitting 1 op " + self.timeEST.index[i], optional = True) kit_interval2mec = mdl.interval_var(start = (min_start_time, self.max_end_timestamp), length = self.kitting_time_mid, name = "kitting 2 op " + self.timeEST.index[i], optional = True) kit_interval3mec = mdl.interval_var(start = (min_start_time, self.max_end_timestamp), length = self.kitting_time_min, name = "kitting 3 op " + self.timeEST.index[i], optional = True) mdl.add(mdl.alternative(interval = kit_interval, array = [kit_interval1mec, kit_interval2mec, kit_interval3mec])) kits_pulse_for_choice += [kit_interval1mec, kit_interval2mec, kit_interval3mec] meca_interval = mdl.interval_var(start = (min_start_time, self.max_end_timestamp), length = meca_length, name = "meca " + self.timeEST.index[i]) qc_interval = mdl.interval_var(start = (min_start_time, self.max_end_timestamp), length = qc_length, name = "qc " + self.timeEST.index[i]) table_slot_occupied_interval = mdl.interval_var(start = (min_start_time, self.max_end_timestamp), length = (0, 9999999999999), name = "Table occupied " + self.timeEST.index[i]) table_occupied_EAST += [table_slot_occupied_interval] mdl.add(mdl.end_before_start(kit_interval, meca_interval)) mdl.add(mdl.end_before_start(meca_interval, qc_interval)) mdl.add(mdl.start_at_end(table_slot_occupied_interval, kit_interval)) mdl.add(mdl.start_at_end(meca_interval, table_slot_occupied_interval)) EAST_vars += [kit_interval] EAST_vars += [meca_interval] EAST_vars += [qc_interval] if i < 11: FOV_vars += [kit_interval] FOV_vars += [meca_interval] FOV_vars += [qc_interval] elif i >= 25: MS3_vars += [kit_interval] MS3_vars += [meca_interval] MS3_vars += [qc_interval] else: MS2_vars += [kit_interval] MS2_vars += [meca_interval] MS2_vars += [qc_interval] ################################################## # Setting requirement relations between interval variables ################################################## for task in MS1_vars: for i in range(len(self.req_taskOUEST)): if (self.req_taskOUEST.index[i] in task.name) and "meca" in task.name: for j in range(len(self.req_taskOUEST.iloc[i, 0])): for other_task in WEST_vars: if self.req_taskOUEST.iloc[i, 0][j] in other_task.name and "qc" in other_task.name: mdl.add(mdl.end_before_start(other_task, task)) #print("##############################################") for task in MS4_vars: for i in range(len(self.req_taskOUEST)): if (self.req_taskOUEST.index[i] in task.name) and "meca" in task.name: for j in range(len(self.req_taskOUEST.iloc[i, 0])): for other_task in WEST_vars: if self.req_taskOUEST.iloc[i, 0][j] in other_task.name and "qc" in other_task.name: mdl.add(mdl.end_before_start(other_task, task)) #print("##############################################") for task in GTW_vars: for i in range(len(self.req_taskOUEST)): if (self.req_taskOUEST.index[i] in task.name) and "meca" in task.name: for j in range(len(self.req_taskOUEST.iloc[i, 0])): for other_task in WEST_vars: if self.req_taskOUEST.iloc[i, 0][j] in other_task.name and "qc" in other_task.name: mdl.add(mdl.end_before_start(other_task, task)) #print("##############################################") for task in MS2_vars: for i in range(len(self.req_taskEST)): if (self.req_taskEST.index[i] in task.name) and "meca" in task.name: for j in range(len(self.req_taskEST.iloc[i, 0])): for other_task in EAST_vars: if self.req_taskEST.iloc[i, 0][j] in other_task.name and "qc" in other_task.name: mdl.add(mdl.end_before_start(other_task, task)) #print("##############################################") for task in MS3_vars: for i in range(len(self.req_taskEST)): if (self.req_taskEST.index[i] in task.name) and "meca" in task.name: for j in range(len(self.req_taskEST.iloc[i, 0])): for other_task in EAST_vars: if self.req_taskEST.iloc[i, 0][j] in other_task.name and "qc" in other_task.name: mdl.add(mdl.end_before_start(other_task, task)) #print("##############################################") for task in FOV_vars: for i in range(len(self.req_taskEST)): if (self.req_taskEST.index[i] in task.name) and "meca" in task.name: for j in range(len(self.req_taskEST.iloc[i, 0])): for other_task in EAST_vars: if self.req_taskEST.iloc[i, 0][j] in other_task.name and "qc" in other_task.name: mdl.add(mdl.end_before_start(other_task, task)) ############################################## # Adding resources constraints ############################################## all_tasks = EAST_vars + WEST_vars meca_resources = [mdl.pulse(task, 1) for task in EAST_vars if "meca" in task.name] meca_resources += [mdl.pulse(task, 1) for task in WEST_vars if "meca" in task.name] meca_resources += [mdl.pulse(task, 1) for task in kits_pulse_for_choice if "kitting 1 op" in task.name] meca_resources += [mdl.pulse(task, 2) for task in kits_pulse_for_choice if "kitting 2 op" in task.name] meca_resources += [mdl.pulse(task, 3) for task in kits_pulse_for_choice if "kitting 3 op" in task.name] qc_resources = [mdl.pulse(task, 1) for task in EAST_vars if "qc" in task.name] qc_resources += [mdl.pulse(task, 1) for task in WEST_vars if "qc" in task.name] work_slots_EAST = [mdl.pulse(task, 1) for task in EAST_vars if "qc" in task.name or "meca" in task.name] work_slots_WEST = [mdl.pulse(task, 1) for task in WEST_vars if "qc" in task.name or "meca" in task.name] kitting_slots_EAST = [mdl.pulse(task, 1) for task in table_occupied_EAST] kitting_slots_EAST += [mdl.pulse(task, 1) for task in EAST_vars if "kitting" in task.name] kitting_slots_WEST = [mdl.pulse(task, 1) for task in table_occupied_WEST] kitting_slots_WEST += [mdl.pulse(task, 1) for task in WEST_vars if "kitting" in task.name] mdl.add(mdl.sum(meca_resources) <= 3) mdl.add(mdl.sum(qc_resources) <= 1) mdl.add(mdl.sum(work_slots_EAST) <= 2) mdl.add(mdl.sum(work_slots_WEST) <= 2) mdl.add(mdl.sum(kitting_slots_EAST) <= 3) mdl.add(mdl.sum(kitting_slots_WEST) <= 3) [mdl.add(mdl.start_of(task) % (14*6) < 11*6) for task in all_tasks if "meca" in task.name] MS1_meca_qc = [task for task in MS1_vars if (("meca" in task.name) or ("qc" in task.name))] mdl.add(mdl.no_overlap(MS1_meca_qc)) MS2_meca_qc = [task for task in MS2_vars if (("meca" in task.name) or ("qc" in task.name))] mdl.add(mdl.no_overlap(MS2_meca_qc)) MS3_meca_qc = [task for task in MS3_vars if (("meca" in task.name) or ("qc" in task.name))] mdl.add(mdl.no_overlap(MS3_meca_qc)) MS4_meca_qc = [task for task in MS4_vars if (("meca" in task.name) or ("qc" in task.name))] mdl.add(mdl.no_overlap(MS4_meca_qc)) FOV_meca_qc = [task for task in FOV_vars if (("meca" in task.name) or ("qc" in task.name))] mdl.add(mdl.no_overlap(FOV_meca_qc)) GTW_meca_qc = [task for task in GTW_vars if (("meca" in task.name) or ("qc" in task.name))] mdl.add(mdl.no_overlap(GTW_meca_qc)) mdl.add(mdl.minimize(mdl.max([mdl.end_of(t) for t in all_tasks]) - mdl.min([mdl.start_of(t) for t in all_tasks]))) return mdl
modes_data.append(mode) #----------------------------------------------------------------------------- # Build the model #----------------------------------------------------------------------------- # Create model mdl = CpoModel() # Create one interval variable per task tasks = {t: mdl.interval_var(name=t.name) for t in tasks_data} # Add precedence constraints for t in tasks_data: for s in t.successors: mdl.add(mdl.end_before_start(tasks[t], tasks[tasks_data[s]])) # Create one optional interval variable per mode modes = { m: mdl.interval_var(name=m.name, optional=True, size=m.duration) for m in modes_data } # Add mode alternative for each task for t in tasks_data: mdl.add(mdl.alternative(tasks[t], [modes[m] for m in t.modes])) # Initialize pulse functions for renewable and non renewable resources renewables = [mdl.pulse((0, 0), 0) for j in range(NB_RENEWABLE)] non_renewables = [0 for j in range(NB_NON_RENEWABLE)] for m in modes_data: