master 0fecb49bc674 cached
49 files
2.7 MB
717.3k tokens
266 symbols
1 requests
Download .txt
Showing preview only (2,869K chars total). Download the full file or copy to clipboard to get everything.
Repository: MJeremy2017/reinforcement-learning-implementation
Branch: master
Commit: 0fecb49bc674
Files: 49
Total size: 2.7 MB

Directory structure:
gitextract_zmbv1ji4/

├── .gitignore
├── AccessControl/
│   ├── ServerAccess.ipynb
│   ├── ServerAccess.py
│   └── TileCoding.py
├── BairdExample/
│   ├── BairdCounterExample.ipynb
│   └── BairdCounterExample.py
├── BlackJack/
│   ├── blackjack_mc.ipynb
│   ├── blackjack_mc.py
│   ├── blackjack_solution.ipynb
│   ├── blackjack_solution.py
│   ├── blackjack_test.ipynb
│   └── policy
├── CliffWalking/
│   ├── cliffWalking.ipynb
│   └── cliffWalking.py
├── DynaMaze/
│   ├── DynaMaze.ipynb
│   ├── DynaMaze.py
│   ├── DynaQ+.py
│   ├── PrioritySweeping.ipynb
│   └── PrioritySweeping.py
├── GridWorld/
│   ├── GridBoard-Q.ipynb
│   ├── GridWorld.ipynb
│   ├── gridWorld.py
│   └── gridWorld_Q.py
├── LICENSE
├── MountainCar/
│   ├── MountainCar.ipynb
│   ├── MountainCar.py
│   └── TileCoding.py
├── MountainCar(Lambda)/
│   ├── MountainCar(Lambda).ipynb
│   ├── MountainCar.py
│   └── TileCoding.py
├── Multi-ArmBandit/
│   ├── Bandit.ipynb
│   └── bandit.py
├── README.md
├── RandomWalk/
│   ├── RandomWalk(n-step).ipynb
│   └── RandomWalk(n-step).py
├── RandomWalk(General)/
│   ├── RandomWalk.ipynb
│   └── RandomWalk.py
├── RandomWalk(Lambda)/
│   ├── TD(Lambda).ipynb
│   └── TD_Lambda.py
├── ShortCorridor/
│   ├── ShortCorridor.ipynb
│   └── ShortCorridor.py
├── TicTacToe/
│   ├── policy_p1
│   ├── policy_p2
│   ├── tic-tac-toe.ipynb
│   └── ticTacToe.py
├── TileCoding/
│   ├── TileCoding.ipynb
│   └── tile_coding.py
└── WindyGridWorld/
    ├── Windy_GW.ipynb
    └── windyGridWorld.py

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
.idea/*
.idea
*/.ipynb_checkpoints
.ipynb_checkpoints
*/__pycache__

