Пример #1
0
def test_preflow_push_makes_enough_space():
    #From ticket #1542
    G = nx.DiGraph()
    nx.add_path(G, [0, 1, 3], capacity=1)
    nx.add_path(G, [1, 2, 3], capacity=1)
    R = preflow_push(G, 0, 3, value_only=False)
    assert_equal(R.graph['flow_value'], 1)
Пример #2
0
def test_notarborescence2():
    # Not an arborescence due to in-degree violation.
    G = nx.MultiDiGraph()
    nx.add_path(G, range(5))
    G.add_edge(6, 4)
    assert_false(nx.is_branching(G))
    assert_false(nx.is_arborescence(G))
Пример #3
0
def test_all_simple_paths_multigraph():
    G = nx.MultiGraph([(1, 2), (1, 2)])
    paths = nx.all_simple_paths(G, 1, 1)
    assert_equal(paths, [])
    nx.add_path(G, [3, 1, 10, 2])
    paths = nx.all_simple_paths(G, 1, 2)
    assert_equal(set(tuple(p) for p in paths), {(1, 2), (1, 2), (1, 10, 2)})
Пример #4
0
def test_bidirectional_dijkstra_ignore():
    G = nx.Graph()
    nx.add_path(G, [1, 2, 10])
    nx.add_path(G, [1, 3, 10])
    assert_raises(
        nx.NetworkXNoPath,
        _bidirectional_dijkstra,
        G,
        1, 2,
        ignore_nodes=[1],
    )
    assert_raises(
        nx.NetworkXNoPath,
        _bidirectional_dijkstra,
        G,
        1, 2,
        ignore_nodes=[2],
    )
    assert_raises(
        nx.NetworkXNoPath,
        _bidirectional_dijkstra,
        G,
        1, 2,
        ignore_nodes=[1, 2],
    )
Пример #5
0
 def setUp(self):
     #
     #       -- s1 --
     #     /     |    \
     #   c1-----c2----c3
     #  /  \   / | \    \
     # r1  r2 r3 r4 r5  r6
     #
     topo = fnss.Topology()
     icr_candidates = ["c1", "c2", "c3"]
     nx.add_path(topo, icr_candidates)
     topo.add_edge("c1", "s1")
     topo.add_edge("c2", "s1")
     topo.add_edge("c3", "s1")
     topo.add_edge("c1", "r1")
     topo.add_edge("c1", "r2")
     topo.add_edge("c2", "r3")
     topo.add_edge("c2", "r4")
     topo.add_edge("c2", "r5")
     topo.add_edge("c3", "r6")
     topo.graph['icr_candidates'] = set(icr_candidates)
     for router in icr_candidates:
         fnss.add_stack(topo, router, 'router')
     for src in ['s1']:
         fnss.add_stack(topo, src, 'source')
     for rcv in ['r1', 'r2', 'r3', 'r4', 'r5', 'r6']:
         fnss.add_stack(topo, rcv, 'receiver')
     self.topo = cacheplacement.IcnTopology(topo)
Пример #6
0
 def test_edges_with_data_not_equal(self):
     G = nx.MultiGraph()
     nx.add_path(G, [0, 1, 2], weight=1)
     H = nx.MultiGraph()
     nx.add_path(H, [0, 1, 2], weight=2)
     self._test_not_equal(G.edges(data=True, keys=True),
                          H.edges(data=True, keys=True))
Пример #7
0
 def nrr_topology(cls):
     """Return topology for testing NRR caching strategies
     """
     # Topology sketch
     #
     # 0 ---- 2----- 4
     #        |       \
     #        |        s
     #        |       /
     # 1 ---- 3 ---- 5
     #
     topology = IcnTopology(fnss.Topology())
     nx.add_path(topology, [0, 2, 4, "s", 5, 3, 1])
     topology.add_edge(2, 3)
     receivers = (0, 1)
     source = "s"
     caches = (2, 3, 4, 5)
     contents = (1, 2, 3, 4)
     fnss.add_stack(topology, source, 'source', {'contents': contents})
     for v in caches:
         fnss.add_stack(topology, v, 'router', {'cache_size': 1})
     for v in receivers:
         fnss.add_stack(topology, v, 'receiver', {})
     fnss.set_delays_constant(topology, 1, 'ms')
     return topology
Пример #8
0
def test_not_connected():
    G = nx.Graph()
    nx.add_path(G, [1, 2, 3])
    nx.add_path(G, [4, 5])
    for interface_func in [nx.minimum_edge_cut, nx.minimum_node_cut]:
        for flow_func in flow_funcs:
            assert_raises(nx.NetworkXError, interface_func, G, flow_func=flow_func)
Пример #9
0
 def compare_graph_paths_names(g, paths, names):
     expected = nx.DiGraph()
     for p in paths:
         nx.add_path(expected, p)
     assert_equal(sorted(expected.nodes), sorted(g.nodes))
     assert_equal(sorted(expected.edges()), sorted(g.edges()))
     g_names = [g.get_edge_data(s, e)['Name'] for s, e in g.edges()]
     assert_equal(names, sorted(g_names))
 def test_path(self):
     path = list(range(10))
     shuffle(path)
     G = nx.Graph()
     nx.add_path(G, path)
     for method in self._methods:
         order = nx.spectral_ordering(G, method=method)
         ok_(order in [path, list(reversed(path))])
Пример #11
0
 def test_weighted(self):
     G = nx.Graph()
     nx.add_cycle(G, range(7), weight=2)
     ans = nx.average_shortest_path_length(G, weight='weight')
     assert_almost_equal(ans, 4)
     G = nx.Graph()
     nx.add_path(G, range(5), weight=2)
     ans = nx.average_shortest_path_length(G, weight='weight')
     assert_almost_equal(ans, 4)
Пример #12
0
 def setUp(self):
     self.P4=nx.path_graph(4)
     self.D=nx.DiGraph()
     self.D.add_edges_from([(0, 2), (0, 3), (1, 3), (2, 3)])
     self.M=nx.MultiGraph()
     nx.add_path(self.M, range(4))
     self.M.add_edge(0,1)
     self.S=nx.Graph()
     self.S.add_edges_from([(0,0),(1,1)])
 def test_P5_multiple_target(self):
     """Betweenness centrality: P5 multiple target"""
     G = nx.Graph()
     nx.add_path(G, range(5))
     b_answer = {0: 0, 1: 1, 2: 1, 3: 0.5, 4: 0, 5: 0}
     b = nx.betweenness_centrality_subset(G, sources=[0], targets=[3, 4],
                                          weight=None)
     for n in sorted(G):
         assert_almost_equal(b[n], b_answer[n])
