def _initialize_model(self): problem = Model() problem.setParam('OutputFlag', False) # edges from source to reviewers, capacity controls maximum reviewer load self._source_vars = problem.addVars(self.numrev, vtype=GRB.CONTINUOUS, lb=0.0, ub=self.ability, name='reviewers') # edges from papers to sink, capacity controls a number of reviewers per paper self._sink_vars = problem.addVars(self.numpapers, vtype=GRB.CONTINUOUS, lb=0.0, ub=self.demand, name='papers') # edges between reviewers and papers. Initially capacities are set to 0 (no edge is added in the network) self._mix_vars = problem.addVars(self.numrev, self.numpapers, vtype=GRB.CONTINUOUS, lb=0.0, ub=0.0, name='assignment') problem.update() # flow balance equations for reviewers' nodes self._balance_reviewers = problem.addConstrs((self._source_vars[i] == self._mix_vars.sum(i, '*') for i in range(self.numrev))) # flow balance equations for papers' nodes self._balance_papers = problem.addConstrs((self._sink_vars[i] == self._mix_vars.sum('*', i) for i in range(self.numpapers))) problem.update() self._problem = problem
def max_return(r, risk_threshold, cvar_alpha=0.95): r_bar = np.mean(r, axis=0) cov = np.cov(r, rowvar=False) n = len(r) k = len(r[0]) m = Model('opt_profolio') m.params.OutputFlag = 0 m.params.NumericFocus = 3 x = m.addVars(k, lb=0, ub=1, vtype=GRB.CONTINUOUS, name='x') z = m.addVars(n, lb=0, vtype=GRB.CONTINUOUS, name='z') eta = m.addVar(lb=-GRB.INFINITY, vtype=GRB.CONTINUOUS, name='eta') m.update() #Portfolio contraint m.addConstr((x.sum() == 1), 'portfolio_ctr') #Risk constraint m.addConstr( (eta + (1.0 / (n * (1 - cvar_alpha))) * z.sum() <= risk_threshold), 'cvar_ctr') #CVaR linearlization m.addConstrs((z[i] >= quicksum(-r[i, j] * x[j] for j in range(k)) - eta for i in range(n)), 'cvar_linear') m.setObjective(quicksum(r_bar[j] * x[j] for j in range(k)), GRB.MAXIMIZE) m.update() m.optimize() x_sol = np.array([x[j].X for j in range(k)]) p_mean = r_bar.dot(x_sol) p_var = x_sol.dot(cov.dot(x_sol)) cvar_loss = (eta + (1.0 / (n * (1 - cvar_alpha))) * z.sum()).getValue() #print(m.status, eta.X, (-1+(1+eta.X)**365), cvar_loss , (-1+(1+cvar_loss)**365)) return x_sol, p_mean, p_var
def initialize_model(cost_matrix, cutoff, model=None): #Add dummy detection cost_matrix = np.insert(cost_matrix, 0, np.ones(cost_matrix.shape[0]) * cutoff, axis=1) M, N = cost_matrix.shape if model is None: model = Model() else: model.remove(model.getVars()) model.remove(model.getConstrs()) model.setParam('OutputFlag', False) # y = [] # for i in range(M): # y.append([]) # for j in range(N): # y[i].append(m.addVar(vtype=GRB.BINARY, name = 'y_%d%d'%(i,j))) y = model.addVars(M, N, vtype=GRB.BINARY, name='y') model.setObjective( quicksum( quicksum([y[i, j] * cost_matrix[i][j] for j in range(N)]) for i in range(M)), GRB.MINIMIZE) # for i in range(M): model.addConstrs( (quicksum(y[i, j] for j in range(N)) == 1 for i in range(M)), name='constraint for track') # for j in range(1,N): model.addConstrs( (quicksum(y[i, j] for i in range(M)) <= 1 for j in range(1, N)), name='constraint for detection') y = list(y.values()) return model, M, N, y
def solve(): model = Model("Enigma Riddle Binary Program") letters = {"E", "N", "I", "G", "M", "A"} digits = range(1, 10) # x[i, j] == 1 => Letter i uses digit j x = model.addVars(letters, digits, vtype=GRB.BINARY) # Final value for first word b = model.addVar(vtype=GRB.INTEGER) first_word = "ENIGMA" second_word = "IGMAEN" # Constraints for the enigma-igmaen numbers model.addConstr( quicksum( quicksum(10**(len(first_word) - 1 - i) * j * x[first_word[i], j] for j in digits) for i in range(len(first_word))) == b) model.addConstr( quicksum( quicksum(10**(len(second_word) - 1 - i) * j * x[second_word[i], j] for j in digits) for i in range(len(second_word))) == b * 1.2) # Conflict constraint, different letters have different digits model.addConstrs(x[i_1, j] + x[i_2, j] <= 1 for i_1 in letters for i_2 in letters for j in digits if i_1 != i_2) # Exactly one digit has to be used per letter model.addConstrs(quicksum(x[i, j] for j in digits) == 1 for i in letters) model.optimize() return model
def solve(): model = Model("Enigma Riddle Binary Program") letters = {"E", "N", "I", "G", "M", "A"} digits = range(1, 10) # x[i, j] == 1 => Letter i uses digit j x = model.addVars(letters, digits, vtype=GRB.BINARY, name=(f"x[{l},{d}]" for l in letters for d in digits)) # Final value for first word first_word = "ENIGMA" second_word = "IGMAEN" factor = 1.2 # Constraint for the enigma-igmaen numbers model.addConstr(factor * quicksum( quicksum(10**(len(first_word) - 1 - i) * j * x[first_word[i], j] for j in digits) for i in range(len(first_word))) - quicksum( quicksum(10**(len(second_word) - 1 - i) * j * x[second_word[i], j] for j in digits) for i in range(len(second_word))) == 0) # Conflict constraint, different letters have different digits model.addConstrs(quicksum(x[i, j] for i in letters) <= 1 for j in digits) # Exactly one digit has to be used per letter model.addConstrs(quicksum(x[i, j] for j in digits) == 1 for i in letters) model.optimize() return model
def stage_prob_builder(t): model = Model('CapExp%i' % t) # Create a model x = model.addVars(data.I, vtype=GRB.CONTINUOUS, lb=0, ub=data.b, obj=1, name='x') x0 = model.addVars(data.I, vtype=GRB.CONTINUOUS, lb=0, ub=data.b, obj=0, name='x0') d = model.addVars(data.J, vtype=GRB.CONTINUOUS, lb=0, ub=0, obj=0, name='d') model.update() if t == 0: # y = model.addVars(data.I, lb=0, ub=1, obj=5, vtype=GRB.BINARY, name='y') # model.addConstrs((x[i] <= data.b * y[i] for i in data.I), 'logic_open') model.addConstr(sum(x[i] for i in data.I), GRB.LESS_EQUAL, data.b, 'globalCap') model.update() else: y = model.addVars(data.I, data.J, lb=0, obj=data.c, vtype=GRB.CONTINUOUS, name='y') s = model.addVars(data.J, lb=0, obj=data.rho, vtype=GRB.CONTINUOUS, name='s') model.update() '''Capacity constraints''' model.addConstrs((sum(y[i, j] for j in data.J) <= x0[i] for i in data.I), 'CapCtr') '''Recourse constraint, subcontracting ''' model.addConstrs((sum(y[i, j] for i in data.I) + s[j] >= d[j] for j in data.J), 'RecCtr') model.update() in_states = [var.VarName for var in x0.values()] out_states = [var.VarName for var in x.values()] rhs_vars = [var.VarName for var in d.values()] return model, in_states, out_states, rhs_vars
def createInstance(self): model = Model() modelVars = {} # x variables are assigned. for i in range(self.m): for j in range(self.n): Vname = 'x_{}_{}'.format(i, j) modelVars[Vname] = model.addVar(vtype=GRB.BINARY, name=Vname) # Term 2: Objective Function obj = quicksum(self.v[j] * modelVars['x_{}_{}'.format(i, j)] for i in range(self.m) for j in range(self.n)) # Term 3: Each job is assigned to at most 1 machine. model.addConstrs( quicksum(modelVars['x_{}_{}'.format(i, j)] for i in range(self.m)) <= 1 for j in range(self.n)) # Term 4: Allows the assignment of at most R resources to a machine. model.addConstrs( quicksum(modelVars['x_{}_{}'.format(i, j)] * self.r[j] for j in self.J[h]) <= self.R for i in range(self.m) for h in range(1, self.k + 1)) # Term 5: Implicit in varaible definition. # Objective Function is set. model._vars = modelVars model.setObjective(obj, GRB.MAXIMIZE) #print(model.getAttr('ModelSense') == GRB.MINIMIZE) return model
class mip_model(object): def __init__(self, samples, delta=1.0): self.n_nodes = samples.n_nodes self.n_samples = samples.n_samples self.delta = delta self.B = samples.B self.T = samples.T self.F = samples.F self.model = Model('DPSL') self.create_model() def create_model(self): self.U = self.model.addVars(self.n_nodes, self.n_samples, name='U', lb=0, ub=1, vtype=GRB.CONTINUOUS) self.M = self.model.addVars(self.n_nodes, name='M', lb=0, ub=1, vtype=GRB.CONTINUOUS) self.y = self.model.addVars(self.n_nodes, self.n_samples, name='y', lb=0, ub=1, vtype=GRB.CONTINUOUS) self.z = self.model.addVars(self.n_nodes, self.n_nodes, self.n_samples, name='z', lb=0, ub=1, vtype=GRB.CONTINUOUS) self.model.addConstrs((self.y[i, n] >= -1 + self.M[i] + self.B[i, n] - self.U[i, n]) for i in range(self.n_nodes) for n in range(self.n_samples)) self.model.addConstrs((self.z[i, j, n] >= -2 + self.T[i, j, n] + self.F[i, j, n] + self.U[j, n] - self.U[i, n]) for i in range(self.n_nodes) for j in range(self.n_nodes) for n in range(self.n_samples) if i != j) cost_expr = 2 * self.M.sum() - (5 / self.n_samples) * self.U.sum() dist_expr = self.y.sum() + self.z.sum() + self.U.sum() self.model.setObjective(cost_expr + self.delta * dist_expr, GRB.MINIMIZE) def solve(self): self.model.optimize() for i in range(self.n_nodes): print(self.M[i].x)
def markovitz_dro_wasserstein(data, delta_param, alpha_param, wasserstein_norm=1): ''' Model from Blanchet et al. 2017 DRO Markovitz reformulation from Wasserstein distance. ''' r = np.mean(data, axis=0) cov = np.cov(data, rowvar=False) k = len(r) n = len(data) m = Model('opt_profolio') m.params.OutputFlag = 0 m.params.NumericFocus = 3 x = m.addVars(k, lb=0, ub=1, vtype=GRB.CONTINUOUS, name='x') norm_p = m.addVar(lb=0, ub=1, vtype=GRB.CONTINUOUS, name='norm') p_SD = m.addVar(lb=0, vtype=GRB.CONTINUOUS, name='p_var') m.update() sqrt_delta = np.sqrt(delta_param) m.addConstr((x.sum() == 1), 'portfolio_ctr') m.addConstr( (quicksum(x[j] * r[j] for j in range(k)) >= alpha_param - sqrt_delta * norm_p), 'return_ctr') m.addConstr((p_SD * p_SD >= quicksum(cov[i, j] * x[i] * x[j] for i in range(k) for j in range(k))), 'SD_def') objfun = p_SD * p_SD + 2 * p_SD * sqrt_delta * norm_p + delta_param * norm_p * norm_p m.setObjective(objfun, GRB.MINIMIZE) if wasserstein_norm == 1: regularizer_norm = 'inf' m.addConstrs((norm_p >= x[j] for j in range(k)), 'norm_def') elif wasserstein_norm == 2: regularizer_norm = 2 m.addConstr((norm_p * norm_p >= (quicksum(x[j] * x[j] for j in range(k)))), 'norm_def') elif wasserstein_norm == 'inf': regularizer_norm = 1 #Note: this works since x>=0 m.addConstr((norm_p == (quicksum(x[j] for j in range(k)))), 'norm_def') else: raise 'wasserstain norm should be 1,2, or inf' m.optimize() x_sol = np.array([x[j].X for j in range(k)]) p_mean = r.dot(x_sol) p_var = x_sol.dot(cov.dot(x_sol)) #print(x_sol, p_mean, p_var) #print('norms' , np.linalg.norm(x_sol) , norm_p.X) return x_sol, p_mean, p_var
def optimize_pareto(Bw, h, ju_s, ju_l, jn_s, jn_l): # create a model m = Model('Pareto') # create decision variables x = m.addVars(an, an, vtype=GRB.BINARY, name='x') y = m.addVars(an, dc, vtype=GRB.BINARY, name='y') ######### add constraints ########## m.addConstrs((x[i, j] == x[j, i] for i in an for j in an), 'symmetric constraint') # Two service areas cant use the same stateful functions when x[i,j] = 0 m.addConstrs((y[i, t] + y[j, t] <= x[i, j] + 1 for i in an for j in an for t in dc), 'x = 0 constraint') # Two service areas use the same stateful functions when x[i,j] = 1 m.addConstrs(((y[i, t] - y[j, t] <= 1 - x[i, j]) for i in an for j in an for t in dc), 'x = 1 constraint') # Each should be at least managed by one dc m.addConstrs((sum(y[i, t] for t in dc) == 1 for i in an), 'one dc for access node') # high availability constraint m.addConstr( sum((1 - x[i, j]) for i in an for j in an if i != j) >= 1, 'ha') # maximum state transfer frequency m.addConstr( sum(h * (1 - x[i, j]) for i in an for j in an if i != j) <= jn_s - 1, 'max state transfer constraint') # maximum latency constraint m.addConstr( sum(y[i, t] * C[i, t] * (Sd / Bw + Lw + Wg) for i in an for t in dc) <= jn_l, 'latency maximum constraint') ######## Objective function ######### m.setObjective((sum(y[i, t] * C[i, t] * (Sd / Bw + Lw + Wg) for i in an for t in dc) - ju_l) / (jn_l - ju_l) + (sum(h * (1 - x[i, j]) for i in an for j in an if i != j) - ju_s) / (jn_s - ju_s), GRB.MINIMIZE) m.optimize() ######## Calculate performance metrics ######### # latency latency = sum(C[i, t] * getattr(y[i, t], 'X') * (Sd / Bw + Lw + Wg) for i in an for t in dc) # state transfer frequency state_transfer = sum(h * (1 - getattr(x[i, j], 'X')) for i in an for j in an if i != j) # total cost cost = latency + state_transfer # number of functions num_func = M_dc - sum( prod(1 - getattr(y[i, t], 'X') for i in an) for t in dc) # total metrics total_metrics = [Bw, h, state_transfer, latency, num_func, cost] return total_metrics
def optimize_latency(Bw, h): # create a model m = Model('latency') # create decision variables x = m.addVars(an, an, vtype=GRB.BINARY, name='x') y = m.addVars(an, dc, vtype=GRB.BINARY, name='y') ######### add constraints ########## # x is symmetric m.addConstrs((x[i, j] == x[j, i] for i in an for j in an), 'symmetric constraint') # Two service areas cant use the same stateful functions when x[i,j] = 0 m.addConstrs((y[i, t] + y[j, t] <= x[i, j] + 1 for i in an for j in an for t in dc), 'x = 0 constraint') # Two service areas use the same stateful functions when x[i,j] = 1 m.addConstrs(((y[i, t] - y[j, t] <= 1 - x[i, j]) for i in an for j in an for t in dc), 'x = 1 constraint') # One access node connects to only one dc m.addConstrs((sum(y[i, t] for t in dc) == 1 for i in an), 'one dc for access node') # high availability constraint m.addConstr( sum((1 - x[i, j]) for i in an for j in an if i != j) >= 1, 'ha') # maximum state transfer frequency m.addConstr( sum(h * (1 - x[i, j]) for i in an for j in an if i != j) <= State_max, 'max state transfer constraint') ######## Objective function ######### # Optimize latency budget m.setObjective( sum(y[i, t] * C[i, t] * (Sd / Bw + Lw + Wg) for i in an for t in dc), GRB.MINIMIZE) m.optimize() ######## Calculate performance metrics ######### # latency latency = sum(C[i, t] * (Sd / Bw + Lw + Wg) * getattr(y[i, t], 'X') for i in an for t in dc) # state transfer frequency state_transfer = sum(h * (1 - getattr(x[i, j], 'X')) for i in an for j in an if i != j) # number of function num_func = M_dc - sum( prod(1 - getattr(y[i, t], 'X') for i in an) for t in dc) # total cost cost = latency + state_transfer # total metrics total_metrics = [Bw, h, state_transfer, latency, num_func, cost] # utopia point, nadir point worst_state = state_transfer best_latency = latency return total_metrics, worst_state, best_latency
def RCI_controller(sys, x): """ Based on zonotopes """ model = Model("Controller") q = sys.phi.shape[1] zeta = tupledict_to_array( model.addVars(range(q), [0], lb=-1, ub=1, name="zeta")) zeta_abs = tupledict_to_array( model.addVars(range(q), [0], lb=0, ub=1, name="zeta_abs", obj=1)) model.update() constraints_list_of_tuples(model, [(-np.eye(sys.n), x), (sys.phi, zeta)]) model.addConstrs(zeta_abs[i, 0] >= zeta[i, 0] for i in range(q)) model.addConstrs(zeta_abs[i, 0] >= -zeta[i, 0] for i in range(q)) model.setParam('OutputFlag', False) model.optimize() zeta_n = np.array([zeta[i, 0].X for i in range(q)]).reshape(q, 1) print zeta_n.T return np.dot(sys.theta, zeta_n)
def solve(): model = Model("Enigma Riddle") letters = {"E", "N", "I", "G", "M", "A"} digits = range(1, 10) x = model.addVars(letters, digits, vtype=GRB.BINARY) y = model.addVars(letters, vtype=GRB.INTEGER) # Stay in digit range for i in letters: model.addRange(y[i], 1, 9, f"digitRange{i}") # Final value for first word b = model.addVar(vtype=GRB.INTEGER) first_word = "ENIGMA" second_word = "IGMAEN" # Constraint for the enigma-igmaen numbers model.addConstr(quicksum(10 ** (len(first_word) - 1 - i) * y[first_word[i]] for i in range(len(first_word))) == b) model.addConstr( quicksum(10 ** (len(second_word) - 1 - i) * y[second_word[i]] for i in range(len(second_word))) == b * 1.2) # Conflict constraint model.addConstrs(x[i_1, j] + x[i_2, j] <= 1 for i_1 in letters for i_2 in letters for j in digits if i_1 != i_2) # Linking constraint model.addConstrs(j * x[i, j] <= y[i] for i in letters for j in digits) # Exactly one digit has to be packed model.addConstrs(quicksum(x[i, j] for j in digits) == 1 for i in letters) model.optimize() return model
def _create_model(self, city_ids, map_points): depot_id = city_ids[0] city_num = len(city_ids) ## prepare the index for decision variables # index of network flow cities = tuple(city_ids) # index of MTZ constraint MTZ_u = tuple(city_ids[1:]) # connecting arcs of the cities cityArcs = [(i,j) for i in cities for j in cities if i != j] ## parameters model (dictionary) # 1. distance map distances_map = self.calculate_distances(city_ids, map_points) ## create model m = Model('TSP') ## create decision variables # 1. choice of arcs between cities x = m.addVars(cityArcs, vtype=GRB.BINARY, name='route') # 2. for expression of non-subtour: [2,N] u = m.addVars(MTZ_u, name='MTZ_u') ## create objective: minimum route distance m.setObjective(quicksum([x[i,j]*distances_map[(i,j)] for (i,j) in cityArcs]), GRB.MINIMIZE) # TOTRY ## create constraints # 1. MTZ formulation m.addConstrs((u[i]-u[j]+city_num*x[i,j] <= city_num-1 for (i,j) in cityArcs if (i>depot_id and j>depot_id)),'MTZ formulation') m.addConstrs((u[i]>=0 and u[i]<=city_num-1 for i in MTZ_u), 'MTZ compensation') # 2. Network flow m.addConstrs((quicksum([x[i,j] for j in cities if i!=j])==1 for i in cities), 'Network flow1') m.addConstrs((quicksum([x[i,j] for i in cities if i!=j])==1 for j in cities), 'Network flow2') return m, x
def TWTgurobi(): jobs = tuple(range(1,5)) jobPairs = [(i,j) for i in jobs for j in jobs if i < j] # job_id as keys and weight as content weight = dict(zip(jobs, (4,3,4,5))) duration = dict(zip(jobs, (12,8,15,9))) deadline = dict(zip(jobs, (16,26,25,27))) # Big M for modeling M = sum(duration.values()) try: m = Model('TWTexample') x = m.addVars(jobPairs, vtype=GRB.BINARY, name='x') startTime = m.addVars(jobs, name='startTime') tardiness = m.addVars(jobs, name='tardiness') m.setObjective(quicksum([weight[j]*tardiness[j] for j in jobs]), GRB.MINIMIZE) m.addConstrs((startTime[j] >= startTime[i]+duration[i]-M*(1-x[i,j]) for(i,j) in jobPairs), 'NoOverplap1') m.addConstrs((startTime[i] >= startTime[j]+duration[j]-M*x[i,j] for(i,j) in jobPairs), 'NoOverplap2') m.addConstrs((tardiness[j] >= startTime[j]+duration[j]-deadline[j] for j in jobs), 'Deadline') m.optimize() if m.status == GRB.Status.INF_OR_UNBD: m.setParam(GRB.Param.DualReductions, 0) m.optimize() if m.status == GRB.Status.OPTIMAL: for v in m.getVars(): print('%s:\t%g' %(v.varName, v.x)) print('Objective:\t%g' % m.objVal) else: statstr = StatusDict[m.status] print('Optimization was stopped with status %s' %statstr) except GurobiError as e: print('Error code '+str(e.errno)+': '+str(e))
def rocket(): from gurobipy import Model, GRB # Set up data Mass = [ 70, 90, 100, 110, 120, 130, 150, 180, 210, 220, 250, 280, 340, 350, 400 ] P = range(len(Mass)) # A, B, C, D Sections = ["A", "B", "C", "D"] S = range(len(Sections)) m = Model('Rocket Payload') X = m.addVars(P, S, vtype=GRB.BINARY, name='X') Y = m.addVars(P, S, name='Y', obj=1) m.addConstrs(Y[p, s] == X[p, s] * Mass[p] for p, s in X.keys()) m.addConstrs(Y.sum('*', s) <= 1000 for s in S) m.addConstrs(X.sum('*', s) >= 3 for s in S) m.addConstr(Y.sum('*', 0) == Y.sum('*', 3)) m.addConstr(Y.sum('*', 1) == Y.sum('*', 2)) m.setAttr(GRB.Attr.ModelSense, GRB.MAXIMIZE) m.optimize()
def _create_model(self, city_ids, map_points): depot_id = city_ids[0] city_num = len(city_ids) ## prepare the index for decision variables # index of network flow cities = tuple(city_ids) # connecting arcs of the cities cityArcs = [(i, j) for i in cities for j in cities if i != j] ## parameters model (dictionary) # 1. distance map distances_map = self.calculate_distances(city_ids, map_points) ## create model m = Model('TSP') ## create decision variables # 1. choice of arcs between cities x = m.addVars(cityArcs, vtype=GRB.BINARY, name='route') m._x = x m._cities = cities m._cityArcs = cityArcs ## create objective: minimum route distance m.setObjective( quicksum([x[i, j] * distances_map[(i, j)] for (i, j) in cityArcs]), GRB.MINIMIZE) # TOTRY ## create constraints # 1. Network flow m.addConstrs((quicksum([x[i, j] for j in cities if i != j]) == 1 for i in cities), 'Network flow1') m.addConstrs((quicksum([x[i, j] for i in cities if i != j]) == 1 for j in cities), 'Network flow2') for (i, j) in cityArcs: if (i, j) in init_solution: x[i, j].start = 1 return m, x
def tpms_assignment(papload, revload, similarity): problem = Model() problem.setParam('OutputFlag', False) numrev = similarity.shape[0] numpap = similarity.shape[1] source_vars = problem.addVars(numrev, vtype=GRB.CONTINUOUS, lb=0, ub=revload, name='reviewers') sink_vars = problem.addVars(numpap, vtype=GRB.CONTINUOUS, lb=0, ub=papload, name='papers') mix_vars = problem.addVars(numrev, numpap, vtype=GRB.CONTINUOUS, lb=0.0, ub=1.0, name='assignment') #Reviewer flow constraints balance_reviewers = problem.addConstrs((source_vars[i] == mix_vars.sum(i, '*') for i in range(numrev))) # avoid COIs #avoid_cois = problem.addConstrs((mix_vars[i][j] == 0 for i in range(numrev) for j in range(numpap) if similarity[i,j] < -0.5)) #Paper flow constraints balance_papers = problem.addConstrs((sink_vars[j] == mix_vars.sum('*', j) for j in range(numpap))) #Objective problem.setObjective(sum([sum([mix_vars[rev, pap] * similarity[rev, pap] for pap in range(numpap)]) for rev in range(numrev)]), GRB.MAXIMIZE) problem.optimize() if problem.status != 2: raise Exception('An error occured') #The rest is a constructun of the assignment dict assignment = {rev : [] for rev in range(numrev)} for pap in range(numpap): for rev in range(numrev): if mix_vars[rev, pap].X == 1: assignment[rev] += [pap] return(assignment)
def TWTgurobi(): # TWT Problem Data jobs = tuple([i + 1 for i in range(4)]) jobPairs = [(i, j) for i in jobs for j in jobs if i < j] weight = dict(zip(jobs, (4, 5, 3, 5))) duration = dict(zip(jobs, (12, 8, 15, 9))) deadline = dict(zip(jobs, (16, 26, 25, 27))) M = sum(duration.values()) try: # Create a new model m = Model('TWTexample') # Create variables # x[(i,j)] = 1 if i << j, else j >> i x = m.addVars(jobPairs, vtype=GRB.BINARY, name='x') startTime = m.addVars(jobs, name='startTime') tardiness = m.addVars(jobs, name='tardiness') # Set objective function m.setObjective(quicksum([weight[j] * tardiness[j] for j in jobs]), GRB.MINIMIZE) # Add constraints m.addConstrs( (startTime[j] >= startTime[i] + duration[i] - M * (1 - x[(i, j)]) for (i, j) in jobPairs), 'NoOverlap1') m.addConstrs( (startTime[i] >= startTime[j] + duration[j] - M * x[(i, j)] for (i, j) in jobPairs), 'NoOverlap2') m.addConstrs((tardiness[j] >= startTime[j] + duration[j] - deadline[j] for j in jobs), 'Deadline') # Solve model m.optimize() if m.status == GRB.Status.INF_OR_UNBD: # Disable dual reductions to determine solve status m.setParam(GRB.Param.DualReductions, 0) m.optimize() # Display solution if m.status == GRB.Status.OPTIMAL: for v in m.getVars(): print('%s:\t%g' % (v.varName, v.x)) print('Objective:\t%g' % m.objVal) else: statstr = StatusDict[m.status] print('Optimization was stopped with status %s' % statstr) except GurobiError as e: print('Error code ' + str(e.errno) + ": " + str(e))
def _run_econstraint_gurobi(mdl: GurobiModel, objectives: List[LinExpr], payoff_table, g: Dict[int, int] = None, solution_extractor: Callable = None) -> NoReturn: p = len(objectives) s = mdl.addVars([k for k in range(1, p)], name='s') lb = {k: min(payoff_table[h, k] for h in range(p)) for k in range(1, p)} r = { k: max(payoff_table[h, k] for h in range(p)) - min(payoff_table[h, k] for h in range(p)) for k in range(1, p) } logger.debug('r: %s', r) epsilon = 1e-3 mdl.setObjective(objectives[0] + epsilon * quicksum(s[k] / r[k] for k in range(1, p)), sense=GRB.MAXIMIZE) if g is None: g = {k: 3 for k in range(1, p)} # default number of grid logger.warning('Using default grid g=3') i = {k: 0 for k in range(1, p)} while True: e = {k: lb[k] + (i[k] * r[k]) / g[k] for k in range(1, p)} logger.info(f'i: {i}, e: {e}') constraints = mdl.addConstrs(objectives[k] - s[k] == e[k] for k in range(1, p)) mdl.optimize() if mdl.SolCount > 0: solution_extractor() logger.info('feasible') else: logger.info('not feasible') mdl.remove(constraints) if all(i[k] == g[k] for k in range(1, p)): break else: for k in range(1, p): if i[k] == g[k]: i[k] = 0 else: i[k] += 1 break
def polytopic_trajectory(system,x0,list_of_goal_polytopes,T,eps=0.1,order=1): """ Description: Polytopic Trajectory Optimization """ model=Model("Point Trajectory Optimization") q=int(order*system.n) x=model.addVars(range(T+1),range(system.n),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="x") u=model.addVars(range(T),range(system.m),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="u") G=model.addVars(range(T+1),range(n),range(q),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="G") theta=model.addVars(range(T),range(m),range(q),lb=-GRB.INFINITY,ub=GRB.INFINITY,name="theta") ## x_PWA=model.addVars([(t,n,i,j) for t in range(T+1) for n in system.list_of_sum_indices \ for i in system.list_of_modes[n] for j in range(system.n)],lb=-GRB.INFINITY,ub=GRB.INFINITY,name="x_pwa") u_PWA=model.addVars([(t,n,i,j) for t in range(T) for n in system.list_of_sum_indices \ for i in system.list_of_modes[n] for j in range(system.m)],lb=-GRB.INFINITY,ub=GRB.INFINITY,name="u_pwa") G_PWA=model.addVars([(t,n,i,row,column) for t in range(T+1) for n in system.list_of_sum_indices \ for i in system.list_of_modes[n] for row in range(system.n) for column in range(q)],\ lb=-GRB.INFINITY,ub=GRB.INFINITY,name="G_pwa") theta_PWA=model.addVars([(t,n,i,row,column) for t in range(T+1) for n in system.list_of_sum_indices \ for i in system.list_of_modes[n] for row in range(system.m) for column in range(q)],\ lb=-GRB.INFINITY,ub=GRB.INFINITY,name="theta_pwa") delta_PWA=model.addVars([(t,n,i) for t in range(T) for n in system.list_of_sum_indices \ for i in system.list_of_modes[n]],vtype=GRB.BINARY,name="delta_pwa") model.update() for j in range(n): model.addConstr(x[0,j]<=x0[j,0]+eps*system.scale[j]) model.addConstr(x[0,j]>=x0[j,0]-eps*system.scale[j]) # Convexhull Dynamics and Constraints model.addConstrs(x[t,j]==x_PWA.sum(t,n,"*",j) for t in range(T+1) for j in range(system.n)\ for n in system.list_of_sum_indices) model.addConstrs(u[t,j]==u_PWA.sum(t,n,"*",j) for t in range(T) for j in range(system.m)\ for n in system.list_of_sum_indices) model.addConstrs(G[t,row,column]==G_PWA.sum(t,n,"*",row,column) for t in range(T) for row in range(system.n)\ for column in range(q) for n in system.list_of_sum_indices) model.addConstrs(G[t,row,column]==G_PWA.sum(t,n,"*",row,column) for t in range(T) for row in range(system.n)\ for column in range(q) for n in system.list_of_sum_indices) raise NotImplementedError
def vrproutes(n, xc, yc, cost_func): rnd = np.random rnd.seed(0) plt.plot(xc[0], yc[0], c='r', marker='s') plt.scatter(xc[1:], yc[1:], c='b') N = [i for i in range(1, n + 1)] V = [0] + N A = [(i, j) for i in V for j in V if i != j] # c = {(i, j): np.hypot(xc[i]-xc[j], yc[i]-yc[j]) for i, j in A} c = {(i, j): cost_func(i, j) for i, j in A} print(c) Q = 20 q = {i: rnd.randint(1, 10) for i in N} mdl = Model('CVRP') x = mdl.addVars(A, vtype=GRB.BINARY) u = mdl.addVars(N, vtype=GRB.CONTINUOUS) mdl.modelSense = GRB.MINIMIZE mdl.params.LogToConsole = False mdl.setObjective(quicksum(x[i, j] * c[i, j] for i, j in A)) mdl.addConstrs(quicksum(x[i, j] for j in V if j != i) == 1 for i in N) mdl.addConstrs(quicksum(x[i, j] for i in V if i != j) == 1 for j in N) mdl.addConstrs((x[i, j] == 1) >> (u[i] + q[j] == u[j]) for i, j in A if i != 0 and j != 0) mdl.addConstrs(u[i] >= q[i] for i in N) mdl.addConstrs(u[i] <= Q for i in N) mdl.Params.MIPGap = 0.001 mdl.Params.TimeLimit = 60 # seconds mdl.optimize() active_arcs = [a for a in A if x[a].x > 0.5] return active_arcs
def Distribution_Matching(D): mean = np.mean(D) moment = [np.var(D), stats.skew(D), stats.kurtosis(D)] N = len(D) T1 = range(N) K = range(len(moment)) #number of moments W = np.array([0.5, 0.35, 0.15]) Omega = np.random.uniform(0, 1, (1, N)) osum = np.sum(Omega) Omega = [i / osum for i in Omega[0]] # Gurobi Model: Define variables ProbModel = Model() P = ProbModel.addVars(N, lb=0, ub=1, vtype=GRB.CONTINUOUS, name="P") S1 = ProbModel.addVars(N, lb=0, vtype=GRB.CONTINUOUS, name="S1") S2 = ProbModel.addVars(N, lb=0, vtype=GRB.CONTINUOUS, name="S2") M1 = ProbModel.addVars(K, lb=0, vtype=GRB.CONTINUOUS, name="M1") M2 = ProbModel.addVars(K, lb=0, vtype=GRB.CONTINUOUS, name="M2") # Objective Function Z = quicksum(W[k] * (M1[k] + M2[k]) for k in K[1:]) + quicksum(Omega[j] * (S1[j] + S2[j]) for j in T1) ProbModel.setObjective(Z, GRB.MINIMIZE) # Define Constraints ProbModel.addConstr(quicksum(P[j] for j in T1) == 1) ProbModel.addConstr(quicksum(D[j] * P[j] for j in T1) == mean) ProbModel.addConstrs( quicksum((D[j] - mean)**(k + 2) * P[j] for j in T1) + M1[k] - M2[k] == moment[k] for k in K) ProbModel.addConstrs( stats.norm.cdf((D[j] - mean) / moment[0]) - quicksum(P[jp] for jp in T1) == S1[j] - S2[j] for j in T1) ProbModel.addConstrs(P[j] >= 0.1 for j in T1) # Solve and publish ProbModel.Params.OutputFlag = 0 ProbModel.optimize() return ProbModel.x[:N]
def Solving_MILP(self, turbines, dist, travelTime, vessel, t, base, farm, \ R, routes, Techs, visited): for t_1 in range(1, t): for b_1 in range(self.num_B): if turbines not in visited[vessel][t_1][b_1][farm]: continue index = visited[vessel][t_1][b_1][farm].index(turbines) if self.time_window[vessel][t][farm] == self.time_window[ vessel][t_1][farm]: c_t = R[vessel][t_1][b_1][farm][0][-4, index] c_p = R[vessel][t_1][b_1][farm][0][-3, index] c_lr = sum(max(0, t - self.WF_deadline[farm][j]) \ * self.WF_penCost[farm][j] for j in turbines) c_total = c_t + c_p + c_lr path = routes[vessel][t_1][b_1][farm][index] NumTechs = Techs[vessel][t_1][b_1][farm][index] return [[c_t, c_p, c_lr, c_total], path, NumTechs] # total num of turbines in the wind farm n = len(self.WF_deadline[farm]) # set of drop off nodes [1,...,n] dropoff = list(map(lambda qq: qq + 1, turbines)) d1 = list(range(n + 1, 2 * n + 1)) # set of pick up nodes [n+1, n+2,...,2n] pickup = [d1[i - 1] for i in dropoff] # set of nodes need vessels to be present waiting = [i + 1 for i in turbines if self.WF_present[farm][i] == 1] nodes = [0] + dropoff + pickup + [2 * n + 1] model = Model() T = model.addVars(nodes, lb=0.0, vtype=GRB.CONTINUOUS) A = [(i, j) for i in nodes for j in nodes if i != j] B = [(p, i) for p in self.types for i in nodes] y = model.addVars(A, vtype=GRB.BINARY) Q = model.addVars(B, lb=0, vtype=GRB.INTEGER) model.addConstr(y[2 * n + 1, 0] == 1) model.addConstrs( quicksum(y[i, j] for j in nodes if i != j) == 1 for i in nodes) # 9 model.addConstr(quicksum(y[0, j] for j in dropoff) == 1) # 10 model.addConstr(quicksum(y[j, 2 * n + 1] for j in pickup) == 1) # 11 model.addConstrs(quicksum(y[i, j] for j in nodes if i != j) == \ quicksum(y[j, i] for j in nodes if i != j) for i in nodes) # 12 model.addConstrs(quicksum(y[i, j] for j in nodes if i != j) == \ quicksum(y[n + i, j] for j in nodes if n + i != j) for i in dropoff) # 13 model.addConstrs(y[i, n + i] == 1 for i in waiting) # 14 model.addConstrs(T[n + i] - T[i] >= self.WF_mainTime[farm][i - 1] \ + self.V_transTime[vessel] for i in dropoff) # 15 model.addConstr( T[2 * n + 1] <= self.time_window[vessel][t][farm]) # 16 model.addConstr(T[0] == 0) # 17 model.addConstrs(y[0, j] == 0 for j in pickup) model.addConstrs(y[j, 2 * n + 1] == 0 for j in dropoff) model.addConstr( quicksum(Q[p, 0] for p in self.types) <= self.V_tech[vessel]) # 18 model.addConstrs(Q[p, 0] <= self.B_tech[base][p][t] for p in self.types) model.addConstrs(Q[p, 0] >= Q[p, i] for p in self.types for i in nodes) for i in nodes[1:-1]: for j in dropoff: if i == j: continue model.addConstrs((y[i, j] == 1) >> \ (Q[p, i] - Q[p, j] == self.WF_tech[farm][j - 1][p]) for p in self.types) for j in pickup: if i == j: continue model.addConstrs((y[i, j] == 1) >> \ (Q[p, j] - Q[p, i] == self.WF_tech[farm][j - n - 1][p]) for p in self.types) model.addConstrs((y[0, j] == 1) >> \ (T[0] + travelTime[0, j] <= T[j]) for j in dropoff) model.addConstrs((y[j, 2 * n + 1] == 1) >> (T[j] + self.V_transTime[vessel] \ + travelTime[j - n, 0] <= T[2 * n + 1]) for j in pickup) for i in nodes[1:-1]: for j in nodes[1:-1]: if j == i + n or i == j: continue i1 = i if i <= n else i - n j1 = j if j <= n else j - n model.addConstr((y[i, j] == 1) >> \ (T[i] + self.V_transTime[vessel] + travelTime[i1, j1] <= T[j])) # 19 # cost for technicians c_qr = sum(Q[p, 0] * self.tech_cost[p] for p in self.types) # travel cost (fuel cost) c_tr = 0 for i in nodes: for j in nodes: if i != j: if i == 2 * n + 1: i1 = 0 elif i <= n: i1 = i else: i1 = i - n i1 = i if i <= n else i - n if j == 2 * n + 1: j1 = 0 elif j <= n: j1 = j else: j1 = j - n c_tr += self.V_cost[vessel] * travelTime[i1, j1] * y[i, j] # penalty cost c_lr = sum(max(0, t + 1 - self.WF_deadline[farm][j]) \ * self.WF_penCost[farm][j] for j in turbines) # ojective function model.modelSense = GRB.MINIMIZE model.setObjective(c_qr + c_tr + c_lr) model.setParam('OutputFlag', 0) model.optimize() if model.status == GRB.OPTIMAL: print('optimal') c_total = model.objVal # cost for technicians c_q = sum(Q[p, 0].x * self.tech_cost[p] for p in self.types) # travel cost (fuel cost) c_t = 0 for i in nodes: for j in nodes: if i != j: if i == 2 * n + 1: i1 = 0 elif i <= n: i1 = i else: i1 = i - n i1 = i if i <= n else i - n if j == 2 * n + 1: j1 = 0 elif j <= n: j1 = j else: j1 = j - n c_t += self.V_cost[vessel] * travelTime[i1, j1] * y[i, j].x path = [] # store the optimal route without base # path = [0] TT = [0] rr = 0 ii = 0 while rr < len(nodes) - 2: for k in nodes: if ii != k and round(y[ii, k].x) == 1: ii = k path.append(k - 1 if k <= n else k - n - 1) TT.append(round(T[k].x, 2)) # path.append(k) break rr += 1 TT.append(T[nodes[-1]].x) [c_t, c_q, c_lr, c_total] = [round(i, 2) for i in [c_t, c_q, c_lr, c_total]] num_techs = [Q[p, 0].x for p in self.types] # print('nodes: ', nodes) # print('path: ', ['vessel[%d]' % vessel] + ['period[%d]' % t] + \ # ['wf[%d]' % farm] + ['b[%d]' % base] + path) # print ('T: ', TT) # print ('###############\n \n') return [[c_t, c_q, c_lr, c_total], path, num_techs] else: print('infeasible') return [[None], None, None]
class Master: """ Master Object for initialising, solving, updating, and column creation of the tail assignment master problem""" def __init__(self, Data): """Formulate the master problem. INPUTS Data :: object, classes.Data; problem data. """ self.Data = Data self.duals = [] self.master = Model("master LP") # Init master model self.master.Params.OutputFlag = 0 # No output self._formulate_master() def _formulate_master(self): """ Formulate set partitioning model for tail assignment""" # Variable dicts # a_dict = {(s_label[1], s): s.cost for s_label, s in self.Data.scheds.items()} dum_dict = { f: 20000 + 20000 * (f.arrival - f.departure) for f in self.Data.flights } # VARIABLES # a = self.master.addVars(a_dict.keys(), name="a", vtype="B") dummy = self.master.addVars(dum_dict.keys(), name="dummy", vtype="B") # OBJECTIVE FUNCTION # self.master.setObjective(dummy.prod(dum_dict)) # FLIGHT CONSTRAINTS # self.master.addConstrs((dummy[key] >= 1 for key in dum_dict), name='flight') # AIRCRAFT CONSTRAINTS # self.master.addConstrs( (a.sum(k, '*') <= 1 for k in self.Data.aircraft), name='aircraft_schedule') self.master.update() # write to file self.master.write("./output/init.lp") def _solve_relax(self): """ Relaxes and solves the master problem. INPUTS master :: object, gurobipy.Model; master problem. RETURNS duals :: list of tuples, (dual, classes.Flight) relax :: object, gurobipy.Model; relaxed master problem. """ self.relax = self.master.relax() self.relax.update() self.relax.optimize() duals = [(float(c.Pi), [ f for f in self.Data.flights if f.i_d == self._split(c.ConstrName) ][0]) for c in self.relax.getConstrs() if "flight" in c.ConstrName] duals = sorted(duals, key=lambda x: x[1].i_d) self.duals.append([d[0] for d in duals]) return self.relax, duals def _generate_column(self, k, it, path): """ Adds column using shortest path from extended TSN. Parameters ---------- k : str, aircraft in subproblem it : int, iteration number path : list, edges in shortest path [(edge_dict, edge_weight), ..] Returns ------- master : object, gurobipy.Model; updated master problem with new column """ col = Column() # Init Column flights = self.Data.flights cost_col = 0 # count number of dummy edges for column obj coeff for p in path: # for each flight in the path if any(f._full_dict() == p[0] for f in flights): flight = [f for f in flights if f._full_dict() == p[0]][0] # Get constraints associated with flight constrs = [ c for c in self.master.getConstrs() if "flight" in c.ConstrName and self._split(c.ConstrName) == flight.i_d ] # Add terms to column for each constraint col.addTerms([1] * len(constrs), constrs) else: cost_col += p[1] # Get constraints associated with aircraft k constr = [ c for c in self.master.getConstrs() if "aircraft_schedule" in c.ConstrName and k in c.ConstrName ][0] col.addTerms(1, constr) # Get aircraft dual for cost lambda_k = [ float(c.Pi) for c in self.relax.getConstrs() if "aircraft_schedule" in c.ConstrName and k in c.ConstrName ][0] # cost of path + 2 due to first edge initialisation cost = 2 + sum(p[1] for p in path) - lambda_k if cost < 0: self.master.addVar(obj=cost_col, vtype="B", name="a[%s,s_%s_%s]" % (k, it, k), column=col) self.master.update() return self, cost @staticmethod def _split(string): """ Split integers in string and return last occurrence""" import re return list(map(int, re.findall(r'\d+', string)))[-1]
for arco in AF: rs[arco] = model.addVars(V[arco], K, vtype=GRB.CONTINUOUS, ub=1.0, lb=0.0, name='r({},{}){}'.format(arco[0], arco[1], s)) r[s] = rs ################### ### Constraints ### ################### ## FIRST STAGE CONSTRAINTS ## #FS1 model.addConstrs((quicksum(y[0][i, j, k] for k in K) <= 1 for i, j in AF), name='(FS1)') #FS2 model.addConstrs((quicksum(y[0][i, j, k] for i, j in A if i == ii) == nav[ii, k] for k in K for ii in Nf), name='(FS2)') #FS3 model.addConstrs( (quicksum(y[0][i, j, k] for i, j in A if j == jj) - quicksum(y[0][i, j, k] for i, j in A if i == jj) == 0 for k in K for jj in Nint), name='(FS3)') ## SECOND STAGE CONSTRAINTS ## #SS1 model.addConstrs(
def find_ranking(comparisons, equal_width=0.2, max_rank=-1, verbose=False): """ Find the least changes to a set of comparisons so that they are consistent (transitive), it returns a topological ranking. comparisons A dictionary with tuple keys in the form of (i, j), values are scalars indicating the probability of i > j. It is assumed that comparisons are symmetric. Use 0 for i < j, 0.5 for i == j, and 1 for i > j (and any value in between). equal_width 0..0.5-equal_width/2 is considered '<=' and 0.5..0.5+equal_width/2 is considered '>='. In between it is considered to be '=='. max_rank Maximal rank, a low value forces the model to choose more equal cases. verbose Whether to print gurobi's progress. Returns: A tuple of size two: 0) Ranking derived from topological sort (list of ranks in order of nodes); 1) Sum of absolute changes to the comparisons. """ # remove unnecessary variables comparisons = {(i, j) if i < j else (j, i): value if i < j else 1 - value for (i, j), value in comparisons.items()} nodes = np.unique([i for ij in comparisons.keys() for i in ij]) # define variables model = Model('comparison') model.setParam('OutputFlag', verbose) values = np.fromiter(comparisons.values(), dtype=float) assert values.max() <= 1 and values.min() >= 0 # variables to encode the error of comparisons E_ij = model.addVars(comparisons.keys(), name='e_ij', vtype=GRB.CONTINUOUS, ub=1.0 - values, lb=-values) # variables to encode hard choice of >=, <=, == Ge_ij = model.addVars(comparisons.keys(), name='ge_ij', vtype=GRB.BINARY) Le_ij = model.addVars(comparisons.keys(), name='le_ij', vtype=GRB.BINARY) Eq_ij = model.addVars(comparisons.keys(), name='eq_ij', vtype=GRB.BINARY) # variables to help with transitivity in non-fully connected graphs if max_rank < 1: max_rank = len(nodes) R_i = model.addVars(nodes, name='r_i', vtype=GRB.CONTINUOUS, lb=0, ub=max_rank) # variables to emulate abs T_ij_pos = {} T_ij_neg = {} index = (values != 1) & (values != 0) T_ij_pos = model.addVars( (ij for ij, value in comparisons.items() if value not in [0.0, 1.0]), vtype=GRB.CONTINUOUS, name='T_ij_pos', lb=0, ub=1 - values[index]) T_ij_neg = model.addVars( (ij for ij, value in comparisons.items() if value not in [0.0, 1.0]), vtype=GRB.CONTINUOUS, name='T_ij_neg', lb=0, ub=values[index]) model.update() # emulate abs for non-binary comparisons: E_ij = T_ij_pos - T_ij_neg model.addConstrs((E_ij[ij] == T_ij_pos[ij] - T_ij_neg[ij] for ij in T_ij_pos), 'E_ij = T_ij_pos - T_ij_neg') # hard decision of >=, <=, and == lower_bound = 0.5 - equal_width / 2.0 upper_bound = 0.5 + equal_width / 2.0 # <= model.addConstrs((E_ij[ij] + comparisons[ij] - upper_bound <= ge_ij for ij, ge_ij in Ge_ij.items()), 'ge_ij_lower_bound') model.addConstrs((E_ij[ij] + comparisons[ij] - upper_bound >= -1 + ge_ij for ij, ge_ij in Ge_ij.items()), 'ge_ij_upper_bound') # >= model.addConstrs((E_ij[ij] + comparisons[ij] - lower_bound >= -le_ij for ij, le_ij in Le_ij.items()), 'le_ij_lower_bound') model.addConstrs((E_ij[ij] + comparisons[ij] - lower_bound <= 1 - le_ij for ij, le_ij in Le_ij.items()), 'le_ij_upper_bound') # == model.addConstrs(( le + eq + ge == 1 for le, eq, ge in zip(Le_ij.values(), Eq_ij.values(), Ge_ij.values())), 'eq_ij') # transitivity for (i, j), eq_a in Eq_ij.items(): le_a = Le_ij[i, j] ge_a = Ge_ij[i, j] for k in nodes: j_, k_ = j, k if j > k: j_, k_ = k, j eq_b = Eq_ij.get((j_, k_), None) if eq_b is None: continue else: le_b = Le_ij[j_, k_] ge_b = Ge_ij[j_, k_] if j_ != j: le_b, ge_b = ge_b, le_b i_, k_ = i, k if i > k: i_, k_ = k, i eq_c = Eq_ij.get((i_, k_), None) if eq_c is None: continue else: le_c = Le_ij[i_, k_] ge_c = Ge_ij[i_, k_] if i_ != i: le_c, ge_c = ge_c, le_c # a <= b and b <= c -> a <= c model.addLConstr(ge_a + ge_b, GRB.LESS_EQUAL, 1 + ge_c, f'transitivity_ge_{i},{j},{k}') # a >= b and b >= c -> a >= c model.addLConstr(le_a + le_b, GRB.LESS_EQUAL, 1 + le_c, f'transitivity_le_{i},{j},{k}') # a <= b and b == c -> a <= c model.addLConstr(le_a + eq_b, GRB.LESS_EQUAL, 1 + le_c, f'transitivity_leeq_{i},{j},{k}') # a == b and b <= c -> a <= c model.addLConstr(eq_a + le_b, GRB.LESS_EQUAL, 1 + le_c, f'transitivity_eqle_{i},{j},{k}') # a >= b and b == c --> a >= c model.addLConstr(ge_a + eq_b, GRB.LESS_EQUAL, 1 + ge_c, f'transitivity_geeq_{i},{j},{k}') # a == b and b >= c --> a >= c model.addLConstr(eq_a + ge_b, GRB.LESS_EQUAL, 1 + ge_c, f'transitivity_eqge_{i},{j},{k}') # a == b and b == c --> a == c model.addLConstr(eq_a + eq_b, GRB.LESS_EQUAL, 1 + eq_c, f'transitivity_eq_{i},{j},{k}') # transitivity helper (for not-fully connected graphs) # also provides a latent rank big_m = max_rank model.addConstrs(((1 - ge_ij) * big_m + R_i[i] >= R_i[j] + 1 for (i, j), ge_ij in Ge_ij.items()), 'rank_transitivity_larger') model.addConstrs(((1 - le_ij) * big_m + R_i[j] >= R_i[i] + 1 for (i, j), le_ij in Le_ij.items()), 'rank_transitivity_smaller') model.addConstrs(((1 - eq_ij) * big_m + R_i[j] >= R_i[i] for (i, j), eq_ij in Eq_ij.items()), 'rank_transitivity_equal1') model.addConstrs(((1 - eq_ij) * big_m + R_i[i] >= R_i[j] for (i, j), eq_ij in Eq_ij.items()), 'rank_transitivity_equal2') # objective function objective = LinExpr() for ij, value in comparisons.items(): if value == 1.0: objective += -E_ij[ij] elif value == 0.0: objective += E_ij[ij] else: objective += T_ij_pos[ij] + T_ij_neg[ij] model.setObjective(objective, GRB.MINIMIZE) # solve model.optimize() # verify abs emulation: one T_ij has to be 0 for ij, value in T_ij_pos.items(): assert value.X == 0 or T_ij_neg[ij] == 0, \ f'T_{ij} pos {value.X} neg {T_ij_neg[ij]}' # find minimal Rs model_ = Model('comparison') model_.setParam('OutputFlag', verbose) R_i = model_.addVars(nodes, name='r_i', vtype=GRB.CONTINUOUS, lb=0, ub=len(nodes)) for ((i, j), ge_ij), le_ij in zip(Ge_ij.items(), Le_ij.values()): if ge_ij.x == 1: model_.addConstr(R_i[i] >= R_i[j] + 1) elif le_ij.x == 1: model_.addConstr(R_i[j] >= R_i[i] + 1) else: model_.addConstr(R_i[j] == R_i[i]) model_.setObjective(R_i.sum(), GRB.MINIMIZE) model_.optimize() return [model_.getVarByName(f'r_i[{i}]').X for i in range(len(nodes))], \ model.objVal
def master(params, time_limit=3600, mip_gap=1): """Genera el modelo maestro de SSTPA""" m = Model("SSTPA Benders Master") m.setParam("TimeLimit", time_limit) m.setParam("LogToConsole", 1) m.setParam("LazyConstraints", 1) m.setParam("MIPGap", mip_gap) # Parse params dict to values N = params['N'] F = params['F'] S = params['S'] I = params['I'] L = params['L'] EL = params['EL'] EV = params['EV'] ################# # * VARIABLES *# ################# # x_nf: x[partido, fecha] # 1 si el partido n se programa finalmente # en la fecha f # 0 en otro caso. x = m.addVars(N, F, vtype=GRB.BINARY, name="x") # y_is: y[equipo][patron_localias] # 1 si al equipo i se le asigna el patron # de localias s # 0 en otro caso y = {i: m.addVars(S[i], vtype=GRB.BINARY, name="y") for i in I} # alfa_jil : alfa[equipo,equipo,fecha] # binaria, toma el valor 1 si el equipo j termina con menos puntos # que el equipo i en el # MEJOR conjunto de # resultados futuros para el equipo i considerando que # se está en la fecha l alfa_m = m.addVars(I, I, F, vtype=GRB.BINARY, name="alfa_m") # alfa_jil : alfa[equipo,equipo,fecha] # binaria, toma el valor 1 si el equipo j tiene termina # con menos puntos que el equipo i, en el PEOR conjunto de # resultados futuros para el equipo i considerando que # se está en la fecha l alfa_p = m.addVars(I, I, F, vtype=GRB.BINARY, name="alfa_p") # beta_il: beta[equipo,fecha] # discreta, indica la mejor posicion # que puede alcanzar el equipo i al final del # torneo, mirando desde la fecha l en el MEJOR # conjunto de resultados futuros para el equipo i beta_m = m.addVars(I, F, vtype=GRB.INTEGER, name="beta_m") # beta_il: beta[equipo, fecha] # discreta, indica la mejor posicion # que puede alcanzar el equipo i al final del # torneo, mirando desde la fecha l en el PEOR # conjunto de resultados futuros para el equipo i beta_p = m.addVars(I, F, vtype=GRB.INTEGER, name="beta_p") ##################### # * RESTRICCIONES *# ##################### # R2 for n in N: m.addConstr((quicksum(x[n, f] for f in F) == 1), name=f"R2-{n}") # R3 for i in I: for f in F: m.addConstr( (quicksum(x[n, f] for n in N if EL[i][n] + EV[i][n] == 1) == 1), name="R3") # R4 m.addConstrs((quicksum(y[i][s] for s in S[i]) == 1 for i in I), name="R4") # R6 for f in F: for i in I: _exp1 = LinExpr(quicksum(x[n, f] for n in N if EL[i][n] == 1)) _exp2 = LinExpr(quicksum(y[i][s] for s in S[i] if L[s][f] == 1)) m.addConstr(_exp1 == _exp2, name=f"R6-{f}-{i}") # R7 for f in F: for i in I: _exp1 = LinExpr(quicksum(x[n, f] for n in N if EV[i][n] == 1)) _exp2 = LinExpr(quicksum(y[i][s] for s in S[i] if L[s][f] == 0)) m.addConstr(_exp1 == _exp2, name=f"R7-{f}-{i}") # R8 for i in I: for l in F: _exp = LinExpr(quicksum(alfa_m[j, i, l] for j in I if i != j)) m.addConstr(beta_m[i, l] == len(I) - _exp, name=f"R8-{i}-{l}") # R9 for i in I: for l in F: _exp = LinExpr(quicksum(alfa_p[j, i, l] for j in I if i != j)) m.addConstr(beta_p[i, l] == len(I) - _exp, name=f"R9-{i}-{l}") ######################### # * FUNCION OBJETIVO *# ######################### _obj = quicksum( quicksum(beta_p[i, l] - beta_m[i, l] for i in I) for l in F) m.setObjective(_obj, GRB.MAXIMIZE) return m
def _create_model(self, job_ids, r_times, p_intervals, m_availabe): ## prepare the index for decision variables # start time of process jobs = tuple(job_ids) machines = tuple(range(len(machine_properties))) # order of executing jobs: tuple list jobPairs = [(i, j) for i in jobs for j in jobs if i < j] # assignment of jobs on machines job_machinePairs = [(i, k) for i in jobs for k in machines] ## parameters model (dictionary) # 1. release time release_time = dict(zip(jobs, tuple(r_times))) # 2. process time process_time = dict(zip(jobs, tuple(p_intervals))) # 3. machiane available time machine_time = dict(zip(machines, tuple(m_availabe))) # 4. define BigM BigM = np.sum(r_times) + np.sum(p_intervals) + np.sum(m_availabe) ## create model m = Model('PMSP') ## create decision variables # 1. assignments of jobs on machines z = m.addVars(job_machinePairs, vtype=GRB.BINARY, name='assign') # 2. order of executing jobs y = m.addVars(jobPairs, vtype=GRB.BINARY, name='order') # 3. start time of executing each job startTime = m.addVars(jobs, name='startTime') ## create objective # m.setObjective(quicksum(startTime), GRB.MINIMIZE) # TOTRY m._max_complete = m.addVar(1, name='max_complete_time') m.setObjective(m._max_complete, GRB.MINIMIZE) # TOTRY m.addConstr((m._max_complete == max_(startTime)), 'minimax') ## create constraints # 1. job release constraint m.addConstrs((startTime[i] >= release_time[i] for i in jobs), 'job release constraint') # 2. machine available constraint m.addConstrs((startTime[i] >= machine_time[k] - BigM * (1 - z[i, k]) for (i, k) in job_machinePairs), 'machine available constraint') # 3. disjunctive constraint m.addConstrs((startTime[j] >= startTime[i] + process_time[i] - BigM * ((1 - y[i, j]) + (1 - z[j, k]) + (1 - z[i, k])) for k in machines for (i, j) in jobPairs), 'temporal disjunctive order1') m.addConstrs((startTime[i] >= startTime[j] + process_time[j] - BigM * (y[i, j] + (1 - z[j, k]) + (1 - z[i, k])) for k in machines for (i, j) in jobPairs), 'temporal disjunctive order2') # 4. one job is assigned to one and only one machine m.addConstrs((quicksum([z[i, k] for k in machines]) == 1 for i in jobs), 'job non-splitting') # set initial solution for (i, k) in job_machinePairs: if (i, k) in assign_list: z[(i, k)].start = 1 else: z[(i, k)].start = 0 for (i, j) in jobPairs: if (i, j) in order_list: y[(i, j)].start = 1 else: y[(i, j)].start = 0 for i in job_ids: startTime[i].start = start_times[i] return m, z, y, startTime
vars = m.addVars(dist.keys(), obj=dist, vtype=GRB.BINARY, name='e') for i, j in vars.keys(): vars[j, i] = vars[i, j] # edge in opposite direction # You could use Python looping constructs and m.addVar() to create # these decision variables instead. The following would be equivalent # to the preceding m.addVars() call... # # vars = tupledict() # for i,j in dist.keys(): # vars[i,j] = m.addVar(obj=dist[i,j], vtype=GRB.BINARY, # name='e[%d,%d]'%(i,j)) # Add degree-2 constraint m.addConstrs(vars.sum(i, '*') == 2 for i in range(n)) # Using Python looping constructs, the preceding would be... # # for i in range(n): # m.addConstr(sum(vars[i,j] for j in range(n)) == 2) # Optimize model m._vars = vars m.Params.lazyConstraints = 1 m.optimize(subtourelim) vals = m.getAttr('x', vars) selected = tuplelist((i, j) for i, j in vals.keys() if vals[i, j] > 0.5)