예제 #1
0
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)
예제 #2
0
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})
예제 #3
0
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)
예제 #4
0
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])))
예제 #5
0
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)
예제 #6
0
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])))
예제 #7
0
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))
예제 #8
0
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
예제 #10
0
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
예제 #11
0
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
예제 #12
0
 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)
예제 #13
0
 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)
예제 #14
0
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)
예제 #15
0
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
예제 #16
0
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
예제 #17
0
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())
예제 #18
0
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]
예제 #19
0
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
예제 #20
0
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
예제 #21
0
 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
예제 #22
0
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
예제 #23
0
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
예제 #24
0
 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
예제 #25
0
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)
예제 #26
0
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
예제 #27
0
    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
예제 #28
0
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)
예제 #29
0
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
예제 #30
0
파일: __init__.py 프로젝트: weddige/kcenter
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
예제 #31
0
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
예제 #33
0
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
예제 #34
0
파일: __init__.py 프로젝트: weddige/kcenter
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
예제 #35
0
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]
예제 #36
0
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
예제 #39
0
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);