Пример #14
0
 def setUp(self):
     deg=[3,2,2,1,0]
     self.G=havel_hakimi_graph(deg)
     self.P=nx.path_graph(3)
     self.WG=nx.Graph( (u,v,{'weight':0.5,'other':0.3})
             for (u,v) in self.G.edges() )
     self.WG.add_node(4)
     self.DG=nx.DiGraph()
     nx.add_path(self.DG, [0,1,2])
Пример #15
0
def test_not_connected():
    G = nx.Graph()
    nx.add_path(G, [1, 2, 3])
    nx.add_path(G, [4, 5])
    for flow_func in flow_funcs:
        assert_equal(nx.node_connectivity(G), 0,
                     msg=msg.format(flow_func.__name__))
        assert_equal(nx.edge_connectivity(G), 0,
                     msg=msg.format(flow_func.__name__))
 def test_P5(self):
     """Betweenness Centrality Subset: P5"""
     G = nx.Graph()
     nx.add_path(G, range(5))
     b_answer = {0: 0, 1: 0.5, 2: 0.5, 3: 0, 4: 0, 5: 0}
     b = nx.betweenness_centrality_subset(G, sources=[0], targets=[3],
                                          weight=None)
     for n in sorted(G):
         assert_almost_equal(b[n], b_answer[n])
 def test_P5(self):
     """Edge betweenness centrality: P5"""
     G = nx.Graph()
     nx.add_path(G, range(5))
     b_answer = dict.fromkeys(G.edges(), 0)
     b_answer[(0, 1)] = b_answer[(1, 2)] = b_answer[(2, 3)] = 0.5
     b = nx.edge_betweenness_centrality_subset(G, sources=[0], targets=[3],
                                               weight=None)
     for n in sorted(G.edges()):
         assert_almost_equal(b[n], b_answer[n])
Пример #18
0
 def test_all_pairs_connectivity_directed(self):
     G = nx.DiGraph()
     nodes = [0, 1, 2, 3]
     nx.add_path(G, nodes)
     A = {n: {} for n in G}
     for u, v in itertools.permutations(nodes, 2):
         A[u][v] = nx.node_connectivity(G, u, v)
     C = nx.all_pairs_node_connectivity(G)
     assert_equal(sorted((k, sorted(v)) for k, v in A.items()),
                  sorted((k, sorted(v)) for k, v in C.items()))
 def test_directed_path_normalized(self):
     """Betweenness centrality: directed path normalized"""
     G=nx.DiGraph()
     nx.add_path(G, [0, 1, 2])
     b=nx.betweenness_centrality(G,
                                       weight=None,
                                       normalized=True)
     b_answer={0: 0.0, 1: 0.5, 2: 0.0}
     for n in sorted(G):
         assert_almost_equal(b[n],b_answer[n])
 def test_path(self):
     # based on setupClass numpy is installed if we get here
     from numpy.random import shuffle
     path = list(range(10))
     shuffle(path)
     G = nx.Graph()
     nx.add_path(G, path)
     for method in self._methods:
         order = nx.spectral_ordering(G, method=method)
         ok_(order in [path, list(reversed(path))])
 def test_disconnected(self):
     G = nx.Graph()
     nx.add_path(G, range(0, 10, 2))
     nx.add_path(G, range(1, 10, 2))
     for method in self._methods:
         order = nx.spectral_ordering(G, method=method)
         assert_equal(set(order), set(G))
         seqs = [list(range(0, 10, 2)), list(range(8, -1, -2)),
                 list(range(1, 10, 2)), list(range(9, -1, -2))]
         ok_(order[:5] in seqs)
         ok_(order[5:] in seqs)
 def test_disconnected_path(self):
     """Betweenness centrality: disconnected path"""
     G=nx.Graph()
     nx.add_path(G, [0, 1, 2])
     nx.add_path(G, [3, 4, 5, 6])
     b_answer={0:0,1:1,2:0,3:0,4:2,5:2,6:0}
     b=nx.betweenness_centrality(G,
                                       weight=None,
                                       normalized=False)
     for n in sorted(G):
         assert_almost_equal(b[n],b_answer[n])
Пример #23
0
 def test_path_weighted_projected_directed_graph(self):
     G = nx.DiGraph()
     nx.add_path(G, range(4))
     P = bipartite.weighted_projected_graph(G, [1, 3])
     assert_nodes_equal(list(P), [1, 3])
     assert_edges_equal(list(P.edges()), [(1, 3)])
     P[1][3]['weight'] = 1
     P = bipartite.weighted_projected_graph(G, [0, 2])
     assert_nodes_equal(list(P), [0, 2])
     assert_edges_equal(list(P.edges()), [(0, 2)])
     P[0][2]['weight'] = 1
 def test_P5_directed(self):
     """Betweenness centrality: P5 directed"""
     G=nx.DiGraph()
     nx.add_path(G, range(5))
     b_answer={0:0,1:1,2:1,3:0,4:0,5:0}
     b=betweenness_centrality_subset(G,
                                     sources=[0],
                                     targets=[3],
                                     weight=None)
     for n in sorted(G):
         assert_almost_equal(b[n],b_answer[n])
Пример #25
0
 def test_add_path(self):
     G = self.G.copy()
     nlist = [12, 13, 14, 15]
     nx.add_path(G, nlist)
     assert_edges_equal(G.edges(nlist), [(12, 13), (13, 14), (14, 15)])
     G = self.G.copy()
     nx.add_path(G, nlist, weight=2.0)
     assert_edges_equal(G.edges(nlist, data=True),
                        [(12, 13, {'weight': 2.}),
                         (13, 14, {'weight': 2.}),
                         (14, 15, {'weight': 2.})])
Пример #26
0
 def test_directed_multigraph_path(self):
     G = nx.MultiDiGraph()
     nx.add_path(G, range(6))
     partition = [{0, 1}, {2, 3}, {4, 5}]
     M = nx.quotient_graph(G, partition, relabel=True)
     assert_equal(sorted(M), [0, 1, 2])
     assert_equal(sorted(M.edges()), [(0, 1), (1, 2)])
     for n in M:
         assert_equal(M.node[n]['nedges'], 1)
         assert_equal(M.node[n]['nnodes'], 2)
         assert_equal(M.node[n]['density'], 0.5)
