{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "$$ \\huge{\\underline{\\textbf{ Gradient Monte Carlo }}} $$\n", "\n", "
\n", "\n", "
Implementation of Gradient Monte Carlo
\n", "
from Sutton and Barto 2018, chapter 9.3.
\n", "
Book available for free here
\n", "\n", "
\n", "\n", "\n", "
From Sutton and Barto (2018) _Reinforcement Learning: An Introduction_, chapter 9.3
\n", "\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Implementation below matches the box exactly, but is for educational purposes only. See notes.\n", "\n", "Notes:\n", "* function approximator should be implemented as independent object - passing vector **w** around is impractical in actual program\n", "* I'm not sure why time step loop iterates foward (t=0,1..,T-1) instead of backwards (t=T-1,T-2,..,0), like we did in previous chapters (backward implementation is more efficient and avoids ackward Gt computation every time step)\n", "* algorithm in the box is for undiscounted case and thus omnits $\\gamma$ parameter\n", "* For alternative implementation, which fixes above issues, see further below." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "def gradient_MC(env, policy, ep, alpha, init_w, v_hat, grad_v_hat):\n", " \"\"\"Gradient Monte Carlo Algorithm\n", " \n", " Params:\n", " env - environment\n", " policy - function in a form: policy(state)->action\n", " ep - number of episodes to run\n", " alpha - step size (0..1]\n", " init_w - function if form init_w() -> weights\n", " v_hat - function in form v_hat(state, weights) -> float\n", " grad_v_hat - function in form grad_v_hat(state, weights) -> delta_weights\n", " \"\"\"\n", " w = init_w()\n", " \n", " for _ in range(ep):\n", " traj, T = generate_episode(env, policy)\n", " for t in range(T):\n", " St, _, _, _ = traj[t] # (st, rew, done, act)\n", " Gt = sum([traj[i][1] for i in range(t+1, T+1)]) # <- this is inefficient\n", " w = w + alpha * (Gt - v_hat(St, w)) * grad_v_hat(St, w)\n", " \n", " return w" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Helper functions:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "def init_w():\n", " return np.zeros(10) # weights for 10 groups\n", " \n", "def v_hat(St, w):\n", " group = (St-1) // 100 # [1-100, 101-200, ..., 901-1000] -> [0, 1, ..., 9]\n", " return w[group]\n", " \n", "def grad_v_hat(St, w):\n", " grad = np.zeros_like(w)\n", " grad[(St-1)//100] = 1\n", " return grad" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "def generate_episode(env, policy):\n", " \"\"\"Generete one complete episode.\n", " \n", " Returns:\n", " trajectory: list of tuples [(st, rew, done, act), (...), (...)],\n", " where St can be e.g tuple of ints or anything really\n", " T: index of terminal state, NOT length of trajectory\n", " \"\"\"\n", " trajectory = []\n", " done = True\n", " while True:\n", " # === time step starts here ===\n", " if done: St, Rt, done = env.reset(), None, False\n", " else: St, Rt, done = env.step(At)\n", " At = policy(St)\n", " trajectory.append((St, Rt, done, At))\n", " if done: break\n", " # === time step ends here ===\n", " return trajectory, len(trajectory)-1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "--- " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", "
Figure 9.1 - \"True\" value is approximated with stright line
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Alternative Implementation" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This section is very important, it is heavily built uppon in following chapters. We will reuse this implementation a lot later on. It's best to get good understanding right here, including both options 1 and 2 in the AggregateFunctApprox.\n", "\n", "This implementation includes following features as compared with original implementation above:\n", "* function approximator is now a trainable black-box object - can be tabular, linear, neural-net\n", "* added discount paramter $\\gamma$\n", "* time-step loop now goes backward for efficiency" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "def gradient_MC_fix(env, policy, ep, gamma, model):\n", " \"\"\"Gradient Monte Carlo Algorithm\n", " \n", " Params:\n", " env - environment\n", " policy - function in a form: policy(state)->action\n", " ep - number of episodes to run\n", " gamma - discount factor [0..1]\n", " model - function approximator, already initialised, with method:\n", " train(state, target) -> None\n", " \"\"\" \n", " for _ in range(ep):\n", " traj, T = generate_episode(env, policy)\n", " Gt = 0\n", " for t in range(T-1,-1,-1):\n", " St, _, _, _ = traj[t] # (st, rew, done, act)\n", " _, Rt_1, _, _ = traj[t+1]\n", " \n", " Gt = gamma * Gt + Rt_1\n", " model.train(St, Gt)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Aggregate Function Approximator" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "class AggregateFunctApprox():\n", " \"\"\"Very simple function approximator\"\"\"\n", " def __init__(self, learn_rate, nb_groups, group_size):\n", " self._lr = learn_rate\n", " self._group_size = group_size\n", " self._w = np.zeros(nb_groups) # weights\n", " \n", " def evaluate(self, state): \n", " # Option 1:\n", " group = (state-1) // self._group_size # [1-100, ..., 901-1000] -> [0, ..., 9]\n", " return self._w[group] # return corresponding value\n", " \n", " # Option 2:\n", " # Implement as a special case of linear combination of features\n", "# group = (state-1) // self._group_size # [1-100, ..., 901-1000] -> [0, ..., 9]\n", "# x = np.zeros_like(self._w)\n", "# x[group] = 1 # one-hot encoded feature vector [0, 1, 0]\n", "# return x @ self._w # linear combination, i.e. dot product\n", " \n", " def train(self, state, target): \n", " # Option 1:\n", " # Because grad_v_hat is a one-hot vector, we can optimize:\n", " group = (state-1) // self._group_size\n", " self._w[group] += self._lr * (target - self._w[group]) # update only one weight, \n", " # standard MC update!\n", " \n", " # Option 2:\n", "# group = (state-1) // self._group_size\n", "# x = np.zeros_like(self._w)\n", "# x[group] = 1 # one-hot feature vector\n", "# grad = x # grad. of lin. comb. is just x" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Evaluate Example 9.1" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "from collections import defaultdict" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Define environment\n", "* V_approx values were picked by trial-and-error, they ignore both nonlinearity and terminal states (which should equal zero)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "class LinearEnv:\n", " \"\"\"\n", " State nb: [ 0 1 ... 499 500 501 ... 1000 1001 ]\n", " State type: [terminal . ... . start . ... . terminal]\n", " \"\"\"\n", " V_approx = np.arange(-1001, 1001, 2) / 1000.0 # ignore nonlinearity at terminal states\n", " \n", " def __init__(self):\n", " self.reset()\n", " \n", " def reset(self):\n", " self._state = 500\n", " self._done = False\n", " return self._state\n", " \n", " def step(self, action):\n", " if self._done: raise ValueError('Episode has terminated')\n", " \n", " if action == 0: self._state -= np.random.randint(1, 101) # step left\n", " elif action == 1: self._state += np.random.randint(1, 101) # step right\n", " else: raise ValueError('Invalid action')\n", " \n", " self._state = np.clip(self._state, 0, 1001) # clip to 0..1001\n", " if self._state in [0, 1001]: # both 0 and 1001 are terminal\n", " self._done = True\n", " \n", " if self._state == 0:\n", " return self._state, -1, self._done # state, rew, done\n", " elif self._state == 1001:\n", " return self._state, 1, self._done\n", " else:\n", " return self._state, 0, self._done" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Plotting" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "def plot_linear(V, env, freq=None, saveimg=None):\n", " fig = plt.figure()\n", " ax = fig.add_subplot(111)\n", " # Note, state 0 is terminal, so we exclude it\n", " ax.plot(range(1,1001), env.V_approx[1:], color='red', linewidth=0.8, label='\"True\" value')\n", " ax.plot(range(1,1001), V[1:], color='blue', linewidth=0.8, label='Approx. MC value')\n", " ax.set_xlabel('State')\n", " ax.set_ylabel('Value Scale')\n", " ax.legend()\n", " \n", " if freq is not None:\n", " mu = np.zeros(len(V)) # convert to array, V has same len as freq\n", " for st in range(len(V)):\n", " mu[st] = freq[st]\n", " ax2 = ax.twinx()\n", " # again, exclude terminal state 0\n", " ax2.bar(range(1,1001), mu[1:], color='gray', width=5, label='State Distr.')\n", " ax2.set_ylabel('Distribution Scale')\n", " ax2.legend(loc='right', bbox_to_anchor=(1.0, 0.2))\n", " \n", " plt.tight_layout()\n", " if saveimg is not None:\n", " plt.savefig(saveimg)\n", " plt.show() " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Create environment" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "env = LinearEnv()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Random policy" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "def policy(st):\n", " return np.random.choice([0, 1])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Solve with original algorithm" ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "scrolled": true }, "outputs": [ { "data": { "image/png": "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W9KxY8e9BtcVKQ+ysiIGF8/MhMGDg2bV88/DqacmNLbSpgSVRyJm2xg9ejS33XYbAD179mT06NG5Caply5Y0CsfG6tWrF3PnzqV79+4ccMABuYO5XnHFFXTr1i33eHvKIZg/as88U1deeSV33XUXAEcccQQDBw6kffv2TJw4scjJEve47LLL6NGjB19//TW9evXi448/BoKWuEU5TMpll13GuHHj6N+/P2PHjmXs2LEAzJo1i0cffZQdO3awadMmmjZtGnWCev/995k8eTKDBw8GgtHUV69erWGNpNzJzISKFYGFC+HGG+H3vw8u65XD2QKUoBJs48aNzJw5k6+++gozIzs7GzPj0UcfBdjnH/2CkkBkeWGthsh6ixYtolatWqxdG/1kxEceeSSVKlVi2rRpPPXUU7kJ6pBDDqFatWq5LaPC9OjRg0svvZRu3bphZjRu3JidO3fSr18/0tPTqV+/Pg888MA+U3rA3lOM5J3SY8KECRwfw+vuIskga1cWlf7zb1g9EoYNgygGgS6r9KBugo0fP56rrrqK77//nlWrVrFmzRoaNmzI3LlzgeAS33fffUdOTg5jx46ldevWAOTk5DB+/HgAXnvttdzyvM466yzGjBkDwKhRo3LrzZs3j3fffZcFCxYwePBgvvvuu6hjHjhwIIMGDdpnyvgBAwZw0003sXXrViCYpmPo0KH77H/sscdSoUIFHnroodzW3p5kU7t2bbZv35773vJq0KABn3/+OQATJkzILe/UqRPPPPNM7pxUCxYsiPr9iJQZn35K5qvjqFj9oOC5pnKcnEAtqIQbPXo0/fv336vsD3/4A6+99ho9evTgzDPPpH///ixatIizzz6bSy65BAhaSYsXL+bUU0/l0EMPzb1MltfTTz/NNddcw2OPPcZhhx3GyJEj2bVrF9dddx0jR46kbt26DBkyhGuuuYaZM2fy0ksvAXDDDTcUGPNZZ52Vb/mNN97I9u3bOe2006hUqRKVKlXijjvuyLdujx49uPPOO3MTY/Xq1bnuuus4+eSTadCgAaeddlq++91///306dOHf/7zn5we0Y3p73//O7fddhunnHIK7k6DBg2YMmVKge9BpEzZsQPuvRf+7//I6jSBSn+sDhWK3q2s03QbSTz9wuzZsxk8eHC+/9AedNBBbN++PQFRlW3J/PsWydesWfCXv8D110Pf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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "weights = gradient_MC(env, policy, ep=10000, alpha=0.0003,\n", " init_w=init_w, v_hat=v_hat, grad_v_hat=grad_v_hat)\n", "V = [v_hat(st, weights) for st in range(1001)]\n", "plot_linear(V, env)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Solve with proper function approximator" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "data": { "image/png": "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+8jd93x+Jg+1oEREKppNm+D//g9++gleeQXi6EQVBd2DEhGpSKZNg44d4fTT4eWXUzY5gVpQIiIVw9q1MHAguMPMmbD//lFHVCS1oEREyjN3GD8eunSB3r2D5TKQnEAtKBGR8mvVquCB2wYNggFei3jIP9UoQYmIlDfuMHIkPP44DBkSjEBeBukSX4qYMmUKZsZnn30WdSj5mjt3LmbGyJEjc8s++eQTzIwHH3wwt+zBBx/kiCOO4Oijj+a4447j+eefL/G5L730UiZPnlzi44hUCN98E4wp+umnweCuZTQ5gRJUyhg3bhwdOnRg/PjxCTtmVlZWwo4FcMwxxzBhwoTc9fHjx3Pcccflrj/11FPMnDmThQsXsmTJEubPn09Fes5OJFI5OcGUGD17wu23B8u1akUdVYkoQaWALVu2sGDBAkaOHLlbgpo7dy6nnnoqf/zjH2nVqhUDBgzIHXuvVq1aXH/99bRt25bOnTuzazLGTp06ccstt9CxY0eGDRvGd999R+fOnTn22GPp3LkzK1euBKBHjx65rZunn36aP//5z0XGecghh7B9+3Z+/PFH3J033niD7t27526/7777ePLJJ6lduzYA++23H3379t3tGMuXL6ddu3a5699++y3HHnssAIMHD+aEE07g6KOPpn///vkmt2bNmrEuHG0+PT2dTp06AbB161Yuu+wyTjjhBNq0aZPvaO0i5dZnn8Fpp8Hq1UGrqUOHqCNKCN2DyiOC2TaYOnUq3bp147DDDqNevXp8/PHHucMWLVy4kGXLltG0aVO6devGSy+9RM+ePdm6dStt27Zl6NChDB48mLvvvjt3Ko1NmzYxb948AM4++2wuueQS+vbty6hRoxg4cCBTp05lxIgRnHzyyTRv3pyhQ4fGPUdTz549mTRpEm3atKFt27ZUr14dgF9++YVffvmFQw89tND9jzzySHbu3MnXX39NixYtmDBhAhdccAEAV199NXfccQcAF198MdOnT+fss8+OK657772X008/nVGjRrFp0ybatWtHly5ddhtcV6TcycyEBx+EqVPhySfh+OOjjiihlKDyiGK2jXHjxnHdddcB0Lt3b8aNG5eboNq1a0eLcGysPn368M4779CzZ08qVaqUO5jrRRddxHnnnZd7vF3lEMwftWueqYsvvpgbb7wRgEaNGjF48GBOO+00pkyZUuRk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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "model = AggregateFunctApprox(learn_rate=0.0003, nb_groups=10, group_size=100)\n", "gradient_MC_fix(env, policy, ep=5000, gamma=1.0, model=model)\n", "V = [model.evaluate(st) for st in range(1001)]\n", "plot_linear(V, env)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Recreate Figure 9.1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We need to track frequency of visit to each state, let's modify our algorithm slightly. Changes are marked with arrows." ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [], "source": [ "def gradient_MC_track_freq(env, policy, ep, gamma, model):\n", " count = defaultdict(float) # <- how many times state visited\n", " total = 0 # <- total state visits to all states\n", " \n", " for _ in range(ep):\n", " traj, T = generate_episode(env, policy)\n", " Gt = 0\n", " for t in range(T-1,-1,-1):\n", " St, _, _, _ = traj[t] # (st, rew, done, act)\n", " _, Rt_1, _, _ = traj[t+1]\n", " \n", " count[St] += 1\n", " total += 1\n", " \n", " Gt = gamma * Gt + Rt_1\n", " model.train(St, Gt)\n", " \n", " for key, val in count.items(): # <- calc. frequency\n", " count[key] = val / total\n", " \n", " return count # <- return freq." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Solve.\n", "* In the book alg. is run for **100k** episodes, alpha=**2e-5**. Here we run for **10k** episodes alpha=**1e-4** to save time." ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [], "source": [ "model = AggregateFunctApprox(learn_rate=0.00001, nb_groups=10, group_size=100) # +10min?\n", "freq = gradient_MC_track_freq(env, policy, ep=100000, gamma=1.0, model=model)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Plot" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAagAAAEYCAYAAAAJeGK1AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvhp/UCwAAIABJREFUeJzs3Xl4VEXWwOHfgbAJIpszsiiggMomYERQRkBAwA1UFFAE3BgVxWVcYL4RBWUGFBfciYIoyiaoIIMiSII7OyKLKAOoEURFkDVAkvP9UTeh6XSSTtKd7nSf93n6Sfe9VberE8hJ1a06JaqKMcYYE21KRboBxhhjTCAWoIwxxkQlC1DGGGOikgUoY4wxUckClDHGmKhkAcoYY0xUsgBljDEmKlmAMsYYE5UsQBljjIlKCZFuQHEqVaqUVqhQIdLNMMaYkDhw4ICqasx2NOIqQFWoUIH9+/dHuhnGGBMSInIw0m0Ip5iNvMYYY0o2C1DGGBPDRKSbiGwUkU0iMjTA+XIiMt07v0RE6nnHq4tIsojsE5Hnc7n2HBFZG662W4AyxpgYJSKlgReA7kBjoK+INPYrdhOwS1UbAE8DY7zjacBDwH25XPtKYF842p0lru5BBXLkyBFSU1NJS0uLdFNMmJUvX546depQpkyZSDfFmOLSGtikqpsBRGQa0ANY71OmB/CI93wm8LyIiKruBz4TkQb+FxWRSsC9wCBgRrgaH/cBKjU1leOPP5569eohIpFujgkTVWXnzp2kpqZSv379SDfHmFBJEJHlPq+TVDXJ53Vt4Cef16nAuX7XyC6jquki8idQHfg9j/d9FHgSOFDYhgcjokN8IjJRRH7NbQxTnGe9sdE1ItLK59wAEfneewwobBvS0tKoXr26BacYJyJUr17desom1qSraqLPI8nvfKBfbP671AZT5mhhkRZAA1V9t4BtLbBI34OaBHTL43x3oKH3GAS8BCAi1YCHcX8JtAYeFpGqhW2EBaf4YD9nE4dSgZN9XtcBtuVWRkQSgBOAP/K4ZlvgbBHZCnwGNBKRlBC19xgRDVCq+gl5fyN6AG+o8xVQRURqAl2BBar6h6ruAhaQd6AzxpjolJ4ezqsvAxqKSH0RKQv0Aeb4lZkDZI1C9QIWqWquPShVfUlVa6lqPaAd8J2qdgh5y4l8Dyo/gcZPa+dxPAcRGSQiy0VkeXp4/yEUWr169di6dSsdOnRg/vz5tGjRghYtWlCpUiVOP/10WrRoQf/+/UPyXv369eOzzz6jXbt2pKamFvl67dq1Y/Xq1SFomTFxRhWefRZuvjmMb6HpwB3AfGADMENV14nISBG53Cs2AaguIptwEx+yp6J7vaSngIEikhpgBmBYRfskidzGRoMeM/XGZJMAKlasmOtfBdGia9eudO3aFYAOHTowduxYEhMTc5RLT08nISHaf3zxacSIETz88MORboaJZrt3w003Qa1aMH58WN9KVecB8/yODfd5ngZcnUvdevlceyvQtMiNzEW096ByGz8NZly1xDjxxBMpXbo01apVy7Pcq6++Sp8+fbj00kvp3r07CxcupGfPntnnb731Vt58800Ali1bRvv27Tn77LPp3r07O3bsAKBKlSqULVuW6tWrU7p06WOu//7773Pttddmv164cCFXXHEFAIMGDSIxMZEmTZowcuTIHG1LT0+nSpUq2a+nTZvGzd5fhjt27ODKK68kMTGR1q1b89VXXxXk22NMbFmxAjp2hD594LnnoFy5SLcoakX7n+BzgDu8ufvnAn+q6nYRmQ/822dixEXAsJC8Y7du8HtesysLqEYN+PDDPIssW7YMgHfeeSffy3355ZesXr2aqlWrsnDhwoBlDh06xF133cWcOXOoUaMGb731Fg899BBJSUk8/7xbED579uwc9bp27crtt9/OwYMHqVChAtOnT6d3794AjB49mmrVqpGenk7Hjh3p1asXjRsH19sfMmQIDzzwAG3atGHr1q1ceumlrF0btsXnxkQnVXjxRXjzTXj7bWiQY3mR8RPRACUiU4EOQA0RScXNzCsDoKov47qlFwObcPPtb/DO/SEij+JuAAKMVNW8JlsEL59gEmkXXXQRVavmPWFxw4YNrFu3js6dOwOQkZFBnTp18r122bJl6dKlC//973/p0aMH8+fP55lnngFg6tSpTJgwgfT0dLZt28b69euDDlALFy5k48aN2a937dqVHQSNiQt79sAtt0D16pCcDOXLR7pFJUJEA5Sq9s3nvAKDczk3EZgYjnZFs4oVK2Y/T0hIIDMzM/t11hofVaV58+Z8+umnBb5+7969mTBhAscddxxt27alYsWKfP/994wbN46lS5dSpUoV+vXrl2M9UalSpfCd+ON7XlVZ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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "V = [model.evaluate(st) for st in range(1001)]\n", "plot_linear(V, env, freq=freq, saveimg=None) # 'assets/fig_0901.png'" ] }, { "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.6.5" } }, "nbformat": 4, "nbformat_minor": 2 }