comment here

This commit is contained in:
ton
2023-03-18 20:03:34 +07:00
commit 4553a0a589
14513 changed files with 2685043 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
Graph
-----

View File

@@ -0,0 +1,42 @@
"""
========================
DAG - Topological Layout
========================
This example combines the `topological_generations` generator with
`multipartite_layout` to show how to visualize a DAG in topologically-sorted
order.
"""
import networkx as nx
import matplotlib.pyplot as plt
G = nx.DiGraph(
[
("f", "a"),
("a", "b"),
("a", "e"),
("b", "c"),
("b", "d"),
("d", "e"),
("f", "c"),
("f", "g"),
("h", "f"),
]
)
for layer, nodes in enumerate(nx.topological_generations(G)):
# `multipartite_layout` expects the layer as a node attribute, so add the
# numeric layer value as a node attribute
for node in nodes:
G.nodes[node]["layer"] = layer
# Compute the multipartite_layout using the "layer" node attribute
pos = nx.multipartite_layout(G, subset_key="layer")
fig, ax = plt.subplots()
nx.draw_networkx(G, pos=pos, ax=ax)
ax.set_title("DAG layout in topological order")
fig.tight_layout()
plt.show()

View File

@@ -0,0 +1,36 @@
"""
===============
Degree Sequence
===============
Random graph from given degree sequence.
"""
import matplotlib.pyplot as plt
import networkx as nx
# Specify seed for reproducibility
seed = 668273
z = [5, 3, 3, 3, 3, 2, 2, 2, 1, 1, 1]
print(nx.is_graphical(z))
print("Configuration model")
G = nx.configuration_model(
z, seed=seed
) # configuration model, seed for reproducibility
degree_sequence = [d for n, d in G.degree()] # degree sequence
print(f"Degree sequence {degree_sequence}")
print("Degree histogram")
hist = {}
for d in degree_sequence:
if d in hist:
hist[d] += 1
else:
hist[d] = 1
print("degree #nodes")
for d in hist:
print(f"{d:4} {hist[d]:6}")
pos = nx.spring_layout(G, seed=seed) # Seed layout for reproducibility
nx.draw(G, pos=pos)
plt.show()

View File

@@ -0,0 +1,36 @@
"""
===========
Erdos Renyi
===========
Create an G{n,m} random graph with n nodes and m edges
and report some properties.
This graph is sometimes called the Erdős-Rényi graph
but is different from G{n,p} or binomial_graph which is also
sometimes called the Erdős-Rényi graph.
"""
import matplotlib.pyplot as plt
import networkx as nx
n = 10 # 10 nodes
m = 20 # 20 edges
seed = 20160 # seed random number generators for reproducibility
# Use seed for reproducibility
G = nx.gnm_random_graph(n, m, seed=seed)
# some properties
print("node degree clustering")
for v in nx.nodes(G):
print(f"{v} {nx.degree(G, v)} {nx.clustering(G, v)}")
print()
print("the adjacency list")
for line in nx.generate_adjlist(G):
print(line)
pos = nx.spring_layout(G, seed=seed) # Seed for reproducible layout
nx.draw(G, pos=pos)
plt.show()

View File

@@ -0,0 +1,20 @@
"""
========================
Expected Degree Sequence
========================
Random graph from given degree sequence.
"""
import networkx as nx
# make a random graph of 500 nodes with expected degrees of 50
n = 500 # n nodes
p = 0.1
w = [p * n for i in range(n)] # w = p*n for all nodes
G = nx.expected_degree_graph(w) # configuration model
print("Degree histogram")
print("degree (#nodes) ****")
dh = nx.degree_histogram(G)
for i, d in enumerate(dh):
print(f"{i:2} ({d:2}) {'*'*d}")

View File

