This repository has been archived on 2023-03-25. You can view files and clone it, but cannot push or open issues or pull requests.
mightyscape-1.1-deprecated/extensions/networkx/classes/coreviews.py
2020-07-30 01:16:18 +02:00

411 lines
13 KiB
Python

# Copyright (C) 2004-2019 by
# Aric Hagberg <hagberg@lanl.gov>
# Dan Schult <dschult@colgate.edu>
# Pieter Swart <swart@lanl.gov>
# All rights reserved.
# BSD license.
#
# Authors: Aric Hagberg (hagberg@lanl.gov),
# Pieter Swart (swart@lanl.gov),
# Dan Schult(dschult@colgate.edu)
"""
"""
from collections.abc import Mapping
import networkx as nx
__all__ = ['AtlasView', 'AdjacencyView', 'MultiAdjacencyView',
'UnionAtlas', 'UnionAdjacency',
'UnionMultiInner', 'UnionMultiAdjacency',
'FilterAtlas', 'FilterAdjacency',
'FilterMultiInner', 'FilterMultiAdjacency',
]
class AtlasView(Mapping):
"""An AtlasView is a Read-only Mapping of Mappings.
It is a View into a dict-of-dict data structure.
The inner level of dict is read-write. But the
outer level is read-only.
See Also
========
AdjacencyView - View into dict-of-dict-of-dict
MultiAdjacencyView - View into dict-of-dict-of-dict-of-dict
"""
__slots__ = ('_atlas',)
def __getstate__(self):
return {'_atlas': self._atlas}
def __setstate__(self, state):
self._atlas = state['_atlas']
def __init__(self, d):
self._atlas = d
def __len__(self):
return len(self._atlas)
def __iter__(self):
return iter(self._atlas)
def __getitem__(self, key):
return self._atlas[key]
def copy(self):
return {n: self[n].copy() for n in self._atlas}
def __str__(self):
return str(self._atlas) # {nbr: self[nbr] for nbr in self})
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, self._atlas)
class AdjacencyView(AtlasView):
"""An AdjacencyView is a Read-only Map of Maps of Maps.
It is a View into a dict-of-dict-of-dict data structure.
The inner level of dict is read-write. But the
outer levels are read-only.
See Also
========
AtlasView - View into dict-of-dict
MultiAdjacencyView - View into dict-of-dict-of-dict-of-dict
"""
__slots__ = () # Still uses AtlasView slots names _atlas
def __getitem__(self, name):
return AtlasView(self._atlas[name])
def copy(self):
return {n: self[n].copy() for n in self._atlas}
class MultiAdjacencyView(AdjacencyView):
"""An MultiAdjacencyView is a Read-only Map of Maps of Maps of Maps.
It is a View into a dict-of-dict-of-dict-of-dict data structure.
The inner level of dict is read-write. But the
outer levels are read-only.
See Also
========
AtlasView - View into dict-of-dict
AdjacencyView - View into dict-of-dict-of-dict
"""
__slots__ = () # Still uses AtlasView slots names _atlas
def __getitem__(self, name):
return AdjacencyView(self._atlas[name])
def copy(self):
return {n: self[n].copy() for n in self._atlas}
class UnionAtlas(Mapping):
"""A read-only union of two atlases (dict-of-dict).
The two dict-of-dicts represent the inner dict of
an Adjacency: `G.succ[node]` and `G.pred[node]`.
The inner level of dict of both hold attribute key:value
pairs and is read-write. But the outer level is read-only.
See Also
========
UnionAdjacency - View into dict-of-dict-of-dict
UnionMultiAdjacency - View into dict-of-dict-of-dict-of-dict
"""
__slots__ = ('_succ', '_pred')
def __getstate__(self):
return {'_succ': self._succ, '_pred': self._pred}
def __setstate__(self, state):
self._succ = state['_succ']
self._pred = state['_pred']
def __init__(self, succ, pred):
self._succ = succ
self._pred = pred
def __len__(self):
return len(self._succ) + len(self._pred)
def __iter__(self):
return iter(set(self._succ.keys()) | set(self._pred.keys()))
def __getitem__(self, key):
try:
return self._succ[key]
except KeyError:
return self._pred[key]
def copy(self):
result = {nbr: dd.copy() for nbr, dd in self._succ.items()}
for nbr, dd in self._pred.items():
if nbr in result:
result[nbr].update(dd)
else:
result[nbr] = dd.copy()
return result
def __str__(self):
return str({nbr: self[nbr] for nbr in self})
def __repr__(self):
return '%s(%r, %r)' % (self.__class__.__name__, self._succ, self._pred)
class UnionAdjacency(Mapping):
"""A read-only union of dict Adjacencies as a Map of Maps of Maps.
The two input dict-of-dict-of-dicts represent the union of
`G.succ` and `G.pred`. Return values are UnionAtlas
The inner level of dict is read-write. But the
middle and outer levels are read-only.
succ : a dict-of-dict-of-dict {node: nbrdict}
pred : a dict-of-dict-of-dict {node: nbrdict}
The keys for the two dicts should be the same
See Also
========
UnionAtlas - View into dict-of-dict
UnionMultiAdjacency - View into dict-of-dict-of-dict-of-dict
"""
__slots__ = ('_succ', '_pred')
def __getstate__(self):
return {'_succ': self._succ, '_pred': self._pred}
def __setstate__(self, state):
self._succ = state['_succ']
self._pred = state['_pred']
def __init__(self, succ, pred):
# keys must be the same for two input dicts
assert(len(set(succ.keys()) ^ set(pred.keys())) == 0)
self._succ = succ
self._pred = pred
def __len__(self):
return len(self._succ) # length of each dict should be the same
def __iter__(self):
return iter(self._succ)
def __getitem__(self, nbr):
return UnionAtlas(self._succ[nbr], self._pred[nbr])
def copy(self):
return {n: self[n].copy() for n in self._succ}
def __str__(self):
return str({nbr: self[nbr] for nbr in self})
def __repr__(self):
return '%s(%r, %r)' % (self.__class__.__name__, self._succ, self._pred)
class UnionMultiInner(UnionAtlas):
"""A read-only union of two inner dicts of MultiAdjacencies.
The two input dict-of-dict-of-dicts represent the union of
`G.succ[node]` and `G.pred[node]` for MultiDiGraphs.
Return values are UnionAtlas.
The inner level of dict is read-write. But the outer levels are read-only.
See Also
========
UnionAtlas - View into dict-of-dict
UnionAdjacency - View into dict-of-dict-of-dict
UnionMultiAdjacency - View into dict-of-dict-of-dict-of-dict
"""
__slots__ = () # Still uses UnionAtlas slots names _succ, _pred
def __getitem__(self, node):
in_succ = node in self._succ
in_pred = node in self._pred
if in_succ:
if in_pred:
return UnionAtlas(self._succ[node], self._pred[node])
return UnionAtlas(self._succ[node], {})
return UnionAtlas({}, self._pred[node])
def copy(self):
nodes = set(self._succ.keys()) | set(self._pred.keys())
return {n: self[n].copy() for n in nodes}
class UnionMultiAdjacency(UnionAdjacency):
"""A read-only union of two dict MultiAdjacencies.
The two input dict-of-dict-of-dict-of-dicts represent the union of
`G.succ` and `G.pred` for MultiDiGraphs. Return values are UnionAdjacency.
The inner level of dict is read-write. But the outer levels are read-only.
See Also
========
UnionAtlas - View into dict-of-dict
UnionMultiInner - View into dict-of-dict-of-dict
"""
__slots__ = () # Still uses UnionAdjacency slots names _succ, _pred
def __getitem__(self, node):
return UnionMultiInner(self._succ[node], self._pred[node])
class FilterAtlas(Mapping): # nodedict, nbrdict, keydict
def __init__(self, d, NODE_OK):
self._atlas = d
self.NODE_OK = NODE_OK
def __len__(self):
return sum(1 for n in self)
def __iter__(self):
try: # check that NODE_OK has attr 'nodes'
node_ok_shorter = 2 * len(self.NODE_OK.nodes) < len(self._atlas)
except AttributeError:
node_ok_shorter = False
if node_ok_shorter:
return (n for n in self.NODE_OK.nodes if n in self._atlas)
return (n for n in self._atlas if self.NODE_OK(n))
def __getitem__(self, key):
if key in self._atlas and self.NODE_OK(key):
return self._atlas[key]
raise KeyError("Key {} not found".format(key))
def copy(self):
try: # check that NODE_OK has attr 'nodes'
node_ok_shorter = 2 * len(self.NODE_OK.nodes) < len(self._atlas)
except AttributeError:
node_ok_shorter = False
if node_ok_shorter:
return {u: self._atlas[u] for u in self.NODE_OK.nodes
if u in self._atlas}
return {u: d for u, d in self._atlas.items()
if self.NODE_OK(u)}
def __str__(self):
return str({nbr: self[nbr] for nbr in self})
def __repr__(self):
return '%s(%r, %r)' % (self.__class__.__name__, self._atlas,
self.NODE_OK)
class FilterAdjacency(Mapping): # edgedict
def __init__(self, d, NODE_OK, EDGE_OK):
self._atlas = d
self.NODE_OK = NODE_OK
self.EDGE_OK = EDGE_OK
def __len__(self):
return sum(1 for n in self)
def __iter__(self):
try: # check that NODE_OK has attr 'nodes'
node_ok_shorter = 2 * len(self.NODE_OK.nodes) < len(self._atlas)
except AttributeError:
node_ok_shorter = False
if node_ok_shorter:
return (n for n in self.NODE_OK.nodes if n in self._atlas)
return (n for n in self._atlas if self.NODE_OK(n))
def __getitem__(self, node):
if node in self._atlas and self.NODE_OK(node):
def new_node_ok(nbr):
return self.NODE_OK(nbr) and self.EDGE_OK(node, nbr)
return FilterAtlas(self._atlas[node], new_node_ok)
raise KeyError("Key {} not found".format(node))
def copy(self):
try: # check that NODE_OK has attr 'nodes'
node_ok_shorter = 2 * len(self.NODE_OK.nodes) < len(self._atlas)
except AttributeError:
node_ok_shorter = False
if node_ok_shorter:
return {u: {v: d for v, d in self._atlas[u].items()
if self.NODE_OK(v) if self.EDGE_OK(u, v)}
for u in self.NODE_OK.nodes if u in self._atlas}
return {u: {v: d for v, d in nbrs.items() if self.NODE_OK(v)
if self.EDGE_OK(u, v)}
for u, nbrs in self._atlas.items()
if self.NODE_OK(u)}
def __str__(self):
return str({nbr: self[nbr] for nbr in self})
def __repr__(self):
return '%s(%r, %r, %r)' % (self.__class__.__name__, self._atlas,
self.NODE_OK, self.EDGE_OK)
class FilterMultiInner(FilterAdjacency): # muliedge_seconddict
def __iter__(self):
try: # check that NODE_OK has attr 'nodes'
node_ok_shorter = 2 * len(self.NODE_OK.nodes) < len(self._atlas)
except AttributeError:
node_ok_shorter = False
if node_ok_shorter:
my_nodes = (n for n in self.NODE_OK.nodes if n in self._atlas)
else:
my_nodes = (n for n in self._atlas if self.NODE_OK(n))
for n in my_nodes:
some_keys_ok = False
for key in self._atlas[n]:
if self.EDGE_OK(n, key):
some_keys_ok = True
break
if some_keys_ok is True:
yield n
def __getitem__(self, nbr):
if nbr in self._atlas and self.NODE_OK(nbr):
def new_node_ok(key):
return self.EDGE_OK(nbr, key)
return FilterAtlas(self._atlas[nbr], new_node_ok)
raise KeyError("Key {} not found".format(nbr))
def copy(self):
try: # check that NODE_OK has attr 'nodes'
node_ok_shorter = 2 * len(self.NODE_OK.nodes) < len(self._atlas)
except AttributeError:
node_ok_shorter = False
if node_ok_shorter:
return {v: {k: d for k, d in self._atlas[v].items()
if self.EDGE_OK(v, k)}
for v in self.NODE_OK.nodes if v in self._atlas}
return {v: {k: d for k, d in nbrs.items() if self.EDGE_OK(v, k)}
for v, nbrs in self._atlas.items() if self.NODE_OK(v)}
class FilterMultiAdjacency(FilterAdjacency): # multiedgedict
def __getitem__(self, node):
if node in self._atlas and self.NODE_OK(node):
def edge_ok(nbr, key):
return self.NODE_OK(nbr) and self.EDGE_OK(node, nbr, key)
return FilterMultiInner(self._atlas[node], self.NODE_OK, edge_ok)
raise KeyError("Key {} not found".format(node))
def copy(self):
try: # check that NODE_OK has attr 'nodes'
node_ok_shorter = 2 * len(self.NODE_OK.nodes) < len(self._atlas)
except AttributeError:
node_ok_shorter = False
if node_ok_shorter:
my_nodes = self.NODE_OK.nodes
return {u: {v: {k: d for k, d in kd.items()
if self.EDGE_OK(u, v, k)}
for v, kd in self._atlas[u].items() if v in my_nodes}
for u in my_nodes if u in self._atlas}
return {u: {v: {k: d for k, d in kd.items()
if self.EDGE_OK(u, v, k)}
for v, kd in nbrs.items() if self.NODE_OK(v)}
for u, nbrs in self._atlas.items() if self.NODE_OK(u)}