Skip to content
Snippets Groups Projects
Commit 1b55a361 authored by msurl's avatar msurl
Browse files

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

parent f1dd6676
No related branches found
No related tags found
No related merge requests found
...@@ -11,7 +11,7 @@ from gurobipy import GRB ...@@ -11,7 +11,7 @@ from gurobipy import GRB
import datetime import datetime
import sys import sys
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
# import lp_to_nx_graph import lp_to_nx_graph
class DominatingSet: class DominatingSet:
...@@ -60,12 +60,20 @@ class KHopDominatingSet(DominatingSet): ...@@ -60,12 +60,20 @@ class KHopDominatingSet(DominatingSet):
class ConnectedKHopDominatingSet(KHopDominatingSet): class ConnectedKHopDominatingSet(KHopDominatingSet):
def __init__(self, G, k, name = "CkDS"): def __init__(self, G, k, name = "CkDS", exclude = {}):
self.G = G self.G = G
super().__init__(G, k, name) 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) 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): def min_ij_separator(G, i, j, C_i):
N_ci = {v for c in C_i for v in G.neighbors(c)} N_ci = {v for c in C_i for v in G.neighbors(c)}
G_prime = nx.Graph(G) G_prime = nx.Graph(G)
...@@ -77,17 +85,21 @@ class ConnectedKHopDominatingSet(KHopDominatingSet): ...@@ -77,17 +85,21 @@ class ConnectedKHopDominatingSet(KHopDominatingSet):
return R_j.intersection(N_ci) return R_j.intersection(N_ci)
def solve(self): 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): ds = {i for i,x_i in enumerate(self.m.getVars()) if x_i.x > 0.5}
iterations = 0 return ds
self.m.optimize()
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) G_prime_prime = model._G.subgraph(ds)
while(not nx.is_connected(G_prime_prime)) and iterations < maxIterations: if(not nx.is_connected(G_prime_prime)):
iterations+=1
C = [c for c in nx.algorithms.components.connected_components(G_prime_prime)] C = [c for c in nx.algorithms.components.connected_components(G_prime_prime)]
for i in range(len(C)-1): for i in range(len(C)-1):
C_i = C[i] C_i = C[i]
...@@ -95,46 +107,26 @@ class ConnectedKHopDominatingSet(KHopDominatingSet): ...@@ -95,46 +107,26 @@ class ConnectedKHopDominatingSet(KHopDominatingSet):
C_j = C[j] C_j = C[j]
h = next(iter(C_i)) h = next(iter(C_i))
l = next(iter(C_j)) l = next(iter(C_j))
min_ij_sep = ConnectedKHopDominatingSet.min_ij_separator(self.G, h, l, C_i) min_ij_sep = ConnectedKHopDominatingSet.min_ij_separator(model._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) model.cbLazy(gp.quicksum(model._vars[s] for s in min_ij_sep) >= model._vars[h] + model._vars[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)
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): class RootedConnectecKHopDominatingSet(ConnectedKHopDominatingSet):
def __init__(self, G, k, root = 0, name = "RCkDS"): 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.root = root
self.m.addConstr(self.nodes[root] >= 1) self.m.addConstr(self.nodes[root] >= 1)
# if __name__ == '__main__': if __name__ == '__main__':
# G = lp_to_nx_graph.read(sys.argv[1]) G = lp_to_nx_graph.read(sys.argv[1])
# if(len(sys.argv) > 2): if(len(sys.argv) > 2):
# k = int(sys.argv[2]) k = int(sys.argv[2])
# else: else:
# k = 1 k = 1
# if(len(sys.argv) > 3):
# maxIterations = int(sys.argv[3])
# else:
# maxIterations = float("inf")
# dsProb = RootedConnectecKHopDominatingSet(G, k, 0) dsProb = RootedConnectecKHopDominatingSet(G, k, 0)
# dsProb.solve_and_draw() dsProb.solve_and_draw()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment