Skip to content

Commit 991e83d

Browse files
20kavishsrossbarMridulSdschult
authored
Improve consistency across notebooks (#98)
* Standardize * Update sudoku.md * Changed links back to old form * change versions back to original * add back ipykernel * clean up, make pre-commit happy * make pre-commit happy * Fix typo. * Rm unnecessary warnings filter. * Fix footnote format. * Condense heading. * More canonical way to create DiGraph. * Condense headings. * Fix header level in flow. * Typo. * Fix heading level. * More heading fixes. * Resolved suggestions * MAINT: changing white text logo to gray banner (#105) * Isomorphism tutorial (#83) Add a high-level notebook introducing isomorphism and the related functionality in NetworkX Co-authored-by: Mridul Seth <mail@mriduls.com> Co-authored-by: Ross Barnowski <rossbar@berkeley.edu> Co-authored-by: Mridul Seth <git@mriduls.com> * Add Python 3.11 to the CI. (#107) * Rm colab cruft. (#106) * created and then removed traversal notebook draft 1 * try converting with jupytext for tests again * test all notebooks except the long exploratory ones * restore the python versions field in tests * Fixup missing ref in Dinitz nb. --------- Co-authored-by: Ross Barnowski <rossbar@berkeley.edu> Co-authored-by: Mridul Seth <mail@mriduls.com> Co-authored-by: Dan Schult <dschult@colgate.edu>
1 parent fd60ff4 commit 991e83d

File tree

10 files changed

+149
-86
lines changed

10 files changed

+149
-86
lines changed

.github/workflows/notebooks.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,7 @@ jobs:
4747
4848
- name: Test with nbval
4949
run: |
50+
find content/algorithms content/generators -name "*.md" -exec jupytext --to notebook {} \;
51+
find content/algorithms content/generators -name "*.ipynb" -print
5052
pip install pytest
51-
pytest --nbval-lax --durations=25 content/
53+
pytest --nbval-lax --durations=25 content/algorithms content/generators

content/algorithms/assortativity/correlation.md

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,29 @@ language_info:
2222
version: 3.8.5
2323
---
2424

25-
# Node assortativity coefficients and correlation measures
25+
# Node Assortativity Coefficients and Correlation Measures
2626

27-
In this tutorial, we will go through the theory of [assortativity](https://en.wikipedia.org/wiki/Assortativity) and its measures.
27+
In this tutorial, we will explore the theory of assortativity [^1] and its measures.
2828

29-
Specifically, we'll focus on assortativity measures available in NetworkX at [algorithms/assortativity/correlation.py](https://github.com/networkx/networkx/blob/main/networkx/algorithms/assortativity/correlation.py):
29+
We'll focus on assortativity measures available in NetworkX at [`algorithms/assortativity/correlation.py`](https://github.com/networkx/networkx/blob/main/networkx/algorithms/assortativity/correlation.py):
3030
* Attribute assortativity
3131
* Numeric assortativity
3232
* Degree assortativity
3333

34-
as well as mixing matrices, which are closely releated to assortativity measures.
34+
as well as mixing matrices, which are closely related to assortativity measures.
35+
36+
## Import packages
37+
38+
```{code-cell} ipython3
39+
import networkx as nx
40+
import matplotlib.pyplot as plt
41+
import pickle
42+
import copy
43+
import random
44+
import warnings
45+
46+
%matplotlib inline
47+
```
3548

3649
## Assortativity
3750

@@ -80,7 +93,7 @@ Pearson correlation coefficient.
8093

8194
Here the property $P(v)$ is a nominal property assigned to each node.
8295
As defined above we calculate the normalized mixing matrix $e$ and from that we
83-
define the attribute assortativity coefficient [^1] as below.
96+
define the attribute assortativity coefficient [^2] as below.
8497

8598
From here onwards we will use subscript notation to denote indexing, for eg. $P_i = P[i]$ and $e_{ij} = e[i][j]$
8699

@@ -93,7 +106,7 @@ It is implemented as `attribute_assortativity_coefficient`.
93106
Here the property $P(v)$ is a numerical property assigned to each
94107
node and the definition of the normalized mixing
95108
matrix $e$, $\sigma_a$, and $\sigma_b$ are same as above.
96-
From these we define numeric assortativity coefficient [^1] as below.
109+
From these we define numeric assortativity coefficient [^2] as below.
97110

98111
$$ r = \frac{\sum\limits_{i,j}P_i P_j(e_{ij} -a_i b_j)}{\sigma_a\sigma_b} $$
99112

@@ -105,7 +118,7 @@ When it comes to measuring degree assortativity for directed networks we have
105118
more options compared to assortativity w.r.t a property because we have 2 types
106119
of degrees, namely in-degree and out-degree.
107120
Based on the 2 types of degrees we can measure $2 \times 2 =4$ different types
108-
of degree assortativity [^2]:
121+
of degree assortativity [^3]:
109122

110123
1. r(in,in) : Measures tendency of having a directed edge (u,v) such that, in-degree(u) = in-degree(v).
111124
2. r(in,out) : Measures tendency of having a directed edge (u,v) such that, in-degree(u) = out-degree(v).
@@ -130,25 +143,14 @@ It is implemented as `degree_assortativity_coefficient` and
130143
`scipy.stats.pearsonr` to calculate the assortativity coefficient which makes
131144
it potentally faster.
132145

133-
## Example
146+
## Assortativity Example
134147

135-
```{code-cell} ipython3
136-
%matplotlib inline
137-
import networkx as nx
138-
import matplotlib.pyplot as plt
139-
import pickle
140-
import copy
141-
import random
142-
import warnings
143-
144-
warnings.filterwarnings("ignore")
145-
```
148+
+++
146149

147150
Illustrating how value of assortativity changes
148151

149152
```{code-cell} ipython3
150153
gname = "g2"
151-
# loading the graph
152154
G = nx.read_graphml(f"data/{gname}.graphml")
153155
with open(f"data/pos_{gname}", "rb") as fp:
154156
pos = pickle.load(fp)
@@ -261,6 +263,10 @@ are drawn.
261263

262264
+++
263265

264-
[^1]: M. E. J. Newman, Mixing patterns in networks <https://doi.org/10.1103/PhysRevE.67.026126>
266+
## References
267+
268+
[^1]: [Wikipedia, Assortativity](https://en.wikipedia.org/wiki/Assortativity)
269+
270+
[^2]: M. E. J. Newman, Mixing patterns in networks <https://doi.org/10.1103/PhysRevE.67.026126>
265271

266-
[^2]: Foster, J.G., Foster, D.V., Grassberger, P. & Paczuski, M. Edge direction and the structure of networks <https://doi.org/10.1073/pnas.0912671107>
272+
[^3]: Foster, J.G., Foster, D.V., Grassberger, P. & Paczuski, M. Edge direction and the structure of networks <https://doi.org/10.1073/pnas.0912671107>

content/algorithms/dag/index.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,25 +25,24 @@ language_info:
2525
# Directed Acyclic Graphs & Topological Sort
2626

2727
In this tutorial, we will explore the algorithms related to a directed acyclic graph
28-
(or a "dag" as it is sometimes called) implemented in networkx under `networkx/algorithms/dag.py`.
28+
(or a "DAG" as it is sometimes called) implemented in NetworkX under [`networkx/algorithms/dag.py`](https://github.com/networkx/networkx/blob/main/networkx/algorithms/dag.py).
2929

3030
First of all, we need to understand what a directed graph is.
3131

32-
## Directed Graph
33-
34-
### Example
32+
## Import packages
3533

3634
```{code-cell} ipython3
37-
%matplotlib inline
3835
import networkx as nx
3936
import matplotlib.pyplot as plt
40-
```
37+
import inspect
4138
42-
```{code-cell} ipython3
43-
triangle_graph = nx.from_edgelist([(1, 2), (2, 3), (3, 1)], create_using=nx.DiGraph)
39+
%matplotlib inline
4440
```
4541

42+
## Example: Directed Graphs
43+
4644
```{code-cell} ipython3
45+
triangle_graph = nx.DiGraph([(1, 2), (2, 3), (3, 1)])
4746
nx.draw_planar(
4847
triangle_graph,
4948
with_labels=True,
@@ -75,7 +74,6 @@ clothing_graph = nx.read_graphml(f"data/clothing_graph.graphml")
7574

7675
```{code-cell} ipython3
7776
plt.figure(figsize=(12, 12), dpi=150)
78-
7977
nx.draw_planar(
8078
clothing_graph,
8179
arrowsize=12,
@@ -164,7 +162,7 @@ Then, a topological sort gives an order in which to perform the jobs.
164162

165163
A closely related application of topological sorting algorithms
166164
was first studied in the early 1960s in the context of the
167-
[PERT technique](https://en.wikipedia.org/wiki/Program_evaluation_and_review_technique)
165+
PERT technique [^1]
168166
for scheduling in project management.
169167
In this application, the vertices of a graph represent the milestones of a project,
170168
and the edges represent tasks that must be performed between one milestone and another.
@@ -343,8 +341,6 @@ We need to check this while the `while` loop is running.
343341
Combining all of the above gives the current implementation of the `topological_generations()` function in NetworkX.
344342

345343
```{code-cell} ipython3
346-
import inspect
347-
348344
print(inspect.getsource(nx.topological_generations))
349345
```
350346

@@ -353,3 +349,7 @@ Let's finally see what the result will be on the `clothing_graph`.
353349
```{code-cell} ipython3
354350
list(nx.topological_generations(clothing_graph))
355351
```
352+
353+
## References
354+
355+
[^1]: [Wikipedia, PERT Technique](https://en.wikipedia.org/wiki/Program_evaluation_and_review_technique)

content/algorithms/euler/euler.md

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,15 @@ kernelspec:
1414

1515
# Euler's Algorithm
1616

17-
In this tutorial, we will explore the Euler's algorithm and its implementation in NetworkX under `networkx/algorithms/euler.py`.
17+
+++
18+
19+
In this tutorial, we will explore Euler's algorithm and its implementation in NetworkX under [`networkx/algorithms/euler.py`](https://github.com/networkx/networkx/blob/main/networkx/algorithms/euler.py).
20+
21+
## Import package
22+
23+
```{code-cell}
24+
import networkx as nx
25+
```
1826

1927
## Seven Bridges of Königsberg
2028

@@ -37,8 +45,7 @@ In order to have a clear look, we should first simplify the map a little.
3745
Euler observed that the choice of route inside each land mass is irrelevant. The only thing that matters is the sequence of bridges to be crossed. This observation allows us to abstract the problem even more. In the graph below, blue vertices represent the land masses and edges represent the bridges that connect them.
3846

3947
```{code-cell}
40-
import networkx as nx
41-
48+
# Create graph
4249
G = nx.DiGraph()
4350
G.add_edge("A", "B", label="a")
4451
G.add_edge("B", "A", label="b")
@@ -50,6 +57,7 @@ G.add_edge("C", "D", label="g")
5057
5158
positions = {"A": (0, 0), "B": (1, -2), "C": (1, 2), "D": (2, 0)}
5259
60+
# Visualize graph
5361
nx.draw_networkx_nodes(G, pos=positions, node_size=500)
5462
nx.draw_networkx_edges(
5563
G, pos=positions, edgelist=[("A", "D"), ("B", "D"), ("C", "D")], arrowstyle="-"
@@ -73,9 +81,10 @@ Note that every Euler Circuit is also an Euler Path.
7381

7482
### Euler's Method
7583

76-
Euler[^2] denoted land masses of the town by capital letters $A$, $B$, $C$ and $D$ and bridges by lowercase $a$, $b$, $c$, $d$, $e$, $f$ and $g$. Let's draw the graph based on this node and edge labels.
84+
Euler [^2] denoted land masses of the town by capital letters $A$, $B$, $C$ and $D$ and bridges by lowercase $a$, $b$, $c$, $d$, $e$, $f$ and $g$. Let's draw the graph based on this node and edge labels.
7785

7886
```{code-cell}
87+
# Design and draw graph
7988
edge_labels = nx.get_edge_attributes(G, "label")
8089
8190
nx.draw_networkx_nodes(G, pos=positions, node_size=500)
@@ -117,7 +126,7 @@ Euler generalized the method he applied for Königsberg problem as follows:
117126
- If there are two vertices with odd degree, then they are the starting and ending vertices.
118127
- If there are no vertices with odd degree, any vertex can be starting or ending vertex and the graph has also an Euler Circuit.
119128

120-
## NetworkX Implementation of Euler's Algorithm
129+
## Euler's Algorithm in NetworkX
121130

122131
NetworkX implements several methods using the Euler's algorithm. These are:
123132
- **is_eulerian** : Whether the graph has an Eulerian circuit
@@ -282,5 +291,6 @@ Euler's algorithm is essential for anyone or anything that uses paths. Some exam
282291

283292
## References
284293

285-
[^1]: <https://en.wikipedia.org/wiki/Seven_Bridges_of_K%C3%B6nigsberg>
286-
[^2]: Euler, Leonhard, ‘Solutio problematis ad geometriam situs pertinentis’ (1741), Eneström 53, MAA Euler Archive.
294+
[^1]: [Wikipedia, Seven Bridge of Konigsberg](https://en.wikipedia.org/wiki/Seven_Bridges_of_K%C3%B6nigsberg)
295+
296+
[^2]: Euler, Leonhard, ‘Solutio problematis ad geometriam situs pertinentis’ (1741), Eneström 53, MAA Euler Archive.

content/algorithms/flow/dinitz_alg.md

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,15 @@ language_info:
2222
version: 3.10.1
2323
---
2424

25-
# Dinitz's algorithm and its applications
26-
In this notebook, we will introduce the [Maximum flow problem](https://en.wikipedia.org/wiki/Maximum_flow_problem)
27-
and [Dinitz's algorithm](https://en.wikipedia.org/wiki/Dinic%27s_algorithm) [^1], which is implemented at
28-
[algorithms/flow/dinitz_alg.py](https://github.com/networkx/networkx/blob/main/networkx/algorithms/flow/dinitz_alg.py)
25+
# Dinitz's Algorithm and Applications
26+
27+
In this tutorial, we will explore the maximum flow problem [^1] and Dinitz's
28+
algorithm [^2] , which is implemented at
29+
[`algorithms/flow/dinitz_alg.py`](https://github.com/networkx/networkx/blob/main/networkx/algorithms/flow/dinitz_alg.py)
2930
in NetworkX. We will also see how it can be used to solve some interesting problems.
3031

31-
## Maximum flow problem
32+
33+
## Import packages
3234

3335
```{code-cell} ipython3
3436
import networkx as nx
@@ -40,16 +42,19 @@ from copy import deepcopy
4042
from collections import deque
4143
```
4244

45+
## Maximum flow problem
46+
4347
### Motivation
48+
4449
Let's say you want to send your friend some data as soon as possible, but the only way
4550
of communication/sending data between you two is through a peer-to-peer network. An
4651
interesting thing about this peer-to-peer network is that it allows you to send data
4752
along the paths you specify with certain limits on the sizes of data per second that
4853
you can send between a pair of nodes in this network.
4954

5055
```{code-cell} ipython3
51-
# Load the example graph
5256
G = nx.read_gml("data/example_graph.gml")
57+
5358
# Extract info about node position from graph (for visualization)
5459
pos = {k: np.asarray(v) for k, v in G.nodes(data="pos")}
5560
label_pos = deepcopy(pos)
@@ -95,8 +100,10 @@ a connection from node $u$ to node $v$ across which we can send data. There are
95100
```{code-cell} ipython3
96101
fig, ax = plt.subplots(figsize=(16, 8))
97102
103+
# Color source and sink node
98104
node_colors = ["skyblue" if n in {"s", "t"} else "lightgray" for n in G.nodes]
99105
106+
# Draw graph
100107
nx.draw(G, pos, ax=ax, node_color=node_colors, with_labels=True)
101108
nx.draw_networkx_labels(G, label_pos, labels=labels, ax=ax, font_size=16)
102109
ax.set_xlim([-1.4, 1.4]);
@@ -108,8 +115,10 @@ you can send from node $u$ to node $v$ is $c_{uv}$, lets call this as capacity o
108115
```{code-cell} ipython3
109116
fig, ax = plt.subplots(figsize=(16, 8))
110117
118+
# Label capacities
111119
capacities = {(u, v): c for u, v, c in G.edges(data="capacity")}
112120
121+
# Draw graph
113122
nx.draw(G, pos, ax=ax, node_color=node_colors, with_labels=True)
114123
nx.draw_networkx_edge_labels(G, pos, edge_labels=capacities, ax=ax)
115124
nx.draw_networkx_labels(G, label_pos, labels=labels, ax=ax, font_size=16)
@@ -539,7 +548,7 @@ fig.tight_layout()
539548
```
540549

541550
Note: Iteration are stopped if the maximum flow found so far exceeds the cutoff value
542-
## Reductions and Applications
551+
## Applications
543552
There are many other problems which can be reduced to Maximum flow problem, for example:
544553
* [Maximum Bipartite Matching](https://en.wikipedia.org/wiki/Matching_(graph_theory))
545554
* [Assignment Problem](https://en.wikipedia.org/wiki/Assignment_problem)
@@ -634,6 +643,8 @@ Above we can see a matching of intermediate shipping points and customers which
634643
gives the maximum shipping in a day.
635644

636645
## References
637-
[^1]: Dinitz' Algorithm: The Original Version and Even's Version. 2006. Yefim Dinitz.
646+
[^1]: [Wikipedia, Maximal Flow Problem](https://en.wikipedia.org/wiki/Maximum_flow_problem)
647+
648+
[^2]: Dinitz' Algorithm: The Original Version and Even's Version. 2006. Yefim Dinitz.
638649
In Theoretical Computer Science. Lecture Notes in Computer Science.
639650
Volume 3895. pp 218-240. <https://doi.org/10.1007/11685654_10>

content/algorithms/lca/LCA.md

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,18 @@ kernelspec:
1313

1414
# Lowest Common Ancestor
1515

16-
In this tutorial, we will explore the python implementation of the lowest common ancestor algorithm in NetworkX at `networkx/algorithms/lowest_common_ancestor.py`. To get a more general overview of Lowest Common Ancestor you can also read the [wikipedia article](https://en.wikipedia.org/wiki/Lowest_common_ancestor). This notebook expects readers to be familiar with the NetworkX API. If you are new to NetworkX, you can go through the [introductory tutorial](https://networkx.org/documentation/latest/tutorial.html).
16+
In this tutorial, we will explore the python implementation of the lowest common ancestor algorithm [^1] in NetworkX at [`networkx/algorithms/lowest_common_ancestor.py`](https://github.com/networkx/networkx/blob/main/networkx/algorithms/lowest_common_ancestors.py). This notebook expects readers to be familiar with the NetworkX API. If you are new to NetworkX, you can go through the [introductory tutorial](https://networkx.org/documentation/latest/tutorial.html).
17+
18+
## Import packages
19+
20+
```{code-cell} ipython3
21+
import matplotlib.pyplot as plt
22+
import networkx as nx
23+
from networkx.drawing.nx_agraph import graphviz_layout
24+
from itertools import chain, count, combinations_with_replacement
25+
```
26+
27+
+++ {"id": "Z5VJ4S_mlMiI"}
1728

1829
## Definitions
1930

@@ -26,6 +37,7 @@ Before diving into the algorithm, let's first remember the concepts of an ancest
2637

2738
- **Lowest Common Ancestor:** For two of nodes $u$ and $v$ in a tree, the lowest common ancestor is the lowest (i.e. deepest) node which is an ancestor of both $u$ and $v$.
2839

40+
2941
## Example
3042

3143
It is always a good idea to learn concepts with an example. Consider the following evolutionary tree. We will draw a directed version of it and define the ancestor/descendant relationships.
@@ -34,13 +46,6 @@ It is always a good idea to learn concepts with an example. Consider the followi
3446

3547
Let's first draw the tree using NetworkX.
3648

37-
```{code-cell}
38-
import matplotlib.pyplot as plt
39-
import networkx as nx
40-
from networkx.drawing.nx_agraph import graphviz_layout
41-
from itertools import chain, count, combinations_with_replacement
42-
```
43-
4449
```{code-cell}
4550
T = nx.DiGraph()
4651
T.add_edges_from(
@@ -190,3 +195,8 @@ dict(nx.all_pairs_lowest_common_ancestor(G))
190195
Naive implementation of lowest common ancestor algorithm finds all ancestors of all nodes in the given pairs. Let the number of nodes given in the pairs be P. In the worst case, finding ancestors of a single node will take O(|V|) times where |V| is the number of nodes. Thus, constructing the ancestor cache of a graph will take O(|V|\*P) times. This step will dominate the others and determine the worst-case running time of the algorithm.
191196

192197
The space complexity of the algorithm will also be determined by the ancestor cache. For each node in the given pairs, there might be O(|V|) ancestors. Thus, space complexity is also O(|V|\*P).
198+
199+
+++
200+
201+
## References
202+
[^1]: [Wikipedia, Lowest common ancestor](https://en.wikipedia.org/wiki/Lowest_common_ancestor)

0 commit comments

Comments
 (0)