diff --git a/python/raw code/connected_k_dominating_set.py b/python/raw code/connected_k_dominating_set.py new file mode 100755 index 0000000000000000000000000000000000000000..6cf5356bd71ef4db35328275912af9d2fec949d9 --- /dev/null +++ b/python/raw code/connected_k_dominating_set.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Sat May 9 23:55:40 2020 + +@author: mario +""" + +import k_transitive_closure +import k_dominating_set +import networkx as nx +import matplotlib.pyplot as plt +import gurobipy as gp +from gurobipy import GRB + +def solve(G, k): + m, nodes = model(G, k, "MINkCDS") + add_constraints(G, k, m) +# + return solve_iteratively(G, k, m, 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 model(G, k, name): + m, nodes = k_dominating_set.model(G,k,name) + add_constraints(G, m, nodes) + return m, nodes + +def add_base_connectivity_constraint(G, m, nodes): + m.addConstrs(nodes[v] <= gp.quicksum(nodes[w] for w in G.neighbors(v)) for v in G.nodes) + +def add_constraints(G, m, nodes): + add_base_connectivity_constraint(G, m, nodes) + +def solve_iteratively(G, k, m, nodes, maxIterations): + iterations = 0 + m.optimize() + + ds = {i for i,x_i in enumerate(m.getVars()) if x_i.x == 1} + + G_prime_prime = 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 = min_ij_separator(G, h, l, C_i) + m.addConstr(gp.quicksum(nodes[s] for s in min_ij_sep) >= nodes[h] + nodes[l] - 1) + + m.optimize() + ds = {i for i,x_i in enumerate(m.getVars()) if x_i.x == 1} + G_prime_prime = G.subgraph(ds) + + return ds, iterations \ No newline at end of file diff --git a/python/raw code/dominating_set.py b/python/raw code/dominating_set.py new file mode 100755 index 0000000000000000000000000000000000000000..e34df5b67d69513135caeacba71438d3fba886b9 --- /dev/null +++ b/python/raw code/dominating_set.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Sat May 9 23:53:13 2020 + +@author: mario +""" +import networkx as nx +import gurobipy as gp +from gurobipy import GRB + + +def add_constraints(G, m, nodes): + m.addConstrs(((gp.quicksum(nodes[n] for n in G.neighbors(v)) + nodes[v] )>= 1) for v in G.nodes) + + +def model(G, name): + m = gp.Model(name) + + nodes = m.addVars(G.nodes, vtype = GRB.BINARY, name = "nodes") + + m.setObjective(gp.quicksum(nodes), GRB.MINIMIZE) + + add_constraints(G,m,nodes) + + return m, nodes + +def solve(G): + m, nodes = model(G,'DS') + m.optimize() + # ds = {v for j,x_j in enumerate(m.getVars()) for i,v in enumerate(G.nodes) if j == i} + ds = {i for i,x_i in enumerate(m.getVars()) if x_i.x == 1} + return ds \ No newline at end of file diff --git a/python/raw code/k_dominating_set.py b/python/raw code/k_dominating_set.py new file mode 100755 index 0000000000000000000000000000000000000000..ad1f7b2a17bdbb757918aabb0c8123dcfb72577a --- /dev/null +++ b/python/raw code/k_dominating_set.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Sat May 9 23:55:30 2020 + +@author: mario +""" +import dominating_set +import k_transitive_closure +import networkx as nx + +def solve(G,k): + G_prime = k_transitive_closure.make_closure(G,k) + dominating_set.solve(G_prime) + +def model(G, k, name): + G_prime = k_transitive_closure.make_closure(G,k) + return dominating_set.model(G_prime, name) \ No newline at end of file diff --git a/python/raw code/k_transitive_closure.py b/python/raw code/k_transitive_closure.py new file mode 100755 index 0000000000000000000000000000000000000000..a0b9179b1021c5dcd618b84dd511d53ac1903c04 --- /dev/null +++ b/python/raw code/k_transitive_closure.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Sat May 9 19:00:59 2020 + +@author: mario +""" + +import networkx as nx +import matplotlib.pyplot as plt + +# G is supposed to be a undirected networx.Graph +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 + + +if __name__ == '__main__': + G = nx.Graph() + G.add_nodes_from(range(10)) + G.add_edges_from((i,i+1) for i in range(9)) + + G_prime = make_closure(G,10) + nx.draw(G_prime) + plt.show() diff --git a/python/raw code/lp_to_nx_graph.py b/python/raw code/lp_to_nx_graph.py new file mode 100755 index 0000000000000000000000000000000000000000..38e12436fc25cb7c9ea393507fca9dece708ce21 --- /dev/null +++ b/python/raw code/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 diff --git a/python/raw code/rooted_connected_k_dominating_set.py b/python/raw code/rooted_connected_k_dominating_set.py new file mode 100755 index 0000000000000000000000000000000000000000..82f5a06dc8e531e355ef7100c51541d3cc9b339f --- /dev/null +++ b/python/raw code/rooted_connected_k_dominating_set.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Sat May 9 23:55:59 2020 + +@author: mario +""" + +import connected_k_dominating_set +import lp_to_nx_graph +import networkx as nx +import matplotlib.pyplot as plt +import gurobipy as gp +import sys +import datetime + + +def add_constraints(G, m, nodes, root): + m.addConstr(nodes[root] >= 1) + +def add_path_constraints(G, m, nodes, root): + m.addConstrs((nodes[v] * len(nx.algorithms.shortest_path(G, root, v))) <= gp.quicksum(nodes) for v in G.nodes) + +def add_path_constraints2(G, m, nodes): + m.addConstrs((nodes[v] * nodes[w] * len(nx.algorithms.shortest_path(G, v, w))) <= gp.quicksum(nodes) for v in G.nodes for w in G.nodes) + +def add_path_constraints3(G, m, nodes, root): + m.addConstr(gp.quicksum(nodes[v] * len(nx.algorithms.shortest_path(G, root, v)) for v in G.nodes) <= (gp.quicksum(nodes)+1)*gp.quicksum(nodes)/2) + +def add_path_constraints4(G, m, nodes): + m.addConstr(gp.quicksum(nodes[v] * nodes[w] * len(nx.algorithms.shortest_path(G, v, w)) for v in G.nodes for w in G.nodes) <= (gp.quicksum(nodes)+1)*gp.quicksum(nodes)/2) + +def add_vertex_separator_degree_constraints(G, m, nodes): + for i in G.nodes: + if(G.degree[i] < 6): + for j in G.nodes: + if i != j and j not in G.neighbors(i): + min_ij_sep = connected_k_dominating_set.min_ij_separator(G, i, j, {i}) + m.addConstr(gp.quicksum(nodes[s] for s in min_ij_sep) >= nodes[i] + nodes[j] - 1) + +def add_all_vertex_separator_constraaints(G, m, nodes): + for i in G.nodes: + for j in G.nodes: + if i != j and j not in G.neighbors(i): + min_ij_sep = connected_k_dominating_set.min_ij_separator(G, i, j, {i}) + m.addConstr(gp.quicksum(nodes[s] for s in min_ij_sep) >= nodes[i] + nodes[j] - 1) + + +def model(G, k, root): + m, nodes = connected_k_dominating_set.model(G, k, "MINkRCDS") + add_constraints(G, m, nodes, root) + # add_path_constraints(G, m, nodes, root) + # add_path_constraints2(G, m, nodes) + # add_path_constraints3(G, m, nodes, root) + # add_path_constraints4(G, m, nodes) + # add_vertex_separator_degree_constraints(G, m, nodes) + # add_all_vertex_separator_constraaints(G, m, nodes) + return m, nodes + +def solve(G, k, root, maxIterations): + m, nodes = model(G, k, root) + return connected_k_dominating_set.solve_iteratively(G, k, m, nodes, maxIterations) + +if __name__ == '__main__': + # G = nx.Graph() + # G.add_nodes_from(range(16)) + # G.add_edges_from([(0,1), (0,2), (1,2), (1,3), (1,4), (1,7), (2,4), (2,5), (2,8), (3,6), (3,7), (3,4), (3,10), (4,7), (4,8), (4, 5), (4,11), (5,8), (5,9), (5,12), + # (6,7), (6,10), (7,8), (7,10), (7,13), (7,11), (8,9), (8,11), (8,12), (8,14), (10,11), (10,13), (11,13), (11,14), (11,12), (13,14), (13,15), (14,15)]) + + # G.add_edges_from([(0,1), (0,2), (1,3), (1,4), (2,4), (2,5), (3,6), (3,7), (4,7), (4,8), (5,8), (5,9), + # (6,10), (7,10), (7,11), (8,11), (8,12), (9,12), (10,13), (11,13), (11,14), (12,14), (13,15), (14,15)]) + + # maxIterations = float("inf") + # maxIterations = 5 + + 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") + + starttime = datetime.datetime.now() + ds, iterations = solve(G, k, 0, maxIterations) + endtime = datetime.datetime.now() + duration = endtime- starttime + duration_sec = duration.total_seconds() + print(f"iterations: {iterations}, duration(s): {duration_sec}") + color_map = ['red' if i in ds else 'green' for i in G.nodes] + nx.draw(G, node_color = color_map) + plt.show() \ No newline at end of file