def __init__(self, fp_listCplexParameters, fp_obInstance): ''' @fp_listCplexParameters: [0:iCandidateFaciNum, 1:fAlpha] ''' self.iCandidateFaciNum = fp_listCplexParameters[0] self.fAlpha = fp_listCplexParameters[1] self.obInstance = fp_obInstance self.model = Model() self.cpomodel = CpoModel()
def minimum_resources(task: ElasticTask, allocation_priority: NonElasticResourcePriority) -> Tuple[int, int, int]: """ Find the optimal non_elastic speeds of the task :param task: The task to use :param allocation_priority: The non-elastic value function to value the speeds :return: non_elastic speeds """ model = CpoModel('non_elasticSpeedsPrioritisation') loading_speed = model.integer_var(min=1, name='loading speed') compute_speed = model.integer_var(min=1, name='compute speed') sending_speed = model.integer_var(min=1, name='sending speed') model.add(task.required_storage / loading_speed + task.required_computation / compute_speed + task.required_results_data / sending_speed <= task.deadline) model.minimize(allocation_priority.evaluate(loading_speed, compute_speed, sending_speed)) model_solution = model.solve(log_output=None) assert model_solution.get_solve_status() == SOLVE_STATUS_FEASIBLE or \ model_solution.get_solve_status() == SOLVE_STATUS_OPTIMAL, \ (model_solution.get_solve_status(), task.__str__()) assert 0 < model_solution.get_value(loading_speed) and \ 0 < model_solution.get_value(compute_speed) and \ 0 < model_solution.get_value(sending_speed), \ (model_solution.get(loading_speed), model_solution.get(compute_speed), model_solution.get(sending_speed)) return model_solution.get_value(loading_speed), \ model_solution.get_value(compute_speed), \ model_solution.get_value(sending_speed)
def get_version_info(): """ If the solver agent defined in the configuration enables this function, this method returns solver version information. This method creates a CP solver to retrieve this information, and end it immediately. It returns a dictionary with various information, as in the following example: :: { "AngelVersion" : 5, # Or 'DllVersion' for Dll "SourceDate" : "Sep 12 2017", "SolverVersion" : "12.8.0.0", "IntMin" : -9007199254740991, "IntMax" : 9007199254740991, "IntervalMin" : -4503599627370494, "IntervalMax" : 4503599627370494, } Returns: Solver information dictionary, or None if not available. """ from docplex.cp.model import CpoModel try: with CpoSolver(CpoModel()) as slvr: return slvr.agent.version_info except: pass return None
def __init__(self, mdl=None): """ Create a new CPO format parser Args: mdl: Model to fill, None (default) to create a new one. """ super(CpoParser, self).__init__() self.model = mdl if mdl is not None else CpoModel() self.expr_dict = {} self.source_file = None self.tokenizer = None self.token = None self.pushtoken = None self.current_loc = None # Do not store location information (would store parser instead of real lines) self.model.source_loc = False # Initialize special function handlers self.fun_handlers = { 'intVar': self._read_fun_intVar, '_intVar': self._read_fun_intVar, 'boolVar': self._read_fun_boolVar, '_boolVar': self._read_fun_boolVar, 'floatVar': self._read_fun_floatVar, '_floatVar': self._read_fun_floatVar, 'intervalVar': self._read_fun_intervalVar, 'sequenceVar': self._read_fun_sequenceVar, 'stateFunction': self._read_fun_stateFunction, 'stepFunction': self._read_fun_stepFunction, 'segmentedFunction': self._read_fun_segmentedFunction, 'transitionMatrix': self._read_fun_transitionMatrix, }
def get_solver_info(): """ Get the information data of the local CP solver that is target by the solver configuration. This method creates a CP solver to retrieve this information, and end it immediately. It returns a dictionary with various information, as in the following example: :: { "AngelVersion" : 5, "SourceDate" : "Sep 12 2017", "SolverVersion" : "12.8.0.0", "IntMin" : -9007199254740991, "IntMax" : 9007199254740991, "IntervalMin" : -4503599627370494, "IntervalMax" : 4503599627370494, "AvailableCommands" : ["Exit", "SetCpoModel", "SolveModel", "StartSearch", "SearchNext", "EndSearch", "RefineConflict", "Propagate", "RunSeeds"] } Returns: Solver information dictionary, or None if not available. """ try: with solver.CpoSolver(CpoModel()) as slvr: if isinstance(slvr.agent, CpoSolverLocal): return slvr.agent.version_info except: pass return None
def convert_fixed_task(tasks: List[Task]): """ Converts tasks to fixed tasks Args: tasks: List of tasks Returns: List of fixed tasks """ fixed_tasks = [] for task in tasks: model = CpoModel('FixedTask') loading_speed = model.integer_var(min=1, name='loading speed') compute_speed = model.integer_var(min=1, name='compute speed') sending_speed = model.integer_var(min=1, name='sending speed') model.add((task.required_storage / loading_speed) + (task.required_computation / compute_speed) + (task.required_results_data / sending_speed) <= ( task.deadline - task.auction_time)) model.minimize(1.2**loading_speed + 1.2**compute_speed + 1.2**sending_speed) model_solution = model.solve(log_output=None, TimeLimit=3) if model_solution.get_solve_status( ) != SOLVE_STATUS_FEASIBLE or model_solution.get_solve_status( ) != SOLVE_STATUS_OPTIMAL: fixed_tasks.append( FixedTask(name=task.name, auction_time=task.auction_time, deadline=task.deadline, required_storage=task.required_storage, required_computation=task.required_computation, required_results_data=task.required_results_data, fixed_loading_speed=model_solution.get_value( loading_speed), fixed_compute_speed=model_solution.get_value( compute_speed), fixed_sending_speed=model_solution.get_value( sending_speed))) else: print(f'Error: {model_solution.get_solve_status()}') return fixed_tasks
def test_cplex(): model = CpoModel('test') x = model.integer_var(name='x') model.minimize(5 * x**2 - 10 * x + 1) solution = model.solve() assert solution.get_solve_status() == SOLVE_STATUS_OPTIMAL
def __init__(self, mdl=None): """ Create a new CPO format parser Args: mdl: Model to fill, None (default) to create a new one. """ super(CpoParser, self).__init__() self.model = mdl if mdl is not None else CpoModel() self.source_file = None self.tokenizer = None self.token = None self.pushtoken = None # Do not store location information (would store parser instead of real lines) self.model.source_loc = False
# Build the model #----------------------------------------------------------------------------- def get_neighbors(l, c): """ Build the list of neighbors of a given cell """ res = [] if c > 0: res.append((l, c - 1)) if c < SIZE - 1: res.append((l, c + 1)) if l > 0: res.append((l - 1, c)) if l < SIZE - 1: res.append((l + 1, c)) return res # Create model mdl = CpoModel() # Create one binary variable for each colored cell color = [[ mdl.integer_var(min=0, max=1, name="C" + str(l) + "_" + str(c)) for c in range(SIZE) ] for l in range(SIZE)] # Forbid adjacent colored cells for l in range(SIZE): for c in range(SIZE - 1): mdl.add((color[l][c] + color[l][c + 1]) < 2) for c in range(SIZE): for l in range(SIZE - 1): mdl.add((color[l][c] + color[l + 1][c]) < 2)
The masonry, roofing, painting, etc. must be scheduled. Some tasks must necessarily take place before others, and these requirements are expressed through precedence constraints. Please refer to documentation for appropriate setup of solving configuration. """ from docplex.cp.model import CpoModel import docplex.cp.utils_visu as visu #----------------------------------------------------------------------------- # Build the model #----------------------------------------------------------------------------- # 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))
# Number of marks on the ruler ORDER = 8 #----------------------------------------------------------------------------- # Prepare the data for modeling #----------------------------------------------------------------------------- # Estimate an upper bound to the ruler length MAX_LENGTH = (ORDER - 1)**2 #----------------------------------------------------------------------------- # Build the model #----------------------------------------------------------------------------- # Create model mdl = CpoModel() # Create array of variables corresponding to position rule marks marks = mdl.integer_var_list(ORDER, 0, MAX_LENGTH, "M") # Create marks distances that should be all different dist = [marks[i] - marks[j] for i in range(1, ORDER) for j in range(0, i)] mdl.add(mdl.all_diff(dist)) # Avoid symmetric solutions by ordering marks mdl.add(marks[0] == 0) for i in range(1, ORDER): mdl.add(marks[i] > marks[i - 1]) # Avoid mirror solution mdl.add((marks[1] - marks[0]) < (marks[ORDER - 1] - marks[ORDER - 2]))
]) # Initialize demand of each customer demand = list([data.popleft() for c in range(nbCustomer)]) # Initialize fixed cost of each location fixedCost = list([data.popleft() for p in range(nbLocation)]) # Initialize capacity of each location capacity = list([data.popleft() for p in range(nbLocation)]) #----------------------------------------------------------------------------- # Build the model #----------------------------------------------------------------------------- mdl = CpoModel() # Create variables identifying which location serves each customer cust = mdl.integer_var_list(nbCustomer, 0, nbLocation - 1, "CustomerLocation") # Create variables indicating which plant location is open open = mdl.integer_var_list(nbLocation, 0, 1, "OpenLocation") # Create variables indicating load of each plant load = [ mdl.integer_var(0, capacity[p], "PlantLoad_" + str(p)) for p in range(nbLocation) ] # Associate plant openness to its load for p in range(nbLocation):
def fixed_resource_allocation_model(env: OnlineFlexibleResourceAllocationEnv, state: EnvState): """ Generate the fixed resource allocation model and then solve it Args: env: Online Flexible Resource Allocation Env state: Environment state Returns: Cplex model """ tasks = env._unallocated_tasks if state.auction_task: tasks.append(state.auction_task) fixed_tasks = convert_fixed_task(tasks) servers = list(state.server_tasks.keys()) model = CpoModel('FixedEnv') server_task_allocation = { (server, task): model.binary_var(name=f'{server.name} server - {task.name} task') for server in servers for task in fixed_tasks } for task in fixed_tasks: model.add( sum(server_task_allocation[(server, task)] for server in servers) <= 1) for server in servers: for time in range(env._total_time_steps): time_tasks = [ task for task in fixed_tasks if task.auction_time <= time <= task.deadline ] model.add( sum( min( task.required_storage, task.fixed_loading_speed * (time + 1 - task.auction_time)) * server_task_allocation[(server, task)] for task in time_tasks) <= server.storage_cap) model.add( sum(task.fixed_compute_speed * server_task_allocation[(server, task)] for task in time_tasks) <= server.computational_cap) model.add( sum((task.fixed_loading_speed + task.fixed_sending_speed) * server_task_allocation[(server, task)] for task in time_tasks) <= server.bandwidth_cap) model.maximize( sum(server_task_allocation[(server, task)] for server in servers for task in fixed_tasks)) model_solution = model.solve(log_output=None, TimeLimit=150) total_tasks_completed = sum( model_solution.get_value(server_task_allocation[(server, task)]) for server in servers for task in fixed_tasks) return total_tasks_completed
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 initialize(self): model = CpoModel() self.model = model instance = self.instance T = len(instance.intervals) first_on = instance.earliest_on_interval_idx last_on = instance.latest_on_interval_idx init_start_times = self.get_init_start_times(sort_starts=True) ub = min(instance.get_ub(), self.get_upper_bound(init_start_times)) total_proc = sum(j.processing_time for j in instance.jobs) # -------------------------------------- Construct the model. job_vars = dict() # Dict[Job, CpoIntervalVar] self.job_vars = job_vars gap_vars = dict() # Dict[Tuple[int, int], CpoIntervalVar] obj = 0 # objective value seq_vars = [] # variables for no-overlap constraint stp = model.create_empty_solution( ) # starting point of the solving procedure step_fns = CpGeneral.get_step_functions( instance, first_on, last_on) # Generate seqment function for each processing time. first_job_var = model.interval_var(length=0, optional=False, name="first_job_var", start=1) seq_vars.append( first_job_var) # dummy job with 0 length, first in the sequence last_job_var = model.interval_var(length=0, optional=False, name="last_job_var", end=T - 1) seq_vars.append( last_job_var) # dummy job with 0 length, last in the sequence # variables for jobs ------------------------------------------------------------------------------------------- for job in instance.jobs: var = model.interval_var(length=job.processing_time, optional=False, name="j[{:d}]".format(job.id)) model.add(cpmod.start_of(var) >= first_on) # earliest possible start time is first_on model.add(cpmod.end_of(var) <= last_on + 1) # latest possible end time is last_on job_vars[job] = var seq_vars.append(var) if self.specialized_solver_config[ "JobInObjectiveModelling"] == 0: # Optional : alternatives = [] for t in range(first_on, T): if t <= last_on - ( job.processing_time - 1 ): # (-1) because unit job can be processed in last_on var = model.interval_var(start=t, length=job.processing_time, optional=True, name="j[{:d},{:d}]".format( t, job.id)) alternatives.append(var) obj += cpmod.presence_of( var) * instance.cumulative_energy_cost[t][ t + job.processing_time - 1] * instance.on_power_consumption # add a present variable for the job model.add(cpmod.alternative(job_vars[job], alternatives)) elif self.specialized_solver_config[ "JobInObjectiveModelling"] == 1: # Logical : for t in range(T): if first_on <= t <= last_on - (job.processing_time - 1): obj += (cpmod.start_of(var, absentValue=-1) == t) * instance.cumulative_energy_cost[t][ t + job.processing_time - 1] * instance.on_power_consumption elif self.specialized_solver_config[ "JobInObjectiveModelling"] == 2: # Element : energy = [ instance.cumulative_energy_cost[t][t + job.processing_time - 1] * instance.on_power_consumption if (first_on <= t <= last_on - (job.processing_time - 1)) else 0 for t in range(T) ] obj += cpmod.element(energy, cpmod.start_of(var)) elif self.specialized_solver_config[ "JobInObjectiveModelling"] == 3: # Overlap : for t in range(T): # add overlaps to objective if first_on <= t <= last_on: obj += cpmod.overlap_length( var, (t, t + 1)) * instance.intervals[ t].energy_cost * instance.on_power_consumption elif self.specialized_solver_config[ "JobInObjectiveModelling"] == 4: # Step function : obj += cpmod.start_eval(var, step_fns[job.processing_time]) else: raise Exception( "Given JobInObjectiveModelling method {0} is not supported." .format( self. specialized_solver_config["JobInObjectiveModelling"])) # add variables for gaps --------------------------------------------------------------------------------------- if self.specialized_solver_config[ "GapsInObjectiveModelling"] == 0: # Fixed : for t_s in range(1, T): for t_e in range(t_s + 1, T): if instance.has_switching_cost(t_s, t_e): if instance.get_gap_lower_bound( t_s, t_e) > ub: # skip gaps that are too costly continue sw_cost = instance.optimal_switching_costs[t_s][t_e] var = model.interval_var(start=t_s, end=t_e, optional=True, name="gap[{:d},{:d}]".format( t_s, t_e)) gap_vars[t_s, t_e] = var seq_vars.append(var) obj += cpmod.presence_of( var ) * sw_cost # if the gap is present, add cost to objective elif self.specialized_solver_config[ "GapsInObjectiveModelling"] == 1: # Free : gaps_by_lengths = {i: [] for i in range(1, T - 1)} for gap_len in range(1, T - total_proc - 1): costs = [ instance.optimal_switching_costs[t][t + gap_len] if instance.optimal_switching_costs[t][t + gap_len] is not None else len(instance.intervals) * instance.on_power_consumption + 1 # TODO : max value for t in range(T) if t + gap_len < T ] costs[0] = 0 # TODO: for absent value for i in range(int(T / gap_len)): var = model.interval_var(optional=True, length=gap_len, name="gap[{:d},{:d}]".format( gap_len, i)) model.add(cpmod.start_of(var, absentValue=1) >= 1) model.add(cpmod.end_of(var) <= T - 1) obj += cpmod.element(costs, cpmod.start_of(var)) gaps_by_lengths[gap_len].append(var) seq_vars.append(var) # force order on the gaps for cur, nxt in zip(gaps_by_lengths[gap_len], gaps_by_lengths[gap_len][1:]): model.add(cpmod.presence_of(cur) >= cpmod.presence_of(nxt)) model.add(cpmod.end_before_start(cur, nxt)) elif self.specialized_solver_config[ "GapsInObjectiveModelling"] == 2: # No : # Gaps will be added to the objective after introducing the sequence variable pass else: raise Exception( "Given GapsInObjectiveModelling method {0} is not supported.". format(self. specialized_solver_config["GapsInObjectiveModelling"])) # add no overlap constraint ------------------------------------------------------------------------------------ seq = model.sequence_var(seq_vars, name="seq") model.add(cpmod.no_overlap(seq)) model.add(cpmod.first(seq, first_job_var)) model.add(cpmod.last(seq, last_job_var)) if self.specialized_solver_config[ "GapsInObjectiveModelling"] == 2: # No : gap_costs = ( [0 for _ in range(T)] + # gap_len == 0 [ instance.optimal_switching_costs[gap_s][gap_s + gap_len] if gap_s + gap_len <= T - 1 and instance.optimal_switching_costs[gap_s][gap_s + gap_len] is not None else INT_MAX for gap_len in range(1, T) for gap_s in range(T) ]) for job in instance.jobs: job_var = self.job_vars[job] obj += cpmod.element( gap_costs, (cpmod.start_of_next(seq, job_var, T - 1) - cpmod.end_of(job_var)) * T + cpmod.end_of(job_var)) obj += cpmod.element(gap_costs, cpmod.start_of_next(seq, first_job_var) * T) # constrain lengths to fill the whole horizon ------------------------------------------------------------------ if self.specialized_solver_config[ "GapsInObjectiveModelling"] != 2: # gaps are modelled if self.specialized_solver_config[ "FillAllModelling"] == 0: # SumLengths : model.add( sum([cpmod.length_of(var) for var in seq_vars]) == T - 2) elif self.specialized_solver_config[ "FillAllModelling"] == 1: # Pulse : cumul_func = 0 for var in seq_vars: if var is not first_job_var and var is not last_job_var: cumul_func += cpmod.pulse(var, 1) model.add(cpmod.always_in(cumul_func, (1, T - 1), 1, 1)) elif self.specialized_solver_config[ "FillAllModelling"] == 2: # StartOfNext : for var in seq_vars: if var is not last_job_var: model.add( cpmod.start_of_next( seq, var, lastValue=T, absentValue=0) == cpmod.end_of(var, absentValue=0)) else: raise Exception( "Given FillAllModelling method {0} is not supported.". format(self.specialized_solver_config["FillAllModelling"])) # set objective model.minimize(obj) # - init start times. # if init_start_times is not None: # for job in instance.jobs: # stp.add_interval_var_solution(job_vars[job], presence=True, start=init_start_times[job]) # # # gaps in the schedule # gaps = self.get_gaps_in_schedule(init_start_times) # # for g_s, g_e in gaps: # stp.add_interval_var_solution(gap_vars[g_s, g_e], presence=True, start=g_s) # # # set starting point # model.set_starting_point(stp) # force ordering of the jobs jobs_by_lengths = self.get_job_by_lengths() for lst in jobs_by_lengths.values(): for j_cur, j_nxt in zip(lst, lst[1:]): model.add( cpmod.end_before_start(job_vars[j_cur], job_vars[j_nxt]))
NB_TASKS = len(TASKS) # Create a unique id for each mode (to retrieve results) MODES = [] for t in TASKS: for i, m in enumerate(t['modes']): m['id'] = "T{}-M{}".format(t['id'], i + 1) MODES.append(m) #----------------------------------------------------------------------------- # 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:
# Create macro point lists for macro in macros: #helpers.createMacroPositionList(macro, pinMovement, minPinPitch) helpers.createMacroPositionList(macro, minPinPitch, minPinPitch) ''' print(len(macros[0].positionList_x)) for i in range(0, len(macros[0].positionList_x)): print(str(macros[0].positionList_x[i]) + '\t' + str(macros[0].positionList_y[i])) ''' # -------------------- # Build Model # -------------------- # Create Model mdl = CpoModel() # Create Variables - move steps new_index_map = dict() for macro in unique_macros: for term in macro.terms: new_index = mdl.integer_var(0, len(macro.positionList_x), term.name) new_index_map[term.name] = new_index ''' # Create Variable - macro.cpo_center.x/y : fix to macro.center.x/y in constraint for macro in macros: macro.cpo_center.x = mdl.integer_var(domain = (macro.center.x, macro.center.x)) macro.cpo_center.y = mdl.integer_var(domain = (macro.center.y, macro.center.y)) ''' # Apply possible movements in each term in each macro and update new cpo_location after movements for macro in macros:
[1,1,0,1,1,1,0,1,0], [1,1,0,0,0,0,1,1,0], [1,0,0,0,1,1,0,0,1], [0,0,1,0,1,1,1,1,0]] compositions_players=[[1,1,1,1,0], [1,1,1,0,0], [0,0,0,0,1], [1,1,0,0,0], [0,1,0,1,1], [1,1,0,1,1], [1,0,1,0,1], [0,1,1,0,1], [1,0,0,1,0]] waittimes=[2,4,1,3,3,2,5,7,6] mdl = CpoModel() numplayers=5 numcompositions=9 def sumcol(ind,mtrx,numcols): return sum([mtrx[i][ind] for i in range(numplayers)]) def checksymmetries(mtrx, numcols): sum_col = [] checked_cur = [] checked = [] ind_col = [] for i in range(numcols): pr = sumcol(i,mtrx,numcols) try: ind = sum_col.index(pr) except:
maxquantity = 10 # Indexes busSize = 0 busCost = 1 for b in Buses: print("buses with ", b[busSize], " seats cost ", b[busCost]) print() for b in Buses: print("buses with ", b[busSize], " seats cost ", b[busCost]) mdl = CpoModel(name='buses') #decision variables mdl.nbBus = mdl.integer_var_dict(Buses, 0, maxquantity, name="nbBus") # Constraint mdl.add(sum(mdl.nbBus[b] * b[busSize] for b in Buses) >= nbKids) # Objective mdl.minimize(sum(mdl.nbBus[b] * b[busCost] for b in Buses)) msol = mdl.solve() # Dislay solution for b in Buses: print(msol[mdl.nbBus[b]], " buses with ", b[busSize], " seats")
from docplex.cp.model import CpoModel from docplex.cp.model import CpoParameters mdl = CpoModel(name='buses') nbbus40 = mdl.integer_var(0, 1000, name='nbBus40') nbbus30 = mdl.integer_var(0, 1000, name='nbBus30') mdl.add(nbbus40 * 40 + nbbus30 * 30 >= 300) mdl.minimize(nbbus40 * 500 + nbbus30 * 400) param = CpoParameters() param.set_TimeLimit(20) param.TimeLimit = 20 #use parameters param for model mdl mdl.set_parameters(param) msol = mdl.solve() print(msol[nbbus40], " buses 40 seats") print(msol[nbbus30], " buses 30 seats") #read params from model mdl param2 = mdl.get_parameters() print("time limit = ", param2["TimeLimit"]) print("time limit = ", param2.get_attribute("TimeLimit")) for i in param2: print(i, " = ", param2[i]) """ which gives
def main(): filename = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data_in/test_1.txt") inst = instance.Instance(filename) # input from master problem, now random id_profile = 0 random.seed(42) rewards = [random.randint(0, 30000) for i in range(inst.J)] #rewards = [random.uniform(0.0, 30000.0) for i in range(inst.J)] equivalences = [[0, 1], [2, 3]] mutexes = [[2, 1], [4, 3]] # input from master problem, now random types = inst.profiles[id_profile] types.insert(0, inst.INIT) types.append(inst.TERM) trans_cost = [[0 for i in range(inst.V)] for j in range(inst.V)] trans_time = [[0 for i in range(inst.V)] for j in range(inst.V)] for i in range(len(inst.edges)): for j in range(len(inst.edges[i])): trans_cost[i][inst.edges[i][j][ 'to']] = inst.edges[i][j]['C'] * inst.edges[i][j]['t'] trans_time[i][inst.edges[i][j]['to']] = inst.edges[i][j]['t'] changeover_cost = 0 for i in range(1, len(types)): changeover_cost += trans_cost[types[i - 1]][types[i]] cp = CpoModel() primitives = [[] for i in range(inst.J)] all_primitives = [] init = cp.interval_var(start=0) init.set_end_max(inst.L) total_cost = changeover_cost + inst.vertices[ inst.INIT]['C'] * cp.length_of(init, 0) modes_of_mach = [init ] # serves only for retrieving starts and ends of modes last_shift = init for i in range(1, len(types) - 1): v = types[i] shift = cp.interval_var() shift.set_size_min(inst.vertices[v]['t_min']) shift.set_size_max(inst.vertices[v]['t_max']) shift.set_end_max(inst.L) total_cost += inst.vertices[v]['C'] * cp.length_of(shift, 0) cp.add( cp.start_at_end(shift, last_shift, -trans_time[types[i - 1]][types[i]])) last_shift = shift modes_of_mach.append(shift) for t in range(inst.J): if inst.tasks[t]['p'][v] <= inst.L: prim = cp.interval_var(size=inst.tasks[t]['p'][v]) total_cost -= rewards[t] * cp.presence_of(prim) prim.set_optional() prim.set_start_min(inst.tasks[t]['r']) prim.set_end_max(inst.tasks[t]['d']) primitives[t].append(prim) all_primitives.append(prim) cp.add(cp.start_before_start(shift, prim)) cp.add(cp.end_before_end(prim, shift)) term = cp.interval_var(end=inst.L) total_cost += inst.vertices[inst.TERM]['C'] * cp.length_of(term, 0) cp.add( cp.start_at_end(term, last_shift, -trans_time[types[len(types) - 2]][inst.TERM])) modes_of_mach.append(term) cp.add(cp.no_overlap(cp.sequence_var(all_primitives))) for t in range(inst.J): cp.add(sum([cp.presence_of(p) for p in primitives[t]]) <= 1) for eq in equivalences: cp.add( sum([cp.presence_of(p) for p in primitives[eq[0]]]) == sum( [cp.presence_of(p) for p in primitives[eq[1]]])) for mut in mutexes: cp.add( sum([cp.presence_of(p) for p in primitives[mut[0]]]) + sum([cp.presence_of(p) for p in primitives[mut[1]]]) <= 1) cp.add(cp.minimize(total_cost)) # set TimeLimit in seconds or delete it for no limit # parameters DefaultInferenceLevel and Workers may be beneficial to add sol = cp.solve( TimeLimit=30, LogVerbosity="Quiet") #, DefaultInferenceLevel='Extended', Workers=1) if sol: tasks = [] for t in range(inst.J): for pr in primitives[t]: p = sol.get_var_solution(pr) if p.is_present(): tasks.append({ "task": t, "start": p.get_start(), "end": p.get_end() }) break modes = [] sched_cost = 0 for t in range(len(modes_of_mach)): m = sol.get_var_solution(modes_of_mach[t]) modes.append({ "mode": types[t], "start": m.get_start(), "end": m.get_end() }) sched_cost += inst.vertices[types[t]]['C'] * m.get_length() print("Solution status: " + sol.get_solve_status()) print("Solve time: " + str(sol.get_solve_time())) print("Objective: " + str(sol.get_objective_values()[0])) print("Schedule cost: " + str(sched_cost)) print(tasks) print(modes) else: print("No solution found.")
# The rest of the file consists of one line per job that contains the list of # operations given as durations for each machines. filename = os.path.dirname( os.path.abspath(__file__)) + "/data/flowshop_default.data" with open(filename, "r") as file: NB_JOBS, NB_MACHINES = [int(v) for v in file.readline().split()] JOB_DURATIONS = [[int(v) for v in file.readline().split()] for i in range(NB_JOBS)] #----------------------------------------------------------------------------- # Build the model #----------------------------------------------------------------------------- # 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
#----------------------------------------------------------------------------- # Prepare the data for modeling #----------------------------------------------------------------------------- # Assign an index to tasks ALL_TASKS = (MASONRY, CARPENTRY, PLUMBING, CEILING, ROOFING, PAINTING, WINDOWS, FACADE, GARDEN, MOVING) for i in range(len(ALL_TASKS)): ALL_TASKS[i].id = i #----------------------------------------------------------------------------- # Build the model #----------------------------------------------------------------------------- # Create model mdl = CpoModel() # Initialize model variable sets all_tasks = [] # Array of all tasks desc = dict() # Dictionary task interval var -> task descriptor house = dict() # Dictionary task interval var -> id of the corresponding house workers_usage = mdl.step_at(0, 0) # Total worker usage # Initialize cash function cash = mdl.step_at(0, 0) for p in range(NB_PAYMENTS): cash += mdl.step_at(PAYMENT_INTERVAL * p, PAYMENT_AMOUNT) # Utility function def make_house(loc, rd):
""" In Constraint Programming decision variables have to be integer but sometimes we need more than this. Let's see how we can handle through decision expressions. Suppose in the bus example we want to book not only whole buses but also percentage of buses. Then we can write """ from docplex.cp.model import CpoModel mdl = CpoModel(name='buses') #now suppose we can book a % of buses not only complete buses scale = 100 scalenbbus40 = mdl.integer_var(0, 1000, name='scalenbBus40') scalenbbus30 = mdl.integer_var(0, 1000, name='scalenbBus30') nbbus40 = scalenbbus40 / scale nbbus30 = scalenbbus30 / scale mdl.add(nbbus40 * 40 + nbbus30 * 30 >= 310) mdl.minimize(nbbus40 * 500 + nbbus30 * 400) msol = mdl.solve() print(msol[scalenbbus40] / scale, " buses 40 seats")
Moreover, there are earliness and tardiness costs associated with some tasks. The objective is to minimize these costs. Please refer to documentation for appropriate setup of solving configuration. """ from docplex.cp.model import CpoModel, CpoSegmentedFunction import docplex.cp.utils_visu as visu #----------------------------------------------------------------------------- # Initialize the problem data #----------------------------------------------------------------------------- # Create model mdl = CpoModel() # House building task descriptor class BuildingTask(object): def __init__(self, name, duration, release_date=None, due_date=None, earliness_cost=None, tardiness_cost=None): self.name = name self.duration = duration self.release_date = release_date self.due_date = due_date
#===============INITIALIZE DATA=============== #items items = [] for i in range(0,len(items_data)): items.append(Item(i, items_data[i])) #bins bins = [] for i in range(len(bins_data)): bins.append(Bin(i, bins_data[i])) #add a new bin at the end of the list, big enough to accommodate ALL items #needed so that all items can be allocated, CPO won't return any solution if an item unallocated bins.append(Bin(nb_bins, sum(items_data))) #===============CREATE MODEL=============== mdl = CpoModel(name = "bin-packing-variant") #===============SETUP DECISION VARIABLES=============== #array of integer variables saying which bin an item goes into wheres = [] bin_idx_of_dump_item = 0 for item in items: bin_list = () for bin in bins[0:nb_bins]: if(alloc_constraint[item.id, bin.id] == 1): bin_list += int(bin.id), #add the last bin (the big one) bin_list += nb_bins, wheres.append(mdl.integer_var(domain=(bin_list), name = "whereItem"+str(item.id))) #===============SETUP CONSTRAINTS===============
# Data Buses = [(40, 500), (30, 400)] nbKids = 300 # Indexes busSize = 0 busCost = 1 for b in Buses: print("buses with ", b[busSize], " seats cost ", b[busCost]) mdl = CpoModel(name='buses') #decision variables mdl.nbBus = { b: mdl.integer_var(0, 1000, name="nbBus" + str(b[busSize])) for b in Buses } # Constraint mdl.add(sum(mdl.nbBus[b] * b[busSize] for b in Buses) >= nbKids) # Objective mdl.minimize(sum(mdl.nbBus[b] * b[busCost] for b in Buses)) msol = mdl.solve()
def solve_seer_ilp(companies, facilities, customers, facilityDemands, costs, alpha=1, log_verbose='Quiet'): assert alpha >= 0 # ensure trace-off factor is >= 0, which show the contribution of representative cost assert log_verbose in ['Quiet', 'Terse', 'Normal', 'Verbose'] n_company = len(companies) n_facility = len(facilities) n_customer = len(customers) n_type = len(facilityDemands) mdl = CpoModel() customerSupplier = mdl.integer_var_list(n_customer, 0, n_facility - 1, 'customerSupplier') openFacility = mdl.integer_var_list(n_facility, 0, 1, 'openFacility') facilityType = mdl.integer_var_list(n_facility, 0, n_type, 'facilityType') customerType = mdl.integer_var_list(n_customer, 0, n_type - 1, 'customerType') openCompany = mdl.integer_var_list(n_company, 0, 1, 'openCompany') company2id = {companies[i].name: i for i in range(n_company)} type2id = {facilityDemands[i].type: i for i in range(n_type)} facilityCompany = [ company2id[facilities[i].company] for i in range(n_facility) ] validFacilityType = np.zeros((n_facility, n_type + 1)) validFacilityType[:, n_type] = 1 for i in range(n_facility): validFacilityType[i, type2id[facilities[i].type]] = 1 for i in range(n_customer): mdl.add(mdl.element(openFacility, customerSupplier[i]) == 1) mdl.add( mdl.element(customerType, i) == mdl.element( facilityType, customerSupplier[i])) mdl.add( mdl.element(mdl.element(customerType, i), validFacilityType[i]) == 1) for i in range(n_facility): mdl.add( mdl.element(mdl.element(facilityType, i), validFacilityType[i]) == 1) mdl.add( mdl.element(openFacility, i) <= mdl.element( openCompany, facilityCompany[i])) mdl.add((mdl.element(openFacility, i) == 1) == ( mdl.element(facilityType, i) < n_type)) for i in range(n_type): mdl.add(mdl.count(facilityType, i) == facilityDemands[i].demand) # Objective total_cost = mdl.scal_prod(openCompany, [c.cost for c in companies]) for i in range(n_customer): total_cost += mdl.element(customerSupplier[i], alpha * costs[i]) mdl.add(mdl.minimize(total_cost)) # ----------------------------------------------------------------------------- # Solve the model and display the result # ----------------------------------------------------------------------------- # Solve model msol = mdl.solve(TimeLimit=TIME_LIMIT, LogVerbosity=log_verbose) selectedFacilities = [] selectedCompanies = [] if msol: for i in range(n_facility): if msol[facilityType[i]] < n_type: selectedFacilities.append(i) if facilityCompany[i] not in selectedCompanies: selectedCompanies.append(facilityCompany[i]) return msol, selectedFacilities, selectedCompanies
def find_skills(worker, task): return next(s for s in SKILLS if (s.worker == worker) and (s.task == task)) # Iterator on houses numbers HOUSES = range(1, NB_HOUSES + 1) # Build the list of all worker names WORKERS = set(sk.worker for sk in SKILLS) #----------------------------------------------------------------------------- # Build the model #----------------------------------------------------------------------------- # Create model mdl = CpoModel() # Variables of the model tasks = {} # dict of interval variable for each house and task wtasks = {} # dict of interval variable for each house and skill for house in HOUSES: for task in TASKS: v = (0, MAX_SCHEDULE) tasks[(house, task)] = mdl.interval_var(v, v, size=task.duration, name="house {} task {}".format( house, task)) for task in SKILLS: wtasks[(house, task)] = mdl.interval_var( optional=True, name="house {} skill {}".format(house, task))