{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n\n# Traffic Assignment without an AequilibraE Model\n\nIn this example, we show how to perform Traffic Assignment in AequilibraE without a model.\n\nWe are using [Sioux Falls data](https://github.com/bstabler/TransportationNetworks/tree/master/SiouxFalls), from TNTP.\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Imports\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "import os\nimport pandas as pd\nimport numpy as np\nfrom tempfile import gettempdir\n\nfrom aequilibrae.matrix import AequilibraeMatrix\nfrom aequilibrae.paths import Graph\nfrom aequilibrae.paths import TrafficAssignment\nfrom aequilibrae.paths.traffic_class import TrafficClass"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "We load the example file from the GMNS GitHub repository\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "net_file = \"https://raw.githubusercontent.com/bstabler/TransportationNetworks/master/SiouxFalls/SiouxFalls_net.tntp\"\n\ndemand_file = \"https://raw.githubusercontent.com/bstabler/TransportationNetworks/master/SiouxFalls/CSV-data/SiouxFalls_od.csv\""
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Let's use a temporary folder to store our data\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "folder = gettempdir()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "First we load our demand file. This file has three columns: O, D, and Ton. \nO and D stand for origin and destination, respectively, and Ton is the demand of each\nOD pair.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "dem = pd.read_csv(demand_file)\nzones = int(max(dem.O.max(), dem.D.max()))\nindex = np.arange(zones) + 1"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Since our OD-matrix is in a different shape than we expect (for Sioux Falls, that\nwould be a 24x24 matrix), we must create our matrix.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "mtx = np.zeros(shape=(zones, zones))\nfor element in dem.to_records(index=False):\n    mtx[element[0]-1][element[1]-1] = element[2]"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Now let's create an AequilibraE Matrix with out data\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "aemfile = os.path.join(folder, \"demand.aem\")\naem = AequilibraeMatrix()\nkwargs = {'file_name': aemfile,\n          'zones': zones,\n          'matrix_names': ['matrix'],\n          \"memory_only\": False}  # We'll save it to disk so we can use it later\n\naem.create_empty(**kwargs)\naem.matrix['matrix'][:,:] = mtx[:,:]\naem.index[:] = index[:]"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Let's import information about our network. As we're loading data in TNTP format,\nwe should do these manipulations.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "net = pd.read_csv(net_file, skiprows=2, sep=\"\\t\", lineterminator=\";\", header=None)\n\nnet.columns = [\"newline\", \"a_node\", \"b_node\", \"capacity\", \"length\", \"free_flow_time\", \"b\", \"power\", \"speed\", \"toll\", \"link_type\", \"terminator\"]\n\nnet.drop(columns=[\"newline\", \"terminator\"], index=[76], inplace=True)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "network = net[['a_node', 'b_node', \"capacity\", 'free_flow_time', \"b\", \"power\"]]\nnetwork = network.assign(direction=1)\nnetwork[\"link_id\"] = network.index + 1\nnetwork = network.astype({\"a_node\":\"int64\", \"b_node\": \"int64\"})"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Let's build our Graph! In case you're in doubt about the Graph, `click here <aequilibrae-graphs>`\nto read more about it.\n%%\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "g = Graph()\ng.cost = network['free_flow_time'].values\ng.capacity = network['capacity'].values\ng.free_flow_time = network['free_flow_time'].values\n\ng.network = network\ng.network_ok = True\ng.status = 'OK'\ng.prepare_graph(index)\ng.set_graph(\"free_flow_time\")\ng.cost = np.array(g.cost, copy=True)\ng.set_skimming([\"free_flow_time\"])\ng.set_blocked_centroid_flows(False)\ng.network[\"id\"] = g.network.link_id"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Let's perform our assignment. Feel free to try different algorithms,\nas well as change the maximum number of iterations and the gap.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "aem = AequilibraeMatrix()\naem.load(aemfile)\naem.computational_view([\"matrix\"])\n\nassigclass = TrafficClass(\"car\", g, aem)\n\nassig = TrafficAssignment()\n\nassig.set_classes([assigclass])\nassig.set_vdf(\"BPR\")\nassig.set_vdf_parameters({\"alpha\": \"b\", \"beta\": \"power\"})\nassig.set_capacity_field(\"capacity\")\nassig.set_time_field(\"free_flow_time\")\nassig.set_algorithm(\"fw\")\nassig.max_iter = 100\nassig.rgap_target = 1e-6\nassig.execute()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Now let's take a look at the Assignment results\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "print(assig.results())"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "And at the Assignment report\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "print(assig.report())"
      ]
    }
  ],
  "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.9.16"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}