{ "cells": [ { "cell_type": "code", "source": [ "!git clone https://github.com/cpwan/RLOR\n", "%cd RLOR" ], "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "5a69iB04JzY2", "outputId": "13a3a63e-34bf-4d8b-a853-9d2597cd03d5" }, "id": "5a69iB04JzY2", "execution_count": 1, "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 | 7.89 MiB/s, done.\n", "/content/RLOR\n" ] } ] }, { "cell_type": "code", "execution_count": 2, "id": "dbe3c5ed", "metadata": { "id": "dbe3c5ed" }, "outputs": [], "source": [ "import numpy as np\n", "import torch\n", "import gym\n", "from models.attention_model_wrapper import Agent" ] }, { "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": "06f10aaf-57ca-4870-d22b-f71a14ea4ec4" }, "outputs": [ { "output_type": "execute_result", "data": { "text/plain": [ "" ] }, "metadata": {}, "execution_count": 3 } ], "source": [ "device = 'cuda'\n", "ckpt_path = './runs/tsp-v0__ppo_or__1__1678160003/ckpt/12000.pt'\n", "agent = Agent(device=device, name='tsp').to(device)\n", "agent.load_state_dict(torch.load(ckpt_path))" ] }, { "cell_type": "markdown", "id": "2cbaa255", "metadata": { "id": "2cbaa255" }, "source": [ "# Define our environment" ] }, { "cell_type": "code", "execution_count": 4, "id": "c2bd466f", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "c2bd466f", "outputId": "92450c8d-f5db-444d-f465-da4a98667799" }, "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 = 'tsp-v0'\n", "env_entry_point = 'envs.tsp_vector_env:TSPVectorEnv'\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=1))])" ] }, { "cell_type": "markdown", "id": "c363d489", "metadata": { "id": "c363d489" }, "source": [ "# Inference" ] }, { "cell_type": "code", "execution_count": 5, "id": "bbee9e3c", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "bbee9e3c", "outputId": "11750d60-eb7c-4d9c-8b40-3a8a92021ffe" }, "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: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: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: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": [ "num_steps = 51\n", "trajectories = []\n", "agent.eval()\n", "obs = envs.reset()\n", "for step in range(0, num_steps):\n", " # ALGO LOGIC: action logic\n", " with torch.no_grad():\n", " action, logits = agent(obs)\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 = obs['observations'][0]\n", "final_return = info[0]['episode']['r']\n", "resulting_traj = np.array(trajectories)[:,0,0]" ] }, { "cell_type": "markdown", "source": [ "## Results" ], "metadata": { "id": "5n9rBoH5Q8gn" }, "id": "5n9rBoH5Q8gn" }, { "cell_type": "code", "execution_count": 7, "id": "dff29ef4", "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "dff29ef4", "outputId": "dcffcda5-5728-464c-ee3e-0fcc702443ff" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "A route of length [-5.908508]\n", "The route is:\n", " [26 34 33 49 37 21 48 43 31 28 42 29 47 39 38 23 27 30 7 32 24 40 20 14\n", " 25 1 18 22 0 11 2 16 45 15 46 12 17 41 8 13 3 6 44 9 10 19 36 5\n", " 35 4 26]\n" ] } ], "source": [ "print(f'A route of length {final_return}')\n", "print('The route is:\\n', resulting_traj)" ] }, { "cell_type": "markdown", "id": "b009802e", "metadata": { "id": "b009802e" }, "source": [ "## Display it in a 2d-grid\n", "- Darker color means later steps in the route." ] }, { "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):\n", " x,y = coords.T\n", " lc = colorline(x,y,cmap='Reds')\n", " plt.axis('square')\n", " return lc" ] }, { "cell_type": "code", "execution_count": 9, "id": "bb0548fb", "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 282 }, "id": "bb0548fb", "outputId": "3e967b86-32e9-4be3-e5b7-c8a457aa12a7" }, "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])" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "name": "python3" }, "language_info": { "name": "python" }, "colab": { "provenance": [] }, "accelerator": "GPU", "gpuClass": "standard" }, "nbformat": 4, "nbformat_minor": 5 }