def test_tsp_mipstart(solver: str): """tsp related tests""" N = ['a', 'b', 'c', 'd', 'e', 'f', 'g'] n = len(N) i0 = N[0] A = { ('a', 'd'): 56, ('d', 'a'): 67, ('a', 'b'): 49, ('b', 'a'): 50, ('d', 'b'): 39, ('b', 'd'): 37, ('c', 'f'): 35, ('f', 'c'): 35, ('g', 'b'): 35, ('b', 'g'): 25, ('a', 'c'): 80, ('c', 'a'): 99, ('e', 'f'): 20, ('f', 'e'): 20, ('g', 'e'): 38, ('e', 'g'): 49, ('g', 'f'): 37, ('f', 'g'): 32, ('b', 'e'): 21, ('e', 'b'): 30, ('a', 'g'): 47, ('g', 'a'): 68, ('d', 'c'): 37, ('c', 'd'): 52, ('d', 'e'): 15, ('e', 'd'): 20 } # input and output arcs per node Aout = {n: [a for a in A if a[0] == n] for n in N} Ain = {n: [a for a in A if a[1] == n] for n in N} m = Model(solver_name=solver) m.verbose = 0 x = { a: m.add_var(name='x({},{})'.format(a[0], a[1]), var_type=BINARY) for a in A } m.objective = xsum(c * x[a] for a, c in A.items()) for i in N: m += xsum(x[a] for a in Aout[i]) == 1, 'out({})'.format(i) m += xsum(x[a] for a in Ain[i]) == 1, 'in({})'.format(i) # continuous variable to prevent subtours: each # city will have a different "identifier" in the planned route y = {i: m.add_var(name='y({})'.format(i), lb=0.0) for i in N} # subtour elimination for (i, j) in A: if i0 not in [i, j]: m.add_constr(y[i] - (n + 1) * x[(i, j)] >= y[j] - n) route = ['a', 'g', 'f', 'c', 'd', 'e', 'b', 'a'] m.start = [(x[route[i - 1], route[i]], 1.0) for i in range(1, len(route))] m.optimize() assert m.status == OptimizationStatus.OPTIMAL assert abs(m.objective_value - 262) <= TOL
(38.15, 15.35), (37.51, 15.17), (35.49, 14.32), (39.36, 19.56), (38.09, 24.36), (36.09, 23.00), (40.44, 13.57), (40.33, 14.15), (40.37, 14.23), (37.57, 22.56)] # latitude and longitude coord = [(rad(x), rad(y)) for (x, y) in coord] # distances in an upper triangular matrix # number of nodes and list of vertices n, V = len(coord), set(range(len(coord))) # distances matrix c = [[0 if i == j else dist(coord[i], coord[j]) for j in V] for i in V] model = Model() # binary variables indicating if arc (i,j) is used on the route or not x = [[model.add_var(var_type=BINARY) for j in V] for i in V] # objective function: minimize the distance model.objective = minimize(xsum(c[i][j] * x[i][j] for i in V for j in V)) # constraint : leave each city only once for i in V: model += xsum(x[i][j] for j in V - {i}) == 1 # constraint : enter each city only once for i in V: model += xsum(x[j][i] for j in V - {i}) == 1
def fl_mip_solver(input_data): # Modify this code to run your optimization algorithm # parse the input lines = input_data.split('\n') parts = lines[0].split() facility_count = int(parts[0]) customer_count = int(parts[1]) facilities = [] for i in range(1, facility_count+1): parts = lines[i].split() facilities.append(Facility(i-1, float(parts[0]), int(parts[1]), Point(float(parts[2]), float(parts[3])) )) customers = [] for i in range(facility_count+1, facility_count+1+customer_count): parts = lines[i].split() customers.append(Customer(i-1-facility_count, int(parts[0]), Point(float(parts[1]), float(parts[2])))) print('F count:',facility_count) print('C count:',customer_count) # instantiates setup cost vector set_cost = [f.setup_cost for f in facilities] # instantiates proportional capacity matrix such that Cap[i,j] represents the demand of # customer 'j' as a fraction of the total capacity of facility 'i' Cap = [[c.demand/f.capacity for c in customers] for f in facilities] # instantiates distance matrix in such a way that "sum_{j \in M} D[i,j]*at[i,j]" is the total # distance cost for facility 'i' D = [[length(c.location, f.location) for c in customers] for f in facilities] # declares MIP model #m = Model(solver_name=CBC) m = Model(solver_name='GRB') print('-Model instatiated!',datetime.datetime.now()) # states search emphasis # - '0' (default) balanced approach # - '1' (feasibility) aggressively searches for feasible solutions # - '2' (optimality) explores search space to tighten dual gap m.emphasis = 2 # whenever the distance of the lower and upper bounds is less or # equal max_gap*100%, the search can be finished m.max_gap = 0.05 # specifies number of used threads # 0 uses solver default configuration, # -1 uses the number of available processing cores # ≥1 uses the specified number of threads. # An increased number of threads may improve the solution time but also increases # the memory consumption. Each thread needs to store a different model instance! m.threads = -1 # controls the generation of cutting planes # cutting planes usually improve the LP relaxation bound but also make the solution time of the LP relaxation larger # -1 means automatic # 0 disables completely # 1 (default) generates cutting planes in a moderate way # 2 generates cutting planes aggressively # 3 generates even more cutting planes m.cuts=-1 m.preprocess=1 m.pump_passes=10 m.sol_pool_size=1 # instantiates open facilities variables op = [m.add_var(name="op{}".format(i),var_type='B') for i in range(facility_count)] # instantiates matrix of atribution variables # (line 'i' is an atribution vector for facility 'i') # e.g.: At[3][4] returns whether customer 4 is assigned to facility 3 At = [[m.add_var(name="At{},{}".format(i,j) ,var_type='B') for j in range(customer_count)] for i in range(facility_count)] print('-Variables declared!',datetime.datetime.now()) # instantiates objective function # m.objective = minimize("setup costs" + "distance costs") # Form example: # m.objective = minimize( # xsum(dist[i, j] * x[i, j] for (i, j) in product(F, C)) + xsum(y[i] for i in F) ) m.objective = minimize( xsum(set_cost[i]*op[i] for i in range(facility_count)) + xsum(sum(D[i][j]*At[i][j] for j in range(customer_count)) for i in range(facility_count)) ) print('-Objective declared!',datetime.datetime.now()) # instatiates capacity constraints # -can be expressed as "sum_{j \in M} Cap[i,j]*At[i,j] <= op[i]" for all facilities 'i' # -if a facility is closed (op[i]=0), its effective capacity is 0 for i in range(facility_count): m.add_lazy_constr( xsum(Cap[i][j]*At[i][j] for j in range(customer_count)) <= op[i] ) # instantiates assignment constraints (maximum of 1 facility per customer) # -can be expressed as: "sum of elements over of each column of 'At' == 1" for i in range(customer_count): m += xsum(At[j][i] for j in range(facility_count)) == 1 print('-Contraints processed!',datetime.datetime.now()) #Maximum time in seconds that the search can go on if a feasible solution #is available and it is not being improved mssi = 1000 #default = inf # specifies maximum number of nodes to be explored in the search tree (default = inf) mn = 40000 #default = 1073741824 # optimize model m within a processing time limit of 'ms' seconds ms = 3000 #default = inf print('-Optimizer start.',datetime.datetime.now()) # executes the optimization #status = m.optimize(max_seconds = ms,max_seconds_same_incumbent = mssi,max_nodes = mn) status = m.optimize(max_seconds = ms , max_seconds_same_incumbent = mssi) final_obj = m.objective_value print('Opt. Status:',status) print('MIP Sol. Obj.:',final_obj) print('Dual Bound:',m.objective_bound) print('Dual gap:',m.gap) used=[i for i in range(facility_count) if m.vars[i].x==1] solution=[None] * customer_count for i in range(facility_count): for j in range(customer_count): if round(m.vars[i*customer_count + j + facility_count].x) == 1: solution[j]=i # parse output varibles and convert to conventional solution output format # calculate the cost of the solution obj = sum([facilities[f].setup_cost for f in used]) for customer in customers: obj += length(customer.location, facilities[solution[customer.index]].location) if status == OptimizationStatus.OPTIMAL: # prepare the solution in the specified output format output_data = '%.2f' % obj + ' ' + str(1) + '\n' output_data += ' '.join(map(str, solution)) elif status == OptimizationStatus.FEASIBLE: output_data = '%.2f' % obj + ' ' + str(0) + '\n' output_data += ' '.join(map(str, solution)) return output_data
class AP: """ 指派问题求解。 """ ap_model = None # 模型 dec_vars = None # decision variable 决策变量 is_init = False # 是否初始化 opt_status = None # 求解状态 def __init__(self, profit_matrix: List[int]): """ 初始化 """ self.profit_matrix = profit_matrix def init_model(self): # 1. 选择求解器初始化 self.ap_model = Model(sense=MINIMIZE, solver_name=CBC) # 2. 定义决策变量 self.dec_vars = [[ self.ap_model.add_var(var_type=BINARY) for i in range(len(self.profit_matrix)) ] for j in range(len(self.profit_matrix))] # 3. 定义目标函数 self.ap_model.objective = minimize( xsum(self.dec_vars[i][j] * self.profit_matrix[i][j] for i in range(len(self.profit_matrix)) for j in range(len(self.profit_matrix)))) # 4. 定义约束条件 for i in range(len(self.profit_matrix)): # 每行只能有一个1 self.ap_model.add_constr( xsum(self.dec_vars[i][j] for j in range(len(self.profit_matrix))) == 1) for j in range(len(self.profit_matrix)): # 每列只能有一个1 self.ap_model.add_constr( xsum(self.dec_vars[i][j] for i in range(len(self.profit_matrix))) == 1) self.is_init = True def solve(self, max_seconds: int = 10): """ 设定约束时间开始求解 :param max_seconds: :return: """ if not self.is_init: self.init_model() self.opt_status = self.ap_model.optimize(max_seconds=max_seconds) return self.opt_status def get_optimum_val(self): """ 获取最优解值 :return: """ if self.opt_status and self.opt_status == OptimizationStatus.OPTIMAL: return self.ap_model.objective_value else: raise Exception('未求得解') def get_optimum_sol(self): """ 获取最优解变量 :return: """ if self.opt_status and self.opt_status == OptimizationStatus.OPTIMAL: return self.dec_vars else: raise Exception('未求得解')
return for cut in cp.cuts: model += cut n = 30 # number of points V = set(range(n)) seed(0) p = [(randint(1, 100), randint(1, 100)) for i in V] # coordinates Arcs = [(i, j) for (i, j) in product(V, V) if i != j] # distance matrix c = [[round(sqrt((p[i][0] - p[j][0])**2 + (p[i][1] - p[j][1])**2)) for j in V] for i in V] model = Model() # binary variables indicating if arc (i,j) is used on the route or not x = [[model.add_var(var_type=BINARY) for j in V] for i in V] # continuous variable to prevent subtours: each city will have a # different sequential id in the planned route except the first one y = [model.add_var() for i in V] # objective function: minimize the distance model.objective = minimize(xsum(c[i][j] * x[i][j] for (i, j) in Arcs)) # constraint : leave each city only once for i in V: model += xsum(x[i][j] for j in V - {i}) == 1
class LP_RCPSP(MilpSolver): def __init__(self, rcpsp_model: SingleModeRCPSPModel, lp_solver=LP_RCPSP_Solver.CBC, params_objective_function: ParamsObjectiveFunction=None, **kwargs): self.rcpsp_model = rcpsp_model self.model: Model = None self.lp_solver = CBC if lp_solver == LP_RCPSP_Solver.GRB: self.lp_solver = GRB elif lp_solver == LP_RCPSP_Solver.CBC: self.lp_solver = CBC self.variable_decision = {} self.constraints_dict = {} self.constraints_dict["lns"] = [] self.aggreg_from_sol, self.aggreg_dict, self.params_objective_function = \ build_aggreg_function_and_params_objective(problem=self.rcpsp_model, params_objective_function= params_objective_function) # self.description_variable_description = {} # self.description_constraint = {} def init_model(self, **args): greedy_start = args.get("greedy_start", True) start_solution = args.get("start_solution", None) verbose = args.get("verbose", False) if start_solution is None: if greedy_start: if verbose: print("Computing greedy solution") greedy_solver = PileSolverRCPSP(self.rcpsp_model) store_solution = greedy_solver.solve(greedy_choice=GreedyChoice.MOST_SUCCESSORS) self.start_solution = store_solution.get_best_solution_fit()[0] makespan = self.rcpsp_model.evaluate(self.start_solution)["makespan"] else: if verbose: print("Get dummy solution") solution = self.rcpsp_model.get_dummy_solution() self.start_solution = solution makespan = self.rcpsp_model.evaluate(solution)["makespan"] else: self.start_solution = start_solution makespan = self.rcpsp_model.evaluate(start_solution)["makespan"] # p = [0, 3, 2, 5, 4, 2, 3, 4, 2, 4, 6, 0] sorted_tasks = sorted(self.rcpsp_model.mode_details.keys()) print(sorted_tasks) p = [int(self.rcpsp_model.mode_details[key][1]['duration']) for key in sorted_tasks] # print('p:', p) # u = [[0, 0], [5, 1], [0, 4], [1, 4], [1, 3], [3, 2], [3, 1], [2, 4], # [4, 0], [5, 2], [2, 5], [0, 0]] u = [] for task in sorted_tasks: tmp = [] for r in self.rcpsp_model.resources.keys(): tmp.append(self.rcpsp_model.mode_details[task][1][r]) u.append(tmp) # print('u: ', u) # c = [6, 8] c = [x for x in self.rcpsp_model.resources.values()] # print('c: ', c) # S = [[0, 1], [0, 2], [0, 3], [1, 4], [1, 5], [2, 9], [2, 10], [3, 8], [4, 6], # [4, 7], [5, 9], [5, 10], [6, 8], [6, 9], [7, 8], [8, 11], [9, 11], [10, 11]] S = [] print('successors: ', self.rcpsp_model.successors) for task in sorted_tasks: for suc in self.rcpsp_model.successors[task]: S.append([task-1, suc-1]) # print('S: ', S) (R, self.J, self.T) = (range(len(c)), range(len(p)), range(sum(p))) # we have a better self.T to limit the number of variables : self.T = range(int(makespan+1)) # model = Model() self.model = Model(sense=MINIMIZE, solver_name=self.lp_solver) self.x: List[List[Var]] = [[self.model.add_var(name="x({},{})".format(j, t), var_type=BINARY) for t in self.T] for j in self.J] self.model.objective = xsum(self.x[len(self.J) - 1][t] * t for t in self.T) for j in self.J: self.model += xsum(self.x[j][t] for t in self.T) == 1 for (r, t) in product(R, self.T): self.model += ( xsum(u[j][r] * self.x[j][t2] for j in self.J for t2 in range(max(0, t - p[j] + 1), t + 1)) <= c[r]) for (j, s) in S: self.model += xsum(t * self.x[s][t] - t * self.x[j][t] for t in self.T) >= p[j] start = [] for j in self.J: for t in self.T: if self.start_solution.rcpsp_schedule[j+1]["start_time"] == t: start += [(self.x[j][t], 1)] else: start += [(self.x[j][t], 0)] self.model.start = start p_s: Union[PartialSolution, None] = args.get("partial_solution", None) self.constraints_partial_solutions = [] if p_s is not None: constraints = [] if p_s.start_times is not None: for task in p_s.start_times: constraints += [self.model.add_constr(xsum([j*self.x[task-1][j] for j in range(len(self.x[task-1]))]) == p_s.start_times[task])] constraints += [self.model.add_constr(self.x[task-1][p_s.start_times[task]] == 1)] if p_s.partial_permutation is not None: for t1, t2 in zip(p_s.partial_permutation[:-1], p_s.partial_permutation[1:]): constraints += [self.model.add_constr(xsum([t * self.x[t1-1][t]-t*self.x[t2-1][t] for t in self.T]) <= 0)] if p_s.list_partial_order is not None: for l in p_s.list_partial_order: for t1, t2 in zip(l[:-1], l[1:]): constraints += [self.model.add_constr(xsum([t * self.x[t1-1][t]-t*self.x[t2-1][t] for t in self.T]) <= 0)] self.starts = {} for j in range(len(self.x)): self.starts[j] = self.model.add_var(name="start_" + str(j), lb=0, ub=makespan) self.model.add_constr(xsum(t * self.x[j][t] for t in self.T) == self.starts[j]) if p_s.start_at_end is not None: for i, j in p_s.start_at_end: constraints += [self.model.add_constr(self.starts[j-1] == self.starts[i-1]+p[i-1])] if p_s.start_together is not None: for i, j in p_s.start_together: constraints += [self.model.add_constr(self.starts[j-1] == self.starts[i-1])] if p_s.start_after_nunit is not None: for t1, t2, delta in p_s.start_after_nunit: constraints += [self.model.add_constr(self.starts[t2-1] >= self.starts[t1-1]+delta)] if p_s.start_at_end_plus_offset is not None: for t1, t2, delta in p_s.start_at_end_plus_offset: constraints += [self.model.add_constr(self.starts[t2-1] >= self.starts[t1-1]+delta+p[t1-1])] self.constraints_partial_solutions = constraints def retrieve_solutions(self, parameters_milp: ParametersMilp) -> ResultStorage: retrieve_all_solution = parameters_milp.retrieve_all_solution nb_solutions_max = parameters_milp.n_solutions_max nb_solution = min(nb_solutions_max, self.model.num_solutions) if not retrieve_all_solution: nb_solution = 1 list_solution_fits = [] print(nb_solution, " solutions found") for s in range(nb_solution): rcpsp_schedule = {} objective = self.model.objective_values[s] for (j, t) in product(self.J, self.T): value = self.x[j][t].xi(s) if value >= 0.5: rcpsp_schedule[j + 1] = {'start_time': t, 'end_time': t + self.rcpsp_model.mode_details[j + 1][1]['duration']} print("Size schedule : ", len(rcpsp_schedule.keys())) try: solution = RCPSPSolution(problem=self.rcpsp_model, rcpsp_schedule=rcpsp_schedule, rcpsp_schedule_feasible=True) fit = self.aggreg_from_sol(solution) list_solution_fits += [(solution, fit)] except: print("Problem =", rcpsp_schedule, len(rcpsp_schedule)) pass return ResultStorage(list_solution_fits=list_solution_fits, best_solution=min(list_solution_fits, key=lambda x: x[1])[0], mode_optim=self.params_objective_function.sense_function) def solve(self, parameters_milp: ParametersMilp=ParametersMilp.default(), **kwargs)->ResultStorage: if self.model is None: self.init_model() limit_time_s = parameters_milp.TimeLimit self.model.sol_pool_size = parameters_milp.PoolSolutions self.model.max_mip_gap_abs = parameters_milp.MIPGapAbs self.model.max_mip_gap = parameters_milp.MIPGap self.model.optimize(max_seconds=limit_time_s, max_solutions=parameters_milp.n_solutions_max) return self.retrieve_solutions(parameters_milp)
#Spyder (Python) - Code C023 """ MIP package """ from mip import Model, MINIMIZE model = Model("dual", MINIMIZE) x1 = model.add_var() x2 = model.add_var() x3 = model.add_var() model += 5 * x1 + x2 + 4 * x3 model += x1 + x2 >= 1 model += x1 - x2 + x3 >= 2 model += x1 >= 0 model += x2 >= 0 model += x3 >= 0 model.optimize() print("x1 = {x1.x}, x2= {x2.x}, x3= {x3.x}".format(**locals()))
[123, 77, 81, 71, 91, 72, 64, 24, 62, 63], [51, 114, 72, 54, 69, 139, 105, 155, 62], [70, 25, 22, 52, 90, 56, 105, 16], [45, 61, 111, 36, 61, 57, 70], [23, 71, 67, 48, 85, 29], [74, 89, 69, 107, 36], [117, 65, 125, 43], [54, 22, 84], [60, 44], [97], []] # number of nodes and list of vertices n, V = len(dists), range(len(dists)) # distances matrix c = [[ 0 if i == j else dists[i][j - i - 1] if j > i else dists[j][i - j - 1] for j in V ] for i in V] model = Model() # binary variables indicating if arc (i,j) is used on the route or not x = [[model.add_var(var_type=BINARY) for j in V] for i in V] # continuous variable to prevent subtours: each city will have a # different sequential id in the planned route except the first one y = [model.add_var() for i in V] # objective function: minimize the distance model.objective = minimize(xsum(c[i][j] * x[i][j] for i in V for j in V)) # constraint : leave each city only once for i in V: model += xsum(x[i][j] for j in set(V) - {i}) == 1
def test_mip_file(solver: str, instance: str): """Tests optimization of MIP models stored in .mps or .lp files""" m = Model(solver_name=solver) # optional file for optimal LP basis bas_file = "" iname = "" for ext in EXTS: if instance.endswith(ext): bas_file = instance.replace(ext, ".bas") if not exists(bas_file): bas_file = "" iname = basename(instance.replace(ext, "")) break assert iname in BOUNDS.keys() lb = BOUNDS[iname][0] ub = BOUNDS[iname][1] assert lb <= ub + TOL has_opt = abs(ub - lb) <= TOL max_dif = max(max(abs(ub), abs(lb)) * 0.01, TOL) m.read(instance) if bas_file: m.verbose = True m.read(bas_file) m.optimize(relax=True) print("Basis loaded!!! Obj value: %f" % m.objective_value) m.optimize(max_nodes=MAX_NODES) if m.status in [OptimizationStatus.OPTIMAL, OptimizationStatus.FEASIBLE]: assert m.num_solutions >= 1 m.check_optimization_results() assert m.objective_value >= lb - max_dif if has_opt and m.status == OptimizationStatus.OPTIMAL: assert abs(m.objective_value - ub) <= max_dif elif m.status == OptimizationStatus.NO_SOLUTION_FOUND: assert m.objective_bound <= ub + max_dif else: assert m.status not in [ OptimizationStatus.INFEASIBLE, OptimizationStatus.INT_INFEASIBLE, OptimizationStatus.UNBOUNDED, OptimizationStatus.ERROR, OptimizationStatus.CUTOFF, ] assert m.objective_bound <= ub + max_dif
def mip_solver(input_data): # Modify this code to run your optimization algorithm # parse the input lines = input_data.split('\n') firstLine = lines[0].split() item_count = int(firstLine[0]) capacity = int(firstLine[1]) items = [] for i in range(1, item_count+1): line = lines[i] parts = line.split() items.append(Item(i-1, int(parts[0]), int(parts[1]))) # a trivial algorithm for filling the knapsack # it takes items in-order until the knapsack is full value = 0 weight = 0 taken = [0]*len(items) # declare value vector val_vec = [item.value for item in items] # declare weight vector scaled by capacity wgt_vec = [item.weight/capacity for item in items] # start MIP solver m = Model(solver_name='GRB') print('-Model instatiated!',datetime.datetime.now()) # states search emphasis # - '0' (default) balanced approach # - '1' (feasibility) aggressively searches for feasible solutions # - '2' (optimality) explores search space to tighten dual gap m.emphasis = 2 # whenever the distance of the lower and upper bounds is less or # equal max_gap*100%, the search can be finished m.max_gap = 0.05 # specifies number of used threads # 0 uses solver default configuration, # -1 uses the number of available processing cores # ≥1 uses the specified number of threads. # An increased number of threads may improve the solution time but also increases # the memory consumption. Each thread needs to store a different model instance! m.threads = -1 # controls the generation of cutting planes # cutting planes usually improve the LP relaxation bound but also make the solution time of the LP relaxation larger # -1 means automatic # 0 disables completely # 1 (default) generates cutting planes in a moderate way # 2 generates cutting planes aggressively # 3 generates even more cutting planes m.cuts=-1 m.preprocess=1 m.pump_passes=10 m.sol_pool_size=1 # instantiates taken items variable vector taken = [m.add_var(name="it{}".format(i),var_type='B') for i in range(item_count)] print('-Variables declared!',datetime.datetime.now()) # instantiates objective function m.objective = maximize( xsum( val_vec[i]*taken[i] for i in range(item_count) ) ) print('-Objective declared!',datetime.datetime.now()) m.add_constr( xsum( wgt_vec[i]*taken[i] for i in range(item_count)) <=1 ) print('-Contraints processed!',datetime.datetime.now()) #Maximum time in seconds that the search can go on if a feasible solution #is available and it is not being improved mssi = 1000 #default = inf # specifies maximum number of nodes to be explored in the search tree (default = inf) mn = 40000 #default = 1073741824 # optimize model m within a processing time limit of 'ms' seconds ms = 3000 #default = inf print('-Optimizer start.',datetime.datetime.now()) # executes the optimization #status = m.optimize(max_seconds = ms,max_seconds_same_incumbent = mssi,max_nodes = mn) status = m.optimize(max_seconds = ms , max_seconds_same_incumbent = mssi) final_obj = m.objective_value print('Opt. Status:',status) print('MIP Sol. Obj.:',final_obj) print('Dual Bound:',m.objective_bound) print('Dual gap:',m.gap) sol = [round(it.x) for it in taken] value = int(final_obj) taken = sol # prepare the solution in the specified output format if status == OptimizationStatus.OPTIMAL: output_data = str(value) + ' ' + str(1) + '\n' output_data += ' '.join(map(str, taken)) elif status == OptimizationStatus.FEASIBLE: output_data = str(value) + ' ' + str(0) + '\n' output_data += ' '.join(map(str, taken)) if item_count == 10000: output_data=greedy(input_data) return output_data
"""Example where a binary program is created and the conflict graph is inspected. """ from itertools import product from sys import stdout as out from mip import Model, BINARY m = m = Model(solver_name="cbc") N = range(1, 7) x = {i: m.add_var(var_type=BINARY, name="x(%d)" % i) for i in N} m += -3 * x[1] + 4 * x[2] - 5 * x[3] + 6 * x[4] + 7 * x[5] + 8 * x[6] <= 2 m += x[1] + x[2] + x[4] >= 1 cg = m.conflict_graph for i, v in product(N, range(2)): out.write("conflicts for x[%d] == %g : " % (i, v)) ca = cg.conflicting_assignments(x[i] == v) for j in ca[0]: out.write("%s == 1 " % j.name) for j in ca[1]: out.write("%s == 0 " % j.name) out.write("\n") # sanity checks confs = {(i, v): cg.conflicting_assignments(x[i] == v) for (i, v) in product(N, range(2))}
from mip import Model, xsum, minimize, INTEGER from os import path import pandas as pd model = Model("Diet") table = path.join(path.dirname(path.abspath(__file__)), 'table.csv') df = pd.read_csv(table) # Variables X = [model.add_var(name=row['name'], var_type=INTEGER, lb=0, ub=row['max_serv']) for i, row in df.iterrows()] def constraint_vars(attr): return (row[attr] * X[i] for i, row in df.iterrows()) # # Objective function # model.objective = minimize(xsum(constraint_vars('price'))) # # Constraints # # Energy model += xsum(constraint_vars('energy')) >= 1000 # Protein model += xsum(constraint_vars('protein')) >= 55 # Calcium model += xsum(constraint_vars('calcium')) >= 800
#!/usr/bin/python # -*- coding: utf-8 -*- """ Simple column generation implementation for a Cutting Stock Problem """ from mip import Model, xsum, Column, CONTINUOUS, INTEGER L = 250 # bar length m = 4 # number of requests w = [187, 119, 74, 90] # size of each item b = [1, 2, 2, 1] # demand for each item # creating master model master = Model() # creating an initial set of patterns which cut one item per bar # to provide the restricted master problem with a feasible solution lambdas = [master.add_var(obj=1, name='lambda_%d' % (j + 1)) for j in range(m)] # creating constraints constraints = [] for i in range(m): constraints.append( master.add_constr(lambdas[i] >= b[i], name='i_%d' % (i + 1))) # creating the pricing problem pricing = Model() # creating pricing variables a = [
def test_cutting_stock(solver: str): n = 10 # maximum number of bars L = 250 # bar length m = 4 # number of requests w = [187, 119, 74, 90] # size of each item b = [1, 2, 2, 1] # demand for each item # creating the model model = Model(solver_name=solver) x = {(i, j): model.add_var(obj=0, var_type=INTEGER, name="x[%d,%d]" % (i, j)) for i in range(m) for j in range(n)} y = { j: model.add_var(obj=1, var_type=BINARY, name="y[%d]" % j) for j in range(n) } # constraints for i in range(m): model.add_constr(xsum(x[i, j] for j in range(n)) >= b[i]) for j in range(n): model.add_constr(xsum(w[i] * x[i, j] for i in range(m)) <= L * y[j]) # additional constraints to reduce symmetry for j in range(1, n): model.add_constr(y[j - 1] >= y[j]) # optimizing the model model.optimize() # sanity tests assert model.status == OptimizationStatus.OPTIMAL assert abs(model.objective_value - 3) <= 1e-4 assert sum(x.x for x in model.vars) >= 5
class LP_MRCPSP(MilpSolver): def __init__(self, rcpsp_model: MultiModeRCPSPModel, lp_solver=LP_RCPSP_Solver.CBC, params_objective_function: ParamsObjectiveFunction=None, **kwargs): self.rcpsp_model = rcpsp_model self.model: Model = None self.lp_solver = CBC if lp_solver == LP_RCPSP_Solver.GRB: self.lp_solver = GRB elif lp_solver == LP_RCPSP_Solver.CBC: self.lp_solver = CBC self.variable_decision = {} self.constraints_dict = {} self.constraints_dict["lns"] = [] self.aggreg_from_sol, self.aggreg_dict, self.params_objective_function = \ build_aggreg_function_and_params_objective(problem=self.rcpsp_model, params_objective_function= params_objective_function) # self.description_variable_description = {} # self.description_constraint = {} def init_model(self, **args): greedy_start = args.get("greedy_start", True) start_solution = args.get("start_solution", None) verbose = args.get("verbose", False) if start_solution is None: if greedy_start: if verbose: print("Computing greedy solution") greedy_solver = PileSolverRCPSP(self.rcpsp_model) store_solution = greedy_solver.solve(greedy_choice=GreedyChoice.MOST_SUCCESSORS) self.start_solution = store_solution.get_best_solution_fit()[0] makespan = self.rcpsp_model.evaluate(self.start_solution)["makespan"] else: if verbose: print("Get dummy solution") solution = self.rcpsp_model.get_dummy_solution() self.start_solution = solution makespan = self.rcpsp_model.evaluate(solution)["makespan"] else: self.start_solution = start_solution makespan = self.rcpsp_model.evaluate(start_solution)["makespan"] # p = [0, 3, 2, 5, 4, 2, 3, 4, 2, 4, 6, 0] sorted_tasks = sorted(self.rcpsp_model.mode_details.keys()) p = [int(max([self.rcpsp_model.mode_details[key][mode]['duration'] for mode in self.rcpsp_model.mode_details[key]])) for key in sorted_tasks] # c = [6, 8] c = [x for x in self.rcpsp_model.resources.values()] renewable = {r: self.rcpsp_model.resources[r] for r in self.rcpsp_model.resources if r not in self.rcpsp_model.non_renewable_resources} non_renewable = {r: self.rcpsp_model.resources[r] for r in self.rcpsp_model.non_renewable_resources} # print('c: ', c) # S = [[0, 1], [0, 2], [0, 3], [1, 4], [1, 5], [2, 9], [2, 10], [3, 8], [4, 6], # [4, 7], [5, 9], [5, 10], [6, 8], [6, 9], [7, 8], [8, 11], [9, 11], [10, 11]] S = [] print('successors: ', self.rcpsp_model.successors) for task in sorted_tasks: for suc in self.rcpsp_model.successors[task]: S.append([task, suc]) # print('S: ', S) (R, self.J, self.T) = (range(len(c)), range(len(p)), range(sum(p))) # we have a better self.T to limit the number of variables : if self.start_solution.rcpsp_schedule_feasible: self.T = range(int(makespan+1)) # model = Model() self.model = Model(sense=MINIMIZE, solver_name=self.lp_solver) self.x: Dict[Var] = {} last_task = max(self.rcpsp_model.mode_details.keys()) variable_per_task = {} for task in sorted_tasks: if task not in variable_per_task: variable_per_task[task] = [] for mode in self.rcpsp_model.mode_details[task]: for t in self.T: self.x[(task, mode, t)] = self.model.add_var(name="x({},{}, {})".format(task, mode, t), var_type=BINARY) variable_per_task[task] += [(task, mode, t)] self.model.objective = xsum(self.x[key] * key[2] for key in variable_per_task[last_task]) for j in variable_per_task: self.model += xsum(self.x[key] for key in variable_per_task[j]) == 1 if isinstance(self.rcpsp_model, RCPSPModelCalendar): renewable_quantity = {r: renewable[r] for r in renewable} else: renewable_quantity = {r: [renewable[r]]*len(self.T) for r in renewable} if isinstance(self.rcpsp_model, RCPSPModelCalendar): non_renewable_quantity = {r: non_renewable[r] for r in non_renewable} else: non_renewable_quantity = {r: [non_renewable[r]]*len(self.T) for r in non_renewable} for (r, t) in product(renewable, self.T): self.model.add_constr(xsum(int(self.rcpsp_model.mode_details[key[0]][key[1]][r]) * self.x[key] for key in self.x if key[2] <= t < key[2]+int(self.rcpsp_model.mode_details[key[0]][key[1]]["duration"])) <= renewable_quantity[r][t]) print(r, t) for r in non_renewable: self.model.add_constr(xsum(int(self.rcpsp_model.mode_details[key[0]][key[1]][r]) * self.x[key] for key in self.x) <= non_renewable_quantity[r][0]) durations = {j: self.model.add_var(name="duration_"+str(j), var_type=INTEGER) for j in variable_per_task} self.durations = durations self.variable_per_task = variable_per_task for j in variable_per_task: self.model.add_constr(xsum(self.rcpsp_model.mode_details[key[0]][key[1]]["duration"]*self.x[key] for key in variable_per_task[j]) == durations[j]) for (j, s) in S: self.model.add_constr(xsum([key[2] * self.x[key] for key in variable_per_task[s]] + [- key[2] * self.x[key] for key in variable_per_task[j]]) >= durations[j]) start = [] for j in self.start_solution.rcpsp_schedule: start_time_j = self.start_solution.rcpsp_schedule[j]["start_time"] mode_j = 1 if j == 1 or j == self.rcpsp_model.n_jobs + 2 else self.start_solution.rcpsp_modes[j - 2] start += [(self.durations[j], self.rcpsp_model.mode_details[j][mode_j]["duration"])] for k in self.variable_per_task[j]: task, mode, time = k if start_time_j == time and mode == mode_j: start += [(self.x[k], 1)] else: start += [(self.x[k], 0)] self.model.start = start p_s: Union[PartialSolution, None] = args.get("partial_solution", None) self.constraints_partial_solutions = [] if p_s is not None: constraints = [] if p_s.start_times is not None: for task in p_s.start_times: constraints += [self.model.add_constr(xsum([self.x[k] for k in self.variable_per_task[task] if k[2] == p_s.start_times[task]]) == 1)] if p_s.partial_permutation is not None: for t1, t2 in zip(p_s.partial_permutation[:-1], p_s.partial_permutation[1:]): constraints += [self.model.add_constr(xsum([key[2] * self.x[key] for key in variable_per_task[t1]] + [- key[2] * self.x[key] for key in variable_per_task[t2]]) <= 0)] if p_s.list_partial_order is not None: for l in p_s.list_partial_order: for t1, t2 in zip(l[:-1], l[1:]): constraints += [self.model.add_constr(xsum([key[2] * self.x[key] for key in variable_per_task[t1]] + [- key[2] * self.x[key] for key in variable_per_task[t2]]) <= 0)] self.constraints_partial_solutions = constraints print('Partial solution constraints : ', self.constraints_partial_solutions) def retrieve_solutions(self, parameters_milp: ParametersMilp) -> ResultStorage: retrieve_all_solution = parameters_milp.retrieve_all_solution nb_solutions_max = parameters_milp.n_solutions_max nb_solution = min(nb_solutions_max, self.model.num_solutions) if not retrieve_all_solution: nb_solution = 1 list_solution_fits = [] print(nb_solution, " solutions found") for s in range(nb_solution): rcpsp_schedule = {} modes = {} objective = self.model.objective_values[s] for (task, mode, t) in self.x: value = self.x[(task, mode, t)].xi(s) if value >= 0.5: rcpsp_schedule[task] = {'start_time': t, 'end_time': t + self.rcpsp_model.mode_details[task][mode]['duration']} modes[task] = mode print("Size schedule : ", len(rcpsp_schedule.keys())) try: modes.pop(1) modes.pop(self.rcpsp_model.n_jobs+2) modes_vec = [modes[k] for k in sorted(modes)] solution = RCPSPSolution(problem=self.rcpsp_model, rcpsp_schedule=rcpsp_schedule, rcpsp_modes=modes_vec, rcpsp_schedule_feasible=True) fit = self.aggreg_from_sol(solution) list_solution_fits += [(solution, fit)] except: pass return ResultStorage(list_solution_fits=list_solution_fits, best_solution=min(list_solution_fits, key=lambda x: x[1])[0], mode_optim=self.params_objective_function.sense_function) def solve(self, parameters_milp: ParametersMilp=ParametersMilp.default(), **kwargs)->ResultStorage: if self.model is None: self.init_model(greedy_start=False, **kwargs) limit_time_s = parameters_milp.TimeLimit self.model.sol_pool_size = parameters_milp.PoolSolutions self.model.max_mip_gap_abs = parameters_milp.MIPGapAbs self.model.max_mip_gap = parameters_milp.MIPGap self.model.optimize(max_seconds=limit_time_s, max_solutions=parameters_milp.n_solutions_max) return self.retrieve_solutions(parameters_milp)
timeLimit = int(argv[2]) threads = int(argv[3]) useCuts = int(argv[4]) useLazy = int(argv[5]) useHeur = int(argv[6]) start = time() inst = tsplib95.load_problem(argv[1]) V = [n - 1 for n in inst.get_nodes()] n, c = len(V), [[0.0 for j in V] for i in V] for (i, j) in product(V, V): if i != j: c[i][j] = inst.wfunc(i + 1, j + 1) model = Model() # binary variables indicating if arc (i,j) is used on the route or not x = [[model.add_var(var_type=BINARY, name='x(%d,%d)' % (i, j)) for j in V] for i in V] # continuous variable to prevent subtours: each city will have a # different sequential id in the planned route except the first one y = [model.add_var(name='y(%d)' % i) for i in V] # objective function: minimize the distance model.objective = minimize(xsum(c[i][j] * x[i][j] for i in V for j in V)) # constraint : leave each city only once for i in V: model += xsum(x[i][j] for j in set(V) - {i}) == 1
def init_model(self, **args): greedy_start = args.get("greedy_start", True) start_solution = args.get("start_solution", None) verbose = args.get("verbose", False) if start_solution is None: if greedy_start: if verbose: print("Computing greedy solution") greedy_solver = PileSolverRCPSP(self.rcpsp_model) store_solution = greedy_solver.solve(greedy_choice=GreedyChoice.MOST_SUCCESSORS) self.start_solution = store_solution.get_best_solution_fit()[0] makespan = self.rcpsp_model.evaluate(self.start_solution)["makespan"] else: if verbose: print("Get dummy solution") solution = self.rcpsp_model.get_dummy_solution() self.start_solution = solution makespan = self.rcpsp_model.evaluate(solution)["makespan"] else: self.start_solution = start_solution makespan = self.rcpsp_model.evaluate(start_solution)["makespan"] # p = [0, 3, 2, 5, 4, 2, 3, 4, 2, 4, 6, 0] sorted_tasks = sorted(self.rcpsp_model.mode_details.keys()) p = [int(max([self.rcpsp_model.mode_details[key][mode]['duration'] for mode in self.rcpsp_model.mode_details[key]])) for key in sorted_tasks] # c = [6, 8] c = [x for x in self.rcpsp_model.resources.values()] renewable = {r: self.rcpsp_model.resources[r] for r in self.rcpsp_model.resources if r not in self.rcpsp_model.non_renewable_resources} non_renewable = {r: self.rcpsp_model.resources[r] for r in self.rcpsp_model.non_renewable_resources} # print('c: ', c) # S = [[0, 1], [0, 2], [0, 3], [1, 4], [1, 5], [2, 9], [2, 10], [3, 8], [4, 6], # [4, 7], [5, 9], [5, 10], [6, 8], [6, 9], [7, 8], [8, 11], [9, 11], [10, 11]] S = [] print('successors: ', self.rcpsp_model.successors) for task in sorted_tasks: for suc in self.rcpsp_model.successors[task]: S.append([task, suc]) # print('S: ', S) (R, self.J, self.T) = (range(len(c)), range(len(p)), range(sum(p))) # we have a better self.T to limit the number of variables : if self.start_solution.rcpsp_schedule_feasible: self.T = range(int(makespan+1)) # model = Model() self.model = Model(sense=MINIMIZE, solver_name=self.lp_solver) self.x: Dict[Var] = {} last_task = max(self.rcpsp_model.mode_details.keys()) variable_per_task = {} for task in sorted_tasks: if task not in variable_per_task: variable_per_task[task] = [] for mode in self.rcpsp_model.mode_details[task]: for t in self.T: self.x[(task, mode, t)] = self.model.add_var(name="x({},{}, {})".format(task, mode, t), var_type=BINARY) variable_per_task[task] += [(task, mode, t)] self.model.objective = xsum(self.x[key] * key[2] for key in variable_per_task[last_task]) for j in variable_per_task: self.model += xsum(self.x[key] for key in variable_per_task[j]) == 1 if isinstance(self.rcpsp_model, RCPSPModelCalendar): renewable_quantity = {r: renewable[r] for r in renewable} else: renewable_quantity = {r: [renewable[r]]*len(self.T) for r in renewable} if isinstance(self.rcpsp_model, RCPSPModelCalendar): non_renewable_quantity = {r: non_renewable[r] for r in non_renewable} else: non_renewable_quantity = {r: [non_renewable[r]]*len(self.T) for r in non_renewable} for (r, t) in product(renewable, self.T): self.model.add_constr(xsum(int(self.rcpsp_model.mode_details[key[0]][key[1]][r]) * self.x[key] for key in self.x if key[2] <= t < key[2]+int(self.rcpsp_model.mode_details[key[0]][key[1]]["duration"])) <= renewable_quantity[r][t]) print(r, t) for r in non_renewable: self.model.add_constr(xsum(int(self.rcpsp_model.mode_details[key[0]][key[1]][r]) * self.x[key] for key in self.x) <= non_renewable_quantity[r][0]) durations = {j: self.model.add_var(name="duration_"+str(j), var_type=INTEGER) for j in variable_per_task} self.durations = durations self.variable_per_task = variable_per_task for j in variable_per_task: self.model.add_constr(xsum(self.rcpsp_model.mode_details[key[0]][key[1]]["duration"]*self.x[key] for key in variable_per_task[j]) == durations[j]) for (j, s) in S: self.model.add_constr(xsum([key[2] * self.x[key] for key in variable_per_task[s]] + [- key[2] * self.x[key] for key in variable_per_task[j]]) >= durations[j]) start = [] for j in self.start_solution.rcpsp_schedule: start_time_j = self.start_solution.rcpsp_schedule[j]["start_time"] mode_j = 1 if j == 1 or j == self.rcpsp_model.n_jobs + 2 else self.start_solution.rcpsp_modes[j - 2] start += [(self.durations[j], self.rcpsp_model.mode_details[j][mode_j]["duration"])] for k in self.variable_per_task[j]: task, mode, time = k if start_time_j == time and mode == mode_j: start += [(self.x[k], 1)] else: start += [(self.x[k], 0)] self.model.start = start p_s: Union[PartialSolution, None] = args.get("partial_solution", None) self.constraints_partial_solutions = [] if p_s is not None: constraints = [] if p_s.start_times is not None: for task in p_s.start_times: constraints += [self.model.add_constr(xsum([self.x[k] for k in self.variable_per_task[task] if k[2] == p_s.start_times[task]]) == 1)] if p_s.partial_permutation is not None: for t1, t2 in zip(p_s.partial_permutation[:-1], p_s.partial_permutation[1:]): constraints += [self.model.add_constr(xsum([key[2] * self.x[key] for key in variable_per_task[t1]] + [- key[2] * self.x[key] for key in variable_per_task[t2]]) <= 0)] if p_s.list_partial_order is not None: for l in p_s.list_partial_order: for t1, t2 in zip(l[:-1], l[1:]): constraints += [self.model.add_constr(xsum([key[2] * self.x[key] for key in variable_per_task[t1]] + [- key[2] * self.x[key] for key in variable_per_task[t2]]) <= 0)] self.constraints_partial_solutions = constraints print('Partial solution constraints : ', self.constraints_partial_solutions)
def create_model(graph: DepGraph_sat.DepGraph, obj_parameter_list): model = Model() for k in graph.depItemDict: item = graph.depItemDict[k] item.var = model.add_var(var_type=BINARY, name=item.varName) for k in graph.depItemDict: item = graph.depItemDict[k] if item.packageName == 'ROOT': model += item.var == 1 for group in item.depGroups: model += xsum(x.var for x in group.items) >= item.var packageDict = {} for k in graph.depItemDict: item = graph.depItemDict[k] if item.packageName not in packageDict: packageDict[item.packageName] = [] packageDict[item.packageName].append(item) for packageName in packageDict: model += xsum(x.var for x in packageDict[packageName]) <= 1 # 减少直接依赖跨越大版本 developers prefer fewer dependency upgrades/downgrades crossing their major versions obj1_item_var_list = [] for g in graph.depItemDict['ROOT'].depGroups: for item in g.items[1:]: if major_version(g.items[0].version, item.version) == True: obj1_item_var_list.append(item.var) ROOT_items_name_lists = ['ROOT'] for g in graph.depItemDict['ROOT'].depGroups: ROOT_items_name_lists.append(g.packageName) for k in graph.depItemDict: item_k = graph.depItemDict[k] if item_k.packageName not in ROOT_items_name_lists: model += xsum( graph.depItemDict[j].var * is_lower_limit(graph.depItemDict[j].depGroups, item_k) for j in graph.depItemDict) >= item_k.var # 直接依赖相同大版本的个数 obj1 = xsum(k for k in obj1_item_var_list) # 是否为直接依赖及原有版本 Encourage to keep direct dependencies’ versions unchanged # # 直接依赖原有版本的个数 # obj2 = xsum(g.items[0].var for g in graph.depItemDict['ROOT'].depGroups) # 直接依赖升级版本的个数 obj2 = xsum(g_items.var * update_version_status(g_items.version, g.items[0].version) for g in graph.depItemDict['ROOT'].depGroups for g_items in g.items) # 直接依赖降级版本的个数 obj3 = xsum(g_items.var * download_version_status(g_items.version, g.items[0].version) for g in graph.depItemDict['ROOT'].depGroups for g_items in g.items) # 减少引入的依赖包 developers prefer to introduce fewer packages in project’s dependency graph # 引入包的总个数 obj4 = xsum(graph.depItemDict[k].var for k in graph.depItemDict) new_obj1 = obj_parameter_list[0] * obj1 new_obj2 = obj_parameter_list[1] * obj2 new_obj3 = obj_parameter_list[2] * obj3 new_obj4 = obj_parameter_list[3] * obj4 model.objective = maximize(new_obj1 - new_obj2 - new_obj3 - new_obj4) # model.objective = minimize(new_obj1 - new_obj2 - new_obj3 - new_obj4) return model
def init_model(self, **args): greedy_start = args.get("greedy_start", True) start_solution = args.get("start_solution", None) verbose = args.get("verbose", False) if start_solution is None: if greedy_start: if verbose: print("Computing greedy solution") greedy_solver = PileSolverRCPSP(self.rcpsp_model) store_solution = greedy_solver.solve(greedy_choice=GreedyChoice.MOST_SUCCESSORS) self.start_solution = store_solution.get_best_solution_fit()[0] makespan = self.rcpsp_model.evaluate(self.start_solution)["makespan"] else: if verbose: print("Get dummy solution") solution = self.rcpsp_model.get_dummy_solution() self.start_solution = solution makespan = self.rcpsp_model.evaluate(solution)["makespan"] else: self.start_solution = start_solution makespan = self.rcpsp_model.evaluate(start_solution)["makespan"] # p = [0, 3, 2, 5, 4, 2, 3, 4, 2, 4, 6, 0] sorted_tasks = sorted(self.rcpsp_model.mode_details.keys()) print(sorted_tasks) p = [int(self.rcpsp_model.mode_details[key][1]['duration']) for key in sorted_tasks] # print('p:', p) # u = [[0, 0], [5, 1], [0, 4], [1, 4], [1, 3], [3, 2], [3, 1], [2, 4], # [4, 0], [5, 2], [2, 5], [0, 0]] u = [] for task in sorted_tasks: tmp = [] for r in self.rcpsp_model.resources.keys(): tmp.append(self.rcpsp_model.mode_details[task][1][r]) u.append(tmp) # print('u: ', u) # c = [6, 8] c = [x for x in self.rcpsp_model.resources.values()] # print('c: ', c) # S = [[0, 1], [0, 2], [0, 3], [1, 4], [1, 5], [2, 9], [2, 10], [3, 8], [4, 6], # [4, 7], [5, 9], [5, 10], [6, 8], [6, 9], [7, 8], [8, 11], [9, 11], [10, 11]] S = [] print('successors: ', self.rcpsp_model.successors) for task in sorted_tasks: for suc in self.rcpsp_model.successors[task]: S.append([task-1, suc-1]) # print('S: ', S) (R, self.J, self.T) = (range(len(c)), range(len(p)), range(sum(p))) # we have a better self.T to limit the number of variables : self.T = range(int(makespan+1)) # model = Model() self.model = Model(sense=MINIMIZE, solver_name=self.lp_solver) self.x: List[List[Var]] = [[self.model.add_var(name="x({},{})".format(j, t), var_type=BINARY) for t in self.T] for j in self.J] self.model.objective = xsum(self.x[len(self.J) - 1][t] * t for t in self.T) for j in self.J: self.model += xsum(self.x[j][t] for t in self.T) == 1 for (r, t) in product(R, self.T): self.model += ( xsum(u[j][r] * self.x[j][t2] for j in self.J for t2 in range(max(0, t - p[j] + 1), t + 1)) <= c[r]) for (j, s) in S: self.model += xsum(t * self.x[s][t] - t * self.x[j][t] for t in self.T) >= p[j] start = [] for j in self.J: for t in self.T: if self.start_solution.rcpsp_schedule[j+1]["start_time"] == t: start += [(self.x[j][t], 1)] else: start += [(self.x[j][t], 0)] self.model.start = start p_s: Union[PartialSolution, None] = args.get("partial_solution", None) self.constraints_partial_solutions = [] if p_s is not None: constraints = [] if p_s.start_times is not None: for task in p_s.start_times: constraints += [self.model.add_constr(xsum([j*self.x[task-1][j] for j in range(len(self.x[task-1]))]) == p_s.start_times[task])] constraints += [self.model.add_constr(self.x[task-1][p_s.start_times[task]] == 1)] if p_s.partial_permutation is not None: for t1, t2 in zip(p_s.partial_permutation[:-1], p_s.partial_permutation[1:]): constraints += [self.model.add_constr(xsum([t * self.x[t1-1][t]-t*self.x[t2-1][t] for t in self.T]) <= 0)] if p_s.list_partial_order is not None: for l in p_s.list_partial_order: for t1, t2 in zip(l[:-1], l[1:]): constraints += [self.model.add_constr(xsum([t * self.x[t1-1][t]-t*self.x[t2-1][t] for t in self.T]) <= 0)] self.starts = {} for j in range(len(self.x)): self.starts[j] = self.model.add_var(name="start_" + str(j), lb=0, ub=makespan) self.model.add_constr(xsum(t * self.x[j][t] for t in self.T) == self.starts[j]) if p_s.start_at_end is not None: for i, j in p_s.start_at_end: constraints += [self.model.add_constr(self.starts[j-1] == self.starts[i-1]+p[i-1])] if p_s.start_together is not None: for i, j in p_s.start_together: constraints += [self.model.add_constr(self.starts[j-1] == self.starts[i-1])] if p_s.start_after_nunit is not None: for t1, t2, delta in p_s.start_after_nunit: constraints += [self.model.add_constr(self.starts[t2-1] >= self.starts[t1-1]+delta)] if p_s.start_at_end_plus_offset is not None: for t1, t2, delta in p_s.start_at_end_plus_offset: constraints += [self.model.add_constr(self.starts[t2-1] >= self.starts[t1-1]+delta+p[t1-1])] self.constraints_partial_solutions = constraints
places = [([i+1 for i in range(29)])] # distances in an upper triangular matrix e = ExampleMatrix() dists = e.getTriangularMatrix() # number of nodes and list of vertices n, V = len(dists), set(range(len(dists))) # distances matrix c = [[0 if i == j else dists[i][j-i-1] if j > i else dists[j][i-j-1] for j in V] for i in V] model = Model() # binary variables indicating if arc (i,j) is used on the route or not x = [[model.add_var(var_type=BINARY) for j in V] for i in V] # continuous variable to prevent subtours: each city will have a # different sequential id in the planned route except the first one y = [model.add_var() for i in V] # objective function: minimize the distance model.objective = minimize(xsum(c[i][j]*x[i][j] for i in V for j in V)) # constraint : leave each city only once for i in V: model += xsum(x[i][j] for j in V - {i}) == 1
def optimize_operation_HWHS(self, number=96, tank_size=3000, ele_capacity=14, save=False, linearization=False, objective=0, *args, **kwargs): '''Operational optimization with regard to different objective function. :param file: :param linearization: True or false :param number: determine the time interval :param tank_size: kg :param ele_capacity: MW :param save: save excel or not? Bool :param objective: 0 for maximal profits :param args: reserved :param kwargs: a dictionary containing random variables. :return: ''' p_w_t = kwargs['wind_power'] pi_t = kwargs['price'] p_l_t = kwargs['power_load'] m_l_h2_t = kwargs['hydrogen_load'] # marginal cost C_m_ele = 20.5 / 2 * 18 * 0.063 * 0.13 # Euros/MWh 1MWh electricity->20.5kg H2 -> # 20.5/2 kmol H2 -> 20.5/2 kmol H2O -> 20.5/2*18 kg H2O -> 0.063DKK/kg H2O C_m_comp = 3600 / 3.221 * 0.004 h2_price = 2 ''' In fact, we need to do linearization every time when we start a new optimization, which means a new supper limit. However, it is very time-consuming, so I decide to do it at only one point to accelerate calculation. ''' if linearization == True: self.ele_breaks[-1] = 20 self.ele_f_breaks[-1] = self.k3_e * 20 + self.b3_e self.con_breaks[-1] = 20 self.con_f_breaks[-1] = self.k3_c * 20 + self.b3_c ''' According to "Hydrogen Station Compression, Storage, and Dispensing Technical Status and Costs: Systems Integration", compressor that impoves hydrogen pressure to 350bar gives an additional cost to hydrogen as $0.14/kg, provided the electricity cost is 1.6kWh/kg and power price is $0.085/kWh. Thus it can be infered that the addtional cost without electricity payment is 0.14-0.085*1.6 = 0.004$/kg ''' # define MILP model if objective == 0 or objective == 1: GLS_milp_model = Model('GLS', sense=MAXIMIZE) else: GLS_milp_model = Model('GLS', sense=MINIMIZE) # ------------------------------------------ADD VARIABLES-------------------------------------- power_utility = [ GLS_milp_model.add_var(lb=-100, ub=100, var_type='C') for i in range(number) ] hydrogen_level = [ GLS_milp_model.add_var(lb=0, ub=tank_size, var_type='C') for i in range(number) ] # kg power_ele = [ GLS_milp_model.add_var(lb=0, ub=ele_capacity, var_type='C') for i in range(number) ] power_comp = [ GLS_milp_model.add_var(lb=0, ub=100, var_type='C') for i in range(number) ] power_converter = [ GLS_milp_model.add_var(lb=0, ub=100, var_type='C') for i in range(number) ] # variables that are only used in objective one. We need a new variable to indicate green hydrogen power_ele_g = [ GLS_milp_model.add_var(lb=0, ub=ele_capacity, var_type='C') for _ in range(number) ] if linearization == True: # Indicating which piece the electrolyser power falls in ele_z = [] for i in range(3): ele_z.append([ GLS_milp_model.add_var(var_type='B') for _ in range(number) ]) # weight ele_w = [] for i in range(4): ele_w.append([ GLS_milp_model.add_var(lb=0, var_type='C') for _ in range(number) ]) # Indicating which piece the converter input power falls in con_z = [] for i in range(3): con_z.append([ GLS_milp_model.add_var(var_type='B') for _ in range(number) ]) # weight con_w = [] for i in range(4): con_w.append([ GLS_milp_model.add_var(lb=0, var_type='C') for _ in range(number) ]) # ------------------------------------OBJECTIVE FUNCTION----------------------------------- Mh2_ini = 1000 # initial amount of hydrogen stored in the tank if objective == 0: # Maxmize the profits GLS_milp_model.objective = xsum( (power_utility[i] * pi_t[i] + p_l_t[i] * pi_t[i] + m_l_h2_t[i] * h2_price - power_ele[i] * C_m_ele - power_comp[i] * C_m_comp) * self.time_span for i in range(number)) elif objective == 1: # Maxmize percentage of green hydrogen GLS_milp_model.objective = xsum( power_ele_g[i] * 20.5 for i in range(number)) / sum(m_l_h2_t) elif objective == 2: # Maxmize efficiency GLS_milp_model.objective = xsum( power_ele[i] * self.time_span * 3600 for i in range(number)) / (sum(m_l_h2_t) * self.time_span * 142) # HHV of H2 is 142MJ/kg # In this situation, the hydrogen production efficiency remains unchanged # and we can claim that a relationship between h2 production rate and electrolyser power is imperative. pass # --------------------------------------CONSTRAINS------------------------------------------ # electrolyser power if linearization == True: for t in range(number): GLS_milp_model += power_ele[t] == xsum( ele_w[i][t] * self.ele_breaks[i] for i in range(4)) GLS_milp_model += xsum(ele_z[i][t] for i in range(3)) == 1 GLS_milp_model += xsum(ele_w[i][t] for i in range(4)) == 1 GLS_milp_model += ele_w[0][t] <= ele_z[0][t] GLS_milp_model += ele_w[1][t] <= ele_z[0][t] + ele_z[1][t] GLS_milp_model += ele_w[2][t] <= ele_z[1][t] + ele_z[2][t] GLS_milp_model += ele_w[3][t] <= ele_z[2][t] GLS_milp_model += power_converter[t] == xsum( con_w[i][t] * self.con_breaks[i] for i in range(4)) GLS_milp_model += xsum(con_z[i][t] for i in range(3)) == 1 GLS_milp_model += xsum(con_w[i][t] for i in range(4)) == 1 GLS_milp_model += con_w[0][t] <= con_z[0][t] GLS_milp_model += con_w[1][t] <= con_z[0][t] + con_z[1][t] GLS_milp_model += con_w[2][t] <= con_z[1][t] + con_z[2][t] GLS_milp_model += con_w[3][t] <= con_z[2][t] # The constrain between electrolyser power and converter power GLS_milp_model += power_ele[t] == xsum( con_w[i][t] * self.con_f_breaks[i] for i in range(4)) # Green hydrogen are those produced by wind energy for t in range(number): GLS_milp_model += power_ele_g[t] <= power_ele[t] GLS_milp_model += power_ele_g[t] <= p_w_t[t] # energy conservation if linearization: for t in range(number): GLS_milp_model += p_w_t[t] - power_utility[t] - p_l_t[ t] - power_comp[t] - power_converter[t] == 0 pass else: for t in range(number): GLS_milp_model += p_w_t[t] - power_utility[t] - p_l_t[ t] - power_comp[t] - power_converter[t] == 0 pass # electrolyser ramping rate limit RLU = 10 RLD = 10 for t in range(number): if t == 0: GLS_milp_model += power_ele[t] - 0 <= RLU GLS_milp_model += power_ele[t] - 0 >= -RLD else: GLS_milp_model += power_ele[t] - power_ele[t - 1] <= RLU GLS_milp_model += power_ele[t] - power_ele[t - 1] >= -RLD # relation between compressor power and electrolyser power for t in range(number): power_comp[t] = power_ele[ t] * 20.5 / 3600 * 1e3 * 3221 / 1e6 # MW, unit conversion # regrading hydrogen tank if linearization == True: for t in range(number): if t == 0: GLS_milp_model += hydrogen_level[t] - Mh2_ini == ( xsum(self.ele_f_breaks[i] * ele_w[i][t] for i in range(4)) - m_l_h2_t[t]) * self.time_span else: GLS_milp_model += hydrogen_level[t] - hydrogen_level[ t - 1] == (xsum(self.ele_f_breaks[i] * ele_w[i][t] for i in range(4)) - m_l_h2_t[t]) * self.time_span else: # Assuming conversion rate of electrolyser is constant, 20.5kg/MWh for t in range(number): if t == 0: GLS_milp_model += hydrogen_level[t] - Mh2_ini == ( power_ele[t] * 20.5 - m_l_h2_t[t]) * self.time_span else: GLS_milp_model += hydrogen_level[t] - hydrogen_level[ t - 1] == (power_ele[t] * 20.5 - m_l_h2_t[t]) * self.time_span GLS_milp_model += hydrogen_level[-1] == Mh2_ini # ---------------------------------------End constrains------------------------------------ # optimize GLS_milp_model.optimize() # ---------------------------------------SAVE RESULTS--------------------------------------- if GLS_milp_model.status.name != 'INFEASIBLE': res_dict = { 'Time': [i * self.time_span for i in range(number)], 'Price': pi_t, 'Power to utility grid': [round(power_utility[i].x, 2) for i in range(number)], 'Converter power': [round(power_converter[i].x) for i in range(number)], 'Electrolyser power': [round(power_ele[i].x, 2) for i in range(number)], 'Compressor power': [round(power_comp[i].x, 2) for i in range(number)], 'Wind power': p_w_t.round(2), 'Hydrogen level': [round(hydrogen_level[i].x) for i in range(number)], 'Green Electrolyser(only valid in object 1)': [round(power_ele_g[i].x, 2) for i in range(number)] } if linearization == True: res_dict['mh2'] = [ xsum(self.ele_f_breaks[i] * ele_w[i][t] for i in range(4)).x for t in range(number) ] else: res_dict['mh2'] = [ round(power_ele[t].x, 2) * 20.5 for t in range(number) ] # -------------------------------------Daily profits--------------------------------------- DP = np.sum([ (res_dict['Power to utility grid'][i] * res_dict['Price'][i] + res_dict['mh2'][i] * h2_price + p_l_t[i] * res_dict['Price'][i] - res_dict['Electrolyser power'][i] * C_m_ele - res_dict['Compressor power'][i] * C_m_comp) * self.time_span for i in range(number) ]) DP = round(DP, 2) # Green hydrogen proportion GH2P = np.sum([min(res_dict['Electrolyser power'][i], res_dict['Wind power'][i]) for i in range(number)]) \ / np.sum(res_dict['Electrolyser power']) GH2P = round(GH2P, 2) # CR = sum(m_l_h2_t) * 142 / ( np.sum(res_dict['Electrolyser power']) * 3600) CR = round(CR, 4) else: DP = 0 GH2P = 0 CR = 0 if save == True: assert GLS_milp_model.status.name != 'INFEASIBLE', 'INFEASIBLE' save_choice = { 0: 'Maximal profits_operation_', 1: 'Maximal green hydrogen_operation_', 2: 'Maximal electrolyser efficiency_operation_' } save_choice2 = 'Linearization' if linearization else 'No_linearization' file = save_choice[objective] + save_choice2 Saving_path = Path(Path().absolute() / 'Data' / (file + '.xlsx')) res = pd.DataFrame(res_dict) try: res.to_excel(Saving_path, float_format='%.3f', index=False) print('Successfully saved') except PermissionError: print('File already exists') wb = load_workbook(Saving_path) ws = wb.active ws['R1'].value = 'Total amount of hydrogen/kg' ws['S1'].value = sum(res_dict['mh2']) * self.time_span ws['R2'].value = 'Total electricity consumed/MWh' ws['S2'].value = sum( res_dict['Electrolyser power']) * self.time_span ws['R3'].value = 'Conversion rate of eletrolyser/(kg/MWh)' ws['S3'].value = sum(res_dict['mh2']) / sum( res_dict['Electrolyser power']) wb.save(Saving_path) objective_value = GLS_milp_model.objective.x if GLS_milp_model.status.name != 'INFEASIBLE' else -1e7 print(f'Status:{GLS_milp_model.status.name}') print(f'Optimal value for objective {objective}: {objective_value}') print(f'Daily profits: {DP}') print(f'Green hydrongen proportion: {GH2P}') print(f'Average efficiency of electrolyser:{CR}') self.status = GLS_milp_model.status.name self.objective_value = objective_value self.DP = DP self.GH2P = GH2P self.CR = CR return GLS_milp_model.status.name, objective_value, DP
from mip import Model, xsum, maximize, BINARY p = [10, 13, 18, 31, 7, 15] w = [11, 15, 20, 35, 10, 33] c, I = 47, range(len(w)) m = Model("knapsack") x = [m.add_var(var_type=BINARY) for i in I] m.objective = maximize(xsum(p[i] * x[i] for i in I)) m += xsum(w[i] * x[i] for i in I) <= c m.optimize() selected = [i for i in I if x[i].x >= 0.99] print("selected items: {}".format(selected))
# Normalize all the lists to be the same lengths max_list_length = max(len(QBcost), len(RBcost), len(WRcost), len(TEcost), len(DEFcost)) for i in [QBcost, RBcost, WRcost, TEcost, DEFcost]: for j in range(max_list_length - len(i)): i.append(0) for i in [QBpoints, RBpoints, WRpoints, TEpoints, DEFpoints]: for j in range(max_list_length - len(i)): i.append(0) max_list_length = range(max_list_length) # Initialize the model m = Model("fanduel") # Declare decision variables QB = [m.add_var(var_type=BINARY) for i in max_list_length] RB1 = [m.add_var(var_type=BINARY) for i in max_list_length] RB2 = [m.add_var(var_type=BINARY) for i in max_list_length] WR1 = [m.add_var(var_type=BINARY) for i in max_list_length] WR2 = [m.add_var(var_type=BINARY) for i in max_list_length] WR3 = [m.add_var(var_type=BINARY) for i in max_list_length] TE = [m.add_var(var_type=BINARY) for i in max_list_length] FLEXRB = [m.add_var(var_type=BINARY) for i in max_list_length] FLEXWR = [m.add_var(var_type=BINARY) for i in max_list_length] DEF = [m.add_var(var_type=BINARY) for i in max_list_length] # Objective is to maximize points m.objective = maximize(xsum(QB[i]*QBpoints[i] +
def select_optimal_lineup(point_key, save_name, df): df = df.copy(deep=True) #drop those with missing values for points df = df[~pd.isnull(df[point_key])] #select optimal lineup #num rows n = range(df.shape[0]) #use free solver m = Model(solver_name=CBC) #n binary vars indicating if player is selected or not x = [m.add_var(var_type=BINARY) for i in n] #objective: maximize predicted points for players selected m.objective = maximize( xsum(df[point_key].tolist()[i] * x[i] for i in n)) #salary constraint m += xsum(df['Salary'].tolist()[i] * x[i] for i in n) <= 50000 #position constraints. 1 of each position, 1 extra gaurd, 1 extra forward, 1 utility #pg m += xsum(df['pg'].tolist()[i] * x[i] for i in n) >= 1 m += xsum(df['pg'].tolist()[i] * x[i] for i in n) <= 3 #sg m += xsum(df['sg'].tolist()[i] * x[i] for i in n) >= 1 m += xsum(df['sg'].tolist()[i] * x[i] for i in n) <= 3 #g m += xsum((df['pg'].tolist()[i] + df['sg'].tolist()[i]) * x[i] for i in n) >= 3 #sf m += xsum(df['sf'].tolist()[i] * x[i] for i in n) >= 1 m += xsum(df['sf'].tolist()[i] * x[i] for i in n) <= 3 #pf m += xsum(df['pf'].tolist()[i] * x[i] for i in n) >= 1 m += xsum(df['pf'].tolist()[i] * x[i] for i in n) <= 3 #f m += xsum((df['sf'].tolist()[i] + df['pf'].tolist()[i]) * x[i] for i in n) >= 3 #c m += xsum(df['c'].tolist()[i] * x[i] for i in n) >= 1 m += xsum(df['c'].tolist()[i] * x[i] for i in n) <= 2 #total m += xsum(x[i] for i in n) == 8 #player constraints - players appear only once for player in player_var_list: m += xsum(df[player].tolist()[i] * x[i] for i in n) <= 1, '{}'.format(player) #optimize m.optimize() #save copy of optimal lineup as record names = [df['Name'].to_list()[i] for i in n if x[i].x >= 0.99] points = [df[point_key].to_list()[i] for i in n if x[i].x >= 0.99] with open( "export/lineups/lineup_{}_{}.csv".format( save_name, date.today()), "w") as f: f.write("name,points\n") for i in range(len(names)): f.write("{},{}\n".format(names[i], points[i])) f.close() #order list of ids to conform with DK template #PG,SG,SF,PF,C,G,F,UTIL final_pos_list = [0 for i in range(8)] for pos in ["pg", "sg", "sf", "pf", "c"]: position_list = [ df['ID'].to_list()[i] for i in n if x[i].x >= 0.99 and df[pos].to_list()[i] == 1 ] if pos == "pg": final_pos_list[0] = position_list[0] elif pos == "sg": final_pos_list[1] = position_list[0] elif pos == "sf": final_pos_list[2] = position_list[0] elif pos == "pf": final_pos_list[3] = position_list[0] elif pos == "c": final_pos_list[4] = position_list[0] if len(position_list) >= 2: if (pos in ["pg", "sg"]) and final_pos_list[5] == 0: final_pos_list[5] = position_list[1] elif pos in ["sf", "pf"] and final_pos_list[6] == 0: final_pos_list[6] = position_list[1] elif pos == "c": final_pos_list[7] = position_list[1] else: final_pos_list[7] = position_list[1] if len(position_list) == 3: final_pos_list[7] = position_list[2] #write template to .csv file #PG,SG,SF,PF,C,G,F,UTIL with open( "export/for_upload/lineup_{}_{}.csv".format( save_name, date.today()), "w") as f: f.write("PG,SG,SF,PF,C,G,F,UTIL\n") for pos in final_pos_list: f.write("{}".format(pos)) if pos != final_pos_list[len(final_pos_list) - 1]: f.write(",") f.close()
from prettytable import PrettyTable # packages awaiting shipment priorities = [ 1, 0, 0, 1, 0, 0, 0, 1] volumes = [40, 25, 130, 180, 70, 200, 35, 90] weights = [60, 120, 210, 240, 100, 320, 90, 150] # Priority packages names_p = [i for i in range(len(priorities)) if priorities[i] == 1] w_p = [weights[i] for i in range(len(priorities)) if priorities[i] == 1] v_p = [volumes[i] for i in range(len(priorities)) if priorities[i] == 1] volume_p = 325 weight_p = 750 I = range(len(w_p)) m = Model("priority") x_p = [m.add_var(var_type=BINARY) for i in I] m.objective = maximize(xsum(x_p[i] for i in I)) m += xsum(v_p[i] * x_p[i] for i in I) <= volume_p m += xsum(w_p[i] * x_p[i] for i in I) <= weight_p m.optimize() selected_p = [i for i in I if x_p[i].x >= 0.99] selected_p_names = [names_p[i]+1 for i in selected_p] print("selected priority packages: {}".format(selected_p_names)) # LEFTOVERS CALCULATION
def main(): spreadsheet_file = pd.ExcelFile('../data.xlsx') worksheets = spreadsheet_file.sheet_names print("all the worksheets ", worksheets) # In[4]: island_coordinates = [] storm_coordinates_radius = [] road_material = {} materialToCost = {"Asphalt": 100, "Concrete": 65, "Gravel": 35} road_time = {} time_matrix = [] print("extracting data...") locationDF = pd.read_excel('data.xlsx', sheet_name="Locations", header=None, skiprows=1) for index, row in locationDF.iterrows(): # print("++" ,type(row[1])) island_coordinates.append((row[1], row[2])) stormDF = pd.read_excel('data.xlsx', sheet_name="Storms", header=None, skiprows=2) for index, row in stormDF.iterrows(): storm_coordinates_radius.append([row[0], row[1], row[2]]) roadMaterialDF = pd.read_excel('data.xlsx', sheet_name="Road Material", header=None, skiprows=1) for index, row in roadMaterialDF.iterrows(): key = f'{row[0]} {row[1]}' value = row[2] road_material[key] = value print("extracting data is done.") # In[5]: print(island_coordinates) print(len(island_coordinates)) # In[6]: print(storm_coordinates_radius) print(len(storm_coordinates_radius)) # In[7]: print("\npreprocessing...") for i in range(len(island_coordinates)): time_matrix.append([]) for j in range(len(island_coordinates)): if i == j: time_matrix[i].append(0) else: island1 = island_coordinates[i] island2 = island_coordinates[j] distance = calculateDistance(island1[0], island1[1], island2[0], island2[1]) roadType = road_material[f'{i + 1} {j + 1}'] time_matrix[i].append(distance / materialToCost[roadType]) # print(time_matrix) dists = [] for i in range(len(island_coordinates)): dists.append([]) for j in range(i + 1, len(island_coordinates)): island1 = island_coordinates[i] island2 = island_coordinates[j] distance = calculateDistance(island1[0], island1[1], island2[0], island2[1]) roadType = road_material[f'{i + 1} {j + 1}'] dists[i].append(distance / materialToCost[roadType]) storms = [] for i in range(len(island_coordinates)): storms.append([]) for j in range(len(island_coordinates)): island1 = island_coordinates[i] island2 = island_coordinates[j] is_stormy = False for k in range(len(storm_coordinates_radius)): if i == j: storms[i].append(0) break else: island1 = island_coordinates[i] island2 = island_coordinates[j] stormInfo = storm_coordinates_radius[k] cx, cy, cradius = stormInfo[0], stormInfo[1], stormInfo[2] if storm_check(island1[0], island1[1], island2[0], island2[1], cx, cy, cradius): # print("--- Storm #", k + 1, " found between island ", i + 1, " and island ", j + 1) is_stormy = True storms[i].append(0) break if i != j and not is_stormy: storms[i].append(1) for i in range(len(storms)): if len(storms) != len(storms[i]): print("?") print(storms) print(storms[29][29]) print("preprocessing is done.") # In[ ]: places = [f'island {i}' for i in range(1, 31)] n, V = len(dists), set(range(len(dists))) model = Model() # binary variables indicating if arc (i,j) is used on the route or not x = [[model.add_var(var_type=BINARY) for j in V] for i in V] # continuous variable to prevent subtours: each city will have a # different sequential id in the planned route except the first one y = [model.add_var() for i in V] # objective function: minimize the distance model.objective = minimize( xsum(time_matrix[i][j] * x[i][j] for i in V for j in V)) # constraint : leave each city only once for i in V: model += xsum(x[i][j] for j in V - {i}) == 1 # constraint : enter each city only once for i in V: model += xsum(x[j][i] for j in V - {i}) == 1 # constraint : storm for i in range(n): for j in range(n): model += (x[i][j] * storms[i][j] == x[i][j]) # subtour elimination for (i, j) in product(V - {0}, V - {0}): if i != j: model += y[i] - (n + 1) * x[i][j] >= y[j] - n # optimizing model.optimize() # In[ ]: print("come on....") # checking if a solution was found if model.num_solutions: print('route with total distance %g found: %s' % (model.objective_value, places[0])) path = places[0] nc = 0 while True: nc = [i for i in V if x[nc][i].x >= 0.99][0] print(' -> %s' % places[nc]) path = path + ' -> %s' % places[nc] if nc == 0: break print('\n') arr = np.array(x) arr = arr.astype(str) file = open("../data.txt", "w") file.write(path + "\n") file.write(str(model.objective_value) + " - ") file.write("\n") for i in range(len(arr)): line = "" for j in range(len(arr[i])): line = line + str(x[i][j].x) if j != len(arr[i]) - 1: line = line + "," file.write(line + "\n") file.close() else: print("no solution")
[117, 65, 125, 43], [54, 22, 84], [60, 44], [97], []] # number of nodes and list of vertices n, V = len(dists), set(range(len(dists))) # distances matrix c = [[0 if i == j else dists[i][j-i-1] if j > i else dists[j][i-j-1] for j in V] for i in V] model = Model() # binary variables indicating if arc (i,j) is used on the route or not x = [[model.add_var(var_type=BINARY) for j in V] for i in V] # continuous variable to prevent subtours: each city will have a # different sequential id in the planned route except the first one y = [model.add_var() for i in V] # objective function: minimize the distance model.objective = minimize(xsum(c[i][j]*x[i][j] for i in V for j in V)) # constraint : leave each city only once for i in V: model += xsum(x[i][j] for j in V - {i}) == 1
v_p = [volumes[i] for i in range(len(priorities)) if priorities[i] == 1] # extracting non-priority packages names_np = [i for i in range(len(priorities)) if priorities[i] == 0] w_np = [weights[i] for i in range(len(priorities)) if priorities[i] == 0] v_np = [volumes[i] for i in range(len(priorities)) if priorities[i] == 0] # quantitative restrictions volume_np = 325 weight = 750 # iterators I_p = range(len(w_p)) I_np = range(len(w_np)) # creating new model m = Model("packages") # creating binary variables [0-DO NOT PACK, 1-PACK] x_p = [m.add_var(var_type=BINARY) for i in I_p] x_np = [m.add_var(var_type=BINARY) for i in I_np] # objective function m.objective = maximize(xsum(x_p[i] for i in I_p) + xsum(x_np[j] for j in I_np)) # limitations m += xsum(v_np[i] * x_np[i] for i in I_np) <= volume_np # m += xsum(v_p[i] * x_p[i] for i in I_p) <= volume_np m += (xsum(w_p[i] * x_p[i] for i in I_p) + xsum(w_np[j] * x_np[j] for j in I_np)) <= weight # run the optimization process
C = 10 # set of curricula CU = 6 T = len(teachers) p_CAP = 1 p_STAB = 1 p_DAYS = 1 p_COMP = 1 # # ma = [[0,1,2],[3,4,5],[6,7,8],[6,7,8]] # meow = 1 - (xsum(ma[i][j] for i in range(2) for j in range(3)) \ # + xsum(ma[i][j] for i in range(2,4) for j in range(3))) m = Model("cbctt") x_cdpr = [[[[m.add_var('x({},{},{},{})'.format(c,d,p,r),var_type=BINARY) for r in range(R)] for p in range(P)] for d in range(D)] for c in range(C)] print('\nx_cdpr:',x_cdpr[0][0][0][0].x) print('\nx_cdpr:',x_cdpr[1][1][0][0].x) print('\nx_cdpr:',x_cdpr[2][2][0][0].x) print('\nx_cdpr:',x_cdpr[3][3][0][0].x) v_cupd = [[[m.add_var('v({},{},{})'.format(cu,p,d),var_type=BINARY) for d in range(D)] for p in range(P)] for cu in range(CU)] print('\nv_cupd:',v_cupd) y_cr = [[m.add_var('y({},{})'.format(c,r),var_type=BINARY) for r in range(R)] for c in range(C)]
def test_tsp_cuts(solver: str): """tsp related tests""" N = ['a', 'b', 'c', 'd', 'e', 'f', 'g'] n = len(N) i0 = N[0] A = { ('a', 'd'): 56, ('d', 'a'): 67, ('a', 'b'): 49, ('b', 'a'): 50, ('d', 'b'): 39, ('b', 'd'): 37, ('c', 'f'): 35, ('f', 'c'): 35, ('g', 'b'): 35, ('b', 'g'): 25, ('a', 'c'): 80, ('c', 'a'): 99, ('e', 'f'): 20, ('f', 'e'): 20, ('g', 'e'): 38, ('e', 'g'): 49, ('g', 'f'): 37, ('f', 'g'): 32, ('b', 'e'): 21, ('e', 'b'): 30, ('a', 'g'): 47, ('g', 'a'): 68, ('d', 'c'): 37, ('c', 'd'): 52, ('d', 'e'): 15, ('e', 'd'): 20 } # input and output arcs per node Aout = {n: [a for a in A if a[0] == n] for n in N} Ain = {n: [a for a in A if a[1] == n] for n in N} m = Model(solver_name=solver) m.verbose = 0 x = { a: m.add_var(name='x({},{})'.format(a[0], a[1]), var_type=BINARY) for a in A } m.objective = xsum(c * x[a] for a, c in A.items()) for i in N: m += xsum(x[a] for a in Aout[i]) == 1, 'out({})'.format(i) m += xsum(x[a] for a in Ain[i]) == 1, 'in({})'.format(i) # continuous variable to prevent subtours: each # city will have a different "identifier" in the planned route y = {i: m.add_var(name='y({})'.format(i), lb=0.0) for i in N} # subtour elimination for (i, j) in A: if i0 not in [i, j]: m.add_constr(y[i] - (n + 1) * x[(i, j)] >= y[j] - n) m.cuts_generator = SubTourCutGenerator() # tiny model, should be enough to find the optimal m.max_seconds = 10 m.max_nodes = 100 m.max_solutions = 1000 m.optimize() assert m.status == OptimizationStatus.OPTIMAL # "mip model status" assert abs(m.objective_value - 262) <= TOL # "mip model objective"