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 new file mode 100755 index 0000000000000000000000000000000000000000..761e53070bde89924d59348dbe64e04d73804210 --- /dev/null +++ b/python/conda package/k_hop_dominating_set_gurobi/k_hop_dominating_set_gurobi/k_hop_dom_set.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Mon May 18 18:44:09 2020 + +@author: mario +""" +import networkx as nx +import gurobipy as gp +from gurobipy import GRB +import datetime +import sys +import matplotlib.pyplot as plt +# import lp_to_nx_graph + + +class DominatingSet: + + def __init__(self, G, name = "DS"): + self.G = G + self.m = gp.Model(name) + self.nodes = self.m.addVars(G.nodes, vtype = GRB.BINARY, name = "nodes") + self.m.setObjective(gp.quicksum(self.nodes), GRB.MINIMIZE) + + # For each node in the graph the node itself or at least one of it's neighbors has to be part of the dominating set + self.m.addConstrs(((gp.quicksum(self.nodes[n] for n in G.neighbors(v)) + self.nodes[v] )>= 1) for v in G.nodes) + + def solve(self): + ds = {i for i,x_i in enumerate(self.m.getVars()) if x_i.x == 1} + return ds + + def solve_and_draw(self): + starttime = datetime.datetime.now() + ds = self.solve() + 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"duration in seconds: {duration_sec}") + nx.draw_kamada_kawai(self.G, node_color = color_map, with_labels = True) + plt.show() + + +class KHopDominatingSet(DominatingSet): + + def __init__(self, G, k, name = "kDS"): + super().__init__(KHopDominatingSet.make_closure(G,k), name) + self.G = G + + def make_closure(G, k): + G_prime = nx.Graph(G) + for v in G.nodes: + neighbors = set(G.neighbors(v)) + for i in range(k-1): + neighbors.update([w for n in neighbors for w in G.neighbors(n)]) + + G_prime.add_edges_from((v,n) for n in neighbors) + + return G_prime + +class ConnectedKHopDominatingSet(KHopDominatingSet): + + def __init__(self, G, k, name = "CkDS"): + 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) + + + 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) + C_i_prime = C_i.copy() + C_i_prime.update(N_ci) + G_prime.remove_edges_from(G.subgraph(C_i_prime).edges) + # dijkstra + R_j = nx.algorithms.dag.descendants(G_prime, j) + 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() + + 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 + + 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) + self.root = root + + self.m.addConstr(self.nodes[root] >= 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") + +# dsProb = RootedConnectecKHopDominatingSet(G, k, 0) +# dsProb.solve_and_draw() diff --git a/python/conda package/k_hop_dominating_set_gurobi/k_hop_dominating_set_gurobi/lp_to_nx_graph.py b/python/conda package/k_hop_dominating_set_gurobi/k_hop_dominating_set_gurobi/lp_to_nx_graph.py new file mode 100755 index 0000000000000000000000000000000000000000..38e12436fc25cb7c9ea393507fca9dece708ce21 --- /dev/null +++ b/python/conda package/k_hop_dominating_set_gurobi/k_hop_dominating_set_gurobi/lp_to_nx_graph.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Wed May 13 17:03:41 2020 + +@author: mario +""" + +import networkx as nx +import re + +# def lp_to_nx_graph(strInput): +# nodePattern = re.compile(r'node\([0-9]+\.\.[0-9]+\)\.') +# print(nodePattern.findall("node(0..195).")) + + +# lp_to_nx_graph("") + + +def cleanLP(lpSTR): + lpSTR = lpSTR.replace(" ", "") + lpSTR = lpSTR.replace("\t", "") + newLPList = [] + for line in lpSTR.split("\n"): + toAdd = line + if "%" in line: + toAdd = line[:line.index("%")] + if toAdd != "": + newLPList.append(toAdd) + return newLPList + +def lpStrToGraphNX(lpSTR): + lpList = cleanLP(lpSTR) + graph = nx.empty_graph(0) + for part in lpList: + if ".." in part and "node" in part: + startrange = int(part[5:part.index("..")]) + endrange = int(part[part.index("..")+2:part.index(").")]) + graph.add_nodes_from(range(startrange, endrange)) + elif "." in part and ".." not in part: + for i in part.split("."): + if "node(" in i: + graph.add_node(int(i[5:-1])) + elif "edge(" in i: + first = int(i[5:i.index(",")]) + second = int(i[i.index(",")+1:-1]) + graph.add_edge(first, second) + if(first == 13 or first == 9): + if(second == 13 or second == 9): + print("Hello") + return graph + +def read(filenameRaw): + fileIn = open(filenameRaw,'r') + graph = lpStrToGraphNX(fileIn.read()) + return graph \ No newline at end of file