-
Notifications
You must be signed in to change notification settings - Fork 224
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1131 from PetholzA/feature/20230920_notebook_dyna…
…mics adds dynamics notebooks/documentation
- Loading branch information
Showing
3 changed files
with
317 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,315 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# Dynamics" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"In this notebook we present some of NetworKit dynamic algorithms to analyze properties of a (dynamic) graph.\n", | ||
"See the [networkit.dynamics](https://networkit.github.io/dev-docs/python_api/dynamics.html) module for a more detailed description. Dynamic algorithms can compute the result for the adapted graph directly from the previous result, without the need to re-run the entire algorithm.\n", | ||
"\n", | ||
"Note: The run() method does not need to be called in order to adapt the result." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# As usual, the first step is to import NetworKit.\n", | ||
"import networkit as nk " | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## The Graph and Graph Events" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Note: In order to maintain consistent result, both the `Graph` and the `Dynamic Algorithm` need to be adjusted. \\\n", | ||
" - The [graph](https://networkit.github.io/dev-docs/python_api/graph.html?highlight=graph#module-networkit.graph) needs to be changed by using the graph manipulation function equivalent to the desired result - like `G.addEdge(...)` or `G.removeEdge(...)`. \\\n", | ||
" - Dynamic Algorithm needs to be changed, using [graph events](https://networkit.github.io/dev-docs/python_api/dynamics.html?highlight=graphevent#networkit.dynamics.GraphEvent) and calling the functions `update(...)` or `updateBatch(...)`." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# Initialize graph\n", | ||
"def initializeGraph():\n", | ||
" G = nk.Graph(5, True)\n", | ||
" G.addEdge(0,1, 0.5)\n", | ||
" G.addEdge(1,2, 1.5)\n", | ||
" return G\n", | ||
"\n", | ||
"# Initialize graph events\n", | ||
"graph_event_edge_add = nk.dynamics.GraphEvent(nk.dynamics.GraphEventType.EDGE_ADDITION, 2,4, 2.0)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## DynDijkstra" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"The [Dynamic Dijkstra](https://networkit.github.io/dev-docs/python_api/distance.html?highlight=dyndijkstra#networkit.distance.DynDijkstra) algorithm computes the shortest paths to all nodes from a given source node, just like [Dikstra's Algorithm](https://networkit.github.io/dev-docs/python_api/distance.html?highlight=dijkstra#networkit.distance.Dijkstra). The dynamic version is able to handle adding and removing edges in the graph (note that both graph and the dynamic algorithm needs to be updated)." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# Run Dijsktra algorithm on the initial graph\n", | ||
"G = initializeGraph()\n", | ||
"sourceNode = 0\n", | ||
"dynDijk = nk.distance.DynDijkstra(G, sourceNode)\n", | ||
"dynDijk.run()\n", | ||
"print(\"path lengths from source node 0 for initial graph: \", dynDijk.getDistances())" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# Update the result of the dynamic algorithm \n", | ||
"G.addEdge(2,4, 2.0)\n", | ||
"dynDijk.update(nk.dynamics.GraphEvent(nk.dynamics.GraphEventType.EDGE_ADDITION, 2,4, 2.0))\n", | ||
"print(\"path lengths from source node 0 after edge addition: \", dynDijk.getDistances())\n", | ||
"\n", | ||
"G.removeEdge(2,4)\n", | ||
"dynDijk.update(nk.dynamics.GraphEvent(nk.dynamics.GraphEventType.EDGE_REMOVAL, 2,4, 2.0))\n", | ||
"print(\"path lengths from source node 0 after edge removal: \", dynDijk.getDistances())" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## DynAPSP" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Similar to the [Dynamic Dijkstra](https://networkit.github.io/dev-docs/python_api/distance.html?highlight=dyndijkstra#networkit.distance.DynDijkstra) algorithm, there exists a variant of [Dynamic All Pairs Shortest Path](https://networkit.github.io/dev-docs/python_api/distance.html?highlight=dynapsp#networkit.distance.DynAPSP), which computes the shortest path for each node to all other nodes. It can handle graph events of the types `EDGE_ADDITION` and `EDGE_WEIGHT_INCREMENT` with a negative value. " | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# Run APSP algorithm on the initial graph\n", | ||
"G = initializeGraph()\n", | ||
"dynAPSP = nk.distance.DynAPSP(G)\n", | ||
"dynAPSP.run()\n", | ||
"print(\"path lengths from all nodes for initial graph: \", dynAPSP.getDistances())" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# Batchwise update the result of the dynamic algorithm \n", | ||
"G.addEdge(1,3, 1.5)\n", | ||
"G.addEdge(2,4, 2.0)\n", | ||
"G.addEdge(0,4, 1.5)\n", | ||
"batch = [nk.dynamics.GraphEvent(nk.dynamics.GraphEventType.EDGE_ADDITION, 1,3, 1.5),\n", | ||
" nk.dynamics.GraphEvent(nk.dynamics.GraphEventType.EDGE_ADDITION, 2,4, 2.0),\n", | ||
" nk.dynamics.GraphEvent(nk.dynamics.GraphEventType.EDGE_ADDITION, 0,4, 1.5)]\n", | ||
"dynAPSP.updateBatch(batch)\n", | ||
"print(\"path lengths from all nodes after batch of edge additions: \", dynAPSP.getDistances())\n", | ||
"\n", | ||
"# Decreasing edge weights\n", | ||
"G.increaseWeight(1,2, -0.5) # Weight decrementation is implemented as negative weight increment\n", | ||
"dynAPSP.update(nk.dynamics.GraphEvent(nk.dynamics.GraphEventType.EDGE_WEIGHT_INCREMENT, 1,2, -0.5)) \n", | ||
"print(\"path lengths from all nodes after edge weight decrement: \", dynAPSP.getDistances())" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## DynBetweenness" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"The [Dynamic Betweenness](https://networkit.github.io/dev-docs/python_api/centrality.html?highlight=dynbet#networkit.centrality.DynBetweenness) algorithm computes the `betweenness centrality` of a graph. It can handle graph events of the types `EDGE_ADDITION` and `EDGE_WEIGHT_INCREMENT` with a negative value and adjusts the result without re-running the entire algorithm over again." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# Run Betweenness algorithm on the initial graph\n", | ||
"G = initializeGraph()\n", | ||
"dynBet = nk.centrality.DynBetweenness(G)\n", | ||
"dynBet.run()\n", | ||
"print(\"betweenness scores of initial graph: \",dynBet.scores())" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# Updating the graph and dynamic algorithm\n", | ||
"G.increaseWeight(2,4, -1.0) # Weight decrementation is implemented as negative weight increment\n", | ||
"dynBet.update(nk.dynamics.GraphEvent(nk.dynamics.GraphEventType.EDGE_WEIGHT_INCREMENT, 2,4, -1.0)) \n", | ||
"print(\"betweenness scores of updated graph: \",dynBet.scores())" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## DynTopHarmonicCloseness" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"The [Dynamic Top Harmonic Closeness](https://networkit.github.io/dev-docs/python_api/centrality.html?highlight=dyn#networkit.centrality.DynTopHarmonicCloseness) algorithm returns the `Harmonic Closeness` score for the k nodes with highest value. " | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# Run Betweenness algorithm on the initial graph\n", | ||
"G = initializeGraph()\n", | ||
"dynHC = nk.centrality.DynTopHarmonicCloseness(G, 3)\n", | ||
"dynHC.run()\n", | ||
"print(\"betweenness scores of initial graph: \",dynHC.topkScoresList())" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# Updating the graph and dynamic algorithm\n", | ||
"G.addEdge(2,4) # Weight decrementation is implemented as negative weight increment\n", | ||
"dynHC.update(nk.dynamics.GraphEvent(nk.dynamics.GraphEventType.EDGE_ADDITION, 2,4, 1.0))\n", | ||
"print(\"betweenness scores of updated graph: \",dynHC.topkScoresList())" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## DynConnectedComponents" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"The [Dynamic Connected Component](https://networkit.github.io/dev-docs/python_api/components.html?highlight=dyn#networkit.components.DynConnectedComponents) algorithm returns the `Connected Components` of an undirected graph. " | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# Run Connected Components algorithm on the initial graph\n", | ||
"G = initializeGraph()\n", | ||
"dynCC = nk.components.DynConnectedComponents(G)\n", | ||
"dynCC.run()\n", | ||
"print(\"connected components of initial graph: \",dynCC.getComponents())" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"# Updating the graph and dynamic algorithm\n", | ||
"G.addEdge(1,3) \n", | ||
"dynCC.update(nk.dynamics.GraphEvent(nk.dynamics.GraphEventType.EDGE_ADDITION, 1,3, 1.0)) \n", | ||
"print(\"connected components of updated graph: \",dynCC.getComponents())" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## Other Dynamic Algorithms and Data Structures" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": { | ||
"jp-MarkdownHeadingCollapsed": true, | ||
"tags": [] | ||
}, | ||
"source": [ | ||
"NetworKit does also include different types of dynamic algorithms and data structures that do not inherit from `DynAlgorithm` which means that they have a different usage: \n", | ||
"- [DynamicMatrix](https://networkit.github.io/dev-docs/cpp_api/classNetworKit_1_1DynamicMatrix.html?highlight=dynamic#_CPPv4N9NetworKit13DynamicMatrixE)\n", | ||
"- [DynamicGenerators](https://networkit.github.io/dev-docs/python_api/generators.html?highlight=dynamic#networkit.generators.DynamicDorogovtsevMendesGenerator)\n", | ||
"- [DynamicNMIDistance](https://networkit.github.io/dev-docs/cpp_api/classNetworKit_1_1DynamicNMIDistance.html?highlight=dynamic#_CPPv4N9NetworKit18DynamicNMIDistanceE)" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "Python 3 (ipykernel)", | ||
"language": "python", | ||
"name": "python3" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 3 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython3", | ||
"version": "3.10.9" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 4 | ||
} |