================================================
FILE: AccessControl/ServerAccess.ipynb
================================================
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Access-Control Queuing Task\n",
    "---\n",
    "This is a decision task involving access control to a set of 10 servers. Customers of four different priorities arrive at a single queue. If given access to a server, the customers pay a reward of `1, 2, 4, or 8` to the server, depending on their priority, with higher priority customers paying more. In each time step, the customer at the head of the queue is either accepted (assigned to one of the servers) or rejected (removed from the queue, with a reward of zero). In either case, on the next time step the next customer in the queue is considered. The queue never empties, and the priorities of the customers in the queue are equally randomly distributed. Of course a customer cannot be served if there is no free server; the customer is always rejected in this case. Each busy server becomes free with probability `p = 0.06` on each time step.\n",
    "\n",
    "The task is to decide on each step whether to accept or reject the next customer, on the basis of his priority and the number of free servers, so as `to maximize long-term reward without discounting`.\n",
    "\n",
    "- State(num_servers, priority)\n",
    "- Action(1, 0)\n",
    "- Reward(1, 2, 4, 8)\n",
    "---\n",
    "<img src=\"differential_sarsa.png\" width=\"600\" style=\"float:left\">"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from TileCoding import *"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "ACTIONS = [0, 1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "class ValueFunction:\n",
    "\n",
    "    def __init__(self, alpha=0.01, numOfTilings=8, maxSize=2048):\n",
    "        self.maxSize = maxSize\n",
    "        self.numOfTilings = numOfTilings\n",
    "\n",
    "        # divide step size equally to each tiling\n",
    "        self.alpha = alpha / numOfTilings  # learning rate for each tile\n",
    "\n",
    "        self.hashTable = IHT(maxSize)\n",
    "\n",
    "        # weight for each tile\n",
    "        self.weights = np.zeros(maxSize)\n",
    "\n",
    "        # position and velocity needs scaling to satisfy the tile software\n",
    "        self.serverScale = self.numOfTilings / 10.0  # 10 servers\n",
    "        self.priorityScale = self.numOfTilings / 3.0  # 4 kinds of priorities\n",
    "\n",
    "    # get indices of active tiles for given state and action\n",
    "    def getActiveTiles(self, n_server, priority, action):\n",
    "        activeTiles = tiles(self.hashTable, self.numOfTilings,\n",
    "                            [self.serverScale * n_server, self.priorityScale * priority],\n",
    "                            [action])\n",
    "        return activeTiles\n",
    "\n",
    "    # estimate the value of given state and action\n",
    "    def value(self, state, action):\n",
    "        n_server, priority = state\n",
    "        activeTiles = self.getActiveTiles(n_server, priority, action)\n",
    "        return np.sum(self.weights[activeTiles]) \n",
    "    \n",
    "    # learn with given state, action and target\n",
    "    def update(self, state, action, delta):\n",
    "        n_server, priority = state\n",
    "        activeTiles = self.getActiveTiles(n_server, priority, action)\n",
    "        \n",
    "        delta *= self.alpha\n",
    "        for activeTile in activeTiles:\n",
    "            self.weights[activeTile] += delta\n",
    "            \n",
    "    def stateValue(self, state):\n",
    "        if state[0] == 0:\n",
    "            # no server available\n",
    "            return self.value(state, 0)\n",
    "        values = [self.value(state, a) for a in ACTIONS]\n",
    "        return max(values)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "code_folding": [
     0
    ]
   },
   "outputs": [],
   "source": [
    "class ServerAcess:\n",
    "    def __init__(self, exp_rate=0.3, beta=0.01):\n",
    "        self.n_server = 10\n",
    "        self.free_prob = 0.06\n",
    "        self.priorities = range(4)\n",
    "        self.actions = ACTIONS  # 0: reject; 1: accept\n",
    "        self.state = (0, 0)  # (num_servers, priority)\n",
    "        \n",
    "        self.exp_rate = exp_rate\n",
    "        self.beta = beta\n",
    "        \n",
    "    def numFreeServers(self):\n",
    "        n = 0\n",
    "        n_free_server = self.state[0]\n",
    "        n_busy_server = self.n_server - n_free_server\n",
    "        for _ in range(n_busy_server):\n",
    "            if np.random.uniform(0, 1) <= 0.06:\n",
    "                n += 1\n",
    "        n_free_server += n\n",
    "        self.state = (n_free_server, self.state[1])\n",
    "        return n_free_server\n",
    "    \n",
    "    def chooseAction(self, valueFunc):\n",
    "        n_free_server = self.numFreeServers()\n",
    "        if n_free_server == 0:\n",
    "            return 0\n",
    "        if np.random.uniform(0, 1) <= self.exp_rate:\n",
    "            action = np.random.choice(self.actions)\n",
    "        else:\n",
    "            values = {}\n",
    "            for a in self.actions:\n",
    "                v = valueFunc.value(self.state, a)\n",
    "                values[a] = v\n",
    "            action = np.random.choice([k for k, v in values.items() if v == max(values.values())])\n",
    "        return action\n",
    "    \n",
    "    def nxtState(self, action):\n",
    "        if action == 1:\n",
    "            n_free_server = self.state[0] - 1\n",
    "        else:\n",
    "            n_free_server = self.state[0]\n",
    "        priority = np.random.choice(self.priorities)\n",
    "        self.state = (n_free_server, priority)\n",
    "        return self.state\n",
    "    \n",
    "    def giveReward(self, action):\n",
    "        # recieve a reward by taking the action\n",
    "        if action == 1:\n",
    "            priority = self.state[1]\n",
    "            return np.power(2, priority)\n",
    "        return 0\n",
    "    \n",
    "    def run(self, valueFunc, steps=1000, inner_steps=100, debug=False):\n",
    "        # updating average reward estimation along the way\n",
    "        avg_reward = 0\n",
    "        self.state = (10, np.random.choice(self.priorities))\n",
    "        cur_state = self.state\n",
    "        cur_action = self.chooseAction(valueFunc)  # n free server is also updated\n",
    "        \n",
    "        total_reward = 0\n",
    "        for i in range(1, steps+1):\n",
    "            reward = self.giveReward(cur_action)\n",
    "            new_state = self.nxtState(cur_action)\n",
    "            new_action = self.chooseAction(valueFunc)\n",
    "            \n",
    "            total_reward += reward\n",
    "            if debug:\n",
    "                print(\"state {} action {} reward {}\".format(cur_state, cur_action, reward))\n",
    "            if i % inner_steps == 0:\n",
    "                print(\"step {} -> avg reward {} total reward {}\".format(i, avg_reward, total_reward))\n",
    "            \n",
    "#             target = reward - avg_reward + valueFunc.value(new_state, new_action)\n",
    "            delta = reward - avg_reward + valueFunc.value(new_state, new_action) - valueFunc.value(cur_state, cur_action)\n",
    "            avg_reward += self.beta*delta\n",
    "            valueFunc.update(cur_state, cur_action, delta)\n",
    "            \n",
    "            cur_state = new_state\n",
    "            cur_action = new_action"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "step 5000 -> avg reward 2.712112568654349 total reward 11381\n",
      "step 10000 -> avg reward 1.6655055071811895 total reward 22506\n",
      "step 15000 -> avg reward 2.1391137499926955 total reward 33799\n",
      "step 20000 -> avg reward 2.5933342886336863 total reward 45665\n",
      "step 25000 -> avg reward 1.9671566131725278 total reward 57326\n",
      "step 30000 -> avg reward 1.632133694866927 total reward 68798\n",
      "step 35000 -> avg reward 2.390062004123471 total reward 80434\n",
      "step 40000 -> avg reward 2.3949169842321223 total reward 91930\n",
      "step 45000 -> avg reward 2.151052488612957 total reward 103797\n",
      "step 50000 -> avg reward 2.032857873620931 total reward 115250\n"
     ]
    }
   ],
   "source": [
    "sa = ServerAcess(exp_rate=0.1)\n",
    "vf = ValueFunction()\n",
    "sa.run(vf, steps=50000, inner_steps=5000, debug=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x10bdf3d30>"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 720x432 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=[10, 6])\n",
    "\n",
    "for prioriy in range(4):\n",
    "    n_servers = []\n",
    "    values = []\n",
    "    for n_server in range(11):\n",
    "        value = vf.stateValue((n_server, prioriy))\n",
    "        n_servers.append(n_server)\n",
    "        values.append(value)\n",
    "    plt.plot(n_servers, values, label=\"priority {}\".format(np.power(2, prioriy)))\n",
    "\n",
    "plt.xlabel(\"Number of Free Servers\", size=14)\n",
    "plt.ylabel(\"State Value\", size=14)\n",
    "plt.legend()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [],
   "source": [
    "l = []\n",
    "for prioriy in range(4):\n",
    "    for n_server in range(11):\n",
    "        action = \"reject\" if vf.value((n_server, prioriy), 0) >= vf.value((n_server, prioriy), 1) else \"accept\"\n",
    "        l.append([prioriy, n_server, action])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Self Tile Coding"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "\n",
    "\n",
    "def create_tiling(feat_range, bins, offset):\n",
    "    \"\"\"\n",
    "    Create 1 tiling spec of 1 dimension(feature)\n",
    "    feat_range: feature range; example: [-1, 1]\n",
    "    bins: number of bins for that feature; example: 10\n",
    "    offset: offset for that feature; example: 0.2\n",
    "    \"\"\"\n",
    "    \n",
    "    return np.linspace(feat_range[0], feat_range[1], bins+1)[1:-1] + offset\n",
    "\n",
    "\n",
    "def create_tilings(feature_ranges, number_tilings, bins, offsets):\n",
    "    \"\"\"\n",
    "    feature_ranges: range of each feature; example: x: [-1, 1], y: [2, 5] -> [[-1, 1], [2, 5]]\n",
    "    number_tilings: number of tilings; example: 3 tilings\n",
    "    bins: bin size for each tiling and dimension; example: [[10, 10], [10, 10], [10, 10]]: 3 tilings * [x_bin, y_bin]\n",
    "    offsets: offset for each tiling and dimension; example: [[0, 0], [0.2, 1], [0.4, 1.5]]: 3 tilings * [x_offset, y_offset]\n",
    "    \"\"\"\n",
    "    tilings = []\n",
    "    # for each tiling\n",
    "    for tile_i in range(number_tilings):\n",
    "        tiling_bin = bins[tile_i]\n",
    "        tiling_offset = offsets[tile_i]\n",
    "        \n",
    "        tiling = []\n",
    "        # for each feature dimension\n",
    "        for feat_i in range(len(feature_ranges)):\n",
    "            feat_range = feature_ranges[feat_i]\n",
    "            # tiling for 1 feature\n",
    "            feat_tiling = create_tiling(feat_range, tiling_bin[feat_i], tiling_offset[feat_i])\n",
    "            tiling.append(feat_tiling)\n",
    "        tilings.append(tiling)\n",
    "    return np.array(tilings)\n",
    "\n",
    "\n",
    "def get_tile_coding(feature, tilings):\n",
    "    \"\"\"\n",
    "    feature: sample feature with multiple dimensions that need to be encoded; example: [0.1, 2.5], [-0.3, 2.0]\n",
    "    tilings: tilings with a few layers\n",
    "    return: the encoding for the feature on each layer\n",
    "    \"\"\"\n",
    "    num_dims = len(feature)\n",
    "    feat_codings = []\n",
    "    for tiling in tilings:\n",
    "        feat_coding = []\n",
    "        for i in range(num_dims):\n",
    "            feat_i = feature[i]\n",
    "            tiling_i = tiling[i]  # tiling on that dimension\n",
    "            coding_i = np.digitize(feat_i, tiling_i)\n",
    "            feat_coding.append(coding_i)\n",
    "        feat_codings.append(feat_coding)\n",
    "    return np.array(feat_codings)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [],
   "source": [
    "server_range = [0, 10]\n",
    "priority_range = [0, 3]\n",
    "feature_ranges = [server_range, priority_range]  # 2 features\n",
    "number_tilings = 8\n",
    "bins = [[16, 16] for _ in range(number_tilings)]\n",
    "offsets = [[i, j] for i, j in zip(np.linspace(server_range[0], server_range[1], number_tilings), \n",
    "                                  np.linspace(priority_range[0], priority_range[1], number_tilings))]\n",
    "\n",
    "tilings = create_tilings(feature_ranges=feature_ranges, number_tilings=number_tilings, bins=bins, offsets=offsets)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(8, 2, 15)"
      ]
     },
     "execution_count": 75,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tilings.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 99,
   "metadata": {},
   "outputs": [],
   "source": [
    "# example Q-function\n",
    "\n",
    "class QValueFunction:\n",
    "\n",
    "    def __init__(self, tilings, actions, lr):\n",
    "        self.tilings = tilings\n",
    "        self.num_tilings = len(self.tilings)\n",
    "        self.actions = [0, 1]\n",
    "        self.lr = lr # / self.num_tilings  # learning rate equally assigned to each tiling\n",
    "        self.state_sizes = [tuple(len(splits) + 1 for splits in tiling) for tiling in\n",
    "                            self.tilings]  # [(10, 10), (10, 10), (10, 10)]\n",
    "        self.q_tables = [np.zeros(shape=(state_size + (len(self.actions),))) for state_size in self.state_sizes]\n",
    "\n",
    "    def value(self, state, action):\n",
    "        state_codings = get_tile_coding(state, self.tilings)  # [[5, 1], [4, 0], [3, 0]] ...\n",
    "        action_idx = self.actions.index(action)\n",
    "\n",
    "        value = 0\n",
    "        for coding, q_table in zip(state_codings, self.q_tables):\n",
    "            # for each q table\n",
    "            value += q_table[tuple(coding) + (action_idx,)]\n",
    "        return value / self.num_tilings\n",
    "\n",
    "#     def update(self, state, action, target):\n",
    "#         n_server, priority = state\n",
    "#         state_codings = get_tile_coding(state, self.tilings)  # [[5, 1], [4, 0], [3, 0]] ...\n",
    "#         action_idx = self.actions.index(action)\n",
    "        \n",
    "#         delta *= self.lr\n",
    "#         for coding, q_table in zip(state_codings, self.q_tables):\n",
    "#             q_table[tuple(coding) + (action_idx,)] += delta\n",
    "    \n",
    "    def update(self, state, action, target):\n",
    "        n_server, priority = state\n",
    "        state_codings = get_tile_coding(state, self.tilings)  # [[5, 1], [4, 0], [3, 0]] ...\n",
    "        action_idx = self.actions.index(action)\n",
    "        \n",
    "        for coding, q_table in zip(state_codings, self.q_tables):\n",
    "            delta = target - q_table[tuple(coding) + (action_idx,)]\n",
    "            q_table[tuple(coding) + (action_idx,)] += self.lr*delta\n",
    "    \n",
    "    def stateValue(self, state):\n",
    "        if state[0] == 0:\n",
    "            # no server available\n",
    "            return self.value(state, 0)\n",
    "        values = [self.value(state, a) for a in ACTIONS]\n",
    "        return max(values)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 100,
   "metadata": {
    "code_folding": [
     0
    ]
   },
   "outputs": [],
   "source": [
    "class ServerAcess:\n",
    "    def __init__(self, exp_rate=0.3, lr=0.1, beta=0.01):\n",
    "        self.n_server = 10\n",
    "        self.free_prob = 0.06\n",
    "        self.priorities = range(4)\n",
    "        self.actions = ACTIONS  # 0: reject; 1: accept\n",
    "        self.state = (0, 0)  # (num_servers, priority)\n",
    "        \n",
    "        self.exp_rate = exp_rate\n",
    "        self.lr = lr\n",
    "        self.beta = beta\n",
    "#         self.alpha = alpha\n",
    "        \n",
    "    def numFreeServers(self):\n",
    "        n = 0\n",
    "        n_free_server = self.state[0]\n",
    "        n_busy_server = self.n_server - n_free_server\n",
    "        for _ in range(n_busy_server):\n",
    "            if np.random.uniform(0, 1) <= 0.06:\n",
    "                n += 1\n",
    "        n_free_server += n\n",
    "        self.state = (n_free_server, self.state[1])\n",
    "        return n_free_server\n",
    "    \n",
    "    def chooseAction(self, valueFunc):\n",
    "        n_free_server = self.numFreeServers()\n",
    "        if n_free_server == 0:\n",
    "            return 0\n",
    "        if np.random.uniform(0, 1) <= self.exp_rate:\n",
    "            action = np.random.choice(self.actions)\n",
    "        else:\n",
    "            values = {}\n",
    "            for a in self.actions:\n",
    "                v = valueFunc.value(self.state, a)\n",
    "                values[a] = v\n",
    "            action = np.random.choice([k for k, v in values.items() if v == max(values.values())])\n",
    "        return action\n",
    "    \n",
    "    def nxtState(self, action):\n",
    "        if action == 1:\n",
    "            n_free_server = self.state[0] - 1\n",
    "        else:\n",
    "            n_free_server = self.state[0]\n",
    "        priority = np.random.choice(self.priorities)\n",
    "        self.state = (n_free_server, priority)\n",
    "        return self.state\n",
    "    \n",
    "    def giveReward(self, action):\n",
    "        # recieve a reward by taking the action\n",
    "        if action == 1:\n",
    "            priority = self.state[1]\n",
    "            return np.power(2, priority)\n",
    "        return 0\n",
    "    \n",
    "    def run(self, valueFunc, steps=1000, inner_steps=100, debug=False):\n",
    "        # updating average reward estimation along the way\n",
    "        avg_reward = 0\n",
    "        self.state = (10, np.random.choice(self.priorities))\n",
    "        cur_state = self.state\n",
    "        cur_action = self.chooseAction(valueFunc)  # n free server is also updated\n",
    "        \n",
    "        total_reward = 0\n",
    "        for i in range(1, steps+1):\n",
    "            reward = self.giveReward(cur_action)\n",
    "            new_state = self.nxtState(cur_action)\n",
    "            new_action = self.chooseAction(valueFunc)\n",
    "            \n",
    "            total_reward += reward\n",
    "            if debug:\n",
    "                print(\"state {} action {} reward {}\".format(cur_state, cur_action, reward))\n",
    "            if i % inner_steps == 0:\n",
    "                print(\"step {} -> avg reward {} total reward {}\".format(i, avg_reward, total_reward))\n",
    "                total_reward = 0\n",
    "            \n",
    "            target = reward - avg_reward + valueFunc.value(new_state, new_action)\n",
    "            delta = reward - avg_reward + valueFunc.value(new_state, new_action) - valueFunc.value(cur_state, cur_action)\n",
    "            avg_reward += self.beta*delta\n",
    "            valueFunc.update(cur_state, cur_action, target)\n",
    "            \n",
    "            cur_state = new_state\n",
    "            cur_action = new_action"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "step 5000 -> avg reward 1.764197559156301 total reward 10802\n",
      "step 10000 -> avg reward 2.2187221384375064 total reward 10614\n",
      "step 15000 -> avg reward 2.169983119676696 total reward 11053\n",
      "step 20000 -> avg reward 1.8439132889821988 total reward 10432\n",
      "step 25000 -> avg reward 2.0885899636716974 total reward 10768\n",
      "step 30000 -> avg reward 1.9450030230763382 total reward 10697\n",
      "step 35000 -> avg reward 2.463629138140144 total reward 11127\n",
      "step 40000 -> avg reward 2.20450155554836 total reward 10859\n",
      "step 45000 -> avg reward 2.51961257884254 total reward 10881\n",
      "step 50000 -> avg reward 2.2825924235160775 total reward 10984\n"
     ]
    }
   ],
   "source": [
    "sa = ServerAcess(exp_rate=0.1)\n",
    "vf = QValueFunction(tilings=tilings, actions=[0, 1], lr=0.01)\n",
    "sa.run(vf, steps=50000, inner_steps=5000, debug=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x10f81c908>"
      ]
     },
     "execution_count": 102,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 720x432 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=[10, 6])\n",
    "\n",
    "for prioriy in range(4):\n",
    "    n_servers = []\n",
    "    values = []\n",
    "    for n_server in range(11):\n",
    "        value = vf.stateValue((n_server, prioriy))\n",
    "        n_servers.append(n_server)\n",
    "        values.append(value)\n",
    "    plt.plot(n_servers, values, label=\"priority {}\".format(np.power(2, prioriy)))\n",
    "plt.legend()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## If not avg Reward"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "code_folding": []
   },
   "outputs": [],
   "source": [
    "class ValueFunction:\n",
    "\n",
    "    def __init__(self, alpha=0.01, numOfTilings=8, maxSize=2048):\n",
    "        self.maxSize = maxSize\n",
    "        self.numOfTilings = numOfTilings\n",
    "\n",
    "        # divide step size equally to each tiling\n",
    "        self.alpha = alpha / numOfTilings  # learning rate for each tile\n",
    "\n",
    "        self.hashTable = IHT(maxSize)\n",
    "\n",
    "        # weight for each tile\n",
    "        self.weights = np.zeros(maxSize)\n",
    "\n",
    "        # position and velocity needs scaling to satisfy the tile software\n",
    "        self.serverScale = self.numOfTilings / 10.0  # 10 servers\n",
    "        self.priorityScale = self.numOfTilings / 3.0  # 4 kinds of priorities\n",
    "\n",
    "    # get indices of active tiles for given state and action\n",
    "    def getActiveTiles(self, n_server, priority, action):\n",
    "        activeTiles = tiles(self.hashTable, self.numOfTilings,\n",
    "                            [self.serverScale * n_server, self.priorityScale * priority],\n",
    "                            [action])\n",
    "        return activeTiles\n",
    "\n",
    "    # estimate the value of given state and action\n",
    "    def value(self, state, action):\n",
    "        n_server, priority = state\n",
    "        activeTiles = self.getActiveTiles(n_server, priority, action)\n",
    "        return np.sum(self.weights[activeTiles]) # /self.numOfTilings\n",
    "\n",
    "    # learn with given state, action and target\n",
    "    def update(self, state, action, delta):\n",
    "        n_server, priority = state\n",
    "        activeTiles = self.getActiveTiles(n_server, priority, action)\n",
    "        \n",
    "        delta *= self.alpha\n",
    "        for activeTile in activeTiles:\n",
    "            self.weights[activeTile] += delta\n",
    "            \n",
    "    def stateValue(self, state):\n",
    "        if state[0] == 0:\n",
    "            # no server available\n",
    "            return self.value(state, 0)\n",
    "        values = [self.value(state, a) for a in ACTIONS]\n",
    "        return max(values)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "code_folding": []
   },
   "outputs": [],
   "source": [
    "class ServerAcess:\n",
    "    def __init__(self, exp_rate=0.3, lr=0.1, beta=0.01):\n",
    "        self.n_server = 10\n",
    "        self.free_prob = 0.06\n",
    "        self.priorities = range(4)\n",
    "        self.actions = ACTIONS  # 0: reject; 1: accept\n",
    "        self.state = (0, 0)  # (num_servers, priority)\n",
    "        \n",
    "        self.exp_rate = exp_rate\n",
    "        self.lr = lr\n",
    "        self.beta = beta\n",
    "#         self.alpha = alpha\n",
    "        \n",
    "    def numFreeServers(self):\n",
    "        n = 0\n",
    "        n_free_server = self.state[0]\n",
    "        n_busy_server = self.n_server - n_free_server\n",
    "        for _ in range(n_busy_server):\n",
    "            if np.random.uniform(0, 1) <= 0.06:\n",
    "                n += 1\n",
    "        n_free_server += n\n",
    "        self.state = (n_free_server, self.state[1])\n",
    "        return n_free_server\n",
    "    \n",
    "    def chooseAction(self, valueFunc):\n",
    "        n_free_server = self.numFreeServers()\n",
    "        if n_free_server == 0:\n",
    "            return 0\n",
    "        if np.random.uniform(0, 1) <= self.exp_rate:\n",
    "            action = np.random.choice(self.actions)\n",
    "        else:\n",
    "            values = {}\n",
    "            for a in self.actions:\n",
    "                v = valueFunc.value(self.state, a)\n",
    "                values[a] = v\n",
    "            action = np.random.choice([k for k, v in values.items() if v == max(values.values())])\n",
    "        return action\n",
    "    \n",
    "    def nxtState(self, action):\n",
    "        if action == 1:\n",
    "            n_free_server = self.state[0] - 1\n",
    "        else:\n",
    "            n_free_server = self.state[0]\n",
    "        priority = np.random.choice(self.priorities)\n",
    "        self.state = (n_free_server, priority)\n",
    "        return self.state\n",
    "    \n",
    "    def giveReward(self, action):\n",
    "        # recieve a reward by taking the action\n",
    "        if action == 1:\n",
    "            priority = self.state[1]\n",
    "            return np.power(2, priority)\n",
    "        return 0\n",
    "    \n",
    "    def run(self, valueFunc, steps=1000, inner_steps=100, debug=False):\n",
    "        # updating average reward estimation along the way\n",
    "        self.state = (10, np.random.choice(self.priorities))\n",
    "        cur_state = self.state\n",
    "        cur_action = self.chooseAction(valueFunc)  # n free server is also updated\n",
    "        \n",
    "        total_reward = 0\n",
    "        for i in range(1, steps+1):\n",
    "            reward = self.giveReward(cur_action)\n",
    "            new_state = self.nxtState(cur_action)\n",
    "            new_action = self.chooseAction(valueFunc)\n",
    "            \n",
    "            total_reward += reward\n",
    "#             print(i)\n",
    "            if debug:\n",
    "                print(\"state {} action {} reward {}\".format(cur_state, cur_action, reward))  \n",
    "#             target = reward - avg_reward + valueFunc.value(new_state, new_action)\n",
    "            delta = reward + valueFunc.value(new_state, new_action) - valueFunc.value(cur_state, cur_action)\n",
    "            valueFunc.update(cur_state, cur_action, delta)\n",
    "            \n",
    "            cur_state = new_state\n",
    "            cur_action = new_action"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "sa = ServerAcess(exp_rate=0.1)\n",
    "vf = ValueFunction()\n",
    "sa.run(vf, steps=50000, inner_steps=5000, debug=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x10bc90a20>"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 720x432 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=[10, 6])\n",
    "\n",
    "for prioriy in range(4):\n",
    "    n_servers = []\n",
    "    values = []\n",
    "    for n_server in range(11):\n",
    "        value = vf.stateValue((n_server, prioriy))\n",
    "        n_servers.append(n_server)\n",
    "        values.append(value)\n",
    "    plt.plot(n_servers, values, label=\"priority {}\".format(np.power(2, prioriy)))\n",
    "    \n",
    "plt.xlabel(\"Number of Free Servers\", size=14)\n",
    "plt.ylabel(\"State Value\", size=14)\n",
    "plt.legend()"
   ]
  }
 ],
 "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
}