Пример #27
0
def test_shortest_augmenting_path_two_phase():
    k = 5
    p = 1000
    G = nx.DiGraph()
    for i in range(k):
        G.add_edge('s', (i, 0), capacity=1)
        nx.add_path(G, ((i, j) for j in range(p)), capacity=1)
        G.add_edge((i, p - 1), 't', capacity=1)
    R = shortest_augmenting_path(G, 's', 't', two_phase=True)
    assert_equal(R.graph['flow_value'], k)
    R = shortest_augmenting_path(G, 's', 't', two_phase=False)
    assert_equal(R.graph['flow_value'], k)
 def test_disconnected_path_endpoints(self):
     """Betweenness centrality: disconnected path endpoints"""
     G=nx.Graph()
     nx.add_path(G, [0, 1, 2])
     nx.add_path(G, [3, 4, 5, 6])
     b_answer={0:2,1:3,2:2,3:3,4:5,5:5,6:3}
     b=nx.betweenness_centrality(G,
                                       weight=None,
                                       normalized=False,
                                       endpoints=True)
     for n in sorted(G):
         assert_almost_equal(b[n],b_answer[n])
Пример #29
0
 def test_default_attribute(self):
     G = nx.Graph(name="Fred")
     G.add_node(1, label=1, color='green')
     nx.add_path(G, [0, 1, 2, 3])
     G.add_edge(1, 2, weight=3)
     G.graph['node_default'] = {'color': 'yellow'}
     G.graph['edge_default'] = {'weight': 7}
     fh = io.BytesIO()
     self.writer(G, fh)
     fh.seek(0)
     H = nx.read_graphml(fh, node_type=int)
     assert_nodes_equal(G.nodes(), H.nodes())
     assert_edges_equal(G.edges(), H.edges())
     assert_equal(G.graph, H.graph)
Пример #30
0
def test_bidirectional_shortest_path_ignore():
    G = nx.Graph()
    nx.add_path(G, [1, 2])
    nx.add_path(G, [1, 3])
    nx.add_path(G, [1, 4])
    pytest.raises(nx.NetworkXNoPath,
                  _bidirectional_shortest_path,
                  G,
                  1,
                  2,
                  ignore_nodes=[1])
    pytest.raises(nx.NetworkXNoPath,
                  _bidirectional_shortest_path,
                  G,
                  1,
                  2,
                  ignore_nodes=[2])
    G = nx.Graph()
    nx.add_path(G, [1, 3])
    nx.add_path(G, [1, 4])
    nx.add_path(G, [3, 2])
    pytest.raises(nx.NetworkXNoPath,
                  _bidirectional_shortest_path,
                  G,
                  1,
                  2,
                  ignore_nodes=[1, 2])
Пример #31
0
 def test_multicast_tree(self):
     topo = fnss.Topology()
     nx.add_path(topo, [2, 1, 3, 4])
     sp = dict(nx.all_pairs_shortest_path(topo))
     tree = util.multicast_tree(sp, 1, [2, 3])
     self.assertSetEqual(set(tree), set([(1, 2), (1, 3)]))
Пример #32
0
def test_connected_double_edge_swap_not_connected():
    with pytest.raises(nx.NetworkXError):
        G = nx.path_graph(3)
        nx.add_path(G, [10, 11, 12])
        G = nx.connected_double_edge_swap(G)
Пример #33
0
def test_ssp_multigraph():
    with pytest.raises(nx.NetworkXNotImplemented):
        G = nx.MultiGraph()
        nx.add_path(G, [1, 2, 3])
        list(nx.shortest_simple_paths(G, 1, 4))
Пример #34
0
 def add_transition_path(self, transition_list, w=None):
     if w == None:
         w = self.std_tran_weight
     nx.add_path(self, transition_list, type="transition", weight=w)
     nx.add_path(self, transition_list[::-1], type="transition", weight=w)
     self.add_self_loops()
Пример #35
0
def test_ssp_source_missing2():
    with pytest.raises(nx.NetworkXNoPath):
        G = nx.Graph()
        nx.add_path(G, [0, 1, 2])
        nx.add_path(G, [3, 4, 5])
        list(nx.shortest_simple_paths(G, 0, 3))
