#----------------------------------------------------------------------------- # Solve the model and display the result #----------------------------------------------------------------------------- # Solve model print("Solving model....") msol = mdl.solve(FailLimit=30000, TimeLimit=10) print("Solution: ") msol.print_solution() if msol and visu.is_visu_enabled(): load = [CpoStepFunction() for j in range(NB_RENEWABLE)] for m in MODES: itv = msol.get_var_solution(modes[m['id']]) if itv.is_present(): for j in range(NB_RENEWABLE): dem = m['demandRenewable'][j] if dem > 0: load[j].add_value(itv.get_start(), itv.get_end(), dem) visu.timeline("Solution for RCPSPMM " + filename) visu.panel("Tasks") for t in TASKS: tid = t['id'] visu.interval(msol.get_var_solution(tasks[tid]), tid, str(tid)) for j in range(NB_RENEWABLE): visu.panel("R " + str(j + 1)) visu.function(segments=[(INTERVAL_MIN, INTERVAL_MAX, CAPACITIES_RENEWABLE[j])], style='area', color='lightgrey') visu.function(segments=load[j], style='area', color=j) visu.show()
# 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)) #----------------------------------------------------------------------------- # Solve the model and display the result #----------------------------------------------------------------------------- # Solve model print("Solving model....") msol = mdl.solve(TimeLimit=10) print("Solution: ") msol.print_solution() # Draw solution if msol and visu.is_visu_enabled(): visu.show(msol)
mdl.add(end_before_start(ceiling, painting)) mdl.add(end_before_start(roofing, windows)) mdl.add(end_before_start(roofing, facade)) mdl.add(end_before_start(plumbing, facade)) mdl.add(end_before_start(roofing, garden)) mdl.add(end_before_start(plumbing, garden)) mdl.add(end_before_start(windows, moving)) mdl.add(end_before_start(facade, moving)) mdl.add(end_before_start(garden, moving)) mdl.add(end_before_start(painting, moving)) ############################################################################## # Solving ############################################################################## # Solve model print("Solving model....") msol = mdl.solve(TimeLimit=10) print("Solution: ") msol.print_solution() ############################################################################## # Display result ############################################################################## # Draw solution if msol and visu.is_visu_enabled(): visu.show(msol)
# Solve model print("Solving model....") msol = mdl.solve(FailLimit=30000, TimeLimit=10) print("Solution: ") msol.print_solution() ############################################################################## # Display result ############################################################################## if msol and visu.is_visu_enabled(): load = [CpoStepFunction() for j in range(nb_renewable)] for m in modes_data: itv = msol.get_var_solution(modes[m]) if itv.is_present(): for j in range(nb_renewable): if 0 < m.demand_renewable[j]: load[j].add_value(itv.get_start(), itv.get_end(), m.demand_renewable[j]) visu.timeline("Solution for RCPSPMM " + filename) visu.panel("Tasks") for t in tasks_data: visu.interval(msol.get_var_solution(tasks[t]), int(t.name[1:]), t.name) for j in range(nb_renewable): visu.panel("R " + str(j + 1)) visu.function(segments=[(INTERVAL_MIN, INTERVAL_MAX, cap_renewables[j])], style='area', color='lightgrey') visu.function(segments=load[j], style='area', color=j) visu.show()
for key, value in acts.items(): if str(acts[key].project_block) == str(pj_bl_list[i]): print(sol.get_var_solution(act_var[key])) if last_end < sol.get_var_solution(act_var[key]).get_end(): last_end = sol.get_var_solution(act_var[key]).get_end() # 탐색 결과 가시화 # 블록 별 스케줄링 결과 rcParams['figure.figsize'] = 15, 60 for i in range(len(pj_bl_list)): visu.panel(name=pj_bl_list[i]) for key, value in acts.items(): if str(acts[key].project_block) == str(pj_bl_list[i]): temp1 = sol.get_var_solution(act_var[key]) visu.interval(temp1,'lightblue',value.id[4:]) visu.show(pngfile="scheduling") # 전체 인력 사용 수준 그래프 print("workforce level for" + str(team)) rcParams['figure.figsize'] = 15, 3 workforce=CpoStepFunction() workforce_standard=CpoStepFunction() workforce_whole=CpoStepFunction() for key, value in acts.items(): wf=sol.get_var_solution(act_var[key]) workforce.add_value(wf.get_start(),wf.get_end(), acts[key].worker) workforce_whole.add_value(0, last_end, sum(worker)) workforce_standard.add_value(0,last_end ,standard) # 공종 별 인력 사용 수준 그래프
def CP(env_time, P_elems, resource_matrix, domain_applications, generated_jobs): '''! Creates a schedule using the Constraint Programming model @param env_time: Current time of the simulation environment @param P_elems: Instances of processing elements in the SoC configuration generated in the simulation environment @param resource_matrix: All processing elements in the SoC configuration @param domain_applications: Applications under consideration for workload generation @param generated_jobs: Instances of applications (jobs) currently being executed in the system ''' ###### Step 1 - Initialize variable and parameters plt.close('all') # Set docplex related parameters context.solver.trace_log = False #params.CpoParameters.OptimalityTolerance = 2 #params.CpoParameters.RelativeOptimalityTolerance= 2 Dags = [] Dags_2 = {} # Get the task in Outstanding and Ready Queues # Since tasks in Completed Queue are already done, they will not be considered for task in common.TaskQueues.outstanding.list: if task.jobID not in Dags: Dags.append(task.jobID) for i in range(len(domain_applications.list)): name = domain_applications.list[i].name if name == task.jobname: Dags_2[task.jobID] = {} Dags_2[task.jobID]['selection'] = i for task in common.TaskQueues.ready.list: if task.jobID not in Dags: Dags.append(task.jobID) for i in range(len(domain_applications.list)): name = domain_applications.list[i].name if name == task.jobname: Dags_2[task.jobID] = {} Dags_2[task.jobID]['selection'] = i #Dags.sort() common.ilp_job_list = [(key, Dags_2[key]['selection']) for key in Dags_2.keys()] #print(Dags_2) NbDags = len(Dags) # Current number of jobs in the system PEs = [] # List of PE element in the given SoC configuration print('[I] Time %d: There is %d job(s) in the system' % (env_time, NbDags)) print('[D] Time %d: ID of the jobs in the system are' % (env_time), Dags) ###### Step 2 - Prepare Data # First, check if there are any tasks currently being executed on a PE # if yes, retrieve remaining time of execution on that PE and # do not assign a task during ILP solution for i, PE in enumerate(P_elems): if (PE.type == 'MEM') or (PE.type == 'CAC'): # Do not consider Memory ond Cache continue PEs.append(PE.name) # Populate the name of the PEs in the SoC #print(PEs) for ID in Dags_2.keys(): Dags_2[ID]['Tasks'] = [ ] # list of tasks that CPLEX will return a schedule for Dags_2[ID]['Functionality'] = [] # list of task-PE relationship Dags_2[ID]['Con_Precedence'] = [] # list of task dependencies app_id = Dags_2[ID]['selection'] #print(len(Dags), len(self.generated_job_list)) num_of_tasks = len(domain_applications.list[app_id].task_list) for task in domain_applications.list[app_id].task_list: Dags_2[ID]['Tasks'].append(task.base_ID) # Next, gather the information about which PE can run which Tasks # and if so, the expected execution time for resource in resource_matrix.list: if (resource.type == 'MEM') or ( resource.type == 'CAC'): # Do not consider Memory ond Cache continue else: if task.name in resource.supported_functionalities: ind = resource.supported_functionalities.index( task.name) #Functionality.append((resource.name, task.base_ID, resource.performance[ind])) Dags_2[ID]['Functionality'].append( (resource.name, task.base_ID, resource.performance[ind])) # Finally, gather dependency information between tasks for i, predecessor in enumerate(task.predecessors): #print(task.ID, predecessor, num_of_tasks, last_ID, task.base_ID) for resource in resource_matrix.list: if (resource.type == 'MEM') or (resource.type == 'CAC'): continue else: #pred_name = self.generated_job_list[job_ind].task_list[predecessor-last_ID].name pred_name = domain_applications.list[app_id].task_list[ predecessor - (task.ID - task.base_ID)].name if (pred_name in resource.supported_functionalities): c_vol = domain_applications.list[app_id].comm_vol[ predecessor - (task.ID - task.base_ID), task.base_ID] Dags_2[ID]['Con_Precedence'].append( (resource.name, Dags_2[ID]['Tasks'][predecessor - (task.ID - task.base_ID)], task.base_ID, c_vol)) #print(Dags_2[ID]['Tasks']) #print(len(Dags_2[ID]['Functionality'])) #print(Dags_2[ID]['Con_Precedence']) ###### Step 3 - Create the model mdl = CpoModel() # Create dag interval variables dags = {d: mdl.interval_var(name="dag" + str(d)) for d in Dags_2.keys()} #print(dags) # Create tasks interval variables and pe_tasks interval variables # pe_tasks are optional and only one of them will be mapped to the corresponding # tasks interval variable # For example, task_1 has 3 pe_tasks (i.e.,P1-task_1, P2-task_1, P3, task_1) # only of these will be selected. If the first one is selected, it means that task_1 will be executed in P1 tasks_2 = {} pe_tasks_2 = {} task_names_ids_2 = {} last_ID = 0 for d in Dags_2.keys(): num_of_tasks = len(generated_jobs[d].task_list) for t in Dags_2[d]['Tasks']: tasks_2[(d, t)] = mdl.interval_var(name=str(d) + "_" + str(t)) for f in Dags_2[d]['Functionality']: #print(f) name = str(d) + "_" + str(f[1]) + '-' + str(f[0]) if len(common.TaskQueues.running.list) == 0 and len( common.TaskQueues.completed.list) == 0: pe_tasks_2[(d, f)] = mdl.interval_var(optional=True, size=int(f[2]), name=name) task_names_ids_2[name] = last_ID + f[1] else: for ii, running_task in enumerate( common.TaskQueues.running.list): if (d == running_task.jobID) and ( f[1] == running_task.base_ID) and ( f[0] == P_elems[running_task.PE_ID].name): ind = resource_matrix.list[ running_task. PE_ID].supported_functionalities.index( running_task.name) exec_time = resource_matrix.list[ running_task.PE_ID].performance[ind] free_time = int(running_task.start_time + exec_time - env_time) #print(free_time) pe_tasks_2[(d, f)] = mdl.interval_var(optional=True, start=0, end=free_time, name=name) task_names_ids_2[name] = last_ID + f[1] break elif (d == running_task.jobID) and (f[1] == running_task.base_ID): pe_tasks_2[(d, f)] = mdl.interval_var(optional=True, size=INTERVAL_MAX, name=name) task_names_ids_2[name] = last_ID + f[1] break else: pe_tasks_2[(d, f)] = mdl.interval_var(optional=True, size=int(f[2]), name=name) task_names_ids_2[name] = last_ID + f[1] for iii, completed_task in enumerate( common.TaskQueues.completed.list): if (d == completed_task.jobID) and ( f[1] == completed_task.base_ID) and ( f[0] == P_elems[completed_task.PE_ID].name): #print(completed_task.name) #pe_tasks[(d,f)] = mdl.interval_var(optional=True, size =0, name = name ) pe_tasks_2[(d, f)] = mdl.interval_var(optional=True, start=0, end=0, name=name) task_names_ids_2[name] = last_ID + f[1] elif (d == completed_task.jobID) and ( f[1] == completed_task.base_ID): pe_tasks_2[(d, f)] = mdl.interval_var(optional=True, size=INTERVAL_MAX, name=name) task_names_ids_2[name] = last_ID + f[1] #print('3',pe_tasks[(d,f)]) last_ID += num_of_tasks #print(tasks_2) #print(task_names_ids_2) # Add the temporal constraints for d in Dags_2.keys(): for c in Dags_2[d]['Con_Precedence']: for (p1, task1, d1) in Dags_2[d]['Functionality']: if p1 == c[0] and task1 == c[1]: p1_id = PEs.index(p1) for (p2, task2, d2) in Dags_2[d]['Functionality']: if p2 == c[0] and task2 == c[2]: mdl.add( mdl.end_before_start( pe_tasks_2[d, (p1, task1, d1)], pe_tasks_2[d, (p2, task2, d2)], 0)) elif p2 != c[0] and task2 == c[2]: p2_id = PEs.index(p2) #print(p2_id) bandwidth = common.ResourceManager.comm_band[p1_id, p2_id] comm_time = int((c[3]) / bandwidth) for ii, completed_task in enumerate( common.TaskQueues.completed.list): if ((d == completed_task.jobID) and (task1 == completed_task.base_ID) and (p1 == P_elems[completed_task.PE_ID].name)): mdl.add( mdl.end_before_start( pe_tasks_2[d, (p1, task1, d1)], pe_tasks_2[d, (p2, task2, d2)], max( 0, comm_time + completed_task.finish_time - env_time))) #print (d, p1,p2, task1,task2, max(0,int(c[3])+completed_task.finish_time-self.env.now) ) break else: #print(d, p1,p2, task1,task2, c[3]) mdl.add( mdl.end_before_start( pe_tasks_2[d, (p1, task1, d1)], pe_tasks_2[d, (p2, task2, d2)], comm_time)) # Add the span constraints # This constraint enables to identify tasks in a dag for d in Dags_2.keys(): mdl.add( mdl.span(dags[d], [tasks_2[(d, t)] for t in Dags_2[d]['Tasks']])) # Add the alternative constraints # This constraint ensures that only one PE is chosen to execute a particular task for d in Dags_2.keys(): for t in Dags_2[d]['Tasks']: mdl.add( mdl.alternative(tasks_2[d, t], [ pe_tasks_2[d, f] for f in Dags_2[d]['Functionality'] if f[1] == t ])) # Add the no overlap constraints # This constraint ensures that there will be no overlap for the task being executed on the same PE for p in PEs: b_list = [ pe_tasks_2[d, f] for d in Dags_2.keys() for f in Dags_2[d]['Functionality'] if f[0] == p ] if b_list: mdl.add( mdl.no_overlap([ pe_tasks_2[d, f] for d in Dags_2.keys() for f in Dags_2[d]['Functionality'] if f[0] == p ])) else: continue # Add the objective mdl.add( mdl.minimize(mdl.sum([mdl.end_of(dags[d]) for i, d in enumerate(Dags)]))) #mdl.add(mdl.minimize(mdl.max([mdl.end_of(pe_tasks_2[(d,f)]) for i,d in enumerate(Dags) for f in Dags_2[d]['Functionality'] ]))) #mdl.add(mdl.minimize(mdl.max(mdl.end_of(dags[d]) for i,d in enumerate(Dags)))) ###### Step 4 - Solve the model and print some results # Solve the model print("\nSolving CP model....") msol = mdl.solve(TimeLimit=60) #msol = mdl.solve() #print("Completed") #print(msol.print_solution()) #print(msol.is_solution_optimal()) print(msol.get_objective_gaps()) print(msol.get_objective_values()[0]) tem_list = [] for d in Dags: #for f in Functionality: for f in Dags_2[d]['Functionality']: #solution = msol.get_var_solution(pe_tasks[(d,f)]) solution = msol.get_var_solution(pe_tasks_2[(d, f)]) if solution.is_present(): #ID = task_names_ids[solution.get_name()] ID = task_names_ids_2[solution.get_name()] tem_list.append( (ID, f[0], solution.get_start(), solution.get_end())) tem_list.sort(key=lambda x: x[2], reverse=False) #print(tem_list) actual_schedule = [] for i, p in enumerate(PEs): count = 0 for item in tem_list: if item[1] == p: actual_schedule.append((item[0], i, count + 1)) count += 1 actual_schedule.sort(key=lambda x: x[0], reverse=False) #print(actual_schedule) common.table = [] for element in actual_schedule: common.table.append((element[1], element[2])) #print(common.table) #print(len(common.table)) if (common.simulation_mode == 'validation'): colors = ['salmon', 'turquoise', 'lime', 'coral', 'lightpink'] PEs.reverse() for i, p in enumerate(PEs): #visu.panel() #visu.pause(PE_busy_times[p]) visu.sequence(name=p) for ii, d in enumerate(Dags): #for f in Functionality: for f in Dags_2[d]['Functionality']: #wt = msol.get_var_solution(pe_tasks[(d,f)]) wt = msol.get_var_solution(pe_tasks_2[(d, f)]) if wt.is_present() and p == f[0]: color = colors[ii % len(colors)] #visu.interval(wt, color, str(task_names_ids[wt.get_name()])) visu.interval(wt, color, str(task_names_ids_2[wt.get_name()])) visu.show() for d in Dags: for task in generated_jobs[d].task_list: task_sched_ID = 0 task.dynamic_dependencies.clear( ) # Clear dependencies from previosu ILP run ind = Dags.index(d) for i in range(ind): selection = Dags_2[Dags[i]]['selection'] task_sched_ID += len( domain_applications.list[selection].task_list) task_sched_ID += task.base_ID task_order = common.table[task_sched_ID][1] for k in Dags: for dyn_depend in generated_jobs[k].task_list: dyn_depend_sched_ID = 0 ind_k = Dags.index(k) for ii in range(ind_k): selection = Dags_2[Dags[ii]]['selection'] dyn_depend_sched_ID += len( domain_applications.list[selection].task_list) dyn_depend_sched_ID += dyn_depend.base_ID if ((common.table[dyn_depend_sched_ID][0] == common.table[task_sched_ID][0]) and (common.table[dyn_depend_sched_ID][1] == task_order - 1) and (dyn_depend.ID not in task.predecessors) and (dyn_depend.ID not in task.dynamic_dependencies)): task.dynamic_dependencies.append(dyn_depend.ID)