{ "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__..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 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__..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 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 }