================================================
FILE: AccessControl/ServerAccess.py
================================================
import numpy as np
import matplotlib.pyplot as plt
from TileCoding import *

ACTIONS = [0, 1]


class ValueFunction:

    def __init__(self, alpha=0.01, numOfTilings=8, maxSize=2048):
        self.maxSize = maxSize
        self.numOfTilings = numOfTilings

        # divide step size equally to each tiling
        self.alpha = alpha / numOfTilings  # learning rate for each tile

        self.hashTable = IHT(maxSize)

        # weight for each tile
        self.weights = np.zeros(maxSize)

        # position and velocity needs scaling to satisfy the tile software
        self.serverScale = self.numOfTilings / 10.0  # 10 servers
        self.priorityScale = self.numOfTilings / 3.0  # 4 kinds of priorities

    # get indices of active tiles for given state and action
    def getActiveTiles(self, n_server, priority, action):
        activeTiles = tiles(self.hashTable, self.numOfTilings,
                            [self.serverScale * n_server, self.priorityScale * priority],
                            [action])
        return activeTiles

    # estimate the value of given state and action
    def value(self, state, action):
        n_server, priority = state
        activeTiles = self.getActiveTiles(n_server, priority, action)
        return np.sum(self.weights[activeTiles])  # /self.numOfTilings

    # learn with given state, action and target
    def update(self, state, action, delta):
        n_server, priority = state
        activeTiles = self.getActiveTiles(n_server, priority, action)

        delta *= self.alpha
        for activeTile in activeTiles:
            self.weights[activeTile] += delta

    def stateValue(self, state):
        if state[0] == 0:
            # no server available
            return self.value(state, 0)
        values = [self.value(state, a) for a in ACTIONS]
        return max(values)


