Commit 1b55a361 by msurl

### added callback function for gurobi to lazily add connectivity constraints and refactored code

parent f1dd6676
 ... ... @@ -11,7 +11,7 @@ from gurobipy import GRB import datetime import sys import matplotlib.pyplot as plt # import lp_to_nx_graph import lp_to_nx_graph class DominatingSet: ... ... @@ -60,12 +60,20 @@ class KHopDominatingSet(DominatingSet): class ConnectedKHopDominatingSet(KHopDominatingSet): def __init__(self, G, k, name = "CkDS"): def __init__(self, G, k, name = "CkDS", exclude = {}): self.G = G super().__init__(G, k, name) # self.m.addConstr(gp.quicksum(gp.quicksum(self.nodes[w] for w in G.neighbors(v)) -2*self.nodes[v] for v in G.nodes) >= -2) if exclude: self.m.addConstrs(self.nodes[v] <= gp.quicksum(self.nodes[w] for w in G.neighbors(v)) for v in G.nodes if v not in exclude) else: self.m.addConstrs(self.nodes[v] <= gp.quicksum(self.nodes[w] for w in G.neighbors(v)) for v in G.nodes) def min_ij_separator(G, i, j, C_i): N_ci = {v for c in C_i for v in G.neighbors(c)} G_prime = nx.Graph(G) ... ... @@ -77,17 +85,21 @@ class ConnectedKHopDominatingSet(KHopDominatingSet): return R_j.intersection(N_ci) def solve(self): return self.solve_iteratively(float("inf")) self.m._vars = self.nodes self.m._G = self.G self.m.Params.lazyConstraints = 1 self.m.optimize(RootedConnectecKHopDominatingSet.elim_unconnectivity) def solve_iteratively(self, maxIterations): iterations = 0 self.m.optimize() ds = {i for i,x_i in enumerate(self.m.getVars()) if x_i.x > 0.5} return ds ds = {i for i,x_i in enumerate(self.m.getVars()) if x_i.x == 1} def elim_unconnectivity(model, where): if where == GRB.Callback.MIPSOL: vals = model.cbGetSolution(model._vars) ds = {i for i in model._vars.keys() if vals[i] > 0.5} G_prime_prime = self.G.subgraph(ds) while(not nx.is_connected(G_prime_prime)) and iterations < maxIterations: iterations+=1 G_prime_prime = model._G.subgraph(ds) if(not nx.is_connected(G_prime_prime)): C = [c for c in nx.algorithms.components.connected_components(G_prime_prime)] for i in range(len(C)-1): C_i = C[i] ... ... @@ -95,46 +107,26 @@ class ConnectedKHopDominatingSet(KHopDominatingSet): C_j = C[j] h = next(iter(C_i)) l = next(iter(C_j)) min_ij_sep = ConnectedKHopDominatingSet.min_ij_separator(self.G, h, l, C_i) self.m.addConstr(gp.quicksum(self.nodes[s] for s in min_ij_sep) >= self.nodes[h] + self.nodes[l] - 1) self.m.optimize() ds = {i for i,x_i in enumerate(self.m.getVars()) if x_i.x == 1} G_prime_prime = self.G.subgraph(ds) min_ij_sep = ConnectedKHopDominatingSet.min_ij_separator(model._G, h, l, C_i) model.cbLazy(gp.quicksum(model._vars[s] for s in min_ij_sep) >= model._vars[h] + model._vars[l] - 1) return ds, iterations def solve_and_draw(self, iterations = float("inf")): starttime = datetime.datetime.now() ds, iterations = self.solve_iteratively(iterations) endtime = datetime.datetime.now() duration = endtime- starttime duration_sec = duration.total_seconds() color_map = ['red' if i in ds else 'green' for i in self.G.nodes] print(f"iterations: {iterations}, duration in seconds: {duration_sec}") nx.draw_kamada_kawai(self.G, node_color = color_map, with_labels = True) plt.show() class RootedConnectecKHopDominatingSet(ConnectedKHopDominatingSet): def __init__(self, G, k, root = 0, name = "RCkDS"): super().__init__(G, k, name) super().__init__(G, k, name, exclude = {root}) self.root = root self.m.addConstr(self.nodes[root] >= 1) # if __name__ == '__main__': # G = lp_to_nx_graph.read(sys.argv[1]) if __name__ == '__main__': G = lp_to_nx_graph.read(sys.argv[1]) # if(len(sys.argv) > 2): # k = int(sys.argv[2]) # else: # k = 1 # if(len(sys.argv) > 3): # maxIterations = int(sys.argv[3]) # else: # maxIterations = float("inf") if(len(sys.argv) > 2): k = int(sys.argv[2]) else: k = 1 # dsProb = RootedConnectecKHopDominatingSet(G, k, 0) # dsProb.solve_and_draw() dsProb = RootedConnectecKHopDominatingSet(G, k, 0) dsProb.solve_and_draw()
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!