ioftools / networkxMiCe / networkxmaster / networkx / classes / coreviews.py @ 5cef0f13
History  View  Annotate  Download (13.4 KB)
1 
# Copyright (C) 20042019 by


2 
# Aric Hagberg <hagberg@lanl.gov>

3 
# Dan Schult <dschult@colgate.edu>

4 
# Pieter Swart <swart@lanl.gov>

5 
# All rights reserved.

6 
# BSD license.

7 
#

8 
# Authors: Aric Hagberg (hagberg@lanl.gov),

9 
# Pieter Swart (swart@lanl.gov),

10 
# Dan Schult(dschult@colgate.edu)

11 
"""

12 
"""

13 
from collections.abc import Mapping 
14 
import networkx as nx 
15  
16 
__all__ = ['AtlasView', 'AdjacencyView', 'MultiAdjacencyView', 
17 
'UnionAtlas', 'UnionAdjacency', 
18 
'UnionMultiInner', 'UnionMultiAdjacency', 
19 
'FilterAtlas', 'FilterAdjacency', 
20 
'FilterMultiInner', 'FilterMultiAdjacency', 
21 
] 
22  
23  
24 
class AtlasView(Mapping): 
25 
"""An AtlasView is a Readonly Mapping of Mappings.

26 

27 
It is a View into a dictofdict data structure.

28 
The inner level of dict is readwrite. But the

29 
outer level is readonly.

30 

31 
See Also

32 
========

33 
AdjacencyView  View into dictofdictofdict

34 
MultiAdjacencyView  View into dictofdictofdictofdict

35 
"""

36 
__slots__ = ('_atlas',)

37  
38 
def __getstate__(self): 
39 
return {'_atlas': self._atlas} 
40  
41 
def __setstate__(self, state): 
42 
self._atlas = state['_atlas'] 
43  
44 
def __init__(self, d): 
45 
self._atlas = d

46  
47 
def __len__(self): 
48 
return len(self._atlas) 
49  
50 
def __iter__(self): 
51 
return iter(self._atlas) 
52  
53 
def __getitem__(self, key): 
54 
return self._atlas[key] 
55  
56 
def copy(self): 
57 
return {n: self[n].copy() for n in self._atlas} 
58  
59 
def __str__(self): 
60 
return str(self._atlas) # {nbr: self[nbr] for nbr in self}) 
61  
62 
def __repr__(self): 
63 
return '%s(%r)' % (self.__class__.__name__, self._atlas) 
64  
65  
66 
class AdjacencyView(AtlasView): 
67 
"""An AdjacencyView is a Readonly Map of Maps of Maps.

68 

69 
It is a View into a dictofdictofdict data structure.

70 
The inner level of dict is readwrite. But the

71 
outer levels are readonly.

72 

73 
See Also

74 
========

75 
AtlasView  View into dictofdict

76 
MultiAdjacencyView  View into dictofdictofdictofdict

77 
"""

78 
__slots__ = () # Still uses AtlasView slots names _atlas

79  
80 
def __getitem__(self, name): 
81 
return AtlasView(self._atlas[name]) 
82  
83 
def copy(self): 
84 
return {n: self[n].copy() for n in self._atlas} 
85  
86  
87 
class MultiAdjacencyView(AdjacencyView): 
88 
"""An MultiAdjacencyView is a Readonly Map of Maps of Maps of Maps.

89 

90 
It is a View into a dictofdictofdictofdict data structure.

91 
The inner level of dict is readwrite. But the

92 
outer levels are readonly.

93 

94 
See Also

95 
========

96 
AtlasView  View into dictofdict

97 
AdjacencyView  View into dictofdictofdict

98 
"""

99 
__slots__ = () # Still uses AtlasView slots names _atlas

100  
101 
def __getitem__(self, name): 
102 
return AdjacencyView(self._atlas[name]) 
103  
104 
def copy(self): 
105 
return {n: self[n].copy() for n in self._atlas} 
106  
107  
108 
class UnionAtlas(Mapping): 
109 
"""A readonly union of two atlases (dictofdict).

110 

111 
The two dictofdicts represent the inner dict of

112 
an Adjacency: `G.succ[node]` and `G.pred[node]`.

113 
The inner level of dict of both hold attribute key:value

114 
pairs and is readwrite. But the outer level is readonly.

115 

116 
See Also

117 
========

118 
UnionAdjacency  View into dictofdictofdict

119 
UnionMultiAdjacency  View into dictofdictofdictofdict

120 
"""