class ServerAcess:
    def __init__(self, exp_rate=0.3, lr=0.1, beta=0.01):
        self.n_server = 10
        self.free_prob = 0.06
        self.priorities = range(4)
        self.actions = ACTIONS  # 0: reject; 1: accept
        self.state = (0, 0)  # (num_servers, priority)

        self.exp_rate = exp_rate
        self.lr = lr
        self.beta = beta

    #         self.alpha = alpha

    def numFreeServers(self):
        n = 0
        n_free_server = self.state[0]
        n_busy_server = self.n_server - n_free_server
        for _ in range(n_busy_server):
            if np.random.uniform(0, 1) <= 0.06:
                n += 1
        n_free_server += n
        self.state = (n_free_server, self.state[1])
        return n_free_server

    def chooseAction(self, valueFunc):
        n_free_server = self.numFreeServers()
        if n_free_server == 0:
            return 0
        if np.random.uniform(0, 1) <= self.exp_rate:
            action = np.random.choice(self.actions)
        else:
            values = {}
            for a in self.actions:
                v = valueFunc.value(self.state, a)
                values[a] = v
            action = np.random.choice([k for k, v in values.items() if v == max(values.values())])
        return action

    def nxtState(self, action):
        if action == 1:
            n_free_server = self.state[0] - 1
        else:
            n_free_server = self.state[0]
        priority = np.random.choice(self.priorities)
        self.state = (n_free_server, priority)
        return self.state

    def giveReward(self, action):
        # recieve a reward by taking the action
        if action == 1:
            priority = self.state[1]
            return np.power(2, priority)
        return 0

    def run(self, valueFunc, steps=1000, inner_steps=100, debug=False):
        # updating average reward estimation along the way
        avg_reward = 0
        self.state = (10, np.random.choice(self.priorities))
        cur_state = self.state
        cur_action = self.chooseAction(valueFunc)  # n free server is also updated

        total_reward = 0
        for i in range(1, steps + 1):
            reward = self.giveReward(cur_action)
            new_state = self.nxtState(cur_action)
            new_action = self.chooseAction(valueFunc)

            total_reward += reward
            if debug:
                print("state {} action {} reward {}".format(cur_state, cur_action, reward))
            if i % inner_steps == 0:
                print("step {} -> avg reward {} total reward {}".format(i, avg_reward, total_reward))

            #             target = reward - avg_reward + valueFunc.value(new_state, new_action)
            delta = reward - avg_reward + valueFunc.value(new_state, new_action) - valueFunc.value(cur_state,
                                                                                                   cur_action)
            avg_reward += self.beta * delta
            valueFunc.update(cur_state, cur_action, delta)

            cur_state = new_state
            cur_action = new_action


if __name__ == "__main__":
    sa = ServerAcess(exp_rate=0.1)
    vf = ValueFunction()
    sa.run(vf, steps=50000, inner_steps=5000, debug=False)

    plt.figure(figsize=[10, 6])

    for prioriy in range(4):
        n_servers = []
        values = []
        for n_server in range(11):
            value = vf.stateValue((n_server, prioriy))
            n_servers.append(n_server)
            values.append(value)
        plt.plot(n_servers, values, label="priority {}".format(np.power(2, prioriy)))
    plt.legend()


================================================
FILE: AccessControl/TileCoding.py
================================================
"""
Tile Coding Software version 3.0beta
by Rich Sutton
based on a program created by Steph Schaeffer and others
External documentation and recommendations on the use of this code is available in the
reinforcement learning textbook by Sutton and Barto, and on the web.
These need to be understood before this code is.

This software is for Python 3 or more.

This is an implementation of grid-style tile codings, based originally on
the UNH CMAC code (see http://www.ece.unh.edu/robots/cmac.htm), but by now highly changed.
Here we provide a function, "tiles", that maps floating and integer
variables to a list of tiles, and a second function "tiles-wrap" that does the same while
wrapping some floats to provided widths (the lower wrap value is always 0).

The float variables will be gridded at unit intervals, so generalization
will be by approximately 1 in each direction, and any scaling will have
to be done externally before calling tiles.

Num-tilings should be a power of 2, e.g., 16. To make the offsetting work properly, it should
also be greater than or equal to four times the number of floats.

The first argument is either an index hash table of a given size (created by (make-iht size)),
an integer "size" (range of the indices from 0), or nil (for testing, indicating that the tile
coordinates are to be returned without being converted to indices).
"""

basehash = hash

class IHT:
    "Structure to handle collisions"
    def __init__(self, sizeval):
        self.size = sizeval
        self.overfullCount = 0
        self.dictionary = {}

    def __str__(self):
        "Prepares a string for printing whenever this object is printed"
        return "Collision table:" + \
               " size:" + str(self.size) + \
               " overfullCount:" + str(self.overfullCount) + \
               " dictionary:" + str(len(self.dictionary)) + " items"

    def count (self):
        return len(self.dictionary)

    def fullp (self):
        return len(self.dictionary) >= self.size

    def getindex (self, obj, readonly=False):
        d = self.dictionary
        if obj in d: return d[obj]
        elif readonly: return None
        size = self.size
        count = self.count()
        if count >= size:
            if self.overfullCount==0: print('IHT full, starting to allow collisions')
            self.overfullCount += 1
            return basehash(obj) % self.size
        else:
            d[obj] = count
            return count

def hashcoords(coordinates, m, readonly=False):
    if isinstance(m, IHT): return m.getindex(tuple(coordinates), readonly)
    if isinstance(m, int): return basehash(tuple(coordinates)) % m
    if m is None: return coordinates

from math import floor, log
from six.moves import zip_longest

