{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Simple example of TuRBO-1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "/mnt/08B82010B81FFAC0/PyCharm Projects/TurBODiscrete\n"
     ]
    }
   ],
   "source": [
    "cd ../../.."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "from baselines.TuRBO.turbo import Turbo1\n",
    "import numpy as np\n",
    "import torch\n",
    "import math\n",
    "import matplotlib\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Set up an optimization problem class"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Levy:\n",
    "    def __init__(self, dim=50):\n",
    "        self.dim = dim\n",
    "        self.lb = -5 * np.ones(dim)\n",
    "        self.ub = 10 * np.ones(dim)\n",
    "        \n",
    "    def __call__(self, x):\n",
    "        assert len(x) == self.dim\n",
    "        assert x.ndim == 1\n",
    "        assert np.all(x <= self.ub) and np.all(x >= self.lb)\n",
    "        w = 1 + (x - 1.0) / 4.0\n",
    "        val = np.sin(np.pi * w[0]) ** 2 + \\\n",
    "            np.sum((w[1:self.dim - 1] - 1) ** 2 * (1 + 10 * np.sin(np.pi * w[1:self.dim - 1] + 1) ** 2)) + \\\n",
    "            (w[self.dim - 1] - 1) ** 2 * (1 + np.sin(2 * np.pi * w[self.dim - 1])**2)\n",
    "        return val\n",
    "\n",
    "f = Levy(20)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Create a Turbo optimizer instance"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Using dtype = torch.float64 \n",
      "Using device = cpu\n"
     ]
    }
   ],
   "source": [
    "turbo1 = Turbo1(\n",
    "    f=f,  # Handle to objective function\n",
    "    lb=f.lb,  # Numpy array specifying lower bounds\n",
    "    ub=f.ub,  # Numpy array specifying upper bounds\n",
    "    n_init=20,  # Number of initial bounds from an Latin hypercube design\n",
    "    max_evals = 2000,  # Maximum number of evaluations\n",
    "    batch_size=10,  # How large batch size TuRBO uses\n",
    "    verbose=True,  # Print information from each batch\n",
    "    use_ard=True,  # Set to true if you want to use ARD for the GP kernel\n",
    "    max_cholesky_size=2000,  # When we switch from Cholesky to Lanczos\n",
    "    n_training_steps=50,  # Number of steps of ADAM to learn the hypers\n",
    "    min_cuda=1024,  # Run on the CPU for small datasets\n",
    "    device=\"cpu\",  # \"cpu\" or \"cuda\"\n",
    "    dtype=\"float64\",  # float64 or float32\n",
    "    guided_restart=True,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Run the optimization process"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Starting from fbest = 48.25\n",
      "60) New best: 40.75\n",
      "70) New best: 33.11\n",
      "80) New best: 27.82\n",
      "130) New best: 18.32\n",
      "140) New best: 11.98\n",
      "170) New best: 9.594\n",
      "210) New best: 9.318\n",
      "220) New best: 8.402\n",
      "250) New best: 6.917\n",
      "280) Restarting with fbest = 6.917\n",
      "Starting from fbest = 50.28\n",
      "530) New best: 6.201\n",
      "560) Restarting with fbest = 6.201\n",
      "Starting from fbest = 65.76\n",
      "840) Restarting with fbest = 10.07\n",
      "Starting from fbest = 58.74\n",
      "1160) Restarting with fbest = 12.63\n",
      "Starting from fbest = 60.74\n",
      "1430) Restarting with fbest = 9.953\n",
      "Starting from fbest = 80.15\n",
      "1620) New best: 6.131\n",
      "1650) Restarting with fbest = 6.131\n",
      "Starting from fbest = 42.33\n",
      "1880) Restarting with fbest = 19.24\n",
      "Starting from fbest = 65.15\n"
     ]
    }
   ],
   "source": [
    "turbo1.optimize()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Best value found:\n",
      "\tf(x) = 6.131\n",
      "Observed at:\n",
      "\tx = [-2.247 -0.103  0.777  0.591  1.055  1.364 -0.222  0.255  1.549  2.4\n",
      "  1.121  2.16  -0.11   0.889  4.025  3.458  0.719  1.266 -0.172  5.399]\n"
     ]
    }
   ],
   "source": [
    "X = turbo1.X  # Evaluated points\n",
    "fX = turbo1.fX  # Observed values\n",
    "ind_best = np.argmin(fX)\n",
    "f_best, x_best = fX[ind_best], X[ind_best, :]\n",
    "\n",
    "print(\"Best value found:\\n\\tf(x) = %.3f\\nObserved at:\\n\\tx = %s\" % (f_best, np.around(x_best, 3)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 29712 characters]\n",
      "text/plain": [
       "<Figure size 504x360 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig = plt.figure(figsize=(7, 5))\n",
    "matplotlib.rcParams.update({'font.size': 16})\n",
    "plt.plot(fX, 'b.', ms=1)  # Plot all evaluated points as blue dots\n",
    "plt.plot(np.minimum.accumulate(fX), 'r', lw=3)  # Plot cumulative minimum as a red line\n",
    "plt.xlim([0, len(fX)])\n",
    "# plt.ylim([0, 30])\n",
    "plt.title(\"10D Levy function\")\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Using dtype = torch.float64 \n",
      "Using device = cpu\n",
      "Starting from fbest = 50.29\n",
      "40) New best: 39.52\n",
      "70) New best: 32.63\n",
      "140) New best: 26.81\n",
      "150) New best: 26.67\n",
      "160) New best: 16.25\n",
      "200) New best: 15.85\n",
      "210) New best: 13.53\n",
      "220) New best: 12.38\n",
      "260) New best: 10.12\n",
      "270) New best: 10.06\n",
      "280) New best: 9.315\n",
      "320) New best: 8.567\n",
      "340) New best: 8.017\n",
      "360) New best: 6.63\n",
      "390) Restarting with fbest = 6.63\n",
      "Starting from fbest = 65.54\n",
      "580) Restarting with fbest = 11.88\n",
      "Starting from fbest = 48.53\n",
      "790) Restarting with fbest = 14.53\n",
      "Starting from fbest = 68.37\n",
      "1000) Restarting with fbest = 12.51\n",
      "Starting from fbest = 85.96\n",
      "1150) New best: 5.597\n",
      "1200) New best: 4.833\n",
      "1230) New best: 4.687\n",
      "1260) Restarting with fbest = 4.687\n",
      "Starting from fbest = 86.47\n",
      "1500) New best: 3.096\n",
      "1510) New best: 2.981\n",
      "1540) Restarting with fbest = 2.981\n",
      "Starting from fbest = 67.97\n",
      "1810) Restarting with fbest = 9.221\n",
      "Starting from fbest = 68.44\n"
     ]
    }
   ],
   "source": [
    "turbo1 = Turbo1(\n",
    "    f=f,  # Handle to objective function\n",
    "    lb=f.lb,  # Numpy array specifying lower bounds\n",
    "    ub=f.ub,  # Numpy array specifying upper bounds\n",
    "    n_init=20,  # Number of initial bounds from an Latin hypercube design\n",
    "    max_evals = 2000,  # Maximum number of evaluations\n",
    "    batch_size=10,  # How large batch size TuRBO uses\n",
    "    verbose=True,  # Print information from each batch\n",
    "    use_ard=True,  # Set to true if you want to use ARD for the GP kernel\n",
    "    max_cholesky_size=2000,  # When we switch from Cholesky to Lanczos\n",
    "    n_training_steps=50,  # Number of steps of ADAM to learn the hypers\n",
    "    min_cuda=1024,  # Run on the CPU for small datasets\n",
    "    device=\"cpu\",  # \"cpu\" or \"cuda\"\n",
    "    dtype=\"float64\",  # float64 or float32\n",
    "    guided_restart=False,\n",
    ")\n",
    "turbo1.optimize()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Extract all evaluations from Turbo and print the best"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Best value found:\n",
      "\tf(x) = 2.981\n",
      "Observed at:\n",
      "\tx = [ 5.449  1.101  0.582  1.008  0.257  0.945  0.372  1.904  1.464  1.783\n",
      "  0.156  1.448  1.667  0.962 -0.55   1.91   0.682  0.473  1.193  1.793]\n"
     ]
    }
   ],
   "source": [
    "X = turbo1.X  # Evaluated points\n",
    "fX = turbo1.fX  # Observed values\n",
    "ind_best = np.argmin(fX)\n",
    "f_best, x_best = fX[ind_best], X[ind_best, :]\n",
    "\n",
    "print(\"Best value found:\\n\\tf(x) = %.3f\\nObserved at:\\n\\tx = %s\" % (f_best, np.around(x_best, 3)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Plot the progress\n",
    "Each trust region is independent and finds different solutions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 30504 characters]\n",
      "text/plain": [
       "<Figure size 504x360 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig = plt.figure(figsize=(7, 5))\n",
    "matplotlib.rcParams.update({'font.size': 16})\n",
    "plt.plot(fX, 'b.', ms=1)  # Plot all evaluated points as blue dots\n",
    "plt.plot(np.minimum.accumulate(fX), 'r', lw=3)  # Plot cumulative minimum as a red line\n",
    "plt.xlim([0, len(fX)])\n",
    "plt.ylim([0, 300])\n",
    "plt.title(\"10D Levy function\")\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 31176 characters]\n",
      "text/plain": [
       "<Figure size 504x360 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig = plt.figure(figsize=(7, 5))\n",
    "matplotlib.rcParams.update({'font.size': 16})\n",
    "plt.plot(fX, 'b.', ms=10)  # Plot all evaluated points as blue dots\n",
    "plt.plot(np.minimum.accumulate(fX), 'r', lw=3)  # Plot cumulative minimum as a red line\n",
    "plt.xlim([0, len(fX)])\n",
    "plt.ylim([0, 30])\n",
    "plt.title(\"10D Levy function\")\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "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.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