121 
__slots__ = ('_succ', '_pred') 
122  
123 
def __getstate__(self): 
124 
return {'_succ': self._succ, '_pred': self._pred} 
125  
126 
def __setstate__(self, state): 
127 
self._succ = state['_succ'] 
128 
self._pred = state['_pred'] 
129  
130 
def __init__(self, succ, pred): 
131 
self._succ = succ

132 
self._pred = pred

133  
134 
def __len__(self): 
135 
return len(self._succ) + len(self._pred) 
136  
137 
def __iter__(self): 
138 
return iter(set(self._succ.keys())  set(self._pred.keys())) 
139  
140 
def __getitem__(self, key): 
141 
try:

142 
return self._succ[key] 
143 
except KeyError: 
144 
return self._pred[key] 
145  
146 
def copy(self): 
147 
result = {nbr: dd.copy() for nbr, dd in self._succ.items()} 
148 
for nbr, dd in self._pred.items(): 
149 
if nbr in result: 
150 
result[nbr].update(dd) 
151 
else:

152 
result[nbr] = dd.copy() 
153 
return result

154  
155 
def __str__(self): 
156 
return str({nbr: self[nbr] for nbr in self}) 
157  
158 
def __repr__(self): 
159 
return '%s(%r, %r)' % (self.__class__.__name__, self._succ, self._pred) 
160  
161  
162 
class UnionAdjacency(Mapping): 
163 
"""A readonly union of dict Adjacencies as a Map of Maps of Maps.

164 

165 
The two input dictofdictofdicts represent the union of

166 
`G.succ` and `G.pred`. Return values are UnionAtlas

167 
The inner level of dict is readwrite. But the

168 
middle and outer levels are readonly.

169 

170 
succ : a dictofdictofdict {node: nbrdict}

171 
pred : a dictofdictofdict {node: nbrdict}

172 
The keys for the two dicts should be the same

173 

174 
See Also

175 
========

176 
UnionAtlas  View into dictofdict

177 
UnionMultiAdjacency  View into dictofdictofdictofdict

178 
"""

179 
__slots__ = ('_succ', '_pred') 
180  
181 
def __getstate__(self): 
182 
return {'_succ': self._succ, '_pred': self._pred} 
183  
184 
def __setstate__(self, state): 
185 
self._succ = state['_succ'] 
186 
self._pred = state['_pred'] 
187  
188 
def __init__(self, succ, pred): 
189 
# keys must be the same for two input dicts

190 
assert(len(set(succ.keys()) ^ set(pred.keys())) == 0) 
191 
self._succ = succ

192 
self._pred = pred

193  
194 
def __len__(self): 
195 
return len(self._succ) # length of each dict should be the same 
196  
197 
def __iter__(self): 
198 
return iter(self._succ) 
199  
200 
def __getitem__(self, nbr): 
201 
return UnionAtlas(self._succ[nbr], self._pred[nbr]) 
202  
203 
def copy(self): 
204 
return {n: self[n].copy() for n in self._succ} 
205  
206 
def __str__(self): 
207 
return str({nbr: self[nbr] for nbr in self}) 
208  
209 
def __repr__(self): 
210 
return '%s(%r, %r)' % (self.__class__.__name__, self._succ, self._pred) 
211  
212  
213 
class UnionMultiInner(UnionAtlas): 
214 
"""A readonly union of two inner dicts of MultiAdjacencies.

215 

216 
The two input dictofdictofdicts represent the union of

217 
`G.succ[node]` and `G.pred[node]` for MultiDiGraphs.

218 
Return values are UnionAtlas.

219 
The inner level of dict is readwrite. But the outer levels are readonly.

220 

221 
See Also

222 
========

223 
UnionAtlas  View into dictofdict

224 
UnionAdjacency  View into dictofdictofdict

225 
UnionMultiAdjacency  View into dictofdictofdictofdict

226 
"""

227 
__slots__ = () # Still uses UnionAtlas slots names _succ, _pred

228  
229 
def __getitem__(self, node): 
230 
in_succ = node in self._succ 
231 
in_pred = node in self._pred 
232 
if in_succ:

233 
if in_pred:

234 
return UnionAtlas(self._succ[node], self._pred[node]) 
235 
return UnionAtlas(self._succ[node], {}) 
236 
return UnionAtlas({}, self._pred[node]) 
237  
238 
def copy(self): 
239 
nodes = set(self._succ.keys())  set(self._pred.keys()) 
240 
return {n: self[n].copy() for n in nodes} 
241  
242  
243 
class UnionMultiAdjacency(UnionAdjacency): 
244 
"""A readonly union of two dict MultiAdjacencies.

245 

246 
The two input dictofdictofdictofdicts represent the union of

247 
`G.succ` and `G.pred` for MultiDiGraphs. Return values are UnionAdjacency.

248 
The inner level of dict is readwrite. But the outer levels are readonly.

249 

250 
See Also

251 
========

252 
UnionAtlas  View into dictofdict

253 
UnionMultiInner  View into dictofdictofdict

254 
"""

255 
__slots__ = () # Still uses UnionAdjacency slots names _succ, _pred

256  
257 
def __getitem__(self, node): 
258 
return UnionMultiInner(self._succ[node], self._pred[node]) 
259  
260  
261 
class FilterAtlas(Mapping): # nodedict, nbrdict, keydict 
262 
def __init__(self, d, NODE_OK): 
263 
self._atlas = d

264 
self.NODE_OK = NODE_OK

265  
266 
def __len__(self): 
267 
return sum(1 for n in self) 
268  
269 
def __iter__(self): 
270 
try: # check that NODE_OK has attr 'nodes' 
271 
node_ok_shorter = 2 * len(self.NODE_OK.nodes) < len(self._atlas) 
272 
except AttributeError: 
273 
node_ok_shorter = False

274 
if node_ok_shorter:

275 
return (n for n in self.NODE_OK.nodes if n in self._atlas) 
276 
return (n for n in self._atlas if self.NODE_OK(n)) 
277  
278 
def __getitem__(self, key): 
279 
if key in self._atlas and self.NODE_OK(key): 
280 
return self._atlas[key] 
281 
raise KeyError("Key {} not found".format(key)) 
282  
283 
def copy(self): 
284 
try: # check that NODE_OK has attr 'nodes' 
285 
node_ok_shorter = 2 * len(self.NODE_OK.nodes) < len(self._atlas) 
286 
except AttributeError: 
287 
node_ok_shorter = False

288 
if node_ok_shorter:

289 
return {u: self._atlas[u] for u in self.NODE_OK.nodes 
290 
if u in self._atlas} 
291 
return {u: d for u, d in self._atlas.items() 
292 
if self.NODE_OK(u)} 
293  
294 
def __str__(self): 
295 
return str({nbr: self[nbr] for nbr in self}) 
296  
297 
def __repr__(self): 
298 
return '%s(%r, %r)' % (self.__class__.__name__, self._atlas, 
299 
self.NODE_OK)

300  
301  
302 
class FilterAdjacency(Mapping): # edgedict 
303 
def __init__(self, d, NODE_OK, EDGE_OK): 
304 
self._atlas = d

305 
self.NODE_OK = NODE_OK

306 
self.EDGE_OK = EDGE_OK

307  
308 
def __len__(self): 
309 
return sum(1 for n in self) 
310  
311 
def __iter__(self): 
312 
try: # check that NODE_OK has attr 'nodes' 
313 
node_ok_shorter = 2 * len(self.NODE_OK.nodes) < len(self._atlas) 
314 
except AttributeError: 
315 
node_ok_shorter = False

316 
if node_ok_shorter:

317 
return (n for n in self.NODE_OK.nodes if n in self._atlas) 
318 
return (n for n in self._atlas if self.NODE_OK(n)) 
319  
320 
def __getitem__(self, node): 
321 
if node in self._atlas and self.NODE_OK(node): 
322 
def new_node_ok(nbr): 
323 
return self.NODE_OK(nbr) and self.EDGE_OK(node, nbr) 
324 
return FilterAtlas(self._atlas[node], new_node_ok) 
325 
raise KeyError("Key {} not found".format(node)) 
326  
327 
def copy(self): 
328 
try: # check that NODE_OK has attr 'nodes' 
329 
node_ok_shorter = 2 * len(self.NODE_OK.nodes) < len(self._atlas) 
330 
except AttributeError: 
331 
node_ok_shorter = False

