Fixed database typo and removed unnecessary class identifier.
This commit is contained in:
parent
00ad49a143
commit
45fb349a7d
5098 changed files with 952558 additions and 85 deletions
191
venv/share/doc/networkx-2.5/examples/subclass/plot_antigraph.py
Normal file
191
venv/share/doc/networkx-2.5/examples/subclass/plot_antigraph.py
Normal file
|
@ -0,0 +1,191 @@
|
|||
"""
|
||||
=========
|
||||
Antigraph
|
||||
=========
|
||||
|
||||
Complement graph class for small footprint when working on dense graphs.
|
||||
|
||||
This class allows you to add the edges that *do not exist* in the dense
|
||||
graph. However, when applying algorithms to this complement graph data
|
||||
structure, it behaves as if it were the dense version. So it can be used
|
||||
directly in several NetworkX algorithms.
|
||||
|
||||
This subclass has only been tested for k-core, connected_components,
|
||||
and biconnected_components algorithms but might also work for other
|
||||
algorithms.
|
||||
|
||||
"""
|
||||
import networkx as nx
|
||||
from networkx.exception import NetworkXError
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
|
||||
class AntiGraph(nx.Graph):
|
||||
"""
|
||||
Class for complement graphs.
|
||||
|
||||
The main goal is to be able to work with big and dense graphs with
|
||||
a low memory footprint.
|
||||
|
||||
In this class you add the edges that *do not exist* in the dense graph,
|
||||
the report methods of the class return the neighbors, the edges and
|
||||
the degree as if it was the dense graph. Thus it's possible to use
|
||||
an instance of this class with some of NetworkX functions.
|
||||
"""
|
||||
|
||||
all_edge_dict = {"weight": 1}
|
||||
|
||||
def single_edge_dict(self):
|
||||
return self.all_edge_dict
|
||||
|
||||
edge_attr_dict_factory = single_edge_dict
|
||||
|
||||
def __getitem__(self, n):
|
||||
"""Return a dict of neighbors of node n in the dense graph.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
n : node
|
||||
A node in the graph.
|
||||
|
||||
Returns
|
||||
-------
|
||||
adj_dict : dictionary
|
||||
The adjacency dictionary for nodes connected to n.
|
||||
|
||||
"""
|
||||
return {
|
||||
node: self.all_edge_dict for node in set(self.adj) - set(self.adj[n]) - {n}
|
||||
}
|
||||
|
||||
def neighbors(self, n):
|
||||
"""Return an iterator over all neighbors of node n in the
|
||||
dense graph.
|
||||
|
||||
"""
|
||||
try:
|
||||
return iter(set(self.adj) - set(self.adj[n]) - {n})
|
||||
except KeyError as e:
|
||||
raise NetworkXError(f"The node {n} is not in the graph.") from e
|
||||
|
||||
def degree(self, nbunch=None, weight=None):
|
||||
"""Return an iterator for (node, degree) in the dense graph.
|
||||
|
||||
The node degree is the number of edges adjacent to the node.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
nbunch : iterable container, optional (default=all nodes)
|
||||
A container of nodes. The container will be iterated
|
||||
through once.
|
||||
|
||||
weight : string or None, optional (default=None)
|
||||
The edge attribute that holds the numerical value used
|
||||
as a weight. If None, then each edge has weight 1.
|
||||
The degree is the sum of the edge weights adjacent to the node.
|
||||
|
||||
Returns
|
||||
-------
|
||||
nd_iter : iterator
|
||||
The iterator returns two-tuples of (node, degree).
|
||||
|
||||
See Also
|
||||
--------
|
||||
degree
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> G = nx.path_graph(4) # or DiGraph, MultiGraph, MultiDiGraph, etc
|
||||
>>> list(G.degree(0)) # node 0 with degree 1
|
||||
[(0, 1)]
|
||||
>>> list(G.degree([0, 1]))
|
||||
[(0, 1), (1, 2)]
|
||||
|
||||
"""
|
||||
if nbunch is None:
|
||||
nodes_nbrs = (
|
||||
(
|
||||
n,
|
||||
{
|
||||
v: self.all_edge_dict
|
||||
for v in set(self.adj) - set(self.adj[n]) - {n}
|
||||
},
|
||||
)
|
||||
for n in self.nodes()
|
||||
)
|
||||
elif nbunch in self:
|
||||
nbrs = set(self.nodes()) - set(self.adj[nbunch]) - {nbunch}
|
||||
return len(nbrs)
|
||||
else:
|
||||
nodes_nbrs = (
|
||||
(
|
||||
n,
|
||||
{
|
||||
v: self.all_edge_dict
|
||||
for v in set(self.nodes()) - set(self.adj[n]) - {n}
|
||||
},
|
||||
)
|
||||
for n in self.nbunch_iter(nbunch)
|
||||
)
|
||||
|
||||
if weight is None:
|
||||
return ((n, len(nbrs)) for n, nbrs in nodes_nbrs)
|
||||
else:
|
||||
# AntiGraph is a ThinGraph so all edges have weight 1
|
||||
return (
|
||||
(n, sum((nbrs[nbr].get(weight, 1)) for nbr in nbrs))
|
||||
for n, nbrs in nodes_nbrs
|
||||
)
|
||||
|
||||
def adjacency_iter(self):
|
||||
"""Return an iterator of (node, adjacency set) tuples for all nodes
|
||||
in the dense graph.
|
||||
|
||||
This is the fastest way to look at every edge.
|
||||
For directed graphs, only outgoing adjacencies are included.
|
||||
|
||||
Returns
|
||||
-------
|
||||
adj_iter : iterator
|
||||
An iterator of (node, adjacency set) for all nodes in
|
||||
the graph.
|
||||
|
||||
"""
|
||||
for n in self.adj:
|
||||
yield (n, set(self.adj) - set(self.adj[n]) - {n})
|
||||
|
||||
|
||||
# Build several pairs of graphs, a regular graph
|
||||
# and the AntiGraph of it's complement, which behaves
|
||||
# as if it were the original graph.
|
||||
Gnp = nx.gnp_random_graph(20, 0.8, seed=42)
|
||||
Anp = AntiGraph(nx.complement(Gnp))
|
||||
Gd = nx.davis_southern_women_graph()
|
||||
Ad = AntiGraph(nx.complement(Gd))
|
||||
Gk = nx.karate_club_graph()
|
||||
Ak = AntiGraph(nx.complement(Gk))
|
||||
pairs = [(Gnp, Anp), (Gd, Ad), (Gk, Ak)]
|
||||
# test connected components
|
||||
for G, A in pairs:
|
||||
gc = [set(c) for c in nx.connected_components(G)]
|
||||
ac = [set(c) for c in nx.connected_components(A)]
|
||||
for comp in ac:
|
||||
assert comp in gc
|
||||
# test biconnected components
|
||||
for G, A in pairs:
|
||||
gc = [set(c) for c in nx.biconnected_components(G)]
|
||||
ac = [set(c) for c in nx.biconnected_components(A)]
|
||||
for comp in ac:
|
||||
assert comp in gc
|
||||
# test degree
|
||||
for G, A in pairs:
|
||||
node = list(G.nodes())[0]
|
||||
nodes = list(G.nodes())[1:4]
|
||||
assert G.degree(node) == A.degree(node)
|
||||
assert sum(d for n, d in G.degree()) == sum(d for n, d in A.degree())
|
||||
# AntiGraph is a ThinGraph, so all the weights are 1
|
||||
assert sum(d for n, d in A.degree()) == sum(d for n, d in A.degree(weight="weight"))
|
||||
assert sum(d for n, d in G.degree(nodes)) == sum(d for n, d in A.degree(nodes))
|
||||
|
||||
nx.draw(Gnp)
|
||||
plt.show()
|
Loading…
Add table
Add a link
Reference in a new issue