comment here
This commit is contained in:
2
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/README.txt
vendored
Normal file
2
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/README.txt
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
Algorithms
|
||||
----------
|
||||
78736
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/WormNet.v3.benchmark.txt
vendored
Normal file
78736
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/WormNet.v3.benchmark.txt
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
BIN
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/__pycache__/plot_blockmodel.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/__pycache__/plot_blockmodel.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/__pycache__/plot_circuits.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/__pycache__/plot_circuits.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/__pycache__/plot_davis_club.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/__pycache__/plot_davis_club.cpython-311.pyc
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/__pycache__/plot_rcm.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/__pycache__/plot_rcm.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/__pycache__/plot_snap.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/__pycache__/plot_snap.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/__pycache__/plot_subgraphs.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/__pycache__/plot_subgraphs.cpython-311.pyc
vendored
Normal file
Binary file not shown.
338
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/hartford_drug.edgelist
vendored
Normal file
338
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/hartford_drug.edgelist
vendored
Normal file
@@ -0,0 +1,338 @@
|
||||
# source target
|
||||
1 2
|
||||
1 10
|
||||
2 1
|
||||
2 10
|
||||
3 7
|
||||
4 7
|
||||
4 209
|
||||
5 132
|
||||
6 150
|
||||
7 3
|
||||
7 4
|
||||
7 9
|
||||
8 106
|
||||
8 115
|
||||
9 1
|
||||
9 2
|
||||
9 7
|
||||
10 1
|
||||
10 2
|
||||
11 133
|
||||
11 218
|
||||
12 88
|
||||
13 214
|
||||
14 24
|
||||
14 52
|
||||
16 10
|
||||
16 19
|
||||
17 64
|
||||
17 78
|
||||
18 55
|
||||
18 103
|
||||
18 163
|
||||
19 18
|
||||
20 64
|
||||
20 180
|
||||
21 16
|
||||
21 22
|
||||
22 21
|
||||
22 64
|
||||
22 106
|
||||
23 20
|
||||
23 22
|
||||
23 64
|
||||
24 14
|
||||
24 31
|
||||
24 122
|
||||
27 115
|
||||
28 29
|
||||
29 28
|
||||
30 19
|
||||
31 24
|
||||
31 32
|
||||
31 122
|
||||
31 147
|
||||
31 233
|
||||
32 31
|
||||
32 86
|
||||
34 35
|
||||
34 37
|
||||
35 34
|
||||
35 43
|
||||
36 132
|
||||
36 187
|
||||
37 38
|
||||
37 90
|
||||
37 282
|
||||
38 42
|
||||
38 43
|
||||
38 210
|
||||
40 20
|
||||
42 15
|
||||
42 38
|
||||
43 34
|
||||
43 35
|
||||
43 38
|
||||
45 107
|
||||
46 61
|
||||
46 72
|
||||
48 23
|
||||
49 30
|
||||
49 64
|
||||
49 108
|
||||
49 115
|
||||
49 243
|
||||
50 30
|
||||
50 47
|
||||
50 55
|
||||
50 125
|
||||
50 163
|
||||
52 218
|
||||
52 224
|
||||
54 111
|
||||
54 210
|
||||
55 65
|
||||
55 67
|
||||
55 105
|
||||
55 108
|
||||
55 222
|
||||
56 18
|
||||
56 64
|
||||
57 65
|
||||
57 125
|
||||
58 20
|
||||
58 30
|
||||
58 50
|
||||
58 103
|
||||
58 180
|
||||
59 164
|
||||
63 125
|
||||
64 8
|
||||
64 50
|
||||
64 70
|
||||
64 256
|
||||
66 20
|
||||
66 84
|
||||
66 106
|
||||
66 125
|
||||
67 22
|
||||
67 50
|
||||
67 113
|
||||
68 50
|
||||
70 50
|
||||
70 64
|
||||
71 72
|
||||
74 29
|
||||
74 75
|
||||
74 215
|
||||
75 74
|
||||
75 215
|
||||
76 58
|
||||
76 104
|
||||
77 103
|
||||
78 64
|
||||
78 68
|
||||
80 207
|
||||
80 210
|
||||
82 8
|
||||
82 77
|
||||
82 83
|
||||
82 97
|
||||
82 163
|
||||
83 82
|
||||
83 226
|
||||
83 243
|
||||
84 29
|
||||
84 154
|
||||
87 101
|
||||
87 189
|
||||
89 90
|
||||
90 89
|
||||
90 94
|
||||
91 86
|
||||
92 19
|
||||
92 30
|
||||
92 106
|
||||
94 72
|
||||
94 89
|
||||
94 90
|
||||
95 30
|
||||
96 75
|
||||
96 256
|
||||
97 80
|
||||
97 128
|
||||
98 86
|
||||
100 86
|
||||
101 87
|
||||
103 77
|
||||
103 104
|
||||
104 58
|
||||
104 77
|
||||
104 103
|
||||
106 22
|
||||
107 38
|
||||
107 114
|
||||
107 122
|
||||
108 49
|
||||
108 55
|
||||
111 121
|
||||
111 128
|
||||
111 210
|
||||
113 253
|
||||
114 107
|
||||
116 30
|
||||
116 140
|
||||
118 129
|
||||
118 138
|
||||
120 88
|
||||
121 128
|
||||
122 31
|
||||
123 32
|
||||
124 244
|
||||
125 132
|
||||
126 163
|
||||
126 180
|
||||
128 38
|
||||
128 111
|
||||
129 118
|
||||
132 29
|
||||
132 30
|
||||
133 30
|
||||
134 135
|
||||
134 150
|
||||
135 134
|
||||
137 144
|
||||
138 118
|
||||
138 129
|
||||
139 142
|
||||
141 157
|
||||
141 163
|
||||
142 139
|
||||
143 2
|
||||
144 137
|
||||
145 151
|
||||
146 137
|
||||
146 165
|
||||
146 169
|
||||
146 171
|
||||
147 31
|
||||
147 128
|
||||
148 146
|
||||
148 169
|
||||
148 171
|
||||
148 282
|
||||
149 128
|
||||
149 148
|
||||
149 172
|
||||
150 86
|
||||
151 145
|
||||
152 4
|
||||
153 134
|
||||
154 155
|
||||
156 161
|
||||
157 141
|
||||
161 156
|
||||
165 144
|
||||
165 148
|
||||
167 149
|
||||
169 15
|
||||
169 148
|
||||
169 171
|
||||
170 115
|
||||
170 173
|
||||
170 183
|
||||
170 202
|
||||
171 72
|
||||
171 148
|
||||
171 169
|
||||
173 170
|
||||
175 100
|
||||
176 10
|
||||
178 181
|
||||
181 178
|
||||
182 38
|
||||
182 171
|
||||
183 96
|
||||
185 50
|
||||
186 127
|
||||
187 50
|
||||
187 65
|
||||
188 30
|
||||
188 50
|
||||
189 87
|
||||
189 89
|
||||
190 35
|
||||
190 38
|
||||
190 122
|
||||
190 182
|
||||
191 54
|
||||
191 118
|
||||
191 129
|
||||
191 172
|
||||
192 149
|
||||
192 167
|
||||
195 75
|
||||
197 50
|
||||
197 188
|
||||
198 218
|
||||
198 221
|
||||
198 222
|
||||
200 65
|
||||
200 220
|
||||
201 113
|
||||
202 156
|
||||
203 232
|
||||
204 194
|
||||
207 38
|
||||
207 122
|
||||
207 124
|
||||
208 30
|
||||
208 50
|
||||
210 38
|
||||
210 207
|
||||
211 37
|
||||
213 35
|
||||
213 38
|
||||
214 13
|
||||
214 14
|
||||
214 171
|
||||
214 213
|
||||
215 75
|
||||
217 39
|
||||
218 68
|
||||
218 222
|
||||
221 198
|
||||
222 198
|
||||
222 218
|
||||
223 39
|
||||
225 3
|
||||
226 22
|
||||
229 65
|
||||
230 68
|
||||
231 43
|
||||
232 95
|
||||
232 203
|
||||
233 99
|
||||
234 68
|
||||
234 230
|
||||
237 244
|
||||
238 145
|
||||
242 3
|
||||
242 113
|
||||
244 237
|
||||
249 96
|
||||
250 156
|
||||
252 65
|
||||
254 65
|
||||
258 113
|
||||
268 4
|
||||
270 183
|
||||
272 6
|
||||
275 96
|
||||
280 183
|
||||
280 206
|
||||
282 37
|
||||
285 75
|
||||
290 285
|
||||
293 290
|
||||
112
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/plot_beam_search.py
vendored
Normal file
112
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/plot_beam_search.py
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
"""
|
||||
===========
|
||||
Beam Search
|
||||
===========
|
||||
|
||||
Beam search with dynamic beam width.
|
||||
|
||||
The progressive widening beam search repeatedly executes a beam search
|
||||
with increasing beam width until the target node is found.
|
||||
"""
|
||||
import math
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import networkx as nx
|
||||
|
||||
|
||||
def progressive_widening_search(G, source, value, condition, initial_width=1):
|
||||
"""Progressive widening beam search to find a node.
|
||||
|
||||
The progressive widening beam search involves a repeated beam
|
||||
search, starting with a small beam width then extending to
|
||||
progressively larger beam widths if the target node is not
|
||||
found. This implementation simply returns the first node found that
|
||||
matches the termination condition.
|
||||
|
||||
`G` is a NetworkX graph.
|
||||
|
||||
`source` is a node in the graph. The search for the node of interest
|
||||
begins here and extends only to those nodes in the (weakly)
|
||||
connected component of this node.
|
||||
|
||||
`value` is a function that returns a real number indicating how good
|
||||
a potential neighbor node is when deciding which neighbor nodes to
|
||||
enqueue in the breadth-first search. Only the best nodes within the
|
||||
current beam width will be enqueued at each step.
|
||||
|
||||
`condition` is the termination condition for the search. This is a
|
||||
function that takes a node as input and return a Boolean indicating
|
||||
whether the node is the target. If no node matches the termination
|
||||
condition, this function raises :exc:`NodeNotFound`.
|
||||
|
||||
`initial_width` is the starting beam width for the beam search (the
|
||||
default is one). If no node matching the `condition` is found with
|
||||
this beam width, the beam search is restarted from the `source` node
|
||||
with a beam width that is twice as large (so the beam width
|
||||
increases exponentially). The search terminates after the beam width
|
||||
exceeds the number of nodes in the graph.
|
||||
|
||||
"""
|
||||
# Check for the special case in which the source node satisfies the
|
||||
# termination condition.
|
||||
if condition(source):
|
||||
return source
|
||||
# The largest possible value of `i` in this range yields a width at
|
||||
# least the number of nodes in the graph, so the final invocation of
|
||||
# `bfs_beam_edges` is equivalent to a plain old breadth-first
|
||||
# search. Therefore, all nodes will eventually be visited.
|
||||
log_m = math.ceil(math.log2(len(G)))
|
||||
for i in range(log_m):
|
||||
width = initial_width * pow(2, i)
|
||||
# Since we are always starting from the same source node, this
|
||||
# search may visit the same nodes many times (depending on the
|
||||
# implementation of the `value` function).
|
||||
for u, v in nx.bfs_beam_edges(G, source, value, width):
|
||||
if condition(v):
|
||||
return v
|
||||
# At this point, since all nodes have been visited, we know that
|
||||
# none of the nodes satisfied the termination condition.
|
||||
raise nx.NodeNotFound("no node satisfied the termination condition")
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Search for a node with high centrality.
|
||||
# ---------------------------------------
|
||||
#
|
||||
# We generate a random graph, compute the centrality of each node, then perform
|
||||
# the progressive widening search in order to find a node of high centrality.
|
||||
|
||||
# Set a seed for random number generation so the example is reproducible
|
||||
seed = 89
|
||||
|
||||
G = nx.gnp_random_graph(100, 0.5, seed=seed)
|
||||
centrality = nx.eigenvector_centrality(G)
|
||||
avg_centrality = sum(centrality.values()) / len(G)
|
||||
|
||||
|
||||
def has_high_centrality(v):
|
||||
return centrality[v] >= avg_centrality
|
||||
|
||||
|
||||
source = 0
|
||||
value = centrality.get
|
||||
condition = has_high_centrality
|
||||
|
||||
found_node = progressive_widening_search(G, source, value, condition)
|
||||
c = centrality[found_node]
|
||||
print(f"found node {found_node} with centrality {c}")
|
||||
|
||||
|
||||
# Draw graph
|
||||
pos = nx.spring_layout(G, seed=seed)
|
||||
options = {
|
||||
"node_color": "blue",
|
||||
"node_size": 20,
|
||||
"edge_color": "grey",
|
||||
"linewidths": 0,
|
||||
"width": 0.1,
|
||||
}
|
||||
nx.draw(G, pos, **options)
|
||||
# Draw node with high centrality as large and red
|
||||
nx.draw_networkx_nodes(G, pos, nodelist=[found_node], node_size=100, node_color="r")
|
||||
plt.show()
|
||||
83
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/plot_betweenness_centrality.py
vendored
Normal file
83
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/plot_betweenness_centrality.py
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
"""
|
||||
=====================
|
||||
Betweenness Centrality
|
||||
=====================
|
||||
|
||||
Betweenness centrality measures of positive gene functional associations
|
||||
using WormNet v.3-GS.
|
||||
|
||||
Data from: https://www.inetbio.org/wormnet/downloadnetwork.php
|
||||
"""
|
||||
|
||||
from random import sample
|
||||
import networkx as nx
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
# Gold standard data of positive gene functional associations
|
||||
# from https://www.inetbio.org/wormnet/downloadnetwork.php
|
||||
G = nx.read_edgelist("WormNet.v3.benchmark.txt")
|
||||
|
||||
# remove randomly selected nodes (to make example fast)
|
||||
num_to_remove = int(len(G) / 1.5)
|
||||
nodes = sample(list(G.nodes), num_to_remove)
|
||||
G.remove_nodes_from(nodes)
|
||||
|
||||
# remove low-degree nodes
|
||||
low_degree = [n for n, d in G.degree() if d < 10]
|
||||
G.remove_nodes_from(low_degree)
|
||||
|
||||
# largest connected component
|
||||
components = nx.connected_components(G)
|
||||
largest_component = max(components, key=len)
|
||||
H = G.subgraph(largest_component)
|
||||
|
||||
# compute centrality
|
||||
centrality = nx.betweenness_centrality(H, k=10, endpoints=True)
|
||||
|
||||
# compute community structure
|
||||
lpc = nx.community.label_propagation_communities(H)
|
||||
community_index = {n: i for i, com in enumerate(lpc) for n in com}
|
||||
|
||||
#### draw graph ####
|
||||
fig, ax = plt.subplots(figsize=(20, 15))
|
||||
pos = nx.spring_layout(H, k=0.15, seed=4572321)
|
||||
node_color = [community_index[n] for n in H]
|
||||
node_size = [v * 20000 for v in centrality.values()]
|
||||
nx.draw_networkx(
|
||||
H,
|
||||
pos=pos,
|
||||
with_labels=False,
|
||||
node_color=node_color,
|
||||
node_size=node_size,
|
||||
edge_color="gainsboro",
|
||||
alpha=0.4,
|
||||
)
|
||||
|
||||
# Title/legend
|
||||
font = {"color": "k", "fontweight": "bold", "fontsize": 20}
|
||||
ax.set_title("Gene functional association network (C. elegans)", font)
|
||||
# Change font color for legend
|
||||
font["color"] = "r"
|
||||
|
||||
ax.text(
|
||||
0.80,
|
||||
0.10,
|
||||
"node color = community structure",
|
||||
horizontalalignment="center",
|
||||
transform=ax.transAxes,
|
||||
fontdict=font,
|
||||
)
|
||||
ax.text(
|
||||
0.80,
|
||||
0.06,
|
||||
"node size = betweenness centrality",
|
||||
horizontalalignment="center",
|
||||
transform=ax.transAxes,
|
||||
fontdict=font,
|
||||
)
|
||||
|
||||
# Resize figure for label readability
|
||||
ax.margins(0.1, 0.05)
|
||||
fig.tight_layout()
|
||||
plt.axis("off")
|
||||
plt.show()
|
||||
79
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/plot_blockmodel.py
vendored
Normal file
79
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/plot_blockmodel.py
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
"""
|
||||
==========
|
||||
Blockmodel
|
||||
==========
|
||||
|
||||
Example of creating a block model using the quotient_graph function in NX. Data
|
||||
used is the Hartford, CT drug users network::
|
||||
|
||||
@article{weeks2002social,
|
||||
title={Social networks of drug users in high-risk sites: Finding the connections},
|
||||
url = {https://doi.org/10.1023/A:1015457400897},
|
||||
doi = {10.1023/A:1015457400897},
|
||||
author={Weeks, Margaret R and Clair, Scott and Borgatti, Stephen P and Radda, Kim and Schensul, Jean J},
|
||||
journal={{AIDS and Behavior}},
|
||||
volume={6},
|
||||
number={2},
|
||||
pages={193--206},
|
||||
year={2002},
|
||||
publisher={Springer}
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
from collections import defaultdict
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import networkx as nx
|
||||
import numpy as np
|
||||
from scipy.cluster import hierarchy
|
||||
from scipy.spatial import distance
|
||||
|
||||
|
||||
def create_hc(G):
|
||||
"""Creates hierarchical cluster of graph G from distance matrix"""
|
||||
path_length = nx.all_pairs_shortest_path_length(G)
|
||||
distances = np.zeros((len(G), len(G)))
|
||||
for u, p in path_length:
|
||||
for v, d in p.items():
|
||||
distances[u][v] = d
|
||||
# Create hierarchical cluster
|
||||
Y = distance.squareform(distances)
|
||||
Z = hierarchy.complete(Y) # Creates HC using farthest point linkage
|
||||
# This partition selection is arbitrary, for illustrive purposes
|
||||
membership = list(hierarchy.fcluster(Z, t=1.15))
|
||||
# Create collection of lists for blockmodel
|
||||
partition = defaultdict(list)
|
||||
for n, p in zip(list(range(len(G))), membership):
|
||||
partition[p].append(n)
|
||||
return list(partition.values())
|
||||
|
||||
|
||||
G = nx.read_edgelist("hartford_drug.edgelist")
|
||||
|
||||
# Extract largest connected component into graph H
|
||||
H = G.subgraph(next(nx.connected_components(G)))
|
||||
# Makes life easier to have consecutively labeled integer nodes
|
||||
H = nx.convert_node_labels_to_integers(H)
|
||||
# Create partitions with hierarchical clustering
|
||||
partitions = create_hc(H)
|
||||
# Build blockmodel graph
|
||||
BM = nx.quotient_graph(H, partitions, relabel=True)
|
||||
|
||||
# Draw original graph
|
||||
pos = nx.spring_layout(H, iterations=100, seed=83) # Seed for reproducibility
|
||||
plt.subplot(211)
|
||||
nx.draw(H, pos, with_labels=False, node_size=10)
|
||||
|
||||
# Draw block model with weighted edges and nodes sized by number of internal nodes
|
||||
node_size = [BM.nodes[x]["nnodes"] * 10 for x in BM.nodes()]
|
||||
edge_width = [(2 * d["weight"]) for (u, v, d) in BM.edges(data=True)]
|
||||
# Set positions to mean of positions of internal nodes from original graph
|
||||
posBM = {}
|
||||
for n in BM:
|
||||
xy = np.array([pos[u] for u in BM.nodes[n]["graph"]])
|
||||
posBM[n] = xy.mean(axis=0)
|
||||
plt.subplot(212)
|
||||
nx.draw(BM, posBM, node_size=node_size, width=edge_width, with_labels=False)
|
||||
plt.axis("off")
|
||||
plt.show()
|
||||
103
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/plot_circuits.py
vendored
Normal file
103
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/plot_circuits.py
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
"""
|
||||
========
|
||||
Circuits
|
||||
========
|
||||
|
||||
Convert a Boolean circuit to an equivalent Boolean formula.
|
||||
|
||||
A Boolean circuit can be exponentially more expressive than an
|
||||
equivalent formula in the worst case, since the circuit can reuse
|
||||
subcircuits multiple times, whereas a formula cannot reuse subformulas
|
||||
more than once. Thus creating a Boolean formula from a Boolean circuit
|
||||
in this way may be infeasible if the circuit is large.
|
||||
|
||||
"""
|
||||
import matplotlib.pyplot as plt
|
||||
import networkx as nx
|
||||
|
||||
|
||||
def circuit_to_formula(circuit):
|
||||
# Convert the circuit to an equivalent formula.
|
||||
formula = nx.dag_to_branching(circuit)
|
||||
# Transfer the operator or variable labels for each node from the
|
||||
# circuit to the formula.
|
||||
for v in formula:
|
||||
source = formula.nodes[v]["source"]
|
||||
formula.nodes[v]["label"] = circuit.nodes[source]["label"]
|
||||
return formula
|
||||
|
||||
|
||||
def formula_to_string(formula):
|
||||
def _to_string(formula, root):
|
||||
# If there are no children, this is a variable node.
|
||||
label = formula.nodes[root]["label"]
|
||||
if not formula[root]:
|
||||
return label
|
||||
# Otherwise, this is an operator.
|
||||
children = formula[root]
|
||||
# If one child, the label must be a NOT operator.
|
||||
if len(children) == 1:
|
||||
child = nx.utils.arbitrary_element(children)
|
||||
return f"{label}({_to_string(formula, child)})"
|
||||
# NB "left" and "right" here are a little misleading: there is
|
||||
# no order on the children of a node. That's okay because the
|
||||
# Boolean AND and OR operators are symmetric. It just means that
|
||||
# the order of the operands cannot be predicted and hence the
|
||||
# function does not necessarily behave the same way on every
|
||||
# invocation.
|
||||
left, right = formula[root]
|
||||
left_subformula = _to_string(formula, left)
|
||||
right_subformula = _to_string(formula, right)
|
||||
return f"({left_subformula} {label} {right_subformula})"
|
||||
|
||||
root = next(v for v, d in formula.in_degree() if d == 0)
|
||||
return _to_string(formula, root)
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Create an example Boolean circuit.
|
||||
# ----------------------------------
|
||||
#
|
||||
# This circuit has a ∧ at the output and two ∨s at the next layer.
|
||||
# The third layer has a variable x that appears in the left ∨, a
|
||||
# variable y that appears in both the left and right ∨s, and a
|
||||
# negation for the variable z that appears as the sole node in the
|
||||
# fourth layer.
|
||||
circuit = nx.DiGraph()
|
||||
# Layer 0
|
||||
circuit.add_node(0, label="∧", layer=0)
|
||||
# Layer 1
|
||||
circuit.add_node(1, label="∨", layer=1)
|
||||
circuit.add_node(2, label="∨", layer=1)
|
||||
circuit.add_edge(0, 1)
|
||||
circuit.add_edge(0, 2)
|
||||
# Layer 2
|
||||
circuit.add_node(3, label="x", layer=2)
|
||||
circuit.add_node(4, label="y", layer=2)
|
||||
circuit.add_node(5, label="¬", layer=2)
|
||||
circuit.add_edge(1, 3)
|
||||
circuit.add_edge(1, 4)
|
||||
circuit.add_edge(2, 4)
|
||||
circuit.add_edge(2, 5)
|
||||
# Layer 3
|
||||
circuit.add_node(6, label="z", layer=3)
|
||||
circuit.add_edge(5, 6)
|
||||
# Convert the circuit to an equivalent formula.
|
||||
formula = circuit_to_formula(circuit)
|
||||
print(formula_to_string(formula))
|
||||
|
||||
|
||||
labels = nx.get_node_attributes(circuit, "label")
|
||||
options = {
|
||||
"node_size": 600,
|
||||
"alpha": 0.5,
|
||||
"node_color": "blue",
|
||||
"labels": labels,
|
||||
"font_size": 22,
|
||||
}
|
||||
plt.figure(figsize=(8, 8))
|
||||
pos = nx.multipartite_layout(circuit, subset_key="layer")
|
||||
nx.draw_networkx(circuit, pos, **options)
|
||||
plt.title(formula_to_string(formula))
|
||||
plt.axis("equal")
|
||||
plt.show()
|
||||
43
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/plot_davis_club.py
vendored
Normal file
43
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/plot_davis_club.py
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
"""
|
||||
==========
|
||||
Davis Club
|
||||
==========
|
||||
|
||||
Davis Southern Club Women
|
||||
|
||||
Shows how to make unipartite projections of the graph and compute the
|
||||
properties of those graphs.
|
||||
|
||||
These data were collected by Davis et al. in the 1930s.
|
||||
They represent observed attendance at 14 social events by 18 Southern women.
|
||||
The graph is bipartite (clubs, women).
|
||||
"""
|
||||
import matplotlib.pyplot as plt
|
||||
import networkx as nx
|
||||
import networkx.algorithms.bipartite as bipartite
|
||||
|
||||
G = nx.davis_southern_women_graph()
|
||||
women = G.graph["top"]
|
||||
clubs = G.graph["bottom"]
|
||||
|
||||
print("Biadjacency matrix")
|
||||
print(bipartite.biadjacency_matrix(G, women, clubs))
|
||||
|
||||
# project bipartite graph onto women nodes
|
||||
W = bipartite.projected_graph(G, women)
|
||||
print()
|
||||
print("#Friends, Member")
|
||||
for w in women:
|
||||
print(f"{W.degree(w)} {w}")
|
||||
|
||||
# project bipartite graph onto women nodes keeping number of co-occurence
|
||||
# the degree computed is weighted and counts the total number of shared contacts
|
||||
W = bipartite.weighted_projected_graph(G, women)
|
||||
print()
|
||||
print("#Friend meetings, Member")
|
||||
for w in women:
|
||||
print(f"{W.degree(w, weight='weight')} {w}")
|
||||
|
||||
pos = nx.spring_layout(G, seed=648) # Seed layout for reproducible node positions
|
||||
nx.draw(G, pos)
|
||||
plt.show()
|
||||
92
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/plot_dedensification.py
vendored
Normal file
92
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/plot_dedensification.py
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
"""
|
||||
===============
|
||||
Dedensification
|
||||
===============
|
||||
|
||||
Examples of dedensification of a graph. Dedensification retains the structural
|
||||
pattern of the original graph and will only add compressor nodes when doing so
|
||||
would result in fewer edges in the compressed graph.
|
||||
"""
|
||||
import matplotlib.pyplot as plt
|
||||
import networkx as nx
|
||||
|
||||
plt.suptitle("Dedensification")
|
||||
|
||||
original_graph = nx.DiGraph()
|
||||
white_nodes = ["1", "2", "3", "4", "5", "6"]
|
||||
red_nodes = ["A", "B", "C"]
|
||||
node_sizes = [250 for node in white_nodes + red_nodes]
|
||||
node_colors = ["white" for n in white_nodes] + ["red" for n in red_nodes]
|
||||
|
||||
original_graph.add_nodes_from(white_nodes + red_nodes)
|
||||
original_graph.add_edges_from(
|
||||
[
|
||||
("1", "C"),
|
||||
("1", "B"),
|
||||
("2", "C"),
|
||||
("2", "B"),
|
||||
("2", "A"),
|
||||
("3", "B"),
|
||||
("3", "A"),
|
||||
("3", "6"),
|
||||
("4", "C"),
|
||||
("4", "B"),
|
||||
("4", "A"),
|
||||
("5", "B"),
|
||||
("5", "A"),
|
||||
("6", "5"),
|
||||
("A", "6"),
|
||||
]
|
||||
)
|
||||
base_options = dict(with_labels=True, edgecolors="black")
|
||||
pos = {
|
||||
"3": (0, 1),
|
||||
"2": (0, 2),
|
||||
"1": (0, 3),
|
||||
"6": (1, 0),
|
||||
"A": (1, 1),
|
||||
"B": (1, 2),
|
||||
"C": (1, 3),
|
||||
"4": (2, 3),
|
||||
"5": (2, 1),
|
||||
}
|
||||
ax1 = plt.subplot(1, 2, 1)
|
||||
plt.title("Original (%s edges)" % original_graph.number_of_edges())
|
||||
nx.draw_networkx(original_graph, pos=pos, node_color=node_colors, **base_options)
|
||||
|
||||
nonexp_graph, compression_nodes = nx.summarization.dedensify(
|
||||
original_graph, threshold=2, copy=False
|
||||
)
|
||||
nonexp_node_colors = list(node_colors)
|
||||
nonexp_node_sizes = list(node_sizes)
|
||||
for node in compression_nodes:
|
||||
nonexp_node_colors.append("yellow")
|
||||
nonexp_node_sizes.append(600)
|
||||
plt.subplot(1, 2, 2)
|
||||
|
||||
plt.title("Dedensified (%s edges)" % nonexp_graph.number_of_edges())
|
||||
nonexp_pos = {
|
||||
"5": (0, 0),
|
||||
"B": (0, 2),
|
||||
"1": (0, 3),
|
||||
"6": (1, 0.75),
|
||||
"3": (1.5, 1.5),
|
||||
"A": (2, 0),
|
||||
"C": (2, 3),
|
||||
"4": (3, 1.5),
|
||||
"2": (3, 2.5),
|
||||
}
|
||||
c_nodes = list(compression_nodes)
|
||||
c_nodes.sort()
|
||||
for spot, node in enumerate(c_nodes):
|
||||
nonexp_pos[node] = (2, spot + 2)
|
||||
nx.draw_networkx(
|
||||
nonexp_graph,
|
||||
pos=nonexp_pos,
|
||||
node_color=nonexp_node_colors,
|
||||
node_size=nonexp_node_sizes,
|
||||
**base_options
|
||||
)
|
||||
|
||||
plt.tight_layout()
|
||||
plt.show()
|
||||
210
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/plot_iterated_dynamical_systems.py
vendored
Normal file
210
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/plot_iterated_dynamical_systems.py
vendored
Normal file
@@ -0,0 +1,210 @@
|
||||
"""
|
||||
==========================
|
||||
Iterated Dynamical Systems
|
||||
==========================
|
||||
|
||||
Digraphs from Integer-valued Iterated Functions
|
||||
|
||||
Sums of cubes on 3N
|
||||
-------------------
|
||||
|
||||
The number 153 has a curious property.
|
||||
|
||||
Let 3N={3,6,9,12,...} be the set of positive multiples of 3. Define an
|
||||
iterative process f:3N->3N as follows: for a given n, take each digit
|
||||
of n (in base 10), cube it and then sum the cubes to obtain f(n).
|
||||
|
||||
When this process is repeated, the resulting series n, f(n), f(f(n)),...
|
||||
terminate in 153 after a finite number of iterations (the process ends
|
||||
because 153 = 1**3 + 5**3 + 3**3).
|
||||
|
||||
In the language of discrete dynamical systems, 153 is the global
|
||||
attractor for the iterated map f restricted to the set 3N.
|
||||
|
||||
For example: take the number 108
|
||||
|
||||
f(108) = 1**3 + 0**3 + 8**3 = 513
|
||||
|
||||
and
|
||||
|
||||
f(513) = 5**3 + 1**3 + 3**3 = 153
|
||||
|
||||
So, starting at 108 we reach 153 in two iterations,
|
||||
represented as:
|
||||
|
||||
108->513->153
|
||||
|
||||
Computing all orbits of 3N up to 10**5 reveals that the attractor
|
||||
153 is reached in a maximum of 14 iterations. In this code we
|
||||
show that 13 cycles is the maximum required for all integers (in 3N)
|
||||
less than 10,000.
|
||||
|
||||
The smallest number that requires 13 iterations to reach 153, is 177, i.e.,
|
||||
|
||||
177->687->1071->345->216->225->141->66->432->99->1458->702->351->153
|
||||
|
||||
The resulting large digraphs are useful for testing network software.
|
||||
|
||||
The general problem
|
||||
-------------------
|
||||
|
||||
Given numbers n, a power p and base b, define F(n; p, b) as the sum of
|
||||
the digits of n (in base b) raised to the power p. The above example
|
||||
corresponds to f(n)=F(n; 3,10), and below F(n; p, b) is implemented as
|
||||
the function powersum(n,p,b). The iterative dynamical system defined by
|
||||
the mapping n:->f(n) above (over 3N) converges to a single fixed point;
|
||||
153. Applying the map to all positive integers N, leads to a discrete
|
||||
dynamical process with 5 fixed points: 1, 153, 370, 371, 407. Modulo 3
|
||||
those numbers are 1, 0, 1, 2, 2. The function f above has the added
|
||||
property that it maps a multiple of 3 to another multiple of 3; i.e. it
|
||||
is invariant on the subset 3N.
|
||||
|
||||
|
||||
The squaring of digits (in base 10) result in cycles and the
|
||||
single fixed point 1. I.e., from a certain point on, the process
|
||||
starts repeating itself.
|
||||
|
||||
keywords: "Recurring Digital Invariant", "Narcissistic Number",
|
||||
"Happy Number"
|
||||
|
||||
The 3n+1 problem
|
||||
----------------
|
||||
|
||||
There is a rich history of mathematical recreations
|
||||
associated with discrete dynamical systems. The most famous
|
||||
is the Collatz 3n+1 problem. See the function
|
||||
collatz_problem_digraph below. The Collatz conjecture
|
||||
--- that every orbit returns to the fixed point 1 in finite time
|
||||
--- is still unproven. Even the great Paul Erdos said "Mathematics
|
||||
is not yet ready for such problems", and offered $500
|
||||
for its solution.
|
||||
|
||||
keywords: "3n+1", "3x+1", "Collatz problem", "Thwaite's conjecture"
|
||||
"""
|
||||
|
||||
import networkx as nx
|
||||
|
||||
nmax = 10000
|
||||
p = 3
|
||||
|
||||
|
||||
def digitsrep(n, b=10):
|
||||
"""Return list of digits comprising n represented in base b.
|
||||
n must be a nonnegative integer"""
|
||||
|
||||
if n <= 0:
|
||||
return [0]
|
||||
|
||||
dlist = []
|
||||
while n > 0:
|
||||
# Prepend next least-significant digit
|
||||
dlist = [n % b] + dlist
|
||||
# Floor-division
|
||||
n = n // b
|
||||
return dlist
|
||||
|
||||
|
||||
def powersum(n, p, b=10):
|
||||
"""Return sum of digits of n (in base b) raised to the power p."""
|
||||
dlist = digitsrep(n, b)
|
||||
sum = 0
|
||||
for k in dlist:
|
||||
sum += k**p
|
||||
return sum
|
||||
|
||||
|
||||
def attractor153_graph(n, p, multiple=3, b=10):
|
||||
"""Return digraph of iterations of powersum(n,3,10)."""
|
||||
G = nx.DiGraph()
|
||||
for k in range(1, n + 1):
|
||||
if k % multiple == 0 and k not in G:
|
||||
k1 = k
|
||||
knext = powersum(k1, p, b)
|
||||
while k1 != knext:
|
||||
G.add_edge(k1, knext)
|
||||
k1 = knext
|
||||
knext = powersum(k1, p, b)
|
||||
return G
|
||||
|
||||
|
||||
def squaring_cycle_graph_old(n, b=10):
|
||||
"""Return digraph of iterations of powersum(n,2,10)."""
|
||||
G = nx.DiGraph()
|
||||
for k in range(1, n + 1):
|
||||
k1 = k
|
||||
G.add_node(k1) # case k1==knext, at least add node
|
||||
knext = powersum(k1, 2, b)
|
||||
G.add_edge(k1, knext)
|
||||
while k1 != knext: # stop if fixed point
|
||||
k1 = knext
|
||||
knext = powersum(k1, 2, b)
|
||||
G.add_edge(k1, knext)
|
||||
if G.out_degree(knext) >= 1:
|
||||
# knext has already been iterated in and out
|
||||
break
|
||||
return G
|
||||
|
||||
|
||||
def sum_of_digits_graph(nmax, b=10):
|
||||
def f(n):
|
||||
return powersum(n, 1, b)
|
||||
|
||||
return discrete_dynamics_digraph(nmax, f)
|
||||
|
||||
|
||||
def squaring_cycle_digraph(nmax, b=10):
|
||||
def f(n):
|
||||
return powersum(n, 2, b)
|
||||
|
||||
return discrete_dynamics_digraph(nmax, f)
|
||||
|
||||
|
||||
def cubing_153_digraph(nmax):
|
||||
def f(n):
|
||||
return powersum(n, 3, 10)
|
||||
|
||||
return discrete_dynamics_digraph(nmax, f)
|
||||
|
||||
|
||||
def discrete_dynamics_digraph(nmax, f, itermax=50000):
|
||||
G = nx.DiGraph()
|
||||
for k in range(1, nmax + 1):
|
||||
kold = k
|
||||
G.add_node(kold)
|
||||
knew = f(kold)
|
||||
G.add_edge(kold, knew)
|
||||
while kold != knew and kold << itermax:
|
||||
# iterate until fixed point reached or itermax is exceeded
|
||||
kold = knew
|
||||
knew = f(kold)
|
||||
G.add_edge(kold, knew)
|
||||
if G.out_degree(knew) >= 1:
|
||||
# knew has already been iterated in and out
|
||||
break
|
||||
return G
|
||||
|
||||
|
||||
def collatz_problem_digraph(nmax):
|
||||
def f(n):
|
||||
if n % 2 == 0:
|
||||
return n // 2
|
||||
else:
|
||||
return 3 * n + 1
|
||||
|
||||
return discrete_dynamics_digraph(nmax, f)
|
||||
|
||||
|
||||
def fixed_points(G):
|
||||
"""Return a list of fixed points for the discrete dynamical
|
||||
system represented by the digraph G.
|
||||
"""
|
||||
return [n for n in G if G.out_degree(n) == 0]
|
||||
|
||||
|
||||
nmax = 10000
|
||||
print(f"Building cubing_153_digraph({nmax})")
|
||||
G = cubing_153_digraph(nmax)
|
||||
print("Resulting digraph has", len(G), "nodes and", G.size(), " edges")
|
||||
print("Shortest path from 177 to 153 is:")
|
||||
print(nx.shortest_path(G, 177, 153))
|
||||
print(f"fixed points are {fixed_points(G)}")
|
||||
31
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/plot_krackhardt_centrality.py
vendored
Normal file
31
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/plot_krackhardt_centrality.py
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
"""
|
||||
=====================
|
||||
Krackhardt Centrality
|
||||
=====================
|
||||
|
||||
Centrality measures of Krackhardt social network.
|
||||
"""
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import networkx as nx
|
||||
|
||||
G = nx.krackhardt_kite_graph()
|
||||
|
||||
print("Betweenness")
|
||||
b = nx.betweenness_centrality(G)
|
||||
for v in G.nodes():
|
||||
print(f"{v:2} {b[v]:.3f}")
|
||||
|
||||
print("Degree centrality")
|
||||
d = nx.degree_centrality(G)
|
||||
for v in G.nodes():
|
||||
print(f"{v:2} {d[v]:.3f}")
|
||||
|
||||
print("Closeness centrality")
|
||||
c = nx.closeness_centrality(G)
|
||||
for v in G.nodes():
|
||||
print(f"{v:2} {c[v]:.3f}")
|
||||
|
||||
pos = nx.spring_layout(G, seed=367) # Seed layout for reproducibility
|
||||
nx.draw(G, pos)
|
||||
plt.show()
|
||||
82
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/plot_parallel_betweenness.py
vendored
Normal file
82
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/plot_parallel_betweenness.py
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
"""
|
||||
====================
|
||||
Parallel Betweenness
|
||||
====================
|
||||
|
||||
Example of parallel implementation of betweenness centrality using the
|
||||
multiprocessing module from Python Standard Library.
|
||||
|
||||
The function betweenness centrality accepts a bunch of nodes and computes
|
||||
the contribution of those nodes to the betweenness centrality of the whole
|
||||
network. Here we divide the network in chunks of nodes and we compute their
|
||||
contribution to the betweenness centrality of the whole network.
|
||||
|
||||
Note: The example output below shows that the non-parallel implementation is
|
||||
faster. This is a limitation of our CI/CD pipeline running on a single core.
|
||||
|
||||
Depending on your setup, you will likely observe a speedup.
|
||||
"""
|
||||
from multiprocessing import Pool
|
||||
import time
|
||||
import itertools
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import networkx as nx
|
||||
|
||||
|
||||
def chunks(l, n):
|
||||
"""Divide a list of nodes `l` in `n` chunks"""
|
||||
l_c = iter(l)
|
||||
while 1:
|
||||
x = tuple(itertools.islice(l_c, n))
|
||||
if not x:
|
||||
return
|
||||
yield x
|
||||
|
||||
|
||||
def betweenness_centrality_parallel(G, processes=None):
|
||||
"""Parallel betweenness centrality function"""
|
||||
p = Pool(processes=processes)
|
||||
node_divisor = len(p._pool) * 4
|
||||
node_chunks = list(chunks(G.nodes(), G.order() // node_divisor))
|
||||
num_chunks = len(node_chunks)
|
||||
bt_sc = p.starmap(
|
||||
nx.betweenness_centrality_subset,
|
||||
zip(
|
||||
[G] * num_chunks,
|
||||
node_chunks,
|
||||
[list(G)] * num_chunks,
|
||||
[True] * num_chunks,
|
||||
[None] * num_chunks,
|
||||
),
|
||||
)
|
||||
|
||||
# Reduce the partial solutions
|
||||
bt_c = bt_sc[0]
|
||||
for bt in bt_sc[1:]:
|
||||
for n in bt:
|
||||
bt_c[n] += bt[n]
|
||||
return bt_c
|
||||
|
||||
|
||||
G_ba = nx.barabasi_albert_graph(1000, 3)
|
||||
G_er = nx.gnp_random_graph(1000, 0.01)
|
||||
G_ws = nx.connected_watts_strogatz_graph(1000, 4, 0.1)
|
||||
for G in [G_ba, G_er, G_ws]:
|
||||
print("")
|
||||
print("Computing betweenness centrality for:")
|
||||
print(G)
|
||||
print("\tParallel version")
|
||||
start = time.time()
|
||||
bt = betweenness_centrality_parallel(G)
|
||||
print(f"\t\tTime: {(time.time() - start):.4F} seconds")
|
||||
print(f"\t\tBetweenness centrality for node 0: {bt[0]:.5f}")
|
||||
print("\tNon-Parallel version")
|
||||
start = time.time()
|
||||
bt = nx.betweenness_centrality(G)
|
||||
print(f"\t\tTime: {(time.time() - start):.4F} seconds")
|
||||
print(f"\t\tBetweenness centrality for node 0: {bt[0]:.5f}")
|
||||
print("")
|
||||
|
||||
nx.draw(G_ba, node_size=100)
|
||||
plt.show()
|
||||
40
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/plot_rcm.py
vendored
Normal file
40
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/plot_rcm.py
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
"""
|
||||
======================
|
||||
Reverse Cuthill--McKee
|
||||
======================
|
||||
|
||||
Cuthill-McKee ordering of matrices
|
||||
|
||||
The reverse Cuthill--McKee algorithm gives a sparse matrix ordering that
|
||||
reduces the matrix bandwidth.
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
import seaborn as sns
|
||||
import networkx as nx
|
||||
|
||||
|
||||
# build low-bandwidth matrix
|
||||
G = nx.grid_2d_graph(3, 3)
|
||||
rcm = list(nx.utils.reverse_cuthill_mckee_ordering(G))
|
||||
print("ordering", rcm)
|
||||
|
||||
print("unordered Laplacian matrix")
|
||||
A = nx.laplacian_matrix(G)
|
||||
x, y = np.nonzero(A)
|
||||
# print(f"lower bandwidth: {(y - x).max()}")
|
||||
# print(f"upper bandwidth: {(x - y).max()}")
|
||||
print(f"bandwidth: {(y - x).max() + (x - y).max() + 1}")
|
||||
print(A)
|
||||
|
||||
B = nx.laplacian_matrix(G, nodelist=rcm)
|
||||
print("low-bandwidth Laplacian matrix")
|
||||
x, y = np.nonzero(B)
|
||||
# print(f"lower bandwidth: {(y - x).max()}")
|
||||
# print(f"upper bandwidth: {(x - y).max()}")
|
||||
print(f"bandwidth: {(y - x).max() + (x - y).max() + 1}")
|
||||
print(B)
|
||||
|
||||
sns.heatmap(B.todense(), cbar=False, square=True, linewidths=0.5, annot=True)
|
||||
plt.show()
|
||||
108
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/plot_snap.py
vendored
Normal file
108
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/plot_snap.py
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
"""
|
||||
==================
|
||||
SNAP Graph Summary
|
||||
==================
|
||||
An example of summarizing a graph based on node attributes and edge attributes
|
||||
using the Summarization by Grouping Nodes on Attributes and Pairwise
|
||||
edges (SNAP) algorithm (not to be confused with the Stanford Network
|
||||
Analysis Project). The algorithm groups nodes by their unique
|
||||
combinations of node attribute values and edge types with other groups
|
||||
of nodes to produce a summary graph. The summary graph can then be used to
|
||||
infer how nodes with different attributes values relate to other nodes in the
|
||||
graph.
|
||||
"""
|
||||
import networkx as nx
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
|
||||
nodes = {
|
||||
"A": dict(color="Red"),
|
||||
"B": dict(color="Red"),
|
||||
"C": dict(color="Red"),
|
||||
"D": dict(color="Red"),
|
||||
"E": dict(color="Blue"),
|
||||
"F": dict(color="Blue"),
|
||||
"G": dict(color="Blue"),
|
||||
"H": dict(color="Blue"),
|
||||
"I": dict(color="Yellow"),
|
||||
"J": dict(color="Yellow"),
|
||||
"K": dict(color="Yellow"),
|
||||
"L": dict(color="Yellow"),
|
||||
}
|
||||
edges = [
|
||||
("A", "B", "Strong"),
|
||||
("A", "C", "Weak"),
|
||||
("A", "E", "Strong"),
|
||||
("A", "I", "Weak"),
|
||||
("B", "D", "Weak"),
|
||||
("B", "J", "Weak"),
|
||||
("B", "F", "Strong"),
|
||||
("C", "G", "Weak"),
|
||||
("D", "H", "Weak"),
|
||||
("I", "J", "Strong"),
|
||||
("J", "K", "Strong"),
|
||||
("I", "L", "Strong"),
|
||||
]
|
||||
original_graph = nx.Graph()
|
||||
original_graph.add_nodes_from(n for n in nodes.items())
|
||||
original_graph.add_edges_from((u, v, {"type": label}) for u, v, label in edges)
|
||||
|
||||
|
||||
plt.suptitle("SNAP Summarization")
|
||||
|
||||
base_options = dict(with_labels=True, edgecolors="black", node_size=500)
|
||||
|
||||
ax1 = plt.subplot(1, 2, 1)
|
||||
plt.title(
|
||||
"Original (%s nodes, %s edges)"
|
||||
% (original_graph.number_of_nodes(), original_graph.number_of_edges())
|
||||
)
|
||||
pos = nx.spring_layout(original_graph, seed=7482934)
|
||||
node_colors = [d["color"] for _, d in original_graph.nodes(data=True)]
|
||||
|
||||
edge_type_visual_weight_lookup = {"Weak": 1.0, "Strong": 3.0}
|
||||
edge_weights = [
|
||||
edge_type_visual_weight_lookup[d["type"]]
|
||||
for _, _, d in original_graph.edges(data=True)
|
||||
]
|
||||
|
||||
nx.draw_networkx(
|
||||
original_graph, pos=pos, node_color=node_colors, width=edge_weights, **base_options
|
||||
)
|
||||
|
||||
node_attributes = ("color",)
|
||||
edge_attributes = ("type",)
|
||||
summary_graph = nx.snap_aggregation(
|
||||
original_graph, node_attributes, edge_attributes, prefix="S-"
|
||||
)
|
||||
|
||||
plt.subplot(1, 2, 2)
|
||||
|
||||
plt.title(
|
||||
"SNAP Aggregation (%s nodes, %s edges)"
|
||||
% (summary_graph.number_of_nodes(), summary_graph.number_of_edges())
|
||||
)
|
||||
summary_pos = nx.spring_layout(summary_graph, seed=8375428)
|
||||
node_colors = []
|
||||
for node in summary_graph:
|
||||
color = summary_graph.nodes[node]["color"]
|
||||
node_colors.append(color)
|
||||
|
||||
edge_weights = []
|
||||
for edge in summary_graph.edges():
|
||||
edge_types = summary_graph.get_edge_data(*edge)["types"]
|
||||
edge_weight = 0.0
|
||||
for edge_type in edge_types:
|
||||
edge_weight += edge_type_visual_weight_lookup[edge_type["type"]]
|
||||
edge_weights.append(edge_weight)
|
||||
|
||||
nx.draw_networkx(
|
||||
summary_graph,
|
||||
pos=summary_pos,
|
||||
node_color=node_colors,
|
||||
width=edge_weights,
|
||||
**base_options
|
||||
)
|
||||
|
||||
plt.tight_layout()
|
||||
plt.show()
|
||||
170
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/plot_subgraphs.py
vendored
Normal file
170
.CondaPkg/env/share/doc/networkx-3.0/examples/algorithms/plot_subgraphs.py
vendored
Normal file
@@ -0,0 +1,170 @@
|
||||
"""
|
||||
=========
|
||||
Subgraphs
|
||||
=========
|
||||
Example of partitioning a directed graph with nodes labeled as
|
||||
supported and unsupported nodes into a list of subgraphs
|
||||
that contain only entirely supported or entirely unsupported nodes.
|
||||
Adopted from
|
||||
https://github.com/lobpcg/python_examples/blob/master/networkx_example.py
|
||||
"""
|
||||
|
||||
import networkx as nx
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
|
||||
def graph_partitioning(G, plotting=True):
|
||||
"""Partition a directed graph into a list of subgraphs that contain
|
||||
only entirely supported or entirely unsupported nodes.
|
||||
"""
|
||||
# Categorize nodes by their node_type attribute
|
||||
supported_nodes = {n for n, d in G.nodes(data="node_type") if d == "supported"}
|
||||
unsupported_nodes = {n for n, d in G.nodes(data="node_type") if d == "unsupported"}
|
||||
|
||||
# Make a copy of the graph.
|
||||
H = G.copy()
|
||||
# Remove all edges connecting supported and unsupported nodes.
|
||||
H.remove_edges_from(
|
||||
(n, nbr, d)
|
||||
for n, nbrs in G.adj.items()
|
||||
if n in supported_nodes
|
||||
for nbr, d in nbrs.items()
|
||||
if nbr in unsupported_nodes
|
||||
)
|
||||
H.remove_edges_from(
|
||||
(n, nbr, d)
|
||||
for n, nbrs in G.adj.items()
|
||||
if n in unsupported_nodes
|
||||
for nbr, d in nbrs.items()
|
||||
if nbr in supported_nodes
|
||||
)
|
||||
|
||||
# Collect all removed edges for reconstruction.
|
||||
G_minus_H = nx.DiGraph()
|
||||
G_minus_H.add_edges_from(set(G.edges) - set(H.edges))
|
||||
|
||||
if plotting:
|
||||
# Plot the stripped graph with the edges removed.
|
||||
_node_colors = [c for _, c in H.nodes(data="node_color")]
|
||||
_pos = nx.spring_layout(H)
|
||||
plt.figure(figsize=(8, 8))
|
||||
nx.draw_networkx_edges(H, _pos, alpha=0.3, edge_color="k")
|
||||
nx.draw_networkx_nodes(H, _pos, node_color=_node_colors)
|
||||
nx.draw_networkx_labels(H, _pos, font_size=14)
|
||||
plt.axis("off")
|
||||
plt.title("The stripped graph with the edges removed.")
|
||||
plt.show()
|
||||
# Plot the the edges removed.
|
||||
_pos = nx.spring_layout(G_minus_H)
|
||||
plt.figure(figsize=(8, 8))
|
||||
ncl = [G.nodes[n]["node_color"] for n in G_minus_H.nodes]
|
||||
nx.draw_networkx_edges(G_minus_H, _pos, alpha=0.3, edge_color="k")
|
||||
nx.draw_networkx_nodes(G_minus_H, _pos, node_color=ncl)
|
||||
nx.draw_networkx_labels(G_minus_H, _pos, font_size=14)
|
||||
plt.axis("off")
|
||||
plt.title("The removed edges.")
|
||||
plt.show()
|
||||
|
||||
# Find the connected components in the stripped undirected graph.
|
||||
# And use the sets, specifying the components, to partition
|
||||
# the original directed graph into a list of directed subgraphs
|
||||
# that contain only entirely supported or entirely unsupported nodes.
|
||||
subgraphs = [
|
||||
H.subgraph(c).copy() for c in nx.connected_components(H.to_undirected())
|
||||
]
|
||||
|
||||
return subgraphs, G_minus_H
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Create an example directed graph.
|
||||
# ---------------------------------
|
||||
#
|
||||
# This directed graph has one input node labeled `in` and plotted in blue color
|
||||
# and one output node labeled `out` and plotted in magenta color.
|
||||
# The other six nodes are classified as four `supported` plotted in green color
|
||||
# and two `unsupported` plotted in red color. The goal is computing a list
|
||||
# of subgraphs that contain only entirely `supported` or `unsupported` nodes.
|
||||
G_ex = nx.DiGraph()
|
||||
G_ex.add_nodes_from(["In"], node_type="input", node_color="b")
|
||||
G_ex.add_nodes_from(["A", "C", "E", "F"], node_type="supported", node_color="g")
|
||||
G_ex.add_nodes_from(["B", "D"], node_type="unsupported", node_color="r")
|
||||
G_ex.add_nodes_from(["Out"], node_type="output", node_color="m")
|
||||
G_ex.add_edges_from(
|
||||
[
|
||||
("In", "A"),
|
||||
("A", "B"),
|
||||
("B", "C"),
|
||||
("B", "D"),
|
||||
("D", "E"),
|
||||
("C", "F"),
|
||||
("E", "F"),
|
||||
("F", "Out"),
|
||||
]
|
||||
)
|
||||
|
||||
###############################################################################
|
||||
# Plot the original graph.
|
||||
# ------------------------
|
||||
#
|
||||
node_color_list = [nc for _, nc in G_ex.nodes(data="node_color")]
|
||||
pos = nx.spectral_layout(G_ex)
|
||||
plt.figure(figsize=(8, 8))
|
||||
nx.draw_networkx_edges(G_ex, pos, alpha=0.3, edge_color="k")
|
||||
nx.draw_networkx_nodes(G_ex, pos, alpha=0.8, node_color=node_color_list)
|
||||
nx.draw_networkx_labels(G_ex, pos, font_size=14)
|
||||
plt.axis("off")
|
||||
plt.title("The original graph.")
|
||||
plt.show()
|
||||
|
||||
###############################################################################
|
||||
# Calculate the subgraphs with plotting all results of intemediate steps.
|
||||
# -----------------------------------------------------------------------
|
||||
#
|
||||
subgraphs_of_G_ex, removed_edges = graph_partitioning(G_ex, plotting=True)
|
||||
|
||||
###############################################################################
|
||||
# Plot the results: every subgraph in the list.
|
||||
# ---------------------------------------------
|
||||
#
|
||||
for subgraph in subgraphs_of_G_ex:
|
||||
_pos = nx.spring_layout(subgraph)
|
||||
plt.figure(figsize=(8, 8))
|
||||
nx.draw_networkx_edges(subgraph, _pos, alpha=0.3, edge_color="k")
|
||||
node_color_list_c = [nc for _, nc in subgraph.nodes(data="node_color")]
|
||||
nx.draw_networkx_nodes(subgraph, _pos, node_color=node_color_list_c)
|
||||
nx.draw_networkx_labels(subgraph, _pos, font_size=14)
|
||||
plt.axis("off")
|
||||
plt.title("One of the subgraphs.")
|
||||
plt.show()
|
||||
|
||||
###############################################################################
|
||||
# Put the graph back from the list of subgraphs
|
||||
# ---------------------------------------------
|
||||
#
|
||||
G_ex_r = nx.DiGraph()
|
||||
# Composing all subgraphs.
|
||||
for subgraph in subgraphs_of_G_ex:
|
||||
G_ex_r = nx.compose(G_ex_r, subgraph)
|
||||
# Adding the previously stored edges.
|
||||
G_ex_r.add_edges_from(removed_edges.edges())
|
||||
|
||||
###############################################################################
|
||||
# Check that the original graph and the reconstructed graphs are isomorphic.
|
||||
# --------------------------------------------------------------------------
|
||||
#
|
||||
assert nx.is_isomorphic(G_ex, G_ex_r)
|
||||
|
||||
###############################################################################
|
||||
# Plot the reconstructed graph.
|
||||
# -----------------------------
|
||||
#
|
||||
node_color_list = [nc for _, nc in G_ex_r.nodes(data="node_color")]
|
||||
pos = nx.spectral_layout(G_ex_r)
|
||||
plt.figure(figsize=(8, 8))
|
||||
nx.draw_networkx_edges(G_ex_r, pos, alpha=0.3, edge_color="k")
|
||||
nx.draw_networkx_nodes(G_ex_r, pos, alpha=0.8, node_color=node_color_list)
|
||||
nx.draw_networkx_labels(G_ex_r, pos, font_size=14)
|
||||
plt.axis("off")
|
||||
plt.title("The reconstructed graph.")
|
||||
plt.show()
|
||||
Reference in New Issue
Block a user