332 
if node_ok_shorter:

333 
return {u: {v: d for v, d in self._atlas[u].items() 
334 
if self.NODE_OK(v) if self.EDGE_OK(u, v)} 
335 
for u in self.NODE_OK.nodes if u in self._atlas} 
336 
return {u: {v: d for v, d in nbrs.items() if self.NODE_OK(v) 
337 
if self.EDGE_OK(u, v)} 
338 
for u, nbrs in self._atlas.items() 
339 
if self.NODE_OK(u)} 
340  
341 
def __str__(self): 
342 
return str({nbr: self[nbr] for nbr in self}) 
343  
344 
def __repr__(self): 
345 
return '%s(%r, %r, %r)' % (self.__class__.__name__, self._atlas, 
346 
self.NODE_OK, self.EDGE_OK) 
347  
348  
349 
class FilterMultiInner(FilterAdjacency): # muliedge_seconddict 
350 
def __iter__(self): 
351 
try: # check that NODE_OK has attr 'nodes' 
352 
node_ok_shorter = 2 * len(self.NODE_OK.nodes) < len(self._atlas) 
353 
except AttributeError: 
354 
node_ok_shorter = False

355 
if node_ok_shorter:

356 
my_nodes = (n for n in self.NODE_OK.nodes if n in self._atlas) 
357 
else:

358 
my_nodes = (n for n in self._atlas if self.NODE_OK(n)) 
359 
for n in my_nodes: 
360 
some_keys_ok = False

361 
for key in self._atlas[n]: 
362 
if self.EDGE_OK(n, key): 
363 
some_keys_ok = True

364 
break

365 
if some_keys_ok is True: 
366 
yield n

367  
368 
def __getitem__(self, nbr): 
369 
if nbr in self._atlas and self.NODE_OK(nbr): 
370 
def new_node_ok(key): 
371 
return self.EDGE_OK(nbr, key) 
372 
return FilterAtlas(self._atlas[nbr], new_node_ok) 
373 
raise KeyError("Key {} not found".format(nbr)) 
374  
375 
def copy(self): 
376 
try: # check that NODE_OK has attr 'nodes' 
377 
node_ok_shorter = 2 * len(self.NODE_OK.nodes) < len(self._atlas) 
378 
except AttributeError: 
379 
node_ok_shorter = False

380 
if node_ok_shorter:

381 
return {v: {k: d for k, d in self._atlas[v].items() 
382 
if self.EDGE_OK(v, k)} 
383 
for v in self.NODE_OK.nodes if v in self._atlas} 
384 
return {v: {k: d for k, d in nbrs.items() if self.EDGE_OK(v, k)} 
385 
for v, nbrs in self._atlas.items() if self.NODE_OK(v)} 
386  
387  
388 
class FilterMultiAdjacency(FilterAdjacency): # multiedgedict 
389 
def __getitem__(self, node): 
390 
if node in self._atlas and self.NODE_OK(node): 
391 
def edge_ok(nbr, key): 
392 
return self.NODE_OK(nbr) and self.EDGE_OK(node, nbr, key) 
393 
return FilterMultiInner(self._atlas[node], self.NODE_OK, edge_ok) 
394 
raise KeyError("Key {} not found".format(node)) 
395  
396 
def copy(self): 
397 
try: # check that NODE_OK has attr 'nodes' 
398 
node_ok_shorter = 2 * len(self.NODE_OK.nodes) < len(self._atlas) 
399 
except AttributeError: 
400 
node_ok_shorter = False

401 
if node_ok_shorter:

402 
my_nodes = self.NODE_OK.nodes

403 
return {u: {v: {k: d for k, d in kd.items() 
404 
if self.EDGE_OK(u, v, k)} 
405 
for v, kd in self._atlas[u].items() if v in my_nodes} 
406 
for u in my_nodes if u in self._atlas} 
407 
return {u: {v: {k: d for k, d in kd.items() 
408 
if self.EDGE_OK(u, v, k)} 
409 
for v, kd in nbrs.items() if self.NODE_OK(v)} 
410 
for u, nbrs in self._atlas.items() if self.NODE_OK(u)} 