You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

209 lines
14 KiB
Plaintext

{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"%load_ext autoreload\n",
"%autoreload 2\n",
"\n",
"import os\n",
"import wget\n",
"import zipfile\n",
"import numpy as np\n",
"import pandas as pd\n",
"import networkx as nx\n",
"import plotly.graph_objects as go\n",
"from utils import *\n",
"from collections import Counter\n",
"from tqdm import tqdm\n",
"import time\n",
"import geopandas as gpd\n",
"import gdown # for downloading files from google drive\n",
"import shutil\n",
"import warnings\n",
"import sys\n",
"from pyvis.network import Network\n",
"warnings.filterwarnings(\"ignore\")"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"import multiprocessing\n",
"import random\n",
"import networkx as nx\n",
"import numpy as np\n",
"import math\n",
"\n",
"def parallel_omega(G, nrand=10, seed=None):\n",
"\n",
" random.seed(seed)\n",
" if not nx.is_connected(G):\n",
" G = G.subgraph(max(nx.connected_components(G), key=len))\n",
"\n",
" if len(G) == 1:\n",
" return 0\n",
"\n",
" niter_lattice_reference = nrand\n",
" niter_random_reference = nrand * 2\n",
" \n",
" def worker(queue):\n",
" while True:\n",
" task = queue.get()\n",
" if task is None:\n",
" break\n",
" random_graph = nx.random_reference(G)\n",
" lattice_graph = nx.lattice_reference(G)\n",
" random_shortest_path = nx.average_shortest_path_length(random_graph)\n",
" lattice_clustering = nx.average_clustering(lattice_graph)\n",
" queue.put((random_shortest_path, lattice_clustering))\n",
" \n",
" n_processes = multiprocessing.cpu_count()\n",
" manager = multiprocessing.Manager()\n",
" queue = manager.Queue()\n",
" processes = [multiprocessing.Process(target=worker, args=(queue,)) for _ in range(n_processes)]\n",
" for process in processes:\n",
" process.start()\n",
" \n",
" for _ in range(nrand):\n",
" queue.put(1)\n",
" \n",
" for _ in range(n_processes):\n",
" queue.put(None)\n",
" \n",
" for process in processes:\n",
" process.join()\n",
" \n",
" shortest_paths = []\n",
" clustering_coeffs = []\n",
" while not queue.empty():\n",
" random_shortest_path, lattice_clustering = queue.get()\n",
" shortest_paths.append(random_shortest_path)\n",
" clustering_coeffs.append(lattice_clustering)\n",
" \n",
" L = nx.average_shortest_path_length(G)\n",
" C = nx.average_clustering(G)\n",
"\n",
" # kill the process\n",
" for process in processes:\n",
" process.terminate()\n",
" process.join()\n",
"\n",
" omega = (np.mean(shortest_paths) / L) - (C / np.mean(clustering_coeffs))\n",
"\n",
"\n",
" return omega"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'Graph with 200 nodes and 584 edges'"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"G = nx.erdos_renyi_graph(200, 0.03)\n",
"G = G.subgraph(max(nx.connected_components(G), key=len))\n",
"nx.info(G)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.6776975801779451"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"omega = parallel_omega(G, nrand=10, seed=42)\n",
"omega"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"ename": "KeyboardInterrupt",
"evalue": "",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)",
"Cell \u001b[0;32mIn[4], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m standard_omega \u001b[39m=\u001b[39m nx\u001b[39m.\u001b[39;49momega(G, nrand\u001b[39m=\u001b[39;49m\u001b[39m10\u001b[39;49m, seed\u001b[39m=\u001b[39;49m\u001b[39m42\u001b[39;49m)\n\u001b[1;32m 2\u001b[0m standard_omega\n",
"File \u001b[0;32m/usr/lib/python3.10/site-packages/networkx/utils/decorators.py:845\u001b[0m, in \u001b[0;36margmap.__call__.<locals>.func\u001b[0;34m(_argmap__wrapper, *args, **kwargs)\u001b[0m\n\u001b[1;32m 844\u001b[0m \u001b[39mdef\u001b[39;00m \u001b[39mfunc\u001b[39m(\u001b[39m*\u001b[39margs, __wrapper\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m, \u001b[39m*\u001b[39m\u001b[39m*\u001b[39mkwargs):\n\u001b[0;32m--> 845\u001b[0m \u001b[39mreturn\u001b[39;00m argmap\u001b[39m.\u001b[39;49m_lazy_compile(__wrapper)(\u001b[39m*\u001b[39;49margs, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwargs)\n",
"File \u001b[0;32m<class 'networkx.utils.decorators.argmap'> compilation 14:6\u001b[0m, in \u001b[0;36margmap_omega_9\u001b[0;34m(G, niter, nrand, seed)\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[39mimport\u001b[39;00m \u001b[39minspect\u001b[39;00m\n\u001b[1;32m 5\u001b[0m \u001b[39mimport\u001b[39;00m \u001b[39mitertools\u001b[39;00m\n\u001b[0;32m----> 6\u001b[0m \u001b[39mimport\u001b[39;00m \u001b[39mre\u001b[39;00m\n\u001b[1;32m 7\u001b[0m \u001b[39mfrom\u001b[39;00m \u001b[39mcollections\u001b[39;00m \u001b[39mimport\u001b[39;00m defaultdict\n\u001b[1;32m 8\u001b[0m \u001b[39mfrom\u001b[39;00m \u001b[39mcontextlib\u001b[39;00m \u001b[39mimport\u001b[39;00m contextmanager\n",
"File \u001b[0;32m/usr/lib/python3.10/site-packages/networkx/algorithms/smallworld.py:367\u001b[0m, in \u001b[0;36momega\u001b[0;34m(G, niter, nrand, seed)\u001b[0m\n\u001b[1;32m 363\u001b[0m niter_random_reference \u001b[39m=\u001b[39m niter \u001b[39m*\u001b[39m \u001b[39m2\u001b[39m\n\u001b[1;32m 365\u001b[0m \u001b[39mfor\u001b[39;00m _ \u001b[39min\u001b[39;00m \u001b[39mrange\u001b[39m(nrand):\n\u001b[1;32m 366\u001b[0m \u001b[39m# Generate random graph\u001b[39;00m\n\u001b[0;32m--> 367\u001b[0m Gr \u001b[39m=\u001b[39m random_reference(G, niter\u001b[39m=\u001b[39;49mniter_random_reference, seed\u001b[39m=\u001b[39;49mseed)\n\u001b[1;32m 368\u001b[0m randMetrics[\u001b[39m\"\u001b[39m\u001b[39mL\u001b[39m\u001b[39m\"\u001b[39m]\u001b[39m.\u001b[39mappend(nx\u001b[39m.\u001b[39maverage_shortest_path_length(Gr))\n\u001b[1;32m 370\u001b[0m \u001b[39m# Generate lattice graph\u001b[39;00m\n",
"File \u001b[0;32m/usr/lib/python3.10/site-packages/networkx/utils/decorators.py:845\u001b[0m, in \u001b[0;36margmap.__call__.<locals>.func\u001b[0;34m(_argmap__wrapper, *args, **kwargs)\u001b[0m\n\u001b[1;32m 844\u001b[0m \u001b[39mdef\u001b[39;00m \u001b[39mfunc\u001b[39m(\u001b[39m*\u001b[39margs, __wrapper\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m, \u001b[39m*\u001b[39m\u001b[39m*\u001b[39mkwargs):\n\u001b[0;32m--> 845\u001b[0m \u001b[39mreturn\u001b[39;00m argmap\u001b[39m.\u001b[39;49m_lazy_compile(__wrapper)(\u001b[39m*\u001b[39;49margs, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwargs)\n",
"File \u001b[0;32m<class 'networkx.utils.decorators.argmap'> compilation 24:6\u001b[0m, in \u001b[0;36margmap_random_reference_19\u001b[0;34m(G, niter, connectivity, seed)\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[39mimport\u001b[39;00m \u001b[39minspect\u001b[39;00m\n\u001b[1;32m 5\u001b[0m \u001b[39mimport\u001b[39;00m \u001b[39mitertools\u001b[39;00m\n\u001b[0;32m----> 6\u001b[0m \u001b[39mimport\u001b[39;00m \u001b[39mre\u001b[39;00m\n\u001b[1;32m 7\u001b[0m \u001b[39mfrom\u001b[39;00m \u001b[39mcollections\u001b[39;00m \u001b[39mimport\u001b[39;00m defaultdict\n\u001b[1;32m 8\u001b[0m \u001b[39mfrom\u001b[39;00m \u001b[39mcontextlib\u001b[39;00m \u001b[39mimport\u001b[39;00m contextmanager\n",
"File \u001b[0;32m/usr/lib/python3.10/site-packages/networkx/algorithms/smallworld.py:100\u001b[0m, in \u001b[0;36mrandom_reference\u001b[0;34m(G, niter, connectivity, seed)\u001b[0m\n\u001b[1;32m 97\u001b[0m G\u001b[39m.\u001b[39mremove_edge(c, d)\n\u001b[1;32m 99\u001b[0m \u001b[39m# Check if the graph is still connected\u001b[39;00m\n\u001b[0;32m--> 100\u001b[0m \u001b[39mif\u001b[39;00m connectivity \u001b[39mand\u001b[39;00m local_conn(G, a, b) \u001b[39m==\u001b[39m \u001b[39m0\u001b[39m:\n\u001b[1;32m 101\u001b[0m \u001b[39m# Not connected, revert the swap\u001b[39;00m\n\u001b[1;32m 102\u001b[0m G\u001b[39m.\u001b[39mremove_edge(a, d)\n\u001b[1;32m 103\u001b[0m G\u001b[39m.\u001b[39mremove_edge(c, b)\n",
"File \u001b[0;32m/usr/lib/python3.10/site-packages/networkx/algorithms/connectivity/connectivity.py:649\u001b[0m, in \u001b[0;36mlocal_edge_connectivity\u001b[0;34m(G, s, t, flow_func, auxiliary, residual, cutoff)\u001b[0m\n\u001b[1;32m 646\u001b[0m \u001b[39melif\u001b[39;00m flow_func \u001b[39mis\u001b[39;00m boykov_kolmogorov:\n\u001b[1;32m 647\u001b[0m kwargs[\u001b[39m\"\u001b[39m\u001b[39mcutoff\u001b[39m\u001b[39m\"\u001b[39m] \u001b[39m=\u001b[39m cutoff\n\u001b[0;32m--> 649\u001b[0m \u001b[39mreturn\u001b[39;00m nx\u001b[39m.\u001b[39;49mmaximum_flow_value(H, s, t, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwargs)\n",
"File \u001b[0;32m/usr/lib/python3.10/site-packages/networkx/algorithms/flow/maxflow.py:307\u001b[0m, in \u001b[0;36mmaximum_flow_value\u001b[0;34m(flowG, _s, _t, capacity, flow_func, **kwargs)\u001b[0m\n\u001b[1;32m 304\u001b[0m \u001b[39mif\u001b[39;00m \u001b[39mnot\u001b[39;00m callable(flow_func):\n\u001b[1;32m 305\u001b[0m \u001b[39mraise\u001b[39;00m nx\u001b[39m.\u001b[39mNetworkXError(\u001b[39m\"\u001b[39m\u001b[39mflow_func has to be callable.\u001b[39m\u001b[39m\"\u001b[39m)\n\u001b[0;32m--> 307\u001b[0m R \u001b[39m=\u001b[39m flow_func(flowG, _s, _t, capacity\u001b[39m=\u001b[39;49mcapacity, value_only\u001b[39m=\u001b[39;49m\u001b[39mTrue\u001b[39;49;00m, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwargs)\n\u001b[1;32m 309\u001b[0m \u001b[39mreturn\u001b[39;00m R\u001b[39m.\u001b[39mgraph[\u001b[39m\"\u001b[39m\u001b[39mflow_value\u001b[39m\u001b[39m\"\u001b[39m]\n",
"File \u001b[0;32m/usr/lib/python3.10/site-packages/networkx/algorithms/flow/edmondskarp.py:237\u001b[0m, in \u001b[0;36medmonds_karp\u001b[0;34m(G, s, t, capacity, residual, value_only, cutoff)\u001b[0m\n\u001b[1;32m 120\u001b[0m \u001b[39mdef\u001b[39;00m \u001b[39medmonds_karp\u001b[39m(\n\u001b[1;32m 121\u001b[0m G, s, t, capacity\u001b[39m=\u001b[39m\u001b[39m\"\u001b[39m\u001b[39mcapacity\u001b[39m\u001b[39m\"\u001b[39m, residual\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m, value_only\u001b[39m=\u001b[39m\u001b[39mFalse\u001b[39;00m, cutoff\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m\n\u001b[1;32m 122\u001b[0m ):\n\u001b[1;32m 123\u001b[0m \u001b[39m \u001b[39m\u001b[39m\"\"\"Find a maximum single-commodity flow using the Edmonds-Karp algorithm.\u001b[39;00m\n\u001b[1;32m 124\u001b[0m \n\u001b[1;32m 125\u001b[0m \u001b[39m This function returns the residual network resulting after computing\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 235\u001b[0m \n\u001b[1;32m 236\u001b[0m \u001b[39m \"\"\"\u001b[39;00m\n\u001b[0;32m--> 237\u001b[0m R \u001b[39m=\u001b[39m edmonds_karp_impl(G, s, t, capacity, residual, cutoff)\n\u001b[1;32m 238\u001b[0m R\u001b[39m.\u001b[39mgraph[\u001b[39m\"\u001b[39m\u001b[39malgorithm\u001b[39m\u001b[39m\"\u001b[39m] \u001b[39m=\u001b[39m \u001b[39m\"\u001b[39m\u001b[39medmonds_karp\u001b[39m\u001b[39m\"\u001b[39m\n\u001b[1;32m 239\u001b[0m \u001b[39mreturn\u001b[39;00m R\n",
"File \u001b[0;32m/usr/lib/python3.10/site-packages/networkx/algorithms/flow/edmondskarp.py:104\u001b[0m, in \u001b[0;36medmonds_karp_impl\u001b[0;34m(G, s, t, capacity, residual, cutoff)\u001b[0m\n\u001b[1;32m 101\u001b[0m \u001b[39mraise\u001b[39;00m nx\u001b[39m.\u001b[39mNetworkXError(\u001b[39m\"\u001b[39m\u001b[39msource and sink are the same node\u001b[39m\u001b[39m\"\u001b[39m)\n\u001b[1;32m 103\u001b[0m \u001b[39mif\u001b[39;00m residual \u001b[39mis\u001b[39;00m \u001b[39mNone\u001b[39;00m:\n\u001b[0;32m--> 104\u001b[0m R \u001b[39m=\u001b[39m build_residual_network(G, capacity)\n\u001b[1;32m 105\u001b[0m \u001b[39melse\u001b[39;00m:\n\u001b[1;32m 106\u001b[0m R \u001b[39m=\u001b[39m residual\n",
"File \u001b[0;32m/usr/lib/python3.10/site-packages/networkx/algorithms/flow/utils.py:139\u001b[0m, in \u001b[0;36mbuild_residual_network\u001b[0;34m(G, capacity)\u001b[0m\n\u001b[1;32m 135\u001b[0m \u001b[39mif\u001b[39;00m \u001b[39mnot\u001b[39;00m R\u001b[39m.\u001b[39mhas_edge(u, v):\n\u001b[1;32m 136\u001b[0m \u001b[39m# Both (u, v) and (v, u) must be present in the residual\u001b[39;00m\n\u001b[1;32m 137\u001b[0m \u001b[39m# network.\u001b[39;00m\n\u001b[1;32m 138\u001b[0m R\u001b[39m.\u001b[39madd_edge(u, v, capacity\u001b[39m=\u001b[39mr)\n\u001b[0;32m--> 139\u001b[0m R\u001b[39m.\u001b[39;49madd_edge(v, u, capacity\u001b[39m=\u001b[39;49m\u001b[39m0\u001b[39;49m)\n\u001b[1;32m 140\u001b[0m \u001b[39melse\u001b[39;00m:\n\u001b[1;32m 141\u001b[0m \u001b[39m# The edge (u, v) was added when (v, u) was visited.\u001b[39;00m\n\u001b[1;32m 142\u001b[0m R[u][v][\u001b[39m\"\u001b[39m\u001b[39mcapacity\u001b[39m\u001b[39m\"\u001b[39m] \u001b[39m=\u001b[39m r\n",
"\u001b[0;31mKeyboardInterrupt\u001b[0m: "
]
}
],
"source": [
"standard_omega = nx.omega(G, nrand=10, seed=42)\n",
"standard_omega"
]
}
],
"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"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "e7370f93d1d0cde622a1f8e1c04877d8463912d04d973331ad4851f04de6915a"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}