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 get_mapping(PG, VG): vnodes, vhosts = multidict({n: len(VG.node[n]['host_ports']) for n in VG.nodes()}) pnodes, phosts = multidict({n: len(PG.node[n]['host_ports']) for n in PG.nodes()}) parcs, pcapacity = multidict({(m, n): PG.edge[m][n]['weight'] for (m, n) in PG.edges()}) parcs = tuplelist(parcs) varcs, vcapacity = multidict({(m, n): VG.edge[m][n]['weight'] for (m, n) in VG.edges()}) varcs = tuplelist(varcs) m = Model('mapping') # Create variables node_mapping = {} for i in vnodes: for j in pnodes: node_mapping[i, j] = m.addVar(vtype=GRB.BINARY, name="x_%s_%s" % (i, j)) edge_mapping = {} for i in vnodes: for p in VG.neighbors(i): for (j, q) in parcs: edge_mapping[i, p, j, q] = m.addVar(vtype=GRB.BINARY, name="y_%s_%s_%s_%s" % (i, p, j, q)) m.update() # Arc capacity constraints for i in vnodes: m.addConstr(quicksum(node_mapping[i, j] for j in pnodes) == 1, 'node_%s' % i) for i in vnodes: for p in VG.neighbors(i): for (j, q) in parcs: m.addConstr(edge_mapping[i, p, j, q] <= ( node_mapping[i, j] + node_mapping[p, q] )/2, 'edge_%s_%s_%s_%s' % (i, p, j, q)) for (j, q) in parcs: m.addConstr(quicksum(edge_mapping[i, p, j, q] + edge_mapping[p, i, j, q]for (i, p) in varcs) <= pcapacity[j, q], 'pcap_%s_%s' % (j, q)) for (i, p) in varcs: m.addConstr(quicksum(edge_mapping[i, p, j, q] + edge_mapping[p, i, j, q] for (j, q) in parcs) >= vcapacity[i, p], 'vcap_%s_%s' % (i, p)) for j in pnodes: m.addConstr(quicksum(node_mapping[i, j] * vhosts[i] for i in vnodes) <= phosts[j], 'phosts_%s' % j) for i in vnodes: m.addConstr(quicksum(node_mapping[i, j] * phosts[j] for j in pnodes) >= vhosts[i], 'vhosts_%s' % i) # Compute optimal solution m.optimize() # Print solution if m.status == GRB.status.OPTIMAL: mapping = {} mapping2 = {} portlist = {} for n in PG: if 'host_ports' in PG.node[n]: portlist[n] = PG.node[n]['host_ports'] solution = m.getAttr('x', edge_mapping) for h in solution: if solution[h] == 1.0: vid1, vid2, pid1, pid2 = h vport1, vport2 = list(VG.node[vid1]['links'][vid2])[0] if (vid1, pid1) not in mapping: mapping[(vid1, pid1)] =[vid1, pid1] if (pid1, vid1) not in mapping2: mapping2[(pid1, vid1)] =[pid1, vid1] (pport1, pport2) = PG.node[pid1]['links'][pid2].pop() # print vid1, vid2, pid1, pid2, pport1, pport2 if pid1 != pid2: PG.node[pid2]['links'][pid1].remove((pport2, pport1)) mapping[(vid1, pid1)].append(vport1) mapping[(vid1, pid1)].append(pport1) mapping2[(pid1, vid1)].append(pport1) mapping2[(pid1, vid1)].append(vport1) if (vid2, pid2) not in mapping: mapping[(vid2, pid2)] =[vid2, pid2] if (pid2, vid2) not in mapping2: mapping2[(pid2, vid2)] =[pid2, vid2] mapping[(vid2, pid2)].append(vport2) mapping[(vid2, pid2)].append(pport2) mapping2[(pid2, vid2)].append(pport2) mapping2[(pid2, vid2)].append(vport2) solution2 = m.getAttr('x', node_mapping) print [h for h in solution2 if solution2[h] == 1.0] for h in solution2: if solution2[h] == 1.0: vid, pid = h if len(VG.node[vid]['host_ports']) == 0: continue for vport in VG.node[vid]['host_ports']: pport = portlist[pid].pop() mapping[(vid, pid)].append(vport) mapping[(vid, pid)].append(pport) mapping2[(pid, vid)].append(pport) mapping2[(pid, vid)].append(vport) return mapping, mapping2 def main(): args = parse_args() VG = gen_graph(args.target_topology) if not networkx.is_connected(VG): print 'Target topology is not connected' sys.exit(1) PG = gen_graph(args.host_topology, int_idx=True) mapping, mapping2 = get_mapping(PG, VG) f = open(args.output, "w") print >>f, "P2Vmap" for id in mapping2: for id2 in mapping2[id]: print >>f, id2, print>>f, "65535 65535" print >>f, "V2Pmap" for id in mapping: for id2 in mapping[id]: print >>f, id2, print>>f, "65535 65535" if __name__ == "__main__": main()
def cost_state_old(s, state_considered, L, Q, gamma): """ Asscoiate each state and its child transition a cost Assumption: paralleltopes """ if s == s.goal: return 0 model = Model("trajectory of polytopes") p = {} for row in range(s.n): p[row] = model.addVar(lb=-1, ub=1) model.update() GLG = np.dot(state_considered.G.T, np.dot(L, state_considered.G)) theta = state_considered.successor[2] u = state_considered.successor[1] i = state_considered.mode theta_Q_theta = np.dot(theta.T, np.dot(Q, theta)) J = QuadExpr() for row in range(s.n): for k in range(s.n): J.add(p[row] * p[k] * GLG[row, k] + p[row] * p[k] * theta_Q_theta[row, k]) model.setParam('OutputFlag', False) model.setObjective(J) model.optimize() return model.ObjVal + np.asscalar( np.dot(state_considered.x.T, np.dot(L, state_considered.x)) + np.dot(u.T, np.dot(Q, u)) + gamma)
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 generate_nn_guard_positive(gurobi_model: grb.Model, input, nn: torch.nn.Sequential, positive, M=1e2, eps=0): gurobi_model.setParam("DualReductions", 0) gurobi_vars = [] gurobi_vars.append(input) Experiment.build_nn_model_core(gurobi_model, gurobi_vars, nn, M) last_layer = gurobi_vars[-1] if positive: constraint = gurobi_model.addConstr(last_layer[0] + eps >= 0, name="last_layer") else: constraint = gurobi_model.addConstr(last_layer[0] + eps <= 0, name="last_layer") gurobi_model.update() gurobi_model.optimize() feasible = gurobi_model.status == 2 or gurobi_model.status == 5 gurobi_model.remove(constraint) gurobi_model.update() gurobi_model.optimize() assert gurobi_model.status == 2, "LP wasn't optimally solved" return feasible
def solve(): model = Model("Enigma Riddle Binary Program") letters = {"E", "N", "I", "G", "M", "A"} digits = range(1, 10) # x[i, j] == 1 => Letter i uses digit j x = model.addVars(letters, digits, vtype=GRB.BINARY) # Final value for first word b = model.addVar(vtype=GRB.INTEGER) first_word = "ENIGMA" second_word = "IGMAEN" # Constraints for the enigma-igmaen numbers model.addConstr( quicksum( quicksum(10**(len(first_word) - 1 - i) * j * x[first_word[i], j] for j in digits) for i in range(len(first_word))) == b) model.addConstr( quicksum( quicksum(10**(len(second_word) - 1 - i) * j * x[second_word[i], j] for j in digits) for i in range(len(second_word))) == b * 1.2) # Conflict constraint, different letters have different digits model.addConstrs(x[i_1, j] + x[i_2, j] <= 1 for i_1 in letters for i_2 in letters for j in digits if i_1 != i_2) # Exactly one digit has to be used per letter model.addConstrs(quicksum(x[i, j] for j in digits) == 1 for i in letters) model.optimize() return model
def solve_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 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 solve(): model = Model("Enigma Riddle Binary Program") letters = {"E", "N", "I", "G", "M", "A"} digits = range(1, 10) # x[i, j] == 1 => Letter i uses digit j x = model.addVars(letters, digits, vtype=GRB.BINARY, name=(f"x[{l},{d}]" for l in letters for d in digits)) # Final value for first word first_word = "ENIGMA" second_word = "IGMAEN" factor = 1.2 # Constraint for the enigma-igmaen numbers model.addConstr(factor * quicksum( quicksum(10**(len(first_word) - 1 - i) * j * x[first_word[i], j] for j in digits) for i in range(len(first_word))) - quicksum( quicksum(10**(len(second_word) - 1 - i) * j * x[second_word[i], j] for j in digits) for i in range(len(second_word))) == 0) # Conflict constraint, different letters have different digits model.addConstrs(quicksum(x[i, j] for i in letters) <= 1 for j in digits) # Exactly one digit has to be used per letter model.addConstrs(quicksum(x[i, j] for j in digits) == 1 for i in letters) model.optimize() return model
def 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 solve(): model = Model("Enigma Riddle") letters = {"E", "N", "I", "G", "M", "A"} digits = range(1, 10) x = model.addVars(letters, digits, vtype=GRB.BINARY) y = model.addVars(letters, vtype=GRB.INTEGER) # Stay in digit range for i in letters: model.addRange(y[i], 1, 9, f"digitRange{i}") # Final value for first word b = model.addVar(vtype=GRB.INTEGER) first_word = "ENIGMA" second_word = "IGMAEN" # Constraint for the enigma-igmaen numbers model.addConstr(quicksum(10 ** (len(first_word) - 1 - i) * y[first_word[i]] for i in range(len(first_word))) == b) model.addConstr( quicksum(10 ** (len(second_word) - 1 - i) * y[second_word[i]] for i in range(len(second_word))) == b * 1.2) # Conflict constraint model.addConstrs(x[i_1, j] + x[i_2, j] <= 1 for i_1 in letters for i_2 in letters for j in digits if i_1 != i_2) # Linking constraint model.addConstrs(j * x[i, j] <= y[i] for i in letters for j in digits) # Exactly one digit has to be packed model.addConstrs(quicksum(x[i, j] for j in digits) == 1 for i in letters) model.optimize() return model
def optimizeGEM(GEM, obj_rxn): """ Plain old FBA using cobra model with gurobi. I made this function because the cobra optimize function gives error when used on split, irreversible model """ model = Model('FBA_model') GEM_rxn_ids = [rxn.id for rxn in GEM.reactions] S = cobra.util.array.create_stoichiometric_matrix(GEM, array_type='dense') # Add variables v = {} for rxn in GEM.reactions: var_id = f'v_{rxn.id}' x = model.addVar(lb=rxn.lower_bound, ub=rxn.upper_bound, obj=0.0, vtype=GRB.CONTINUOUS, name=var_id) v[var_id] = x # Add constraints for i, row in enumerate(S): c = '' for j, coeff in enumerate(row): rxn_id = GEM_rxn_ids[j] if coeff != 0: c += f'{coeff} * v["v_{rxn_id}"] +' c = c[:-1] c += '== 0' model.addConstr(eval(c), f'mass_balance_{GEM.metabolites[i].id}') # Set Objective model.setObjective(v['v_' + obj_rxn], GRB.MAXIMIZE) model.optimize() return model
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, )
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 OptimalTransportGurobi(H1, H2): n = len(H1) m = len(H2) mod = Model() # Parameters I = list(range(n)) J = (range(m)) # Variables x = {} for i in I: for j in J: x[i,j] = mod.addVar(obj=D(H1[i], H2[j])) # Constraints on the supports for i in I: mod.addConstr(quicksum(x[i,j] for j in J) == 1) for j in J: mod.addConstr(quicksum(x[i,j] for i in I) == 1) # Train: Solve the model mod.optimize() ColMap = [] for i in I: for j in J: if x[i,j].X > 0.5: ColMap.append(j) return ColMap
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 optimize_latency(Bw, h): # create a model m = Model('latency') # create decision variables x = m.addVars(an, an, vtype=GRB.BINARY, name='x') y = m.addVars(an, dc, vtype=GRB.BINARY, name='y') ######### add constraints ########## # x is symmetric m.addConstrs((x[i, j] == x[j, i] for i in an for j in an), 'symmetric constraint') # Two service areas cant use the same stateful functions when x[i,j] = 0 m.addConstrs((y[i, t] + y[j, t] <= x[i, j] + 1 for i in an for j in an for t in dc), 'x = 0 constraint') # Two service areas use the same stateful functions when x[i,j] = 1 m.addConstrs(((y[i, t] - y[j, t] <= 1 - x[i, j]) for i in an for j in an for t in dc), 'x = 1 constraint') # One access node connects to only one dc m.addConstrs((sum(y[i, t] for t in dc) == 1 for i in an), 'one dc for access node') # high availability constraint m.addConstr( sum((1 - x[i, j]) for i in an for j in an if i != j) >= 1, 'ha') # maximum state transfer frequency m.addConstr( sum(h * (1 - x[i, j]) for i in an for j in an if i != j) <= State_max, 'max state transfer constraint') ######## Objective function ######### # Optimize latency budget m.setObjective( sum(y[i, t] * C[i, t] * (Sd / Bw + Lw + Wg) for i in an for t in dc), GRB.MINIMIZE) m.optimize() ######## Calculate performance metrics ######### # latency latency = sum(C[i, t] * (Sd / Bw + Lw + Wg) * getattr(y[i, t], 'X') for i in an for t in dc) # state transfer frequency state_transfer = sum(h * (1 - getattr(x[i, j], 'X')) for i in an for j in an if i != j) # number of function num_func = M_dc - sum( prod(1 - getattr(y[i, t], 'X') for i in an) for t in dc) # total cost cost = latency + state_transfer # total metrics total_metrics = [Bw, h, state_transfer, latency, num_func, cost] # utopia point, nadir point worst_state = state_transfer best_latency = latency return total_metrics, worst_state, best_latency
def TWTgurobi(): jobs = tuple(range(1,5)) jobPairs = [(i,j) for i in jobs for j in jobs if i < j] # job_id as keys and weight as content weight = dict(zip(jobs, (4,3,4,5))) duration = dict(zip(jobs, (12,8,15,9))) deadline = dict(zip(jobs, (16,26,25,27))) # Big M for modeling M = sum(duration.values()) try: m = Model('TWTexample') x = m.addVars(jobPairs, vtype=GRB.BINARY, name='x') startTime = m.addVars(jobs, name='startTime') tardiness = m.addVars(jobs, name='tardiness') m.setObjective(quicksum([weight[j]*tardiness[j] for j in jobs]), GRB.MINIMIZE) m.addConstrs((startTime[j] >= startTime[i]+duration[i]-M*(1-x[i,j]) for(i,j) in jobPairs), 'NoOverplap1') m.addConstrs((startTime[i] >= startTime[j]+duration[j]-M*x[i,j] for(i,j) in jobPairs), 'NoOverplap2') m.addConstrs((tardiness[j] >= startTime[j]+duration[j]-deadline[j] for j in jobs), 'Deadline') m.optimize() if m.status == GRB.Status.INF_OR_UNBD: m.setParam(GRB.Param.DualReductions, 0) m.optimize() if m.status == GRB.Status.OPTIMAL: for v in m.getVars(): print('%s:\t%g' %(v.varName, v.x)) print('Objective:\t%g' % m.objVal) else: statstr = StatusDict[m.status] print('Optimization was stopped with status %s' %statstr) except GurobiError as e: print('Error code '+str(e.errno)+': '+str(e))
class RegressionModel: def __init__(self, instance): self.model = Model() self.vars = dict() self._set_model(instance) def _set_model(self, instance): model = self.model factors = range(instance.factors) obs = range(instance.obs) X = instance.X Y = instance.Y beta_0 = model.addVar(lb=-GRB.INFINITY) beta_1 = model.addVars(factors, lb=-GRB.INFINITY) error = quicksum((Y[i] - beta_0 - quicksum(beta_1[j] * X[i][j] for j in factors)) ** 2 for i in obs) model.setObjective(error, sense=GRB.MINIMIZE) self.vars['beta_0'] = beta_0 self.vars['beta_1'] = beta_1 def solve(self): self.model.optimize() m = list(map(lambda x: x.X, self.vars['beta_1'].values())) n = self.vars['beta_0'].X return m, n
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 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 _cut_half(c, P): """ Given polytopen and direction c, cut it into half """ n = c.shape[0] assert n == P.H.shape[1] model = Model("n") x = tupledict_to_array( model.addVars(range(n), [0], lb=-GRB.INFINITY, ub=GRB.INFINITY, name="x")) model.update() constraints_list_of_tuples(model, [(P.H, x), (-np.eye(P.h.shape[0]), P.h)], sign="<") J = LinExpr([(c[i, 0], x[i, 0]) for i in range(n)]) model.setParam('OutputFlag', False) model.setObjective(J, GRB.MINIMIZE) model.optimize() g_min = model.ObjVal model.setObjective(J, GRB.MAXIMIZE) # Max model.reset() model.optimize() g_max = model.ObjVal g = np.array([(g_max + g_min) / 2.0]).reshape(1, 1) P1 = polytope(np.vstack((P.H, c.T)), np.vstack((P.h, g))) P2 = polytope(np.vstack((P.H, -c.T)), np.vstack((P.h, -g))) return P1, P2, (c, g)
def rocket(): from gurobipy import Model, GRB # Set up data Mass = [ 70, 90, 100, 110, 120, 130, 150, 180, 210, 220, 250, 280, 340, 350, 400 ] P = range(len(Mass)) # A, B, C, D Sections = ["A", "B", "C", "D"] S = range(len(Sections)) m = Model('Rocket Payload') X = m.addVars(P, S, vtype=GRB.BINARY, name='X') Y = m.addVars(P, S, name='Y', obj=1) m.addConstrs(Y[p, s] == X[p, s] * Mass[p] for p, s in X.keys()) m.addConstrs(Y.sum('*', s) <= 1000 for s in S) m.addConstrs(X.sum('*', s) >= 3 for s in S) m.addConstr(Y.sum('*', 0) == Y.sum('*', 3)) m.addConstr(Y.sum('*', 1) == Y.sum('*', 2)) m.setAttr(GRB.Attr.ModelSense, GRB.MAXIMIZE) m.optimize()
def 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 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 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
class IandPModel: def __init__(self, instance): self.model = Model() self.vars = dict() self._set_model(instance) def _set_model(self, instance): T = instance.periods c = instance.c h = instance.h d = instance.d model = self.model x = model.addVars(range(T)) z = model.addVars(range(T)) model.addConstrs(z[t] == z[t - 1] + x[t] - d[t] for t in range(1, T)) model.addConstr(z[0] == x[0] - d[0]) obj = quicksum(c[t] * x[t] + h[t] * z[t] for t in range(T)) model.setObjective(obj, sense=GRB.MINIMIZE) self.vars = {'x': x, 'z': z} def solve(self): self.model.optimize()
def optimize(inputFile, outputFile): '''Function which takes in two input arguments: - inputFile: the path to the input data. (.xlsx format) - outputFile: the path to the output data. (.xlsx format) The outputFile gives the optimal set of books to carry as well as the minimum number of books needed.''' genres = pd.read_excel(inputFile, sheet_name='genres', index_col=0).fillna(0) requirements = pd.read_excel(inputFile, sheet_name='requirements', index_col=0) mod = Model() I = genres.index J = genres.columns x = mod.addVars(I, vtype=GRB.BINARY) mod.setObjective(sum(x[i] for i in I)) for j in J: mod.addConstr( sum(genres.loc[i, j] * x[i] for i in I) >= requirements.loc[j]) mod.setParam('outputflag', False) mod.optimize() writer = pd.ExcelWriter(outputFile) carry = [] for i in I: if x[i].x: carry.append(i) pd.DataFrame(carry,columns=['books'])\ .to_excel(writer,sheet_name='optimal_decision') pd.DataFrame([mod.objVal],columns=['books_needed'])\ .to_excel(writer,sheet_name='objective',index=False) writer.save()
def optimize_pareto(Bw, h, ju_s, ju_l, jn_s, jn_l): # create a model m = Model('Pareto') # create decision variables x = m.addVars(an, an, vtype=GRB.BINARY, name='x') y = m.addVars(an, dc, vtype=GRB.BINARY, name='y') ######### add constraints ########## m.addConstrs((x[i, j] == x[j, i] for i in an for j in an), 'symmetric constraint') # Two service areas cant use the same stateful functions when x[i,j] = 0 m.addConstrs((y[i, t] + y[j, t] <= x[i, j] + 1 for i in an for j in an for t in dc), 'x = 0 constraint') # Two service areas use the same stateful functions when x[i,j] = 1 m.addConstrs(((y[i, t] - y[j, t] <= 1 - x[i, j]) for i in an for j in an for t in dc), 'x = 1 constraint') # Each should be at least managed by one dc m.addConstrs((sum(y[i, t] for t in dc) == 1 for i in an), 'one dc for access node') # high availability constraint m.addConstr( sum((1 - x[i, j]) for i in an for j in an if i != j) >= 1, 'ha') # maximum state transfer frequency m.addConstr( sum(h * (1 - x[i, j]) for i in an for j in an if i != j) <= jn_s - 1, 'max state transfer constraint') # maximum latency constraint m.addConstr( sum(y[i, t] * C[i, t] * (Sd / Bw + Lw + Wg) for i in an for t in dc) <= jn_l, 'latency maximum constraint') ######## Objective function ######### m.setObjective((sum(y[i, t] * C[i, t] * (Sd / Bw + Lw + Wg) for i in an for t in dc) - ju_l) / (jn_l - ju_l) + (sum(h * (1 - x[i, j]) for i in an for j in an if i != j) - ju_s) / (jn_s - ju_s), GRB.MINIMIZE) m.optimize() ######## Calculate performance metrics ######### # latency latency = sum(C[i, t] * getattr(y[i, t], 'X') * (Sd / Bw + Lw + Wg) for i in an for t in dc) # state transfer frequency state_transfer = sum(h * (1 - getattr(x[i, j], 'X')) for i in an for j in an if i != j) # total cost cost = latency + state_transfer # number of functions num_func = M_dc - sum( prod(1 - getattr(y[i, t], 'X') for i in an) for t in dc) # total metrics total_metrics = [Bw, h, state_transfer, latency, num_func, cost] return total_metrics
def 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)
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 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 main(): try: (sizes, cs, aovs, ems) = loadData('./data.csv') cs = cs[:7] + cs[12:13] + cs[18:19] aovs = aovs[:7] + aovs[12:13] + aovs[18:19] # ems = fixEms(ems) # Create a new model m = Model("mip1") # Create variables vars = createVariables(m) # Integrate new variables m.update() # maximize \sum_{i=1}^{2096}sizes_i\sum_{j=1}^{24}cs_j*aov_j # Set objective m.setObjective(sum([sum([cs[i][j]*aovs[i][j]*vars[i][j] for i in range(ncategory)])*sizes[j] for j in range(nrecords)]), GRB.MAXIMIZE) # c1,c2,c3,c4,c5,c6,c7,c42,c64 # v0,v1,v2,v3,v4,v6,v6,v7, v8 # Add constraints: sum([vars[7][j]+vars[8][j]+vars[9][j] for j in range(nrecords)]) == sum([vars[0][j] for j in range(nrecords)]) m.addConstr(sum([vars[7][j] for j in range(nrecords)]) <= sum([vars[3][j] for j in range(nrecords)])) m.addConstr(sum([vars[8][j] for j in range(nrecords)]) <= sum([vars[5][j] for j in range(nrecords)])) m.addConstr(sum([vars[7][j] for j in range(nrecords)]) <= 18000) m.addConstr(sum([vars[7][j] for j in range(nrecords)]) >= 8000) m.addConstr(sum([vars[8][j] for j in range(nrecords)]) <= 6000) m.addConstr(sum([vars[8][j] for j in range(nrecords)]) >= 3000) m.addConstr(sum([vars[0][j] for j in range(nrecords)]) <= 25000) m.addConstr(sum([vars[0][j] for j in range(nrecords)]) >= 10000) m.addConstr(sum([vars[1][j] for j in range(nrecords)]) <= 8500) m.addConstr(sum([vars[1][j] for j in range(nrecords)]) >= 5000) m.addConstr(sum([vars[2][j] for j in range(nrecords)]) <= 8000) m.addConstr(sum([vars[2][j] for j in range(nrecords)]) >= 1500) m.addConstr(sum([vars[3][j] for j in range(nrecords)]) <= 10000) m.addConstr(sum([vars[3][j] for j in range(nrecords)]) >= 4000) m.addConstr(sum([vars[4][j] for j in range(nrecords)]) <= 8000) m.addConstr(sum([vars[4][j] for j in range(nrecords)]) >= 1500) m.addConstr(sum([vars[5][j] for j in range(nrecords)]) <= 20000) m.addConstr(sum([vars[5][j] for j in range(nrecords)]) >= 9000) m.addConstr(sum([vars[6][j] for j in range(nrecords)]) <= 15000) m.addConstr(sum([vars[6][j] for j in range(nrecords)]) >= 8000) for j in range(nrecords): m.addConstr(sum([vars[i][j] for i in range(0, 9)]) <= 3*sizes[j]) m.update() m.optimize() m.write("./macy.lp") for v in m.getVars(): print v.varName, v.x print 'Obj:', m.objVal except GurobiError: print 'Error reported: {}'.format(GurobiError)
class mip_model(object): def __init__(self, samples, delta=1.0): self.n_nodes = samples.n_nodes self.n_samples = samples.n_samples self.delta = delta self.B = samples.B self.T = samples.T self.F = samples.F self.model = Model('DPSL') self.create_model() def create_model(self): self.U = self.model.addVars(self.n_nodes, self.n_samples, name='U', lb=0, ub=1, vtype=GRB.CONTINUOUS) self.M = self.model.addVars(self.n_nodes, name='M', lb=0, ub=1, vtype=GRB.CONTINUOUS) self.y = self.model.addVars(self.n_nodes, self.n_samples, name='y', lb=0, ub=1, vtype=GRB.CONTINUOUS) self.z = self.model.addVars(self.n_nodes, self.n_nodes, self.n_samples, name='z', lb=0, ub=1, vtype=GRB.CONTINUOUS) self.model.addConstrs((self.y[i, n] >= -1 + self.M[i] + self.B[i, n] - self.U[i, n]) for i in range(self.n_nodes) for n in range(self.n_samples)) self.model.addConstrs((self.z[i, j, n] >= -2 + self.T[i, j, n] + self.F[i, j, n] + self.U[j, n] - self.U[i, n]) for i in range(self.n_nodes) for j in range(self.n_nodes) for n in range(self.n_samples) if i != j) cost_expr = 2 * self.M.sum() - (5 / self.n_samples) * self.U.sum() dist_expr = self.y.sum() + self.z.sum() + self.U.sum() self.model.setObjective(cost_expr + self.delta * dist_expr, GRB.MINIMIZE) def solve(self): self.model.optimize() for i in range(self.n_nodes): print(self.M[i].x)
def 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 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 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 _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 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 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 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
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)
# Re-optimize until either we have run a certain number of iterations # or complementary slackness conditions apply. for k in range(1, 101): # max sum i,j: c_ij * x_ij model.setObjective( sum( # Original objective function sum(c_ij * x_ij for c_ij, x_ij in zip(c_i, x_i)) for c_i, x_i in zip(c, x) ) + sum ( # Penalties for dualized constraints u_j * p_j for u_j, p_j in zip(u, penalties) ) ) model.optimize() print 'iteration', k, 'obj =', model.objVal, \ 'u =', u, 'penalties =', [p.x for p in penalties] # Test for complementary slackness stop = True eps = 10e-6 for u_i, p_i in zip(u, penalties): if abs(u_i) > eps and abs(p_i.x) > eps: stop = False break if stop: print 'primal feasible & optimal' break
def generateInstance(self): # Check that variables have been intialized correctly if (not self.planes) or (self.n == 0) or (self.T == 0): logging.error('Store is not initialized correctly. Check for completeness of input-file.') return None model = Model("PlaneSolver") """ r: Earliest landing possibility b: Best landing d: latest landing g: penalty for each time earlier from best h: penalty for each time later from best s_ij: if i lands before j: s needs to pass in time x_i: Landing time for i p_i: positive divertion from bi n_i: negative divertion from bi """ bigM = max([max(x["s"]) for x in self.planes]) logging.debug("Using bigM punishment: " + str(bigM)) # generate Variables x = {} # Landing time p = {} # Positive divertion from optimal landing time n = {} # Negative divertion from optimal landing time s = {} # 1 iff plane i lands before j + buffer is invalid s1 = {} # for these, see constraints s2 = {} h1 = {} h2 = {} for i in range(len(self.planes)): x[i] = model.addVar(name="x_%d" % (i+1), vtype="i", lb=self.planes[i]["r"], ub=self.planes[i]["d"]) p[i] = model.addVar(name="p_%d" % (i+1), vtype="i", obj=self.planes[i]["h"], lb=0, ub=self.planes[i]["d"] - self.planes[i]["b"]) n[i] = model.addVar(name="n_%d" % (i+1), vtype="i", obj=self.planes[i]["g"], lb=0, ub=self.planes[i]["b"] - self.planes[i]["r"]) for j in range(len(self.planes)): s[i, j] = model.addVar(name="s_%d_%d" % (i+1, j+1), vtype="b", obj=bigM, lb=0, ub=1) s1[i, j] = model.addVar(name="s1_%d_%d" % (i+1, j+1), vtype="b", obj=0, lb=0, ub=1) s2[i, j] = model.addVar(name="s2_%d_%d" % (i+1, j+1), vtype="b", obj=0, lb=0, ub=1) h1[i, j] = model.addVar(name="h1_%d_%d" % (i+1, j+1), vtype="i", obj=0, lb=0) h2[i, j] = model.addVar(name="h2_%d_%d" % (i+1, j+1), vtype="i", obj=0, lb=0) model.modelSense = GRB.MINIMIZE model.update() for y in model.getVars(): if y.ub < 10000: logging.debug("%10s\t[%5d:%5d]\tobj %4d", y.varName, y.lb, y.ub, y.obj) # Constraints for i in range(len(self.planes)): logging.debug("{} == {} + {} - {}".format(x[i].varName, self.planes[i]["b"], p[i].varName, n[i].varName)) model.addConstr(x[i] == self.planes[i]["b"] + p[i] - n[i]) for j in range(len(self.planes)): if j == i: continue # model.addConstr(x[j] - x[i] ) # Force s = s1 AND s2 model.addConstr(s[i, j] <= s1[i, j]) model.addConstr(s[i, j] <= s2[i, j]) model.addConstr(s[i, j] >= s1[i, j] + s2[i, j] - 1) # s2 == xj - xi > 0 logging.debug("{}\t <= {}\t - {}\t - {}\t".format(s2[i, j].varName, x[j].varName, x[i].varName, h1[i, j].varName)) model.addConstr(s2[i, j] <= x[j] - x[i] + h1[i, j]) logging.debug("{}\t >= 1\t".format(h1[i, j].varName)) model.addConstr(h1[i, j] >= 1) logging.debug("{}\t - {}\t + {}\t <= {}\t*{}\t".format(x[j].varName, x[i].varName, h1[i, j].varName, s2[i, j].varName, bigM)) model.addConstr(x[j] - x[i] + h1[i, j] <= s2[i, j]*bigM) # s1 == xi + sij - xj > 0 logging.debug("{}\t + {}\t - {}\t >= {}\t".format(x[i].varName, self.planes[i]["s"][j], x[j].varName, s1[i, j].varName)) model.addConstr(s1[i, j] <= x[i] + self.planes[i]["s"][j] - x[j] + h2[i, j]) logging.debug("{}\t + {}\t - {}\t <= {}\t*{}\t".format(x[i].varName, self.planes[i]["s"][j], x[j].varName, s1[i, j].varName, bigM)) model.addConstr(x[i] + self.planes[i]["s"][j] - x[j] <= s1[i, j]*bigM) # solve it model.optimize() # Debugging printouts dbgStrs = {} for y in model.getVars(): if y.varName[0:2] not in dbgStrs: dbgStrs[y.varName[0:2]] = [] dbgStrs[y.varName[0:2]].append("%8s = %4s [%4s]" % (y.varName, int(y.x), int(y.x*y.obj) if y.obj else "")) for x in dbgStrs: dbgStrs[x].sort() while dbgStrs: printed = False keys = [x for x in dbgStrs.keys()] keys.sort() logStr = "" for x in keys: if dbgStrs[x]: logStr += dbgStrs[x][0] dbgStrs[x] = dbgStrs[x][1::] printed = True else: logStr += " "*22 logging.debug(logStr) if not printed: break self.model = model
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 __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 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 _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 createModel(self): w = {} self.y = {} self.x = {} m = Model("Optimization Model") m.Params.timeLimit = self.timeLimit #Create variables for n in range(self.nScenario): for k in range(self.numberOfFinancialAsstValues): for j in range(self.numLandowners): w[j, k, n] = m.addVar(vtype=GRB.CONTINUOUS, name="w_j"+str(j)+"_k"+str(k)+"_n"+str(n)) for k in range(self.numberOfFinancialAsstValues): for j in range(self.numLandowners): self.y[j, k] = m.addVar(vtype=GRB.BINARY, name="y_j"+str(j)+"_k"+str(k)) if self.method == 2: for k in range(1, self.numberOfFinancialAsstValues): self.x[k] = m.addVar(vtype=GRB.BINARY, name="x_k%s" % k) m.update() #6a updated for n in range(self.nScenario): m.addConstr(quicksum(w[0,k,n] for k in range(self.numberOfFinancialAsstValues)) == self.SecondStgValues[n]*quicksum(self.DecisionProb[n,0,k]*self.y[0, k] for k in range(self.numberOfFinancialAsstValues)), name = "6a_n"+str(n)) #6b updated for r in range(1,self.numLandowners): for n in range(self.nScenario): m.addConstr(quicksum(w[r-1,k,n] for k in range(self.numberOfFinancialAsstValues)) == quicksum(w[r,k,n]*(1/max(self.DecisionProb[n,r,k],0.00001)) for k in range(self.numberOfFinancialAsstValues)), name = "6b_j"+str(r)+"_n"+str(n)) #6c updated for k in range(self.numberOfFinancialAsstValues): for r in range(self.numLandowners): for n in range(self.nScenario): m.addConstr(w[r, k, n] <= self.y[r, k]*self.SecondStgValues[n], name = "6c_j"+str(r)+"_k"+str(k)+"_n"+str(n)) #6e m.addConstr(quicksum(quicksum(self.C_k[k]*self.y[j, k] for k in range(self.numberOfFinancialAsstValues))*self.AreaBelongsToLandowners[j] for j in range(self.numLandowners)) <= self.Budget_param, name = "6e") #6f for j in range(self.numLandowners): m.addConstr(quicksum(self.y[j, k] for k in range(self.numberOfFinancialAsstValues)) == 1, name = "6f_j"+str(j)) #6g -- Uniform if self.method == 1: for j in range(self.numLandowners-1): for k in range(self.numberOfFinancialAsstValues): m.addConstr(self.y[j, k] == self.y[j+1, k], name = "uniform constraint") #6h -- Hybrid if self.method == 2: for j in range(self.numLandowners): for k in range(1, self.numberOfFinancialAsstValues): m.addConstr(self.y[j, k] <= self.x[k]) m.addConstr(quicksum(self.x[k] for k in range(1, self.numberOfFinancialAsstValues)) <= 1, name = "hybrid constraint") #6a -- Objective m.setObjective(quicksum(quicksum(w[self.numLandowners-1, k, n] for k in range(self.numberOfFinancialAsstValues)) for n in range(self.nScenario)), GRB.MINIMIZE) m.update() start = timeit.default_timer() m.optimize() stop = timeit.default_timer() time = stop - start return m, time
class SQModel(object): ''' classdocs ''' # Private model object __model = [] # Private model variables __z0 = {} __z = {} __q = {} # Private model parameters __BackupCapacity = {} __bBackupLink = {} __links = [] __nodes = [] __capacity = [] __epsilon = 1 __impSample = {} __N = 1 def __init__(self,imp_samp,nodes,links,capacity,epsilon,N,backup_link,link_capacity): ''' Constructor ''' self.__links = links self.__nodes = nodes self.__capacity = capacity self.__epsilon = epsilon self.__N = N self.__loadModel(imp_samp,backup_link,link_capacity) def __loadModel(self,imp_samp, backup_link,link_capacity): # Create optimization model self.__model = Model('Backup') for i,j in self.__links: for k in range(self.__N): 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() for i,j in self.__links: self.__q[i,j] = self.__model.addVar(lb=-GRB.INFINITY,name='q[%s][%s]' %(i,j)) self.__model.update() self.__model.modelSense = GRB.MINIMIZE self.__model.setObjective(quicksum(self.__q[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/(self.__N*self.__epsilon)*quicksum(self.__z[k,i,j]*imp_samp[k] for (k) in range(self.__N)) <= self.__q[i,j],'[CONST]Buffer_Prob_I[%s][%s]'%(i,j)) self.__model.update() # Link capacity constraints for i,j in self.__links: for k in range(self.__N): self.__model.addConstr((quicksum(backup_link[i,j,s,d]*self.__capacity[k,s,d] for s,d in self.__links) - link_capacity[i,j] - self.__z0[i,j]) <= 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(self.__N): self.__model.addConstr(self.__z[k,i,j] >= 0,'[CONST]Buffer_Prob_III[%s][%s][%s]' % (k,i,j)) self.__model.update() def optimize(self,MipGap, TimeLimit, LogLevel = None): self.__model.write('quantile.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: #SuperQuantileSolution = self.__model.getAttr('x', self.__z0) SuperQuantileSolution = {} OptimalZnot = {} for i,j in self.__links: name='q[%s][%s]'%(i,j) v = self.__model.getVarByName(name) SuperQuantileSolution[i,j]=v.x name='z0[%s][%s]'%(i,j) v = self.__model.getVarByName(name) OptimalZnot[i,j]=v.x if LogLevel == 1: for v in self.__model.getVars(): print('%s %g' % (v.varName, v.x)) else: print('Optimal value not found!\n') SuperQuantileSolution = {} OptimalZnot={} return SuperQuantileSolution, OptimalZnot def reset(self): ''' Reset model solution ''' self.__model.reset()
def solve(n, width, height, startNodes, targetNodes, startTimes, endTimes): model = Model("BoatSolver") def toGrid(val, y=0): if isinstance(val, list): return val[0] + val[1] * width return val + y * width T = max(endTimes) x = {} wait = {} for i, j, t in itertools.product(range(n), range(width * height), range(T)): x[i, j, t] = model.addVar(name="x_%d_%d_%d" % (i+1, j+1, t+1), vtype="b", obj=1) wait[i, j, t] = model.addVar(name="wait_%d_%d_%d" % (i+1, j+1, t+1), vtype="i", obj=-1) model.modelSense = GRB.MINIMIZE model.update() # Force startpositions for i, (sN, sT) in enumerate(zip(startNodes, startTimes)): for t in range(sT): for j in range(width * height): if j == toGrid(sN - 1) and t == sT - 1: logging.debug("start: %s == 1", x[i, j, t].varName) model.addConstr(x[i, j, t] == 1) else: logging.debug("start: %s == 0", x[i, j, t].varName) model.addConstr(x[i, j, t] == 0) # Force endpositions for i, (eN, eT) in enumerate(zip(targetNodes, endTimes)): j = toGrid(eN - 1) logging.debug("end: %s == 1", x[i, j, eT - 1].varName) model.addConstr(x[i, j, eT - 1] == 1) # Container vanishes after endTime for t in range(eT, T): logging.debug("end: %s == 0", x[i, j, t].varName) model.addConstr(x[i, j, t] == 0) # single container per node for j, t in itertools.product(range(width * height), range(T)): logging.debug("%s <= 1", [x[i, j, t].varName for i in range(n)]) model.addConstr(quicksum(x[i, j, t] for i in range(n)) <= 1) # Force valid container movement for w, h in itertools.product(range(width), range(height)): vals = [toGrid(w, h)] if h >= 1: vals += [toGrid(w, h - 1)] if w >= 1: vals += [toGrid(w - 1, h)] if h+1 < height: vals += [toGrid(w, h + 1)] if w+1 < width: vals += [toGrid(w + 1, h)] for i, t in itertools.product(range(n), range(1, T)): if endTimes[i] > t and startTimes[i] <= t: logging.debug("sum(%s) >= %s", [x[i, j, t].varName for j in vals], x[i, toGrid(w, h), t - 1].varName) model.addConstr(quicksum(x[i, j, t] for j in vals) >= x[i, toGrid(w, h), t - 1]) else: logging.debug("skipped(%s) >= %s", [x[i, j, t].varName for j in vals], x[i, toGrid(w, h), t - 1].varName) for i, t in itertools.product(range(n), range(1, T)): logging.debug("sum(%s) <= 1", [x[i, j, t].varName for j in vals]) model.addConstr(quicksum(x[i, j, t] for j in vals) <= 1) # Force continous line through grid for i, t in itertools.product(range(n), range(0, T)): if endTimes[i] > t and startTimes[i] <= t + 1: logging.debug("sum(%s) == 1", [x[i, j, t].varName for j in range(width * height)]) model.addConstr(quicksum(x[i, j, t] for j in range(width * height)) == 1) else: logging.debug("sum(%s) == 0", [x[i, j, t].varName for j in range(width * height)]) model.addConstr(quicksum(x[i, j, t] for j in range(width * height)) == 0) # Prevent ships from passing over same link for t in range(1, T): for w, h in itertools.product(range(width - 1), range(height)): for i in range(n): for k in range(i+1, n): model.addConstr(x[i, toGrid(w, h), t - 1] + x[i, toGrid(w + 1, h), t] + x[k, toGrid(w, h), t] + x[k, toGrid(w + 1, h), t - 1] <= 3) model.addConstr(x[i, toGrid(w, h), t] + x[i, toGrid(w + 1, h), t - 1] + x[k, toGrid(w, h), t - 1] + x[k, toGrid(w + 1, h), t] <= 3) for w, h in itertools.product(range(width), range(height - 1)): for i in range(n): for k in range(i+1, n): model.addConstr(x[i, toGrid(w, h), t - 1] + x[i, toGrid(w, h + 1), t] + x[k, toGrid(w, h), t] + x[k, toGrid(w, h + 1), t - 1] <= 3) model.addConstr(x[i, toGrid(w, h), t] + x[i, toGrid(w, h + 1), t - 1] + x[k, toGrid(w, h), t - 1] + x[k, toGrid(w, h + 1), t] <= 3) # Allow free waiting for i, j, t in itertools.product(range(n), range(width * height), range(0, T)): if t < startTimes[i]: model.addConstr(x[i, j, t] == wait[i, j, t]) else: model.addConstr(x[i, j, t - 1] + x[i, j, t] - 1 <= wait[i, j, t]) model.addConstr(x[i, j, t - 1] >= wait[i, j, t]) model.addConstr(x[i, j, t] >= wait[i, j, t]) model.optimize() for y in model.getVars(): if y.x: logging.warning("%s = %d", y.varName, y.x) 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 _master(self, final=False): self.img_cmd_duals = defaultdict(float) self.clique_inter_duals = defaultdict(float) model = Model() model.params.OutputFlag = False obj = [] # x[i,c] = 1 if clique c is used x = {} for clique in self.cliques: if final: x[clique] = v = model.addVar(vtype=GRB.BINARY) else: x[clique] = v = model.addVar() obj.append(clique.cost * v) model.update() # Each image has to run each of its commands. img_cmd_constraints = {} for img, cmds in self.problem.images.items(): for cmd in cmds: vlist = [x[c] for c in self.img_cmd_to_cliques[img, cmd]] if final: model.addConstr(quicksum(vlist) == 1) else: img_cmd_constraints[img, cmd] = model.addConstr(quicksum(vlist) >= 1) # Clique intersections clique_inter_constraints = {} for c1, c2 in self.intersections: clique_inter_constraints[c1, c2] = model.addConstr(x[c1] + x[c2] <= 1) model.setObjective(quicksum(obj), GRB.MINIMIZE) model.optimize() if final: print '\n[final master obj: %.02f]' % model.objVal return [c for c in self.cliques if x[c].x > 0.5] else: header = ' | %s' % (' '.join('% 6s' % c for c in self.problem.commands)) print '-' * len(header) print header print '-' * len(header) for img in self.problem.images: duals = [] for cmd in self.problem.commands: try: extra = img_cmd_constraints[img, cmd].pi self.img_cmd_duals[img, cmd] = extra duals.append(round(extra, 1) or '') except KeyError: duals.append('') print '% 4s | %s' % (img, ' '.join('% 6s' % d for d in duals)) print '-' * len(header) for (c1, c2), c in sorted(clique_inter_constraints.items()): if c.pi: print '[clique/inter dual] %s | %s = %.02f' % (c1, c2, c.pi) self.clique_inter_duals[c1, c2] = c.pi
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 _subproblem(self): cliques = [] for (c1, c2), pi in self.clique_inter_duals.items(): int_images = c1.images_set.intersection(c2.images_set) # Remove images in c1 not in c2 z = pi + c1.cost for i in int_images: dual = sum(self.img_cmd_duals[i, cmd] for cmd in c1.commands) z -= dual if z < 0: cliques.append(Clique(self.problem, int_images, c1.commands)) # Remove images in c2 not in c1 z = pi + c2.cost for i in int_images: dual = sum(self.img_cmd_duals[i, cmd] for cmd in c2.commands) z -= dual if z < 0: cliques.append(Clique(self.problem, int_images, c2.commands)) # Pare images off until they don't intersect anymore if len(c1.images) <= 2 or len(c2.images) <= 2: continue model = Model() model.params.OutputFlag = False # model.params.OutputFlag = False obj = [pi] p1 = model.addVar(vtype=GRB.BINARY) p2 = model.addVar(vtype=GRB.BINARY) q1 = {i: model.addVar(vtype=GRB.BINARY) for i in c1.images} q2 = {i: model.addVar(vtype=GRB.BINARY) for i in c2.images} r1 = {i: model.addVar(vtype=GRB.BINARY) for i in int_images} r2 = {i: model.addVar(vtype=GRB.BINARY) for i in int_images} model.update() obj.append(c1.cost * p1) obj.append(c2.cost * p2) for i in c1.images: dual = sum(self.img_cmd_duals[i, cmd] for cmd in c1.commands) obj.append(-dual * q1[i]) for i in c2.images: dual = sum(self.img_cmd_duals[i, cmd] for cmd in c2.commands) obj.append(-dual * q2[i]) for i in int_images: model.addConstr(p1 <= r1[i] + r2[i]) model.addConstr(p2 <= r1[i] + r2[i]) for i in c1.images: model.addConstr(q1[i] <= p1) if i in int_images: model.addConstr(q1[i] <= 1 - r1[i]) for i in c2.images: model.addConstr(q2[i] <= p1) if i in int_images: model.addConstr(q2[i] <= 1 - r2[i]) model.setObjective(sum(obj), GRB.MINIMIZE) model.optimize() if model.objVal >= 0: continue for c, v, r in [(c1, p1, r1), (c2, p2, r2)]: if v.x < 0.5: continue # Figure out what images are left in the clique rem_imgs = set(c.images) for i, riv in r.items(): if riv.x > 0.5: rem_imgs.remove(i) if len(rem_imgs) > 1: cliques.append(Clique(self.problem, rem_imgs, c.commands)) rem_imgs_1 = set(c1.images) rem_imgs_2 = set(c2.images) z = -c1.cost - c2.cost for i in int_images: dual1 = sum(self.img_cmd_duals[i, cmd] for cmd in c1.commands) dual2 = sum(self.img_cmd_duals[i, cmd] for cmd in c2.commands) if dual1 > dual2: rem_imgs_1.remove(i) z += dual1 else: rem_imgs_2.remove(i) z += dual2 if z > 0: cliques.append(Clique(self.problem, rem_imgs_1, c1.commands)) cliques.append(Clique(self.problem, rem_imgs_2, c2.commands)) return cliques
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
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
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 __objective_function(self, x, q, p_changed=None): m = Model("Overall_Model") if p_changed is not None: j0 = self.project_list.index(p_changed) CT = self.last_CT CT[j0] = self.optmize_single_project(x, j0, self.project_list, self.project_activity, self.resource_supplier_list, self.resource_supplier_release_time, self.supplier_project_shipping, self.M, self.output_dir) else: CT = {} CT_ASYNC = dict() for j in range(self.project_n): ## solve individual model get Project complete date CT_ASYNC[j] = self.pool.apply_async(HeuristicParallelModel.optmize_single_project, (x, j, self.project_list, self.project_activity, self.resource_supplier_list, self.resource_supplier_release_time, self.supplier_project_shipping, self.M, self.output_dir)) for j in range(self.project_n): CT[j] = CT_ASYNC[j].get() self.last_CT = deepcopy(CT) DT = {} TD = {} for j in range(self.project_n): ## 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")) self.obj_value_trace.append(m.objVal) return m.objVal, argmax([self.w[j] * TD[j].X for j in range(self.project_n)])