Skip to content

Improve consistency #98

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 29 commits into from
Aug 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
ab2700b
Standardize
20kavishs Mar 24, 2023
30b54ee
Update sudoku.md
20kavishs Mar 24, 2023
2b9b75d
Changed links back to old form
20kavishs Mar 24, 2023
be1bc45
change versions back to original
20kavishs Mar 24, 2023
fc017a2
add back ipykernel
20kavishs Mar 26, 2023
5ed2872
clean up, make pre-commit happy
MridulS Mar 31, 2023
e8b11d8
Merge branch 'main' into improveConsistency
MridulS Mar 31, 2023
dff5fab
make pre-commit happy
MridulS Mar 31, 2023
de75f82
Fix typo.
rossbar Apr 9, 2023
28e89c4
Rm unnecessary warnings filter.
rossbar Apr 9, 2023
8ba46f3
Fix footnote format.
rossbar Apr 9, 2023
4ecf27e
Condense heading.
rossbar Apr 9, 2023
6cc9a46
More canonical way to create DiGraph.
rossbar Apr 9, 2023
41de46e
Condense headings.
rossbar Apr 9, 2023
e0169a8
Fix header level in flow.
rossbar Apr 9, 2023
0fb7a96
Typo.
rossbar Apr 9, 2023
e12e528
Fix heading level.
rossbar Apr 9, 2023
66ec90c
More heading fixes.
rossbar Apr 9, 2023
64eaf96
Resolved suggestions
20kavishs Apr 17, 2023
5b22b0a
MAINT: changing white text logo to gray banner (#105)
bsipocz Apr 9, 2023
fe0aa39
Isomorphism tutorial (#83)
paulitapb Apr 9, 2023
7654f34
Add Python 3.11 to the CI. (#107)
rossbar Apr 13, 2023
0edd262
Rm colab cruft. (#106)
rossbar Apr 14, 2023
7449b8c
created and then removed traversal notebook draft 1
20kavishs Jul 31, 2023
1096b9f
Merge branch 'main' into improveConsistency
dschult Aug 27, 2023
915ef5f
try converting with jupytext for tests again
dschult Aug 27, 2023
9fded05
test all notebooks except the long exploratory ones
dschult Aug 27, 2023
97752ef
restore the python versions field in tests
dschult Aug 27, 2023
e003608
Fixup missing ref in Dinitz nb.
rossbar Aug 27, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/notebooks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,7 @@ jobs:

- name: Test with nbval
run: |
find content/algorithms content/generators -name "*.md" -exec jupytext --to notebook {} \;
find content/algorithms content/generators -name "*.ipynb" -print
pip install pytest
pytest --nbval-lax --durations=25 content/
pytest --nbval-lax --durations=25 content/algorithms content/generators
50 changes: 28 additions & 22 deletions content/algorithms/assortativity/correlation.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,29 @@ language_info:
version: 3.8.5
---

# Node assortativity coefficients and correlation measures
# Node Assortativity Coefficients and Correlation Measures

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

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):
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):
* Attribute assortativity
* Numeric assortativity
* Degree assortativity

as well as mixing matrices, which are closely releated to assortativity measures.
as well as mixing matrices, which are closely related to assortativity measures.

## Import packages

```{code-cell} ipython3
import networkx as nx
import matplotlib.pyplot as plt
import pickle
import copy
import random
import warnings

%matplotlib inline
```

## Assortativity

Expand Down Expand Up @@ -80,7 +93,7 @@ Pearson correlation coefficient.

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

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

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

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

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

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

## Example
## Assortativity Example

```{code-cell} ipython3
%matplotlib inline
import networkx as nx
import matplotlib.pyplot as plt
import pickle
import copy
import random
import warnings

warnings.filterwarnings("ignore")
```
+++

Illustrating how value of assortativity changes

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

+++

[^1]: M. E. J. Newman, Mixing patterns in networks <https://doi.org/10.1103/PhysRevE.67.026126>
## References

[^1]: [Wikipedia, Assortativity](https://en.wikipedia.org/wiki/Assortativity)

[^2]: M. E. J. Newman, Mixing patterns in networks <https://doi.org/10.1103/PhysRevE.67.026126>

[^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>
[^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>
24 changes: 12 additions & 12 deletions content/algorithms/dag/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,25 +25,24 @@ language_info:
# Directed Acyclic Graphs & Topological Sort

In this tutorial, we will explore the algorithms related to a directed acyclic graph
(or a "dag" as it is sometimes called) implemented in networkx under `networkx/algorithms/dag.py`.
(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).

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

## Directed Graph

### Example
## Import packages

```{code-cell} ipython3
%matplotlib inline
import networkx as nx
import matplotlib.pyplot as plt
```
import inspect

```{code-cell} ipython3
triangle_graph = nx.from_edgelist([(1, 2), (2, 3), (3, 1)], create_using=nx.DiGraph)
%matplotlib inline
```

## Example: Directed Graphs

```{code-cell} ipython3
triangle_graph = nx.DiGraph([(1, 2), (2, 3), (3, 1)])
nx.draw_planar(
triangle_graph,
with_labels=True,
Expand Down Expand Up @@ -75,7 +74,6 @@ clothing_graph = nx.read_graphml(f"data/clothing_graph.graphml")

```{code-cell} ipython3
plt.figure(figsize=(12, 12), dpi=150)

nx.draw_planar(
clothing_graph,
arrowsize=12,
Expand Down Expand Up @@ -164,7 +162,7 @@ Then, a topological sort gives an order in which to perform the jobs.

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

```{code-cell} ipython3
import inspect

print(inspect.getsource(nx.topological_generations))
```

Expand All @@ -353,3 +349,7 @@ Let's finally see what the result will be on the `clothing_graph`.
```{code-cell} ipython3
list(nx.topological_generations(clothing_graph))
```

## References

[^1]: [Wikipedia, PERT Technique](https://en.wikipedia.org/wiki/Program_evaluation_and_review_technique)
24 changes: 17 additions & 7 deletions content/algorithms/euler/euler.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,15 @@ kernelspec:

# Euler's Algorithm

In this tutorial, we will explore the Euler's algorithm and its implementation in NetworkX under `networkx/algorithms/euler.py`.
+++

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).

## Import package

```{code-cell}
import networkx as nx
```

## Seven Bridges of Königsberg

Expand All @@ -37,8 +45,7 @@ In order to have a clear look, we should first simplify the map a little.
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.

```{code-cell}
import networkx as nx

# Create graph
G = nx.DiGraph()
G.add_edge("A", "B", label="a")
G.add_edge("B", "A", label="b")
Expand All @@ -50,6 +57,7 @@ G.add_edge("C", "D", label="g")

positions = {"A": (0, 0), "B": (1, -2), "C": (1, 2), "D": (2, 0)}

# Visualize graph
nx.draw_networkx_nodes(G, pos=positions, node_size=500)
nx.draw_networkx_edges(
G, pos=positions, edgelist=[("A", "D"), ("B", "D"), ("C", "D")], arrowstyle="-"
Expand All @@ -73,9 +81,10 @@ Note that every Euler Circuit is also an Euler Path.

### Euler's Method

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.
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.

```{code-cell}
# Design and draw graph
edge_labels = nx.get_edge_attributes(G, "label")

nx.draw_networkx_nodes(G, pos=positions, node_size=500)
Expand Down Expand Up @@ -117,7 +126,7 @@ Euler generalized the method he applied for Königsberg problem as follows:
- If there are two vertices with odd degree, then they are the starting and ending vertices.
- If there are no vertices with odd degree, any vertex can be starting or ending vertex and the graph has also an Euler Circuit.

## NetworkX Implementation of Euler's Algorithm
## Euler's Algorithm in NetworkX

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

## References

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

[^2]: Euler, Leonhard, ‘Solutio problematis ad geometriam situs pertinentis’ (1741), Eneström 53, MAA Euler Archive.
27 changes: 19 additions & 8 deletions content/algorithms/flow/dinitz_alg.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ language_info:
version: 3.10.1
---

# Dinitz's algorithm and its applications
In this notebook, we will introduce the [Maximum flow problem](https://en.wikipedia.org/wiki/Maximum_flow_problem)
and [Dinitz's algorithm](https://en.wikipedia.org/wiki/Dinic%27s_algorithm) [^1], which is implemented at
[algorithms/flow/dinitz_alg.py](https://github.com/networkx/networkx/blob/main/networkx/algorithms/flow/dinitz_alg.py)
# Dinitz's Algorithm and Applications

In this tutorial, we will explore the maximum flow problem [^1] and Dinitz's
algorithm [^2] , which is implemented at
[`algorithms/flow/dinitz_alg.py`](https://github.com/networkx/networkx/blob/main/networkx/algorithms/flow/dinitz_alg.py)
in NetworkX. We will also see how it can be used to solve some interesting problems.

## Maximum flow problem

## Import packages

```{code-cell} ipython3
import networkx as nx
Expand All @@ -40,16 +42,19 @@ from copy import deepcopy
from collections import deque
```

## Maximum flow problem

### Motivation

Let's say you want to send your friend some data as soon as possible, but the only way
of communication/sending data between you two is through a peer-to-peer network. An
interesting thing about this peer-to-peer network is that it allows you to send data
along the paths you specify with certain limits on the sizes of data per second that
you can send between a pair of nodes in this network.

```{code-cell} ipython3
# Load the example graph
G = nx.read_gml("data/example_graph.gml")

# Extract info about node position from graph (for visualization)
pos = {k: np.asarray(v) for k, v in G.nodes(data="pos")}
label_pos = deepcopy(pos)
Expand Down Expand Up @@ -95,8 +100,10 @@ a connection from node $u$ to node $v$ across which we can send data. There are
```{code-cell} ipython3
fig, ax = plt.subplots(figsize=(16, 8))

# Color source and sink node
node_colors = ["skyblue" if n in {"s", "t"} else "lightgray" for n in G.nodes]

# Draw graph
nx.draw(G, pos, ax=ax, node_color=node_colors, with_labels=True)
nx.draw_networkx_labels(G, label_pos, labels=labels, ax=ax, font_size=16)
ax.set_xlim([-1.4, 1.4]);
Expand All @@ -108,8 +115,10 @@ you can send from node $u$ to node $v$ is $c_{uv}$, lets call this as capacity o
```{code-cell} ipython3
fig, ax = plt.subplots(figsize=(16, 8))

# Label capacities
capacities = {(u, v): c for u, v, c in G.edges(data="capacity")}

# Draw graph
nx.draw(G, pos, ax=ax, node_color=node_colors, with_labels=True)
nx.draw_networkx_edge_labels(G, pos, edge_labels=capacities, ax=ax)
nx.draw_networkx_labels(G, label_pos, labels=labels, ax=ax, font_size=16)
Expand Down Expand Up @@ -539,7 +548,7 @@ fig.tight_layout()
```

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

## References
[^1]: Dinitz' Algorithm: The Original Version and Even's Version. 2006. Yefim Dinitz.
[^1]: [Wikipedia, Maximal Flow Problem](https://en.wikipedia.org/wiki/Maximum_flow_problem)

[^2]: Dinitz' Algorithm: The Original Version and Even's Version. 2006. Yefim Dinitz.
In Theoretical Computer Science. Lecture Notes in Computer Science.
Volume 3895. pp 218-240. <https://doi.org/10.1007/11685654_10>
26 changes: 18 additions & 8 deletions content/algorithms/lca/LCA.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,18 @@ kernelspec:

# Lowest Common Ancestor

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).
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).

## Import packages

```{code-cell} ipython3
import matplotlib.pyplot as plt
import networkx as nx
from networkx.drawing.nx_agraph import graphviz_layout
from itertools import chain, count, combinations_with_replacement
```

+++ {"id": "Z5VJ4S_mlMiI"}

## Definitions

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

- **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$.


## Example

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.
Expand All @@ -34,13 +46,6 @@ It is always a good idea to learn concepts with an example. Consider the followi

Let's first draw the tree using NetworkX.

```{code-cell}
import matplotlib.pyplot as plt
import networkx as nx
from networkx.drawing.nx_agraph import graphviz_layout
from itertools import chain, count, combinations_with_replacement
```

```{code-cell}
T = nx.DiGraph()
T.add_edges_from(
Expand Down Expand Up @@ -190,3 +195,8 @@ dict(nx.all_pairs_lowest_common_ancestor(G))
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.

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).

+++

## References
[^1]: [Wikipedia, Lowest common ancestor](https://en.wikipedia.org/wiki/Lowest_common_ancestor)
Loading