Пример #36
0
def main():
    # Create a graph
    graph = Graph()
    # Create graph connections (Actual distance)

    #Subdomain A
    #Client -> Switch
    graph.connect('ClientA', 'SwitchA', client_switch)
    graph.connect('ClientB', 'SwitchA', client_switch)
    graph.connect('ClientC', 'SwitchA', client_switch)
    graph.connect('ClientD', 'SwitchA', client_switch)
    graph.connect('ClientE', 'SwitchA', client_switch)

    #Switch -> client
    graph.connect('SwitchA', 'ClientA', switch_client)
    graph.connect('SwitchA', 'ClientB', switch_client)
    graph.connect('SwitchA', 'ClientC', switch_client)
    graph.connect('SwitchA', 'ClientD', switch_client)
    graph.connect('SwitchA', 'ClientE', switch_client)

    #Branch
    graph.connect('SwitchA', 'SwitchB', switch_client)

    #Subdomain B
    #Client -> Switch
    graph.connect('ClientF', 'SwitchB', client_switch)
    graph.connect('ClientG', 'SwitchB', client_switch)
    graph.connect('ClientH', 'SwitchB', client_switch)
    graph.connect('ClientI', 'SwitchB', client_switch)
    graph.connect('ClientJ', 'SwitchB', client_switch)
    graph.connect('ClientK', 'SwitchB', client_switch)

    #Switch -> client
    graph.connect('SwitchB', 'ClientF', switch_client)
    graph.connect('SwitchB', 'ClientG', switch_client)
    graph.connect('SwitchB', 'ClientH', switch_client)
    graph.connect('SwitchB', 'ClientI', switch_client)
    graph.connect('SwitchB', 'ClientJ', switch_client)
    graph.connect('SwitchB', 'ClientK', switch_client)

    #Port opennings between non branched
    graph.connect('ClientA', 'ClientB', client_client)
    graph.connect('ClientJ', 'ClientB', client_client)
    graph.connect('ClientH', 'ClientB', client_client)
    graph.connect('ClientB', 'ClientK', client_client)

    # Create heuristics (inverse vulnerabilities)
    heuristics = {}
    heuristics['ClientA'] = no_vulns
    heuristics['ClientB'] = no_vulns
    heuristics['ClientC'] = no_vulns
    heuristics['ClientD'] = no_vulns
    heuristics['ClientE'] = no_vulns
    heuristics['ClientF'] = no_vulns
    heuristics['ClientG'] = no_vulns
    heuristics['ClientH'] = minor
    heuristics['ClientI'] = no_vulns
    heuristics['ClientJ'] = no_vulns
    heuristics['ClientK'] = no_vulns
    heuristics['SwitchA'] = minor
    heuristics['SwitchB'] = medium

    # Run the search algorithm
    print(
        "-------------------------------------------------------------------------------------"
    )
    print(
        "-------------------------------------------------------------------------------------"
    )
    print("Current Graph Nodes are: \n")
    print(
        "-------------------------------------------------------------------------------------"
    )
    for i in graph.nodes():
        print(i)
    print(
        "-------------------------------------------------------------------------------------"
    )

    print(
        "\nInput the nodes you are determining the likely threat path for: \n")

    #Get traversal input
    beginning_node = None
    target_node = None

    while (beginning_node not in graph.nodes()):
        beginning_node = input("Please input starting node: ")
        if (beginning_node not in graph.nodes()):
            print("\nNode not present in graph, please try again\n")

    while (target_node not in graph.nodes()):
        target_node = input("Please input target node: ")
        if (target_node not in graph.nodes()):
            print("\nNode not present in graph, please try again\n")

    print("\nSearching............\n")
    #Traverse and retrieve results
    path = astar_search(graph, heuristics, beginning_node, target_node)
    node_titles = [item[0] for item in path[:-1]]
    print(
        "-------------------------------------------------------------------------------------"
    )
    print(
        "-------------------------------------------------------------------------------------"
    )
    print("Search completed\n")
    print("Displaying results.....")
    print(
        "-------------------------------------------------------------------------------------"
    )
    for i in path:
        print(i)
    print(
        "-------------------------------------------------------------------------------------"
    )
    print("Based on the search algorithm, nodes of interest are: \n")
    for i in node_titles:
        print(i)
    print(
        "-------------------------------------------------------------------------------------"
    )
    print(
        "-------------------------------------------------------------------------------------"
    )
    print("Generating graph visualisation..........\n")

    # Build nxGraph
    G = nx.MultiDiGraph()
    G.add_nodes_from(graph.nodes())
    G.add_edge('ClientA', 'SwitchA', label=2)
    G.add_edge('ClientB', 'SwitchA', label=2)
    G.add_edge('ClientC', 'SwitchA', label=2)
    G.add_edge('ClientD', 'SwitchA', label=2)
    G.add_edge('ClientE', 'SwitchA', label=2)
    G.add_edge('SwitchA', 'ClientA', label=4)
    G.add_edge('SwitchA', 'ClientB', label=4)
    G.add_edge('SwitchA', 'ClientC', label=4)
    G.add_edge('SwitchA', 'ClientD', label=4)
    G.add_edge('SwitchA', 'ClientE', label=4)
    G.add_edge('SwitchA', 'SwitchB', label=4)
    G.add_edge('ClientF', 'SwitchB', label=2)
    G.add_edge('ClientG', 'SwitchB', label=2)
    G.add_edge('ClientH', 'SwitchB', label=2)
    G.add_edge('ClientI', 'SwitchB', label=2)
    G.add_edge('ClientJ', 'SwitchB', label=2)
    G.add_edge('ClientK', 'SwitchB', label=2)
    G.add_edge('SwitchB', 'ClientF', label=4)
    G.add_edge('SwitchB', 'ClientG', label=4)
    G.add_edge('SwitchB', 'ClientH', label=4)
    G.add_edge('SwitchB', 'ClientI', label=4)
    G.add_edge('SwitchB', 'ClientJ', label=4)
    G.add_edge('SwitchB', 'ClientK', label=4)
    G.add_edge('ClientA', 'ClientB', label=2)
    G.add_edge('ClientJ', 'ClientB', label=2)
    G.add_edge('ClientH', 'ClientB', label=2)
    G.add_edge('ClientB', 'ClientK', label=2)

    # Build SubGraph
    sg = nx.MultiDiGraph()
    nx.add_path(sg, node_titles)

    def visualize(G, sg, name='attack-graph.html'):
        N = pvnet.Network(height='100%',
                          width='100%',
                          bgcolor='#222222',
                          font_color='white',
                          directed=True)
        opts = '''
            var options = {
              "physics": {
                "forceAtlas2Based": {
                  "gravitationalConstant": -100,
                  "centralGravity": 0.01,
                  "springLength": 100,
                  "springConstant": 0.09,
                  "avoidOverlap": 1
                },
                "minVelocity": 0.75,
                "solver": "forceAtlas2Based",
                "timestep": 0.22
              }
            }
        '''

        N.set_options(opts)

        for n in G:
            if n in sg:  # if the node is part of the sub-graph
                color = 'green'
                size = 40
            else:
                color = 'red'
                size = 30
            N.add_node(n, label=n, color=color, size=size)

        for e in G.edges():
            if e in sg.edges():  # if the edge is part of sub-graph
                color = 'green'
                width = 5
            else:
                color = 'red'
                width = 1
            N.add_edge((e[0]), (e[1]), color=color, width=width)

        return N.show(name)

    visualize(G, sg)
def test_target_missing():
    G = nx.Graph()
    nx.add_path(G, [1, 2, 3])
    paths = list(nx.all_simple_paths(nx.MultiGraph(G), 1, 4))
Пример #38
0
 def test_bidirectional_dijkstra_no_path(self):
     with pytest.raises(nx.NetworkXNoPath):
         G = nx.Graph()
         nx.add_path(G, [1, 2, 3])
         nx.add_path(G, [4, 5, 6])
         path = nx.bidirectional_dijkstra(G, 1, 6)
def test_source_missing():
    G = nx.Graph()
    nx.add_path(G, [1, 2, 3])
    paths = list(nx.all_simple_paths(nx.MultiGraph(G), 0, 3))
Пример #40
0
 def test_has_path(self):
     G = nx.Graph()
     nx.add_path(G, range(3))
     nx.add_path(G, range(3, 5))
     assert nx.has_path(G, 0, 2)
     assert not nx.has_path(G, 0, 4)
})])

