{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import matlab.engine" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "from shutil import copyfile" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import pandas as pd" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "/home/radu/Projects/Master-Project/Simulink\n" ] } ], "source": [ "cd \"../Simulink\"" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "eng = matlab.engine.start_matlab()" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "eng.load_system(\"polydome\", background = True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Which experimental set to simulate:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "exp_id = 'Exp1'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Copy the corresponding WDB to the model input location:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'../Data/input_WDB.mat'" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "copyfile(f\"../Data/Experimental_data_WDB/{exp_id}_WDB.mat\", \"../Data/input_WDB.mat\")" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
timetimestampzenithazimuthdnidhiOutsideTempTsky_radrelative_humidityprecipitationcloud_indexpressurewind_speedwind_directionaoiincidence_mainincidence_secondpoa_directpoa_diffuse
0020170601200078.691622290.4308197.25133759.90864422.016.050-99990.5963000-999978.691622-9999-99991.42191159.908644
130020170601200579.489651291.2795017.67211456.53708822.016.050-99990.5963000-999979.489651-9999-99991.39949456.537088
260020170601201080.282334292.1305038.42313953.49267422.016.050-99990.5963000-999980.282334-9999-99991.42176953.492674
390020170601201581.069332292.98412352.65724465.77023922.016.050-99990.5963000-999981.069332-9999-99998.17446765.770239
4120020170601202081.850261293.84065394.36440362.82917722.016.050-99990.5963000-999981.850261-9999-999913.37715762.829177
\n", "
" ], "text/plain": [ " time timestamp zenith azimuth dni dhi \\\n", "0 0 201706012000 78.691622 290.430819 7.251337 59.908644 \n", "1 300 201706012005 79.489651 291.279501 7.672114 56.537088 \n", "2 600 201706012010 80.282334 292.130503 8.423139 53.492674 \n", "3 900 201706012015 81.069332 292.984123 52.657244 65.770239 \n", "4 1200 201706012020 81.850261 293.840653 94.364403 62.829177 \n", "\n", " OutsideTemp Tsky_rad relative_humidity precipitation cloud_index \\\n", "0 22.0 16.0 50 -9999 0.5 \n", "1 22.0 16.0 50 -9999 0.5 \n", "2 22.0 16.0 50 -9999 0.5 \n", "3 22.0 16.0 50 -9999 0.5 \n", "4 22.0 16.0 50 -9999 0.5 \n", "\n", " pressure wind_speed wind_direction aoi incidence_main \\\n", "0 96300 0 -9999 78.691622 -9999 \n", "1 96300 0 -9999 79.489651 -9999 \n", "2 96300 0 -9999 80.282334 -9999 \n", "3 96300 0 -9999 81.069332 -9999 \n", "4 96300 0 -9999 81.850261 -9999 \n", "\n", " incidence_second poa_direct poa_diffuse \n", "0 -9999 1.421911 59.908644 \n", "1 -9999 1.399494 56.537088 \n", "2 -9999 1.421769 53.492674 \n", "3 -9999 8.174467 65.770239 \n", "4 -9999 13.377157 62.829177 " ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df_wdb = pd.read_pickle(f\"../Data/Experimental_python/{exp_id}_WDB.pkl\")\n", "df_wdb.head()" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
PowerSetpointOutsideTempSupplyTempInsideTempSolRad
timestamp
2017-06-01 20:00:00+02:004325.03448323.522.024.524.30000061.321333
2017-06-01 20:05:00+02:004287.00000023.522.015.524.28333357.926100
2017-06-01 20:10:00+02:004319.76666723.522.015.224.08333354.902033
2017-06-01 20:15:00+02:002893.34482823.522.014.923.93333373.860700
2017-06-01 20:20:00+02:0059.13793123.522.018.223.66666776.042533
\n", "
" ], "text/plain": [ " Power Setpoint OutsideTemp SupplyTemp \\\n", "timestamp \n", "2017-06-01 20:00:00+02:00 4325.034483 23.5 22.0 24.5 \n", "2017-06-01 20:05:00+02:00 4287.000000 23.5 22.0 15.5 \n", "2017-06-01 20:10:00+02:00 4319.766667 23.5 22.0 15.2 \n", "2017-06-01 20:15:00+02:00 2893.344828 23.5 22.0 14.9 \n", "2017-06-01 20:20:00+02:00 59.137931 23.5 22.0 18.2 \n", "\n", " InsideTemp SolRad \n", "timestamp \n", "2017-06-01 20:00:00+02:00 24.300000 61.321333 \n", "2017-06-01 20:05:00+02:00 24.283333 57.926100 \n", "2017-06-01 20:10:00+02:00 24.083333 54.902033 \n", "2017-06-01 20:15:00+02:00 23.933333 73.860700 \n", "2017-06-01 20:20:00+02:00 23.666667 76.042533 " ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df = pd.read_pickle(f\"../Data/Experimental_python/{exp_id}_data.pkl\")\n", "df.head()" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "Tsample = 300\n", "eng.workspace['Tsample'] = Tsample" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Experiment runtime: 1200\n" ] } ], "source": [ "runtime = df_wdb['time'].iloc[-1] - Tsample\n", "runtime = 1200\n", "print(f\"Experiment runtime: {runtime}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Simulink" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Set the CARNOT simulation initial temperature `t0`" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [], "source": [ "eng.workspace['t0'] = float(df['InsideTemp'][0])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Set the CARNOT simulation air exchange rate" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [], "source": [ "day_air_exchange_rate = 2.5\n", "night_air_exchange_rate = 2.5" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [], "source": [ "air_exchange_rate = np.zeros((df_wdb.shape[0], 2))\n", "air_exchange_rate[:, 0] = df_wdb['time']\n", "air_exchange_rate[:, 1] = np.where(df['Power'] < 100, day_air_exchange_rate, night_air_exchange_rate)\n", "eng.workspace['air_exchange_rate'] = matlab.double(air_exchange_rate.tolist())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Set the CARNOT simulation input heat power" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Get the original electric power consumption" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [], "source": [ "power = np.array([df_wdb['time'], df['Power']]).T" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Get the heating power by passing through a heating/cooling COP" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [], "source": [ "COP_heating = -5.0\n", "COP_cooling = 5.0" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [], "source": [ "COP = np.where(df['Setpoint'] > df['InsideTemp'], COP_heating, -1*COP_cooling)" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [], "source": [ "power[:, 1] = COP * power[:, 1]" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [], "source": [ "eng.workspace['power'] = matlab.double(power.tolist())" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [], "source": [ "eng.set_param('polydome', 'StopTime', str(runtime), nargout = 0)" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "ename": "MatlabExecutionError", "evalue": "Error due to multiple causes.\n", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mMatlabExecutionError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0meng\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mworkspace\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'result'\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0meng\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msim\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'polydome'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;32m/usr/lib/python3.9/site-packages/matlab/engine/matlabengine.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 68\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mFutureResult\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_engine\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfuture\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnargs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_stdout\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_stderr\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfeval\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 69\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 70\u001b[0;31m return FutureResult(self._engine(), future, nargs, _stdout,\n\u001b[0m\u001b[1;32m 71\u001b[0m _stderr, feval=True).result()\n\u001b[1;32m 72\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/usr/lib/python3.9/site-packages/matlab/engine/futureresult.py\u001b[0m in \u001b[0;36mresult\u001b[0;34m(self, timeout)\u001b[0m\n\u001b[1;32m 65\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpythonengine\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mgetMessage\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'TimeoutCannotBeNegative'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 66\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 67\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__future\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mresult\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtimeout\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 68\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 69\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mcancel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/usr/lib/python3.9/site-packages/matlab/engine/fevalfuture.py\u001b[0m in \u001b[0;36mresult\u001b[0;34m(self, timeout)\u001b[0m\n\u001b[1;32m 80\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mTimeoutError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpythonengine\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mgetMessage\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'MatlabFunctionTimeout'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 81\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 82\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_result\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpythonengine\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mgetFEvalResult\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_future\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_nargout\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mout\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_out\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0merr\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_err\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 83\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_retrieved\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mTrue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 84\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_result\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mMatlabExecutionError\u001b[0m: Error due to multiple causes.\n" ] } ], "source": [ "eng.workspace['result'] = eng.sim('polydome')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Interpret the resulting data as a python dataframe" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "dict_simulation = {}\n", "dict_simulation['values'] = np.asarray(eng.eval('result.SimulatedTemp.Data')).reshape(-1)\n", "dict_simulation['time'] = np.asarray(eng.eval('result.SimulatedTemp.Time')).reshape(-1)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df_simulation = pd.DataFrame(dict_simulation)\n", "#df_simulation['time'] = df_simulation['time'].astype(int)\n", "df_simulation.set_index('time', inplace = True, drop = True)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df_simulation['timestamp'] = df.index[0] + df_simulation.index.map(lambda x: pd.Timedelta(seconds = x))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df_simulation = df_simulation.reset_index().set_index('timestamp')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plt.figure(figsize = (15, 5))\n", "plt.plot(df_simulation.index, df_simulation['values'], label = 'Simulated Temperature')\n", "plt.plot(df.index, df['InsideTemp'], '--',label = 'Inside Temperature')\n", "plt.plot(df.index, df['OutsideTemp'], '-.', label = 'Outside Temperature')\n", "plt.title('Temperatures')\n", "plt.legend()\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plt.figure(figsize = (15, 5))\n", "plt.plot(df.index, df['Setpoint'], label = 'HVAC Controller Setpoint Temperature')\n", "plt.title('Temperatures')\n", "plt.legend()\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Resample to 5/10/15 min by taking the mean when there are multiple points, and padding with zero order when data is missing" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df_resampled_5 = df_simulation['values'].resample('5min').mean().pad()\n", "df_resampled_10 = df_simulation['values'].resample('10min').mean().pad()\n", "df_resampled_15 = df_simulation['values'].resample('15min').mean().pad()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "plt.figure(figsize = (15, 5))\n", "plt.plot(df_simulation.index, df_simulation['values'], label = 'original')\n", "plt.plot(df_resampled_5.index, df_resampled_5, label = 'resampled 5min')\n", "plt.plot(df_resampled_10.index, df_resampled_10, label = 'resampled 10min')\n", "plt.plot(df_resampled_15.index, df_resampled_15, label = 'resampled 15min')\n", "plt.title('Resampling simulation data to different intervals')\n", "plt.legend()\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Export the resampled data-set for further use" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df_resampled_5.to_pickle(f\"../Data/CARNOT_output/{exp_id}_simulation_df.pkl\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df['Power'].plot(figsize = (20, 5))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Add the outputs to the experimental df and export the result: " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df['Heat'] = power[:, 1]\n", "df['SimulatedTemp'] = df_resampled_5" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Quick sanity check \n", "\n", "NOTE: This assumption is only correct for for experiments 1 and 2, but is currently applied everywhere.\n", "Keeping track of this only ensures that the GP can train on the same data that is fed to CARNOT" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "(np.where(np.sign(df['Setpoint'] - df['InsideTemp']) == 1, 1, -3) * df['Power']).equals(df['Heat'])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df.to_pickle(f\"../Data/CARNOT_output/{exp_id}_full.pkl\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df['Heat'].plot(figsize = (25, 5))" ] }, { "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.9.5" }, "toc-autonumbering": false, "toc-showmarkdowntxt": false }, "nbformat": 4, "nbformat_minor": 4 }