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 @@
Drawing
-------

View File

@@ -0,0 +1,20 @@
"""
====================
Custom Node Position
====================
Draw a graph with node(s) located at user-defined positions.
When a position is set by the user, the other nodes can still be neatly organised in a layout.
"""
import networkx as nx
import numpy as np
G = nx.path_graph(20) # An example graph
center_node = 5 # Or any other node to be in the center
edge_nodes = set(G) - {center_node}
# Ensures the nodes around the circle are evenly distributed
pos = nx.circular_layout(G.subgraph(edge_nodes))
pos[center_node] = np.array([0, 0]) # manually specify node position
nx.draw(G, pos, with_labels=True)

View File

@@ -0,0 +1,152 @@
"""
=============
Chess Masters
=============
An example of the MultiDiGraph class.
The function `chess_pgn_graph` reads a collection of chess matches stored in
the specified PGN file (PGN ="Portable Game Notation"). Here the (compressed)
default file::
chess_masters_WCC.pgn.bz2
contains all 685 World Chess Championship matches from 1886--1985.
(data from http://chessproblem.my-free-games.com/chess/games/Download-PGN.php)
The `chess_pgn_graph()` function returns a `MultiDiGraph` with multiple edges.
Each node is the last name of a chess master. Each edge is directed from white
to black and contains selected game info.
The key statement in `chess_pgn_graph` below is::
G.add_edge(white, black, game_info)
where `game_info` is a `dict` describing each game.
"""
import matplotlib.pyplot as plt
import networkx as nx
# tag names specifying what game info should be
# stored in the dict on each digraph edge
game_details = ["Event", "Date", "Result", "ECO", "Site"]
def chess_pgn_graph(pgn_file="chess_masters_WCC.pgn.bz2"):
"""Read chess games in pgn format in pgn_file.
Filenames ending in .bz2 will be uncompressed.
Return the MultiDiGraph of players connected by a chess game.
Edges contain game data in a dict.
"""
import bz2
G = nx.MultiDiGraph()
game = {}
with bz2.BZ2File(pgn_file) as datafile:
lines = [line.decode().rstrip("\r\n") for line in datafile]
for line in lines:
if line.startswith("["):
tag, value = line[1:-1].split(" ", 1)
game[str(tag)] = value.strip('"')
else:
# empty line after tag set indicates
# we finished reading game info
if game:
white = game.pop("White")
black = game.pop("Black")
G.add_edge(white, black, **game)
game = {}
return G
G = chess_pgn_graph()
print(
f"Loaded {G.number_of_edges()} chess games between {G.number_of_nodes()} players\n"
)
# identify connected components of the undirected version
H = G.to_undirected()
Gcc = [H.subgraph(c) for c in nx.connected_components(H)]
if len(Gcc) > 1:
print(f"Note the disconnected component consisting of:\n{Gcc[1].nodes()}")
# find all games with B97 opening (as described in ECO)
openings = {game_info["ECO"] for (white, black, game_info) in G.edges(data=True)}
print(f"\nFrom a total of {len(openings)} different openings,")
print("the following games used the Sicilian opening")
print('with the Najdorff 7...Qb6 "Poisoned Pawn" variation.\n')
for (white, black, game_info) in G.edges(data=True):
if game_info["ECO"] == "B97":
summary = f"{white} vs {black}\n"
for k, v in game_info.items():
summary += f" {k}: {v}\n"
summary += "\n"
print(summary)
# make new undirected graph H without multi-edges
H = nx.Graph(G)
# edge width is proportional number of games played
edgewidth = [len(G.get_edge_data(u, v)) for u, v in H.edges()]
# node size is proportional to number of games won
wins = dict.fromkeys(G.nodes(), 0.0)
for (u, v, d) in G.edges(data=True):
r = d["Result"].split("-")
if r[0] == "1":
wins[u] += 1.0
elif r[0] == "1/2":
wins[u] += 0.5
wins[v] += 0.5
else:
wins[v] += 1.0
nodesize = [wins[v] * 50 for v in H]
# Generate layout for visualization
pos = nx.kamada_kawai_layout(H)
# Manual tweaking to limit node label overlap in the visualization
pos["Reshevsky, Samuel H"] += (0.05, -0.10)
pos["Botvinnik, Mikhail M"] += (0.03, -0.06)
pos["Smyslov, Vassily V"] += (0.05, -0.03)
fig, ax = plt.subplots(figsize=(12, 12))
# Visualize graph components
nx.draw_networkx_edges(H, pos, alpha=0.3, width=edgewidth, edge_color="m")
nx.draw_networkx_nodes(H, pos, node_size=nodesize, node_color="#210070", alpha=0.9)
label_options = {"ec": "k", "fc": "white", "alpha": 0.7}
nx.draw_networkx_labels(H, pos, font_size=14, bbox=label_options)
# Title/legend
font = {"fontname": "Helvetica", "color": "k", "fontweight": "bold", "fontsize": 14}
ax.set_title("World Chess Championship Games: 1886 - 1985", font)
# Change font color for legend
font["color"] = "r"
ax.text(
0.80,
0.10,
"edge width = # games played",
horizontalalignment="center",
transform=ax.transAxes,
fontdict=font,
)
ax.text(
0.80,
0.06,
"node size = # games won",
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()

View File

@@ -0,0 +1,75 @@
"""
=================
Custom node icons
=================
Example of using custom icons to represent nodes with matplotlib.
Images for node icons courtesy of www.materialui.co
"""
import matplotlib.pyplot as plt
import networkx as nx
import PIL
# Image URLs for graph nodes
icons = {
"router": "icons/router_black_144x144.png",
"switch": "icons/switch_black_144x144.png",
"PC": "icons/computer_black_144x144.png",
}
# Load images
images = {k: PIL.Image.open(fname) for k, fname in icons.items()}
# Generate the computer network graph
G = nx.Graph()
G.add_node("router", image=images["router"])
for i in range(1, 4):
G.add_node(f"switch_{i}", image=images["switch"])
for j in range(1, 4):
G.add_node("PC_" + str(i) + "_" + str(j), image=images["PC"])
G.add_edge("router", "switch_1")
G.add_edge("router", "switch_2")
G.add_edge("router", "switch_3")
for u in range(1, 4):
for v in range(1, 4):
G.add_edge("switch_" + str(u), "PC_" + str(u) + "_" + str(v))
# Get a reproducible layout and create figure
pos = nx.spring_layout(G, seed=1734289230)
fig, ax = plt.subplots()
# Note: the min_source/target_margin kwargs only work with FancyArrowPatch objects.
# Force the use of FancyArrowPatch for edge drawing by setting `arrows=True`,
# but suppress arrowheads with `arrowstyle="-"`
nx.draw_networkx_edges(
G,
pos=pos,
ax=ax,
arrows=True,
arrowstyle="-",
min_source_margin=15,
min_target_margin=15,
)
# Transform from data coordinates (scaled between xlim and ylim) to display coordinates
tr_figure = ax.transData.transform
# Transform from display to figure coordinates
tr_axes = fig.transFigure.inverted().transform
# Select the size of the image (relative to the X axis)
icon_size = (ax.get_xlim()[1] - ax.get_xlim()[0]) * 0.025
icon_center = icon_size / 2.0
# Add the respective image to each node
for n in G.nodes:
xf, yf = tr_figure(pos[n])
xa, ya = tr_axes((xf, yf))
# get overlapped axes and plot icon
a = plt.axes([xa - icon_center, ya - icon_center, icon_size, icon_size])
a.imshow(G.nodes[n]["image"])
a.axis("off")
plt.show()

View File

@@ -0,0 +1,50 @@
"""
===============
Degree Analysis
===============
This example shows several ways to visualize the distribution of the degree of
nodes with two common techniques: a *degree-rank plot* and a
*degree histogram*.
In this example, a random Graph is generated with 100 nodes. The degree of
each node is determined, and a figure is generated showing three things:
1. The subgraph of connected components
2. The degree-rank plot for the Graph, and
3. The degree histogram
"""
import networkx as nx
import numpy as np
import matplotlib.pyplot as plt
G = nx.gnp_random_graph(100, 0.02, seed=10374196)
degree_sequence = sorted((d for n, d in G.degree()), reverse=True)
dmax = max(degree_sequence)
fig = plt.figure("Degree of a random graph", figsize=(8, 8))
# Create a gridspec for adding subplots of different sizes
axgrid = fig.add_gridspec(5, 4)
ax0 = fig.add_subplot(axgrid[0:3, :])
Gcc = G.subgraph(sorted(nx.connected_components(G), key=len, reverse=True)[0])
pos = nx.spring_layout(Gcc, seed=10396953)
nx.draw_networkx_nodes(Gcc, pos, ax=ax0, node_size=20)
nx.draw_networkx_edges(Gcc, pos, ax=ax0, alpha=0.4)
ax0.set_title("Connected components of G")
ax0.set_axis_off()
ax1 = fig.add_subplot(axgrid[3:, :2])
ax1.plot(degree_sequence, "b-", marker="o")
ax1.set_title("Degree Rank Plot")
ax1.set_ylabel("Degree")
ax1.set_xlabel("Rank")
ax2 = fig.add_subplot(axgrid[3:, 2:])
ax2.bar(*np.unique(degree_sequence, return_counts=True))
ax2.set_title("Degree histogram")
ax2.set_xlabel("Degree")
ax2.set_ylabel("# of Nodes")
fig.tight_layout()
plt.show()

View File

@@ -0,0 +1,46 @@
"""
==============
Directed Graph
==============
Draw a graph with directed edges using a colormap and different node sizes.
Edges have different colors and alphas (opacity). Drawn using matplotlib.
"""
import matplotlib as mpl
import matplotlib.pyplot as plt
import networkx as nx
seed = 13648 # Seed random number generators for reproducibility
G = nx.random_k_out_graph(10, 3, 0.5, seed=seed)
pos = nx.spring_layout(G, seed=seed)
node_sizes = [3 + 10 * i for i in range(len(G))]
M = G.number_of_edges()
edge_colors = range(2, M + 2)
edge_alphas = [(5 + i) / (M + 4) for i in range(M)]
cmap = plt.cm.plasma
nodes = nx.draw_networkx_nodes(G, pos, node_size=node_sizes, node_color="indigo")
edges = nx.draw_networkx_edges(
G,
pos,
node_size=node_sizes,
arrowstyle="->",
arrowsize=10,
edge_color=edge_colors,
edge_cmap=cmap,
width=2,
)
# set alpha value for each edge
for i in range(M):
edges[i].set_alpha(edge_alphas[i])
pc = mpl.collections.PatchCollection(edges, cmap=cmap)
pc.set_array(edge_colors)
ax = plt.gca()
ax.set_axis_off()
plt.colorbar(pc, ax=ax)
plt.show()

View File

@@ -0,0 +1,23 @@
"""
=============
Edge Colormap
=============
Draw a graph with matplotlib, color edges.
"""
import matplotlib.pyplot as plt
import networkx as nx
G = nx.star_graph(20)
pos = nx.spring_layout(G, seed=63) # Seed layout for reproducibility
colors = range(20)
options = {
"node_color": "#A0CBE2",
"edge_color": colors,
"width": 4,
"edge_cmap": plt.cm.Blues,
"with_labels": False,
}
nx.draw(G, pos, **options)
plt.show()

View File

@@ -0,0 +1,35 @@
"""
=========
Ego Graph
=========
Example using the NetworkX ego_graph() function to return the main egonet of
the largest hub in a Barabási-Albert network.
"""
from operator import itemgetter
import matplotlib.pyplot as plt
import networkx as nx
# Create a BA model graph - use seed for reproducibility
n = 1000
m = 2
seed = 20532
G = nx.barabasi_albert_graph(n, m, seed=seed)
# find node with largest degree
node_and_degree = G.degree()
(largest_hub, degree) = sorted(node_and_degree, key=itemgetter(1))[-1]
# Create ego graph of main hub
hub_ego = nx.ego_graph(G, largest_hub)
# Draw graph
pos = nx.spring_layout(hub_ego, seed=seed) # Seed layout for reproducibility
nx.draw(hub_ego, pos, node_color="b", node_size=50, with_labels=False)
# Draw ego as large and red
options = {"node_size": 300, "node_color": "r"}
nx.draw_networkx_nodes(hub_ego, pos, nodelist=[largest_hub], **options)
plt.show()

View File

@@ -0,0 +1,22 @@
"""
===========
Eigenvalues
===========
Create an G{n,m} random graph and compute the eigenvalues.
"""
import matplotlib.pyplot as plt
import networkx as nx
import numpy.linalg
n = 1000 # 1000 nodes
m = 5000 # 5000 edges
G = nx.gnm_random_graph(n, m, seed=5040) # Seed for reproducibility
L = nx.normalized_laplacian_matrix(G)
e = numpy.linalg.eigvals(L.toarray())
print("Largest eigenvalue:", max(e))
print("Smallest eigenvalue:", min(e))
plt.hist(e, bins=100) # histogram with 100 bins
plt.xlim(0, 2) # eigenvalues between 0 and 2
plt.show()

View File

@@ -0,0 +1,52 @@
"""
==========
Four Grids
==========
Draw a 4x4 graph with matplotlib.
This example illustrates the use of keyword arguments to `networkx.draw` to
customize the visualization of a simple Graph comprising a 4x4 grid.
"""
import matplotlib.pyplot as plt
import networkx as nx
G = nx.grid_2d_graph(4, 4) # 4x4 grid
pos = nx.spring_layout(G, iterations=100, seed=39775)
# Create a 2x2 subplot
fig, all_axes = plt.subplots(2, 2)
ax = all_axes.flat
nx.draw(G, pos, ax=ax[0], font_size=8)
nx.draw(G, pos, ax=ax[1], node_size=0, with_labels=False)
nx.draw(
G,
pos,
ax=ax[2],
node_color="tab:green",
edgecolors="tab:gray", # Node surface color
edge_color="tab:gray", # Color of graph edges
node_size=250,
with_labels=False,
width=6,
)
H = G.to_directed()
nx.draw(
H,
pos,
ax=ax[3],
node_color="tab:orange",
node_size=20,
with_labels=False,
arrowsize=10,
width=2,
)
# Set margins for the axes so that nodes aren't clipped
for a in ax:
a.margins(0.10)
fig.tight_layout()
plt.show()

View File

@@ -0,0 +1,26 @@
"""
=================
House With Colors
=================
Draw a graph with matplotlib.
"""
import matplotlib.pyplot as plt
import networkx as nx
G = nx.house_graph()
# explicitly set positions
pos = {0: (0, 0), 1: (1, 0), 2: (0, 1), 3: (1, 1), 4: (0.5, 2.0)}
# Plot nodes with different properties for the "wall" and "roof" nodes
nx.draw_networkx_nodes(
G, pos, node_size=3000, nodelist=[0, 1, 2, 3], node_color="tab:blue"
)
nx.draw_networkx_nodes(G, pos, node_size=2000, nodelist=[4], node_color="tab:orange")
nx.draw_networkx_edges(G, pos, alpha=0.5, width=6)
# Customize axes
ax = plt.gca()
ax.margins(0.11)
plt.tight_layout()
plt.axis("off")
plt.show()

View File

@@ -0,0 +1,142 @@
"""
===========
Knuth Miles
===========
`miles_graph()` returns an undirected graph over 128 US cities. The
cities each have location and population data. The edges are labeled with the
distance between the two cities.
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/drawing/knuth_miles.txt.gz
"""
import gzip
import re
# Ignore any warnings related to downloading shpfiles with cartopy
import warnings
warnings.simplefilter("ignore")
import numpy as np
import matplotlib.pyplot as plt
import networkx as nx
def miles_graph():
"""Return the cites example graph in miles_dat.txt
from the Stanford GraphBase.
"""
# open file miles_dat.txt.gz (or miles_dat.txt)
fh = gzip.open("knuth_miles.txt.gz", "r")
G = nx.Graph()
G.position = {}
G.population = {}
cities = []
for line in fh.readlines():
line = line.decode()
if line.startswith("*"): # skip comments
continue
numfind = re.compile(r"^\d+")
if numfind.match(line): # this line is distances
dist = line.split()
for d in dist:
G.add_edge(city, cities[i], weight=int(d))
i = i + 1
else: # this line is a city, position, population
i = 1
(city, coordpop) = line.split("[")
cities.insert(0, city)
(coord, pop) = coordpop.split("]")
(y, x) = coord.split(",")
G.add_node(city)
# assign position - Convert string to lat/long
G.position[city] = (-float(x) / 100, float(y) / 100)
G.population[city] = float(pop) / 1000
return G
G = miles_graph()
print("Loaded miles_dat.txt containing 128 cities.")
print(G)
# make new graph of cites, edge if less then 300 miles between them
H = nx.Graph()
for v in G:
H.add_node(v)
for (u, v, d) in G.edges(data=True):
if d["weight"] < 300:
H.add_edge(u, v)
# draw with matplotlib/pylab
fig = plt.figure(figsize=(8, 6))
# nodes colored by degree sized by population
node_color = [float(H.degree(v)) for v in H]
# Use cartopy to provide a backdrop for the visualization
try:
import cartopy.crs as ccrs
import cartopy.io.shapereader as shpreader
ax = fig.add_axes([0, 0, 1, 1], projection=ccrs.LambertConformal(), frameon=False)
ax.set_extent([-125, -66.5, 20, 50], ccrs.Geodetic())
# Add map of countries & US states as a backdrop
for shapename in ("admin_1_states_provinces_lakes_shp", "admin_0_countries"):
shp = shpreader.natural_earth(
resolution="110m", category="cultural", name=shapename
)
ax.add_geometries(
shpreader.Reader(shp).geometries(),
ccrs.PlateCarree(),
facecolor="none",
edgecolor="k",
)
# NOTE: When using cartopy, use matplotlib directly rather than nx.draw
# to take advantage of the cartopy transforms
ax.scatter(
*np.array([v for v in G.position.values()]).T,
s=[G.population[v] for v in H],
c=node_color,
transform=ccrs.PlateCarree(),
zorder=100 # Ensure nodes lie on top of edges/state lines
)
# Plot edges between the cities
for edge in H.edges():
edge_coords = np.array([G.position[v] for v in edge])
ax.plot(
edge_coords[:, 0],
edge_coords[:, 1],
transform=ccrs.PlateCarree(),
linewidth=0.75,
color="k",
)
except ImportError:
# If cartopy is unavailable, the backdrop for the plot will be blank;
# though you should still be able to discern the general shape of the US
# from graph nodes and edges!
nx.draw(
H,
G.position,
node_size=[G.population[v] for v in H],
node_color=node_color,
with_labels=False,
)
plt.show()

View File

@@ -0,0 +1,54 @@
"""
=================
Labels And Colors
=================
Use `nodelist` and `edgelist` to apply custom coloring and labels to various
components of a graph.
"""
import matplotlib.pyplot as plt
import networkx as nx
G = nx.cubical_graph()
pos = nx.spring_layout(G, seed=3113794652) # positions for all nodes
# nodes
options = {"edgecolors": "tab:gray", "node_size": 800, "alpha": 0.9}
nx.draw_networkx_nodes(G, pos, nodelist=[0, 1, 2, 3], node_color="tab:red", **options)
nx.draw_networkx_nodes(G, pos, nodelist=[4, 5, 6, 7], node_color="tab:blue", **options)
# edges
nx.draw_networkx_edges(G, pos, width=1.0, alpha=0.5)
nx.draw_networkx_edges(
G,
pos,
edgelist=[(0, 1), (1, 2), (2, 3), (3, 0)],
width=8,
alpha=0.5,
edge_color="tab:red",
)
nx.draw_networkx_edges(
G,
pos,
edgelist=[(4, 5), (5, 6), (6, 7), (7, 4)],
width=8,
alpha=0.5,
edge_color="tab:blue",
)
# some math labels
labels = {}
labels[0] = r"$a$"
labels[1] = r"$b$"
labels[2] = r"$c$"
labels[3] = r"$d$"
labels[4] = r"$\alpha$"
labels[5] = r"$\beta$"
labels[6] = r"$\gamma$"
labels[7] = r"$\delta$"
nx.draw_networkx_labels(G, pos, labels, font_size=22, font_color="whitesmoke")
plt.tight_layout()
plt.axis("off")
plt.show()

View File

@@ -0,0 +1,41 @@
"""
===================
Multipartite Layout
===================
"""
import itertools
import matplotlib.pyplot as plt
import networkx as nx
subset_sizes = [5, 5, 4, 3, 2, 4, 4, 3]
subset_color = [
"gold",
"violet",
"violet",
"violet",
"violet",
"limegreen",
"limegreen",
"darkorange",
]
def multilayered_graph(*subset_sizes):
extents = nx.utils.pairwise(itertools.accumulate((0,) + subset_sizes))
layers = [range(start, end) for start, end in extents]
G = nx.Graph()
for (i, layer) in enumerate(layers):
G.add_nodes_from(layer, layer=i)
for layer1, layer2 in nx.utils.pairwise(layers):
G.add_edges_from(itertools.product(layer1, layer2))
return G
G = multilayered_graph(*subset_sizes)
color = [subset_color[data["layer"]] for v, data in G.nodes(data=True)]
pos = nx.multipartite_layout(G, subset_key="layer")
plt.figure(figsize=(8, 8))
nx.draw(G, pos, node_color=color, with_labels=False)
plt.axis("equal")
plt.show()

View File

@@ -0,0 +1,15 @@
"""
=============
Node Colormap
=============
Draw a graph with matplotlib, color by degree.
"""
import matplotlib.pyplot as plt
import networkx as nx
G = nx.cycle_graph(24)
pos = nx.circular_layout(G)
nx.draw(G, pos, node_color=range(24), node_size=800, cmap=plt.cm.Blues)
plt.show()

View File

@@ -0,0 +1,68 @@
"""
================
Rainbow Coloring
================
Generate a complete graph with 13 nodes in a circular layout with the
edges colored by node distance. The node distance is given by the minimum
number of nodes traversed along an arc between any two nodes on the circle.
Such graphs are the subject of Ringel's conjecture, which states: any complete
graph with ``2n + 1`` nodes can be tiled by any tree with ``n + 1`` nodes
(i.e. copies of the tree can be placed over the complete graph such that each
edge in the complete graph is covered exactly once). The edge coloring is
helpful in determining how to place the tree copies.
References
----------
https://www.quantamagazine.org/mathematicians-prove-ringels-graph-theory-conjecture-20200219/
"""
import matplotlib.pyplot as plt
import networkx as nx
# A rainbow color mapping using matplotlib's tableau colors
node_dist_to_color = {
1: "tab:red",
2: "tab:orange",
3: "tab:olive",
4: "tab:green",
5: "tab:blue",
6: "tab:purple",
}
# Create a complete graph with an odd number of nodes
nnodes = 13
G = nx.complete_graph(nnodes)
# A graph with (2n + 1) nodes requires n colors for the edges
n = (nnodes - 1) // 2
ndist_iter = list(range(1, n + 1))
# Take advantage of circular symmetry in determining node distances
ndist_iter += ndist_iter[::-1]
def cycle(nlist, n):
return nlist[-n:] + nlist[:-n]
# Rotate nodes around the circle and assign colors for each edge based on
# node distance
nodes = list(G.nodes())
for i, nd in enumerate(ndist_iter):
for u, v in zip(nodes, cycle(nodes, i + 1)):
G[u][v]["color"] = node_dist_to_color[nd]
pos = nx.circular_layout(G)
# Create a figure with 1:1 aspect ratio to preserve the circle.
fig, ax = plt.subplots(figsize=(8, 8))
node_opts = {"node_size": 500, "node_color": "w", "edgecolors": "k", "linewidths": 2.0}
nx.draw_networkx_nodes(G, pos, **node_opts)
nx.draw_networkx_labels(G, pos, font_size=14)
# Extract color from edge data
edge_colors = [edgedata["color"] for _, _, edgedata in G.edges(data=True)]
nx.draw_networkx_edges(G, pos, width=2.0, edge_color=edge_colors)
ax.set_axis_off()
fig.tight_layout()
plt.show()

View File

@@ -0,0 +1,44 @@
"""
======================
Random Geometric Graph
======================
Example
"""
import matplotlib.pyplot as plt
import networkx as nx
# Use seed when creating the graph for reproducibility
G = nx.random_geometric_graph(200, 0.125, seed=896803)
# position is stored as node attribute data for random_geometric_graph
pos = nx.get_node_attributes(G, "pos")
# find node near center (0.5,0.5)
dmin = 1
ncenter = 0
for n in pos:
x, y = pos[n]
d = (x - 0.5) ** 2 + (y - 0.5) ** 2
if d < dmin:
ncenter = n
dmin = d
# color by path length from node near center
p = dict(nx.single_source_shortest_path_length(G, ncenter))
plt.figure(figsize=(8, 8))
nx.draw_networkx_edges(G, pos, alpha=0.4)
nx.draw_networkx_nodes(
G,
pos,
nodelist=list(p.keys()),
node_size=80,
node_color=list(p.values()),
cmap=plt.cm.Reds_r,
)
plt.xlim(-0.05, 1.05)
plt.ylim(-0.05, 1.05)
plt.axis("off")
plt.show()

View File

@@ -0,0 +1,47 @@
"""
=======
Sampson
=======
Sampson's monastery data.
Shows how to read data from a zip file and plot multiple frames.
The data file can be found at:
- https://github.com/networkx/networkx/blob/main/examples/drawing/sampson_data.zip
"""
import zipfile
from io import BytesIO as StringIO
import matplotlib.pyplot as plt
import networkx as nx
with zipfile.ZipFile("sampson_data.zip") as zf:
e1 = StringIO(zf.read("samplike1.txt"))
e2 = StringIO(zf.read("samplike2.txt"))
e3 = StringIO(zf.read("samplike3.txt"))
G1 = nx.read_edgelist(e1, delimiter="\t")
G2 = nx.read_edgelist(e2, delimiter="\t")
G3 = nx.read_edgelist(e3, delimiter="\t")
pos = nx.spring_layout(G3, iterations=100, seed=173)
plt.clf()
plt.subplot(221)
plt.title("samplike1")
nx.draw(G1, pos, node_size=50, with_labels=False)
plt.subplot(222)
plt.title("samplike2")
nx.draw(G2, pos, node_size=50, with_labels=False)
plt.subplot(223)
plt.title("samplike3")
nx.draw(G3, pos, node_size=50, with_labels=False)
plt.subplot(224)
plt.title("samplike1,2,3")
nx.draw(G3, pos, edgelist=list(G3.edges()), node_size=50, with_labels=False)
nx.draw_networkx_edges(G1, pos, alpha=0.25)
nx.draw_networkx_edges(G2, pos, alpha=0.25)
plt.tight_layout()
plt.show()

View File

@@ -0,0 +1,29 @@
"""
==========
Self-loops
==========
A self-loop is an edge that originates from and terminates the same node.
This example shows how to draw self-loops with `nx_pylab`.
"""
import networkx as nx
import matplotlib.pyplot as plt
# Create a graph and add a self-loop to node 0
G = nx.complete_graph(3, create_using=nx.DiGraph)
G.add_edge(0, 0)
pos = nx.circular_layout(G)
# As of version 2.6, self-loops are drawn by default with the same styling as
# other edges
nx.draw(G, pos, with_labels=True)
# Add self-loops to the remaining nodes
edgelist = [(1, 1), (2, 2)]
G.add_edges_from(edgelist)
# Draw the newly added self-loops with different formatting
nx.draw_networkx_edges(G, pos, edgelist=edgelist, arrowstyle="<|-", style="dashed")
plt.show()

View File

@@ -0,0 +1,14 @@
"""
===========
Simple Path
===========
Draw a graph with matplotlib.
"""
import matplotlib.pyplot as plt
import networkx as nx
G = nx.path_graph(8)
pos = nx.spring_layout(G, seed=47) # Seed layout for reproducibility
nx.draw(G, pos=pos)
plt.show()

View File

@@ -0,0 +1,58 @@
"""
==================
Spectral Embedding
==================
The spectral layout positions the nodes of the graph based on the
eigenvectors of the graph Laplacian $L = D - A$, where $A$ is the
adjacency matrix and $D$ is the degree matrix of the graph.
By default, the spectral layout will embed the graph in two
dimensions (you can embed your graph in other dimensions using the
``dim`` argument to either :func:`~drawing.nx_pylab.draw_spectral` or
:func:`~drawing.layout.spectral_layout`).
When the edges of the graph represent similarity between the incident
nodes, the spectral embedding will place highly similar nodes closer
to one another than nodes which are less similar.
This is particularly striking when you spectrally embed a grid
graph. In the full grid graph, the nodes in the center of the
graph are pulled apart more than nodes on the periphery.
As you remove internal nodes, this effect increases.
"""
import matplotlib.pyplot as plt
import networkx as nx
options = {"node_color": "C0", "node_size": 100}
G = nx.grid_2d_graph(6, 6)
plt.subplot(332)
nx.draw_spectral(G, **options)
G.remove_edge((2, 2), (2, 3))
plt.subplot(334)
nx.draw_spectral(G, **options)
G.remove_edge((3, 2), (3, 3))
plt.subplot(335)
nx.draw_spectral(G, **options)
G.remove_edge((2, 2), (3, 2))
plt.subplot(336)
nx.draw_spectral(G, **options)
G.remove_edge((2, 3), (3, 3))
plt.subplot(337)
nx.draw_spectral(G, **options)
G.remove_edge((1, 2), (1, 3))
plt.subplot(338)
nx.draw_spectral(G, **options)
G.remove_edge((4, 2), (4, 3))
plt.subplot(339)
nx.draw_spectral(G, **options)
plt.show()

View File

@@ -0,0 +1,52 @@
"""
==========================
Traveling Salesman Problem
==========================
This is an example of a drawing solution of the traveling salesman problem
The function is used to produce the solution is christofides,
where given a set of nodes, it calculates the route of the nodes
that the traveler has to follow in order to minimize the total cost.
"""
import matplotlib.pyplot as plt
import networkx as nx
import networkx.algorithms.approximation as nx_app
import math
G = nx.random_geometric_graph(20, radius=0.4, seed=3)
pos = nx.get_node_attributes(G, "pos")
# Depot should be at (0,0)
pos[0] = (0.5, 0.5)
H = G.copy()
# Calculating the distances between the nodes as edge's weight.
for i in range(len(pos)):
for j in range(i + 1, len(pos)):
dist = math.hypot(pos[i][0] - pos[j][0], pos[i][1] - pos[j][1])
dist = dist
G.add_edge(i, j, weight=dist)
cycle = nx_app.christofides(G, weight="weight")
edge_list = list(nx.utils.pairwise(cycle))
# Draw closest edges on each node only
nx.draw_networkx_edges(H, pos, edge_color="blue", width=0.5)
# Draw the route
nx.draw_networkx(
G,
pos,
with_labels=True,
edgelist=edge_list,
edge_color="red",
node_size=200,
width=3,
)
print("The route of the traveller is:", cycle)
plt.show()

View File

@@ -0,0 +1,62 @@
"""
==========
Unix Email
==========
Create a directed graph, allowing multiple edges and self loops, from a unix
mailbox. The nodes are email addresses with links that point from the sender
to the receivers. The edge data is a Python email.Message object which
contains all of the email message data.
This example shows the power of `DiGraph` to hold edge data of arbitrary Python
objects (in this case a list of email messages).
The sample unix email mailbox called "unix_email.mbox" may be found here:
- https://github.com/networkx/networkx/blob/main/examples/drawing/unix_email.mbox
"""
from email.utils import getaddresses, parseaddr
import mailbox
import matplotlib.pyplot as plt
import networkx as nx
# unix mailbox recipe
# see https://docs.python.org/3/library/mailbox.html
def mbox_graph():
mbox = mailbox.mbox("unix_email.mbox") # parse unix mailbox
G = nx.MultiDiGraph() # create empty graph
# parse each messages and build graph
for msg in mbox: # msg is python email.Message.Message object
(source_name, source_addr) = parseaddr(msg["From"]) # sender
# get all recipients
# see https://docs.python.org/3/library/email.html
tos = msg.get_all("to", [])
ccs = msg.get_all("cc", [])
resent_tos = msg.get_all("resent-to", [])
resent_ccs = msg.get_all("resent-cc", [])
all_recipients = getaddresses(tos + ccs + resent_tos + resent_ccs)
# now add the edges for this mail message
for (target_name, target_addr) in all_recipients:
G.add_edge(source_addr, target_addr, message=msg)
return G
G = mbox_graph()
# print edges with message subject
for (u, v, d) in G.edges(data=True):
print(f"From: {u} To: {v} Subject: {d['message']['Subject']}")
pos = nx.spring_layout(G, iterations=10, seed=227)
nx.draw(G, pos, node_size=0, alpha=0.4, edge_color="r", font_size=16, with_labels=True)
ax = plt.gca()
ax.margins(0.08)
plt.show()

View File

@@ -0,0 +1,44 @@
"""
==============
Weighted Graph
==============
An example using Graph as a weighted network.
"""
import matplotlib.pyplot as plt
import networkx as nx
G = nx.Graph()
G.add_edge("a", "b", weight=0.6)
G.add_edge("a", "c", weight=0.2)
G.add_edge("c", "d", weight=0.1)
G.add_edge("c", "e", weight=0.7)
G.add_edge("c", "f", weight=0.9)
G.add_edge("a", "d", weight=0.3)
elarge = [(u, v) for (u, v, d) in G.edges(data=True) if d["weight"] > 0.5]
esmall = [(u, v) for (u, v, d) in G.edges(data=True) if d["weight"] <= 0.5]
pos = nx.spring_layout(G, seed=7) # positions for all nodes - seed for reproducibility
# nodes
nx.draw_networkx_nodes(G, pos, node_size=700)
# edges
nx.draw_networkx_edges(G, pos, edgelist=elarge, width=6)
nx.draw_networkx_edges(
G, pos, edgelist=esmall, width=6, alpha=0.5, edge_color="b", style="dashed"
)
# node labels
nx.draw_networkx_labels(G, pos, font_size=20, font_family="sans-serif")
# edge weight labels
edge_labels = nx.get_edge_attributes(G, "weight")
nx.draw_networkx_edge_labels(G, pos, edge_labels)
ax = plt.gca()
ax.margins(0.08)
plt.axis("off")
plt.tight_layout()
plt.show()

View File

@@ -0,0 +1,84 @@
From alice@edu Thu Jun 16 16:12:12 2005
From: Alice <alice@edu>
Subject: NetworkX
Date: Thu, 16 Jun 2005 16:12:13 -0700
To: Bob <bob@gov>
Status: RO
Content-Length: 86
Lines: 5
Bob, check out the new networkx release - you and
Carol might really like it.
Alice
From bob@gov Thu Jun 16 18:13:12 2005
Return-Path: <bob@gov>
Subject: Re: NetworkX
From: Bob <bob@gov>
To: Alice <alice@edu>
Content-Type: text/plain
Date: Thu, 16 Jun 2005 18:13:12 -0700
Status: RO
Content-Length: 26
Lines: 4
Thanks for the tip.
Bob
From ted@com Thu Jul 28 09:53:31 2005
Return-Path: <ted@com>
Subject: Graph package in Python?
From: Ted <ted@com>
To: Bob <bob@gov>
Content-Type: text/plain
Date: Thu, 28 Jul 2005 09:47:03 -0700
Status: RO
Content-Length: 90
Lines: 3
Hey Ted - I'm looking for a Python package for
graphs and networks. Do you know of any?
From bob@gov Thu Jul 28 09:59:31 2005
Return-Path: <bob@gov>
Subject: Re: Graph package in Python?
From: Bob <bob@gov>
To: Ted <ted@com>
Content-Type: text/plain
Date: Thu, 28 Jul 2005 09:59:03 -0700
Status: RO
Content-Length: 180
Lines: 9
Check out the NetworkX package - Alice sent me the tip!
Bob
>> bob@gov scrawled:
>> Hey Ted - I'm looking for a Python package for
>> graphs and networks. Do you know of any?
From ted@com Thu Jul 28 15:53:31 2005
Return-Path: <ted@com>
Subject: get together for lunch to discuss Networks?
From: Ted <ted@com>
To: Bob <bob@gov>, Carol <carol@gov>, Alice <alice@edu>
Content-Type: text/plain
Date: Thu, 28 Jul 2005 15:47:03 -0700
Status: RO
Content-Length: 139
Lines: 5
Hey everyrone! Want to meet at that restaurant on the
island in Konigsburg tonight? Bring your laptops
and we can install NetworkX.
Ted