# エッジの追加(方法1)
edges = [(0, 1, {
    "color": "lightblue"
}), (1, 2, {
    "color": "lightblue"
}), (2, 3, {
    "color": "lightblue"
}), (3, 0, {
    "color": "lightblue"
})]
G.add_edges_from(edges)

# エッジの追加(方法2)
nx.add_path(G, [0, 4, 5, 6, 0], color="royalblue")
nx.add_path(G, [0, 7, 8, 9, 0], color="steelblue")

# ノードの色をセット
node_color = [node["color"] for node in G.nodes.values()]

# エッジの色をセット
edge_color = [edge["color"] for edge in G.edges.values()]

# グラフを出力
fig = plt.figure()
pos = nx.circular_layout(G)
nx.draw_networkx(G, pos, edge_color=edge_color, node_color=node_color)
plt.axis("off")
fig.savefig("test.png")
Пример #42
0
 def test_two_cliques_num(self):
     # This graph has two major cliques [0,1,2,3,4] and [11,12,13,14]
     # but the first one is bigger so that's the maximum_clique.
     G = nx.complete_graph(5)
     nx.add_path(G, [4, 5, 6, 7, 8])
     nx.add_path(G, [2, 9, 10])
     nx.add_path(G, [9, 11])
     nx.add_path(G, [11, 12, 13, 14, 11])
     nx.add_path(G, [12, 14])
     nx.add_path(G, [13, 11])
     clique_number = dnx.clique_number(G, dimod.ExactSolver())
     self.assertEqual(clique_number, 5)
Пример #43
0
def test_edge_target_missing():
    with pytest.raises(nx.NodeNotFound):
        G = nx.Graph()
        nx.add_path(G, [1, 2, 3])
        list(nx.all_simple_edge_paths(nx.MultiGraph(G), 1, 4))
Пример #44
0
 def setUp(self):
     self.Gi = nx.grid_2d_graph(5, 5)
     self.Gs = nx.Graph()
     nx.add_path(self.Gs, 'abcdef')
     self.bigG = nx.grid_2d_graph(25,
                                  25)  # bigger than 500 nodes for sparse