@@ -0,0 +1,44 @@
"""
========
Football
========
Load football network in GML format and compute some network statistcs.
Shows how to download GML graph in a zipped file, unpack it, and load
into a NetworkX graph.
Requires Internet connection to download the URL
http://www-personal.umich.edu/~mejn/netdata/football.zip
"""
import urllib.request
import io
import zipfile
import matplotlib.pyplot as plt
import networkx as nx
url = "http://www-personal.umich.edu/~mejn/netdata/football.zip"
sock = urllib.request.urlopen(url) # open URL
s = io.BytesIO(sock.read()) # read into BytesIO "file"
sock.close()
zf = zipfile.ZipFile(s) # zipfile object
txt = zf.read("football.txt").decode() # read info file
gml = zf.read("football.gml").decode() # read gml data
# throw away bogus first line with # from mejn files
gml = gml.split("\n")[1:]
G = nx.parse_gml(gml) # parse gml data
print(txt)
# print degree for each team - number of games
for n, d in G.degree():
print(f"{n:20} {d:2}")
options = {"node_color": "black", "node_size": 50, "linewidths": 0, "width": 0.1}
pos = nx.spring_layout(G, seed=1969) # Seed for reproducible layout
nx.draw(G, pos, **options)
plt.show()

View File

@@ -0,0 +1,25 @@
"""
===========
Karate Club
===========
Zachary's Karate Club graph
Data file from:
http://vlado.fmf.uni-lj.si/pub/networks/data/Ucinet/UciData.htm
Zachary W. (1977).
An information flow model for conflict and fission in small groups.
Journal of Anthropological Research, 33, 452-473.
"""
import matplotlib.pyplot as plt
import networkx as nx
G = nx.karate_club_graph()
print("Node Degree")
for v in G:
print(f"{v:4} {G.degree(v):6}")
nx.draw_circular(G, with_labels=True)
plt.show()

View File

@@ -0,0 +1,96 @@
"""
==========
Morse Trie
==========
A prefix tree (aka a "trie") representing the Morse encoding of the alphabet.
A letter can be encoded by tracing the path from the corresponding node in the
tree to the root node, reversing the order of the symbols encountered along
the path.
"""
import networkx as nx
# Unicode characters to represent the dots/dashes (or dits/dahs) of Morse code
dot = ""
dash = ""
# Start with the direct mapping of letter -> code
morse_direct_mapping = {
"a": dot + dash,
"b": dash + dot * 3,
"c": dash + dot + dash + dot,
"d": dash + dot * 2,
"e": dot,
"f": dot * 2 + dash + dot,
"g": dash * 2 + dot,
"h": dot * 4,
"i": dot * 2,
"j": dot + dash * 3,
"k": dash + dot + dash,
"l": dot + dash + dot * 2,
"m": dash * 2,
"n": dash + dot,
"o": dash * 3,
"p": dot + dash * 2 + dot,
"q": dash * 2 + dot + dash,
"r": dot + dash + dot,
"s": dot * 3,
"t": dash,
"u": dot * 2 + dash,
"v": dot * 3 + dash,
"w": dot + dash * 2,
"x": dash + dot * 2 + dash,
"y": dash + dot + dash * 2,
"z": dash * 2 + dot * 2,
}
### Manually construct the prefix tree from this mapping
# Some preprocessing: sort the original mapping by code length and character
# value
morse_mapping_sorted = dict(
sorted(morse_direct_mapping.items(), key=lambda item: (len(item[1]), item[1]))
)
# More preprocessing: create the reverse mapping to simplify lookup
reverse_mapping = {v: k for k, v in morse_direct_mapping.items()}
reverse_mapping[""] = "" # Represent the "root" node with an empty string
# Construct the prefix tree from the sorted mapping
G = nx.DiGraph()
for node, char in morse_mapping_sorted.items():
pred = char[:-1]
# Store the dot/dash relating the two letters as an edge attribute "char"
G.add_edge(reverse_mapping[pred], node, char=char[-1])
# For visualization purposes, layout the nodes in topological order
for i, layer in enumerate(nx.topological_generations(G)):
for n in layer:
G.nodes[n]["layer"] = i
pos = nx.multipartite_layout(G, subset_key="layer", align="horizontal")
# Flip the layout so the root node is on top
for k in pos:
pos[k][-1] *= -1
# Visualize the trie
nx.draw(G, pos=pos, with_labels=True)
elabels = {(u, v): l for u, v, l in G.edges(data="char")}
nx.draw_networkx_edge_labels(G, pos, edge_labels=elabels)
# A letter can be encoded by following the path from the given letter (node) to
# the root node
def morse_encode(letter):
pred = next(G.predecessors(letter)) # Each letter has only 1 predecessor
symbol = G[pred][letter]["char"]
if pred != "":
return morse_encode(pred) + symbol # Traversing the trie in reverse
return symbol
# Verify that the trie encoding is correct
import string
for letter in string.ascii_lowercase:
assert morse_encode(letter) == morse_direct_mapping[letter]
print(" ".join([morse_encode(ltr) for ltr in "ilovenetworkx"]))