def tiles(ihtORsize, numtilings, floats, ints=[], readonly=False):
    """returns num-tilings tile indices corresponding to the floats and ints"""
    qfloats = [floor(f*numtilings) for f in floats]
    Tiles = []
    for tiling in range(numtilings):
        tilingX2 = tiling*2
        coords = [tiling]
        b = tiling
        for q in qfloats:
            coords.append( (q + b) // numtilings )
            b += tilingX2
        coords.extend(ints)
        Tiles.append(hashcoords(coords, ihtORsize, readonly))
    return Tiles

def tileswrap (ihtORsize, numtilings, floats, wrapwidths, ints=[], readonly=False):
    """returns num-tilings tile indices corresponding to the floats and ints, wrapping some floats"""
    qfloats = [floor(f*numtilings) for f in floats]
    Tiles = []
    for tiling in range(numtilings):
        tilingX2 = tiling*2
        coords = [tiling]
        b = tiling
        for q, width in zip_longest(qfloats, wrapwidths):
            c = (q + b%numtilings) // numtilings
            coords.append(c%width if width else c)
            b += tilingX2
        coords.extend(ints)
        Tiles.append(hashcoords(coords, ihtORsize, readonly))
    return Tiles

================================================
FILE: BairdExample/BairdCounterExample.ipynb
================================================
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Baird Counter Example\n",
    "---\n",
    "To convert them to semi-gradient form, we simply replace the update to an array `(V or Q)` to an update to a weight vector `(w)`, using the approximate value function (`vˆ` or `qˆ`) and its gradient. Many of these algorithms use the per-step `importance sampling ratio` (importance weight):\n",
    "\n",
    "<img src=\"rho.png\" width=\"200\">\n",
    "\n",
    "<img src=\"weights_update.png\" width=\"300\">\n",
    "\n",
    "---\n",
    "The dashed action takes the system to one of the six upper states with equal probability, whereas the solid action takes the system to the seventh state. The `behavior policy b` selects the dashed and solid actions with probabilities `6/7` and `1/7`, so that the next-state distribution under it is uniform (the same for all nonterminal states), which is also the starting distribution for each episode. The target policy `π` always takes the solid action, and so the on-policy distribution (for `π`) is concentrated in the seventh state. The reward is `zero` on all transitions. The discount rate is `γ = 0.99`.\n",
    "\n",
    "<img src=\"Baird.png\" width=\"600\">\n",
    "\n",
    "- [Target Policy & Behaviour Policy](https://stats.stackexchange.com/questions/410131/in-rl-why-using-a-behavior-policy-instead-of-the-target-policy-for-an-episode-i)\n",
    "- [Target Policy & Behaviour Policy2](https://stats.stackexchange.com/questions/237085/how-to-correctly-compute-rho-in-reinforcement-learning-with-importance-sampli?rq=1)\n",
    "\n",
    "---\n",
    "## TDC\n",
    "<img src=\"TDC.png\" width=300>\n",
    "<img src=\"TDC_v.png\" width=300>\n",
    "\n",
    "which again is O(d) if the final product (xt*vt) is done first. This algorithm is known as either TD(0) with gradient correction (TDC) or, alternatively, as GTD(0)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "STATES = range(7)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 115,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Baird:\n",
    "    \n",
    "    def __init__(self, gamma=0.99, alpha=0.01):\n",
    "        self.state = np.random.choice(STATES)\n",
    "        self.prob = 1.0/7\n",
    "        self.actions = [\"solid\", \"dash\"]\n",
    "        self.gamma = gamma\n",
    "        self.alpha = alpha\n",
    "        \n",
    "        self.features = np.zeros((len(STATES), 8))  # n_states x n_weights (this is the representation of states)\n",
    "        for i in range(len(STATES)):\n",
    "            if i == 6:\n",
    "                self.features[i, -2] = 1\n",
    "                self.features[i, -1] = 2\n",
    "            else:\n",
    "                self.features[i, i] = 2\n",
    "                self.features[i, -1] = 1\n",
    "        \n",
    "        self.weights = np.ones(8)\n",
    "        self.weights[-2] = 10\n",
    "        \n",
    "    def chooseAction(self):\n",
    "        if np.random.binomial(1, self.prob) == 1:\n",
    "            action = \"solid\"\n",
    "        else:\n",
    "            action = \"dash\"\n",
    "        return action\n",
    "    \n",
    "    def takeAction(self, action):\n",
    "        if action == \"solid\":\n",
    "            nxtState = 6\n",
    "        else:\n",
    "            nxtState = np.random.choice(STATES[:-1])\n",
    "        return nxtState\n",
    "    \n",
    "    def value(self, state):\n",
    "        v = np.dot(ba.features[state, :], ba.weights)\n",
    "        return v\n",
    "    \n",
    "    def run_semi_gradient_TD(self, rounds=100, sarsa=False):\n",
    "        reward = 0\n",
    "        \n",
    "        step_weights = np.zeros((rounds, len(self.weights)))\n",
    "        for i in range(rounds):\n",
    "            step_weights[i, :] = self.weights\n",
    "            action = self.chooseAction()\n",
    "            nxtState = self.takeAction(action)\n",
    "            \n",
    "            if action == \"dash\":\n",
    "                rho = 0\n",
    "            else:\n",
    "                rho = 1/self.prob\n",
    "            \n",
    "            if sarsa:\n",
    "                rho = 1\n",
    "            \n",
    "            delta = reward + self.gamma*self.value(nxtState) - self.value(self.state)\n",
    "            delta *= self.alpha*rho\n",
    "            # update\n",
    "            self.weights += delta*self.features[state, :]\n",
    "                        \n",
    "            self.state = nxtState\n",
    "        return step_weights\n",
    "    \n",
    "    def run_TDC(self, beta=0.01, rounds=100):\n",
    "        reward = 0\n",
    "        v = np.zeros(8)\n",
    "        \n",
    "        step_weights = np.zeros((rounds, len(self.weights)))\n",
    "        for i in range(rounds):\n",
    "            step_weights[i, :] = self.weights\n",
    "            action = self.chooseAction()\n",
    "            nxtState = self.takeAction(action)\n",
    "            \n",
    "            if action == \"dash\":\n",
    "                rho = 0\n",
    "            else:\n",
    "                rho = 1/self.prob\n",
    "            \n",
    "            delta = reward + self.gamma*self.value(nxtState) - self.value(self.state)\n",
    "            self.weights += self.alpha*rho*(delta*self.features[self.state, :] - \n",
    "                                            self.gamma*self.features[nxtState, :]*np.dot(self.features[self.state, :], v))\n",
    "            v += beta*rho*(delta - np.dot(v, self.features[self.state, :]))*self.features[self.state, :]\n",
    "            \n",
    "            self.state = nxtState\n",
    "        print(\"last v \\n\", v)\n",
    "        return step_weights"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 104,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[2. 0. 0. 0. 0. 0. 0. 1.]\n",
      " [0. 2. 0. 0. 0. 0. 0. 1.]\n",
      " [0. 0. 2. 0. 0. 0. 0. 1.]\n",
      " [0. 0. 0. 2. 0. 0. 0. 1.]\n",
      " [0. 0. 0. 0. 2. 0. 0. 1.]\n",
      " [0. 0. 0. 0. 0. 2. 0. 1.]\n",
      " [0. 0. 0. 0. 0. 0. 1. 2.]]\n",
      "\n",
      "[ 1.  1.  1.  1.  1.  1. 10.  1.]\n"
     ]
    }
   ],
   "source": [
    "ba = Baird()\n",
    "print(ba.features)\n",
    "print()\n",
    "print(ba.weights)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Semi-gradient TD"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 100,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "ba = Baird()\n",
    "step_weigts_q = ba.run_semi_gradient_TD(rounds=1000)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "metadata": {},
   "outputs": [],
   "source": [
    "ba = Baird()\n",
    "step_weigts_sarsa = ba.run_semi_gradient_TD(rounds=1000, sarsa=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x110b46cf8>"
      ]
     },
     "execution_count": 102,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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GSTXwPkX4Gcq3kRERMDMsoCZJNebW+5xHJEzoklMRIa2rwMbgFrg//U4i4iIyEBxF8llCl4gOUJFZNDQEEoREREREZFBQj1wIiIiIiIig4QKOBERERERkUFiQExikpeX5woLC72OISIi/aCioqLaOZfvdY7BQvdIEZHhoaf3xwFRwBUWFlJeXu51DBER6QdmttvrDIOJ7pEiIsNDT++PGkIpIiIiIiIySKiAExERERERGSRUwImIiIiIiAwSA+IZOBERERERkdOJRqPs3buX9vZ2r6O8a+FwmIKCAoLB4Lt6vwo4EREREREZFPbu3Ut2djaFhYWYmddxzphzjpqaGvbu3cvUqVPf1Tk0hFJERERERAaF9vZ2Ro8ePSiLNwAzY/To0WfVg6gCTkREREREBo3BWrwdcbb5VcCJiIiIiIj0gm9+85tMmjSJrKysPruGCjgREREREZFecM011/Dyyy/36TVUwImIiPQyM7vfzA6Z2Vtd9o0ysz+b2dbU95FeZhQRkTO3YsUK7rzzTgCWLVvGokWLAFizZg033ngjF198MePHj+/TDJqFUkREpPf9ArgLeKDLvtuBNc65H5rZ7antb3iQTURkSPhff9jIpv2NvXrO2RNy+O4155/0eFlZGatWrWLp0qWUl5cTiUSIRqOsX7+e0tLSXs1yMuqBExGRk3LOsXv3brZu3crWrVu9jjNoOOeeB2qP2X0d8MvU618CH+mPLJEdDUQPtPTHpUREhrzi4mIqKipoamoiFApRUlJCeXk569at67cCTj1wIiJyUvv27WP16tVActas7373ux4nGtTGOueqAJxzVWY25mQNzWwJsARg8uTJZ3XRmoc2keiIM/G7JVjQf1bnEhEZSE7VU9ZXgsEghYWFrF69moULF1JUVMTatWvZvn07s2bN6pcM6oETEZGTam1tBeDaa6/li1/8osdphg/n3L3OuQXOuQX5+flnda7M946HmCPyTlMvpRMRGd7KyspYuXIlZWVllJaWcs899zBv3rx+W95ABZyIiJxUNBoFYOLEiRQUFHicZtA7aGbjAVLfD/XHRTMuTHb0Vf/sTVrfONwflxQRGdJKS0upqqqipKSEsWPHEg6HO4dPfv3rX6egoIDW1lYKCgr43ve+1+vX1xBKERE5qVgsBiSHjMhZ+y/gc8APU99/3x8XDY7JYPRNs6n59RY6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
Download .txt
gitextract_zmbv1ji4/

├── .gitignore
├── AccessControl/
│   ├── ServerAccess.ipynb
│   ├── ServerAccess.py
│   └── TileCoding.py
├── BairdExample/
│   ├── BairdCounterExample.ipynb
│   └── BairdCounterExample.py
├── BlackJack/
│   ├── blackjack_mc.ipynb
│   ├── blackjack_mc.py
│   ├── blackjack_solution.ipynb
│   ├── blackjack_solution.py
│   ├── blackjack_test.ipynb
│   └── policy
├── CliffWalking/
│   ├── cliffWalking.ipynb
│   └── cliffWalking.py
├── DynaMaze/
│   ├── DynaMaze.ipynb
│   ├── DynaMaze.py
│   ├── DynaQ+.py
│   ├── PrioritySweeping.ipynb
│   └── PrioritySweeping.py
├── GridWorld/
│   ├── GridBoard-Q.ipynb
│   ├── GridWorld.ipynb
│   ├── gridWorld.py
│   └── gridWorld_Q.py
├── LICENSE
├── MountainCar/
│   ├── MountainCar.ipynb
│   ├── MountainCar.py
│   └── TileCoding.py
├── MountainCar(Lambda)/
│   ├── MountainCar(Lambda).ipynb
│   ├── MountainCar.py
│   └── TileCoding.py
├── Multi-ArmBandit/
│   ├── Bandit.ipynb
│   └── bandit.py
├── README.md
├── RandomWalk/
│   ├── RandomWalk(n-step).ipynb
│   └── RandomWalk(n-step).py
├── RandomWalk(General)/
│   ├── RandomWalk.ipynb
│   └── RandomWalk.py
├── RandomWalk(Lambda)/
│   ├── TD(Lambda).ipynb
│   └── TD_Lambda.py
├── ShortCorridor/
│   ├── ShortCorridor.ipynb
│   └── ShortCorridor.py
├── TicTacToe/
│   ├── policy_p1
│   ├── policy_p2
│   ├── tic-tac-toe.ipynb
│   └── ticTacToe.py
├── TileCoding/
│   ├── TileCoding.ipynb
│   └── tile_coding.py
└── WindyGridWorld/
    ├── Windy_GW.ipynb
    └── windyGridWorld.py
