{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n\n# Network simplifier\n\nIn this example we use Nauru network to show how one can simplify the network,\nmerging short links into longer ones or turning links into nodes, and saving\ntheses changes into the project.\n\nWe use Folium to visualize the resulting network.\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        ".. seealso::\n    Several functions, methods, classes and modules are used in this example:\n\n    * :func:`aequilibrae.project.tools.network_simplifier.NetworkSimplifier`\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "# Imports\nimport branca\nimport folium\nfrom uuid import uuid4\nfrom tempfile import gettempdir\nfrom os.path import join\n\nfrom aequilibrae.utils.create_example import create_example\nfrom aequilibrae.project.tools.network_simplifier import NetworkSimplifier"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Let's use the Nauru example project for display\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "fldr = join(gettempdir(), uuid4().hex)\n\nproject = create_example(fldr, \"nauru\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "To simplify the network, we need to create a graph. As Nauru doesn't have any centroid in its network\nwe have to create a centroid from an arbitrary node, otherwise we cannot create a graph.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "nodes = project.network.nodes\ncentroid_count = nodes.data.query(\"is_centroid == 1\").shape[0]\n\nif centroid_count == 0:\n    arbitrary_node = nodes.data[\"node_id\"][0]\n    nd = nodes.get(arbitrary_node)\n    nd.is_centroid = 1\n    nd.save()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "# Let's analyze the mode car or 'c' in our model\nmode = \"c\""
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "# Let's set the graph for computation\nnetwork = project.network\nnetwork.build_graphs(modes=[mode])\ngraph = network.graphs[mode]\ngraph.set_graph(\"distance\")\ngraph.set_skimming(\"distance\")\ngraph.set_blocked_centroid_flows(False)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "# Let's revert to setting up that node as centroid in case we had to do it\nif centroid_count == 0:\n    nd.is_centroid = 0\n    nd.save()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "We check the number of links and nodes our project has initially.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "links_before = project.network.links.data\nnodes_before = project.network.nodes.data\n\nprint(\"This project initially has {} links and {} nodes\".format(links_before.shape[0], nodes_before.shape[0]))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Let's call the ``NetworkSimplifier`` class. Any changes made to the database using this class\nare permanent. Make sure you have a backup if necessary.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "net = NetworkSimplifier()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "When we choose to simplify the network, we pass a graph object to the function,\nand the output of this operation is\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "net.simplify(graph)\nnet.rebuild_network()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Let's plot the previous and actual networks!\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "links_after = net.network.links.data\nnodes_after = net.network.nodes.data"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "fig = branca.element.Figure()\n\nsubplot1 = fig.add_subplot(1, 2, 1)\nsubplot2 = fig.add_subplot(1, 2, 2)\n\nmap1 = folium.Map(location=[-0.508371, 166.931142], zoom_start=17)\nmap1 = links_before.explore(m=map1, color=\"black\", style_kwds={\"weight\": 2}, name=\"links_before\")\nmap1 = nodes_before.explore(m=map1, color=\"red\", style_kwds={\"radius\": 3, \"fillOpacity\": 1.0}, name=\"nodes_before\")\nfolium.LayerControl().add_to(map1)\n\nmap2 = folium.Map(location=[-0.508371, 166.931142], zoom_start=17)\nmap2 = links_after.explore(m=map2, color=\"black\", style_kwds={\"weight\": 2}, name=\"links_after\")\nmap2 = nodes_after.explore(m=map2, color=\"blue\", style_kwds={\"radius\": 3, \"fillOpacity\": 1.0}, name=\"nodes_after\")\nfolium.LayerControl().add_to(map2)\n\nsubplot1.add_child(map1)\nsubplot2.add_child(map2)\n\nfig"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Differently we can simplify the network by collapsing links into nodes.\nNotice that this operation modifies the network in the neighborhood.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "net.collapse_links_into_nodes([903])\nnet.rebuild_network()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Let's plot the network once again and check the modifications!\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "links_after = net.network.links.data\nnodes_after = net.network.nodes.data"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "fig = branca.element.Figure()\n\nsubplot1 = fig.add_subplot(1, 2, 1)\nsubplot2 = fig.add_subplot(1, 2, 2)\n\nmap1 = folium.Map(location=[-0.509363, 166.928563], zoom_start=18)\nmap1 = links_before.explore(m=map1, color=\"black\", style_kwds={\"weight\": 2}, name=\"links_before\")\nmap1 = nodes_before.explore(m=map1, color=\"red\", style_kwds={\"radius\": 3, \"fillOpacity\": 1.0}, name=\"nodes_before\")\nfolium.LayerControl().add_to(map1)\n\nmap2 = folium.Map(location=[-0.509363, 166.928563], zoom_start=18)\nmap2 = links_after.explore(m=map2, color=\"black\", style_kwds={\"weight\": 2}, name=\"links_after\")\nmap2 = nodes_after.explore(m=map2, color=\"blue\", style_kwds={\"radius\": 3, \"fillOpacity\": 1.0}, name=\"nodes_after\")\nfolium.LayerControl().add_to(map2)\n\nsubplot1.add_child(map1)\nsubplot2.add_child(map2)\n\nfig"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "project.close()"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "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.18"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}