Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 0 additions & 8 deletions .bumpversion.cfg

This file was deleted.

124 changes: 0 additions & 124 deletions .github/workflows/publish-package.yaml

This file was deleted.

7 changes: 0 additions & 7 deletions nams/functions.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
import numpy as np
from markdown import Markdown
from IPython.display import HTML


def ecdf(data):
return np.sort(data), np.arange(1, len(data) + 1) / len(data)


def render_html(ans):
md = Markdown()
return HTML(md.convert(ans))
4 changes: 1 addition & 3 deletions nams/solutions/bipartite.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import networkx as nx
import pandas as pd
from nams.functions import render_html


def extract_partition_nodes(G: nx.Graph, partition: str):
Expand Down Expand Up @@ -86,13 +85,12 @@ def find_connected_persons(G, person, crime):
def bipartite_degree_centrality_denominator():
"""Answer to bipartite graph denominator for degree centrality."""

ans = """
return """
The total number of neighbors that a node can _possibly_ have
is the number of nodes in the other partition.
This comes naturally from the definition of a bipartite graph,
where nodes can _only_ be connected to nodes in the other partition.
"""
return ans


def find_most_crime_person(G, person_nodes):
Expand Down
5 changes: 2 additions & 3 deletions nams/solutions/paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import networkx as nx
import pandas as pd
import seaborn as sns
from nams.functions import render_html


def bfs_algorithm():
Expand All @@ -22,10 +21,10 @@ def bfs_algorithm():
3. For each node in the queue:
1. Remove node from the queue.
2. Add neighbors of the node to the queue. Check if destination node is present or not.
3. If destination node is present, end. <!--Credit: @cavaunpeu for finding bug in pseudocode.-->
3. If destination node is present, end.
4. If destination node is not present, continue.
"""
return render_html(ans)
return ans


def path_exists(node1, node2, G):
Expand Down
9 changes: 3 additions & 6 deletions nams/solutions/structures.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@

import networkx as nx
from nxviz import circos
from nams.functions import render_html


def triangle_finding_strategies():
"""
How to find triangles.
"""
ans = """
return """
One way would be to take one node, and look at its neighbors.
If its neighbors are also connected to one another,
then we have found a triangle.
Expand All @@ -21,7 +20,6 @@ def triangle_finding_strategies():
If the starting node is the neighbor of the node two hops away,
then the path we traced traces out the nodes in a triangle.
"""
return render_html(ans)


def in_triangle(G, node):
Expand Down Expand Up @@ -60,7 +58,7 @@ def triadic_closure_algorithm():
"""
How to do triadic closure.
"""
ans = """
return """
I would suggest the following strategy:

1. Pick a node
Expand All @@ -76,7 +74,6 @@ def triadic_closure_algorithm():
of the starting node.
If not, then we have another triadic closure to make.
"""
return render_html(ans)


def get_open_triangles_neighbors(G, node) -> set:
Expand Down Expand Up @@ -107,7 +104,7 @@ def simplest_clique():
"""
Answer to "what is the simplest clique".
"""
return render_html("The simplest clique is an edge.")
return "The simplest clique is an edge."


def size_k_maximal_cliques(G, k):
Expand Down
66 changes: 24 additions & 42 deletions notebooks/00-preface/01-setup.py
Original file line number Diff line number Diff line change
@@ -1,86 +1,68 @@
# /// script
# requires-python = ">=3.13"
# dependencies = [
# "marimo",
# ]
# ///

import marimo

__generated_with = "0.14.10"
__generated_with = "0.23.9"
app = marimo.App(width="medium")


@app.cell
def _():
import marimo as mo

return (mo,)


@app.cell(hide_code=True)
def _(mo):
mo.md(
r"""
mo.md(r"""
## Introduction

In order to get the most of this book,
you will want to be able to execute the examples in the notebooks,
modify them, break the code, and fix it.
Pedagogically, that is the best way for you to learn the concepts.
Here's the recommended way to get set up.
"""
)
""")
return


@app.cell(hide_code=True)
def _(mo):
mo.md(
r"""
mo.md(r"""
## Quick Setup

To get started with the notebooks, follow these simple steps:

1. Git clone the repository: https://github.com/ericmjl/Network-Analysis-Made-Simple

1. **Install uv** (the Python package manager):
Follow the installation instructions at [https://docs.astral.sh/uv/getting-started/installation/](https://docs.astral.sh/uv/getting-started/installation/)

2. **Navigate to the notebook directory**:
```bash
cd notebooks/00-preface/ # replace with the actual numbered subdir!
```
2. **Install pixi** (the package manager):
Follow the installation instructions at [https://pixi.sh](https://pixi.sh)

3. **Run the notebook**:
3. **Run the notebooks**:
```bash
uvx marimo edit --sandbox 01-setup.py
pixi run marimo edit --no-token notebooks/
```

Once Marimo is launched, on the bottom, click on "on startup", "on cel change", and "on module change" to disable automatic execution. This will allow us to mimic original Jupyter behaviour, which is advantageous for a teaching setting (but toggle them back to "autorun" )
Once Marimo is launched, on the bottom, click on "on startup", "on cell change", and "on module change" to disable automatic execution. This will allow us to mimic original Jupyter behaviour, which is advantageous for a teaching setting (but toggle them back to "autorun" when you're done with the tutorial).


That's it! The `--sandbox` flag ensures a clean, isolated environment for running the notebooks with all necessary dependencies automatically managed.
"""
)
That's it! Pixi ensures a clean, isolated environment for running the notebooks with all necessary dependencies automatically managed.
""")
return


@app.cell(hide_code=True)
def _(mo):
mo.md(
r"""
mo.md(r"""
## What this does

- **uv** is a fast Python package manager that handles dependency resolution and virtual environments
- **pixi** is a fast package manager that handles dependency resolution and environments
- **marimo** is an interactive notebook environment optimized for Python
- The `--sandbox` flag creates an isolated environment for each notebook, preventing dependency conflicts
- All required packages are automatically installed when you run the notebook
- All required packages are automatically installed via the pixi manifest
- No manual environment setup, conda environments, or Docker containers needed

This approach eliminates the need for manual environment setup, conda environments, or Docker containers while ensuring reproducible execution of the tutorial content.
"""
)
This approach ensures reproducible execution of the tutorial content.
""")
return


@app.cell(hide_code=True)
def _():
import marimo as mo
return (mo,)


if __name__ == "__main__":
app.run()
Loading