def grow_dom_set_solver(G): """ Generates a dominating set by adding vertices with small median distance to all other vertices """ n = len(G.nodes()) if n < 10: return dijkstra_solve(G) dist = [[0 for i in range(n)] for i in range(n)] all_paths_iter = nx.all_pairs_dijkstra(G) for u, (distance, path) in all_paths_iter: for v in distance: dist[u][v] = distance[v] median_dist = [median(dist[v]) for v in range(n)] #current sub vertices sub_nodes = set(G.nodes()) #queue for vertices, sorted in ascending order I guess Q = sorted(range(n), key=lambda v: median_dist[v]) while len(Q) > 0: v = Q.pop() sub_nodes.remove(v) if not nx.is_dominating_set(G, sub_nodes): sub_nodes.add(v) assert nx.is_dominating_set(G, sub_nodes) if len(sub_nodes) == 1: T = nx.Graph() T.add_nodes_from(sub_nodes) return T else: return dijkstra_solve(G, sub_nodes, sub_nodes)
def test_wikipedia_is_dominating_set(): """Example from https://en.wikipedia.org/wiki/Dominating_set""" G = nx.cycle_graph(4) G.add_edges_from([(0, 4), (1, 4), (2, 5)]) assert nx.is_dominating_set(G, {4, 3, 5}) assert nx.is_dominating_set(G, {0, 2}) assert nx.is_dominating_set(G, {1, 2})
def test_is_dominating_set(): G = nx.path_graph(4) d = {1, 3} assert nx.is_dominating_set(G, d) d = {0, 2} assert nx.is_dominating_set(G, d) d = {1} assert not nx.is_dominating_set(G, d)
def test_wikipedia_is_dominating_set(): """Example from http://en.wikipedia.org/wiki/Dominating_set """ G = nx.cycle_graph(4) G.add_edges_from([(0, 4), (1, 4), (2, 5)]) assert_true(nx.is_dominating_set(G, set([4, 3, 5]))) assert_true(nx.is_dominating_set(G, set([0, 2]))) assert_true(nx.is_dominating_set(G, set([1, 2])))
def test_is_dominating_set(): G = nx.path_graph(4) d = set([1, 3]) assert nx.is_dominating_set(G, d) d = set([0, 2]) assert nx.is_dominating_set(G, d) d = set([1]) assert not nx.is_dominating_set(G, d)
def test_wikipedia_is_dominating_set(): """Example from http://en.wikipedia.org/wiki/Dominating_set """ G = nx.cycle_graph(4) G.add_edges_from([(0, 4), (1, 4), (2,5)]) assert_true(nx.is_dominating_set(G, set([4, 3, 5]))) assert_true(nx.is_dominating_set(G, set([0, 2]))) assert_true(nx.is_dominating_set(G, set([1, 2])))
def test_is_dominating_set(): G = nx.path_graph(4) d = set([1, 3]) assert_true(nx.is_dominating_set(G, d)) d = set([0, 2]) assert_true(nx.is_dominating_set(G, d)) d = set([1]) assert_false(nx.is_dominating_set(G, d))
def solve(G): T = findSpanningTreeDFS(G) # T = nx.minimum_spanning_tree(G) while True: node_degree = T.degree(list(T.nodes())) leaves = [] for node in node_degree: if node[1] == 1: edge = list(G.edges(node[0]))[0] leaves.append((node[0], G.get_edge_data(edge[0], edge[1])['weight'])) # leaves = Sort_Tuple(leaves, 1) random.shuffle(leaves) score = average_pairwise_distance(T) all_worse = True while len(leaves) > 0: leaf = leaves.pop()[0] if T.degree(leaf) == 1: newT = T.copy() newT.remove_node(leaf) newScore = average_pairwise_distance(newT) if newScore < score and nx.is_dominating_set(G, newT.nodes()): all_worse = False score = newScore T = newT if all_worse: break return T
def cost_of_solution(G, closed_walk, conquered_set): cost = 0 message = '' if not is_valid_walk(G, closed_walk): message += 'This is not a valid walk for the given graph\n' cost = 'infinite' if not closed_walk[0] == closed_walk[-1]: message += 'The start and end vertices are not the same\n' cost = 'infinite' if not nx.is_dominating_set(G, conquered_set): message += 'It is not true that every kingdom is either conquered, or adjacent to a conquered kingdom\n' cost = 'infinite' if cost != 'infinite': if len(closed_walk) == 1: closed_walk_edges = [] else: closed_walk_edges = get_edges_from_path( closed_walk[:-1]) + [(closed_walk[-2], closed_walk[-1])] conquering_cost = sum([G.nodes[v]['weight'] for v in conquered_set]) travelling_cost = sum( [G.edges[e]['weight'] for e in closed_walk_edges]) cost = conquering_cost + travelling_cost message += f'The conquering cost of your solution is {conquering_cost}\n' message += f'The travelling cost of your solution is {travelling_cost}\n' message += f'The total cost of your solution is {cost}' return cost, message
def solve(G, T=None, cost=float('inf'), multiplier=1): """ Args: G: networkx.Graph T: the best known dominating-set tree. None if unknown cost: the cost of the best known T Returns: T: networkx.Graph """ tries, max_tries = 0, int(multiplier * len(list(G.nodes))) while tries < max_tries: if cost == 0: break nodes = list(G.nodes) random.shuffle(nodes) i = 0 while not nx.is_dominating_set(G, nodes[:i]) or not nx.is_connected( G.subgraph(nodes[:i])): i += 1 new_T, new_cost = min( (pick_leaves(G, t, utils.average_pairwise_distance_fast(t)) for t in gen_candidates(G, nodes[:i])), key=lambda p: p[1]) if new_cost < cost: T, cost = new_T, new_cost tries = 0 else: tries += 1 return T, cost
def test_dominating_set(self): input = networkx.generators.cycle_graph(10) output = graph.dominating_set(input, 4) self.assertEqual(len(output), 4) self.assertTrue(networkx.is_dominating_set(input, output)) output = graph.dominating_set(input, 3) self.assertIsNone(output)
def remove(copy, G_copy, k): nonlocal min_dist nonlocal minT has_valid = False count = 0 for c in itertools.combinations(G_copy.edges(), k): temp = copy.copy() if count >= 10000: return solve(G) count += 1 for e in c: u, v = e[0], e[1] if copy.degree(u) == 1: copy.remove_node(u) elif copy.degree(v) == 1: copy.remove_node(v) else: copy.remove_edge(u, v) if is_valid_network(G, copy): has_valid = True if average_pairwise_distance_fast(copy) < min_dist: min_dist = average_pairwise_distance_fast(copy) minT = copy.copy() elif nx.is_dominating_set(G, copy.nodes()) and nx.is_connected(copy): has_valid = True copy = temp if not has_valid: return remove(copy, G_copy, k+1)
def small_graph_bruteforce_recursive(G, currG, costPQ): T = copy.deepcopy(currG) #for all edges in the current graph for e in T.edges: #BASE CASE: continue or don't continue if nx.is_connected(currG) and nx.is_dominating_set(G, currG): if nx.is_tree(currG): heappush( costPQ, (average_pairwise_distance_fast(currG), currG)) #records print(costPQ[0]) else: #the current graph is not connected or dominating return e0 = e[0] e1 = e[1] w = G.get_edge_data(e0, e1)['weight'] #remove then recursive currG.remove_edge(e[0], e[1]) if currG.degree(e[1]) == 0: currG.remove_node(e[1]) if currG.degree(e[0]) == 0: currG.remove_node(e[0]) small_graph_bruteforce_recursive(G, currG, costPQ) #recursive call #re-add what I just removed if e0 not in currG.nodes: currG.add_node(e0) if e1 not in currG.nodes: currG.add_node(e1) currG.add_edge(e0, e1, weight=w)
def prune(T, G, leaves): score = score = average_pairwise_distance_fast(T) while leaves: l = leaves.popleft() parent = list(T.neighbors(l))[0] edge_weight = T.get_edge_data(parent, l)['weight'] T.remove_node(l) if nx.is_dominating_set(G, T.nodes): new_score = average_pairwise_distance_fast(T) p = np.random.random() if new_score > score and p < 0.5: T.add_node(l) T.add_edge(l, parent, weight=edge_weight) else: score = new_score #append new leaves if T.degree(parent) == 1: leaves.append(parent) else: T.add_node(l) T.add_edge(l, parent, weight=edge_weight) #print('hello') #print(nx.is_tree(T)) return T
def prune_leaves(leaves, min_tree, G): removed = 0 kept_leaves = [] for leaf in leaves: if (leaf): e = list(min_tree.edges(leaf, data='weight'))[0] #print("leaf: " + str(leaf)) #print("leaf edge: " + str(e)) #cost = average_pairwise_distance_fast(min_tree) min_tree.remove_node(leaf) #new_cost = average_pairwise_distance_fast(min_tree) # if (new_cost > cost): # IMPLEMENT DP HERE? # choose between keeping node and removing it # like choose min_cost(keeping_node, removing_node) # idk how to implement tho if (not nx.is_dominating_set(G, min_tree.nodes)): min_tree.add_node(leaf) min_tree.add_edge(e[0], e[1], weight=e[2]) #print("Leaf kept") kept_leaves.append(leaf) else: removed += 1 #if (removed): #print("(Removal) We removed " + str(removed) + " leaves in this iter") return min_tree, kept_leaves, removed
def tree_operation(G, M): """ Takes in a tree and compares the optimal way to trim or untrim the leaf nodes for a lower average pairwise distance. Returns the trimmed tree. """ nodes = list(M.nodes()) if len(nodes) == 1: return M elif len(nodes) == 2: return M.subgraph(nodes[0]) # stores the leaf node and its edge weight N = M.copy() dict = {} for node in nodes: if M.degree(node) == 1: a = list(M.edges(node)) dict[node] = a[0] for n in dict: N.remove_node(n) assert nx.is_dominating_set(G, N.nodes()) shortest = average_pairwise_distance_fast(N) for n in dict: N.add_node(n) u = dict[n][0] v = dict[n][1] N.add_edge(u, v, weight=M[v][u]["weight"]) newDist = average_pairwise_distance_fast(N) if newDist < shortest: shortest = newDist else: N.remove_node(n) return M.subgraph(N.nodes())
def solve2(G): """ Args: G: networkx.Graph Returns: T: networkx.Graph """ pq = [] #min heap for Kruskals edge popping for e in G.edges: heappush(pq, (-G.edges[e]['weight'], e)) T = copy.deepcopy(G) costpq = [] #min heap with minimal pairwise distance with its tree while pq: if (T.number_of_nodes() == 2): break node = heappop(pq) e = node[1] # print(e) w = node[0] * -1 T.remove_edge(e[0], e[1]) if T.degree(e[1]) == 0: T.remove_node(e[1]) if T.degree(e[0]) == 0: T.remove_node(e[0]) if nx.is_connected(T) and nx.is_dominating_set(G, T): if nx.is_tree(T): heappush(costpq, (average_pairwise_distance_fast(T), T)) # cost = average_pairwise_distance_fast(T) else: T.add_edge(e[0], e[1], weight=w) return heappop(costpq)[1]
def sample_candidate(sample, G): num_nodes = G.number_of_nodes() node_in = list(sample.nodes()) done = False tried = num_nodes node_tried = list(G.nodes()) while not done: F = sample.copy() switch_try = np.random.randint(0, tried) tried = tried - 1 switch = node_tried[switch_try] node_tried.remove(switch) if switch in node_in: F.remove_node(switch) else: F.add_node(switch) for neighbor in nx.all_neighbors(G, switch): if neighbor in node_in: F.add_edge(switch, neighbor, weight=G[switch][neighbor]['weight']) if nx.is_dominating_set(G, F.nodes()) and nx.is_connected(F): done = True return F
def pre_trimming(G): """ Returns a dominating set greedily pruned by removing vertices with high median distance to other vertices. Updates distances as vertices are pruned so you only need the max each time rather than succesive mins. """ dist = {v: {} for v in G.nodes()} all_paths_iter = nx.all_pairs_dijkstra(G) for u, (distance, path) in all_paths_iter: for v in distance: dist[u][v] = distance[v] #current sub vertices sub_nodes = set(G.nodes()) median_dist = {v: median(dist[v].values) for v in sub_nodes} #Only to track remaining attempts Q = list(G.nodes()) while len(Q) > 0: x = max(Q, key=lambda v: median_dist[v]) Q.remove(x) sub_nodes.remove(x) if not nx.is_dominating_set(G, sub_nodes): sub_nodes.add(x) else: dist.pop(x) for v in dist: dist[v].pop(x) median_dist = {v: median(dist[v]) for v in sub_nodes} return sub_nodes
def greedy_sub_ds_fn(G): ds = set(G.nodes()) prio = seq(G.nodes()).order_by(value_fn(G)).to_list() for node in prio: ds.remove(node) if not nx.is_dominating_set(G, ds): ds.add(node) return ds
def random_conquer(G): kingdoms = [i for i in range(nx.number_of_nodes(G))] conquered_set = [] while not nx.is_dominating_set(G, conquered_set): conquering = random.choice(kingdoms) kingdoms.remove(conquering) conquered_set.append(conquering) return conquered_set
def build_tree(G, L, NodeLevel, l_max, n): """ Args: G: networkx.Graph L: dictionary mapping levels to a list of the nodes in them NodeLevel: dictionary mapping nodes in G to their level l_max: the level of the core node(s) n: dictionary mapping edges to the number of pairs (u, v) for which the edge is used in the shortest path between u and v in some shortest path tree T, summed over all T Returns: MRCT: networkx.Graph - spanning tree of G created by greedily adding edges with maximal n values to the core node """ T = nx.Graph() deg = {} flag = 0 for k in G.nodes: deg[k] = sum([n.get((k, j), 0) for j in G.nodes]) core = [k for k in G.nodes if NodeLevel[k] == l_max] if len(core) == 1: T.add_node(core[0]) else: T.add_node(max(core, key=lambda x: deg[x])) l = l_max unconnected = [] for l in range(l_max, 0, -1): j = 0 while j < len(unconnected): k = unconnected[j] #i = max(T, key = lambda x : weight_heuristic(x, k, n, G)) V = list(T.nodes) i = min(V, key=lambda x: test_edge(T, G, x, k)) if (i, k) not in G.edges: pass else: T.add_node(k) T.add_weighted_edges_from([(i, j, G[i][k]['weight'])]) unconnected.remove(k) j += 1 for k in L[l]: if k in T: pass else: #i = max(T, key = lambda x : weight_heuristic(x, k, n, G)) V = list(T.nodes) i = min(V, key=lambda x: test_edge(T, G, x, k)) if (i, k) not in G.edges: unconnected.append(k) else: T.add_node(k) T.add_weighted_edges_from([(i, k, G[i][k]['weight'])]) if nx.is_dominating_set(G, T): flag = 1 break if flag == 1: break return T, L, NodeLevel, l_max
def greedy_sub_cds_fn(G): cds = set(G.nodes()) prio = seq(G.nodes()).order_by(value_fn(G)).to_list() for node in prio: cds.remove(node) if not nx.is_dominating_set(G, cds) or \ not g_utils.is_connected_subset(G, cds): cds.add(node) return cds
def random_steiner_tree(G): D = set() #remainder of vertices R = list(G.nodes()) W = [G.degree[v] for v in remainder] while not nx.is_dominating_set(G, D): x = random.choices(R, weights=W) D.add(x) return dijkstra_solve(G, D, D)
def domCheckFirst2(G, max, min=1): nod = nx.nodes(G) for i in range(min, max + 1): co = itertools.combinations(nod, i) for j in co: if nx.is_dominating_set(G, j): return len(j) break return None
def min_connected_dominating_sets_non_distributed(cls, G): """Compute a CDS, based on algorithm of Butenko, Cheng, Oliveira, Pardalos Based on the paper: BUTENKO, Sergiy, CHENG, Xiuzhen, OLIVEIRA, Carlos A., et al. A new heuristic for the minimum connected dominating set problem on ad hoc wireless networks. In : Recent developments in cooperative control and optimization. Springer US, 2004. p. 61-73. """ assert nx.is_connected(G) G2 = copy.deepcopy(G) # Step 1: initialization # take the node with maximum degree as the starting node starting_node = max(G2.degree().items(), key=operator.itemgetter(1))[0] fixed_nodes = {starting_node} # Enqueue the neighbor nodes of starting node to Q in descending order by their degree neighbor_nodes = G2.neighbors(starting_node) neighbor_nodes_sorted = OrderedDict( sorted(G2.degree(neighbor_nodes).items(), key=operator.itemgetter(1), reverse=True)).keys() priority_queue = deque( neighbor_nodes_sorted ) # a priority queue is maintained centrally to decide whether an element would be a part of CDS. inserted_set = set(neighbor_nodes_sorted + [starting_node]) # Step 2: calculate the cds while priority_queue: u = priority_queue.pop() # check if the graph after removing u is still connected rest_graph = copy.deepcopy(G2) rest_graph.remove_node(u) if nx.is_connected(rest_graph): G2.remove_node(u) else: # is not connected fixed_nodes.add(u) # add neighbors of u to the priority queue, which never are inserted into Q inserted_neighbors = set(G2.neighbors(u)) - inserted_set inserted_neighbors_sorted = OrderedDict( sorted(G2.degree(inserted_neighbors).items(), key=operator.itemgetter(1), reverse=True)).keys() priority_queue.extend(inserted_neighbors_sorted) inserted_set.update(inserted_neighbors_sorted) # Step 3: verify the result assert nx.is_dominating_set(G, fixed_nodes) and nx.is_connected( G.subgraph(fixed_nodes)) return fixed_nodes
def is_valid_network(G, T): """ Checks whether T is a valid network of G. Args: G: networkx.Graph T: networkx.Graph Returns: bool: whether T is a valid network """ return nx.is_tree(T) and nx.is_dominating_set(G, T.nodes)
def remove_neighbor(G, kingdoms, conquered_set): kingdoms = set(kingdoms) attempts = 0 while attempts < 10: conquered_set_copy = list(conquered_set) to_remove = random.choice(conquered_set_copy) conquered_set_copy.remove(to_remove) if nx.is_dominating_set(G, conquered_set_copy): return conquered_set_copy attempts += 1 return conquered_set
def dominating_set(graph, size): """ Tries to compute dominating set of size k. :param graph: Graph :param size: int :return: list """ for nodes in itertools.combinations(graph.nodes(), size): if networkx.is_dominating_set(graph, nodes): return nodes
def domCheck(G, max, min=1): fin = [] nod = nx.nodes(G) for i in range(min, max + 1): if not fin: co = itertools.combinations(nod, i) for j in co: if nx.is_dominating_set(G, j): fin.append(j) else: break return fin
def compute_1_connected_k_dominating_set(G, CDS): MIScandidates = [] add_flag = True MIScandidates.append(CDS[0]) for i in range(1, len(CDS)): for j in range(0, len(MIScandidates)): if G.has_edge(CDS[i], MIScandidates[j]): add_flag = False break if add_flag: MIScandidates.append(CDS[i]) # print "MIScandidates" # print MIScandidates MIS = nx.maximal_independent_set(G, MIScandidates) # print "Maximal Independent Set" # print MIS C = list(set(CDS) - set(MIScandidates)) # print "C is", # print C newCDS = MIS # print newCDS for i in C: newCDS.append(i) CDSGraph = G.subgraph(newCDS) if not (nx.is_dominating_set(G, newCDS) and nx.is_connected(CDSGraph)): print "Error, C and I did not create a CDS" sys.exit() I1 = MIS # Here we just construct a 3-dominating set # Could be a loop to m, for an m-dominating set newG = G.copy() newG.remove_nodes_from(I1) I2 = nx.maximal_independent_set(newG) # Union of sets DA = list(set(I1) | set(I2) | set(C)) return DA
def solve_dominating_set_then_tsp(G, dominating_set_fn, tour_fn, start=None, all_paths=None): ds = dominating_set_fn(G) if not nx.is_dominating_set(G, ds): raise Exception('fn failed to make dominating set') tour = tour_fn(G, ds, start=start, all_paths=all_paths) # BAD TOUR try: k_utils.check(G, tour, ds) except: print('failed for ' + tour_fn.__name__ + '.') raise return tour, ds
def minimal_dominating_set(graph): """ Computes a minimal dominating set with brute force. :param graph: Graph :return: list """ k = 1 while True: for nodes in itertools.combinations(graph.nodes(), k): if networkx.is_dominating_set(graph, nodes): return nodes k += 1
def maes_randomization_alg(G, T, iterations): #min heap with minimal pairwise distance for ALL random trees costPQ = [] costs = [] for iter in range(iterations): #edges in the tree so far delete_edges = list(T.edges) #how many edges to delete from the start tree initially delete_num_edges = random.randint(1, len(delete_edges)) MODgraph = copy.deepcopy(G) #delete "delete_num_edges" VALID edges in total while (delete_num_edges > 0 and len(delete_edges) != 0): chosen_edge = random.choice(delete_edges) w = MODgraph.get_edge_data(chosen_edge[0], chosen_edge[1])['weight'] # e0 = chosen_edge[0] # e1 = chosen_edge[1] MODgraph.remove_edge(chosen_edge[0], chosen_edge[1]) # if MODgraph.degree(chosen_edge[1]) == 0: # MODgraph.remove_node(chosen_edge[1]) # if MODgraph.degree(chosen_edge[0]) == 0: # MODgraph.remove_node(chosen_edge[0]) delete_edges.remove(chosen_edge) if not (nx.is_connected(MODgraph) and nx.is_dominating_set(G, MODgraph)): #invalid edge,re-add what I just removed if chosen_edge[0] not in MODgraph.nodes: MODgraph.add_node(chosen_edge[0]) if chosen_edge[1] not in MODgraph.nodes: MODgraph.add_node(chosen_edge[1]) MODgraph.add_edge(chosen_edge[0], chosen_edge[1], weight=w) else: #found a valid edge delete_num_edges -= 1 #save time to see if NO edges from T can be removed if (not nx.is_isomorphic(G, MODgraph)): randTree = solve2(MODgraph) cost = average_pairwise_distance_fast(randTree) if cost not in costs: costs.append(cost) heappush(costPQ, (cost, randTree)) if len(costPQ) == 0: heappush(costPQ, (average_pairwise_distance_fast(T), T)) return heappop(costPQ)[1]
def domSet_WheSub(G, onlyLook, total=None): uG = G.copy( ) #make a deepcopy of the orig graph to update for the algorithm domSet = [] #list to place dominant set neighSet = set([]) #list of neighbors to dominating set if not total: loop_num = len( onlyLook) #total is the set maximum number of loops for graph else: #default as many nodes in graph loop_num = total #can also set a lower limit though for i in range(loop_num): nodes_sel = MaxDegSub( G=uG, onlyLook=onlyLook ) #select nodes from updated graph with max degree centrality #chooses among degree ties with the maximum set of new neighbors if len(nodes_sel) > 1: temp = DegTieBreak(G=uG, neighSet=neighSet, nbunch=nodes_sel) node_sel = temp[0] neigh_cur = temp[1] newR = temp[2] else: node_sel = nodes_sel[0] neigh_cur = set( uG[node_sel].keys()) #neighbors of the current node newR = neigh_cur - neighSet #new neighbors added in domSet.append(node_sel) #append that node to domSet list #break loop if dominant set found, else decrement counter if nx.is_dominating_set(G, domSet): break #should only bother to do this junk if dominant set has not been found! uG.remove_node(node_sel) #remove node from updated graph #now this part does two loops to remove the edges between reached nodes #one for all pairwise combinations of the new reached nodes, the second #for the product of all new reached nodes compared to prior reached nodes #new nodes that have been reached for i in itertools.combinations(newR, 2): if uG.has_edge(*i): uG.remove_edge(*i) #product of new nodes and old neighbor set #this loop could be pretty costly in big networks, consider dropping #should not make much of a difference for j in itertools.product(newR, neighSet): if uG.has_edge(*j): uG.remove_edge(*j) #now update the neighSet to include newnodes, but strip nodes that are in the dom set #since they are pruned from graph, all of their edges are gone as well neighSet = (newR | neighSet) - set(domSet) return domSet
# plt.show() plt.savefig("1_initial.png") CDS = computeCDS(G) print "\n" print "CDS" print CDS # G1 = G.subgraph(CDS) # nx.draw(G1) # plt.show() if nx.is_dominating_set(G, CDS): print "Succesfull Connected Dominating Set" else: print "ERROR, did not achieve Connected Dominating Set" print "\n" # position = nx.fruchterman_reingold_layout(G) # nx.draw_networkx_nodes(G,position, nodelist=G.nodes(), node_color="b") nx.draw_networkx_nodes(G, position, nodelist=CDS, node_color="r") # nx.draw_networkx_edges(G,position) # nx.draw_networkx_labels(G,position) plt.savefig("2_CDS.png")
def computeCDS(G): # Temporary copy of graph graphD = G.copy() # Current CDS in D D = G.nodes() # print "Initial D" # print D # Current fixed vetrices in F F = [] neighbourhood = [] for i in range(0, nx.number_of_nodes(G)): neighbourhood.append(len(G.neighbors(i))) # print "Neighbourhood " # print neighbourhood # print "Index of min value is", # print neighbourhood.index(min(neighbourhood)) minimum = 99999 maximum = -1 while set(D) - set(F): minimum = 99999 maximum = -1 # find min number of neighbours for i in set(D) - set(F): if neighbourhood[i] < minimum: minimum = neighbourhood[i] u = i # u = neighbourhood.index(minimum) # print "D is ", # print D # print "u is", # print u tempG = graphD.copy() tempG.remove_node(u) if not nx.is_connected(tempG): F.append(u) else: D.remove(u) # Error correction if not nx.is_dominating_set(G, D): # print "Error, reverting D and exiting" D.append(u) break # graphD = tempG.copy() graphD.remove_node(u) # adjust neighbours for node in D: if node in G.neighbors(u): neighbourhood[node] = neighbourhood[node] - 1 if not set(G.neighbors(u)).intersection(F): for i in G.neighbors(u): if neighbourhood[i] > maximum: maximum = neighbourhood[i] w = i # w = neighbourhood.index(maximum) F.append(w) # print "F is", # print F return D
def test_dominating_set(): G = nx.gnp_random_graph(100, 0.1) D = nx.dominating_set(G) assert_true(nx.is_dominating_set(G, D)) D = nx.dominating_set(G, start_with=0) assert_true(nx.is_dominating_set(G, D))
def checkIfIsDominatingSet(graph, dominatingSet): return nx.is_dominating_set(graph, dominatingSet);