Пример #45
0
def test_source_missing():
    with pytest.raises(nx.NodeNotFound):
        G = nx.Graph()
        nx.add_path(G, [1, 2, 3])
        list(nx.all_simple_paths(nx.MultiGraph(G), 0, 3))
    def processAlgorithm(self, parameters, context, feedback):

        try:
            import os, sys, math, string, random, tempfile
            import processing as st
            import networkx as nx
        except Exception as e:
            feedback.reportError(
                QCoreApplication.translate('Error', '%s' % (e)))
            feedback.reportError(QCoreApplication.translate('Error', ' '))
            feedback.reportError(
                QCoreApplication.translate(
                    'Error',
                    'Error loading modules - please install the necessary python module'
                ))
            return {}

        layer = self.parameterAsVectorLayer(parameters, self.Polygons, context)

        if layer == None:
            feedback.reportError(
                QCoreApplication.translate(
                    'Error',
                    'Do not use the "Selected features only" option when applying the algorithm to selected features'
                ))
            return {}

        aMethod = parameters[self.Method]
        Threshold = parameters[self.T]
        tField = self.parameterAsString(parameters, self.tField, context)
        sField = self.parameterAsString(parameters, self.sField, context)
        dField = self.parameterAsString(parameters, self.dField, context)

        mDict = {0: "Centerlines", 1: "All", 2: "Circles"}
        Method = mDict[aMethod]

        context.setInvalidGeometryCheck(QgsFeatureRequest.GeometryNoCheck)

        field_check = layer.fields().indexFromName('ID')

        if field_check == -1:
            pr = layer.dataProvider()
            pr.addAttributes([QgsField("ID", QVariant.Int)])
            layer.updateFields()

        layer.startEditing()
        for feature in layer.getFeatures():
            feature['ID'] = feature.id()
            layer.updateFeature(feature)
        layer.commitChanges()

        fet = QgsFeature()
        fields = QgsFields()
        fields.append(QgsField("ID", QVariant.Int))
        field_names = ['Distance', 'RDistance', 'SP_Dist', 'SP_RDist']

        for name in field_names:
            fields.append(QgsField(name, QVariant.Double))

        fet2 = QgsFeature(fields)
        (writer2, dest_id) = self.parameterAsSink(parameters, self.Output,
                                                  context, fields,
                                                  QgsWkbTypes.LineString,
                                                  layer.sourceCrs())

        outDir = os.path.join(tempfile.gettempdir(), 'GA')
        if not os.path.exists(outDir):
            os.mkdir(outDir)

        fname = ''.join(
            random.choice(string.ascii_lowercase) for i in range(10))
        infc = os.path.join(outDir, '%s.shp' % (fname))
        Densify_Interval = parameters[self.Densify]
        s = parameters[self.Simplify]

        Precision, tol = 6, 1e-6

        keepNodes = set([])
        fields = QgsFields()
        fields.append(QgsField("ID", QVariant.Int))
        writer = QgsVectorFileWriter(
            infc, "CP1250", fields, QgsWkbTypes.Point, layer.sourceCrs(),
            "ESRI Shapefile")  #.shp requirement of SAGA

        features = layer.selectedFeatures()
        total = layer.selectedFeatureCount()
        if len(features) == 0:
            features = layer.getFeatures()
            total = layer.featureCount()

        total = 100.0 / total

        feedback.pushInfo(
            QCoreApplication.translate('Update', 'Creating Vertices'))
        thresholds = {}

        for enum, feature in enumerate(features):
            if total != -1:
                feedback.setProgress(int(enum * total))

            geomType = feature.geometry()
            if sField:
                s = feature[sField]
            if dField:
                Densify_Interval = feature[dField]
            if s:
                if s > 0:
                    geomType = geomType.simplify(s)
            if Densify_Interval:
                if Densify_Interval > 0:
                    geomType = geomType.densifyByDistance(Densify_Interval)

            ID = feature['ID']
            geom = []
            if geomType.wkbType() == QgsWkbTypes.Polygon:
                polygon = geomType.asPolygon()
                geom = chain(*polygon)
            else:
                polygons = geomType.asMultiPolygon()
                geom = chain(*chain(*polygons))

            for points in geom:
                if (round(points.x(),
                          Precision), round(points.y(),
                                            Precision)) not in keepNodes:
                    pnt = QgsGeometry.fromPointXY(
                        QgsPointXY(points.x(), points.y()))
                    fet.setGeometry(pnt)
                    fet.setAttributes([ID])
                    writer.addFeature(fet)
                    keepNodes.update([(round(points.x(), Precision),
                                       round(points.y(), Precision))])
            if tField:
                tValue = feature[tField]
                try:
                    thresholds[ID] = int(tValue)
                except Exception as e:
                    feedback.reportError(
                        QCoreApplication.translate(
                            'Error',
                            'Non-numeric value found in field for trim iteration function.'
                        ))
                    return {}

        feedback.pushInfo(
            QCoreApplication.translate('Update', 'Creating Voronoi Polygons'))
        del writer

        tempVP = os.path.join(outDir, 'VL.shp')  #.shp requirement of SAGA

        param = {'POINTS': infc, 'POLYGONS': tempVP, 'FRAME': 10.0}
        Voronoi = st.run("saga:thiessenpolygons",
                         param,
                         context=context,
                         feedback=None)

        del keepNodes
        edges = {}

        feedback.pushInfo(
            QCoreApplication.translate('Update', 'Calculating Edges'))

        param = {'INPUT': Voronoi['POLYGONS'], 'OUTPUT': 'memory:'}
        lines = st.run("qgis:polygonstolines",
                       param,
                       context=context,
                       feedback=feedback)

        param = {'INPUT': lines['OUTPUT'], 'OUTPUT': 'memory:'}
        exploded = st.run("native:explodelines",
                          param,
                          context=context,
                          feedback=feedback)
        param = {
            'INPUT': exploded['OUTPUT'],
            'PREDICATE': 6,
            'INTERSECT': layer,
            'METHOD': 0
        }
        st.run("native:selectbylocation",
               param,
               context=context,
               feedback=None)
        total = 100.0 / exploded['OUTPUT'].selectedFeatureCount()

        for enum, feature in enumerate(exploded['OUTPUT'].selectedFeatures()):
            try:
                if total != -1:
                    feedback.setProgress(int(enum * total))
                part = feature.geometry().asPolyline()
                startx = None
                for point in part:
                    if startx == None:
                        startx, starty = (round(point.x(), Precision),
                                          round(point.y(), Precision))
                        continue
                    endx, endy = (round(point.x(), Precision),
                                  round(point.y(), Precision))
                    geom = QgsGeometry.fromPolylineXY(
                        [QgsPointXY(startx, starty),
                         QgsPointXY(endx, endy)])
                    ID = feature['ID']
                    Length = geom.length()
                    if Length > tol:
                        if ID in edges:
                            edges[ID].add_edge((startx, starty), (endx, endy),
                                               weight=Length)
                        else:
                            Graph = nx.Graph()
                            Graph.add_edge((startx, starty), (endx, endy),
                                           weight=Length)
                            edges[ID] = Graph
                    startx, starty = endx, endy

            except Exception as e:
                feedback.reportError(
                    QCoreApplication.translate('Error', '%s' % (e)))

        feedback.pushInfo(
            QCoreApplication.translate(
                'Update', 'Calculating %s Centerlines' % (len(edges))))

        if edges:
            total = 100.0 / len(edges)
            for enum, FID in enumerate(edges):

                feedback.setProgress(int(enum * total))
                G = edges[FID]
                maxG = max(nx.connected_components(G),
                           key=len)  #Largest Connected Graph
                G = G.subgraph(maxG)
                try:
                    if Threshold > 0 or tField:
                        if tField:
                            Threshold = thresholds[FID]
                        else:
                            Threshold = int(Threshold)
                        G2 = G.copy()
                        G3 = G.copy()
                        for n in range(int(Threshold)):
                            degree = G2.degree()
                            removeNodes = [k for k, v in degree if v == 1]
                            G2.remove_nodes_from(removeNodes)

                        degree = G2.degree()
                        if len(G2) < 2:
                            feedback.reportError(
                                QCoreApplication.translate(
                                    'Update',
                                    'No centerline found after trimming dangles for polygon ID %s - skipping'
                                    % (FID)))
                            continue

                        endPoints = [k for k, v in degree if v == 1]

                        G3.remove_edges_from(G2.edges)

                        for source in endPoints:
                            length, path = nx.single_source_dijkstra(
                                G3, source, weight='weight')
                            Index = max(length, key=length.get)
                            nx.add_path(G2, path[Index])

                        del G3

                        source = list(
                            G2.nodes())[0]  #Get length along all paths
                        for n in range(2):
                            length, path = nx.single_source_dijkstra(
                                G, source, weight='weight')
                            Index = max(length, key=length.get)
                            source = path[Index][-1]
                        length2, path2 = nx.single_source_dijkstra(
                            G, source, weight='weight')

                        for p in G2.edges:
                            points = []
                            points.append(QgsPointXY(p[0][0], p[0][1]))
                            points.append(QgsPointXY(p[1][0], p[1][1]))

                            D = max([
                                length[(p[0][0], p[0][1])],
                                length[(p[1][0], p[1][1])]
                            ])
                            D2 = max([
                                length2[(p[0][0], p[0][1])],
                                length2[(p[1][0], p[1][1])]
                            ])

                            dx = path[Index][0][0] - p[1][0]
                            dy = path[Index][0][1] - p[1][1]
                            dx2 = path[Index][0][0] - p[0][0]
                            dy2 = path[Index][0][1] - p[0][1]
                            SP = max([
                                math.sqrt((dx**2) + (dy**2)),
                                math.sqrt((dx2**2) + (dy2**2))
                            ])

                            dx = path[Index][-1][0] - p[1][0]
                            dy = path[Index][-1][1] - p[1][1]
                            dx2 = path[Index][-1][0] - p[0][0]
                            dy2 = path[Index][-1][1] - p[0][1]
                            SP2 = max([
                                math.sqrt((dx**2) + (dy**2)),
                                math.sqrt((dx2**2) + (dy2**2))
                            ])

                            fet2.setGeometry(
                                QgsGeometry.fromPolylineXY(points))
                            fet2.setAttributes([FID, D, D2, SP, SP2])
                            writer2.addFeature(fet2)

                        del G2

                    elif Method == 'All':

                        curLen = 0
                        G2 = G.copy()
                        while len(G2) != curLen:
                            curLen = len(G2)
                            degree = G2.degree()
                            removeNodes = [k for k, v in degree if v == 1]
                            G2.remove_nodes_from(removeNodes)

                        source = list(G.nodes())[0]
                        for n in range(2):
                            length, path = nx.single_source_dijkstra(
                                G, source, weight='weight')
                            Index = max(length, key=length.get)
                            source = path[Index][-1]

                        nx.add_path(G2, path[Index])

                        source = list(
                            G2.nodes())[0]  #Get length along all paths
                        for n in range(2):
                            length, path = nx.single_source_dijkstra(
                                G, source, weight='weight')
                            Index = max(length, key=length.get)
                            source = path[Index][-1]
                        length2, path2 = nx.single_source_dijkstra(
                            G, source, weight='weight')

                        for p in G2.edges:
                            points = []
                            points.append(QgsPointXY(p[0][0], p[0][1]))
                            points.append(QgsPointXY(p[1][0], p[1][1]))

                            D = max([
                                length[(p[0][0], p[0][1])],
                                length[(p[1][0], p[1][1])]
                            ])
                            D2 = max([
                                length2[(p[0][0], p[0][1])],
                                length2[(p[1][0], p[1][1])]
                            ])

                            dx = path[Index][0][0] - p[1][0]
                            dy = path[Index][0][1] - p[1][1]
                            dx2 = path[Index][0][0] - p[0][0]
                            dy2 = path[Index][0][1] - p[0][1]
                            SP = max([
                                math.sqrt((dx**2) + (dy**2)),
                                math.sqrt((dx2**2) + (dy2**2))
                            ])

                            dx = path[Index][-1][0] - p[1][0]
                            dy = path[Index][-1][1] - p[1][1]
                            dx2 = path[Index][-1][0] - p[0][0]
                            dy2 = path[Index][-1][1] - p[0][1]
                            SP2 = max([
                                math.sqrt((dx**2) + (dy**2)),
                                math.sqrt((dx2**2) + (dy2**2))
                            ])

                            fet2.setGeometry(
                                QgsGeometry.fromPolylineXY(points))
                            fet2.setAttributes([FID, D, D2, SP, SP2])
                            writer2.addFeature(fet2)

                        del G2

                    elif Method == 'Circles':

                        curLen = 0
                        G2 = G.copy()
                        while len(G2) != curLen:
                            curLen = len(G2)
                            degree = G2.degree()
                            removeNodes = [k for k, v in degree if v == 1]
                            G2.remove_nodes_from(removeNodes)

                        for p in G2.edges:
                            points = []
                            points.append(QgsPointXY(p[0][0], p[0][1]))
                            points.append(QgsPointXY(p[1][0], p[1][1]))

                            fet2.setGeometry(
                                QgsGeometry.fromPolylineXY(points))
                            fet2.setAttributes([FID])
                            writer2.addFeature(fet2)

                        del G2

                    else:
                        source = list(G.nodes())[0]
                        for n in range(2):
                            length, path = nx.single_source_dijkstra(
                                G, source, weight='weight')
                            Index = max(length, key=length.get)
                            source = path[Index][-1]
                        length2, path2 = nx.single_source_dijkstra(
                            G, source, weight='weight')
                        sx = None
                        for p in path[Index]:
                            if sx == None:
                                sx, sy = p[0], p[1]
                                continue
                            ex, ey = p[0], p[1]
                            D = max([length[(sx, sy)], length[(ex, ey)]])
                            D2 = max([length2[(sx, sy)], length2[(ex, ey)]])
                            dx = path[Index][0][0] - ex
                            dy = path[Index][0][1] - ey
                            dx2 = path[Index][0][0] - sx
                            dy2 = path[Index][0][1] - sy
                            SP = max([
                                math.sqrt((dx**2) + (dy**2)),
                                math.sqrt((dx2**2) + (dy2**2))
                            ])

                            dx = path[Index][-1][0] - ex
                            dy = path[Index][-1][1] - ey
                            dx2 = path[Index][-1][0] - sx
                            dy2 = path[Index][-1][1] - sy
                            SP2 = max([
                                math.sqrt((dx**2) + (dy**2)),
                                math.sqrt((dx2**2) + (dy2**2))
                            ])

                            points = [QgsPointXY(sx, sy), QgsPointXY(ex, ey)]
                            fet2.setGeometry(
                                QgsGeometry.fromPolylineXY(points))
                            fet2.setAttributes([FID, D, D2, SP, SP2])
                            writer2.addFeature(fet2)
                            sx, sy = ex, ey

                except Exception as e:
                    feedback.reportError(
                        QCoreApplication.translate('Update', '%s' % (e)))
                    feedback.reportError(
                        QCoreApplication.translate(
                            'Update',
                            'No centerline found for polygon ID %s - skipping'
                            % (FID)))
                    continue

        del writer2, edges

        return {self.Output: dest_id}
