Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/networkx/algorithms/hybrid.py: 9%
76 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-10-20 07:00 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-10-20 07:00 +0000
1"""
2Provides functions for finding and testing for locally `(k, l)`-connected
3graphs.
5"""
6import copy
8import networkx as nx
10__all__ = ["kl_connected_subgraph", "is_kl_connected"]
13@nx._dispatch
14def kl_connected_subgraph(G, k, l, low_memory=False, same_as_graph=False):
15 """Returns the maximum locally `(k, l)`-connected subgraph of `G`.
17 A graph is locally `(k, l)`-connected if for each edge `(u, v)` in the
18 graph there are at least `l` edge-disjoint paths of length at most `k`
19 joining `u` to `v`.
21 Parameters
22 ----------
23 G : NetworkX graph
24 The graph in which to find a maximum locally `(k, l)`-connected
25 subgraph.
27 k : integer
28 The maximum length of paths to consider. A higher number means a looser
29 connectivity requirement.
31 l : integer
32 The number of edge-disjoint paths. A higher number means a stricter
33 connectivity requirement.
35 low_memory : bool
36 If this is True, this function uses an algorithm that uses slightly
37 more time but less memory.
39 same_as_graph : bool
40 If True then return a tuple of the form `(H, is_same)`,
41 where `H` is the maximum locally `(k, l)`-connected subgraph and
42 `is_same` is a Boolean representing whether `G` is locally `(k,
43 l)`-connected (and hence, whether `H` is simply a copy of the input
44 graph `G`).
46 Returns
47 -------
48 NetworkX graph or two-tuple
49 If `same_as_graph` is True, then this function returns a
50 two-tuple as described above. Otherwise, it returns only the maximum
51 locally `(k, l)`-connected subgraph.
53 See also
54 --------
55 is_kl_connected
57 References
58 ----------
59 .. [1] Chung, Fan and Linyuan Lu. "The Small World Phenomenon in Hybrid
60 Power Law Graphs." *Complex Networks*. Springer Berlin Heidelberg,
61 2004. 89--104.
63 """
64 H = copy.deepcopy(G) # subgraph we construct by removing from G
66 graphOK = True
67 deleted_some = True # hack to start off the while loop
68 while deleted_some:
69 deleted_some = False
70 # We use `for edge in list(H.edges()):` instead of
71 # `for edge in H.edges():` because we edit the graph `H` in
72 # the loop. Hence using an iterator will result in
73 # `RuntimeError: dictionary changed size during iteration`
74 for edge in list(H.edges()):
75 (u, v) = edge
76 # Get copy of graph needed for this search
77 if low_memory:
78 verts = {u, v}
79 for i in range(k):
80 for w in verts.copy():
81 verts.update(G[w])
82 G2 = G.subgraph(verts).copy()
83 else:
84 G2 = copy.deepcopy(G)
85 ###
86 path = [u, v]
87 cnt = 0
88 accept = 0
89 while path:
90 cnt += 1 # Found a path
91 if cnt >= l:
92 accept = 1
93 break
94 # record edges along this graph
95 prev = u
96 for w in path:
97 if prev != w:
98 G2.remove_edge(prev, w)
99 prev = w
100 # path = shortest_path(G2, u, v, k) # ??? should "Cutoff" be k+1?
101 try:
102 path = nx.shortest_path(G2, u, v) # ??? should "Cutoff" be k+1?
103 except nx.NetworkXNoPath:
104 path = False
105 # No Other Paths
106 if accept == 0:
107 H.remove_edge(u, v)
108 deleted_some = True
109 if graphOK:
110 graphOK = False
111 # We looked through all edges and removed none of them.
112 # So, H is the maximal (k,l)-connected subgraph of G
113 if same_as_graph:
114 return (H, graphOK)
115 return H
118@nx._dispatch
119def is_kl_connected(G, k, l, low_memory=False):
120 """Returns True if and only if `G` is locally `(k, l)`-connected.
122 A graph is locally `(k, l)`-connected if for each edge `(u, v)` in the
123 graph there are at least `l` edge-disjoint paths of length at most `k`
124 joining `u` to `v`.
126 Parameters
127 ----------
128 G : NetworkX graph
129 The graph to test for local `(k, l)`-connectedness.
131 k : integer
132 The maximum length of paths to consider. A higher number means a looser
133 connectivity requirement.
135 l : integer
136 The number of edge-disjoint paths. A higher number means a stricter
137 connectivity requirement.
139 low_memory : bool
140 If this is True, this function uses an algorithm that uses slightly
141 more time but less memory.
143 Returns
144 -------
145 bool
146 Whether the graph is locally `(k, l)`-connected subgraph.
148 See also
149 --------
150 kl_connected_subgraph
152 References
153 ----------
154 .. [1] Chung, Fan and Linyuan Lu. "The Small World Phenomenon in Hybrid
155 Power Law Graphs." *Complex Networks*. Springer Berlin Heidelberg,
156 2004. 89--104.
158 """
159 graphOK = True
160 for edge in G.edges():
161 (u, v) = edge
162 # Get copy of graph needed for this search
163 if low_memory:
164 verts = {u, v}
165 for i in range(k):
166 [verts.update(G.neighbors(w)) for w in verts.copy()]
167 G2 = G.subgraph(verts)
168 else:
169 G2 = copy.deepcopy(G)
170 ###
171 path = [u, v]
172 cnt = 0
173 accept = 0
174 while path:
175 cnt += 1 # Found a path
176 if cnt >= l:
177 accept = 1
178 break
179 # record edges along this graph
180 prev = u
181 for w in path:
182 if w != prev:
183 G2.remove_edge(prev, w)
184 prev = w
185 # path = shortest_path(G2, u, v, k) # ??? should "Cutoff" be k+1?
186 try:
187 path = nx.shortest_path(G2, u, v) # ??? should "Cutoff" be k+1?
188 except nx.NetworkXNoPath:
189 path = False
190 # No Other Paths
191 if accept == 0:
192 graphOK = False
193 break
194 # return status
195 return graphOK