diff --git a/python/conda package/k_hop_dominating_set_gurobi/k_hop_dominating_set_gurobi/k_hop_dom_set.py b/python/conda package/k_hop_dominating_set_gurobi/k_hop_dominating_set_gurobi/k_hop_dom_set.py index 761e53070bde89924d59348dbe64e04d73804210..48fde6e1fdcd552027460bddc217ee7bb8140f18 100755 --- a/python/conda package/k_hop_dominating_set_gurobi/k_hop_dominating_set_gurobi/k_hop_dom_set.py +++ b/python/conda package/k_hop_dominating_set_gurobi/k_hop_dominating_set_gurobi/k_hop_dom_set.py @@ -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,10 +60,18 @@ 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.addConstrs(self.nodes[v] <= gp.quicksum(self.nodes[w] for w in G.neighbors(v)) for v in G.nodes) + + + # 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): @@ -77,64 +85,48 @@ class ConnectedKHopDominatingSet(KHopDominatingSet): return R_j.intersection(N_ci) def solve(self): - return self.solve_iteratively(float("inf")) - - def solve_iteratively(self, maxIterations): - iterations = 0 - self.m.optimize() + self.m._vars = self.nodes + self.m._G = self.G + self.m.Params.lazyConstraints = 1 + self.m.optimize(RootedConnectecKHopDominatingSet.elim_unconnectivity) - ds = {i for i,x_i in enumerate(self.m.getVars()) if x_i.x == 1} - - G_prime_prime = self.G.subgraph(ds) - while(not nx.is_connected(G_prime_prime)) and iterations < maxIterations: - iterations+=1 - C = [c for c in nx.algorithms.components.connected_components(G_prime_prime)] - for i in range(len(C)-1): - C_i = C[i] - for j in range(i+1, len(C)): - 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) - - return ds, iterations + ds = {i for i,x_i in enumerate(self.m.getVars()) if x_i.x > 0.5} + return ds - 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() + 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 = 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] + for j in range(i+1, len(C)): + C_j = C[j] + h = next(iter(C_i)) + l = next(iter(C_j)) + 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) + 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()