{ "cells": [ { "cell_type": "code", "execution_count": 1, "id": "3f3052cd", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "3f3052cd", "outputId": "78d129fd-0956-4f88-ae39-def9953a982e" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "Cloning into 'RLOR'...\n", "remote: Enumerating objects: 52, done.\u001b[K\n", "remote: Counting objects: 100% (52/52), done.\u001b[K\n", "remote: Compressing objects: 100% (35/35), done.\u001b[K\n", "remote: Total 52 (delta 12), reused 52 (delta 12), pack-reused 0\u001b[K\n", "Unpacking objects: 100% (52/52), 5.19 MiB | 4.39 MiB/s, done.\n", "/content/RLOR\n" ] } ], "source": [ "!git clone https://github.com/cpwan/RLOR\n", "%cd RLOR" ] }, { "cell_type": "code", "execution_count": 2, "id": "f01dfb64", "metadata": { "id": "f01dfb64" }, "outputs": [], "source": [ "import numpy as np\n", "import torch\n", "import gym" ] }, { "cell_type": "markdown", "id": "985bf6e6", "metadata": { "id": "985bf6e6" }, "source": [ "# Define our agent" ] }, { "cell_type": "code", "execution_count": 3, "id": "953a7fde", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "953a7fde", "outputId": "9b37d746-b9a0-4d53-c12a-b2445ed6bd9d" }, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "" ] }, "metadata": {}, "execution_count": 3 } ], "source": [ "from models.attention_model_wrapper import Agent\n", "device = 'cuda'\n", "ckpt_path = './runs/cvrp-v0__ppo_or__1__1678159979/ckpt/12000.pt'\n", "agent = Agent(device=device, name='cvrp').to(device)\n", "agent.load_state_dict(torch.load(ckpt_path))" ] }, { "cell_type": "markdown", "id": "2cbaa255", "metadata": { "id": "2cbaa255" }, "source": [ "# Define our environment\n", "## CVRP\n", "Given a depot, n nodes with their demands, and the capacity of the vehicle, \n", "find the shortest path that fulfills the demand of every node.\n" ] }, { "cell_type": "code", "execution_count": 4, "id": "81fd7b68", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "81fd7b68", "outputId": "f4a9d9d8-29f7-413d-b462-d27f04a0153a" }, "outputs": [ { "output_type": "stream", "name": "stderr", "text": [ "/usr/local/lib/python3.9/dist-packages/gym/utils/passive_env_checker.py:31: UserWarning: \u001b[33mWARN: A Box observation space has an unconventional shape (neither an image, nor a 1D vector). We recommend flattening the observation to have only a 1D vector or use a custom policy to properly process the data. Actual observation shape: (50, 2)\u001b[0m\n", " logger.warn(\n", "/usr/local/lib/python3.9/dist-packages/gym/core.py:317: DeprecationWarning: \u001b[33mWARN: Initializing wrapper in old step API which returns one bool instead of two. It is recommended to set `new_step_api=True` to use new step API. This will be the default behaviour in future.\u001b[0m\n", " deprecation(\n", "/usr/local/lib/python3.9/dist-packages/gym/wrappers/step_api_compatibility.py:39: DeprecationWarning: \u001b[33mWARN: Initializing environment in old step API which returns one bool instead of two. It is recommended to set `new_step_api=True` to use new step API. This will be the default behaviour in future.\u001b[0m\n", " deprecation(\n", "/usr/local/lib/python3.9/dist-packages/gym/vector/vector_env.py:56: DeprecationWarning: \u001b[33mWARN: Initializing vector env in old step API which returns one bool array instead of two. It is recommended to set `new_step_api=True` to use new step API. This will be the default behaviour in future.\u001b[0m\n", " deprecation(\n" ] } ], "source": [ "from wrappers.syncVectorEnvPomo import SyncVectorEnv\n", "from wrappers.recordWrapper import RecordEpisodeStatistics\n", "\n", "env_id = 'cvrp-v0'\n", "env_entry_point = 'envs.cvrp_vector_env:CVRPVectorEnv'\n", "seed = 0\n", "\n", "gym.envs.register(\n", " id=env_id,\n", " entry_point=env_entry_point,\n", ")\n", "\n", "def make_env(env_id, seed, cfg={}):\n", " def thunk():\n", " env = gym.make(env_id, **cfg)\n", " env = RecordEpisodeStatistics(env)\n", " env.seed(seed)\n", " env.action_space.seed(seed)\n", " env.observation_space.seed(seed)\n", " return env\n", " return thunk\n", "\n", "envs = SyncVectorEnv([make_env(env_id, seed, dict(n_traj=50))])" ] }, { "cell_type": "markdown", "id": "c363d489", "metadata": { "id": "c363d489" }, "source": [ "# Inference\n", "We use the Multi-Greedy search strategy: running greedy sampling with different starting nodes" ] }, { "cell_type": "code", "execution_count": 5, "id": "bbee9e3c", "metadata": { "id": "bbee9e3c", "outputId": "5632253d-9a70-433b-c35a-3d97e478da0d", "colab": { "base_uri": "https://localhost:8080/" } }, "outputs": [ { "output_type": "stream", "name": "stderr", "text": [ "/usr/local/lib/python3.9/dist-packages/gym/utils/passive_env_checker.py:174: UserWarning: \u001b[33mWARN: Future gym versions will require that `Env.reset` can be passed a `seed` instead of using `Env.seed` for resetting the environment random number generator.\u001b[0m\n", " logger.warn(\n", "/usr/local/lib/python3.9/dist-packages/gym/utils/passive_env_checker.py:190: UserWarning: \u001b[33mWARN: Future gym versions will require that `Env.reset` can be passed `return_info` to return information from the environment resetting.\u001b[0m\n", " logger.warn(\n", "/usr/local/lib/python3.9/dist-packages/gym/utils/passive_env_checker.py:195: UserWarning: \u001b[33mWARN: Future gym versions will require that `Env.reset` can be passed `options` to allow the environment initialisation to be passed additional information.\u001b[0m\n", " logger.warn(\n", "/usr/local/lib/python3.9/dist-packages/gym/utils/passive_env_checker.py:141: UserWarning: \u001b[33mWARN: The obs returned by the `reset()` method was expecting numpy array dtype to be float32, actual type: float64\u001b[0m\n", " logger.warn(\n", "/usr/local/lib/python3.9/dist-packages/gym/utils/passive_env_checker.py:165: UserWarning: \u001b[33mWARN: The obs returned by the `reset()` method is not within the observation space.\u001b[0m\n", " logger.warn(f\"{pre} is not within the observation space.\")\n", "/usr/local/lib/python3.9/dist-packages/gym/utils/passive_env_checker.py:227: DeprecationWarning: \u001b[33mWARN: Core environment is written in old step API which returns one bool instead of two. It is recommended to rewrite the environment with new step API. \u001b[0m\n", " logger.deprecation(\n", "/usr/local/lib/python3.9/dist-packages/gym/utils/passive_env_checker.py:234: UserWarning: \u001b[33mWARN: Expects `done` signal to be a boolean, actual type: \u001b[0m\n", " logger.warn(\n", "/usr/local/lib/python3.9/dist-packages/gym/utils/passive_env_checker.py:141: UserWarning: \u001b[33mWARN: The obs returned by the `step()` method was expecting numpy array dtype to be float32, actual type: float64\u001b[0m\n", " logger.warn(\n", "/usr/local/lib/python3.9/dist-packages/gym/utils/passive_env_checker.py:165: UserWarning: \u001b[33mWARN: The obs returned by the `step()` method is not within the observation space.\u001b[0m\n", " logger.warn(f\"{pre} is not within the observation space.\")\n", "/usr/local/lib/python3.9/dist-packages/gym/utils/passive_env_checker.py:260: UserWarning: \u001b[33mWARN: The reward returned by `step()` must be a float, int, np.integer or np.floating, actual type: \u001b[0m\n", " logger.warn(\n" ] } ], "source": [ "trajectories = []\n", "agent.eval()\n", "obs = envs.reset()\n", "done = np.array([False])\n", "while not done.all():\n", " # ALGO LOGIC: action logic\n", " with torch.no_grad():\n", " action, logits = agent(obs)\n", " if trajectories==[]: # Multi-greedy inference\n", " action = torch.arange(1, envs.n_traj + 1).repeat(1, 1)\n", " \n", " obs, reward, done, info = envs.step(action.cpu().numpy())\n", " trajectories.append(action.cpu().numpy())" ] }, { "cell_type": "code", "execution_count": 6, "id": "f0fbf6fd", "metadata": { "id": "f0fbf6fd" }, "outputs": [], "source": [ "nodes_coordinates = np.vstack([obs['depot'],obs['observations'][0]])\n", "final_return = info[0]['episode']['r']\n", "best_traj = np.argmax(final_return)\n", "resulting_traj = np.array(trajectories)[:,0,best_traj]\n", "resulting_traj_with_depot = np.hstack([np.zeros(1,dtype = int),resulting_traj])" ] }, { "cell_type": "markdown", "source": [ "## Results" ], "metadata": { "id": "ViNGfd1PQwlw" }, "id": "ViNGfd1PQwlw" }, { "cell_type": "code", "execution_count": 7, "id": "dff29ef4", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "dff29ef4", "outputId": "8a57a330-b340-4d60-dc83-2a1ea548c7d0" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "A route of length -11.283475875854492\n", "The route is:\n", " [ 0 16 32 27 7 30 23 38 40 2 11 0 9 10 19 36 35 4 5 18 0 25 42 43\n", " 48 21 37 31 50 0 13 8 41 17 12 46 0 3 6 44 0 22 26 49 34 33 28 0\n", " 1 14 29 39 47 0 20 24 45 15 0 0]\n" ] } ], "source": [ "print(f'A route of length {final_return[best_traj]}')\n", "print('The route is:\\n', resulting_traj_with_depot)" ] }, { "cell_type": "markdown", "id": "1b78c529", "metadata": { "id": "1b78c529" }, "source": [ "### Display it in a 2d-grid\n", "- Darker color means later steps in the route.\n", "- We abuse the errorbar to show the relative size of demand at each customer." ] }, { "cell_type": "code", "execution_count": 8, "id": "dc681a06", "metadata": { "tags": [ "\"hide-cell\"" ], "cellView": "form", "id": "dc681a06" }, "outputs": [], "source": [ "#@title Helper function for plotting\n", "# colorline taken from https://nbviewer.org/github/dpsanders/matplotlib-examples/blob/master/colorline.ipynb\n", "import matplotlib.pyplot as plt\n", "from matplotlib.collections import LineCollection\n", "from matplotlib.colors import ListedColormap, BoundaryNorm\n", "\n", "def make_segments(x, y):\n", " '''\n", " Create list of line segments from x and y coordinates, in the correct format for LineCollection:\n", " an array of the form numlines x (points per line) x 2 (x and y) array\n", " '''\n", "\n", " points = np.array([x, y]).T.reshape(-1, 1, 2)\n", " segments = np.concatenate([points[:-1], points[1:]], axis=1)\n", " \n", " return segments\n", "\n", "def colorline(x, y, z=None, cmap=plt.get_cmap('copper'), norm=plt.Normalize(0.0, 1.0), linewidth=1, alpha=1.0):\n", " '''\n", " Plot a colored line with coordinates x and y\n", " Optionally specify colors in the array z\n", " Optionally specify a colormap, a norm function and a line width\n", " '''\n", " \n", " # Default colors equally spaced on [0,1]:\n", " if z is None:\n", " z = np.linspace(0.3, 1.0, len(x))\n", " \n", " # Special case if a single number:\n", " if not hasattr(z, \"__iter__\"): # to check for numerical input -- this is a hack\n", " z = np.array([z])\n", " \n", " z = np.asarray(z)\n", " \n", " segments = make_segments(x, y)\n", " lc = LineCollection(segments, array=z, cmap=cmap, norm=norm, linewidth=linewidth, alpha=alpha)\n", " \n", " ax = plt.gca()\n", " ax.add_collection(lc)\n", " \n", " return lc\n", "\n", "def plot(coords, demand):\n", " x,y = coords.T\n", " lc = colorline(x,y,cmap='Reds')\n", " plt.axis('square')\n", " x, y =obs['observations'][0].T\n", " h = obs['demand']/4\n", " h = np.vstack([h*0,h])\n", " plt.errorbar(x,y,h,fmt='None',elinewidth=2)\n", " return lc" ] }, { "cell_type": "code", "execution_count": 9, "id": "aa5e32f2", "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 282 }, "id": "aa5e32f2", "outputId": "8da68d19-138b-4e3e-c481-02e06416c5e7" }, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "" ] }, "metadata": {}, "execution_count": 9 }, { "output_type": "display_data", "data": { "text/plain": [ "
" ], "image/png": "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\n" }, "metadata": { "needs_background": "light" } } ], "source": [ "plot(nodes_coordinates[resulting_traj_with_depot], obs['demand'])" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "name": "python3" }, "language_info": { "name": "python" }, "colab": { "provenance": [] }, "accelerator": "GPU", "gpuClass": "standard" }, "nbformat": 4, "nbformat_minor": 5 }