Пример #47
0
 def test_has_path(self):
     G = nx.Graph()
     nx.add_path(G, range(3))
     nx.add_path(G, range(3, 5))
     assert_true(nx.has_path(G, 0, 2))
     assert_false(nx.has_path(G, 0, 4))
Пример #48
0
 def test_all_shortest_paths(self):
     G = nx.Graph()
     nx.add_path(G, [0, 1, 2, 3])
     nx.add_path(G, [0, 10, 20, 3])
     assert_equal([[0, 1, 2, 3], [0, 10, 20, 3]],
                  sorted(nx.all_shortest_paths(G, 0, 3)))
     # with weights
     G = nx.Graph()
     nx.add_path(G, [0, 1, 2, 3])
     nx.add_path(G, [0, 10, 20, 3])
     assert_equal([[0, 1, 2, 3], [0, 10, 20, 3]],
                  sorted(nx.all_shortest_paths(G, 0, 3, weight='weight')))
     # weights and method specified
     G = nx.Graph()
     nx.add_path(G, [0, 1, 2, 3])
     nx.add_path(G, [0, 10, 20, 3])
     assert_equal([[0, 1, 2, 3], [0, 10, 20, 3]],
                  sorted(
                      nx.all_shortest_paths(G,
                                            0,
                                            3,
                                            weight='weight',
                                            method='dijkstra')))
     G = nx.Graph()
     nx.add_path(G, [0, 1, 2, 3])
     nx.add_path(G, [0, 10, 20, 3])
     assert_equal([[0, 1, 2, 3], [0, 10, 20, 3]],
                  sorted(
                      nx.all_shortest_paths(G,
                                            0,
                                            3,
                                            weight='weight',
                                            method='bellman-ford')))