View File

@@ -0,0 +1,133 @@
"""
=========================
Napoleon Russian Campaign
=========================
Minard's data from Napoleon's 1812-1813 Russian Campaign.
https://web.archive.org/web/20080112042656/http://www.math.yorku.ca/SCS/Gallery/minard/minard.txt
"""
import matplotlib.pyplot as plt
import networkx as nx
def minard_graph():
data1 = """\
24.0,54.9,340000,A,1
24.5,55.0,340000,A,1
25.5,54.5,340000,A,1
26.0,54.7,320000,A,1
27.0,54.8,300000,A,1
28.0,54.9,280000,A,1
28.5,55.0,240000,A,1
29.0,55.1,210000,A,1
30.0,55.2,180000,A,1
30.3,55.3,175000,A,1
32.0,54.8,145000,A,1
33.2,54.9,140000,A,1
34.4,55.5,127100,A,1
35.5,55.4,100000,A,1
36.0,55.5,100000,A,1
37.6,55.8,100000,A,1
37.7,55.7,100000,R,1
37.5,55.7,98000,R,1
37.0,55.0,97000,R,1
36.8,55.0,96000,R,1
35.4,55.3,87000,R,1
34.3,55.2,55000,R,1
33.3,54.8,37000,R,1
32.0,54.6,24000,R,1
30.4,54.4,20000,R,1
29.2,54.3,20000,R,1
28.5,54.2,20000,R,1
28.3,54.3,20000,R,1
27.5,54.5,20000,R,1
26.8,54.3,12000,R,1
26.4,54.4,14000,R,1
25.0,54.4,8000,R,1
24.4,54.4,4000,R,1
24.2,54.4,4000,R,1
24.1,54.4,4000,R,1"""
data2 = """\
24.0,55.1,60000,A,2
24.5,55.2,60000,A,2
25.5,54.7,60000,A,2
26.6,55.7,40000,A,2
27.4,55.6,33000,A,2
28.7,55.5,33000,R,2
29.2,54.2,30000,R,2
28.5,54.1,30000,R,2
28.3,54.2,28000,R,2"""
data3 = """\
24.0,55.2,22000,A,3
24.5,55.3,22000,A,3
24.6,55.8,6000,A,3
24.6,55.8,6000,R,3
24.2,54.4,6000,R,3
24.1,54.4,6000,R,3"""
cities = """\
24.0,55.0,Kowno
25.3,54.7,Wilna
26.4,54.4,Smorgoni
26.8,54.3,Moiodexno
27.7,55.2,Gloubokoe
27.6,53.9,Minsk
28.5,54.3,Studienska
28.7,55.5,Polotzk
29.2,54.4,Bobr
30.2,55.3,Witebsk
30.4,54.5,Orscha
30.4,53.9,Mohilow
32.0,54.8,Smolensk
33.2,54.9,Dorogobouge
34.3,55.2,Wixma
34.4,55.5,Chjat
36.0,55.5,Mojaisk
37.6,55.8,Moscou
36.6,55.3,Tarantino
36.5,55.0,Malo-Jarosewii"""
c = {}
for line in cities.split("\n"):
x, y, name = line.split(",")
c[name] = (float(x), float(y))
g = []
for data in [data1, data2, data3]:
G = nx.Graph()
i = 0
G.pos = {} # location
G.pop = {} # size
last = None
for line in data.split("\n"):
x, y, p, r, n = line.split(",")
G.pos[i] = (float(x), float(y))
G.pop[i] = int(p)
if last is None:
last = i
else:
G.add_edge(i, last, **{r: int(n)})
last = i
i = i + 1
g.append(G)
return g, c
(g, city) = minard_graph()
plt.figure(1, figsize=(11, 5))
plt.clf()
colors = ["b", "g", "r"]
for G in g:
c = colors.pop(0)
node_size = [G.pop[n] // 300 for n in G]
nx.draw_networkx_edges(G, G.pos, edge_color=c, width=4, alpha=0.5)
nx.draw_networkx_nodes(G, G.pos, node_size=node_size, node_color=c, alpha=0.5)
nx.draw_networkx_nodes(G, G.pos, node_size=5, node_color="k")
for c in city:
x, y = city[c]
plt.text(x, y + 0.1, c)
plt.show()

View File

@@ -0,0 +1,80 @@
"""
=====
Roget
=====
Build a directed graph of 1022 categories and 5075 cross-references as defined
in the 1879 version of Roget's Thesaurus. This example is described in Section
1.2 of
Donald E. Knuth, "The Stanford GraphBase: A Platform for Combinatorial
Computing", ACM Press, New York, 1993.
http://www-cs-faculty.stanford.edu/~knuth/sgb.html
Note that one of the 5075 cross references is a self loop yet it is included in
the graph built here because the standard networkx `DiGraph` class allows self
loops. (cf. 400pungency:400 401 403 405).
The data file can be found at:
- https://github.com/networkx/networkx/blob/main/examples/graph/roget_dat.txt.gz
"""
import gzip
import re
import sys
import matplotlib.pyplot as plt
import networkx as nx
def roget_graph():
"""Return the thesaurus graph from the roget.dat example in
the Stanford Graph Base.
"""
# open file roget_dat.txt.gz
fh = gzip.open("roget_dat.txt.gz", "r")
G = nx.DiGraph()
for line in fh.readlines():
line = line.decode()
if line.startswith("*"): # skip comments
continue
if line.startswith(" "): # this is a continuation line, append
line = oldline + line
if line.endswith("\\\n"): # continuation line, buffer, goto next
oldline = line.strip("\\\n")
continue
(headname, tails) = line.split(":")
# head
numfind = re.compile(r"^\d+") # re to find the number of this word
head = numfind.findall(headname)[0] # get the number
G.add_node(head)
for tail in tails.split():
if head == tail:
print("skipping self loop", head, tail, file=sys.stderr)
G.add_edge(head, tail)
return G
G = roget_graph()
print("Loaded roget_dat.txt containing 1022 categories.")
print(G)
UG = G.to_undirected()
print(nx.number_connected_components(UG), "connected components")
options = {
"node_color": "black",
"node_size": 1,
"edge_color": "gray",
"linewidths": 0,
"width": 0.1,
}
nx.draw_circular(UG, **options)
plt.show()

View File

@@ -0,0 +1,63 @@
"""
======
Triads
======
According to the paper by Snijders, T. (2012). “Transitivity and triads.”
University of Oxford, there are 16 Triad Types possible. This plot shows
the 16 Triad Types that can be identified within directed networks.
Triadic relationships are especially useful when analysing Social Networks.
The first three digits refer to the number of mutual, asymmetric and null
dyads (bidirectional, unidirection and nonedges) and the letter gives
the Orientation as Up (U), Down (D) , Cyclical (C) or Transitive (T).
"""
import networkx as nx
import matplotlib.pyplot as plt
fig, axes = plt.subplots(4, 4, figsize=(10, 10))
triads = {
"003": [],
"012": [(1, 2)],
"102": [(1, 2), (2, 1)],
"021D": [(3, 1), (3, 2)],
"021U": [(1, 3), (2, 3)],
"021C": [(1, 3), (3, 2)],
"111D": [(1, 2), (2, 1), (3, 1)],
"111U": [(1, 2), (2, 1), (1, 3)],
"030T": [(1, 2), (3, 2), (1, 3)],
"030C": [(1, 3), (3, 2), (2, 1)],
"201": [(1, 2), (2, 1), (3, 1), (1, 3)],
"120D": [(1, 2), (2, 1), (3, 1), (3, 2)],
"120U": [(1, 2), (2, 1), (1, 3), (2, 3)],
"120C": [(1, 2), (2, 1), (1, 3), (3, 2)],
"210": [(1, 2), (2, 1), (1, 3), (3, 2), (2, 3)],
"300": [(1, 2), (2, 1), (2, 3), (3, 2), (1, 3), (3, 1)],
}
for (title, triad), ax in zip(triads.items(), axes.flatten()):
G = nx.DiGraph()
G.add_nodes_from([1, 2, 3])
G.add_edges_from(triad)
nx.draw_networkx(
G,
ax=ax,
with_labels=False,
node_color=["green"],
node_size=200,
arrowsize=20,
width=2,
pos=nx.planar_layout(G),
)
ax.set_xlim(val * 1.2 for val in ax.get_xlim())
ax.set_ylim(val * 1.2 for val in ax.get_ylim())
ax.text(
0,
0,
title,
fontsize=15,
fontweight="extra bold",
horizontalalignment="center",
bbox=dict(boxstyle="square,pad=0.3", fc="none"),
)
fig.tight_layout()
plt.show()

View File

@@ -0,0 +1,88 @@
"""
==================
Words/Ladder Graph
==================
Generate an undirected graph over the 5757 5-letter words in the datafile
`words_dat.txt.gz`. Two words are connected by an edge if they differ in one
letter, resulting in 14,135 edges. This example is described in Section 1.1 of
Donald E. Knuth, "The Stanford GraphBase: A Platform for Combinatorial
Computing", ACM Press, New York, 1993.
http://www-cs-faculty.stanford.edu/~knuth/sgb.html
The data file can be found at:
- https://github.com/networkx/networkx/blob/main/examples/graph/words_dat.txt.gz
"""
import gzip
from string import ascii_lowercase as lowercase
import matplotlib.pyplot as plt
import networkx as nx
def generate_graph(words):
G = nx.Graph(name="words")
lookup = {c: lowercase.index(c) for c in lowercase}
def edit_distance_one(word):
for i in range(len(word)):
left, c, right = word[0:i], word[i], word[i + 1 :]
j = lookup[c] # lowercase.index(c)
for cc in lowercase[j + 1 :]:
yield left + cc + right
candgen = (
(word, cand)
for word in sorted(words)
for cand in edit_distance_one(word)
if cand in words
)
G.add_nodes_from(words)
for word, cand in candgen:
G.add_edge(word, cand)
return G
def words_graph():
"""Return the words example graph from the Stanford GraphBase"""
fh = gzip.open("words_dat.txt.gz", "r")
words = set()
for line in fh.readlines():
line = line.decode()
if line.startswith("*"):
continue
w = str(line[0:5])
words.add(w)
return generate_graph(words)
G = words_graph()
print("Loaded words_dat.txt containing 5757 five-letter English words.")
print("Two words are connected if they differ in one letter.")
print(G)
print(f"{nx.number_connected_components(G)} connected components")
for (source, target) in [("chaos", "order"), ("nodes", "graph"), ("pound", "marks")]:
print(f"Shortest path between {source} and {target} is")
try:
shortest_path = nx.shortest_path(G, source, target)
for n in shortest_path:
print(n)
except nx.NetworkXNoPath:
print("None")
# draw a subset of the graph
boundary = list(nx.node_boundary(G, shortest_path))
G.add_nodes_from(shortest_path, color="red")
G.add_nodes_from(boundary, color="blue")
H = G.subgraph(shortest_path + boundary)
colors = nx.get_node_attributes(H, "color")
options = {"node_size": 1500, "alpha": 0.3, "node_color": colors.values()}
pos = nx.kamada_kawai_layout(H)
nx.draw(H, pos, **options)
nx.draw_networkx_labels(H, pos, font_weight="bold")
plt.show()