class Backup(object): """ Class object for normal-based backup network model. Parameters ---------- nodes: set of nodes links: set of links capacity: capacities per link based based on random failures mean: mean for failure random variable std: standard deviation for failure random variable invstd: inverse of Phi-normal distribution for (1-epsilon) Returns ------- solution: set of capacity assigned per backup link. """ # Private model object __model = [] # Private model variables __BackupCapacity = {} __bBackupLink = {} __ValidLink = {} # Private model parameters __links = [] __nodes = [] __capacity = [] __mean = [] __std = [] __invstd = 1 def __init__(self,nodes,links,capacity,mean,std,invstd): ''' Constructor ''' self.__links = links self.__nodes = nodes self.__capacity = capacity self.__mean = mean self.__std = std self.__invstd = invstd self.__loadModel() def __loadModel(self): # Create optimization model self.__model = Model('Backup') # Auxiliary variables for SOCP reformulation U = {} R = {} # Create variables for i,j in self.__links: self.__BackupCapacity[i,j] = self.__model.addVar(lb=0, obj=1, name='Backup_Capacity[%s,%s]' % (i, j)) self.__model.update() for i,j in self.__links: for s,d in self.__links: self.__bBackupLink[i,j,s,d] = self.__model.addVar(vtype=GRB.BINARY,obj=1,name='Backup_Link[%s,%s,%s,%s]' % (i, j, s, d)) self.__model.update() for i,j in self.__links: U[i,j] = self.__model.addVar(obj=1,name='U[%s,%s]' % (i, j)) self.__model.update() for i,j in self.__links: for s,d in self.__links: R[i,j,s,d] = self.__model.addVar(obj=1,name='R[%s,%s,%s,%s]' % (i,j,s,d)) self.__model.update() self.__model.modelSense = GRB.MINIMIZE #m.setObjective(quicksum([fixedCosts[p]*open[p] for p in plants])) self.__model.setObjective(quicksum(self.__BackupCapacity[i,j] for i,j in self.__links)) self.__model.update() #------------------------------------------------------------------------# # Constraints definition # # # # # #------------------------------------------------------------------------# # Link capacity constraints for i,j in self.__links: self.__model.addConstr(self.__BackupCapacity[i,j] >= quicksum(self.__mean[s,d]*self.__bBackupLink[i,j,s,d] for (s,d) in self.__links) + U[i,j]*self.__invstd,'[CONST]Link_Cap_%s_%s' % (i, j)) self.__model.update() # SCOP Reformulation Constraints for i,j in self.__links: self.__model.addConstr(quicksum(R[i,j,s,d]*R[i,j,s,d] for (s,d) in self.__links) <= U[i,j]*U[i,j],'[CONST]SCOP1[%s][%s]' % (i, j)) self.__model.update() # SCOP Reformulation Constraints for i,j in self.__links: for s,d in self.__links: self.__model.addConstr(self.__std[s,d]*self.__bBackupLink[i,j,s,d] == R[i,j,s,d],'[CONST]SCOP2[%s][%s][%s][%s]' % (i, j,s,d)) self.__model.update() for i in self.__nodes: for s,d in self.__links: # Flow conservation constraints if i == s: self.__model.addConstr(quicksum(self.__bBackupLink[i,j,s,d] for i,j in self.__links.select(i,'*')) - quicksum(self.__bBackupLink[j,i,s,d] for j,i in self.__links.select('*',i)) == 1,'Flow1[%s,%s,%s,%s]' % (i,j,s, d)) # Flow conservation constraints elif i == d: self.__model.addConstr(quicksum(self.__bBackupLink[i,j,s,d] for i,j in self.__links.select(i,'*')) - quicksum(self.__bBackupLink[j,i,s,d] for j,i in self.__links.select('*',i)) == -1,'Flow2[%s,%s,%s,%s]' % (i,j,s, d)) # Flow conservation constraints else: self.__model.addConstr(quicksum(self.__bBackupLink[i,j,s,d] for i,j in self.__links.select(i,'*')) - quicksum(self.__bBackupLink[j,i,s,d] for j,i in self.__links.select('*',i)) == 0,'Flow3[%s,%s,%s,%s]' % (i,j,s, d)) self.__model.update() def optimize(self,MipGap, TimeLimit): self.__model.write('backup.lp') if MipGap != None: self.__model.params.timeLimit = TimeLimit if TimeLimit != None: self.__model.params.MIPGap = MipGap # Compute optimal solution self.__model.optimize() # Print solution if self.__model.status == GRB.Status.OPTIMAL: solution = self.__model.getAttr('x', self.__BackupCapacity) for i,j in self.__links: if solution[i,j] > 0: print('%s -> %s: %g' % (i, j, solution[i,j])) else: print('Optimal value not found!\n') solution = [] return solution; def reset(self): ''' Reset model solution ''' self.__model.reset()
def create_problem(cobra_model, objective_sense="maximize"): lp = Model("cobra") lp.Params.OutputFlag = 0 if objective_sense == 'maximize': objective_sign = -1.0 elif objective_sense == 'minimize': objective_sign = 1.0 else: raise ValueError("objective_sense must be 'maximize' or 'minimize'") # create metabolites/constraints metabolite_constraints = {} for metabolite in cobra_model.metabolites: metabolite_constraints[metabolite] = \ lp.addConstr(0.0, sense_dict[metabolite._constraint_sense], metabolite._bound, metabolite.id) lp.update() # create reactions/variables along with S matrix for j, reaction in enumerate(cobra_model.reactions): constraints = [metabolite_constraints[i] \ for i in reaction._metabolites] stoichiometry = reaction._metabolites.values() lp.addVar( lb=float(reaction.lower_bound), ub=float(reaction.upper_bound), obj=objective_sign * reaction.objective_coefficient, name=reaction.id, vtype=variable_kind_dict[reaction.variable_kind], column=Column(stoichiometry, constraints)) lp.update() return lp
class MainProblem: def __init__(self): self.model = Model("main_problem") self.x_1 = self.model.addVar(lb=0, name="x_1") self.x_2 = self.model.addVar(lb=0, name="x_2") self.x_3 = self.model.addVar(lb=0, name="x_3") self.x_4 = self.model.addVar(lb=0, name="x_4") self.x_5 = self.model.addVar(lb=0, name="x_5") self.model.addConstr(self.x_1 + self.x_4 + self.x_5 <= 3) self.model.addConstr(2 * self.x_2 + 3 * self.x_4 <= 12) self.model.addConstr(self.x_3 - 7 * self.x_5 <= -16) self.model.addConstr(-self.x_4 + self.x_5 <= 2) self.x_hat_4 = None self.x_hat_5 = None self.model.setObjective( -2 * self.x_1 - self.x_2 + self.x_3 + 3 * self.x_4 - 3 * self.x_5, GRB.MINIMIZE, ) def solve(self): self.model.optimize() return self.model.objVal
def build_model(plants, warehouses, capacity, demand, fixed_costs, trans_costs): # decision variables m = Model("facility") is_open = [] for p in plants: is_open.append(m.addVar(vtype=GRB.BINARY, name="is_open[{}]".format(p))) trans_qty = [] for w in warehouses: trans_qty.append([]) for p in plants: trans_qty[w].append(m.addVar(vtype=GRB.CONTINUOUS, name="trans_qty[{}.{}]".format(p, w), lb=0.0)) m.update() # objective function m.setObjective(quicksum(fixed_costs[p] * is_open[p] for p in plants) + quicksum(trans_costs[w][p] * trans_qty[w][p] for w in warehouses for p in plants), GRB.MINIMIZE) # constraints for p in plants: m.addConstr(quicksum(trans_qty[w][p] for w in warehouses) <= capacity[p] * is_open[p], "Capacity({})".format(p)) for w in warehouses: m.addConstr(quicksum(trans_qty[w][p] for p in plants) == demand[w], "Demand({})".format(w)) m.update() return m
class MasterProblem: def __init__(self): self.model = Model("benders_master_problem") self.x_4 = self.model.addVar(lb=0, name="x_4") self.x_5 = self.model.addVar(lb=0, name="x_5") self.phi = self.model.addVar(lb=-100 * 100 * 100, name="phi") self.model.addConstr(-self.x_4 + self.x_5 <= 2) self.model.setObjective( 3 * self.x_4 - 3 * self.x_5 + self.phi, GRB.MINIMIZE, ) def add_cut(self, lhs, pi_1, pi_2): self.model.addConstr( lhs <= self.phi - self.x_4 * pi_1 - self.x_5 * pi_2, name="cut") def solve(self): self.model.optimize() return ( self.model.objVal, self.x_4.x, self.x_5.x, )
def solve_lp_knapsack_gurobi(scores, costs, budget): from gurobipy import Model, LinExpr, GRB n = len(scores) # Create a new model. m = Model("lp_knapsack") # Create variables. for i in range(n): m.addVar(lb=0.0, ub=1.0) m.update() vars = m.getVars() # Set objective. obj = LinExpr() for i in range(n): obj += scores[i] * vars[i] m.setObjective(obj, GRB.MAXIMIZE) # Add constraint. expr = LinExpr() for i in range(n): expr += costs[i] * vars[i] m.addConstr(expr, GRB.LESS_EQUAL, budget) # Optimize. m.optimize() assert m.status == GRB.OPTIMAL x = np.zeros(n) for i in range(n): x[i] = vars[i].x return x
def create_problem(cobra_model, objective_sense="maximize"): lp = Model("cobra") lp.Params.OutputFlag = 0 if objective_sense == "maximize": objective_sign = -1.0 elif objective_sense == "minimize": objective_sign = 1.0 else: raise ValueError("objective_sense must be 'maximize' or 'minimize'") # create metabolites/constraints metabolite_constraints = {} for metabolite in cobra_model.metabolites: metabolite_constraints[metabolite] = lp.addConstr( 0.0, sense_dict[metabolite._constraint_sense], metabolite._bound, metabolite.id ) lp.update() # create reactions/variables along with S matrix for j, reaction in enumerate(cobra_model.reactions): constraints = [metabolite_constraints[i] for i in reaction._metabolites] stoichiometry = reaction._metabolites.values() lp.addVar( lb=float(reaction.lower_bound), ub=float(reaction.upper_bound), obj=objective_sign * reaction.objective_coefficient, name=reaction.id, vtype=variable_kind_dict[reaction.variable_kind], column=Column(stoichiometry, constraints), ) lp.update() return lp
def solve_optimal_gurobi(matrix): """ Solves a given tsp instance optimal using the python gurobi solver interface. Returns a list of indices. The result list has a cardinality of the length of the matrix. """ model = Model() model.Params.OutputFlag = 0 n = len(matrix); N = list(range(n)) # Create variables x = [[model.addVar(vtype=GRB.BINARY, ub=1.0, lb=0.0, name='x{}{}'.format(i,j)) for j in N] for i in range(n)] u = [ model.addVar(vtype=GRB.CONTINUOUS, name='u{}'.format(i)) for i in N] # miller tucker vars model.update() # Set objective sum_tour_length = [x[i][j] * matrix[i][j] for i in N for j in N] model.setObjective(quicksum(sum_tour_length), GRB.MINIMIZE) # Constraints for assignment problem: [model.addConstr(quicksum([x[i][j] for j in range(n)]) == 1) for i in N] [model.addConstr(quicksum([x[i][j] for i in range(n)]) == 1) for j in N] # Constraints for subtour elimination: [model.addConstr(2 <= u[i] <= n) for i in N[1:]] [model.addConstr(u[i] - u[j] + 1 <= (n-1)*(1-x[i][j])) for i in N[1:] for j in N[1:]] model.update() #model.write('gurobi.lp') model.optimize() if model.status == GRB.Status.OPTIMAL: return __grb_retrieve_tour(model, x)
class WheatSubProblem: def __init__(self, cfg: Config): self.cfg = cfg # model.ModelSense is minimization by default self.model = Model("wheat_sub_problem") self.x_1 = self.model.addVar(ub=self.cfg.area, name="x_1") probability = 1 / len(self.cfg.scenarios) for index, scenario in enumerate(self.cfg.scenarios): self._variables_constraint(index, scenario, probability) def _variables_constraint(self, index, scenario, probability): y_11 = self.model.addVar(name=f"y_11_{index}", obj=self.cfg.wheat.buy_price * probability) y_12 = self.model.addVar(name=f"y_12_{index}", obj=-self.cfg.wheat.sell_price * probability) self.model.addConstr( self.cfg.wheat.requirement <= self.x_1 * self.cfg.wheat.produce_rate * (1 + scenario) + y_11 - y_12, name="wheat_produce_constraint", ) def solve(self, _lambda): self.x_1.obj = _lambda + self.cfg.wheat.plant_cost self.model.optimize() return ( self.model.objVal, self.x_1.x, )
def solve(budget, buses, lines, u, c, b, S, D): m = Model('inhibit') w, v, y = {}, {}, {} for i in buses: w[i] = m.addVar(vtype=GRB.BINARY, name="w_%s" % i) for i, j in lines: v[i, j] = m.addVar(vtype=GRB.BINARY, name='v_%s_%s' % (i, j)) y[i, j] = m.addVar(vtype=GRB.BINARY, name='y_%s_%s' % (i, j)) m.update() for i, j in lines: m.addConstr(w[i] - w[j] <= v[i, j] + y[i, j], 'balance1_%s_%s' % (i, j)) m.addConstr(w[j] - w[i] <= v[i, j] + y[i, j], 'balance2_%s_%s' % (i, j)) m.addConstr( quicksum(c[i, j] * y[i, j] for i, j in lines) <= budget, 'budget') m.setObjective( quicksum(u[i, j] * v[i, j] for i, j in lines) + quicksum(b[i] * (1 - w[i]) for i in S) - quicksum(b[i] * w[i] for i in D)) m.setParam('OutputFlag', 0) m.optimize() m.write('gurobi.lp') return w, v, y, m
def calculate_sample_weights(pred, c, D, prev_sample_weights=None): # Dual problem tree_count = len(pred) sample_count = len(c) m = Model("sample_weight_optimiser") sample_weights = [ m.addVar(vtype=GRB.CONTINUOUS, name="sample_weights " + str(i), ub=D if D > 0 else 1) for i in range(sample_count) ] # Set sample weights to given value if prev_sample_weights is not None: for i in range(min(len(prev_sample_weights), len(sample_weights))): sample_weights[i].setAttr("Start", prev_sample_weights[i]) gamma = m.addVar(vtype=GRB.CONTINUOUS, name="gamma", lb=float("-inf")) m.setObjective(gamma, GRB.MINIMIZE) m.addConstr(quicksum(sample_weights) == 1, name="weights = 1") for t in range(tree_count): m.addConstr(quicksum([ c[i] * sample_weights[i] * pred[t][i] for i in range(sample_count) ]) <= gamma, name="Constraint on tree " + str(t)) m.setParam("LogToConsole", 0) m.optimize() return [w.X for w in sample_weights], gamma.X
def compute_plane(self, batch, row, col, candidates, candidate_flows, is_lower): model = Model() model.setParam('OutputFlag', False) model.setParam('NumericFocus', 2) a = model.addVar(lb=-GRB.INFINITY, ub=GRB.INFINITY) b = model.addVar(lb=-GRB.INFINITY, ub=GRB.INFINITY) c = model.addVar(lb=-GRB.INFINITY, ub=GRB.INFINITY) differences = list() for candidate, flow in zip(candidates, candidate_flows): (x, y), z = flow[batch, row, col], candidate[batch, row, col] x, y, z = x.item(), y.item(), z.item() if is_lower: model.addConstr(a + b * x + c * y <= z) differences.append(z - a + b * x + c * y) else: model.addConstr(a + b * x + c * y >= z) differences.append(a + b * x + c * y - z) model.setObjective(quicksum(differences), sense=GRB.MINIMIZE) model.optimize() if model.status != GRB.OPTIMAL: raise ValueError('Gurobi: objective not optimal') return a.x, b.x, c.x
def add_set_flag( m: gModel, label: str, x_var: gVar, A: Sequence[Sequence[float]], b: Sequence[float], K: float, ) -> gVar: if len(A) == 1: delta = m.addVar(vtype=g.GRB.BINARY, name=label) deltas = [delta] else: deltas = [ m.addVar(vtype=g.GRB.BINARY, name=delta_label(label, i)) for i in range(len(A)) ] delta = m.addVar(vtype=g.GRB.BINARY, name=label) for i in range(len(A)): m.addConstr( g.quicksum(A[i][j] * x_var[j] for j in range(len(x_var))) - deltas[i] * K <= b[i]) m.addConstr( g.quicksum(A[i][j] * x_var[j] for j in range(len(x_var))) + (1 - deltas[i]) * K >= b[i]) if len(A) > 1: for i in range(len(A)): m.addConstr(delta >= deltas[i]) m.addConstr(delta <= g.quicksum(deltas)) return delta
def q2(): from gurobipy import Model, GRB, quicksum, LinExpr import numpy from functions import open_data # Creation of the model m = Model('LR') # Your code goes here x, y = open_data() N, n = len(x), len(x[0]) # The following example is here to help you build the model (you must adapt it !!!) # Define decision variables var = [] # w, b, z for i in range(n): var.append(m.addVar(lb = -GRB.INFINITY, vtype=GRB.CONTINUOUS, name = 'w_{}'.format(i), obj = 1)) var.append(m.addVar(lb = -GRB.INFINITY, vtype=GRB.CONTINUOUS, name = 'b'.format(i), obj = 1)) for i in range(N): var.append(m.addVar(lb = 0, vtype=GRB.CONTINUOUS, name = 'z_{}'.format(i), obj = 1)) #m.update() # Constraints expr={} for j in range(N): expr = LinExpr() for i in range(n): expr += -var[i]*x[j][i] expr += -var[n] expr += -var[n+1+j] m.addConstr(expr, GRB.LESS_EQUAL, -y[j]) expr = LinExpr() for i in range(n): expr.add(var[i], x[j][i]) expr += var[n] expr += -var[n+1+j] m.addConstr(expr, GRB.LESS_EQUAL, y[j]) # Define objective function: obj=LinExpr() for i in range(N): obj += var[n+1+i] m.setObjective(obj, GRB.MINIMIZE) m.update() m.optimize() m.write('q2.lp') # Your code goes here #if m.status == GRB.Status.OPTIMAL: z = m.objVal b = var[n].x w = [v.x for v in var[:n]] #print([v.x for v in var[n+1:]]) return ([z, b, w])
def re_verification_tree_extension(s, x, G, i, state_end, factor=0.99): """ This is a method to deal with numerical inaccuracies in high dimensioanl MILPs that are terminated early. Requires solving a linear program. If feasible, the computed control startegy is recomputed. If infeasible, report back, raise a flag, and abort the tree extention Inputs: state_X, state_end Output: flag, u, theta """ model = Model("verifying tree extention") G_dynamic = np.empty((s.n, s.n), dtype='object') theta = np.empty((s.m, s.n), dtype='object') u = np.empty((s.m, 1), dtype='object') x_bar = np.empty((s.n, 1), dtype='object') for row in range(s.n): for column in range(s.n): G_dynamic[row, column] = model.addVar(lb=-GRB.INFINITY, ub=GRB.INFINITY) for row in range(s.m): u[row, 0] = model.addVar(lb=-GRB.INFINITY, ub=GRB.INFINITY) for column in range(s.n): theta[row, column] = model.addVar(lb=-GRB.INFINITY, ub=GRB.INFINITY) for row in range(s.n): x_bar[row, 0] = model.addVar(lb=-GRB.INFINITY, ub=GRB.INFINITY) model.update() for row in range(s.n): for column in range(s.n): AG = LinExpr() for k in range(s.n): AG.add(s.A[i][row, k] * G[k, column]) for k in range(s.m): AG.add(s.B[i][row, k] * theta[k, column]) model.addConstr(G_dynamic[row, column] == AG * factor) for row in range(s.n): Bu = LinExpr() for k in range(s.m): Bu.add(s.B[i][row, k] * u[k, 0]) model.addConstr(x_bar[row, 0] == np.dot(s.A[i], x)[row, 0] + Bu + s.c[i][row, 0]) eps = subset_eps(model, G_dynamic, s.Pi, state_end.polytope.H, state_end.polytope.h, x_bar) subset(model, theta, s.Pi, s.F[i], s.f[i], u) model.setParam("OutputFlag", False) model.optimize() if model.Status == 2: print("eps=", valuation(eps).T) if np.amax(valuation(eps)) > 10**-3: print( "\n-" * 10, "Too large of Epsilon: %d Tree extention failed!" % np.amax(valuation(eps)), "\n-" * 10) return None else: print("Tree extention verified succesuflly!") return (valuation(u), valuation(theta), valuation(eps)) else: print("\n-" * 10, "Infeasible! Tree extention failed!", "\n-" * 10) return None
def repair(self): this = self data_size = self.instance.size() def get_cj(j, x_vars): x_list = [x_vars[i][j] for i in xrange(data_size)] multi_list = list() for k in xrange(data_size): if k not in self.neighbor_map[j]: continue for i in xrange(data_size): multi_list.append(x_vars[i][k]) return quicksum(x_list) + quicksum(multi_list) def build_objective(x_vars): result = list() for i, record1 in enumerate(this.instance.data): for j, record2 in enumerate(this.instance.data): result.append(record1.distance(record2) * x_vars[i][j]) return result try: m = Model('mip1') x = list() y = list() for i, record in enumerate(self.instance.data): variables = [m.addVar(vtype=GRB.BINARY, name='x_%d_%d' % (i, j)) for j in xrange(data_size)] x.append(variables) y.append(m.addVar(vtype=GRB.BINARY, name='y_%d' % i)) m.addConstr(quicksum(x[i]) == 1, name='sum_%d' % i) for j, record in enumerate(self.instance.data): c_j = get_cj(j, x) m.addConstr(c_j - self.k * y[j] >= 0, name='constr_1_%d' % j) m.addConstr(y[j] * data_size - c_j >= 1 - self.k, name='constr_2_%d' % j) m.addConstr(y[j] + quicksum([y[i] if i in self.neighbor_map[j] else 0 for i in xrange(data_size)]) - quicksum([x[k][j] for k in xrange(data_size)]) / float(data_size) >= 0, name='constr_3_%d' % j) m.setObjective(quicksum(build_objective(x))) print '---- Begin to solve the ILP ----' m.optimize() repair_result = list() for v in m.getVars(): if v.varName.startswith('x') and v.x == 1: _, record_id, candidate_id = v.varName.split('_') repair_result.append((int(record_id), int(candidate_id))) print('Obj: %g' % m.objVal) return repair_result except GurobiError as e: print('Error code ' + str(e.errno) + ": " + str(e)) except AttributeError: import traceback; traceback.print_exc() print('Encountered an attribute error')
def VRPSol(n, K, C, Ps, Ds, d, F, TimeLimit): m = Model() m.setParam(GRB.Param.TimeLimit, TimeLimit) # Create variables x = {} for i in Ps: for j in Ps: if i != j : x[i,j] = m.addVar(obj=F(Ps[i], Ps[j]), vtype=GRB.BINARY, name='x'+str(i)+'_'+str(j)) # Create Miller variables (subtour elimination) u = {} for i in Ds: if i != d: u[i] = m.addVar(obj=0.0, vtype=GRB.CONTINUOUS, lb=Ds[i], ub=C, name='u'+str(i)) m.update() # Add outdegree constraint for j in Ps: if j != d: Ls = list(filter(lambda z: z!=j, Ps)) m.addConstr(quicksum(x[i,j] for i in Ls) == 1) # Add indegree constraint for i in Ps: if i != d: Ls = filter(lambda z: z!=i, Ps) m.addConstr(quicksum(x[i,j] for j in Ls) == 1) # Number of vehicles Ls = list(filter(lambda z: z!=d, Ps)) m.addConstr(quicksum(x[i,d] for i in Ls) == K) m.addConstr(quicksum(x[d,j] for j in Ls) == K) # Subtour elimination constraints for i in Ls: for j in Ls: if i != j: m.addConstr( u[i] - u[j] +C*x[i,j] <= C - Ds[j] ) m.update() # Solve the model m.optimize() solution = m.getAttr('x', x) selected = [(i,j) for (i,j) in solution if solution[i,j] > 0.5] # Xs = [p for p in Ps.values()] # Ws = [w for w in Ds.values()] # for i,j in selected: # DisegnaSegmento(Ps[i], Ps[j]) # plt.scatter([i for i,j in Xs[1:]], [j for i,j in Xs[1:]], # s=Ws[1:], alpha=0.3, cmap='viridis') # plt.plot([Xs[0][0]], [Xs[0][1]], marker='s', color='red', alpha=0.5) # plt.axis('square') # plt.axis('off') return m.objVal, selected
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 fair_l1_solution(old_solutions, num_patients): solutions = process_solutions(old_solutions) num_solutions = len(solutions) patient_to_solutions = [[] for _ in range(num_patients)] for s, solution in enumerate(solutions): for p in solution: patient_to_solutions[p].append(s) model = Model() model.params.OutputFlag = 0 solution_probs = [ model.addVar(lb=0.0, ub=1.0, vtype=GRB.CONTINUOUS) for _ in range(num_solutions) ] model.addConstr(quicksum(solution_probs), GRB.EQUAL, 1.0) patient_probs = [ model.addVar(lb=0.0, ub=1.0, vtype=GRB.CONTINUOUS) for _ in range(num_patients) ] for i in range(num_patients): expr = quicksum(solution_probs[j] for j in patient_to_solutions[i]) model.addConstr(patient_probs[i], GRB.EQUAL, expr) m = model.addVar(lb=0.0, ub=1.0, vtype=GRB.CONTINUOUS) model.addConstr(quicksum(patient_probs), GRB.EQUAL, num_patients * m) distance_to_mean = [ model.addVar(lb=0.0, ub=1.0, vtype=GRB.CONTINUOUS) for _ in range(num_patients) ] for i in range(num_patients): model.addConstr(distance_to_mean[i], GRB.GREATER_EQUAL, patient_probs[i] - m) model.addConstr(distance_to_mean[i], GRB.GREATER_EQUAL, m - patient_probs[i]) model.setObjective(quicksum(distance_to_mean), GRB.MINIMIZE) model.optimize() #return [solution_probs[i].x for i in range(num_solutions)] if (model.status == GRB.Status.OPTIMAL): solution_prob_dict = {} for i in range(num_solutions): solution_prob_dict[i] = solution_probs[i].x return solution_prob_dict else: return {}
def fair_maxmin_solution(solutions, num_patients): model = Model('maximin_fair') model.params.outputflag = 0 solutions = process_solutions(solutions) solution_size = len(solutions) solution_dict = {} dict_array = [] solution_vars = [] for i in range(solution_size): p = model.addVar(lb=0, ub=1, vtype=GRB.CONTINUOUS) solution_dict[i] = p solution_vars.append(p) solution_exprt = quicksum(solution_vars) model.addConstr(solution_exprt, GRB.EQUAL, 1.0) node_prob_dict = {} for i in range(solution_size): for item in solutions[i]: if int(item) in node_prob_dict.keys(): node_prob_dict[int(item)].append(i) else: node_prob_dict[int(item)] = [i] y = model.addVar(lb=0, ub=1.0, vtype=GRB.CONTINUOUS) for key, value in node_prob_dict.items(): tmp = [] for solution in value: tmp.append(solution_dict[solution]) expr = quicksum(tmp) #expr_constant = float(len(value)) model.addConstr(expr, GRB.GREATER_EQUAL, y) model.update() model.setObjective(y, GRB.MAXIMIZE) model.update() try: model.optimize() except e: print(e) if (model.status == GRB.Status.OPTIMAL): solution_prob_dict = {} for key, value in solution_dict.items(): solution_prob_dict[key] = value.x return solution_prob_dict else: return {}
class MasterProblem: def __init__(self): self.model = Model("benders_master_problem") self.x_1 = self.model.addVar(lb=0, name="x_1", vtype=GRB.BINARY) self.x_2 = self.model.addVar(lb=0, name="x_2", vtype=GRB.BINARY) self.phi = self.model.addVar(lb=-100, name="phi") self.model.addConstr(self.x_1 + self.x_2 <= 1) self.model.setObjective( 3 * self.x_1 + 5 * self.x_2 + self.phi, GRB.MINIMIZE, ) def add_cut(self, lhs, x_hat_1, x_hat_2): if x_hat_1 == 1 and x_hat_2 == 0: self.model.addConstr( lhs + BIG_M * (self.x_1 - 1) - BIG_M * (self.x_2) <= self.phi, name="cut", ) if x_hat_1 == 0 and x_hat_2 == 1: self.model.addConstr( lhs - BIG_M * (self.x_1) + BIG_M * (self.x_2 - 1) <= self.phi, name="cut", ) if x_hat_1 == 0 and x_hat_2 == 0: self.model.addConstr( lhs - BIG_M * (self.x_1) - BIG_M * (self.x_2) <= self.phi, name="cut", ) if x_hat_1 == 1 and x_hat_2 == 1: self.model.addConstr( lhs + BIG_M * (self.x_1 - 1) + BIG_M * (self.x_2 - 1) <= self.phi, name="cut", ) def solve(self): self.model.optimize() print() print(f"PHI: {self.phi.x}") print(f"X_1: {self.x_1.x}") print(f"X_2: {self.x_2.x}") print() return ( self.model.objVal, self.x_1.x, self.x_2.x, )
def mip_gurobipy(x, y0, n, m, N): from gurobipy import Model, GRB, quicksum # set big M M = 100 # generate model model = Model('linear regression_mip') # variables r = [ model.addVar(name='r({})'.format(i), vtype=GRB.CONTINUOUS) for i in range(n) ] t = [ model.addVar(name='t({})'.format(i), vtype=GRB.CONTINUOUS) for i in range(n) ] q = [ model.addVar(name='q({})'.format(i), vtype=GRB.BINARY) for i in range(n) ] b = [ model.addVar(name='b({})'.format(j), lb=-inf, vtype=GRB.CONTINUOUS) for j in range(m) ] # objective model.setObjective(quicksum(r[i] - t[i] for i in range(n)), GRB.MINIMIZE) # constraints for i in range(n): model.addConstr(r[i] >= y0[i] - quicksum(x[j, i] * b[j] for j in range(m))) model.addConstr(r[i] >= quicksum(x[j, i] * b[j] for j in range(m)) - y0[i]) model.addConstr(t[i] <= M * (1 - q[i])) model.addConstr(t[i] <= r[i]) model.addConstr(quicksum(q[i] for i in range(n)) >= N) # optimize model.optimize() # get results r_sol = [r[i].x for i in range(n)] q_sol = [round(q[i].x) for i in range(n)] b_sol = [b[j].x for j in range(m)] t_sol = [t[i].x for i in range(n)] return r_sol, q_sol, b_sol
class MasterProblem: """ Benders's master problem. In each iteration a new cut will be added into this. """ def __init__(self, cfg: Config): self.model = Model("benders_master_porblem") self.cfg = cfg self.x_1 = self.model.addVar(vtype=GRB.CONTINUOUS, lb=0, name="x_1") self.x_2 = self.model.addVar(vtype=GRB.CONTINUOUS, lb=0, name="x_2") self.x_3 = self.model.addVar(vtype=GRB.CONTINUOUS, lb=0, name="x_3") self.phi = self.model.addVar(vtype=GRB.CONTINUOUS, lb=-100 * 100 * 100, name="phi") self.model.addConstr(self.x_1 + self.x_2 + self.x_3 <= cfg.area, name="area_constraint") self.model.setObjective( self.x_1 * cfg.wheat.plant_cost + self.x_2 * cfg.corn.plant_cost + self.x_3 * cfg.beet.plant_cost + self.phi, GRB.MINIMIZE, ) def add_cut(self, lhs, pi_1, pi_2, pi_3): """ add_cut adds new cuts to master problem based on given dual values and constant. these parameters come from the sub problem optimal solution in each benders iteration. """ self.model.addConstr( lhs <= self.phi - self.x_1 * pi_1 - self.x_2 * pi_2 - self.x_3 * pi_3, name="cut", ) def solve(self): """ solve solves master problem and returns the optimal solution """ self.model.optimize() return ( self.model.objVal, self.x_1.x, self.x_2.x, self.x_3.x, )
def build_gurobi_model(case): G, B = case.G, case.B P = real(case.demands) Q = imag(case.demands) branches = case.branch_list n = len(case.demands) vhat = case.vhat s2 = 2**.5 gens = {bus: gen.v for bus, gen in case.gens.items()} del gens[0] m = GurobiModel("jabr") u = [m.addVar(name='u_%d' % i) for i in range(n)] R = {(i, j): m.addVar(name='R_%d_%d' % (i, j)) for i, j in branches} I = {(i, j): m.addVar(lb=-GRB.INFINITY, name='I_%d_%d' % (i, j)) for i, j in branches} for i, j in branches: R[j, i] = R[i, j] I[j, i] = I[i, j] m.update() m.addConstr(u[0] == vhat * vhat / s2, 'u0') for gen, v in gens.iteritems(): m.addConstr(u[gen] == v * v / s2, 'u%d' % gen) for i, j in branches: m.addQConstr(2 * u[i] * u[j] >= R[i, j] * R[i, j] + I[i, j] * I[i, j], 'cone_%d_%d' % (i, j)) k = lambda i: (j for j in B[i, :].nonzero()[1]) s = lambda i, j: 1 if i < j else -1 for i in range(1, n): m.addConstr( -s2 * u[i] * G[i, :].sum() + quicksum(G[i, j] * R[i, j] + B[i, j] * s(i, j) * I[i, j] for j in k(i)) == P[i], 'real_flow_%d_%d' % (i, j)) if i in gens: continue m.addConstr( s2 * u[i] * B[i, :].sum() + quicksum(-B[i, j] * R[i, j] + G[i, j] * s(i, j) * I[i, j] for j in k(i)) == Q[i], 'reac_flow_%d_%d' % (i, j)) m.setObjective(quicksum(R[i, j] for i, j in branches), sense=GRB.MAXIMIZE) m.params.outputFlag = 0 #m.params.barQCPConvTol = 5e-10 m.optimize() if m.status != 2: raise ValueError("gurobi failed to converge: %s (check log)" % m.status) u_opt = [x.getAttr('x') for x in u] R_opt = {(i, j): x.getAttr('x') for (i, j), x in R.items()} I_opt = {(i, j): x.getAttr('x') for (i, j), x in I.items()} return u_opt, R_opt, I_opt
def generateInstance(self): def euc_dist(bor, sh): dx = bor["x_coord"] - sh["x_coord"] dy = bor["y_coord"] - sh["y_coord"] return math.sqrt(dx * dx + dy * dy) model = Model('FireSolver') # Generate variables x = {} for bor in self.boroughs: # New firehouses for fh in self.new_firehouses + self.old_firehouses: name = "x_" + fh["loc_id"] + "_" + bor["loc_id"] x[bor["loc_id"], fh["loc_id"]] = model.addVar(name=name, vtype ="b", obj=self.cost_coef * euc_dist(bor, fh)) # Open variables openfh = {} for fh in self.new_firehouses: openfh[fh["loc_id"]] = model.addVar(name = "open_" + fh["loc_id"], vtype ="b", obj=fh["construction_cost"]) # Close variables closefh = {} for fh in self.old_firehouses: closefh[fh["loc_id"]] = model.addVar(name = "close_" + fh["loc_id"], vtype ="b", obj=fh["destruction_cost"]) model.modelSense = GRB.MINIMIZE model.update() # Constraints: one firehouse / borough for bor in self.boroughs: model.addConstr(quicksum(x[key] for key in x if key[0] == bor["loc_id"]) == 1) # capacity of firehouses for fh in self.new_firehouses: model.addConstr(quicksum(x[key] for key in x if key[1] == fh["loc_id"]) <= self.capacity * openfh[fh["loc_id"]]) # If it is not removed, the initial assignment needs to be respected for fh in self.old_firehouses: for bor in self.boroughs: if bor["currently_protected_by"] == fh["loc_id"]: model.addConstr(x[bor["loc_id"], fh["loc_id"]] == 1 - closefh[fh["loc_id"]]) else: model.addConstr(x[bor["loc_id"], fh["loc_id"]] == 0) # solve it model.optimize() self.model = model
def build_ilp(g, eqs, forbidden, simple_cycles, match): m = Model() m.setAttr('ModelSense', GRB.MAXIMIZE) edges = sorted(g.edges(eqs)) # y: is edge e in the matching? The worth of each allowed match is 1. obj_coeff = {e: (1 if e not in forbidden else 0) for e in edges} y = {e: m.addVar(vtype=GRB.BINARY, obj=obj_coeff[e]) for e in edges} m.update() # An equation is matched at most once for eq in eqs: add_matched_at_most_once_con(m, y, g.edges(eq)) # A variable is matched at most once set_eqs = set(eqs) vrs = sorted(v for v in g if v not in set_eqs) for v in vrs: add_matched_at_most_once_con(m, y, list( (eq, v) for v, eq in g.edges(v))) # break_each_cycle_at_least_once(eqs, m, y, simple_cycles) # set_lower_bound_if_any(g, eqs, m, y) # # Set feasible solution from the matching, if any if match is not None: match = set(match) for edge, var in iteritems(y): var.setAttr('Start', 1 if edge in match else 0) return m, y
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
def gurobi_qp(self, qp): n = qp.H.shape[1] model = Model() x = { i: model.addVar( vtype=GRB.CONTINUOUS, name='x_%d' % i, lb=qp.lb, ub=qp.ub) for i in range(n) } model.update() obj = QuadExpr() rows, cols = qp.H.nonzero() for i, j in zip(rows, cols): obj += 0.5 * x[i] * qp.H[i, j] * x[j] for i in range(n): obj += qp.f[i] * x[i] model.setObjective(obj, GRB.MINIMIZE) if qp.A is not None: A_nonzero_rows = get_nonzero_rows(qp.A) for i, row in A_nonzero_rows.items(): model.addConstr(quicksum(qp.A[i, j] * x[j] for j in row) <= qp.b[i]) if qp.Aeq is not None: A_nonzero_rows = get_nonzero_rows(qp.Aeq) for i, row in A_nonzero_rows.items(): model.addConstr(quicksum(qp.Aeq[i, j] * x[j] for j in row) == qp.beq[i]) model.optimize() self.solution = empty(n) for i in range(n): self.solution[i] = model.getVarByName('x_%d' % i).x
def sample_from_polytope(polytope): """ A random point in H,h """ model=Model("Polytope Sampling") n=polytope.H.shape[1] alpha=np.random.random((n,1))-0.5 theta=model.addVar(lb=-GRB.INFINITY,ub=GRB.INFINITY) model.update() Hx_Anchor=np.dot(polytope.H,polytope.anchor) H_alpha=np.dot(polytope.H,alpha) for row in range(polytope.H.shape[0]): model.addConstr(H_alpha[row,0]*theta+Hx_Anchor[row,0]<=polytope.h[row]) model.setObjective(theta,GRB.MINIMIZE) model.setParam('OutputFlag',False) model.optimize() theta_min=theta.X model.reset() model.setObjective(theta,GRB.MAXIMIZE) model.optimize() theta_max=theta.X c=rand() x_sample=(polytope.anchor+alpha*theta_min)*c+(polytope.anchor+alpha*theta_max)*(1-c) polytope.anchor=x_sample return x_sample
def construct_lp_model(c, A, d): from gurobipy import Model, LinExpr, GRB # A = numpy.array (matrix) # c = numpy.array (vector) # d = numpy.array (vector) k, n = A.shape # Creation of the gurobi model m = Model("sp") # Variables x = list() for i in range(n): x.append(m.addVar(lb=-GRB.INFINITY, ub=GRB.INFINITY, name='x_%d' % i)) # Objective Function objExpr = LinExpr() for i in range(n): objExpr.add(x[i], c[i]) m.setObjective(objExpr, GRB.MAXIMIZE) # Constraints expr = {} for j in range(k): expr = LinExpr() for i in range(n): expr.add(x[i], A[j, i]) m.addConstr(expr, GRB.LESS_EQUAL, d[j]) # Update the model to add new entries m.update() return m
def _construct_smore_lp(self, G, edge_to_paths, num_total_paths): m = Model('min-edge-util') # Create variables: one for each path path_vars = m.addVars(num_total_paths, vtype=GRB.CONTINUOUS, lb=0.0, ub=1.0, name='f') max_link_util_var = m.addVar(vtype=GRB.CONTINUOUS, lb=0.0, name='z') m.update() m.setObjective(max_link_util_var, GRB.MINIMIZE) # Add demand constraints for k, d_k, path_ids in self.commodities: m.addConstr(quicksum(path_vars[p] for p in path_ids) == 1) # Add edge util constraints for u, v, c_e in G.edges.data('capacity'): paths = edge_to_paths[(u, v)] constr_vars = [ path_vars[p] * self.commodities[self._path_to_commod[p]][-2] for p in paths ] m.addConstr(quicksum(constr_vars) / c_e <= max_link_util_var) return LpSolver(m, None, self.DEBUG, self.VERBOSE, self.out)
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 check_redundancy_row(H, h, ROW, atol=10**-8): model = Model("Row Redundancy Check") n = H.shape[1] x = np.empty((n, 1), dtype='object') for row in range(n): x[row, 0] = model.addVar(lb=-GRB.INFINITY, ub=GRB.INFINITY) model.update() for row in [r for r in range(H.shape[0]) if r != ROW]: Hx = LinExpr() for column in range(n): Hx.add(H[row, column] * x[column, 0]) model.addConstr(Hx <= h[row, 0]) J = LinExpr() for column in range(n): J.add(H[ROW, column] * x[column, 0]) model.setObjective(J, GRB.MAXIMIZE) model.setParam('OutputFlag', False) model.optimize() if model.Status == 2: if J.getValue() > h[ROW, 0] + atol: return False # It is NOT redundant else: return True # It is redudant else: return False
def ilp(costMatrix): #Invalid_Connections : -1 if costMatrix.shape==(0,0): return [] dist_mat=numpy.copy(costMatrix) dist_mat[costMatrix==-1]=10e10 size_x = dist_mat.shape[0] size_y = dist_mat.shape[1] size_min = int(numpy.amin([size_x,size_y])) from gurobipy import Model, quicksum, GRB m=Model("mip1") COS,VAR={},{} for i in range(size_x): x_cos, x_var = [],[] for j in range(size_y): COS[i,j]=dist_mat[i,j] VAR[i,j]=m.addVar(vtype='B',name="["+str(i)+","+str(j)+"]") m.update() # Set objective m.setObjective( quicksum(\ COS[x,y]*VAR[x,y] for x in range(size_x) \ for y in range(size_y) \ ),GRB.MINIMIZE) # Constrains HORIZONTAL for i in range(size_x): m.addConstr( quicksum\ (VAR[i,y] for y in range(size_y)) <= 1) # Constrains VERTICAL for i in range(size_y): m.addConstr( quicksum\ (VAR[x,i] for x in range(size_x)) <= 1) m.addConstr(quicksum(\ VAR[x,y] for x in range(size_x) for y in range(size_y)) == int(size_min)) m.setParam("OutputFlag",False) m.optimize() res=numpy.zeros(dist_mat.shape,dtype=bool) for i in range(size_x): for j in range(size_y): res[i,j]=VAR[i,j].x binMatrix = numpy.zeros( costMatrix.shape,dtype=bool ) binMatrix[res==1]=1 binMatrix[costMatrix==-1]=0 return binMatrix
def build_gurobi_model(case): G, B = case.G, case.B P = real(case.demands) Q = imag(case.demands) branches = case.branch_list n = len(case.demands) vhat = case.vhat s2 = 2**.5 gens = {bus: gen.v for bus, gen in case.gens.items()} del gens[0] m = GurobiModel("jabr") u = [m.addVar(name='u_%d'%i) for i in range(n)] R = {(i, j): m.addVar(name='R_%d_%d' % (i, j)) for i, j in branches} I = {(i, j): m.addVar(lb=-GRB.INFINITY, name='I_%d_%d' % (i, j)) for i, j in branches} for i, j in branches: R[j, i] = R[i, j] I[j, i] = I[i, j] m.update() m.addConstr(u[0] == vhat*vhat/s2, 'u0') for gen, v in gens.iteritems(): m.addConstr(u[gen] == v*v/s2, 'u%d' % gen) for i, j in branches: m.addQConstr(2*u[i]*u[j] >= R[i,j]*R[i,j] + I[i,j]*I[i,j], 'cone_%d_%d' % (i, j)) k = lambda i: (j for j in B[i, :].nonzero()[1]) s = lambda i, j: 1 if i < j else -1 for i in range(1, n): m.addConstr(-s2*u[i]*G[i, :].sum() + quicksum(G[i,j]*R[i,j] + B[i,j]*s(i,j)*I[i,j] for j in k(i)) == P[i], 'real_flow_%d_%d' % (i, j)) if i in gens: continue m.addConstr(s2*u[i]*B[i, :].sum() + quicksum(-B[i,j]*R[i,j] + G[i,j]*s(i,j)*I[i,j] for j in k(i)) == Q[i], 'reac_flow_%d_%d' % (i, j)) m.setObjective(quicksum(R[i,j] for i, j in branches), sense=GRB.MAXIMIZE) m.params.outputFlag = 0 #m.params.barQCPConvTol = 5e-10 m.optimize() if m.status != 2: raise ValueError("gurobi failed to converge: %s (check log)" % m.status) u_opt = [x.getAttr('x') for x in u] R_opt = {(i, j): x.getAttr('x') for (i, j), x in R.items()} I_opt = {(i, j): x.getAttr('x') for (i, j), x in I.items()} return u_opt, R_opt, I_opt
def create_problem(cobra_model, quadratic_component=None, **kwargs): """Solver-specific method for constructing a solver problem from a cobra.Model. This can be tuned for performance using kwargs """ lp = Model("") the_parameters = parameter_defaults if kwargs: the_parameters = parameter_defaults.copy() the_parameters.update(kwargs) # Set verbosity first to quiet infos on parameter changes if "verbose" in the_parameters: set_parameter(lp, "verbose", the_parameters["verbose"]) for k, v in iteritems(the_parameters): set_parameter(lp, k, v) # Create variables #TODO: Speed this up variable_list = [lp.addVar(_float(x.lower_bound), _float(x.upper_bound), float(x.objective_coefficient), variable_kind_dict[x.variable_kind], str(i)) for i, x in enumerate(cobra_model.reactions)] reaction_to_variable = dict(zip(cobra_model.reactions, variable_list)) # Integrate new variables lp.update() #Constraints are based on mass balance #Construct the lin expression lists and then add #TODO: Speed this up as it takes about .18 seconds #HERE for i, the_metabolite in enumerate(cobra_model.metabolites): constraint_coefficients = [] constraint_variables = [] for the_reaction in the_metabolite._reaction: constraint_coefficients.append(_float(the_reaction._metabolites[the_metabolite])) constraint_variables.append(reaction_to_variable[the_reaction]) #Add the metabolite to the problem lp.addConstr(LinExpr(constraint_coefficients, constraint_variables), sense_dict[the_metabolite._constraint_sense.upper()], the_metabolite._bound, str(i)) # Set objective to quadratic program if quadratic_component is not None: set_quadratic_objective(lp, quadratic_component) lp.update() return(lp)
def global_model(N, k_choices, distance_matrix): if k_choices >= N: raise ValueError("k_choices must be less than N") model = Model("distance1") trajectories = range(N) distance_matrix = np.array( distance_matrix / distance_matrix.max(), dtype=np.float64) dm = distance_matrix ** 2 y, x = {}, {} for i in trajectories: y[i] = model.addVar(vtype="B", obj=0, name="y[%s]" % i) for j in range(i + 1, N): x[i, j] = model.addVar( vtype="B", obj=1.0, name="x[%s,%s]" % (i, j)) model.update() model.setObjective(quicksum([x[i, j] * dm[j][i] for i in trajectories for j in range(i + 1, N)])) # Add constraints to the model model.addConstr(quicksum([y[i] for i in trajectories]) <= k_choices, "27") for i in trajectories: for j in range(i + 1, N): model.addConstr(x[i, j] <= y[i], "28-%s-%s" % (i, j)) model.addConstr(x[i, j] <= y[j], "29-%s-%s" % (i, j)) model.addConstr(y[i] + y[j] <= 1 + x[i, j], "30-%s-%s" % (i, j)) model.addConstr(quicksum([x[i, j] for i in trajectories for j in range(i + 1, N)]) <= nchoosek(k_choices, 2), "Cut_1") model.update() return model
def find_feasible_start(n_colors, h, statespace, conflicts, verbose=False): model = Model("TimeFeasibility") p = len(h) y = {} # y[i,k] = if color i gets slot l for i in range(n_colors): for l in range(p): y[i,l] = model.addVar(vtype=GRB.BINARY, name="y_%s_%s" % (i,l)) model.update() # Building constraints... # c1: all get one for i in range(n_colors): model.addConstr( quicksum([ y[i, l] for l in range(p) ]) == 1, "c1") # c2: each slot needs to be used tops once for l in range(p): model.addConstr( quicksum([ y[i, l] for i in range(n_colors) ]) <= 1, "c2") ### c3: statespace constraints for i in range(n_colors): #print l, h[l], i, [s for s in statespace] model.addConstr( quicksum([ y[i, l] for l in range(p) if h[l] not in statespace[i] ]) == 0, "c3") # objective: minimize conflicts #obj = quicksum([ y[i,l] * y[j,l] for l in range(p) for i in range(n_colors) for j in range(i+1, n_colors) ]) obj = quicksum([ sum(y[i,l] for i in range(n_colors)) for l in range(p) ]) #obj = 0 model.setObjective(obj, GRB.MINIMIZE) if not verbose: model.params.OutputFlag = 0 model.optimize() # return best room schedule color_schedule = [] if model.status == GRB.INFEASIBLE: return color_schedule for i in range(n_colors): for l in range(p): v = model.getVarByName("y_%s_%s" % (i,l)) if v.x == 1: color_schedule.append(h[l]) break return color_schedule
def check_feasability_ILP(exams_to_schedule, period, data, verbose=False): # More precise but by far to slow compared to heuristic r = data['r'] T = data['T'] s = data['s'] z = {} model = Model("RoomFeasability") # z[i,k] = if exam i is written in room k for k in range(r): # print k, period if T[k][period] == 1: for i in exams_to_schedule: z[i, k] = model.addVar(vtype=GRB.BINARY, name="z_%s_%s" % (i, k)) model.update() # Building constraints... # c1: seats for all students for i in exams_to_schedule: expr = LinExpr() for k in range(r): if T[k][period] == 1: expr.addTerms(1, z[i, k]) model.addConstr(expr >= s[i], "c1") # c2: only one exam per room for k in range(r): if T[k][period] == 1: expr = LinExpr() for i in exams_to_schedule: expr.addTerms(1, z[i, k]) model.addConstr(expr <= 1, "c2") model.setObjective(0, GRB.MINIMIZE) if not verbose: model.params.OutputFlag = 0 model.params.heuristics = 0 model.params.PrePasses = 1 model.optimize() # return best room schedule try: return model.objval except GurobiError: logging.warning('check_feasability_ILP: model has no objVal') return None
def solve(budget, buses, lines, u, c, b, S, D): m = Model('inhibit') w, v, y = {}, {}, {} for i in buses: w[i] = m.addVar(vtype=GRB.BINARY, name="w_%s" % i) for i, j in lines: v[i, j] = m.addVar(vtype=GRB.BINARY, name='v_%s_%s' % (i, j)) y[i, j] = m.addVar(vtype=GRB.BINARY, name='y_%s_%s' % (i, j)) m.update() for i, j in lines: m.addConstr(w[i]-w[j] <= v[i, j] + y[i, j], 'balance1_%s_%s' % (i, j)) m.addConstr(w[j]-w[i] <= v[i, j] + y[i, j], 'balance2_%s_%s' % (i, j)) m.addConstr(quicksum(c[i, j]*y[i, j] for i, j in lines) <= budget, 'budget') m.setObjective(quicksum(u[i, j]*v[i, j] for i, j in lines) + quicksum(b[i]*(1-w[i]) for i in S) - quicksum(b[i]*w[i] for i in D)) m.setParam('OutputFlag', 0) m.optimize() m.write('gurobi.lp') return w, v, y, m
def _cut(self, model, val_func, cut_func): '''Returns true if a cut was added to the master''' problem = self.problem theta = self.theta x = self.x # Create subproblem. sub = Model() # y[ip,iq,s,c] = 1 if images ip & iq have a shared path through stage # s by running command c during s, 0 otherwise y = {} for (ip, iq), cmds in problem.shared_cmds.items(): for s, c in product(problem.shared_stages[ip, iq], cmds): y[ip,iq,s,c] = sub.addVar(name='y[%s,%s,%s,%s]' % (ip,iq,s,c)) sub.update() # Find shared paths among image pairs. constraints = defaultdict(list) for (ip, iq), cmds in problem.shared_cmds.items(): for s in problem.shared_stages[ip,iq]: for c in cmds: constraints[ip,s,c].append(sub.addConstr(y[ip,iq,s,c] <= val_func(model, x[ip,s,c]))) constraints[iq,s,c].append(sub.addConstr(y[ip,iq,s,c] <= val_func(model, x[iq,s,c]))) if s > 1: sub.addConstr(sum(y[ip,iq,s,c] for c in cmds) <= sum(y[ip,iq,s-1,c] for c in cmds)) sub.setObjective( -sum(problem.commands[c] * y[ip,iq,s,c] for ip,iq,s,c in y), GRB.MINIMIZE ) sub.optimize() # Add the dual prices for each variable pi = defaultdict(float) for isp, cons in constraints.iteritems(): for c in cons: pi[isp] += c.pi # Detect optimality if val_func(model, theta) >= sub.objVal: return False # no cuts to add # Optimality cut cut_func(model, theta >= sum(pi[isp]*x[isp] for isp in pi if pi[isp])) return True
def two_cycle(A, C, gap): """ Solve high-vertex dense graphs by reduction to weighted matching ILP. """ _ = '*' m = Model() m.modelsense = GRB.MAXIMIZE m.params.mipgap = gap m.params.timelimit = 60 * 60 n = A.shape[0] vars = {} edges = tuplelist() # model as undirected graph for i in range(n): for j in range(i+1, n): if A[i, j] == 1 and A[j, i] == 1: e = (i, j) edges.append(e) w_i = 2 if i in C else 1 w_j = 2 if j in C else 1 w = w_i + w_j var = m.addVar(vtype=GRB.BINARY, obj=w) vars[e] = var m.update() # 2 cycle constraint <=> undirected flow <= 1 for i in range(n): lhs = LinExpr() lhs_vars = [vars[e] for e in chain(edges.select(i, _), edges.select(_, i))] ones = [1.0]*len(lhs_vars) lhs.addTerms(ones, lhs_vars) m.addConstr(lhs <= 1) m.optimize() m.update() cycles = [list(e) for e in edges if vars[e].x == 1.0] return cycles, m.objval
def build_model(data, n_cliques = 0, verbose = True): # Load Data Format n = data['n'] r = data['r'] p = data['p'] s = data['s'] c = data['c'] h = data['h'] w = data['w'] location = data['location'] conflicts = data['conflicts'] locking_times = data['locking_times'] T = data['T'] similarp = data['similarp'] model = Model("ExaminationScheduling") if verbose: print("Building variables...") # x[i,k,l] = 1 if exam i is at time l in room k x = {} for k in range(r): for l in range(p): if T[k][l] == 1: for i in range(n): if location[k] in w[i]: x[i,k,l] = model.addVar(vtype=GRB.BINARY, name="x_%s_%s_%s" % (i,k,l)) # y[i,l] = 1 if exam i is at time l y = {} for i in range(n): for l in range(p): y[i, l] = model.addVar(vtype=GRB.BINARY, name="y_%s_%s" % (i,l)) # integrate new variables model.update() # for i in range(p+5): # for l in range(i-5): # y[i, l].setAttr("BranchPriority", s[i]) # model.update() start = timeit.default_timer() # not very readable but same constraints as in GurbiLinear_v_10: speeded up model building by 2 for small problems (~400 exams) and more for huger problem ~1500 exams if verbose: print("Building constraints...") s_sorted = sorted(range(len(c)), key = lambda k: c[k]) obj = LinExpr() sumconflicts = {} maxrooms = {} for i in range(n): sumconflicts[i] = sum(conflicts[i]) if s[i] <= 50: maxrooms[i] = 1 elif s[i] <= 100: maxrooms[i] = 2 elif s[i] <= 400: maxrooms[i] = 7 elif s[i] <= 700: maxrooms[i] = 9 else: maxrooms[i] = 12 c2 = LinExpr() c4 = LinExpr() for l in range(p): c1 = LinExpr() c1 = LinExpr() c3 = LinExpr() for k in range(r): if T[k][l] == 1 and location[k] in w[i]: # print k, c[k], 1-(1/(pow(2,s_sorted.index(k)))) obj.addTerms( 1-(1/(pow(2,s_sorted.index(k)))) , x[i, k, l]) c1.addTerms(1, x[i,k,l]) c4.addTerms(c[k],x[i,k,l]) model.addConstr(c1 <= maxrooms[i]* y[i,l], "c1a") model.addConstr(c1 >= y[i,l], "C1b") for j in conflicts[i]: c3.addTerms(1,y[j,l]) model.addConstr(c3 <= (1 - y[i,l])*sumconflicts[i], "c3") c2.addTerms(1,y[i,l]) model.addConstr( c2 == 1 , "c2") model.addConstr(c4 >= s[i], "c4") sumrooms = {} for l in range(p): sumrooms[l] = 0 cover_inequalities = LinExpr() for k in range(r): if T[k][l] == 1: sumrooms[l] += 1 c5 = LinExpr() for i in range(n): if location[k] in w[i]: c5.addTerms(1,x[i,k,l]) model.addConstr( c5 <= 1, "c5") cover_inequalities += c5 model.addConstr(cover_inequalities <= sumrooms[l], "cover_inequalities") # Break Symmetry # First only use small rooms in a period if all bigger rooms are already used # TODO Do for every location if similarp[0] >= 0: for i in range(i-1): for l in range(p): model.addConstr(y[i,l] <= quicksum( y[i+1,sim] for sim in similarp), "s1") # for l in range(p): # for index, k in enumerate(s_sorted): # #print k, index # s1 = LinExpr() # if index < len(s_sorted)-1: # if T[k][l] == 1: # for k2 in range(r-index): # if T[s_sorted[index+k2]][l] == 1: # for i in range(n): # # if location[k] in w[i]: # s1.addTerms([1,-1], [x[i,k,l], x[i,s_sorted[index+k2],l]]) # break # model.addConstr( s1 <= 0 , "s1") #if p <= n: # for l in range(p): # model.addConstr( quicksum(y[l,i] for i in range(l)) >= 1, "s1") # for l in range(p-1): # for i in range(n): # model.addConstr( y[i,l] - quicksum(y[i,l+1] for i in range(l,n)) <= 0, "l1") model.setObjective( obj, GRB.MINIMIZE) print timeit.default_timer()-start if verbose: print("All constrained and objective built - OK") if not verbose: model.params.OutputFlag = 0 # Set Parameters #print("Setting Parameters...") # max presolve agressivity #model.params.presolve = 2 # Choosing root method 3= concurrent = run barrier and dual simplex in parallel model.params.method = 3 #model.params.MIPFocus = 1 model.params.OutputFlag = 1 #model.params.MIPFocus = 1 # cuts #model.params.cuts = 0 #model.params.coverCuts = 2 #model.params.CutPasses = 4 # heuristics #model.params.heuristics = 0 #model.params.symmetry = 2 # # Tune the model # model.tune() # if model.tuneResultCount > 0: # # Load the best tuned parameters into the model # model.getTuneResult(0) # # Write tuned parameters to a file # model.write('tune1.prm') # return return(model)
def cycle_milp(A, C, k, gap): n = A.shape[0] t_0 = time.clock() _ = '*' m = Model() m.modelsense = GRB.MAXIMIZE m.params.mipgap = gap cycles = [] vars = [] cycles_grouped = [[] for i in range(n)] vars_grouped = [[] for i in range(n)] print('[%.1f] Generating variables...' % (time.clock() - t_0)) print('i = ', end='') for i in range(n): for cycle in dfs_cycles(i, A, k): w = sum([2 if j in C else 1 for j in cycle]) var = m.addVar(vtype=GRB.BINARY, obj=w) vars.append(var) cycles.append(cycle) cycles_grouped[i].append(cycle) vars_grouped[i].append(var) for j in cycle: if j > i: vars_grouped[j].append(var) cycles_grouped[j].append(cycle) if (i + 1) % 10 == 0: print(i + 1) m.update() print('[%.1f] Generated variables...' % (time.clock() - t_0)) print('[%.1f] Generating constraints...' % (time.clock() - t_0)) for i in range(n): vars_i = vars_grouped[i] lhs = LinExpr() ones = [1.0]*len(vars_i) lhs.addTerms(ones, vars_i) m.addConstr(lhs <= 1.0) print('[%.1f] Generated constraints...' % (time.clock() - t_0)) print('[%.1f] Begin Optimizing %d vertex %d cycle model' % (time.clock() - t_0, n, len(cycles))) m.update() m.optimize() m.update() print('[%.1f] Finished Optimizing' % (time.clock() - t_0)) print('[%.1f] Building cycles...' % (time.clock() - t_0)) final_cycles = [] for i in range(len(vars)): var = vars[i] if var.x == 1.0: cycle = cycles[i] final_cycles.append(cycle) print('[%.1f] Finished building cycles' % (time.clock() - t_0)) return final_cycles, m.objval
class BFPBackupNetwork_Continuous(object): """ Class object for buffered failure probability-based model. Parameters ---------- Gamma: importance sampling vector Nodes: set of nodes Links: set of links Capacity: capacities per link based based on random failures Survivability: desired survivabiliy factor (epsilon) K: number of random scenarios Returns ------- BackupCapacity: set of capacity per backup link. BackupRoutes: set of backup links """ # Private model object model = [] # Private model variables BackupCapacity = {} bBackupLink = {} z0 = {} z = {} def __init__(self): """ Constructor """ def LoadModel(self, Gamma, Nodes, Links, Capacity, Survivability, NumSamples): """ Load model. Parameters ---------- Gamma : importance sampling vector """ self.Links = tuplelist(Links) self.Capacity = Capacity # Create optimization model self.model = Model("Backup") # Create variables for i, j in self.Links: self.BackupCapacity[i, j] = self.model.addVar( vtype=GRB.CONTINUOUS, lb=0, name="Backup_Capacity[%s,%s]" % (i, j) ) # self.BackupCapacity[i,j] = self.model.addVar(lb=0, name='Backup_Capacity[%s,%s]' % (i, j)) self.model.update() for i, j in self.Links: for s, d in self.Links: self.bBackupLink[i, j, s, d] = self.model.addVar( vtype=GRB.BINARY, name="Backup_Link[%s,%s,%s,%s]" % (i, j, s, d) ) self.model.update() for i, j in self.Links: for k in range(NumSamples): self.z[k, i, j] = self.model.addVar(lb=0, name="z[%s][%s][%s]" % (k, i, j)) self.model.update() for i, j in self.Links: self.z0[i, j] = self.model.addVar(lb=-GRB.INFINITY, name="z0[%s][%s]" % (i, j)) self.model.update() self.model.modelSense = GRB.MINIMIZE self.model.setObjective(quicksum(self.BackupCapacity[i, j] for i, j in self.Links)) self.model.update() # ------------------------------------------------------------------------# # Constraints definition # # # # # # ------------------------------------------------------------------------# # Buffer probability I for i, j in self.Links: self.model.addConstr( self.z0[i, j] + 1 / (NumSamples * Survivability) * quicksum(self.z[k, i, j] for (k) in range(NumSamples)) <= 0, "[CONST]Buffer_Prob_I[%s][%s]" % (i, j), ) self.model.update() # Link capacity constraints for i, j in self.Links: for k in range(NumSamples): if Gamma == None: self.model.addConstr( ( quicksum(self.bBackupLink[i, j, s, d] * Capacity[k, s, d] for s, d in self.Links) - self.BackupCapacity[i, j] - self.z0[i, j] ) <= self.z[k, i, j], "[CONST]Buffer_Prob_II[%s][%s][%s]" % (k, i, j), ) else: self.model.addConstr( ( quicksum(self.bBackupLink[i, j, s, d] * Capacity[k, s, d] for s, d in self.Links) - self.BackupCapacity[i, j] - self.z0[i, j] ) * Gamma[k] <= self.z[k, i, j], "[CONST]Buffer_Prob_II[%s][%s][%s]" % (k, i, j), ) self.model.update() # Link capacity constraints for i, j in self.Links: for k in range(NumSamples): self.model.addConstr(self.z[k, i, j] >= 0, "[CONST]Buffer_Prob_III[%s][%s][%s]" % (k, i, j)) self.model.update() for i in Nodes: for s, d in self.Links: # Flow conservation constraints if i == s: self.model.addConstr( quicksum(self.bBackupLink[i, j, s, d] for i, j in self.Links.select(i, "*")) - quicksum(self.bBackupLink[j, i, s, d] for j, i in self.Links.select("*", i)) == 1, "Flow1[%s,%s,%s]" % (i, s, d), ) # Flow conservation constraints elif i == d: self.model.addConstr( quicksum(self.bBackupLink[i, j, s, d] for i, j in self.Links.select(i, "*")) - quicksum(self.bBackupLink[j, i, s, d] for j, i in self.Links.select("*", i)) == -1, "Flow2[%s,%s,%s]" % (i, s, d), ) # Flow conservation constraints else: self.model.addConstr( quicksum(self.bBackupLink[i, j, s, d] for i, j in self.Links.select(i, "*")) - quicksum(self.bBackupLink[j, i, s, d] for j, i in self.Links.select("*", i)) == 0, "Flow3[%s,%s,%s]" % (i, s, d), ) self.model.update() def Optimize(self, MipGap=None, TimeLimit=None, LogLevel=None): """ Optimize the defined model. Parameters ---------- MipGap : desired gap TimeLimit : time limit LogLevel: log level 1 for printing all optimal variables and None otherwise Returns ------- BackupCapacity: The total capacity assigned per backup link BackupRoutes: The set of selected backup links A tuple list with all paths for edge (s,d) that uses (i,j). """ self.model.write("bpbackup.lp") if MipGap != None: self.model.params.MIPGap = MipGap if TimeLimit != None: self.model.params.timeLimit = TimeLimit # Compute optimal solution self.model.optimize() # Print solution if self.model.status == GRB.Status.OPTIMAL: if LogLevel == 1: for v in self.model.getVars(): print("%s %g" % (v.varName, v.x)) self.BackupCapacitySolution = self.model.getAttr("x", self.BackupCapacity) self.BackupRoutesSolution = self.model.getAttr("x", self.bBackupLink) self.BackupLinksSolution = {} self.HatBackupCapacity = {} for link in self.BackupCapacitySolution: if self.BackupCapacitySolution[link] < 1 and self.BackupCapacitySolution[link] > 0.001: self.HatBackupCapacity[link] = math.ceil(self.BackupCapacitySolution[link]) else: self.HatBackupCapacity[link] = math.floor(self.BackupCapacitySolution[link]) if self.HatBackupCapacity[link] > 0: if len(self.BackupLinksSolution) == 0: self.BackupLinksSolution = [link] else: self.BackupLinksSolution = self.BackupLinksSolution + [link] else: print("Optimal value not found!\n") self.BackupCapacitySolution = [] self.BackupRoutesSolution = {} self.BackupLinksSolution = {} return self.BackupCapacitySolution, self.BackupRoutesSolution, self.BackupLinksSolution, self.HatBackupCapacity def SaveBakupNetwork(self, file_name): """Save the optimal backup network to the file ``file_name``.""" data = { "links": [i for i in self.BackupCapacitySolution], "capacities": [self.BackupCapacitySolution[i] for i in self.BackupCapacitySolution], "routes": [i for i in self.BackupRoutesSolution], "status": [self.BackupRoutesSolution[i] for i in self.BackupRoutesSolution], } f = open(file_name, "w") json.dump(data, f) f.close() def LoadBackupNetwork(self, file_name): """Load a backup network from the file ``file_name``. Returns the backup network solution saved in the file. """ f = open(file_name, "r") data = json.load(f) f.close() self.BackupCapacitySolution = {} self.BackupRoutesSolution = {} self.BackupLinksSolution = {} links = [i for i in data["links"]] capacities = [i for i in data["capacities"]] routes = [i for i in data["routes"]] status = [i for i in data["status"]] IndexAux = 0 for i, j in links: self.BackupCapacitySolution[i, j] = capacities[IndexAux] IndexAux = IndexAux + 1 self.HatBackupCapacity = {} for link in self.BackupCapacitySolution: if self.BackupCapacitySolution[link] < 1 and self.BackupCapacitySolution[link] > 0.001: self.HatBackupCapacity[link] = math.ceil(self.BackupCapacitySolution[link]) else: self.HatBackupCapacity[link] = math.floor(self.BackupCapacitySolution[link]) if self.HatBackupCapacity[link] > 0: if len(self.BackupLinksSolution) == 0: self.BackupLinksSolution = [link] else: self.BackupLinksSolution = self.BackupLinksSolution + [link] IndexAux = 0 for i, j, s, d in routes: self.BackupRoutesSolution[i, j, s, d] = status[IndexAux] IndexAux = IndexAux + 1 return self.BackupCapacitySolution, self.BackupRoutesSolution, self.BackupLinksSolution, self.HatBackupCapacity def ResetModel(self): """ Reset model solution. """ self.BackupCapacity = {} self.bBackupLink = {} self.z0 = {} self.z = {} if self.model: self.model.reset()
class SolveSC1GuMIP: """ Solve the initial marking problem optimally using Guroby (it must be install). The computation time can be quite long for big instances. """ def __init__(self, dataflow, verbose, lp_filename): """ Constructor """ self.dataflow = dataflow self.verbose = verbose self.lp_filename = lp_filename self.col_v = {} # dict use for storing gamma's variable column self.col_m0 = {} # dict use for storing bds's variable column self.col_fm0 = {} # dict use for storing FM0's variable column def compute_initial_marking(self): """launch the computation. This function return the objective value of the MILP problem The initial marking of the graph in parameter is modify. """ self.__init_prob() # Modify parameters self.__create_col() # Add Col on prob self.__create_row() # Add Row (constraint) on prob self.__create_obj() # Add objectif function self.__solve_prob() # Launch the solver and set preload of the graph del self.prob # Del prob return self.Z # Return the total amount find by the solver def __init_prob(self): # Modify parameters logging.info("Generating initial marking problem") self.prob = Model("SC1_MIP") # Gurobi parameters: if not self.verbose: self.prob.params.OutputFlag = 0 try: os.remove("gurobi.log") except OSError: pass self.prob.params.Threads = 2 self.prob.params.intfeastol = 0.000001 def __create_col(self): # Add Col on prob # Create column bds (M0) for arc in self.dataflow.get_arc_list(): self.__add_col_m0(arc) # Create column bds (FM0) for arc in self.dataflow.get_arc_list(): self.__add_col_fm0(arc) # Create column lambda (v) for task in self.dataflow.get_task_list(): phase_count = self.__get_range_phases(task) for i in xrange(phase_count): self.__add_col_v(str(task) + "/" + str(i)) # Integrate new variables self.prob.update() def __create_row(self): # Add Row (constraint) on prob # BEGUIN FILL ROW ######################################################################## # Constraint FM0*step - M0 = 0 # ######################################################################## for arc in self.dataflow.get_arc_list(): if not self.dataflow.is_arc_reentrant(arc): arc_gcd = self.dataflow.get_gcd(arc) self.__add_frow(arc, arc_gcd) ######################################################################## # Constraint u-u'+M0 >= W1+1 # ######################################################################## for arc in self.dataflow.get_arc_list(): source = self.dataflow.get_source(arc) target = self.dataflow.get_target(arc) if not self.dataflow.is_arc_reentrant(arc): range_source = self.__get_range_phases(source) range_target = self.__get_range_phases(target) prod_list = self.__get_prod_rate_list(arc) cons_list = self.__get_cons_rate_list(arc) if self.dataflow.is_pcg: threshold_list = self.__get_threshold_list(arc) arc_gcd = self.dataflow.get_gcd(arc) pred_prod = 0 for sourcePhase in xrange(range_source): # source/prod/out normaux if sourcePhase > 0: pred_prod += prod_list[sourcePhase - 1] pred_cons = 0 cons = 0 for targetPhase in xrange(range_target): # target/cons/in normaux cons += cons_list[targetPhase] if targetPhase > 0: pred_cons += cons_list[targetPhase - 1] w = cons - pred_prod - arc_gcd if self.dataflow.is_pcg: w += pred_cons + threshold_list[targetPhase] - cons str_v1 = str(source) + "/" + str(sourcePhase) str_v2 = str(target) + "/" + str(targetPhase) self.__add_row(str_v1, str_v2, arc, w) # END FILL ROW def __create_obj(self): obj = QuadExpr() for arc in self.dataflow.get_arc_list(): obj += self.col_m0[arc] self.prob.setObjective(obj, GRB.MINIMIZE) def __solve_prob(self): # Launch the solver and set preload of the graph logging.info("loading matrix ...") self.prob.update() if self.lp_filename is not None: problem_location = str(self.prob.write(self.lp_filename)) logging.info("Writing problem: " + str(problem_location)) logging.info("solving problem ...") self.prob.optimize() logging.info("Integer solving done !") self.Z = self.prob.objVal for arc in self.dataflow.get_arc_list(): if not self.dataflow.is_arc_reentrant(arc): self.dataflow.set_initial_marking(arc, int(self.col_m0[arc].x)) logging.info("SC1 MIP Mem tot (no reentrant): " + str(self.Z)) # Add a variable lamda def __add_col_v(self, name): var = self.prob.addVar(vtype=GRB.CONTINUOUS, name=name) self.col_v[name] = var # Add a variable M0 def __add_col_m0(self, arc): var = self.prob.addVar(lb=0, vtype=GRB.INTEGER) self.col_m0[arc] = var # Add a variable FM0 def __add_col_fm0(self, arc): var = self.prob.addVar(lb=0, vtype=GRB.INTEGER) self.col_fm0[arc] = var # Add a constraint: lambda1 - lambda2 + M0 > W1 def __add_row(self, str_v1, str_v2, arc, w): expr = LinExpr() if not self.dataflow.is_arc_reentrant(arc): expr += self.col_v[str_v1] expr -= self.col_v[str_v2] expr += self.col_m0[arc] self.prob.addConstr(expr, GRB.GREATER_EQUAL, w + 0.00001) # Add a constraint: FM0*step = M0 def __add_frow(self, arc, step): expr = LinExpr() expr += self.col_fm0[arc]*float(step) expr -= self.col_m0[arc] self.prob.addConstr(expr, GRB.EQUAL, 0) def __get_range_phases(self, task): if self.dataflow.is_sdf: return 1 range_task = self.dataflow.get_phase_count(task) if self.dataflow.is_pcg: range_task += self.dataflow.get_ini_phase_count(task) return range_task def __get_prod_rate_list(self, arc): if self.dataflow.is_sdf: return [self.dataflow.get_prod_rate(arc)] prod_list = self.dataflow.get_prod_rate_list(arc) if self.dataflow.is_pcg: prod_list = self.dataflow.get_ini_prod_rate_list(arc) + prod_list return prod_list def __get_cons_rate_list(self, arc): if self.dataflow.is_sdf: return [self.dataflow.get_cons_rate(arc)] cons_list = self.dataflow.get_cons_rate_list(arc) if self.dataflow.is_pcg: cons_list = self.dataflow.get_ini_cons_rate_list(arc) + cons_list return cons_list def __get_threshold_list(self, arc): return self.dataflow.get_ini_threshold_list(arc) + self.dataflow.get_threshold_list(arc)
[ 8, 9, 5] ] a = [ [ 5, 7, 2], [14, 8, 7], [10, 6, 12], [ 8, 4, 15], [ 6, 12, 5] ] # x[i][j] = 1 if i is assigned to j x = [] for i in range(len(c)): x_i = [] for j in c[i]: x_i.append(model.addVar(vtype=GRB.BINARY)) x.append(x_i) # As stated, the GAP has these following constraints. We dualize these into # penalties instead, using variables so we can easily extract their values. penalties = [model.addVar() for _ in x] model.update() # Dualized constraints: sum j: x_ij <= 1 for all i for p, x_i in zip(penalties, x): model.addConstr(p == 1 - sum(x_i)) # sum i: a_ij * x_ij <= b[j] for all j for j in range(len(b)): model.addConstr(sum(a[i][j] * x[i][j] for i in range(len(x))) <= b[j])
def __objective_function(self, x, q): m = Model("Overall_Model") CT = {} DT = {} TD = {} #### Add Variable #### for j in range(self.project_n): ## solve individual model get Project complete date CT[j] = self.__optmize_single_project(x, j) ## Project Tadeness,construction completion time DT[j] = m.addVar(obj=0, vtype=GRB.CONTINUOUS, name="(DT%d)" % j) TD[j] = m.addVar(obj=0, vtype=GRB.CONTINUOUS, name="(TD%d)" % j) DT[-1] = m.addVar(obj=0, vtype=GRB.CONTINUOUS, name="(DT-1)") ## Review Sequence z_ij z = {} for i in range(self.project_n): for j in range(self.project_n): if i != j: z[i, j] = m.addVar(obj=0, vtype=GRB.BINARY, name="(z%d,%d)" % (i, j)) for j in range(self.project_n): z[-1, j] = m.addVar(obj=0, vtype=GRB.BINARY, name="(z%d,%d)" % (-1, j)) m.update(); #### Add Constraint #### ## Constrain 2: project complete data>due data ## for j in range(self.project_n): m.addConstr(DT[j] - TD[j], GRB.LESS_EQUAL, self.DD[j], name="constraint_2_project_%d" % j) ## Constraint 13 for j in range(self.project_n): m.addConstr(DT[j], GRB.GREATER_EQUAL, CT[j] + self.review_duration[j], name="constraint_13_project_%d" % j) ## Constraint 14 for i in range(-1, self.project_n): for j in range(self.project_n): if i != j: m.addConstr(DT[j], GRB.GREATER_EQUAL, DT[i] - self.M * (1 - z[i, j]) + self.review_duration[j], name="constraint_14_project_%d_project_%d" % (i, j)) ## Constrain 15 for j in range(self.project_n): m.addConstr(quicksum(z[i, j] for i in range(-1, self.project_n) if i != j), GRB.EQUAL, 1, name="constraint_15_project_%d" % j) ## Constrain 16 m.addConstr(quicksum(z[-1, j] for j in range(self.project_n)), GRB.EQUAL, 1, name="constraint_16") ## Constrain 17 for i in range(self.project_n): m.addConstr(quicksum(z[i, j] for j in range(self.project_n) if j != i), GRB.LESS_EQUAL, 1, name="constraint_17_project_%d" % i) m.update() # Set optimization objective - minimize sum of expr = LinExpr() for j in range(self.project_n): expr.add(self.w[j] * TD[j]) m.setObjective(expr, GRB.MINIMIZE) m.update() m.params.presolve = 1 m.update() m.optimize() m.write(join(self.output_dir, "heuristic_whole.lp")) m.write(join(self.output_dir, "heuristic_whole.sol")) print([self.w[j] * TD[j].X for j in range(self.project_n)]) return m.objVal, argmax([self.w[j] * TD[j].X for j in range(self.project_n)])
def build_model(data, n_cliques = 0, verbose = True): # Load Data Format n = data['n'] r = data['r'] p = data['p'] s = data['s'] c = data['c'] h = data['h'] w = data['w'] location = data['location'] conflicts = data['conflicts'] locking_times = data['locking_times'] T = data['T'] model = Model("ExaminationScheduling") if verbose: print("Building variables...") # x[i,k,l] = 1 if exam i is at time l in room k x = {} for k in range(r): for l in range(p): if T[k][l] == 1: for i in range(n): if location[k] in w[i]: x[i,k,l] = model.addVar(vtype=GRB.BINARY, name="x_%s_%s_%s" % (i,k,l)) # y[i,l] = 1 if exam i is at time l y = {} for i in range(n): for l in range(p): y[i, l] = model.addVar(vtype=GRB.BINARY, name="y_%s_%s" % (i,l)) # integrate new variables model.update() start = timeit.default_timer() # not very readable but same constraints as in GurbiLinear_v_10: speeded up model building by 2 for small problems (~400 exams) and more for huger problem ~1500 exams if verbose: print("Building constraints...") obj = LinExpr() sumconflicts = {} maxrooms = {} for i in range(n): sumconflicts[i] = sum(conflicts[i]) if s[i] <= 50: maxrooms[i] = 1 elif s[i] <= 100: maxrooms[i] = 2 elif s[i] <= 400: maxrooms[i] = 7 elif s[i] <= 700: maxrooms[i] = 9 else: maxrooms[i] = 12 c2 = LinExpr() c4 = LinExpr() for l in range(p): c1 = LinExpr() c1 = LinExpr() c3 = LinExpr() for k in range(r): if T[k][l] == 1 and location[k] in w[i]: c1.addTerms(1, x[i, k, l]) c4.addTerms(c[k],x[i,k,l]) obj += c1 model.addConstr(c1 <= maxrooms[i]* y[i,l], "c1a") model.addConstr(c1 >= y[i,l], "C1b") for j in conflicts[i]: c3.addTerms(1,y[j,l]) model.addConstr(c3 <= (1 - y[i,l])*sumconflicts[i], "c3") c2.addTerms(1,y[i,l]) model.addConstr( c2 == 1 , "c2") model.addConstr(c4 >= s[i], "c4") sumrooms = {} for l in range(p): sumrooms[l] = 0 cover_inequalities = LinExpr() for k in range(r): if T[k][l] == 1: sumrooms[l] += 1 c5 = LinExpr() for i in range(n): if location[k] in w[i]: c5.addTerms(1,x[i,k,l]) model.addConstr( c5 <= 1, "c5") cover_inequalities += c5 model.addConstr(cover_inequalities <= sumrooms[l], "cover_inequalities") model.setObjective( obj, GRB.MINIMIZE) print timeit.default_timer()-start if verbose: print("All constrained and objective built - OK") if not verbose: model.params.OutputFlag = 0 # Set Parameters #print("Setting Parameters...") # max presolve agressivity #model.params.presolve = 2 # Choosing root method 3= concurrent = run barrier and dual simplex in parallel #model.params.method = 1 #model.params.MIPFocus = 1 model.params.OutputFlag = 1 model.params.Method = 3 # cuts model.params.cuts = 0 model.params.cliqueCuts = 0 model.params.coverCuts = 0 model.params.flowCoverCuts = 0 model.params.FlowPathcuts = 0 model.params.GUBCoverCuts = 0 model.params.impliedCuts = 0 model.params.MIPSepCuts = 0 model.params.MIRCuts = 0 model.params.ModKCuts = 0 model.params.NetworkCuts = 2 model.params.SUBMIPCuts = 0 model.params.ZeroHalfCuts = 0 model.params.TimeLimit = 30 # # Tune the model # model.tune() # if model.tuneResultCount > 0: # # Load the best tuned parameters into the model # model.getTuneResult(0) # # Write tuned parameters to a file # model.write('tune1.prm') # return return(model)
def __optmize_single_project(self, x, j): ''' Given the generated x for single project, try to optimize the tardiness of the project. :param x: the assignment of resource supplier to project :param j: index of project :return: ''' m = Model("SingleProject_%d" % j) #### Create variables #### project = self.project_list[j] ## Project complete data,Project Tadeness,construction completion time CT = m.addVar(obj=0, vtype=GRB.CONTINUOUS, name="(CT%d)" % j) ## Activity start time ST = {} project_activities = self.project_activity[project] # print(project_activities.nodes()) for row in project_activities.nodes(): ST[row] = m.addVar(obj=0, vtype=GRB.CONTINUOUS, name="(ST%d,%s)" % (j, row)) ## Review sequence z_ij ## move to annealing objective function # y y = {} for activity_i in project_activities.nodes(): for activity_j in project_activities.nodes(): # print(project_activities.node[activity_i]) # print(dir(project_activities.node[activity_i])) if activity_i != activity_j and len(list( set(project_activities.node[activity_i]['rk_resources']).intersection( project_activities.node[activity_j]['rk_resources']))) > 0: y[activity_i, activity_j] = m.addVar(obj=0, vtype=GRB.BINARY, name="(y%d,%s,%s)" % (j, activity_i, activity_j)) m.update() #### Create constrains #### ## Constrain 2: project complete data>due data ## move to annealing objective function ## Constrain 3: supplier capacity limit ## move to annealing neighbor & random generator ## Constrain 4,6: project demand require; each project receive from one supplier for each resource ## move to annealing neighbor & random generator ## constrain 5: shipping constrain ## move to annealing neighbor & random generator ## Constrain 7:budget limit ## move to annealing constraint valid ## Constrain 8: activity starting constrain for a in project_activities.nodes(): for r in project_activities.node[a]['resources']: resource_delivered_days = 0 for s in self.resource_supplier_list[r]: resource_delivered_days += x.get((r, s, project), 0) * \ (self.resource_supplier_release_time[r, s] + self.supplier_project_shipping[ r, s, project]) m.addConstr(resource_delivered_days, GRB.LESS_EQUAL, ST[a], name="constraint_8_project_%d_activity_%s_resource_%s" % (j, a, r)) ## Constrain 9 activity sequence constrain for row1, row2 in project_activities.edges(): # print(row1, '#', row2, '#', j) # print(ST) m.addConstr(ST[row1] + project_activities.node[row1]['duration'], GRB.LESS_EQUAL, ST[row2], name="constraint_9_project_%d_activity_%s_activity_%s" % (j, row1, row2)) ## Constrain 10,11 for row1 in project_activities.nodes(): for row2 in project_activities.nodes(): if row1 != row2 and len(list( set(project_activities.node[row1]['rk_resources']).intersection( project_activities.node[row2]['rk_resources']))) > 0: m.addConstr(ST[row1] + project_activities.node[row1]['duration'] - self.M * ( 1 - y[row1, row2]), GRB.LESS_EQUAL, ST[row2], name="constraint_10_project_%d_activity_%s_activity_%s" % (j, row1, row2)) m.addConstr( ST[row2] + project_activities.node[row2]['duration'] - self.M * (y[row1, row2]), GRB.LESS_EQUAL, ST[row1], name="constraint_11_project_%d_activity_%s_activity_%s" % (j, row1, row2)) # m.addConstr(y[j,row1,row2]+y[j,row2,row1],GRB.LESS_EQUAL,1) ## Constrain 12 for row in project_activities.nodes(): # print(project_activities.node[row]['duration']) m.addConstr(CT, GRB.GREATER_EQUAL, ST[row] + project_activities.node[row]['duration'], name="constraint_12_project_%d_activity_%s" % (j, row)) ## Constrain 13 ## move to anealing objective function ## Constrain 14 ## move to anealing objective function ## Constrain 15 ## move to anealing objective function ## Constrain 16 ## move to anealing objective function ## Constrain 17 ## move to anealing objective function m.update() # Set optimization objective - minimize completion time expr = LinExpr() expr.add(CT) m.setObjective(expr, GRB.MINIMIZE) m.update() ########################################## m.params.presolve = 1 m.update() # Solve # m.params.presolve=0 m.optimize() m.write(join(self.output_dir, "heuristic_%d.lp" % j)) m.write(join(self.output_dir, "heuristic_%d.sol" % j)) return m.objVal
def lazy_cycle_constraint(A, C, k, gap): """ Lazily generate cycle constraints as potential feasible solutions are generated. """ _ = '*' m = Model() m.modelsense = GRB.MAXIMIZE m.params.mipgap = gap m.params.timelimit = 5 * 60 * 60 m.params.lazyconstraints = 1 n = A.shape[0] edges = tuplelist() vars = {} for i in range(n): for j in range(n): if A[i, j] == 1: e = (i, j) edges.append(e) w = 2 if j in C else 1 var = m.addVar(vtype=GRB.BINARY, obj=w) vars[e] = var m.update() # flow constraints for i in range(n): out_vars = [vars[e] for e in edges.select(i, _)] out_ones = [1.0]*len(out_vars) out_expr = LinExpr() out_expr.addTerms(out_ones, out_vars) in_vars = [vars[e] for e in edges.select(_, i)] in_ones = [1.0]*len(in_vars) in_expr = LinExpr() in_expr.addTerms(in_ones, in_vars) m.addConstr(in_expr <= 1) m.addConstr(out_expr == in_expr) m.update() ith_cycle = 0 def callback(model, where): if where == GRB.Callback.MIPSOL: sols = model.cbGetSolution([vars[e] for e in edges]) c_edges = [edges[i] for i in range(len(edges)) if sols[i] > 0.5] cycles = cycles_from_edges(c_edges) for cycle in cycles: len_cycle = len(cycle) if len_cycle > k: cycle_vars = [vars[(cycle[i], cycle[(i+1) % len_cycle])] for i in range(len_cycle)] ones = [1.0]*len(cycle_vars) expr = LinExpr() expr.addTerms(ones, cycle_vars) model.cbLazy(expr <= len_cycle - 1) m.optimize(callback) m.update() c_edges = [e for e in edges if vars[e].x == 1.0] cycles = cycles_from_edges(c_edges) return cycles, m.objval
def gurobi(wanted_parts, available_parts, stores, shipping_cost=10.0): from gurobipy import Model, GRB, LinExpr kf1 = lambda x: (x['item_id'], x['wanted_color_id']) kf2 = lambda x: (x['ItemID'], x['ColorID']) available_by_store = utils.groupby(available_parts, lambda x: x['store_id']) store_by_id = dict( (s['store_id'], s) for s in stores ) m = Model() store_variables = {} # store id to variable indicating store is used quantity_variables = [] # list of all lot variables + metadata # for every store for (store_id, inventory) in available_by_store.iteritems(): # a variable for if anything was bought from this store. if 1, then pay # shipping cost and all store inventory is available; if 0, then don't pay # for shipping and every lot in it has 0 quantity available store_variables[store_id] = m.addVar(0.0, 1.0, shipping_cost, GRB.BINARY, "use-store=%s" % (store_id,)) for lot in inventory: store_id = lot['store_id'] quantity = lot['quantity_available'] unit_cost= lot['cost_per_unit'] item_id = lot['item_id'] color_id = lot['color_id'] # a variable for how much to buy of this lot v = m.addVar(0.0, quantity, unit_cost, GRB.CONTINUOUS, "quantity-store=%s-item=%s-color=%s" % (store_id, item_id, color_id)) # keep a list of all lots quantity_variables.append({ 'store_id': store_id, 'item_id': lot['item_id'], 'wanted_color_id': lot['wanted_color_id'], 'color_id': lot['color_id'], 'variable': v, 'quantity_available': quantity, 'cost_per_unit': unit_cost }) # actually put the variables into the model m.update() # for every lot in every store for lot in quantity_variables: use_store = store_variables[lot['store_id']] quantity = lot['quantity_available'] unit_cost = lot['cost_per_unit'] v = lot['variable'] # a constraint for how much can be bought m.addConstr(LinExpr([1.0, -1 * quantity], [v, use_store]), GRB.LESS_EQUAL, 0.0, "maxquantity-store=%s-item=%s-color-%d" % (lot['store_id'], lot['item_id'], lot['color_id'])) # for every wanted lot variables_by_id = utils.groupby(quantity_variables, kf1) for lot in wanted_parts: # a constraint saying amount bought >= wanted amount variables = map(lambda x: x['variable'], variables_by_id[kf2(lot)]) constants = len(variables) * [1.0] m.addConstr(LinExpr(constants, variables), GRB.GREATER_EQUAL, lot['Qty'], "wantedamount-item=%s-color=%s" % (lot['ItemID'], lot['ColorID'])) # for every store variables_by_store = utils.groupby(quantity_variables, lambda x: x['store_id']) for (store_id, variables) in variables_by_store.iteritems(): use_store = store_variables[store_id] minimum_purchase = store_by_id[store_id]['minimum_buy'] # a constraint saying "if I purchased from this store, I bought the minimum amount or more" constants = [v['cost_per_unit'] for v in variables] + [-1 * minimum_purchase] variables = [v['variable'] for v in variables] + [use_store] m.addConstr(LinExpr(constants, variables), GRB.GREATER_EQUAL, 0.0, "minbuy-store=%d" % (store_id,)) # minimize sum of costs of items bought + shipping costs m.setParam(GRB.param.MIPGap, 0.01) # stop when duality gap <= 1% m.optimize() # get results if m.ObjVal < float('inf'): result = [] for lot in quantity_variables: # get variable out v = lot['variable'] del lot['variable'] # lot variables are continuous, so they might not actually be integral. # If they're not, check that they're "almost" integral, so we can just # round. Otherwise, print this warning. According to theory the optimal # solution is for all continuous variables to be integral. if v.X != int(v.X) and abs(v.X - round(v.X)) > 1e-3: print 'Uh oh. Variable %s has value %f. This is a little close for comfort.' % (v.VarName, v.X) # save quantity to buy if it's > 0 lot['quantity'] = int(round(v.X)) if lot['quantity'] > 0: result.append(lot) cost = sum(e['quantity'] * e['cost_per_unit'] for e in result) store_ids = list(set(e['store_id'] for e in result)) return [{ 'cost': cost, 'allocation': result, 'store_ids': store_ids }] else: print 'No solution :(' return []
def constantino(A, C, k, gap): """ Polynomial-sized CCMcP Edge-Extended Model See Constantino et al. (2013) """ t_0 = time.clock() _ = '*' m = Model() m.modelsense = GRB.MAXIMIZE m.params.mipgap = gap # m.params.timelimit = 60 * 60 # m.params.nodefilestart = 1.0 # m.params.nodefiledir = './.nodefiledir' # m.params.presparsify = 0 # m.params.presolve = 0 n = A.shape[0] vars = {} edges = tuplelist() print('[%.1f] Generating variables...' % (time.clock() - t_0)) # Variables for l in range(n): for i in range(l, n): for j in range(l, n): if A[i, j] == 1: e = (l, i, j) edges.append(e) w = 2 if j in C else 1 var = m.addVar(vtype=GRB.BINARY, obj=w) vars[e] = var if l % 100 == 0 and l != 0: print('[%.1f] l = %d' % (time.clock() - t_0, l)) m.update() print('[%.1f] Generated variables' % (time.clock() - t_0)) print('[%.1f] Adding flow constraints...' % (time.clock() - t_0)) # Constraint (2): Flow in = Flow out for l in range(n): for i in range(l, n): # Flow in lhs_vars = [vars[e] for e in edges.select(l, _, i)] ones = [1.0]*len(lhs_vars) lhs = LinExpr() lhs.addTerms(ones, lhs_vars) # Flow out rhs_vars = [vars[e] for e in edges.select(l, i, _)] ones = [1.0]*len(rhs_vars) rhs = LinExpr() rhs.addTerms(ones, rhs_vars) # Flow in = Flow out m.addConstr(lhs == rhs) if l % 100 == 0 and l != 0: print('[%.1f] l = %d' % (time.clock() - t_0, l)) print('[%.1f] Added flow constraints' % (time.clock() - t_0)) print('[%.1f] Adding cycle vertex constraints...' % (time.clock() - t_0)) # Constraint (3): Use a vertex only once per cycle for i in range(n): c_vars = [vars[e] for e in edges.select(_, i, _)] ones = [1.0]*len(c_vars) expr = LinExpr() expr.addTerms(ones, c_vars) m.addConstr(expr <= 1.0) if i % 100 == 0 and i != 0: print('[%.1f] V_i = %d' % (time.clock() - t_0, i)) print('[%.1f] Added cycle vertex constraints' % (time.clock() - t_0)) print('[%.1f] Adding cycle cardinality constraints...' % (time.clock() - t_0)) # Constraint (4): Limit cardinality of cycles to k for l in range(n): c_vars = [vars[e] for e in edges.select(l, _, _)] ones = [1.0]*len(c_vars) expr = LinExpr() expr.addTerms(ones, c_vars) m.addConstr(expr <= k) if l % 100 == 0 and l != 0: print('[%.1f] l = %d' % (time.clock() - t_0, l)) print('[%.1f] Added cycle cardinality constraints' % (time.clock() - t_0)) print('[%.1f] Adding cycle index constraints...' % (time.clock() - t_0)) # Constraint (5): Cycle index is smallest vertex-index for l in range(n): rhs_vars = [vars[e] for e in edges.select(l, l, _)] ones = [1.0]*len(rhs_vars) rhs = LinExpr() rhs.addTerms(ones, rhs_vars) for i in range(l+1, n): lhs_vars = [vars[e] for e in edges.select(l, i, _)] if len(lhs_vars) > 0: ones = [1.0]*len(lhs_vars) lhs = LinExpr() lhs.addTerms(ones, lhs_vars) m.addConstr(lhs <= rhs) if l % 100 == 0 and l != 0: print('[%.1f] l = %d' % (time.clock() - t_0, l)) print('[%.1f] Added cycle index constraints...' % (time.clock() - t_0)) print('[%.1f] Begin Optimizing %d vertex model' % (time.clock() - t_0, n)) m.optimize() m.update() print('[%.1f] Finished Optimizing' % (time.clock() - t_0)) print('[%.1f] Building cycles...' % (time.clock() - t_0)) cycles = [] for l in range(n): c_edges = [(e[1], e[2]) for e in edges.select(l, _, _) if vars[e].x == 1.0] cycles.extend(cycles_from_edges(c_edges)) print('[%.1f] Finished building cycles' % (time.clock() - t_0)) return cycles, m.objval
def _optimize_gurobi(cobra_model, new_objective=None, objective_sense='maximize', min_norm=0, the_problem=None, tolerance_optimality=1e-6, tolerance_feasibility=1e-6, tolerance_barrier=None, tolerance_integer=1e-9, error_reporting=None, print_solver_time=False, copy_problem=False, lp_method=0, relax_b=None, quad_precision=False, quadratic_component=None, reuse_basis=True, lp_parallel=None, update_problem_reaction_bounds=True): """Uses the gurobi (http://gurobi.com) optimizer to perform an optimization on cobra_model for the objective_coefficients in cobra_model._objective_coefficients based on objective sense. cobra_model: A cobra.Model object new_objective: Reaction, String, or Integer referring to a reaction in cobra_model.reactions to set as the objective. Currently, only supports single objective coeffients. Will expand to include mixed objectives. objective_sense: 'maximize' or 'minimize' min_norm: not implemented the_problem: None or a problem object for the specific solver that can be used to hot start the next solution. tolerance_optimality: Solver tolerance for optimality. tolerance_feasibility: Solver tolerance for feasibility. quad_precision: Boolean. Whether or not to used quad precision in calculations error_reporting: None or True to disable or enable printing errors encountered when trying to find the optimal solution. print_solver_time: False or True. Indicates if the time to calculate the solution should be displayed. quadratic_component: None or scipy.sparse.dok of dim(len(cobra_model.reactions),len(cobra_model.reactions)) If not None: Solves quadratic programming problems for cobra_models of the form: minimize: 0.5 * x' * quadratic_component * x + cobra_model._objective_coefficients' * x such that, cobra_model._lower_bounds <= x <= cobra_model._upper_bounds cobra_model._S * x (cobra_model._constraint_sense) cobra_model._b NOTE: When solving quadratic problems it may be necessary to disable quad_precision and use lp_method = 0 for gurobi. reuse_basis: Boolean. If True and the_problem is a model object for the solver, attempt to hot start the solution. update_problem_reaction_bounds: Boolean. Set to True if you're providing the_problem and you've modified reaction bounds on your cobra_model since creating the_problem. Only necessary for CPLEX lp_parallel: Not implemented lp.optimize() with Salmonella model: cold start: 0.063 seconds hot start: 0.057 seconds (Slow due to copying the LP) """ if relax_b is not None: raise Exception('Need to reimplement constraint relaxation') from numpy import array, nan, zeros #TODO: speed this up if objective_sense == 'maximize': objective_sense = -1 else: objective_sense = 1 from gurobipy import Model, LinExpr, GRB, QuadExpr sense_dict = {'E': GRB.EQUAL, 'L': GRB.LESS_EQUAL, 'G': GRB.GREATER_EQUAL} from cobra.flux_analysis.objective import update_objective from cobra.solvers.legacy import status_dict, variable_kind_dict variable_kind_dict = eval(variable_kind_dict['gurobi']) status_dict = eval(status_dict['gurobi']) #Update objectives if they are new. if new_objective and new_objective != 'update problem': update_objective(cobra_model, new_objective) #Create a new problem if not the_problem or the_problem in ['return', 'setup'] or \ not isinstance(the_problem, Model): lp = Model("cobra") lp.Params.OutputFlag = 0 lp.Params.LogFile = '' # Create variables #TODO: Speed this up variable_list = [lp.addVar(lb=float(x.lower_bound), ub=float(x.upper_bound), obj=objective_sense*float(x.objective_coefficient), name=x.id, vtype=variable_kind_dict[x.variable_kind]) for x in cobra_model.reactions] reaction_to_variable = dict(zip(cobra_model.reactions, variable_list)) # Integrate new variables lp.update() #Set objective to quadratic program if quadratic_component is not None: if not hasattr(quadratic_component, 'todok'): raise Exception('quadratic component must be a scipy.sparse type array') quadratic_objective = QuadExpr() for (index_0, index_1), the_value in quadratic_component.todok().items(): quadratic_objective.addTerms(the_value, variable_list[index_0], variable_list[index_1]) lp.setObjective(quadratic_objective, sense=objective_sense) #Constraints are based on mass balance #Construct the lin expression lists and then add #TODO: Speed this up as it takes about .18 seconds #HERE for the_metabolite in cobra_model.metabolites: constraint_coefficients = [] constraint_variables = [] for the_reaction in the_metabolite._reaction: constraint_coefficients.append(the_reaction._metabolites[the_metabolite]) constraint_variables.append(reaction_to_variable[the_reaction]) #Add the metabolite to the problem lp.addConstr(LinExpr(constraint_coefficients, constraint_variables), sense_dict[the_metabolite._constraint_sense.upper()], the_metabolite._bound, the_metabolite.id) else: #When reusing the basis only assume that the objective coefficients or bounds can change if copy_problem: lp = the_problem.copy() else: lp = the_problem if not reuse_basis: lp.reset() for the_variable, the_reaction in zip(lp.getVars(), cobra_model.reactions): the_variable.lb = float(the_reaction.lower_bound) the_variable.ub = float(the_reaction.upper_bound) the_variable.obj = float(objective_sense*the_reaction.objective_coefficient) if the_problem == 'setup': return lp if print_solver_time: start_time = time() lp.update() lp.setParam("FeasibilityTol", tolerance_feasibility) lp.setParam("OptimalityTol", tolerance_optimality) if tolerance_barrier: lp.setParam("BarConvTol", tolerance_barrier) if quad_precision: lp.setParam("Quad", 1) lp.setParam("Method", lp_method) #Different methods to try if lp_method fails the_methods = [0, 2, 1] if lp_method in the_methods: the_methods.remove(lp_method) if not isinstance(the_problem, Model): lp.optimize() if lp.status in status_dict: status = status_dict[lp.status] else: status = 'failed' if status != 'optimal': #Try to find a solution using a different method lp.setParam("MarkowitzTol", 1e-2) for lp_method in the_methods: lp.setParam("Method", lp_method) lp.optimize() if status_dict[lp.status] == 'optimal': break else: lp.setParam("TimeLimit", 0.6) lp.optimize() lp.setParam("TimeLimit", "default") if lp.status in status_dict: status = status_dict[lp.status] else: status = 'failed' if status != 'optimal': lp.setParam("MarkowitzTol", 1e-2) #Try to find a solution using a different method for lp_method in the_methods: lp.setParam("Method", lp_method) lp.optimize() if status_dict[lp.status] == 'optimal': break if status_dict[lp.status] != 'optimal': lp = optimize_gurobi(cobra_model, new_objective=new_objective, objective_sense=objective_sense, min_norm=min_norm, the_problem=None, print_solver_time=print_solver_time)['the_problem'] if print_solver_time: print 'optimize time: %f'%(time() - start_time) x_dict = {} y_dict = {} y = None if lp.status in status_dict: status = status_dict[lp.status] else: status = 'failed' if status == 'optimal': objective_value = objective_sense*lp.ObjVal [x_dict.update({v.VarName: v.X}) for v in lp.getVars()] x = array([x_dict[v.id] for v in cobra_model.reactions]) if lp.isMIP: y = y_dict = None #MIP's don't have duals else: [y_dict.update({c.ConstrName: c.Pi}) for c in lp.getConstrs()] y = array([y_dict[v.id] for v in cobra_model.metabolites]) else: y = y_dict = x = x_dict = None objective_value = None if error_reporting: print 'gurobi failed: %s'%lp.status the_solution = Solution(objective_value, x=x, x_dict=x_dict, y=y, y_dict=y_dict, status=status) solution = {'the_problem': lp, 'the_solution': the_solution} return solution
def build_model(data, n_cliques = 0, verbose = True): # Load Data Format n = data['n'] r = data['r'] p = data['p'] s = data['s'] c = data['c'] h = data['h'] w = data['w'] location = data['location'] conflicts = data['conflicts'] locking_times = data['locking_times'] T = data['T'] model = Model("ExaminationScheduling") if verbose: print("Building variables...") # x[i,k,l] = 1 if exam i is at time l in room k x = {} for k in range(r): for l in range(p): if T[k][l] == 1: for i in range(n): if location[k] in w[i]: x[i,k,l] = model.addVar(vtype=GRB.BINARY, name="x_%s_%s_%s" % (i,k,l)) # y[i,l] = 1 if exam i is at time l y = {} for i in range(n): for l in range(p): y[i, l] = model.addVar(vtype=GRB.BINARY, name="y_%s_%s" % (i,l)) # integrate new variables model.update() start = timeit.default_timer() # adding constraints as found in MidTerm.pdf if verbose: print("Building constraints...") if verbose: print("c1: connecting variables x and y") for i in range(n): for l in range(p): model.addConstr( quicksum([ x[i, k, l] for k in range(r) if T[k][l] == 1 and location[k] in w[i] ]) <= 12 * y[i, l], "c1a") model.addConstr( quicksum([ x[i, k, l] for k in range(r) if T[k][l] == 1 and location[k] in w[i] ]) >= y[i, l], "c1b") if verbose: print("c2: each exam at exactly one time") for i in range(n): model.addConstr( quicksum([ y[i, l] for l in range(p) ]) == 1 , "c2") """ Idea: -instead of saving a conflict Matrix, save Cliques of exams that cannot be written at the same time -then instead of saying of one exam is written in a given period all conflicts cannot be written in the same period we could say -for all exams in a given clique only one can be written """ if verbose: print("c3: avoid conflicts") for i in range(n): for l in range(p): # careful!! Big M changed! model.addConstr(quicksum([ y[j,l] for j in conflicts[i] ]) <= (1 - y[i, l]) * sum(conflicts[i]), "c3") if verbose: print("c4: seats for all students") for i in range(n): model.addConstr( quicksum([ x[i, k, l] * c[k] for k in range(r) for l in range(p) if T[k][l] == 1 and location[k] in w[i] ]) >= s[i], "c4") if verbose: print("c5: only one exam per room per period") for k in range(r): for l in range(p): if T[k][l] == 1: model.addConstr( quicksum([ x[i, k, l] for i in range(n) if location[k] in w[i] ]) <= 1, "c5") if verbose: print("All constrained built - OK") # objective: minimize number of used rooms if verbose: print("Building Objective...") obj1 = quicksum([ x[i,k,l] for i,k,l in itertools.product(range(n), range(r), range(p)) if T[k][l] == 1 and location[k] in w[i]]) model.setObjective( obj1, GRB.MINIMIZE) print timeit.default_timer()-start if not verbose: model.params.OutputFlag = 0 # Set Parameters #print("Setting Parameters...") # max presolve agressivity #model.params.presolve = 2 # Choosing root method 3= concurrent = run barrier and dual simplex in parallel #model.params.method = 1 #model.params.MIPFocus = 1 #model.params.cuts = 0 model.params.OutputFlag = 1 # # Tune the model # model.tune() # if model.tuneResultCount > 0: # # Load the best tuned parameters into the model # model.getTuneResult(0) # # Write tuned parameters to a file # model.write('tune1.prm') # return return(model)
class GurobiSolver(Solver): """ Implements the solver interface using gurobipy. """ def __init__(self): Solver.__init__(self) self.problem = GurobiModel() def __getstate__(self): tmp_file = tempfile.mktemp(suffix=".lp") self.problem.update() self.problem.write(tmp_file) cplex_form = open(tmp_file).read() repr_dict = {'var_ids': self.var_ids, 'constr_ids': self.constr_ids, 'cplex_form': cplex_form} return repr_dict def __setstate__(self, repr_dict): tmp_file = tempfile.mktemp(suffix=".lp") open(tmp_file, 'w').write(repr_dict['cplex_form']) self.problem = read(tmp_file) self.var_ids = repr_dict['var_ids'] self.constr_ids = repr_dict['constr_ids'] def add_variable(self, var_id, lb=None, ub=None, vartype=VarType.CONTINUOUS, persistent=True, update_problem=True): """ Add a variable to the current problem. Arguments: var_id : str -- variable identifier lb : float -- lower bound ub : float -- upper bound vartype : VarType -- variable type (default: CONTINUOUS) persistent : bool -- if the variable should be reused for multiple calls (default: true) update_problem : bool -- update problem immediately (default: True) """ lb = lb if lb is not None else -GRB.INFINITY ub = ub if ub is not None else GRB.INFINITY map_types = {VarType.BINARY: GRB.BINARY, VarType.INTEGER: GRB.INTEGER, VarType.CONTINUOUS: GRB.CONTINUOUS} if var_id in self.var_ids: var = self.problem.getVarByName(var_id) var.setAttr('lb', lb) var.setAttr('ub', ub) var.setAttr('vtype', map_types[vartype]) else: self.problem.addVar(name=var_id, lb=lb, ub=ub, vtype=map_types[vartype]) self.var_ids.append(var_id) if not persistent: self.temp_vars.add(var_id) if update_problem: self.problem.update() def add_constraint(self, constr_id, lhs, sense='=', rhs=0, persistent=True, update_problem=True): """ Add a variable to the current problem. Arguments: constr_id : str -- constraint identifier lhs : list [of (str, float)] -- variables and respective coefficients sense : {'<', '=', '>'} -- default '=' rhs : float -- right-hand side of equation (default: 0) persistent : bool -- if the variable should be reused for multiple calls (default: True) update_problem : bool -- update problem immediately (default: True) """ grb_sense = {'=': GRB.EQUAL, '<': GRB.LESS_EQUAL, '>': GRB.GREATER_EQUAL} if constr_id in self.constr_ids: constr = self.problem.getConstrByName(constr_id) self.problem.remove(constr) expr = quicksum([coeff * self.problem.getVarByName(r_id) for r_id, coeff in lhs if coeff]) self.problem.addConstr(expr, grb_sense[sense], rhs, constr_id) self.constr_ids.append(constr_id) if not persistent: self.temp_constrs.add(constr_id) if update_problem: self.problem.update() def remove_variable(self, var_id): """ Remove a variable from the current problem. Arguments: var_id : str -- variable identifier """ if var_id in self.var_ids: self.problem.remove(self.problem.getVarByName(var_id)) self.var_ids.remove(var_id) def remove_constraint(self, constr_id): """ Remove a constraint from the current problem. Arguments: constr_id : str -- constraint identifier """ if constr_id in self.constr_ids: self.problem.remove(self.problem.getConstrByName(constr_id)) self.constr_ids.remove(constr_id) def update(self): """ Update internal structure. Used for efficient lazy updating. """ self.problem.update() def solve_lp(self, objective, model=None, constraints=None, get_shadow_prices=False, get_reduced_costs=False): """ Solve an LP optimization problem. Arguments: objective : dict (of str to float) -- reaction ids in the objective function and respective coefficients, the sense is maximization by default model : ConstraintBasedModel -- model (optional, leave blank to reuse previous model structure) constraints : dict (of str to (float, float)) -- environmental or additional constraints (optional) get_shadow_prices : bool -- return shadow price information if available (optional, default: False) get_reduced_costs : bool -- return reduced costs information if available (optional, default: False) Returns: Solution """ return self._generic_solve(None, objective, GRB.MAXIMIZE, model, constraints, get_shadow_prices, get_reduced_costs) def solve_qp(self, quad_obj, lin_obj, model=None, constraints=None, get_shadow_prices=False, get_reduced_costs=False): """ Solve an LP optimization problem. Arguments: quad_obj : dict (of (str, str) to float) -- map reaction pairs to respective coefficients lin_obj : dict (of str to float) -- map single reaction ids to respective linear coefficients model : ConstraintBasedModel -- model (optional, leave blank to reuse previous model structure) constraints : dict (of str to (float, float)) -- overriding constraints (optional) get_shadow_prices : bool -- return shadow price information if available (default: False) get_reduced_costs : bool -- return reduced costs information if available (default: False) Returns: Solution """ return self._generic_solve(quad_obj, lin_obj, GRB.MINIMIZE, model, constraints, get_shadow_prices, get_reduced_costs) def _generic_solve(self, quad_obj, lin_obj, sense, model=None, constraints=None, get_shadow_prices=False, get_reduced_costs=False): if model: self.build_problem(model) problem = self.problem if constraints: old_constraints = {} for r_id, (lb, ub) in constraints.items(): lpvar = problem.getVarByName(r_id) old_constraints[r_id] = (lpvar.lb, lpvar.ub) lpvar.lb = lb if lb is not None else -GRB.INFINITY lpvar.ub = ub if ub is not None else GRB.INFINITY problem.update() #create objective function quad_obj_expr = [q * problem.getVarByName(r_id1) * problem.getVarByName(r_id2) for (r_id1, r_id2), q in quad_obj.items() if q] if quad_obj else [] lin_obj_expr = [f * problem.getVarByName(r_id) for r_id, f in lin_obj.items() if f] if lin_obj else [] obj_expr = quicksum(quad_obj_expr + lin_obj_expr) problem.setObjective(obj_expr, sense) problem.update() # from datetime import datetime # self.problem.write("problem_{}.lp".format(str(datetime.now()))) #run the optimization problem.optimize() status = status_mapping[problem.status] if problem.status in status_mapping else Status.UNKNOWN message = str(problem.status) if status == Status.OPTIMAL: fobj = problem.ObjVal values = OrderedDict([(r_id, problem.getVarByName(r_id).X) for r_id in self.var_ids]) #if metabolite is disconnected no constraint will exist shadow_prices = OrderedDict([(m_id, problem.getConstrByName(m_id).Pi) for m_id in self.constr_ids if problem.getConstrByName(m_id)]) if get_shadow_prices else None reduced_costs = OrderedDict([(r_id, problem.getVarByName(r_id).RC) for r_id in self.var_ids]) if get_reduced_costs else None solution = Solution(status, message, fobj, values, shadow_prices, reduced_costs) else: solution = Solution(status, message) #reset old constraints because temporary constraints should not be persistent if constraints: for r_id, (lb, ub) in old_constraints.items(): lpvar = problem.getVarByName(r_id) lpvar.lb, lpvar.ub = lb, ub problem.update() return solution
def tsp_gurobi(edges): """ Modeled using GUROBI python example. """ from gurobipy import Model, GRB, quicksum edges = populate_edge_weights(edges) incoming, outgoing, nodes = node_to_edge(edges) idx = dict((n, i) for i, n in enumerate(nodes)) nedges = len(edges) n = len(nodes) m = Model() step = lambda x: "u_{0}".format(x) # Create variables vars = {} for i, (a, b, w) in enumerate(edges): vars[i] = m.addVar(obj=w, vtype=GRB.BINARY, name=str(i)) for u in nodes[1:]: u = step(u) vars[u] = m.addVar(obj=0, vtype=GRB.INTEGER, name=u) m.update() # Bounds for step variables for u in nodes[1:]: u = step(u) vars[u].lb = 1 vars[u].ub = n - 1 # Add degree constraint for v in nodes: incoming_edges = incoming[v] outgoing_edges = outgoing[v] m.addConstr(quicksum(vars[x] for x in incoming_edges) == 1) m.addConstr(quicksum(vars[x] for x in outgoing_edges) == 1) # Subtour elimination edge_store = dict(((idx[a], idx[b]), i) for i, (a, b, w) in enumerate(edges)) # Given a list of edges, finds the shortest subtour def subtour(s_edges): visited = [False] * n cycles = [] lengths = [] selected = [[] for i in range(n)] for x, y in s_edges: selected[x].append(y) while True: current = visited.index(False) thiscycle = [current] while True: visited[current] = True neighbors = [x for x in selected[current] if not visited[x]] if len(neighbors) == 0: break current = neighbors[0] thiscycle.append(current) cycles.append(thiscycle) lengths.append(len(thiscycle)) if sum(lengths) == n: break return cycles[lengths.index(min(lengths))] def subtourelim(model, where): if where != GRB.callback.MIPSOL: return selected = [] # make a list of edges selected in the solution sol = model.cbGetSolution([model._vars[i] for i in range(nedges)]) selected = [edges[i] for i, x in enumerate(sol) if x > .5] selected = [(idx[a], idx[b]) for a, b, w in selected] # find the shortest cycle in the selected edge list tour = subtour(selected) if len(tour) == n: return # add a subtour elimination constraint c = tour incident = [edge_store[a, b] for a, b in pairwise(c + [c[0]])] model.cbLazy(quicksum(model._vars[x] for x in incident) <= len(tour) - 1) m.update() m._vars = vars m.params.LazyConstraints = 1 m.optimize(subtourelim) selected = [v.varName for v in m.getVars() if v.x > .5] selected = [int(x) for x in selected if x[:2] != "u_"] results = sorted(x for i, x in enumerate(edges) if i in selected) \ if selected else None return results
def run_algorithm(self): old_M = self.M old_items = [i.copy() for i in self.items] map_name_to_old_item = dict() for i in old_items: map_name_to_old_item[i.name] = i self.scale_items_by_cost() from gurobipy import Model, GRB model = Model("NP-Hard") print("Setting Model Parameters") # set timeout model.setParam('TimeLimit', 1600) model.setParam('MIPFocus', 3) model.setParam('PrePasses', 1) model.setParam('Heuristics', 0.01) model.setParam('Method', 0) map_name_to_item = dict() map_name_to_cost = dict() map_name_to_weight = dict() map_name_to_profit = dict() map_class_to_name = dict() item_names = list() print("Preprocessing data for model...") for item in self.items: item_names.append(item.name) map_name_to_item[item.name] = item map_name_to_cost[item.name] = item.cost map_name_to_weight[item.name] = item.weight map_name_to_profit[item.name] = item.profit if item.classNumber not in map_class_to_name: map_class_to_name[item.classNumber] = list() map_class_to_name[item.classNumber].append(item.name) class_numbers = list(map_class_to_name.keys()) print("Setting model variables...") # binary variables =1, if use>0 items = model.addVars(item_names, vtype=GRB.BINARY, name="items") classes = model.addVars(class_numbers, vtype=GRB.BINARY, name="class numbers") print("Setting model objective...") # maximize profit objective = items.prod(map_name_to_profit) model.setObjective(objective, GRB.MAXIMIZE) # constraints print("Setting model constraints") model.addConstr(items.prod(map_name_to_weight) <= self.P,"weight capacity") model.addConstr(items.prod(map_name_to_cost) <= self.M,"cost capacity") # if any item from a class is chosen, that class variable has to be a binary of 1 for num in class_numbers: model.addGenConstrOr(classes[num], [items[x] for x in map_class_to_name[num]] ,name="class count") for c in self.raw_constraints: count = model.addVar() for n in c: if n in classes: count += classes[n] model.addConstr(count <= 1, name="constraint") print("Start optimizing...") model.optimize() print("Done! ") # Status checking status = model.Status if status == GRB.Status.INF_OR_UNBD or \ status == GRB.Status.INFEASIBLE or \ status == GRB.Status.UNBOUNDED: print('The model cannot be solved because it is infeasible or unbounded') if status != GRB.Status.OPTIMAL: print('Optimization was stopped with status ' + str(status)) Problem = True try: model.write("mps_model/" + self.filename + ".sol") except Exception as e: pass print("Generating solution file...") # Display solution solution_names = list() for i, v in enumerate(items): try: if items[v].X > 0.9: solution_names.append(item_names[i]) except Exception as e: pass self.M = old_M self.items = old_items solution = [map_name_to_old_item[i] for i in solution_names] return solution