Пример #49
0
 def setup_class(cls):
     cls.Gi = nx.grid_2d_graph(5, 5)
     cls.Gs = nx.Graph()
     nx.add_path(cls.Gs, "abcdef")
     cls.bigG = nx.grid_2d_graph(25, 25)  # > 500 nodes for sparse
Пример #50
0
def test_ssp_target_missing():
    with pytest.raises(nx.NodeNotFound):
        G = nx.Graph()
        nx.add_path(G, [1, 2, 3])
        list(nx.shortest_simple_paths(G, 1, 4))
Пример #51
0
    def test_add_path(self):
        G = self.G.copy()
        nlist = [12, 13, 14, 15]
        nx.add_path(G, nlist)
        assert_edges_equal(G.edges(nlist), [(12, 13), (13, 14), (14, 15)])
        G = self.G.copy()
        nx.add_path(G, nlist, weight=2.0)
        assert_edges_equal(G.edges(nlist, data=True),
                           [(12, 13, {'weight': 2.}),
                            (13, 14, {'weight': 2.}),
                            (14, 15, {'weight': 2.})])

        G = self.G.copy()
        nlist = [None]
        nx.add_path(G, nlist)
        assert_edges_equal(G.edges(nlist), [])
        assert_nodes_equal(G, list(self.G) + [None])

        G = self.G.copy()
        nlist = iter([None])
        nx.add_path(G, nlist)
        assert_edges_equal(G.edges([None]), [])
        assert_nodes_equal(G, list(self.G) + [None])

        G = self.G.copy()
        nlist = [12]
        nx.add_path(G, nlist)
        assert_edges_equal(G.edges(nlist), [])
        assert_nodes_equal(G, list(self.G) + [12])

        G = self.G.copy()
        nlist = iter([12])
        nx.add_path(G, nlist)
        assert_edges_equal(G.edges([12]), [])
        assert_nodes_equal(G, list(self.G) + [12])

        G = self.G.copy()
        nlist = []
        nx.add_path(G, nlist)
        assert_edges_equal(G.edges, self.G.edges)
        assert_nodes_equal(G, list(self.G))

        G = self.G.copy()
        nlist = iter([])
        nx.add_path(G, nlist)
        assert_edges_equal(G.edges, self.G.edges)
        assert_nodes_equal(G, list(self.G))
Пример #52
0
def test_all_simple_edge_paths_directed():
    G = nx.DiGraph()
    nx.add_path(G, [1, 2, 3])
    nx.add_path(G, [3, 2, 1])
    paths = nx.all_simple_edge_paths(G, 1, 3)
    assert {tuple(p) for p in paths} == {((1, 2), (2, 3))}
Пример #53
0
 def test_digraph_ignore2(self):
     G = nx.DiGraph()
     nx.add_path(G, range(4))
     x = list(edge_dfs(G, [0], orientation="ignore"))
     x_ = [(0, 1, FORWARD), (1, 2, FORWARD), (2, 3, FORWARD)]
     assert x == x_
def test_ssp_source_missing():
    G = nx.Graph()
    nx.add_path(G, [1, 2, 3])
    paths = list(nx.shortest_simple_paths(G, 0, 3))
Пример #55
0
 def test_all_shortest_paths(self):
     G = nx.Graph()
     nx.add_path(G, [0, 1, 2, 3])
     nx.add_path(G, [0, 10, 20, 3])
     assert [[0, 1, 2, 3], [0, 10, 20,
                            3]] == sorted(nx.all_shortest_paths(G, 0, 3))
     # with weights
     G = nx.Graph()
     nx.add_path(G, [0, 1, 2, 3])
     nx.add_path(G, [0, 10, 20, 3])
     assert [[0, 1, 2, 3],
             [0, 10, 20,
              3]] == sorted(nx.all_shortest_paths(G, 0, 3, weight="weight"))
     # weights and method specified
     G = nx.Graph()
     nx.add_path(G, [0, 1, 2, 3])
     nx.add_path(G, [0, 10, 20, 3])
     assert [[0, 1, 2, 3], [0, 10, 20, 3]] == sorted(
         nx.all_shortest_paths(G, 0, 3, weight="weight", method="dijkstra"))
     G = nx.Graph()
     nx.add_path(G, [0, 1, 2, 3])
     nx.add_path(G, [0, 10, 20, 3])
     assert [[0, 1, 2, 3], [0, 10, 20, 3]] == sorted(
         nx.all_shortest_paths(G,
                               0,
                               3,
                               weight="weight",
                               method="bellman-ford"))
def test_ssp_target_missing():
    G = nx.Graph()
    nx.add_path(G, [1, 2, 3])
    paths = list(nx.shortest_simple_paths(G, 1, 4))
Пример #57
0
 def test_digraph2(self):
     G = nx.DiGraph()
     nx.add_path(G, range(4))
     x = list(edge_dfs(G, [0]))
     x_ = [(0, 1), (1, 2), (2, 3)]
     assert x == x_
def test_all_simple_paths_directed():
    G = nx.DiGraph()
    nx.add_path(G, [1, 2, 3])
    nx.add_path(G, [3, 2, 1])
    paths = nx.all_simple_paths(G, 1, 3)
    assert_equal(set(tuple(p) for p in paths), {(1, 2, 3)})
Пример #59
0
 def test_digraph_rev2(self):
     G = nx.DiGraph()
     nx.add_path(G, range(4))
     x = list(edge_dfs(G, [3], orientation="reverse"))
     x_ = [(2, 3, REVERSE), (1, 2, REVERSE), (0, 1, REVERSE)]
     assert x == x_
Пример #60
-1
def test_barbell():
    G = nx.barbell_graph(8, 4)
    nx.add_path(G, [7, 20, 21, 22])
    nx.add_cycle(G, [22, 23, 24, 25])
    pts = set(nx.articulation_points(G))
    assert_equal(pts, {7, 8, 9, 10, 11, 12, 20, 21, 22})

    answer = [
        {12, 13, 14, 15, 16, 17, 18, 19},
        {0, 1, 2, 3, 4, 5, 6, 7},
        {22, 23, 24, 25},
        {11, 12},
        {10, 11},
        {9, 10},
        {8, 9},
        {7, 8},
        {21, 22},
        {20, 21},
        {7, 20},
    ]
    assert_components_equal(list(nx.biconnected_components(G)), answer)

    G.add_edge(2,17)
    pts = set(nx.articulation_points(G))
    assert_equal(pts, {7, 20, 21, 22})