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 calculate_min_flow(graph, objective, supply, num_goods): result = {} try: model = gp.Model("Network optimization") model.setParam(GRB.Param.OutputFlag, False) flow_indices = gp.tuplelist( (i, j) for i in range(graph.num_edges) for j in range(num_goods)) pos_flow = model.addVars(flow_indices, name='pf') neg_flow = model.addVars(flow_indices, name='nf') mu_indices = gp.tuplelist(range(graph.num_edges)) pos_mu = model.addVars(mu_indices, name='p_mu') neg_mu = model.addVars(mu_indices, name='n_mu') subdiff = objective.subdifferential0() #Add mu >= f(x) for i in range(graph.num_edges): (v, w) = graph.edges[i] length = graph.edge_lengths[v][w] for a in subdiff: pos_eq = 0 neg_eq = 0 for j in range(num_goods): pos_eq += length * a[j] * pos_flow[i, j] neg_eq += length * a[j] * neg_flow[i, j] model.addConstr(pos_mu[i] >= pos_eq) model.addConstr(neg_mu[i] >= neg_eq) #Add divergence constraints div_constraints = [[] for _ in range(graph.num_vertices)] for k in range(graph.num_vertices): for j in range(num_goods): eq = 0 for i in graph.vertex_to_edges[k]: edge = graph.edges[i] if k == edge[0]: eq += pos_flow[i, j] - neg_flow[i, j] else: eq += neg_flow[i, j] - pos_flow[i, j] div_constraints[k].append(model.addConstr(eq == supply[k][j])) #Define objective eq = 0 for i in range(graph.num_edges): eq += pos_mu[i] + neg_mu[i] model.setObjective(eq, GRB.MINIMIZE) model.optimize() result['flow'] = np.array( [[pos_flow[i, j].x - neg_flow[i, j].x for j in range(num_goods)] for i in range(graph.num_edges)]) result['phi'] = np.array( [[div_constraints[k][j].pi for j in range(num_goods)] for k in range(graph.num_vertices)]) result['value'] = model.ObjVal return result except gp.GurobiError as e: print('Error code ' + str(e.errno) + ': ' + str(e)) except AttributeError: print('Attribute error (WTF??)')
def assignFromRTVGraph(self, rtvGraph): m = gp.Model("rtv-assignment") # m.setParam(GRB.Param.OutputFlag, 0) m.setParam(GRB.Param.LogToConsole, 0) m.setParam(GRB.Param.LogFile, "output/gurobi/log.txt") e_ij = gp.tuplelist([(edge.source, edge.target) for edge in rtvGraph.es.select(etype="veh_trip")]) x_k = gp.tuplelist([(v.index) for v in rtvGraph.vs.select(vtype="request")]) req_trips = gp.tupledict({ req.index: [rtvGraph.es[edge].target for edge in rtvGraph.incident(req, ig.ALL)] for req in rtvGraph.vs.select(vtype="request")}) cost_ij = gp.tupledict({(edge.source, edge.target): edge["cost"] for edge in rtvGraph.es.select(etype="veh_trip")}) cost_ko = 1e6 trips = gp.tuplelist([(v.index) for v in rtvGraph.vs.select(vtype="trip")]) vehs = gp.tuplelist([(v.index) for v in rtvGraph.vs.select(vtype="vehicle")]) reqs = gp.tuplelist([(v.index) for v in rtvGraph.vs.select(vtype="request")]) veh_trip_flow = m.addVars(e_ij, vtype=GRB.BINARY, name="e") req_ignored = m.addVars(x_k, vtype=GRB.BINARY, name="x") m.setObjective(veh_trip_flow.prod(cost_ij) + cost_ko * req_ignored.sum(), GRB.MINIMIZE) m.addConstrs((veh_trip_flow.sum(i, "*") <= 1 for i in vehs), "one_veh_per_trip") for k in reqs: m.addConstr(sum([veh_trip_flow.sum("*", j) for j in req_trips[k]]) + req_ignored[k] == 1, "one_veh_max_per_req[{}]".format(k)) m.optimize() if m.status == GRB.OPTIMAL: veh_trips = m.getAttr('x', veh_trip_flow) veh_routes = dict() for edge in rtvGraph.es.select(etype="veh_trip"): veh = rtvGraph.vs[edge.source] vehID = veh.index tripID = edge.target if veh_trips[vehID, tripID] > 0: veh_routes[veh["vid"]] = edge["route"] ignored_reqs = m.getAttr('x', req_ignored) rejected_reqs = set() for req in reqs: if ignored_reqs[req] > 0: rejected_reqs.add(rtvGraph.vs[req]["rid"]) else: return None, None return veh_routes, rejected_reqs
def __init__(self, iter_of_iters): """ Construct a multi-index Slicer object :param iter_of_iters An iterable of iterables. Usually a list of lists, or a list of tuples. Each inner iterable must be the same size. The "*" string has a special flag meaning and cannot be a member of any of the inner iterables. """ verify(hasattr(iter_of_iters, "__iter__"), "need an iterator of iterators") copied = tuple(iter_of_iters) verify(all(hasattr(_, "__iter__") for _ in copied), "need iterator of iterators") self._indicies = tuple(map(tuple, copied)) if self._indicies: verify( min(map(len, self._indicies)) == max(map(len, self._indicies)), "each inner iterator needs to have the same number of elements" ) verify(not any("*" in _ for _ in self._indicies), "The '*' character cannot itself be used as an index") self._gu = None if gu: self._gu = gu.tuplelist(self._indicies) self._indicies = None self.clear()
def build(inst, patterns=None, bound=None, relaxed=False): threshold, lvec, bvec = inst m = len(lvec) assert m == len(bvec) is_active, arcs = create_arcflow_arcs(inst) arcs = gp.tuplelist(arcs) model = gp.Model() x = model.addVars( arcs, name='x', vtype=gp.GRB.CONTINUOUS if relaxed else gp.GRB.INTEGER, ub=[gp.GRB.INFINITY if arc[2] == -1 else bvec[arc[2]] for arc in arcs]) # set start values if patterns is not None: for arc, count in create_variable_start(inst, patterns).items(): x[arc].start = count for j in is_active: if j == 0 or j == threshold: continue model.addConstr(x.sum(j, '*', '*') == x.sum('*', j, '*')) for i in range(m): model.addConstr(x.sum('*', '*', i) <= bvec[i]) obj = x.sum(0, '*', '*') model.setObjective(obj, sense=gp.GRB.MAXIMIZE) if bound is not None: model.addConstr(obj <= bound) return model
def _add_initial_heading(self, times, initial_heading): if get_array_greater_zero(initial_heading): # create degrees for all initial headings degrees = grb.tupledict() arcs = grb.tuplelist() for index in range(len(self.graph.vertices)): v_a = np.array(self.graph.vertices[index]) ad_indexes = [ j for j in range(len(self.graph.vertices)) if self.graph.ad_matrix[index, j] > 0 ] vert_arr = np.array( [self.graph.vertices[i] for i in ad_indexes]) l = len(vert_arr) degrees = np.array([ get_angle(v_a, vert, initial_heading[index]) for vert in vert_arr ]) tuple_list = [((index, ad_indexes[i]), degrees[i]) for i in range(l)] # Correct entries with NaN for i in range(len(tuple_list)): if tuple_list[i] == np.NaN: tuple_list[i][-1] = 0 arcs_i, multidict_i = grb.multidict( tuple_list) if tuple_list else (None, None) degrees.update(multidict_i) arcs.extend(arcs_i) for arc in arcs: self.model.addConstr(times[arc] >= degrees[arc], name="degree_constraint_init")
def exact_gurobi(tsp): global n points, n = tsp.points, tsp.n # Dictionary of Euclidean distance between each pair of points dist = {(i,j) : math.sqrt(sum((points[i][k]-points[j][k])**2 for k in range(2))) for i in range(n) for j in range(i)} with stdout_redirected(), stderr_redirected(): m = gbp.Model() # Create variables vars = m.addVars(dist.keys(), obj=dist, vtype=gbp.GRB.BINARY, name='e') for i,j in vars.keys(): vars[j,i] = vars[i,j] # edge in opposite direction # Add degree-2 constraint m.addConstrs(vars.sum(i,'*') == 2 for i in range(n)) # Optimize model m._vars = vars m.Params.lazyConstraints = 1 m.optimize(subtourelim) vals = m.getAttr('x', vars) selected = gbp.tuplelist((i,j) for i,j in vals.keys() if vals[i,j] > 0.5) tour = subtour(selected) assert len(tour) == n tour.append(tour[0]) tour_len = tsp.tour_length(tour) return tour, tour_len
def createWeightReductionLPWithSetGraph(self,projective,setGraphEdges): model = gp.Model(self.modelName) self.edges = gp.tuplelist(self.g.graph.edges()) self.nodes = self.g.graph.nodes() # add the new variables: # new weights w = {} # incidence vector for the new graph y = {} # diff edges counters d = {} # declare varuables for (u,v) in self.edges: w[u,v] = model.addVar(lb=-1e21,vtype=gp.GRB.CONTINUOUS, name='w_%s_%s' % (u,v)) y[((u,v),)] = model.addVar(vtype=gp.GRB.BINARY, name='y_%s_%s' % (u,v)) d[u,v] = model.addVar(vtype=gp.GRB.BINARY, name='d_%s_%s' % (u,v)) model.update() # incoming edges constraints - every node except for 0 has one incoming edge self.addIncomingEdgesConstrs(self.nodes,self.edges,model,y,'Y') if projective: # non projectivie constrs self.addProjectiveConstrs(self.nodes,model,y,'Y') else: # non proj constrs and vars self.newLPFlowVars = self.addNonProjectiveConstrs(self.nodes,self.edges,y,model,'Y') # diff edges constraints for (u,v) in self.edges: isEdge = 0; if (setGraphEdges.has_key((u,v))): isEdge =1; model.addConstr(d[u,v] + y[((u,v),)], gp.GRB.GREATER_EQUAL,isEdge,'d_z_y_%s_%s' % (u,v)) model.addConstr(d[u,v] + isEdge, gp.GRB.GREATER_EQUAL,y[((u,v),)],'d_y_z_%s_%s' % (u,v)) # lower bounds on w constraints for feature in self.g.allWeights: allSubsets = allNonEmptySubsets(feature) allW = 0 for f in allSubsets: if self.g.allWeights.has_key(f): allW += self.g.allWeights[f] else: print('Oh no! subset is %s, expected to find %s' % (feature,f)) operator = gp.GRB.GREATER_EQUAL; if (allW < 0): operator = gp.GRB.LESS_EQUAL # print(self.g.graph.edges()) model.addConstr(gp.quicksum(w[u,v] for (u,v) in feature),operator,allW,'subset_%s' % '_'.join([str(u) + '_' + str(v) for (u,v) in feature])) self.WeightReductionLPModelWithSetGraph = model self.newWeightsVars = w self.newLPVars = y self.diffEdges = d
def subtourelim(model, where): global var_x, lazy_glob, callbacks_glob, houses_per_period n = houses_per_period if where == GRB.Callback.MIPSOL: vals = model.cbGetSolution(var_x) selected = tuplelist() for i in range(houses_per_period): for j in range(houses_per_period): if vals[i, j, 0, 0] > 0.5 : selected.append((i,j)) tour = subtour(selected) if len(tour) < n: combinationF = list(combinations(tour, 2)) if len(combinationF) == 1: expr = len(tour) - 1 model.cbLazy(var_x[combinationF[0][1], combinationF[0][0], 0, 0] + var_x[combinationF[0][0], combinationF[0][1], 0, 0] <= expr) lazy_glob += 1 else: expr = len(tour) - 1 sumarapida = 0 for i in tour: for j in tour: sumarapida += var_x[i, j, 0, 0] + var_x[j, i, 0, 0] model.cbLazy(sumarapida <= expr) lazy_glob += 1 callbacks_glob += 1
def createLP(self,projective): model = gp.Model(self.modelName) edges = gp.tuplelist(self.g.graph.edges()) nodes = self.g.graph.nodes() # Create variables and objective z = {} for feature in self.g.allWeights: z[feature] = model.addVar(vtype=gp.GRB.BINARY, name='z_%s' % '_'.join([str(u) + '_' + str(v) for (u,v) in feature])) model.update() # incoming edges constraints - every node except for 0 has one incoming edge self.addIncomingEdgesConstrs(nodes,edges,model,z,'Z') if (projective): # projectivity + no circles constraints self.addProjectiveConstrs(nodes,model,z,'Z') else: # non proj constrs and vars self.LPFlowVars = self.addNonProjectiveConstrs(nodes,edges,z,model,'Z') self.LPModel = model self.LPVars = z self.edges = edges self.nodes = nodes
def solveLP(area,coord): m=grb.Model('ILP') modes=[1,2,3,4] allpath=grb.tuplelist() cost={} for cell1 in area: for cell2 in area[cell1]: for mode in modes: allpath.append((cell1,cell2,mode)) if(mode==1): cost[(cell1,cell2,mode)]=distance(coord[cell1-1][0],coord[cell2-1][0]) elif(mode==2): cost[(cell1,cell2,mode)]=distance(coord[cell1-1][0],coord[cell2-1][1]) elif(mode==3): cost[(cell1,cell2,mode)]=distance(coord[cell1-1][1],coord[cell2-1][0]) else: cost[(cell1,cell2,mode)]=distance(coord[cell1-1][1],coord[cell2-1][1]) pathvar=m.addVars(allpath,vtype=grb.GRB.BINARY, name="path") m.setObjective(pathvar.prod(cost), grb.GRB.MINIMIZE) for cell1 in area: m.addConstr( sum(pathvar.select(cell1,'*',1))+ sum(pathvar.select(cell1,'*',2))+ sum(pathvar.select('*',cell1,1))+ sum(pathvar.select('*',cell1,3))==1,str(cell1)+'a') m.addConstr( sum(pathvar.select('*',cell1,2))+ sum(pathvar.select(cell1,'*',3))+ sum(pathvar.select('*',cell1,4))+ sum(pathvar.select(cell1,'*',4))==1,str(cell1)+'b') m.optimize() return (m,pathvar)
def subtour_elimination(model, where): ''' Callback que, para uma solução ótima do K-TSP relaxado, verifica se essa solução viola restrições de eliminação de subciclo e, se sim, adiciona essas restrições ao modelo, que será re-otimizado. Args: model: o modelo associado a callback. where: indica da onde no processo de otimização a callback foi chamada. ''' if where == GRB.Callback.MIPSOL: # Analisar cada rota t for t in range(model._K): # Criar lista de arestas na rota t selecionadas na solução x_sol = model.cbGetSolution(model._vars) edges_in_tour = gp.tuplelist((i, j) for i, j, k in model._vars.keys() if x_sol[i, j, k] > 0.5 and k == t) # Encontrar menor ciclo e verificar se viola restrição, i.e., se # não percorre todos os vértices, formando um subciclo cycle = shortest_cycle(model._n, edges_in_tour) if len(cycle) < n: # Adicionar restrições de eliminação de subciclo, para cada par # de vértices do subciclo encontrado model.cbLazy( gp.quicksum( model._vars[i, j, t] for i, j in combinations(cycle, 2)) <= len(cycle) - 1)
def update_gurobi_model(model, linksNode): # set new best solution model._preprocessingSolution['Path_Disutility'] = model._best # determine all reachable nodes, as in preprocessing feasibleNodes, listOfReachableNodes = get_all_feasible_nodes( model._graphInstance.Graph_for_Preprocessing.subgraph( model._FeasibleNodes), model._graphOrigin, model._graphInstance.Graph_for_Preprocessing_Reverse.subgraph( model._FeasibleNodes), model._graphDestination, model._preprocessingSolution) # remove all edge variables, who contain a node, that is no part of the reduced Graph node_remain = gb.tuplelist() remove_link = [] for i, j, m in linksNode: var_name = 'y[' + str(i) + ',' + str(j) + ',' + str(m) + ']' if i not in feasibleNodes: remove_link.append(var_name) else: if j not in feasibleNodes: remove_link.append(var_name) else: node_remain.append((i, j, m)) print('Removed ' + str(len(remove_link)) + ' variables based on the new identified feasible solution') # remove links for link in remove_link: model.remove(model.getVarByName(link)) return node_remain
def _calculate_degrees(self) -> (grb.tuplelist, grb.tupledict): # Calculate degrees degrees = grb.tupledict() arcs = grb.tuplelist() for i in range(len(self.graph.vertices)): arcs_i, degrees_i = self._get_angles(i) if arcs_i: degrees.update(degrees_i) arcs.extend(arcs_i) return arcs, degrees
def subtourelim(model, where): if where == gbp.GRB.Callback.MIPSOL: # make a list of edges selected in the solution vals = model.cbGetSolution(model._vars) selected = gbp.tuplelist((i,j) for i,j in model._vars.keys() if vals[i,j] > 0.5) # find the shortest cycle in the selected edge list tour = subtour(selected) if len(tour) < n: # add subtour elimination constraint for every pair of cities in tour model.cbLazy(gbp.quicksum(model._vars[i,j] for i,j in itertools.combinations(tour, 2)) <= len(tour)-1)
def NormalBackupModelExample(plot_options, num_nodes,p,invstd,mip_gap, time_limit): ####################################### # Generating graphs ####################################### #Generates a complete indirect graph H = nx.complete_graph(num_nodes) # transforms the indirect graph in directed one G = H.to_directed() #Generates a list with all links (edges) in the graph links = G.edges() #Generates a list with all nodes (vertex) in the graph nodes = G.nodes() capacity={} mean={} std={} Aux=1 for s,d in links: #generating capacity for each s,d link capacity[s,d] = Aux #Generate mean for each s,d link based on Bernouilli distribution mean[s,d] = Aux*p #Generate std for each s,d link based on Bernouilli distribution std[s,d]=math.sqrt(Aux*p*(1-(Aux*p))) if capacity[s,d] > 0: G.add_weighted_edges_from([(s,d,capacity[s,d])]) else: G.add_weighted_edges_from([(s,d,capacity[s,d])]) if plot_options == 1: pos = plotGraph(G, option=0, position=None) ################################ # # optimization # ################################ links = tuplelist(links) BackupNet = Backup(nodes,links,capacity,mean,std,invstd) solution = BackupNet.optimize(mip_gap,time_limit) #penalizes the links chosen to be backup links for i,j in links: if solution[i,j] < 0.1: G.remove_edge(i, j) if plot_options == 1: option=1 plotGraph(G, option, pos)
def __init__(self, nodes=None, patients=None, mutations=None, interactions=None, node_mutations=None, node_neighbors=None): """ :param nodes: ([str]) gene nodes :param patients: ([str]) patient ids :param mutations: ([(str, str)]) node-patient links :param interactions: ([(str, str)]) node-node links :param node_mutations: ({str: {str,}}) node to patient adjacency list :param node_neighbors: ({str: {str,}}) node adjacency list :return """ self.nodes = list() if nodes is None else nodes self.patients = list() if patients is None else patients self.interactions = tuplelist([]) if interactions is None else interactions self.mutations = tuplelist([]) if mutations is None else mutations # auxiliary data structures self.node_mutations = OrderedDict() if node_mutations is None else node_mutations self.node_neighbors = OrderedDict() if node_neighbors is None else node_neighbors self.weights = dict()
def subtourelim(model, where): if where == GRB.Callback.MIPSOL: vals = model.cbGetSolution(model._vars) selected = gp.tuplelist( (i, j) for i, j in model._vars.keys() if vals[i, j] > 0.5) tour = subtour(selected) if len(tour) < n: model.cbLazy( gp.quicksum( model._vars[i, j] for i, j in combinations(tour, 2)) <= len(tour) - 1)
def permute_mutations(self, seed): print "shuffling keys" original = copy.deepcopy(self) index_dictionary = {n: n for n in self.nodes} keys = copy.deepcopy(self.nodes) random.seed(seed) random.shuffle(keys) shuffled_dictionary = dict(zip(keys, index_dictionary.values())) self.mutations = tuplelist() self.interactions = tuplelist() self.node_mutations = OrderedDict() self.node_neighbors = OrderedDict() for n in original.nodes: if n in original.node_mutations: for p in original.node_mutations[n]: self.append_mutation(p, shuffled_dictionary[n]) for u in original.node_neighbors[n]: self.append_interaction(shuffled_dictionary[n], shuffled_dictionary[u])
def subtourelim(model, where): if (where == grb.GRB.Callback.MIPSOL): x_sol = model.cbGetSolution(model._x) arcs = grb.tuplelist( (i, j) for i, j in model._x.keys() if x_sol[i, j] > 0.9) components = getGraphComponents(arcs) for component in components: if (len(component) < n): model.cbLazy( grb.quicksum(x[i, j] for i in component for j in component if i != j) <= len(component) - 1)
def subTour_eliminator(model, where): if where == GRB.Callback.MIPSOL: # possible solution values = model.cbGetSolution(model._vars) selected_nodes = guro.tuplelist((i_1, i_2) for (i_1, i_2) in model._vars.keys() if values[i_1, i_2] > 0.5) sol_tour = get_cycle(selected_nodes) all_tours.append(sol_tour) if len(sol_tour) < len(locations): model.cbLazy(guro.quicksum(model._vars[i_1, i_2] for (i_1, i_2) in combinations(sol_tour, 2)) <= len(sol_tour)-1)
def elimSubTour(model, where): if where == gurobipy.GRB.Callback.MIPSOL: vals = model.cbGetSolution(model._xVar) selectedPairs = gurobipy.tuplelist( (i, j) for i, j in vals.keys() if vals[i, j] > 0.5) visited, notVisited = findSubTour(selectedPairs) # If there is subtour, add constraint: the cut should have at least 2 edges if len(notVisited) > 0: model.cbLazy( gurobipy.quicksum(model._xVar[i, j] for j in notVisited for i in visited if i < j) + gurobipy.quicksum(model._xVar[j, i] for j in notVisited for i in visited if i > j) >= 2)
def tsp_compute(dist_matrix: np.ndarray): # Dictionary of Euclidean distance between each pair of points n = len(dist_matrix) dist = {(i, j): dist_matrix[i, j] for i in range(dist_matrix.shape[0]) for j in range(i)} m = grb.Model() # Create variables vars = m.addVars(dist.keys(), obj=dist, vtype=grb.GRB.BINARY, name="e") for i, j in vars.keys(): vars[j, i] = vars[i, j] # edge in opposite direction # You could use Python looping constructs and m.addVar() to create # these decision variables instead. The following would be equivalent # to the preceding m.addVars() call... # # vars = tupledict() # for i,j in dist.keys(): # vars[i,j] = m.addVar(obj=dist[i,j], vtype=GRB.BINARY, # name='e[%d,%d]'%(i,j)) # Add degree-2 constraint m.addConstrs(vars.sum(i, "*") == 2 for i in range(n)) # Using Python looping constructs, the preceding would be... # # for i in range(n): # m.addConstr(sum(vars[i,j] for j in range(n)) == 2) # Optimize model m._vars = vars m.Params.lazyConstraints = 1 m.optimize(subtourelim) vals = m.getAttr("x", vars) selected = grb.tuplelist( (i, j) for i, j in vals.keys() if vals[i, j] > 0.5) tour = subtour(selected) assert len(tour) == n print("") print("Optimal tour: %s" % str(tour)) print("Optimal cost: %g" % m.objVal) print("") return tour
def __init__(self, *initial_data, **kwargs): self.syllabus_ID = None self.name = None self.organization_ID = None self.device_type_ID = None self.precedence = None self.event_arcs = tuplelist( ) # Tuplelist of arcs (parent event id, child event id) self._ancestors = {} self.events = {} # Set of event objects for dictionary in initial_data: for key in dictionary: setattr(self, key, dictionary[key]) for key in kwargs: setattr(self, key, kwargs[key])
def fix_sub(self): global var_x n = self.HOUSES_PER_PERIOD self.m.Params.lazyConstraints = 1 self.m.optimize(self.subtourelim) selected = tuplelist() for i in range(self.HOUSES_PER_PERIOD): for j in range(self.HOUSES_PER_PERIOD): if var_x[i, j, 0, 0].X > 0.5: selected.append((i,j)) tour = subtour(selected) assert len(tour) == n self.tourfinal = tour self.m.write('sols/SolutionForID_'+ str(self.result_id) + '.sol')
def subtourelim(model, where): if where == grp.GRB.Callback.MIPSOL: # make a list of edges selected in the solution vals = model.cbGetSolution(model._vars) selected = grp.tuplelist((i,j) for i,j in model._vars.keys() if vals[i,j] > 0.5) # find the shortest cycle in the selected edge list tour = subtour(selected) if len(tour) < n: tour_sum = grp.LinExpr() for tour_index, tour_stop in enumerate(tour): if tour_index < len(tour)-1: tour_sum += model._vars[tour[tour_index], tour[tour_index+1]] else: tour_sum += model._vars[tour[tour_index], tour[0]] model.cbLazy(tour_sum <= len(tour)-1)
def solve_model(m, vars): # Optimize model m._vars = vars m.Params.lazyConstraints = 1 m.optimize(subtourelim) #m.optimize() vals = m.getAttr('x', vars) selected = gp.tuplelist((i, j) for i, j in vals.keys() if vals[i, j] > 0.5) tour = subtour(selected) assert len(tour) == n print('') print('Optimal tour: %s' % str(tour)) print('Optimal cost: %g' % m.objVal) print('') return tour
def exact_dual_LP(mdp): """ Construct an exponentially large LP to solve the MDP with Gurobi. This LP follows the standard construction given, for example, on p.25 of 'Competitive Markov Decision Processes' by Filar & Vrieze. The solution to this LP is the value of the initial state. After optimize() has been called, the variables of the LP indicate the optimal policy as follows: if the variable v has v.name=s_a, then action a is optimal in state s iff v.x > 0. """ lp = G.Model() # Throws a NameError if gurobipy wasn't loaded sa_vars = G.tuplelist() for s in mdp.reachable_states: sa_vars.append((s, "STOP", lp.addVar(name=str(s)+"_STOP", lb=0))) for a in mdp.actions: if a.prereq <= s: sa_vars.append((s, a, lp.addVar(name=str(s)+"_"+a.name, lb=0))) lp.update() # set objective obj = G.LinExpr() for s,a,var in sa_vars: rew = mdp.terminal_reward(s) if a == "STOP": obj += rew * var else: obj += (a.stop_prob * rew - a.cost) * var lp.setObjective(obj, G.GRB.MAXIMIZE) # set constraints for s in mdp.reachable_states: constr = G.quicksum([v for _,__,v in sa_vars.select(s)]) for parent,action in mdp.reachable_states[s]: prob = action.trans_prob(parent, s, mdp.variables) var = sa_vars.select(parent,action)[0][2] constr -= prob * var if s == mdp.initial: lp.addConstr(constr, G.GRB.EQUAL, G.LinExpr(1)) else: lp.addConstr(constr, G.GRB.EQUAL, G.LinExpr(0)) lp.update() lp.optimize() return lp, sa_vars
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 graph_parameter(node_file="Nodes_Revised.csv", arc_file="Arcs.csv", commodities_file="Commodities.csv"): # data setup into pandas df's node_df = pd.read_csv(node_file) arc_df = pd.read_csv(arc_file) commodities_df = pd.read_csv(commodities_file) # comodities and quantity {commodity:quantity} commodity_quantity = { k: g['weight'].values[0] for k, g in commodities_df.groupby('name') } # nodes nodes = node_df['nodes'].tolist() # arcs (tuplelist) arcs = tuplelist([tuple(pair) for pair in arc_df.values]) # sources {commodity:source} commodity_source = { k: g['source'].values[0] for k, g in commodities_df.groupby('name') } # sinks {commodity:sink} commodity_sink = { k: g['sink'].values[0] for k, g in commodities_df.groupby('name') } # m_distance {(arc pair): euclidean distance} m_distance = {} for x, y in arcs: x1, y1 = node_df.loc[node_df['nodes'] == x].values[0][1:3] x2, y2 = node_df.loc[node_df['nodes'] == y].values[0][1:3] distance = np.sqrt((x2 - x1)**2 + (y2 - y1)**2) m_distance[(x, y)] = distance final_list = [ commodity_quantity, nodes, arcs, commodity_source, commodity_sink, m_distance ] return final_list
def subtourelim(model, where): if where == GRB.Callback.MIPSOL: # Chọn ra tập các cạnh trong solution hiện tại vals = model.cbGetSolution(model._vars) selected = gp.tuplelist( (i, j) for i, j in model._vars.keys() if vals[i, j] > 0.5) # Tìm ra chu trình có trọng số nhỏ nhất dựa trên các tập cạnh đã được chọn tour = subtour(selected) # Nếu như chu trình này không đi qua n đỉnh if len(tour) < n: # thêm ràng buộc loai bỏ các subtour model.cbLazy( gp.quicksum( model._vars[i, j] for i, j in combinations(tour, 2)) <= len(tour) - 1)
def maximizeMarginalRate(bounds, A, b, noLog=True): # A is a matrix and b is a column vector # bounds = ((min_f1, max_f1), ..., (min_fk, max_fk)) # A f <= b # return (throughput_f1, ... throughput_fk) > (0, ..., 0) if feasible; # otherwise (0, ..., 0) numFlow = len(bounds) (numRow, numCol) = A.shape assert numRow == len(b) and numCol == numFlow model = gp.Model() # define variables flows = gp.tuplelist(t for t in range(numFlow)) t = model.addVars(flows, vtype=gp.GRB.CONTINUOUS, name="t_") for f in flows: (minRate, maxRate) = bounds[f] t[f].setAttr(gp.GRB.Attr.LB, minRate) t[f].setAttr(gp.GRB.Attr.UB, maxRate) model.update() # define the objective function model.setObjective(t.sum(), gp.GRB.MAXIMIZE) # define constraints for row in range(numRow): expr = 0 for f in flows: expr += A[row, f] * t[f] model.addConstr(expr <= b[row], name="c_{0}".format(row)) # solve optimization problem (LP) if noLog: model.setParam("LogToConsole", 0) model.optimize() status = model.status throughputs = [0] * numFlow if status == gp.GRB.Status.OPTIMAL: for f in flows: throughputs[f] = t[f].X elif status == gp.GRB.Status.INFEASIBLE: pass else: assert False, "Solver returns neither OPTIMAL nor INFEASIBLE." return tuple(throughputs)
def subtourelim(model, where): if where == gp.GRB.Callback.MIPSOL: # make a list of edges selected in the solution vals = model.cbGetSolution(model._vars) selected = gp.tuplelist( (i, j) for i, j in model._vars.keys() if vals[i, j] > 0.5) # find the shortest cycle in the selected edge list tour, tours = subtour(selected) if len(tour) < n: model._subtours += 1 # add subtour elimination constraint for every pair of cities in tour model.cbLazy( gp.quicksum( model._vars[i, j] for i, j in itertools.combinations(tour, 2)) <= len(tour) - 1) #st.write(tour) current_length = round(model.cbGet(gp.GRB.Callback.MIPSOL_OBJ)) best = round(model.cbGet(gp.GRB.Callback.MIPSOL_OBJBST)) bound = max(0, round(model.cbGet(gp.GRB.Callback.MIPSOL_OBJBND))) model._summary.markdown( "**Sub tour elimination constraints** {:d} **Lower bound** {:d}km \n**Current Solution** {:d}km - {:d} subtour(s)" .format(model._subtours, bound, current_length, len(tours))) #TODO update bound in other callback. Structure output plt.plot([x[0] for x in points], [x[1] for x in points], 'o') #print("total tours " + str(sum(len(t) for t in tours))) for tour in tours: tour.append(tour[0]) points_tour = [points[i] for i in tour] i = [x[0] for x in points_tour], [x[1] for x in points_tour], '-' # plt.plot([x[0] for x in points_tour], [x[1] for x in points_tour], '-') fig1, ax = plt.subplots() ax.plot([x[0] for x in points_tour], [x[1] for x in points_tour], '-') # plt.axis([0, 105, 0, 105]) # plt.xlabel("km") # plt.ylabel("km") # model._plot.pyplot() ax.set_xlabel('km') ax.set_ylabel('km') model._plot.pyplot(fig1)
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 get_edges_in_tour(tour_id, x_sol, all_edges): ''' Função que, dado o conjunto de variáveis na solução, retorna as arestas (i, j) que estão presentes em uma rota. Args: tour_id: identificador da rota. x_sol: valores de 'x' (variáveis que indicam presença das arestas) na solução. all_edges: lista de arestas (i,j) no grafo de entrada. Returns: Lista de arestas (i,j) na rota 'tour_id'. ''' return gp.tuplelist( (i, j) for i, j, k in all_edges if x_sol[i, j, k] > 0.5 and k == tour_id )
def make_transfers(players): m = Model("make_transfers") m.params.OutputFlag = 0 cur_lu = lineup.Lineup().connect(players) new_xs, cur_xs = [], [] team_pos = tuplelist() teams = [[] for _ in xrange(players.shape[0])] gks, defs, mids, fors = [], [], [], [] assigns = [gks, defs, mids, fors] tcodes = set() for i in xrange(players.shape[0]): obj = pick_team.player_objective(players.iloc[i], 75) v = m.addVar(vtype=GRB.BINARY, obj=obj) if players.iloc[i]["code"] in cur_lu: cur_xs.append((v, players.iloc[i])) else: new_xs.append((v, players.iloc[i])) ptype = players.iloc[i]["element_type"] tcode = players.iloc[i]["team_code"] assigns[ptype - 1].append(v) teams[tcode - 1].append(v) tcodes.add(tcode) team_pos.append((v, ptype, tcode)) m.update() money_in, money_out = compute_money_diff(cur_lu, cur_xs, new_xs) pick_team.per_pos_team_constr(m, tcodes, team_pos) pick_team.total_team_constr(m, teams) m.addConstr(quicksum(gks) == 2) m.addConstr(quicksum(defs) == 5) m.addConstr(quicksum(mids) == 5) m.addConstr(quicksum(fors) == 3) m.addConstr(quicksum(money_out) <= quicksum(money_in)) m.optimize() return construct_new_team(cur_lu, cur_xs, new_xs)
def WassersteinDualSimplex(h1, h2, M): """ Find the Wasserstein distance using the dual simplex """ n = len(h1) # Build model m = Model() m.setParam(GRB.Param.NumericFocus, 3) #m.setParam(GRB.Param.TimeLimit, 300) #m.setParam(GRB.Param.Presolve, 0) #m.setParam(GRB.Param.Threads, 1) # Options are: # -1=automatic, 0=primal simplex, 1=dual simplex, 2=barrier, # 3=concurrent, 4=deterministic concurrent. #m.setParam(GRB.Param.Method, 0) print('1. Start building model') # Create variables x = {} P = set() D = [] for i in range(n): if h1[i] > 0: x[i] = {} for j in range(n): if h2[j] > 0: x[i][j] = m.addVar(ub=min(h1[i], h2[j]), obj=M[i][j]) D.append((i, j)) P.add(j) D = tuplelist(D) m.update() print('2. Add initial constraint sets') for i in x: m.addConstr(quicksum(x[i][j] for j in x[i]) <= h1[i]) for j in P: m.addConstr(quicksum(x[i][j] for i, j in D.select('*', j)) >= h2[j]) print('3. Start solution phase') # Solve the model m.optimize() return m.getAttr(GRB.Attr.ObjVal)
def main(N, dist): global n n = N m = gp.Model() m.setParam('OutputFlag', 0) vars = m.addVars(dist.keys(), obj=dist, vtype=GRB.BINARY, name='e') for i, j in vars.keys(): vars[j, i] = vars[i, j] m.addConstrs(vars.sum(i, '*') == 2 for i in range(n)) m._vars = vars m.Params.lazyConstraints = 1 m.optimize(subtourelim) vals = m.getAttr('x', vars) selected = gp.tuplelist((i, j) for i, j in vals.keys() if vals[i, j] > 0.5) tour = subtour(selected) assert len(tour) == n return tour, m.objVal
def main(budget=3): data = read_csv('temp.csv') s = data.groupby('fbus').p.sum() d = -data.groupby('tbus').p.sum() b = s.add(d, fill_value=0) x = data.set_index(['fbus', 'tbus']) capacities = x.to_dict()['p'] x['costs'] = 1 c = x.to_dict()['costs'] buses = list(b.index) lines, u = multidict(capacities) lines = tuplelist(lines) S = set(b[b>0].index) D = set(b[b<=0].index) b = b.to_dict() w, v, y, m = solve(budget, buses, lines, u, c, b, S, D) if not m.status == GRB.status.OPTIMAL: raise RuntimeError('Gurobi did not converge, status %d' % m.status) for i, j in y: if y[i, j].x > 0: print('%d %d' % (i, j))
def createAndSolveOriginalLP(self,projective): model = gp.Model(self.modelName) graph = self.g.graph partsManager = self.g.partsManager edges = gp.tuplelist(graph.edges()) nodes = graph.nodes() # Create variables and objective z = {} sibs = {} gpnt = {} edge2val = {} sibs2val = {} gpnt2val = {} # slack variables for p in partsManager.getAllParts(): if p.type == 'arc': u = p.u v = p.v z[u,v] = model.addVar(vtype=gp.GRB.BINARY, name=('z_%s_%s' % (u,v))) edge2val[u,v] = p.val elif p.type == 'sibl': u = p.u v1 = p.v1 v2 = p.v2 sibs[u,v1,v2] = model.addVar(vtype=gp.GRB.BINARY, name=('sibs_%s_%s_%s' % (u,v1,v2))) sibs2val[u,v1,v2] = p.val elif p.type == 'grandParant': g = p.g u = p.u v = p.v gpnt[g,u,v] = model.addVar(vtype=gp.GRB.BINARY, name=('gpnt_%s_%s_%s' % (g,u,v))) gpnt2val[g,u,v] = p.val model.update() # incoming edges constraints - every node except for 0 has one incoming edge self.addIncomingEdgesConstrs(nodes,edges,model,z,'Z') if (projective): # projectivity + no circles constraints self.addProjectiveConstrs(nodes,model,z,'Z',partsManager) else: # non proj constrs and vars self.LPFlowVars = self.addNonProjectiveConstrs(nodes,edges,z,model,'Z') # high order parts for (u,v1,v2) in sibs: model.addConstr(sibs[u,v1,v2], gp.GRB.LESS_EQUAL,z[u,v1]) model.addConstr(sibs[u,v1,v2], gp.GRB.LESS_EQUAL,z[u,v2]) model.addConstr(sibs[u,v1,v2], gp.GRB.GREATER_EQUAL,z[u,v1] + z[u,v2] - 1) for (g,u,v) in gpnt: model.addConstr(gpnt[g,u,v], gp.GRB.LESS_EQUAL,z[g,u]) model.addConstr(gpnt[g,u,v], gp.GRB.LESS_EQUAL,z[u,v]) model.addConstr(gpnt[g,u,v], gp.GRB.GREATER_EQUAL,z[g,u] + z[u,v] - 1) model.update() # define objective model.setObjective(gp.quicksum(z[u,v]*edge2val[u,v] for (u,v) in edges) + \ gp.quicksum(sibs[u,v1,v2]*sibs2val[u,v1,v2] for (u,v1,v2) in sibs2val.keys()) + \ gp.quicksum(gpnt[u,v1,v2]*gpnt2val[u,v1,v2] for (u,v1,v2) in gpnt2val.keys()) \ ,gp.GRB.MAXIMIZE) model.update() model.setParam('OutputFlag', False ) # solve the model model.optimize() if model.status == gp.GRB.status.OPTIMAL: optEdges = [] for (u,v) in edges: if z[u,v].x > 0: optEdges.append((u,v)) return optEdges
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 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 createLP(self,projective,setGraphEdges,applyPositiveSlacks,alpha): model = gp.Model(self.modelName) graph = self.g.graph partsManager = self.g.partsManager edges = gp.tuplelist(graph.edges()) nodes = graph.nodes() nonEdgeParts = [] M = 1000 # Create variables and objective z = {} # weights wplus = {} # wminus = {} # diff edges counters d = {} # slack variables slackVars = {} for p in partsManager.getAllParts(): if p.type == 'arc': u = p.u v = p.v z[u,v] = model.addVar(vtype=gp.GRB.BINARY, name=('z_%s_%s' % (u,v))) wplus[u,v] = model.addVar(vtype=gp.GRB.CONTINUOUS, name=('w+_%s_%s' % (u,v)), lb=-1e21) # wminus[u,v] = model.addVar(vtype=gp.GRB.CONTINUOUS, name=('w-_%s_%s' % (u,v)), lb=-1e21) d[u,v] = model.addVar(vtype=gp.GRB.BINARY, name=('d_%s_%s' % (u,v))) nonEdgeParts.append(p) slackVars[p] = model.addVar(vtype=gp.GRB.CONTINUOUS) model.update() # incoming edges constraints - every node except for 0 has one incoming edge self.addIncomingEdgesConstrs(nodes,edges,model,z,'Z') if (projective): # projectivity + no circles constraints self.addProjectiveConstrs(nodes,model,z,'Z',partsManager) else: # non proj constrs and vars self.LPFlowVars = self.addNonProjectiveConstrs(nodes,edges,z,model,'Z',partsManager) # diff edges constraints for (u,v) in edges: isEdge = 0; if (u,v) in setGraphEdges: isEdge =1; model.addConstr(d[u,v] + z[u,v], gp.GRB.GREATER_EQUAL,isEdge,'d_z_y_%s_%s' % (u,v)) model.addConstr(d[u,v] + isEdge, gp.GRB.GREATER_EQUAL,z[u,v],'d_y_z_%s_%s' % (u,v)) # # for z to be the incoming graph # for (u,v) in setGraphEdges: # if (u,v) in edges: # model.addConstr(z[u,v], gp.GRB.GREATER_EQUAL,1,'z_%s_%s_eq_1' % (u,v)) # lower bounds on w constraints for part in filter(lambda prt: prt.type in ["arc","grandParant"],partsManager.getAllParts()): allSubparts = part.getAllSubParts() allW = part.val for p in allSubparts: try: partType = p['type'] except KeyError: print allSubparts print p print part raise if partsManager.hasPart(partType,p): allW += partsManager.getPart(partType,p).val operator = gp.GRB.GREATER_EQUAL; if (allW < 0): operator = gp.GRB.LESS_EQUAL # print(self.g.graph.edges()) allExistingEdges = part.getAllExistingEdges() allExistingEdges = filter(lambda (u,v): partsManager.hasArc(u,v),allExistingEdges) allNonExistingEdges = part.getAllNonExistingEdges(self.g.n) allNonExistingEdges = filter(lambda (u,v): partsManager.hasArc(u,v),allNonExistingEdges) if (len(allExistingEdges) + len(allNonExistingEdges) > 0): # print "adding constr '" + str(part) + "', allExisting edges are:",allExistingEdges,", all non existing edges are:",allNonExistingEdges if allW < 0: model.addConstr(gp.quicksum(wplus[u,v] for (u,v) in allExistingEdges) \ # + gp.quicksum(wminus[u,v] for (u,v) in allNonExistingEdges)\ - slackVars[part],\ operator,allW,str(part)) elif applyPositiveSlacks: model.addConstr(gp.quicksum(wplus[u,v] for (u,v) in allExistingEdges) \ # + gp.quicksum(wminus[u,v] for (u,v) in allNonExistingEdges) \ + slackVars[part],\ operator,allW,str(part)) else: model.addConstr(gp.quicksum(wplus[u,v] for (u,v) in allExistingEdges) \ # + gp.quicksum(wminus[u,v] for (u,v) in allNonExistingEdges) \ ,operator,allW,str(part)) model.update() # define objective model.setObjective( # gp.quicksum(2*z[u,v]*(wplus[u,v] - wminus[u,v]) for (u,v) in edges) \ gp.quicksum(2*z[u,v]*wplus[u,v] for (u,v) in edges) \ - gp.quicksum(d[u,v]*alpha for (u,v) in edges) \ # - gp.quicksum((wplus[u,v] - wminus[u,v])*(wplus[u,v] - wminus[u,v]) for (u,v) in edges) \ - gp.quicksum(wplus[u,v]*wplus[u,v] for (u,v) in edges) \ - gp.quicksum(M*slackVars[part] for part in nonEdgeParts) \ - gp.quicksum(z[u,v]*z[u,v] for (u,v) in edges) \ ,gp.GRB.MAXIMIZE) # model.setObjective(- gp.quicksum(wplus[u,v]*wplus[u,v] for (u,v) in edges)\ # - gp.quicksum(M*slackVars[part] for part in nonEdgeParts),gp.GRB.MAXIMIZE) model.update() self.model = model self.LPVars = z self.edges = edges self.nodes = nodes self.wplus = wplus # self.wminus = wminus self.slack = slackVars
def PathBackupModelExample(plot_options,num_nodes,p,invstd,mip_gap,time_limit,cutoff): "" ####################################### # Generating graphs ####################################### #Generates a complete indirect graph H = nx.complete_graph(num_nodes) # transforms the indirect graph in directed one G = H.to_directed() #Generates a list with all links (edges) in the graph links = G.edges() #Generates a list with all nodes (vertex) in the graph nodes = G.nodes() capacity={} Aux = 1 for s,d in links: #generating capacity for each s,d link capacity[s,d] = Aux if capacity[s,d] > 0: G.add_weighted_edges_from([(s,d,capacity[s,d])]) else: G.add_weighted_edges_from([(s,d,capacity[s,d])]) if plot_options == 1: ############################################## # Plot Initial Graph ############################################## pos = plotGraph(G, option=None, position=None) ####################################### # Optimization Model ####################################### #Find all possible paths in the graph for all source -> destination pairs paths = getAllPaths(G,cutoff) #Find all possible paths for each source (s) -> destination (d) pair Psd = {} for s,d in links: Psd[s,d] = nx.all_simple_paths(G, s, d,cutoff) #Find all s->d paths that uses the i->j link Pij={} for i,j in links: for s,d in links: Pij[i,j,s,d] = getLinkPaths(G,i,j,s,d,cutoff) capacity={} mean={} std={} AuxCount = 0 Aux=1 for s,d in links: #generating capacity for each s,d link capacity[s,d] = Aux #Generate mean for each s,d link based on Binomial distribution mean[s,d] = Aux*p #Generate std for each s,d link based on Binomial distribution std[s,d]=math.sqrt(Aux*p*(1-(Aux*p))) AuxCount = AuxCount+1 #optimization links = tuplelist(links) # Creating a backup network model BackupNet = PathBackup(nodes,links,paths,Psd,Pij,capacity,mean,std,invstd) # Find a optimal solution solution = BackupNet.optimize(mip_gap,time_limit) #Remove links not chosen as backup link for i,j in links: if solution[i,j] < 0.1: G.remove_edge(i, j) ############################################## # Plot Solution ############################################## if plot_options == 1: option=1 plotGraph(G, option, pos)
def solve(self, objective, constraints, cached_data, warm_start, verbose, solver_opts): """Returns the result of the call to the solver. Parameters ---------- objective : LinOp The canonicalized objective. constraints : list The list of canonicalized cosntraints. cached_data : dict A map of solver name to cached problem data. warm_start : bool Not used. verbose : bool Should the solver print output? solver_opts : dict Additional arguments for the solver. Returns ------- tuple (status, optimal value, primal, equality dual, inequality dual) """ import gurobipy # Get problem data data = self.get_problem_data(objective, constraints, cached_data) c = data[s.C] b = data[s.B] A = dok_matrix(data[s.A]) # Save the dok_matrix. data[s.A] = A n = c.shape[0] solver_cache = cached_data[self.name()] # TODO warmstart with SOC constraints. if warm_start and solver_cache.prev_result is not None \ and len(data[s.DIMS][s.SOC_DIM]) == 0: model = solver_cache.prev_result["model"] variables = solver_cache.prev_result["variables"] gur_constrs = solver_cache.prev_result["gur_constrs"] c_prev = solver_cache.prev_result["c"] A_prev = solver_cache.prev_result["A"] b_prev = solver_cache.prev_result["b"] # If there is a parameter in the objective, it may have changed. if len(lu.get_expr_params(objective)) > 0: c_diff = c - c_prev I_unique = list(set(np.where(c_diff)[0])) for i in I_unique: variables[i].Obj = c[i] else: # Stay consistent with Gurobi's representation of the problem c = c_prev # Get equality and inequality constraints. sym_data = self.get_sym_data(objective, constraints, cached_data) all_constrs, _, _ = self.split_constr(sym_data.constr_map) # If there is a parameter in the constraints, # A or b may have changed. if self._param_in_constr(all_constrs): A_diff = dok_matrix(A - A_prev) b_diff = b - b_prev # Figure out which rows of A and elements of b have changed try: idxs, _ = zip(*[x for x in A_diff.keys()]) except ValueError: idxs = [] I_unique = list(set(idxs) | set(np.where(b_diff)[0])) nonzero_locs = gurobipy.tuplelist(A.keys()) # Update locations which have changed for i in I_unique: # Remove old constraint if it exists if gur_constrs[i] is not None: model.remove(gur_constrs[i]) gur_constrs[i] = None # Add new constraint if nonzero_locs.select(i, "*"): expr_list = [] for loc in nonzero_locs.select(i, "*"): expr_list.append((A[loc], variables[loc[1]])) expr = gurobipy.LinExpr(expr_list) if i < data[s.DIMS][s.EQ_DIM]: ctype = gurobipy.GRB.EQUAL elif data[s.DIMS][s.EQ_DIM] <= i \ < data[s.DIMS][s.EQ_DIM] + data[s.DIMS][s.LEQ_DIM]: ctype = gurobipy.GRB.LESS_EQUAL gur_constrs[i] = model.addConstr(expr, ctype, b[i]) model.update() else: # Stay consistent with Gurobi's representation of the problem A = A_prev b = b_prev else: model = gurobipy.Model() variables = [] for i in range(n): # Set variable type. if i in data[s.BOOL_IDX]: vtype = gurobipy.GRB.BINARY elif i in data[s.INT_IDX]: vtype = gurobipy.GRB.INTEGER else: vtype = gurobipy.GRB.CONTINUOUS variables.append( model.addVar( obj=c[i], name="x_%d" % i, vtype=vtype, # Gurobi's default LB is 0 (WHY???) lb=-gurobipy.GRB.INFINITY, ub=gurobipy.GRB.INFINITY) ) model.update() eq_constrs = self.add_model_lin_constr(model, variables, range(data[s.DIMS][s.EQ_DIM]), gurobipy.GRB.EQUAL, A, b) leq_start = data[s.DIMS][s.EQ_DIM] leq_end = data[s.DIMS][s.EQ_DIM] + data[s.DIMS][s.LEQ_DIM] ineq_constrs = self.add_model_lin_constr(model, variables, range(leq_start, leq_end), gurobipy.GRB.LESS_EQUAL, A, b) soc_start = leq_end soc_constrs = [] new_leq_constrs = [] for constr_len in data[s.DIMS][s.SOC_DIM]: soc_end = soc_start + constr_len soc_constr, new_leq, new_vars = self.add_model_soc_constr( model, variables, range(soc_start, soc_end), A, b ) soc_constrs.append(soc_constr) new_leq_constrs += new_leq variables += new_vars soc_start += constr_len gur_constrs = eq_constrs + ineq_constrs + \ soc_constrs + new_leq_constrs model.update() # Set verbosity and other parameters model.setParam("OutputFlag", verbose) # TODO user option to not compute duals. model.setParam("QCPDual", True) for key, value in solver_opts.items(): model.setParam(key, value) results_dict = {} try: model.optimize() results_dict["primal objective"] = model.ObjVal results_dict["x"] = np.array([v.X for v in variables]) # Only add duals if not a MIP. # Not sure why we need to negate the following, # but need to in order to be consistent with other solvers. if not self.is_mip(data): vals = [] for lc in gur_constrs: if lc is not None: if isinstance(lc, gurobipy.QConstr): vals.append(lc.QCPi) else: vals.append(lc.Pi) else: vals.append(0) results_dict["y"] = -np.array(vals) results_dict["status"] = self.STATUS_MAP.get(model.Status, s.SOLVER_ERROR) except gurobipy.GurobiError: results_dict["status"] = s.SOLVER_ERROR results_dict["model"] = model results_dict["variables"] = variables results_dict["gur_constrs"] = gur_constrs results_dict[s.SOLVE_TIME] = model.Runtime return self.format_results(results_dict, data, cached_data)
def LoadModel(self,Gamma,Nodes,Links,Capacity,Survivability,NumSamples,BackupCapacity, BackupLinks): """ Load model. Parameters ---------- Gamma : importance sampling vector """ self.Links = tuplelist(Links) self.Capacity = Capacity self.BackupCapacity = BackupCapacity self.BackupLinks = tuplelist(BackupLinks) # Create optimization model self.model = Model('Backup') SumBackupCapacity=0 SumFloorBackupCapacity=0 self.HatBackupCapacity={} for i,j in self.BackupLinks: self.BackupCapacity[i,j]=round(BackupCapacity[i,j],1) self.HatBackupCapacity[i,j]=math.floor(self.BackupCapacity[i,j]) SumBackupCapacity=SumBackupCapacity+BackupCapacity[i,j] SumFloorBackupCapacity=SumFloorBackupCapacity+self.HatBackupCapacity[i,j] self.BarDelta = math.ceil(SumBackupCapacity-SumFloorBackupCapacity) print('barDelta=%g'%self.BarDelta) # Create variables for i,j in self.BackupLinks: self.Delta[i,j] = self.model.addVar(vtype=GRB.INTEGER,lb=0, name='Delta[%s,%s]' % (i, j)) self.model.update() self.Theta = self.model.addVar(name='Theta') self.model.update() for i,j in self.BackupLinks: 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.BackupLinks: 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.BackupLinks: 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(self.Theta) self.model.update() #------------------------------------------------------------------------# # Constraints definition # # # # # #------------------------------------------------------------------------# # Buffer probability I for i,j in self.BackupLinks: self.model.addConstr(self.z0[i,j] + 1/(NumSamples*Survivability)*quicksum(self.z[k,i,j] for (k) in range(NumSamples)) <= self.Theta,'[CONST]Buffer_Prob_I[%s][%s]'%(i,j)) self.model.update() # Link capacity constraints for i,j in self.BackupLinks: 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.Delta[i,j] + self.HatBackupCapacity[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.Delta[i,j] + self.HatBackupCapacity[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.BackupLinks: 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,j in self.BackupLinks: self.model.addConstr(quicksum(self.Delta[i,j] for i,j in self.BackupLinks) <= self.BarDelta, '[CONST]Delta[%s][%s]' % (i,j)) 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.BackupLinks.select(i,'*')) - quicksum(self.bBackupLink[j,i,s,d] for j,i in self.BackupLinks.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.BackupLinks.select(i,'*')) - quicksum(self.bBackupLink[j,i,s,d] for j,i in self.BackupLinks.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.BackupLinks.select(i,'*')) - quicksum(self.bBackupLink[j,i,s,d] for j,i in self.BackupLinks.select('*',i)) == 0,'Flow3[%s,%s,%s]' % (i,s,d)) self.model.update()
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 solve(self, objective, constraints, cached_data, warm_start, verbose, solver_opts): """Returns the result of the call to the solver. Parameters ---------- objective : LinOp The canonicalized objective. constraints : list The list of canonicalized cosntraints. cached_data : dict A map of solver name to cached problem data. warm_start : bool Not used. verbose : bool Should the solver print output? solver_opts : dict Additional arguments for the solver. Returns ------- tuple (status, optimal value, primal, equality dual, inequality dual) """ import gurobipy # Get problem data data = self.get_problem_data(objective, constraints, cached_data) c = data[s.C] b = data[s.B] h = data[s.H] A = dok_matrix(data[s.A]) G = dok_matrix(data[s.G]) n = c.shape[0] solver_cache = cached_data[self.name()] if warm_start and solver_cache.prev_result is not None: model = solver_cache.prev_result["model"] variables = solver_cache.prev_result["variables"] eq_constrs = solver_cache.prev_result["eq_constrs"] ineq_constrs = solver_cache.prev_result["ineq_constrs"] c_prev = solver_cache.prev_result["c"] A_prev = solver_cache.prev_result["A"] b_prev = solver_cache.prev_result["b"] G_prev = solver_cache.prev_result["G"] h_prev = solver_cache.prev_result["h"] # If there is a parameter in the objective, it may have changed. if len(lu.get_expr_params(objective)) > 0: c_diff = c - c_prev I_unique = list(set(np.where(c_diff)[0])) for i in I_unique: variables[i].Obj = c[i] else: # Stay consistent with Gurobi's representation of the problem c = c_prev # Get equality and inequality constraints. sym_data = self.get_sym_data(objective, constraints, cached_data) eq_constr, ineq_constr, _ = self.split_constr(sym_data.constr_map) # If there is a parameter in the equality constraints, # A or b may have changed. if self.param_in_constr(eq_constr): A_diff = dok_matrix(A - A_prev) b_diff = b - b_prev # Figure out which rows of A and elements of b have changed try: I, _ = zip(*[x for x in A_diff.iterkeys()]) except ValueError: I = [] I_unique = list(set(I) | set(np.where(b_diff)[0])) A_nonzero_locs = gurobipy.tuplelist([x for x in A.iterkeys()]) # Update locations which have changed for i in I_unique: # Remove old constraint if it exists if eq_constrs[i] != None: model.remove(eq_constrs[i]) eq_constrs[i] = None # Add new constraint if len(A_nonzero_locs.select(i, "*")): expr_list = [] for loc in A_nonzero_locs.select(i, "*"): expr_list.append((A[loc], variables[loc[1]])) expr = gurobipy.LinExpr(expr_list) eq_constrs[i] = model.addConstr(expr, gurobipy.GRB.EQUAL, b[i]) model.update() else: # Stay consistent with Gurobi's representation of the problem A = A_prev b = b_prev # If there is a parameter in the inequality constraints, # G or h may have changed. if self.param_in_constr(ineq_constr): G_diff = dok_matrix(G - G_prev) h_diff = h - h_prev # Figure out which rows of G and elements of h have changed try: I, _ = zip(*[x for x in G_diff.iterkeys()]) except ValueError: I = [] I_unique = list(set(I) | set(np.where(h_diff)[0])) G_nonzero_locs = gurobipy.tuplelist([x for x in G.iterkeys()]) # Update locations which have changed for i in I_unique: # Remove old constraint if it exists if ineq_constrs[i] != None: model.remove(ineq_constrs[i]) ineq_constrs[i] = None # Add new constraint if len(G_nonzero_locs.select(i, "*")): expr_list = [] for loc in G_nonzero_locs.select(i, "*"): expr_list.append((G[loc], variables[loc[1]])) expr = gurobipy.LinExpr(expr_list) ineq_constrs[i] = model.addConstr(expr, gurobipy.GRB.LESS_EQUAL, h[i]) model.update() else: # Stay consistent with Gurobi's representation of the problem G = G_prev h = h_prev else: model = gurobipy.Model() variables = [ model.addVar( obj = c[i], name = "x_%d" % i, # Gurobi's default LB is 0 (WHY???) lb = -gurobipy.GRB.INFINITY, ub = gurobipy.GRB.INFINITY) for i in xrange(n)] model.update() eq_constrs = [None] * b.shape[0] if A.nnz > 0 or b.any: try: I, _ = zip(*[x for x in A.iterkeys()]) except ValueError: I = [] eq_constrs_nonzero_idxs = list(set(I) | set(np.where(b)[0])) A_nonzero_locs = gurobipy.tuplelist([x for x in A.iterkeys()]) for i in eq_constrs_nonzero_idxs: expr_list = [] for loc in A_nonzero_locs.select(i, "*"): expr_list.append((A[loc], variables[loc[1]])) expr = gurobipy.LinExpr(expr_list) eq_constrs[i] = model.addConstr(expr, gurobipy.GRB.EQUAL, b[i]) ineq_constrs = [None] * h.shape[0] if G.nnz > 0 or h.any: try: I, _ = zip(*[x for x in G.iterkeys()]) except ValueError: I = [] ineq_constrs_nonzero_idxs = list(set(I) | set(np.where(h)[0])) G_nonzero_locs = gurobipy.tuplelist([x for x in G.iterkeys()]) for i in ineq_constrs_nonzero_idxs: expr_list = [] for loc in G_nonzero_locs.select(i, "*"): expr_list.append((G[loc], variables[loc[1]])) expr = gurobipy.LinExpr(expr_list) ineq_constrs[i] = model.addConstr(expr, gurobipy.GRB.LESS_EQUAL, h[i]) model.update() # Set verbosity and other parameters if verbose: model.setParam("OutputFlag", True) else: model.setParam("OutputFlag", False) for key, value in solver_opts.items(): if key in self.CUSTOM_OPTS: continue model.setParam(key, value) try: model.optimize() results_dict = { "model": model, "variables": variables, "eq_constrs": eq_constrs, "ineq_constrs": ineq_constrs, "c": c, "A": A, "b": b, "G": G, "h": h, "status": self.STATUS_MAP.get(model.Status, "unknown"), "primal objective": model.ObjVal, "x": np.array([v.X for v in variables]), # Not sure why we need to negate the following, # but need to in order to be consistent with other solvers. "y": -np.array([lc.Pi if lc != None else 0 for lc in eq_constrs]), "z": -np.array([lc.Pi if lc != None else 0 for lc in ineq_constrs]), } except gurobipy.GurobiError: results_dict = { "status": s.SOLVER_ERROR } return self.format_results(results_dict, data[s.DIMS], data[s.OFFSET], cached_data)