Download .txt
SYMBOL INDEX (266 symbols across 23 files)

FILE: AccessControl/ServerAccess.py
  class ValueFunction (line 8) | class ValueFunction:
    method __init__ (line 10) | def __init__(self, alpha=0.01, numOfTilings=8, maxSize=2048):
    method getActiveTiles (line 27) | def getActiveTiles(self, n_server, priority, action):
    method value (line 34) | def value(self, state, action):
    method update (line 40) | def update(self, state, action, delta):
    method stateValue (line 48) | def stateValue(self, state):
  class ServerAcess (line 56) | class ServerAcess:
    method __init__ (line 57) | def __init__(self, exp_rate=0.3, lr=0.1, beta=0.01):
    method numFreeServers (line 70) | def numFreeServers(self):
    method chooseAction (line 81) | def chooseAction(self, valueFunc):
    method nxtState (line 95) | def nxtState(self, action):
    method giveReward (line 104) | def giveReward(self, action):
    method run (line 111) | def run(self, valueFunc, steps=1000, inner_steps=100, debug=False):

FILE: AccessControl/TileCoding.py
  class IHT (line 31) | class IHT:
    method __init__ (line 33) | def __init__(self, sizeval):
    method __str__ (line 38) | def __str__(self):
    method count (line 45) | def count (self):
    method fullp (line 48) | def fullp (self):
    method getindex (line 51) | def getindex (self, obj, readonly=False):
  function hashcoords (line 65) | def hashcoords(coordinates, m, readonly=False):
  function tiles (line 73) | def tiles(ihtORsize, numtilings, floats, ints=[], readonly=False):
  function tileswrap (line 88) | def tileswrap (ihtORsize, numtilings, floats, wrapwidths, ints=[], reado...

FILE: BairdExample/BairdCounterExample.py
  class Baird (line 7) | class Baird:
    method __init__ (line 9) | def __init__(self, gamma=0.99, alpha=0.01):
    method chooseAction (line 28) | def chooseAction(self):
    method takeAction (line 35) | def takeAction(self, action):
    method value (line 42) | def value(self, state):
    method run_semi_gradient_TD (line 46) | def run_semi_gradient_TD(self, rounds=100, sarsa=False):
    method run_TDC (line 71) | def run_TDC(self, beta=0.01, rounds=100):

FILE: BlackJack/blackjack_mc.py
  class BlackJackMC (line 6) | class BlackJackMC(object):
    method __init__ (line 8) | def __init__(self):
    method giveCard (line 16) | def giveCard():
    method dealerPolicy (line 21) | def dealerPolicy(self, current_value, usable_ace, is_end):
    method playerPolicy (line 41) | def playerPolicy(self, current_value, usable_ace, is_end):
    method _giveCredit (line 60) | def _giveCredit(self, player_value, dealer_value, is_end=True):
    method play (line 84) | def play(self, rounds=1000):

FILE: BlackJack/blackjack_solution.py
  class BlackJackSolution (line 5) | class BlackJackSolution:
    method __init__ (line 7) | def __init__(self, lr=0.1, exp_rate=0.3):
    method giveCard (line 29) | def giveCard():
    method dealerPolicy (line 34) | def dealerPolicy(self, current_value, usable_ace, is_end):
    method chooseAction (line 53) | def chooseAction(self):
    method playerNxtState (line 75) | def playerNxtState(self, action):
    method winner (line 106) | def winner(self, player_value, dealer_value):
    method _giveCredit (line 128) | def _giveCredit(self, player_value, dealer_value):
    method reset (line 136) | def reset(self):
    method deal2cards (line 141) | def deal2cards(self, show=False):
    method play (line 157) | def play(self, rounds=1000):
    method savePolicy (line 197) | def savePolicy(self, file="policy"):
    method loadPolicy (line 202) | def loadPolicy(self, file="policy"):
    method playWithDealer (line 208) | def playWithDealer(self, rounds=1000):

FILE: CliffWalking/cliffWalking.py
  class Cliff (line 10) | class Cliff:
    method __init__ (line 12) | def __init__(self):
    method nxtPosition (line 19) | def nxtPosition(self, action):
    method giveReward (line 42) | def giveReward(self):
    method show (line 50) | def show(self):
  class Agent (line 68) | class Agent:
    method __init__ (line 69) | def __init__(self, exp_rate=0.3, lr=0.1, sarsa=True):
    method chooseAction (line 84) | def chooseAction(self):
    method reset (line 101) | def reset(self):
    method play (line 106) | def play(self, rounds=10):
  function showRoute (line 145) | def showRoute(states):

FILE: DynaMaze/DynaMaze.py
  class Maze (line 12) | class Maze:
    method __init__ (line 14) | def __init__(self):
    method nxtPosition (line 27) | def nxtPosition(self, action):
    method giveReward (line 43) | def giveReward(self):
    method showMaze (line 50) | def showMaze(self):
  class DynaAgent (line 67) | class DynaAgent:
    method __init__ (line 69) | def __init__(self, exp_rate=0.3, lr=0.1, n_steps=5, episodes=1):
    method chooseAction (line 90) | def chooseAction(self):
    method reset (line 111) | def reset(self):
    method play (line 116) | def play(self):

FILE: DynaMaze/DynaQ+.py
  class Maze (line 11) | class Maze:
    method __init__ (line 13) | def __init__(self):
    method nxtPosition (line 26) | def nxtPosition(self, action):
    method giveReward (line 42) | def giveReward(self):
    method showMaze (line 49) | def showMaze(self):
  class DynaAgentPlus (line 66) | class DynaAgentPlus:
    method __init__ (line 68) | def __init__(self, exp_rate=0.3, lr=0.1, n_steps=5, episodes=1, timeWe...
    method chooseAction (line 91) | def chooseAction(self):
    method reset (line 112) | def reset(self):
    method updateModel (line 118) | def updateModel(self, state, nxtState, action, reward):
    method play (line 129) | def play(self):

FILE: DynaMaze/PrioritySweeping.py
  class Maze (line 12) | class Maze:
    method __init__ (line 14) | def __init__(self):
    method nxtPosition (line 27) | def nxtPosition(self, action):
    method giveReward (line 43) | def giveReward(self):
    method showMaze (line 50) | def showMaze(self):
  class PriorityAgent (line 67) | class PriorityAgent:
    method __init__ (line 69) | def __init__(self, exp_rate=0.3, lr=0.1, n_steps=5, episodes=1, theta=0):
    method chooseAction (line 95) | def chooseAction(self):
    method reset (line 116) | def reset(self):
    method play (line 121) | def play(self):

FILE: GridWorld/gridWorld.py
  class State (line 12) | class State:
    method __init__ (line 13) | def __init__(self, state=START):
    method giveReward (line 20) | def giveReward(self):
    method isEndFunc (line 28) | def isEndFunc(self):
    method nxtPosition (line 32) | def nxtPosition(self, action):
    method showBoard (line 57) | def showBoard(self):
  class Agent (line 76) | class Agent:
    method __init__ (line 78) | def __init__(self):
    method chooseAction (line 91) | def chooseAction(self):
    method takeAction (line 108) | def takeAction(self, action):
    method reset (line 112) | def reset(self):
    method play (line 116) | def play(self, rounds=10):
    method showValues (line 143) | def showValues(self):

FILE: GridWorld/gridWorld_Q.py
  class State (line 11) | class State:
    method __init__ (line 12) | def __init__(self, state=START):
    method giveReward (line 19) | def giveReward(self):
    method isEndFunc (line 27) | def isEndFunc(self):
    method _chooseActionProb (line 31) | def _chooseActionProb(self, action):
    method nxtPosition (line 41) | def nxtPosition(self, action):
    method showBoard (line 73) | def showBoard(self):
  class Agent (line 90) | class Agent:
    method __init__ (line 92) | def __init__(self):
    method chooseAction (line 109) | def chooseAction(self):
    method takeAction (line 127) | def takeAction(self, action):
    method reset (line 132) | def reset(self):
    method play (line 137) | def play(self, rounds=10):

FILE: MountainCar(Lambda)/MountainCar.py
  class ValueFunction (line 11) | class ValueFunction:
    method __init__ (line 13) | def __init__(self, stepSize=0.3, numOfTilings=8, maxSize=2048, lam=0.9...
    method getActiveTiles (line 37) | def getActiveTiles(self, position, velocity, action):
    method value (line 46) | def value(self, position, velocity, action):
    method update (line 53) | def update(self, position, velocity, action, target):
    method costToGo (line 72) | def costToGo(self, position, velocity):
  class MountainCar (line 79) | class MountainCar:
    method __init__ (line 81) | def __init__(self, exp_rate=0.1, debug=True):
    method reset (line 88) | def reset(self):
    method takeAction (line 93) | def takeAction(self, action):
    method chooseAction (line 108) | def chooseAction(self, valueFunc, state):
    method giveReward (line 122) | def giveReward(self, state):
    method play (line 130) | def play(self, valueFunction, rounds=50):

FILE: MountainCar(Lambda)/TileCoding.py
  class IHT (line 31) | class IHT:
    method __init__ (line 33) | def __init__(self, sizeval):
    method __str__ (line 38) | def __str__(self):
    method count (line 45) | def count (self):
    method fullp (line 48) | def fullp (self):
    method getindex (line 51) | def getindex (self, obj, readonly=False):
  function hashcoords (line 65) | def hashcoords(coordinates, m, readonly=False):
  function tiles (line 73) | def tiles(ihtORsize, numtilings, floats, ints=[], readonly=False):
  function tileswrap (line 88) | def tileswrap (ihtORsize, numtilings, floats, wrapwidths, ints=[], reado...

FILE: MountainCar/MountainCar.py
  class ValueFunction (line 11) | class ValueFunction:
    method __init__ (line 13) | def __init__(self, stepSize, numOfTilings=8, maxSize=2048):
    method getActiveTiles (line 30) | def getActiveTiles(self, position, velocity, action):
    method value (line 39) | def value(self, position, velocity, action):
    method update (line 46) | def update(self, position, velocity, action, target):
    method costToGo (line 54) | def costToGo(self, position, velocity):
  class MountainCar (line 61) | class MountainCar:
    method __init__ (line 63) | def __init__(self, n=1, exp_rate=0.1, gamma=1, debug=True):
    method reset (line 72) | def reset(self):
    method takeAction (line 77) | def takeAction(self, action):
    method chooseAction (line 92) | def chooseAction(self, valueFunc):
    method giveReward (line 106) | def giveReward(self):
    method play (line 113) | def play(self, valueFunction, rounds=1):

FILE: MountainCar/TileCoding.py
  class IHT (line 31) | class IHT:
    method __init__ (line 33) | def __init__(self, sizeval):
    method __str__ (line 38) | def __str__(self):
    method count (line 45) | def count (self):
    method fullp (line 48) | def fullp (self):
    method getindex (line 51) | def getindex (self, obj, readonly=False):
  function hashcoords (line 65) | def hashcoords(coordinates, m, readonly=False):
  function tiles (line 73) | def tiles(ihtORsize, numtilings, floats, ints=[], readonly=False):
  function tileswrap (line 88) | def tileswrap (ihtORsize, numtilings, floats, wrapwidths, ints=[], reado...

FILE: Multi-ArmBandit/bandit.py
  class Bandit (line 5) | class Bandit:
    method __init__ (line 6) | def __init__(self, k=10, exp_rate=.3, lr=0.1, ucb=False, seed=None, c=2):
    method chooseAction (line 26) | def chooseAction(self):
    method takeAction (line 43) | def takeAction(self, action):
    method play (line 55) | def play(self, n):

FILE: RandomWalk(General)/RandomWalk.py
  class LinearValueFunction (line 12) | class LinearValueFunction:
    method __init__ (line 14) | def __init__(self, order, method="poly"):
    method value (line 21) | def value(self, state):
    method update (line 26) | def update(self, delta, state):
  class AggValueFunction (line 32) | class AggValueFunction:
    method __init__ (line 34) | def __init__(self, num_groups=10):
    method value (line 39) | def value(self, state):
    method update (line 49) | def update(self, delta, state):
  class RandomWalk (line 55) | class RandomWalk:
    method __init__ (line 57) | def __init__(self, step=1, lr=2e-5, gamma=1, debug=True):
    method chooseAction (line 66) | def chooseAction(self):
    method takeAction (line 70) | def takeAction(self, action):
    method giveReward (line 88) | def giveReward(self):
    method reset (line 95) | def reset(self):
    method play (line 99) | def play(self, valueFunction, rounds=1e5):
  function plot_fig (line 146) | def plot_fig(func):

FILE: RandomWalk(Lambda)/TD_Lambda.py
  class ValueFunction (line 11) | class ValueFunction:
    method __init__ (line 12) | def __init__(self, alpha=0.1):
    method value (line 16) | def value(self, state):
    method learn (line 20) | def learn(self, state, delta):
  class RandomWalk (line 24) | class RandomWalk:
    method __init__ (line 26) | def __init__(self, start=START, end=False, lmbda=0.4, debug=False):
    method chooseAction (line 36) | def chooseAction(self):
    method takeAction (line 40) | def takeAction(self, action):
    method giveReward (line 53) | def giveReward(self, state):
    method reset (line 61) | def reset(self):
    method gt2tn (line 66) | def gt2tn(self, valueFunc, start, end):
    method play (line 73) | def play(self, valueFunc, rounds=100):
  class ValueFunctionTD (line 111) | class ValueFunctionTD:
    method __init__ (line 112) | def __init__(self, alpha=0.1, gamma=0.9, lmbda=0.8):
    method value (line 119) | def value(self, state):
    method updateZ (line 123) | def updateZ(self, state):
    method learn (line 128) | def learn(self, state, nxtState, reward):
  class RWTD (line 134) | class RWTD:
    method __init__ (line 136) | def __init__(self, start=START, end=False, debug=False):
    method chooseAction (line 143) | def chooseAction(self):
    method takeAction (line 147) | def takeAction(self, action):
    method giveReward (line 159) | def giveReward(self, state):
    method reset (line 167) | def reset(self):
    method play (line 172) | def play(self, valueFunc, rounds=100):

FILE: RandomWalk/RandomWalk(n-step).py
  class RandomWalk (line 10) | class RandomWalk:
    method __init__ (line 12) | def __init__(self, n, start=START, end=False, lr=0.1, gamma=1, debug=F...
    method chooseAction (line 34) | def chooseAction(self):
    method takeAction (line 38) | def takeAction(self, action):
    method giveReward (line 51) | def giveReward(self):
    method reset (line 59) | def reset(self):
    method play (line 63) | def play(self, rounds=100):

FILE: ShortCorridor/ShortCorridor.py
  class ShortCorridor (line 4) | class ShortCorridor:
    method __init__ (line 5) | def __init__(self, alpha=0.2, gamma=0.8):
    method softmax (line 13) | def softmax(self, vector):
    method chooseAction (line 16) | def chooseAction(self):
    method takeAction (line 30) | def takeAction(self, action):
    method giveReward (line 41) | def giveReward(self):
    method reset (line 46) | def reset(self):
    method run (line 49) | def run(self, rounds=100):

FILE: TicTacToe/ticTacToe.py
  class State (line 8) | class State:
    method __init__ (line 9) | def __init__(self, p1, p2):
    method getHash (line 19) | def getHash(self):
    method winner (line 23) | def winner(self):
    method availablePositions (line 60) | def availablePositions(self):
    method updateState (line 68) | def updateState(self, position):
    method giveReward (line 74) | def giveReward(self):
    method reset (line 88) | def reset(self):
    method play (line 94) | def play(self, rounds=100):
    method play2 (line 137) | def play2(self):
    method showBoard (line 171) | def showBoard(self):
  class Player (line 188) | class Player:
    method __init__ (line 189) | def __init__(self, name, exp_rate=0.3):
    method getHash (line 197) | def getHash(self, board):
    method chooseAction (line 201) | def chooseAction(self, positions, current_board, symbol):
    method addState (line 221) | def addState(self, state):
    method feedReward (line 225) | def feedReward(self, reward):
    method reset (line 232) | def reset(self):
    method savePolicy (line 235) | def savePolicy(self):
    method loadPolicy (line 240) | def loadPolicy(self, file):
  class HumanPlayer (line 246) | class HumanPlayer:
    method __init__ (line 247) | def __init__(self, name):
    method chooseAction (line 250) | def chooseAction(self, positions):
    method addState (line 259) | def addState(self, state):
    method feedReward (line 263) | def feedReward(self, reward):
    method reset (line 266) | def reset(self):

FILE: TileCoding/tile_coding.py
  function create_tiling (line 4) | def create_tiling(feat_range, bins, offset):
  function create_tilings (line 15) | def create_tilings(feature_ranges, number_tilings, bins, offsets):
  function get_tile_coding (line 39) | def get_tile_coding(feature, tilings):
  class QValueFunction (line 60) | class QValueFunction:
    method __init__ (line 62) | def __init__(self, tilings, actions, lr):
    method value (line 71) | def value(self, state, action):
    method update (line 81) | def update(self, state, action, target):

FILE: WindyGridWorld/windyGridWorld.py
  class State (line 4) | class State:
    method __init__ (line 5) | def __init__(self, state=(3, 0), rows=7, cols=10):
    method giveReward (line 14) | def giveReward(self):
    method nxtPosition (line 20) | def nxtPosition(self, action):
    method showBoard (line 56) | def showBoard(self):
  class Agent (line 76) | class Agent:
    method __init__ (line 78) | def __init__(self, lr=0.2, exp_rate=0.3):
    method chooseAction (line 98) | def chooseAction(self):
    method takeAction (line 116) | def takeAction(self, action):
    method reset (line 121) | def reset(self):
    method play (line 125) | def play(self, rounds=10):
Condensed preview — 49 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,010K chars).
[
  {
    "path": ".gitignore",
    "chars": 67,
    "preview": ".idea/*\n.idea\n*/.ipynb_checkpoints\n.ipynb_checkpoints\n*/__pycache__"
  },
  {
    "path": "AccessControl/ServerAccess.ipynb",
    "chars": 145583,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Access-Control Queuing Task\\n\",\n   "
  },
  {
    "path": "AccessControl/ServerAccess.py",
    "chars": 5445,
    "preview": "import numpy as np\nimport matplotlib.pyplot as plt\nfrom TileCoding import *\n\nACTIONS = [0, 1]\n\n\nclass ValueFunction:\n\n  "
  },
  {
    "path": "AccessControl/TileCoding.py",
    "chars": 3940,
    "preview": "\"\"\"\nTile Coding Software version 3.0beta\nby Rich Sutton\nbased on a program created by Steph Schaeffer and others\nExterna"
  },
  {
    "path": "BairdExample/BairdCounterExample.ipynb",
    "chars": 96600,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Baird Counter Example\\n\",\n    \"---\\"
  },
  {
    "path": "BairdExample/BairdCounterExample.py",
    "chars": 3827,
    "preview": "import numpy as np\nimport matplotlib.pyplot as plt\n\nSTATES = range(7)\n\n\nclass Baird:\n\n    def __init__(self, gamma=0.99,"
  },
  {
    "path": "BlackJack/blackjack_mc.ipynb",
    "chars": 239408,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### MC Simulation BlackJack State-V"
  },
  {
    "path": "BlackJack/blackjack_mc.py",
    "chars": 5532,
    "preview": "import numpy as np\nimport matplotlib.pyplot as plt\nfrom mpl_toolkits.mplot3d import Axes3D\n\n\nclass BlackJackMC(object):\n"
  },
  {
    "path": "BlackJack/blackjack_solution.ipynb",
    "chars": 62842,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 1,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n "
  },
  {
    "path": "BlackJack/blackjack_solution.py",
    "chars": 8938,
    "preview": "import numpy as np\nimport pickle\n\n\nclass BlackJackSolution:\n\n    def __init__(self, lr=0.1, exp_rate=0.3):\n        self."
  },
  {
    "path": "BlackJack/blackjack_test.ipynb",
    "chars": 748344,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 3,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n "
  },
  {
    "path": "CliffWalking/cliffWalking.ipynb",
    "chars": 82464,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Cliff Walking\\n\",\n    \"---\\n\",\n    "
  },
  {
    "path": "CliffWalking/cliffWalking.py",
    "chars": 6392,
    "preview": "import numpy as np\n\n\nROWS = 4\nCOLS = 12\nS = (3, 0)\nG = (3, 11)\n\n\nclass Cliff:\n\n    def __init__(self):\n        self.end "
  },
  {
    "path": "DynaMaze/DynaMaze.ipynb",
    "chars": 58735,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Rules\\n\",\n    \"---\\n\",\n    \"<img"
  },
  {
    "path": "DynaMaze/DynaMaze.py",
    "chars": 5716,
    "preview": "import numpy as np\nimport matplotlib.pyplot as plt\n\nROWS = 6\nCOLS = 9\nS = (2, 0)\nG = (0, 8)\nBLOCKS = [(1, 2), (2, 2), (3"
  },
  {
    "path": "DynaMaze/DynaQ+.py",
    "chars": 5601,
    "preview": "import numpy as np\n\nROWS = 6\nCOLS = 9\nS = (2, 0)\nG = (0, 8)\nBLOCKS = [(1, 2), (2, 2), (3, 2), (0, 7), (1, 7), (2, 7), (4"
  },
  {
    "path": "DynaMaze/PrioritySweeping.ipynb",
    "chars": 37858,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Priority Sweeping\\n\",\n    \"---\\n"
  },
  {
    "path": "DynaMaze/PrioritySweeping.py",
    "chars": 5931,
    "preview": "from queue import PriorityQueue\nimport numpy as np\n\nROWS = 6\nCOLS = 9\nS = (2, 0)\nG = (0, 8)\nBLOCKS = [(1, 2), (2, 2), (3"
  },
  {
    "path": "GridWorld/GridBoard-Q.ipynb",
    "chars": 69074,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Grid Board Q-Learning\\n\",\n    \"---\\"
  },
  {
    "path": "GridWorld/GridWorld.ipynb",
    "chars": 125197,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Grid Board\\n\",\n    \"---\\n\",\n    \"<i"
  },
  {
    "path": "GridWorld/gridWorld.py",
    "chars": 4940,
    "preview": "import numpy as np\n\n# global variables\nBOARD_ROWS = 3\nBOARD_COLS = 4\nWIN_STATE = (0, 3)\nLOSE_STATE = (1, 3)\nSTART = (2, "
  },
  {
    "path": "GridWorld/gridWorld_Q.py",
    "chars": 5743,
    "preview": "import numpy as np\n\nBOARD_ROWS = 3\nBOARD_COLS = 4\nWIN_STATE = (0, 3)\nLOSE_STATE = (1, 3)\nSTART = (2, 0)\nDETERMINISTIC = "
  },
  {
    "path": "LICENSE",
    "chars": 1069,
    "preview": "MIT License\n\nCopyright (c) 2019 Jeremy Zhang\n\nPermission is hereby granted, free of charge, to any person obtaining a co"
  },
  {
    "path": "MountainCar/MountainCar.ipynb",
    "chars": 346724,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# Mountain Car with gradient SARSA\\"
  },
  {
    "path": "MountainCar/MountainCar.py",
    "chars": 6513,
    "preview": "import numpy as np\nimport matplotlib.pyplot as plt\nfrom TileCoding import *\nfrom mpl_toolkits.mplot3d import Axes3D\n\nVEL"
  },
  {
    "path": "MountainCar/TileCoding.py",
    "chars": 3940,
    "preview": "\"\"\"\nTile Coding Software version 3.0beta\nby Rich Sutton\nbased on a program created by Steph Schaeffer and others\nExterna"
  },
  {
    "path": "MountainCar(Lambda)/MountainCar(Lambda).ipynb",
    "chars": 91812,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Sarsa(λ)\\n\",\n    \"---\\n\",\n    \"Very"
  },
  {
    "path": "MountainCar(Lambda)/MountainCar.py",
    "chars": 6792,
    "preview": "import numpy as np\nimport matplotlib.pyplot as plt\nfrom TileCoding import *\n\n\nVELOCITY_BOUND = [-0.07, 0.07]\nPOSITION_BO"
  },
  {
    "path": "MountainCar(Lambda)/TileCoding.py",
    "chars": 3940,
    "preview": "\"\"\"\nTile Coding Software version 3.0beta\nby Rich Sutton\nbased on a program created by Steph Schaeffer and others\nExterna"
  },
  {
    "path": "Multi-ArmBandit/Bandit.ipynb",
    "chars": 98521,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"### Multi-Arm Bandit\\n\",\n    \"---\\n"
  },
  {
    "path": "Multi-ArmBandit/bandit.py",
    "chars": 3106,
    "preview": "import numpy as np\nimport matplotlib.pyplot as plt\n\n\nclass Bandit:\n    def __init__(self, k=10, exp_rate=.3, lr=0.1, ucb"
  },
  {
    "path": "README.md",
    "chars": 3047,
    "preview": "# Reinforcement Learning Algorithms Implementation\n---\nReinforcement Learning Examples\n\nIn each file, there is a jupyter"
  },
  {
    "path": "RandomWalk/RandomWalk(n-step).ipynb",
    "chars": 93487,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Randow Walk\\n\",\n    \"---\\n\",\n    \"#"
  },
  {
    "path": "RandomWalk/RandomWalk(n-step).py",
    "chars": 4344,
    "preview": "import numpy as np\n\n# 19 states (not including the ending state)\nNUM_STATES = 19\nSTART = 9\nEND_0 = 0\nEND_1 = 20\n\n\nclass "
  },
  {
    "path": "RandomWalk(General)/RandomWalk.ipynb",
    "chars": 89761,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"1000 Steps Random Walk\\n\",\n    \"---"
  },
  {
    "path": "RandomWalk(General)/RandomWalk.py",
    "chars": 5439,
    "preview": "import numpy as np\nimport matplotlib.pyplot as plt\n\nNUM_STATES = 1000\nSTART = 500\nEND_0 = 0\nEND_1 = 1001\n\nTRUE_VALUES = "
  },
  {
    "path": "RandomWalk(Lambda)/TD(Lambda).ipynb",
    "chars": 114182,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Offline Lambda\\n\",\n    \"---\\n\",\n   "
  },
  {
    "path": "RandomWalk(Lambda)/TD_Lambda.py",
    "chars": 6899,
    "preview": "import numpy as np\nimport matplotlib.pyplot as plt\n\n# 19 states (not including the ending state)\nNUM_STATES = 19\nSTART ="
  },
  {
    "path": "ShortCorridor/ShortCorridor.ipynb",
    "chars": 7739,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Short Corridor with Switched Action"
  },
  {
    "path": "ShortCorridor/ShortCorridor.py",
    "chars": 2928,
    "preview": "import numpy as np\n\n\nclass ShortCorridor:\n    def __init__(self, alpha=0.2, gamma=0.8):\n        self.actions = [\"left\", "
  },
  {
    "path": "TicTacToe/tic-tac-toe.ipynb",
    "chars": 18369,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Tic Tac Toe\\n\",\n    \"---\\n\",\n    \"T"
  },
  {
    "path": "TicTacToe/ticTacToe.py",
    "chars": 8853,
    "preview": "import numpy as np\nimport pickle\n\nBOARD_ROWS = 3\nBOARD_COLS = 3\n\n\nclass State:\n    def __init__(self, p1, p2):\n        s"
  },
  {
    "path": "TileCoding/TileCoding.ipynb",
    "chars": 192597,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Tile Coding\\n\",\n    \"\\n\",\n    \"-"
  },
  {
    "path": "TileCoding/tile_coding.py",
    "chars": 3407,
    "preview": "import numpy as np\n\n\ndef create_tiling(feat_range, bins, offset):\n    \"\"\"\n    Create 1 tiling spec of 1 dimension(featur"
  },
  {
    "path": "WindyGridWorld/Windy_GW.ipynb",
    "chars": 13289,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Windy Grid World\\n\",\n    \"---\\n\",\n "
  },
  {
    "path": "WindyGridWorld/windyGridWorld.py",
    "chars": 5389,
    "preview": "import numpy as np\n\n\nclass State:\n    def __init__(self, state=(3, 0), rows=7, cols=10):\n        self.END_STATE = (3, 7)"
  }
]

// ... and 3 more files (download for full content)

About this extraction

This page contains the full source code of the MJeremy2017/reinforcement-learning-implementation GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 49 files (2.7 MB), approximately 717.3k tokens, and a symbol index with 266 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!