{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "135c08ed-bb56-402b-8f70-6753236fb3fd",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "544a9dae-f975-4b9b-8ce8-6acb0cebe67f",
   "metadata": {},
   "outputs": [],
   "source": [
    "import gpflow\n",
    "import tensorflow as tf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "4e4ea353-bcaa-4f11-8482-fc4a1350e6e3",
   "metadata": {},
   "outputs": [],
   "source": [
    "import casadi as cs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "6ed9f89d-5004-46d6-bee0-912fda25edfd",
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.preprocessing import MinMaxScaler\n",
    "from sklearn.exceptions import NotFittedError"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fdde6962-b16a-4986-b872-ecc692b3e7d9",
   "metadata": {
    "id": "0aba0df5-b0e3-4738-bb61-1dad869d1ea3"
   },
   "source": [
    "## Load previously exported data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "8e31e7be-e669-4c2a-a44d-79c2d61278c6",
   "metadata": {},
   "outputs": [],
   "source": [
    "dfs_train = []\n",
    "dfs_test = []"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "2ea88fb9-7fb0-47fe-be7f-ff4401d12f14",
   "metadata": {},
   "outputs": [],
   "source": [
    "train_exps = ['Exp1', 'Exp3', 'Exp5', 'Exp6']\n",
    "test_exps = ['Exp2', 'Exp4', 'Exp7']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "573381ca-2162-4a90-8e68-af4f5c61a1c9",
   "metadata": {},
   "outputs": [],
   "source": [
    "for exp in train_exps:\n",
    "    dfs_train.append(pd.read_csv(f\"../Data/Good_CARNOT/{exp}_table.csv\").rename(columns = {'Power': 'SimulatedHeat'}))\n",
    "    \n",
    "for exp in test_exps:\n",
    "    dfs_test.append(pd.read_csv(f\"../Data/Good_CARNOT/{exp}_table.csv\").rename(columns = {'Power': 'SimulatedHeat'}))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "6c6d2eb9-7052-4161-82af-812d1cdae872",
   "metadata": {},
   "outputs": [],
   "source": [
    "#t_cols = ['time_h', 'time_m']\n",
    "t_cols = []\n",
    "w_cols = ['SolRad', 'OutsideTemp']\n",
    "u_cols = ['SimulatedHeat']\n",
    "y_cols = ['SimulatedTemp']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "4f0fa4b8-3aa3-479c-b6ee-5268896cb4e5",
   "metadata": {},
   "outputs": [],
   "source": [
    "t_lags = 0\n",
    "w_lags = 1\n",
    "u_lags = 2\n",
    "y_lags = 3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "56c6ceb7-b448-419f-9502-1fd96f674711",
   "metadata": {},
   "outputs": [],
   "source": [
    "dict_cols = {\n",
    "    't': (t_lags, t_cols),\n",
    "    'w': (w_lags, w_cols),\n",
    "    'u': (u_lags, u_cols),\n",
    "    'y': (y_lags, y_cols)\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ad177bfe-dbbd-4808-9f52-8cb5118dd928",
   "metadata": {},
   "source": [
    "Create the scaler and set up input data scaling:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "4cd8297e-19c3-4615-a493-577a585f23d2",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "7uZWtjPo6XhD",
    "outputId": "e0c4a8be-881e-4adc-a344-0b7e4ee9bc75"
   },
   "outputs": [],
   "source": [
    "scaler = MinMaxScaler(feature_range = (-1, 1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "025a3183-0cd9-45fe-98ca-d12ae5bc6307",
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_scaled_df(df, dict_cols, scaler):\n",
    "    \n",
    "    t_list = dict_cols['t'][1]\n",
    "    w_list = dict_cols['w'][1]\n",
    "    u_list = dict_cols['u'][1]\n",
    "    y_list = dict_cols['y'][1]\n",
    "    \n",
    "    df_local = df[t_list + w_list + u_list + y_list]\n",
    "    df_scaled = df_local.to_numpy()\n",
    "    \n",
    "    try:\n",
    "        df_scaled = scaler.transform(df_scaled)\n",
    "    except NotFittedError:\n",
    "        df_scaled = scaler.fit_transform(df_scaled)\n",
    "        \n",
    "    df_scaled = pd.DataFrame(df_scaled, index = df_local.index, columns = df_local.columns)\n",
    "    \n",
    "    return df_scaled"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "17ccf631-9789-4787-bcb4-83f45a36dddc",
   "metadata": {},
   "outputs": [],
   "source": [
    "df_train = pd.concat(dfs_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "d62d612e-9b00-4d7a-9c3f-12c4d418dc9c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>SolRad</th>\n",
       "      <th>OutsideTemp</th>\n",
       "      <th>SimulatedHeat</th>\n",
       "      <th>SimulatedTemp</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>57.936582</td>\n",
       "      <td>22.0</td>\n",
       "      <td>-31500</td>\n",
       "      <td>23.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>54.914443</td>\n",
       "      <td>22.0</td>\n",
       "      <td>-31500</td>\n",
       "      <td>20.585367</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>73.944706</td>\n",
       "      <td>22.0</td>\n",
       "      <td>-31500</td>\n",
       "      <td>20.300922</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>76.206334</td>\n",
       "      <td>22.0</td>\n",
       "      <td>-31500</td>\n",
       "      <td>20.034647</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>65.120057</td>\n",
       "      <td>22.0</td>\n",
       "      <td>-31500</td>\n",
       "      <td>19.786064</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "      SolRad  OutsideTemp  SimulatedHeat  SimulatedTemp\n",
       "0  57.936582         22.0         -31500      23.000000\n",
       "1  54.914443         22.0         -31500      20.585367\n",
       "2  73.944706         22.0         -31500      20.300922\n",
       "3  76.206334         22.0         -31500      20.034647\n",
       "4  65.120057         22.0         -31500      19.786064"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_train = df_train[t_cols + w_cols + u_cols + y_cols]\n",
    "df_train.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0fbc4b0d-a91a-4a00-bce5-da119fe2c271",
   "metadata": {},
   "source": [
    "Condition number of the raw input data:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "e9eace0f-3f1e-4746-b396-ad1af97690f0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "16199.169760599052"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.linalg.cond(df_train.to_numpy())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3d5ccf02-919d-4781-a194-19f3599202d7",
   "metadata": {},
   "source": [
    "Fit the scaler and scale the data:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "913c6705-e8e7-4b40-9aed-6ec5e1d1b010",
   "metadata": {},
   "outputs": [],
   "source": [
    "df_train_sc = get_scaled_df(df_train, dict_cols, scaler)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5728348e-2aac-4975-b308-0de3c3347933",
   "metadata": {},
   "source": [
    "Check the condition number of the input data:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "847a66b9-a7b8-47b5-974e-7ca79369088a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4.946636675064373"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.linalg.cond(df_train_sc.to_numpy())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "51ab5f01-60be-4ed4-9b2a-d9038b086236",
   "metadata": {},
   "source": [
    "NOTE: Condition number of scaled data is much smaller. This makes sense."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d76e19ec-5c52-43f5-9043-a8e25e730bdd",
   "metadata": {},
   "source": [
    "Scale the data for each experiment individually. Used for validation graphs:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "fbb2019d-c5d1-463e-bca6-a57adcb3373a",
   "metadata": {},
   "outputs": [],
   "source": [
    "dfs_train_sc = []\n",
    "dfs_test_sc = []\n",
    "for df in dfs_train:\n",
    "    df_sc = get_scaled_df(df, dict_cols, scaler)\n",
    "    dfs_train_sc.append(df_sc)\n",
    "    \n",
    "for df in dfs_test:\n",
    "    df_sc = get_scaled_df(df, dict_cols, scaler)\n",
    "    dfs_test_sc.append(df_sc)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3ce1f200-136f-4ea2-aa51-dadf4b2a0cf3",
   "metadata": {},
   "source": [
    "Set up the function which generated the GPR input matrix from the experimental data (including all autoregressive inputs, etc.):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "adc3cd49-b4f6-43a6-ad24-76e8fbce1746",
   "metadata": {},
   "outputs": [],
   "source": [
    "def data_to_gpr(df, dict_cols):\n",
    "    \n",
    "    t_list = dict_cols['t'][1]\n",
    "    w_list = dict_cols['w'][1]\n",
    "    u_list = dict_cols['u'][1]\n",
    "    y_list = dict_cols['y'][1]\n",
    "    \n",
    "    df_gpr = df[t_list + w_list + u_list + y_list].copy()\n",
    "    \n",
    "    for lags, names in dict_cols.values():\n",
    "        for name in names:\n",
    "            col_idx = df_gpr.columns.get_loc(name)\n",
    "            for lag in range(1, lags + 1):\n",
    "                df_gpr.insert(col_idx + lag, f\"{name}_{lag}\", df_gpr.loc[:, name].shift(lag))\n",
    "\n",
    "    df_gpr.dropna(inplace = True)\n",
    "    \n",
    "    return df_gpr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "ce6e9294-7a9d-440f-b017-85467719f2dd",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>SolRad</th>\n",
       "      <th>SolRad_1</th>\n",
       "      <th>OutsideTemp</th>\n",
       "      <th>OutsideTemp_1</th>\n",
       "      <th>SimulatedHeat</th>\n",
       "      <th>SimulatedHeat_1</th>\n",
       "      <th>SimulatedHeat_2</th>\n",
       "      <th>SimulatedTemp</th>\n",
       "      <th>SimulatedTemp_1</th>\n",
       "      <th>SimulatedTemp_2</th>\n",
       "      <th>SimulatedTemp_3</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>-0.855164</td>\n",
       "      <td>-0.859463</td>\n",
       "      <td>0.058824</td>\n",
       "      <td>0.058824</td>\n",
       "      <td>-1.0</td>\n",
       "      <td>-1.0</td>\n",
       "      <td>-1.0</td>\n",
       "      <td>-0.295224</td>\n",
       "      <td>-0.270561</td>\n",
       "      <td>-0.244215</td>\n",
       "      <td>-0.020567</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>-0.876235</td>\n",
       "      <td>-0.855164</td>\n",
       "      <td>0.058824</td>\n",
       "      <td>0.058824</td>\n",
       "      <td>-1.0</td>\n",
       "      <td>-1.0</td>\n",
       "      <td>-1.0</td>\n",
       "      <td>-0.318248</td>\n",
       "      <td>-0.295224</td>\n",
       "      <td>-0.270561</td>\n",
       "      <td>-0.244215</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>-0.911207</td>\n",
       "      <td>-0.876235</td>\n",
       "      <td>0.058824</td>\n",
       "      <td>0.058824</td>\n",
       "      <td>-1.0</td>\n",
       "      <td>-1.0</td>\n",
       "      <td>-1.0</td>\n",
       "      <td>-0.340062</td>\n",
       "      <td>-0.318248</td>\n",
       "      <td>-0.295224</td>\n",
       "      <td>-0.270561</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>-0.933425</td>\n",
       "      <td>-0.911207</td>\n",
       "      <td>0.058824</td>\n",
       "      <td>0.058824</td>\n",
       "      <td>1.0</td>\n",
       "      <td>-1.0</td>\n",
       "      <td>-1.0</td>\n",
       "      <td>-0.361066</td>\n",
       "      <td>-0.340062</td>\n",
       "      <td>-0.318248</td>\n",
       "      <td>-0.295224</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>-0.952322</td>\n",
       "      <td>-0.933425</td>\n",
       "      <td>0.058824</td>\n",
       "      <td>0.058824</td>\n",
       "      <td>-1.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>-1.0</td>\n",
       "      <td>0.051533</td>\n",
       "      <td>-0.361066</td>\n",
       "      <td>-0.340062</td>\n",
       "      <td>-0.318248</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     SolRad  SolRad_1  OutsideTemp  OutsideTemp_1  SimulatedHeat  \\\n",
       "3 -0.855164 -0.859463     0.058824       0.058824           -1.0   \n",
       "4 -0.876235 -0.855164     0.058824       0.058824           -1.0   \n",
       "5 -0.911207 -0.876235     0.058824       0.058824           -1.0   \n",
       "6 -0.933425 -0.911207     0.058824       0.058824            1.0   \n",
       "7 -0.952322 -0.933425     0.058824       0.058824           -1.0   \n",
       "\n",
       "   SimulatedHeat_1  SimulatedHeat_2  SimulatedTemp  SimulatedTemp_1  \\\n",
       "3             -1.0             -1.0      -0.295224        -0.270561   \n",
       "4             -1.0             -1.0      -0.318248        -0.295224   \n",
       "5             -1.0             -1.0      -0.340062        -0.318248   \n",
       "6             -1.0             -1.0      -0.361066        -0.340062   \n",
       "7              1.0             -1.0       0.051533        -0.361066   \n",
       "\n",
       "   SimulatedTemp_2  SimulatedTemp_3  \n",
       "3        -0.244215        -0.020567  \n",
       "4        -0.270561        -0.244215  \n",
       "5        -0.295224        -0.270561  \n",
       "6        -0.318248        -0.295224  \n",
       "7        -0.340062        -0.318248  "
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dfs_gpr_train = []\n",
    "for df_sc in dfs_train_sc:\n",
    "    dfs_gpr_train.append(data_to_gpr(df_sc, dict_cols))\n",
    "df_gpr_train = pd.concat(dfs_gpr_train)\n",
    "df_gpr_train.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "395b093c-04f8-437f-a2b4-4350ce851226",
   "metadata": {},
   "outputs": [],
   "source": [
    "df_gpr_train = df_gpr_train.sample(n = 500)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "7bcc9265-9ff0-4630-abdf-321d75180da7",
   "metadata": {},
   "outputs": [],
   "source": [
    "dfs_gpr_test = []\n",
    "for df_sc in dfs_test_sc:\n",
    "    dfs_gpr_test.append(data_to_gpr(df_sc, dict_cols))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "609b6a99-d122-4af9-a5e6-84005f899f2b",
   "metadata": {
    "id": "eZAetwUd6YuE"
   },
   "outputs": [],
   "source": [
    "df_input_train = df_gpr_train.drop(columns = dict_cols['w'][1] + dict_cols['u'][1] + dict_cols['y'][1])\n",
    "df_output_train = df_gpr_train[dict_cols['y'][1]]\n",
    "\n",
    "np_input_train = df_input_train.to_numpy()\n",
    "np_output_train = df_output_train.to_numpy().reshape(-1, 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "f884ea7d-5dde-404b-8b99-94592d1aa2b9",
   "metadata": {},
   "outputs": [],
   "source": [
    "data_train = (np_input_train, np_output_train)\n",
    "#pickle.dump(data_train, open(Path(\"data_train.pkl\"), 'wb'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "c3a19716-82ba-4ef8-86bc-47da3a518d06",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>SolRad_1</th>\n",
       "      <th>OutsideTemp_1</th>\n",
       "      <th>SimulatedHeat_1</th>\n",
       "      <th>SimulatedHeat_2</th>\n",
       "      <th>SimulatedTemp_1</th>\n",
       "      <th>SimulatedTemp_2</th>\n",
       "      <th>SimulatedTemp_3</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>176</th>\n",
       "      <td>0.320390</td>\n",
       "      <td>-0.411765</td>\n",
       "      <td>1.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.022707</td>\n",
       "      <td>-0.000856</td>\n",
       "      <td>-0.024018</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>491</th>\n",
       "      <td>-0.242351</td>\n",
       "      <td>0.058824</td>\n",
       "      <td>1.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.360771</td>\n",
       "      <td>0.336727</td>\n",
       "      <td>0.312594</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>111</th>\n",
       "      <td>-0.994599</td>\n",
       "      <td>-0.647059</td>\n",
       "      <td>1.0</td>\n",
       "      <td>-1.0</td>\n",
       "      <td>-0.674620</td>\n",
       "      <td>-0.262339</td>\n",
       "      <td>-0.282320</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>187</th>\n",
       "      <td>-0.515202</td>\n",
       "      <td>-0.882353</td>\n",
       "      <td>1.0</td>\n",
       "      <td>-1.0</td>\n",
       "      <td>-0.762459</td>\n",
       "      <td>-0.736413</td>\n",
       "      <td>-0.322186</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>335</th>\n",
       "      <td>-0.994964</td>\n",
       "      <td>-0.647059</td>\n",
       "      <td>1.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>-0.406616</td>\n",
       "      <td>-0.817147</td>\n",
       "      <td>-0.794250</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     SolRad_1  OutsideTemp_1  SimulatedHeat_1  SimulatedHeat_2  \\\n",
       "176  0.320390      -0.411765              1.0              1.0   \n",
       "491 -0.242351       0.058824              1.0              1.0   \n",
       "111 -0.994599      -0.647059              1.0             -1.0   \n",
       "187 -0.515202      -0.882353              1.0             -1.0   \n",
       "335 -0.994964      -0.647059              1.0              1.0   \n",
       "\n",
       "     SimulatedTemp_1  SimulatedTemp_2  SimulatedTemp_3  \n",
       "176         0.022707        -0.000856        -0.024018  \n",
       "491         0.360771         0.336727         0.312594  \n",
       "111        -0.674620        -0.262339        -0.282320  \n",
       "187        -0.762459        -0.736413        -0.322186  \n",
       "335        -0.406616        -0.817147        -0.794250  "
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_input_train.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "46b1c9ca-557c-40f8-a8a9-187f1f6bbba6",
   "metadata": {
    "id": "l_VzOWL66aD3"
   },
   "outputs": [],
   "source": [
    "## Define Kernel"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "8bfeac5e-22ae-408f-a928-03c66e4280ff",
   "metadata": {
    "id": "oBHgoYNf6b6t"
   },
   "outputs": [],
   "source": [
    "nb_dims = np_input_train.shape[1]\n",
    "rational_dims = np.arange(0, (dict_cols['t'][0] + 1) * len(dict_cols['t'][1]), 1)\n",
    "nb_rational_dims = len(rational_dims)\n",
    "squared_dims = np.arange(nb_rational_dims, nb_dims, 1)\n",
    "nb_squared_dims = len(squared_dims)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "0672bd9e-f2e7-48f4-9d30-7f00171b7a9b",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "_WagEJum8uUG",
    "outputId": "c65ec503-b964-49f6-fe3a-51c57a175f9b"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "rational: 0\n",
      "squared: 7\n"
     ]
    }
   ],
   "source": [
    "print(f\"rational: {nb_rational_dims}\")\n",
    "print(f\"squared: {nb_squared_dims}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "d2e67ab9-c903-4605-9167-76fe0b811e3a",
   "metadata": {
    "id": "kTIQlLIP6dJz"
   },
   "outputs": [],
   "source": [
    "squared_l = np.linspace(1, 1, nb_squared_dims)\n",
    "rational_l = np.linspace(1, 1, nb_rational_dims)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "ab407ff8-aac1-48c5-94aa-ee693a451a38",
   "metadata": {
    "id": "MEGkQJvY_izQ"
   },
   "outputs": [],
   "source": [
    "variance = tf.math.reduce_variance(np_input_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 303,
   "id": "b28d8306-8d13-46e7-a6ec-c3e0549bf07b",
   "metadata": {
    "id": "WZfssVHG6edn"
   },
   "outputs": [],
   "source": [
    "k0 = gpflow.kernels.SquaredExponential(lengthscales = squared_l, active_dims = squared_dims, variance = variance)\n",
    "k1 = gpflow.kernels.Constant(variance = variance)\n",
    "k2 = gpflow.kernels.RationalQuadratic(lengthscales = rational_l, active_dims = rational_dims, variance = variance)\n",
    "k3 = gpflow.kernels.Periodic(k2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 458,
   "id": "cb2867d9-85ff-4c4e-84ae-182cec152dd6",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 169
    },
    "id": "vo8rcdBm6fuc",
    "outputId": "75485dcd-961c-40d9-cf1f-d10516e2b80f"
   },
   "outputs": [],
   "source": [
    "k = (k0 + k1) * k2\n",
    "k = k0"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bbde76b9-07ec-4292-b419-3b49663c008b",
   "metadata": {
    "id": "4af25a43-15c9-4543-af73-3c313b5fc7af"
   },
   "source": [
    "## Compile Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 459,
   "id": "fd569132-6a46-4029-9eb5-8d1878f172d7",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 190
    },
    "id": "PC4cbp926j29",
    "outputId": "72c9441d-2657-4e0f-de70-11a197d07ad3"
   },
   "outputs": [],
   "source": [
    "m = gpflow.models.GPR(\n",
    "    data = data_train, \n",
    "    kernel = k, \n",
    "    mean_function = None,\n",
    "    )"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fd24e71e-9c98-4577-82de-0aeffd966286",
   "metadata": {
    "id": "08f41235-12df-4e9c-bf63-e7a4390cf21a"
   },
   "source": [
    "## Train Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 460,
   "id": "9c70c87e-22c0-456b-9a09-fc98f273cdbf",
   "metadata": {
    "id": "Pn5TwPPT6ogs"
   },
   "outputs": [],
   "source": [
    "opt = gpflow.optimizers.Scipy()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 461,
   "id": "405d1197-23df-4d00-8fef-9fa26b63e236",
   "metadata": {
    "id": "slQg9Ohv6oxR"
   },
   "outputs": [],
   "source": [
    "from datetime import datetime"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 462,
   "id": "81cff1a8-dd95-4cf1-96b2-c92af0843068",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 212
    },
    "id": "GhsxZhc56p43",
    "outputId": "778ec150-cfc3-44b7-9e21-e52bf69d494a",
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Finished fitting in 0:00:01.293315\n"
     ]
    }
   ],
   "source": [
    "start_time = datetime.now()\n",
    "opt.minimize(m.training_loss, m.trainable_variables)\n",
    "print(f\"Finished fitting in {datetime.now() - start_time}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8bf5c4b8-1c6e-4f39-8665-c3518f54c207",
   "metadata": {},
   "source": [
    "## CasADi Optimization part"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 350,
   "id": "cefb26f7-0c9a-4b8a-b658-ee6eb6f16ea0",
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_tf_evaluator(model):\n",
    "    @tf.function\n",
    "    def tensor_model_eval(tf_input):\n",
    "        preds = model.predict_f(tf_input)\n",
    "        return preds\n",
    "    return tensor_model_eval"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 364,
   "id": "706a8865-9a1a-42b4-bcfe-7802256cad0f",
   "metadata": {},
   "outputs": [],
   "source": [
    "tensor_model_eval = get_tf_evaluator(m)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 399,
   "id": "69aa5a0d-53ff-41a3-a22f-08d74a102407",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(<tf.Tensor: shape=(1, 1), dtype=float64, numpy=array([[1.03053204]])>,\n",
       " <tf.Tensor: shape=(1, 1), dtype=float64, numpy=array([[1.15445209e-06]])>)"
      ]
     },
     "execution_count": 399,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "m.predict_f(tf_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 400,
   "id": "2493b2c2-ef9a-4370-9887-31eb43e181e6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(<tf.Tensor: shape=(1, 1), dtype=float64, numpy=array([[1.03053322]])>,\n",
       " <tf.Tensor: shape=(1, 1), dtype=float64, numpy=array([[1.15737976e-06]])>)"
      ]
     },
     "execution_count": 400,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tensor_model_eval(tf_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 401,
   "id": "efefc120-53e4-4ab4-9899-7d79f62ac7b7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "DM(-7.03164e-195)"
      ]
     },
     "execution_count": 401,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cs_model(np_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 405,
   "id": "67c4057a-5b73-408b-be06-10828a10da4f",
   "metadata": {},
   "outputs": [],
   "source": [
    "cs_model.update_model(m)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 407,
   "id": "c40e3957-19cf-43fe-accf-aacb58f7587e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "DM(1.03053)"
      ]
     },
     "execution_count": 407,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cs_model(np_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 516,
   "id": "1864beb3-7896-42cd-8553-1bacf1bf5aaf",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Package the resulting regression model in a CasADi callback\n",
    "class GPR(cs.Callback):\n",
    "    def __init__(self, name, model, opts={}):\n",
    "        cs.Callback.__init__(self)\n",
    "\n",
    "        print(\"Instance of GPR callback\")\n",
    "        self.model = model\n",
    "        self.tf_evaluator = get_tf_evaluator(model)\n",
    "        self.n_in = model.data[0].shape[1]\n",
    "        self.tf_var = tf.Variable(np.ones((1, self.n_in)), dtype = tf.float64)\n",
    "        # Create a variable to keep all the gradient callback references\n",
    "        self.refs = []\n",
    "\n",
    "        self.construct(name, opts)\n",
    "    \n",
    "    # Update tf_evaluator\n",
    "    def update_model(self, model):\n",
    "        self.model = model\n",
    "        self.tf_evaluator = get_tf_evaluator(model)\n",
    "    \n",
    "    # Number of inputs/outputs\n",
    "    def get_n_in(self): return 1\n",
    "    def get_n_out(self): return 1\n",
    "    \n",
    "\n",
    "    # Sparsity of the input/output\n",
    "    def get_sparsity_in(self,i):\n",
    "        return cs.Sparsity.dense(1,self.n_in)\n",
    "    def get_sparsity_out(self,i):\n",
    "        return cs.Sparsity.dense(1,1)\n",
    "\n",
    "\n",
    "    def eval(self, arg):\n",
    "        self.tf_var.assign(arg[0])\n",
    "        [mean, _] = self.tf_evaluator(self.tf_var)\n",
    "        #[mean, _] = self.model.predict_f(arg[0])\n",
    "        return [mean.numpy()]\n",
    "    \n",
    "    def has_reverse(self, nadj): return nadj==1\n",
    "    def get_reverse(self, nadj, name, inames, onames, opts):\n",
    "        grad_callback = GPR_grad(name, self.n_in, self.tf_evaluator, self.tf_var)\n",
    "        self.refs.append(grad_callback)\n",
    "        \n",
    "        nominal_in = self.mx_in()\n",
    "        nominal_out = self.mx_out()\n",
    "        adj_seed = self.mx_out()\n",
    "        return cs.Function(name, nominal_in+nominal_out+adj_seed, grad_callback.call(nominal_in), inames, onames)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 517,
   "id": "6084bd09-4a0f-43bc-8090-fec07556556f",
   "metadata": {},
   "outputs": [],
   "source": [
    "class GPR_grad(cs.Callback):\n",
    "    def __init__(self, name, n_in, tf_evaluator, tf_var, opts={}):\n",
    "        cs.Callback.__init__(self)\n",
    "        self.tf_evaluator = tf_evaluator\n",
    "        self.n_in = n_in\n",
    "        self.tf_var = tf_var\n",
    "\n",
    "\n",
    "        self.construct(name, opts)\n",
    "\n",
    "    \n",
    "    def get_n_in(self): return 1\n",
    "    def get_n_out(self): return 1\n",
    "    \n",
    "    def get_sparsity_in(self,i):\n",
    "        return cs.Sparsity.dense(1,self.n_in)\n",
    "    def get_sparsity_out(self,i):\n",
    "        return cs.Sparsity.dense(1,self.n_in)\n",
    "    \n",
    "\n",
    "    def eval(self, arg):\n",
    "        self.tf_var.assign(arg[0])\n",
    "        with tf.GradientTape() as tape:\n",
    "            preds = self.tf_evaluator(self.tf_var)\n",
    "\n",
    "        grads = tape.gradient(preds, self.tf_var)\n",
    "        return [grads.numpy()]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 519,
   "id": "eb5224ae-09b0-4cb5-92f1-8476cfa32469",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Instance of GPR callback\n"
     ]
    }
   ],
   "source": [
    "cs_model = GPR(\"gpr\", m)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 419,
   "id": "9294cdc6-e2de-4230-9214-440712df5bb3",
   "metadata": {},
   "outputs": [],
   "source": [
    "np_test = np.ones((1, 7))\n",
    "tf_test = tf.Variable(np_test, dtype = tf.float64)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 422,
   "id": "4545f9d9-8488-4e75-9143-b63671395143",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5.13 ms ± 115 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
     ]
    }
   ],
   "source": [
    "%%timeit\n",
    "tf_test.assign(2 * np_test)\n",
    "tensor_model_eval(tf_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 421,
   "id": "779dc6b2-b6b3-478f-ace2-edb9443233cf",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "13.9 ms ± 533 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n"
     ]
    }
   ],
   "source": [
    "%%timeit\n",
    "casual_model_eval(np_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 273,
   "id": "4529796e-879c-4984-bce7-e17051546b5e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "41.8 ms ± 381 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)\n"
     ]
    }
   ],
   "source": [
    "%%timeit\n",
    "tf_iter = tf.Variable(np_test, dtype = tf.float64)\n",
    "with tf.GradientTape() as tape:\n",
    "    preds = m.predict_f(tf_iter)\n",
    "grads = tape.gradient(preds, tf_iter)\n",
    "grads"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 117,
   "id": "088c73cf-5512-443e-b9db-4f8ed2311414",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "22.7 ms ± 733 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)\n"
     ]
    }
   ],
   "source": [
    "%%timeit\n",
    "with tf.GradientTape() as tape:\n",
    "    preds = tensor_model_eval(tf_test)\n",
    "grads = tape.gradient(preds, tf_test)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "074b2c86-9a01-4963-8dda-57f442261a4b",
   "metadata": {},
   "source": [
    "### Multiple shooting problem formulation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 520,
   "id": "debd1d82-f50b-4ddf-aa34-bdd808c5e6d0",
   "metadata": {},
   "outputs": [],
   "source": [
    "N_horizon = 8\n",
    "n_states = 7"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 521,
   "id": "259d01bf-abad-43a7-8a14-0c5725b3aef9",
   "metadata": {},
   "outputs": [],
   "source": [
    "X = cs.MX.sym(\"X\", N_horizon + 1, n_states)\n",
    "lbd = cs.MX.sym(\"lambda\")\n",
    "x0 = cs.MX.sym(\"x0\", 1, n_states)\n",
    "W = cs.MX.sym(\"W\", N_horizon, 2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 522,
   "id": "fdda49b3-7751-43a5-a4ff-858631ebf73a",
   "metadata": {},
   "outputs": [],
   "source": [
    "g = []\n",
    "lbg = []\n",
    "ubg = []\n",
    "\n",
    "lbx = -np.inf*np.ones(X.shape)\n",
    "ubx = np.inf*np.ones(X.shape)\n",
    "\n",
    "T_set_sc = 2.5\n",
    "##\n",
    "# Set up the opjective function\n",
    "##\n",
    "\n",
    "# stage cost\n",
    "u_cost = cs.dot(X[:, 2], X[:, 2])\n",
    "\n",
    "# temperature constraint\n",
    "y_cost = 0.01 * cs.dot(X[:, 4], X[:, 4])\n",
    "\n",
    "J = u_cost + y_cost"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 523,
   "id": "1e2ae7b4-a311-4080-8c22-cf0d10693fcc",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Set up equality constraints for the first step\n",
    "for idx in range(n_states):\n",
    "    g.append(X[0, idx] - x0[0, idx])\n",
    "    lbg.append(0)\n",
    "    ubg.append(0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 524,
   "id": "373aee32-112d-4d55-b553-a6d360e98748",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Set up equality constraints for the following steps\n",
    "for idx in range(1, N_horizon + 1):\n",
    "    base_col = 0\n",
    "    # w\n",
    "    nb_cols = dict_cols['w'][0]\n",
    "    for w_idx in range(W.shape[1]):\n",
    "        w_base_col = w_idx * nb_cols\n",
    "        g.append(X[idx, base_col + w_base_col] - W[idx - 1, w_idx])\n",
    "        lbg.append(0)\n",
    "        ubg.append(0)\n",
    "        for w_lag_idx in range(1, nb_cols):\n",
    "            g.append(X[idx, base_col + w_base_col + w_lag_idx] - X[idx - 1, base_col + w_base_col + w_lag_idx - 1])\n",
    "            lbg.append(0)\n",
    "            ubg.append(0)\n",
    "            \n",
    "    base_col += nb_cols * W.shape[1]\n",
    "    # u\n",
    "    nb_cols = dict_cols['u'][0]\n",
    "\n",
    "    lbx[idx, base_col] = -1 #lower bound on input\n",
    "    ubx[idx, base_col] = 1 #upper bound on input\n",
    "    for u_lag_idx in range(1, nb_cols):\n",
    "        g.append(X[idx, base_col + u_lag_idx] - X[idx - 1, base_col + u_lag_idx - 1])\n",
    "        lbg.append(0)\n",
    "        ubg.append(0)\n",
    "    \n",
    "    base_col += nb_cols\n",
    "    # y\n",
    "    nb_cols = dict_cols['y'][0]\n",
    "    g.append(X[idx, base_col] - cs_model(X[idx - 1, :]))\n",
    "    lbg.append(0)\n",
    "    ubg.append(0)\n",
    "    for y_lag_idx in range(1, nb_cols):\n",
    "        g.append(X[idx, base_col + y_lag_idx] - X[idx - 1, base_col + y_lag_idx - 1])\n",
    "        lbg.append(0)\n",
    "        ubg.append(0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 525,
   "id": "c0ba0f93-f284-41a4-b70e-61ee04c8591a",
   "metadata": {},
   "outputs": [],
   "source": [
    "p = cs.vertcat(cs.vec(W), cs.vec(x0))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 526,
   "id": "0e33b5fa-9f3e-47f5-8369-c4f62ae09bcc",
   "metadata": {},
   "outputs": [],
   "source": [
    "prob = {'f': J, 'x': cs.vec(X), 'g': cs.vertcat(*g), 'p': p}\n",
    "options = {\"ipopt\": {\"hessian_approximation\": \"limited-memory\", \"max_iter\": 100,\n",
    "                     \"acceptable_tol\": 1e-4, \"tol\": 1e-4,\n",
    "                     \"linear_solver\": \"ma27\",\n",
    "                     #\"warm_start_init_point\": \"yes\"\n",
    "                     #\"acceptable_obj_change_tol\": 1e-5, \n",
    "                     #\"mu_strategy\": \"adaptive\",\n",
    "                    }}\n",
    "solver = cs.nlpsol(\"solver\",\"ipopt\",prob, options)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 527,
   "id": "92802031-6a68-45b9-b894-f9ea44fbb2b5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.19784954, 0.75380109, 0.20258375, 0.48384381, 0.26975897,\n",
       "        0.59621339, 0.89703682]])"
      ]
     },
     "execution_count": 527,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "real_x0 = np.random.rand(*x0.shape)\n",
    "real_x0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 528,
   "id": "f7d9ee2b-7e75-4dbd-899b-1a002bcd3d3f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.870293  , 0.08461537],\n",
       "       [0.65722421, 0.34585863],\n",
       "       [0.70636811, 0.12671317],\n",
       "       [0.78048239, 0.64362432],\n",
       "       [0.50636252, 0.66469496],\n",
       "       [0.77969876, 0.09749162],\n",
       "       [0.25604673, 0.25789882],\n",
       "       [0.1594542 , 0.46832943]])"
      ]
     },
     "execution_count": 528,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "real_W = np.random.rand(*W.shape)\n",
    "real_W"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 529,
   "id": "4eccd416-9939-43aa-b81f-4ce981d7e353",
   "metadata": {},
   "outputs": [],
   "source": [
    "real_p = cs.vertcat(cs.vec(real_W), cs.vec(real_x0))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 530,
   "id": "f6e595f5-3126-445a-877e-b54168f8d7de",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "DM(1.03058)"
      ]
     },
     "execution_count": 530,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cs_model(np_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 512,
   "id": "80b023cf-6563-4517-9d83-d39bba9dd6da",
   "metadata": {},
   "outputs": [],
   "source": [
    "cs_model.update_model(m)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 513,
   "id": "cf3fd768-4b47-4a69-bc3f-96e7343608ae",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "DM(1.03058)"
      ]
     },
     "execution_count": 513,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cs_model(np_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 536,
   "id": "1e94b993-7e81-46be-9e20-94b964c27347",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "This is Ipopt version 3.13.4, running with linear solver ma27.\n",
      "\n",
      "Number of nonzeros in equality constraint Jacobian...:      135\n",
      "Number of nonzeros in inequality constraint Jacobian.:        0\n",
      "Number of nonzeros in Lagrangian Hessian.............:        0\n",
      "\n",
      "Total number of variables............................:       63\n",
      "                     variables with only lower bounds:        0\n",
      "                variables with lower and upper bounds:        8\n",
      "                     variables with only upper bounds:        0\n",
      "Total number of equality constraints.................:       55\n",
      "Total number of inequality constraints...............:        0\n",
      "        inequality constraints with only lower bounds:        0\n",
      "   inequality constraints with lower and upper bounds:        0\n",
      "        inequality constraints with only upper bounds:        0\n",
      "\n",
      "iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls\n",
      "   0  0.0000000e+00 8.97e-01 0.00e+00   0.0 0.00e+00    -  0.00e+00 0.00e+00   0\n",
      "   1  5.7575353e-02 2.49e-03 8.97e-01  -6.0 8.97e-01    -  9.43e-01 1.00e+00h  1\n",
      "   2  6.3726414e-02 9.47e-07 3.51e-01  -1.9 1.05e-01    -  9.95e-01 1.00e+00h  1\n",
      "   3  4.6035747e-02 6.50e-07 4.49e-03  -3.1 5.84e-02    -  1.00e+00 1.00e+00f  1\n",
      "   4  4.6032694e-02 1.12e-08 1.98e-05  -5.3 8.15e-04    -  1.00e+00 1.00e+00h  1\n",
      "\n",
      "Number of Iterations....: 4\n",
      "\n",
      "                                   (scaled)                 (unscaled)\n",
      "Objective...............:   4.6032694495482543e-02    4.6032694495482543e-02\n",
      "Dual infeasibility......:   1.9751167684148774e-05    1.9751167684148774e-05\n",
      "Constraint violation....:   1.1249818632208530e-08    1.1249818632208530e-08\n",
      "Complementarity.........:   5.7908803598244531e-06    5.7908803598244531e-06\n",
      "Overall NLP error.......:   1.9751167684148774e-05    1.9751167684148774e-05\n",
      "\n",
      "\n",
      "Number of objective function evaluations             = 5\n",
      "Number of objective gradient evaluations             = 5\n",
      "Number of equality constraint evaluations            = 5\n",
      "Number of inequality constraint evaluations          = 0\n",
      "Number of equality constraint Jacobian evaluations   = 5\n",
      "Number of inequality constraint Jacobian evaluations = 0\n",
      "Number of Lagrangian Hessian evaluations             = 0\n",
      "Total CPU secs in IPOPT (w/o function evaluations)   =      1.002\n",
      "Total CPU secs in NLP function evaluations           =      5.199\n",
      "\n",
      "EXIT: Optimal Solution Found.\n",
      "      solver  :   t_proc      (avg)   t_wall      (avg)    n_eval\n",
      "       nlp_f  |  31.00us (  6.20us)  31.34us (  6.27us)         5\n",
      "       nlp_g  | 376.39ms ( 75.28ms) 177.69ms ( 35.54ms)         5\n",
      "    nlp_grad  | 888.99ms (888.99ms) 217.22ms (217.22ms)         1\n",
      "  nlp_grad_f  |  65.00us ( 10.83us)  63.12us ( 10.52us)         6\n",
      "   nlp_jac_g  |   5.94 s (989.93ms)   1.60 s (266.53ms)         6\n",
      "       total  |   7.21 s (  7.21 s)   2.00 s (  2.00 s)         1\n"
     ]
    }
   ],
   "source": [
    "res = solver(lbx = cs.vec(lbx), ubx = cs.vec(ubx), p = real_p, lbg = lbg, ubg = ubg)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 445,
   "id": "902f3a30-4fca-4e10-84a4-2fc380bdff81",
   "metadata": {},
   "outputs": [],
   "source": [
    "## Old result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 443,
   "id": "ca224e84-6c4a-4205-bf8d-006e67599f02",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "DM(\n",
       "[[0.761242, 0.36861, 0.556879, 0.104919, 0.160625, 0.774017, 0.547034], \n",
       " [0.480629, 0.922048, -0.000639741, 0.556879, 0.2753, 0.160625, 0.774017], \n",
       " [0.00685743, 0.247726, -0.000615418, -0.000639741, 0.187375, 0.2753, 0.160625], \n",
       " [0.447852, 0.283534, -0.000597185, -0.000615418, 0.192971, 0.187375, 0.2753], \n",
       " [0.624033, 0.160237, -0.000576846, -0.000597185, 0.200781, 0.192971, 0.187375], \n",
       " [0.771545, 0.00394968, -0.000558971, -0.000576846, 0.205897, 0.200781, 0.192971], \n",
       " [0.660621, 0.609428, -0.000568339, -0.000558971, 0.206814, 0.205897, 0.200781], \n",
       " [0.914765, 0.539141, -0.000550041, -0.000568339, 0.221992, 0.206814, 0.205897], \n",
       " [0.0561185, 0.209053, 0, -0.000550041, 0.236093, 0.221992, 0.206814]])"
      ]
     },
     "execution_count": 443,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "res['x'].reshape((N_horizon + 1, n_states))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 444,
   "id": "6a3dd26b-64ca-4a88-be86-248f800f2f88",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "DM(0.2753)"
      ]
     },
     "execution_count": 444,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cs_model([0.761242, 0.36861, 0.556879, 0.104919, 0.160625, 0.774017, 0.547034])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 446,
   "id": "865b7e52-1b57-4aee-a027-89639d12d0f3",
   "metadata": {},
   "outputs": [],
   "source": [
    "## New result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 466,
   "id": "9f362d2f-5c14-40f7-989d-db691ebc3005",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "DM(\n",
       "[[0.761242, 0.36861, 0.556879, 0.104919, 0.160625, 0.774017, 0.547034], \n",
       " [0.480629, 0.922048, -0.000640366, 0.556879, 0.275295, 0.160625, 0.774017], \n",
       " [0.00685743, 0.247726, -0.000615877, -0.000640366, 0.187418, 0.275295, 0.160625], \n",
       " [0.447852, 0.283534, -0.00059751, -0.000615877, 0.193019, 0.187418, 0.275295], \n",
       " [0.624033, 0.160237, -0.000577033, -0.00059751, 0.200834, 0.193019, 0.187418], \n",
       " [0.771545, 0.00394968, -0.000558939, -0.000577033, 0.205969, 0.200834, 0.193019], \n",
       " [0.660621, 0.609428, -0.000568317, -0.000558939, 0.206929, 0.205969, 0.200834], \n",
       " [0.914765, 0.539141, -0.000550168, -0.000568317, 0.22211, 0.206929, 0.205969], \n",
       " [0.0561185, 0.209053, 0, -0.000550168, 0.236208, 0.22211, 0.206929]])"
      ]
     },
     "execution_count": 466,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "res['x'].reshape((N_horizon + 1, n_states))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 467,
   "id": "1c5a8976-257f-4a47-bed9-4529077a78e2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "DM(0.275295)"
      ]
     },
     "execution_count": 467,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cs_model([0.761242, 0.36861, 0.556879, 0.104919, 0.160625, 0.774017, 0.547034])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c3dba702-e4cf-48de-b034-5485b5bfd7ac",
   "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.9.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
