diff --git a/projects/3-mazes/Chappidi.ipynb b/projects/3-mazes/Chappidi.ipynb new file mode 100644 index 0000000..680de74 --- /dev/null +++ b/projects/3-mazes/Chappidi.ipynb @@ -0,0 +1,662 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First, we load up some useful libraries for visualization and data structures." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "\n", + "import matplotlib\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "import matplotlib.patches as patches\n", + "import matplotlib.axes as axes\n", + "import copy\n", + "import random\n", + "from queue import PriorityQueue" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next we need a Maze class for pathfinding. It will help to have read the RedBlobGames [A\\* tutorial](http://www.redblobgames.com/pathfinding/a-star/introduction.html) before continuing.\n", + "\n", + "These Mazes are defined in ASCII diagrams and can have walls (\"#\"), empty spaces (\".\"), switches (numbers), and doors (letters; closed are uppercase). The \"0\" switch toggles the open status of all the \"a\" doors, \"1\" goes to the \"b\" doors, etc. Mazes can also contain pits: \"?\" pits have a 30% chance of killing the player and \"!\" pits have a 60% chance. Every maze has one player start location \"@\" and one goal square \"X\". Walls and closed doors block movement." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[(1, 0), (0, -1), (0, 1), 'switch']\n" + ] + }, + { + "data": { + "image/png": "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\nmSX9PyB+ZXycXJ7PAAAAAElFTkSuQmCC\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "class TreeNode:\n", + " \n", + " def __init__(self, val):\n", + " self.value = val\n", + " self.children = []\n", + " self.parent = None\n", + " \n", + " def add_child(self, tn):\n", + " self.children.append(tn)\n", + " tn.parent = self\n", + "class Maze:\n", + " SwitchMap = {\"0\":\"a\", \"1\":\"b\", \"2\":\"c\", \"3\":\"d\", \"4\":\"e\", \"5\":\"f\", \"6\":\"g\", \"7\":\"h\", \"8\":\"i\", \"9\":\"j\"}\n", + " Colors = {\"a\":\"coral\",\"b\":\"tan\",\"c\":\"palegreen\",\"d\":\"blue\",\"e\":\"cyan\",\"f\":\"magenta\",\"g\":\"yellow\",\"h\":\"olive\",\"i\":\"purple\",\"j\":\"darkgreen\",\n", + " \"0\":\"coral\",\"1\":\"tan\",\"2\":\"palegreen\",\"3\":\"blue\",\"4\":\"cyan\",\"5\":\"magenta\",\"6\":\"yellow\",\"7\":\"olive\",\"8\":\"purple\",\"9\":\"darkgreen\",\n", + " \"?\":\"orange\",\n", + " \"!\":\"red\",\n", + " \"x\":\"green\",\"@\":\"gray\",\n", + " \"#\":\"sienna\",\".\":\"white\"}\n", + " \n", + " def __init__(self,rows):\n", + " self.grid = [list(r) for r in rows]\n", + " self.grid.reverse()\n", + " height = len(self.grid)\n", + " width = len(self.grid[0])\n", + " self.exit_pos = None\n", + " self.player_pos = None\n", + " self.player_alive = True\n", + " self.cost = 0\n", + " self.path = None\n", + " for y in range(0,height):\n", + " assert len(self.grid[y]) == width, \"All rows must be equal length!\"\n", + " for x in range(0,width):\n", + " c = self.grid[y][x]\n", + " assert c == \"#\" or c == \".\" or c == \"!\" or c == \"?\" or c == \"@\" or c.isalnum()\n", + " if c.lower() == \"x\":\n", + " assert self.exit_pos == None\n", + " self.exit_pos = (x,y)\n", + " if c == \"@\":\n", + " assert self.player_pos == None\n", + " self.player_pos = (x,y)\n", + " self.grid[y][x] = \".\"\n", + " \n", + " #added \n", + " def __eq__(self, other):\n", + " return self.grid == other.grid and self.player_pos == other.player_pos and self.player_alive == other.player_alive\n", + " def __neq__(self, other):\n", + " return not self == other\n", + " def __hash__(self):\n", + " return hash(str(self.grid)) % 100000 + hash(self.player_pos) % 100000 + hash(self.player_alive) % 100000\n", + " def __lt__(self, other):\n", + " if self == other: return False\n", + " return id(self) < id(other)\n", + " #end of added\n", + " \n", + " def clone(self):\n", + " return copy.deepcopy(self)\n", + " \n", + " def toggle_cell(self,switchnum,c):\n", + " if c.isalpha() and Maze.SwitchMap[switchnum] == c.lower():\n", + " if c.islower():\n", + " return c.upper()\n", + " else:\n", + " return c.lower()\n", + " return c\n", + " \n", + " def toggle(self):\n", + " assert self.player_alive\n", + " height = len(self.grid)\n", + " width = len(self.grid[0])\n", + " (px,py) = self.player_pos\n", + " switchnum = self.grid[py][px]\n", + " assert switchnum.isnumeric()\n", + " for y in range(0,height):\n", + " for x in range(0,width):\n", + " self.grid[y][x] = self.toggle_cell(switchnum,self.grid[y][x])\n", + " \n", + " def is_free(self,x,y):\n", + " if y < 0 or y >= len(self.grid):\n", + " return False\n", + " if x < 0 or x >= len(self.grid[0]):\n", + " return False\n", + " cell = self.grid[y][x]\n", + " return (\n", + " cell == \".\" or cell == \"X\" or \n", + " cell == \"?\" or cell == \"!\" or \n", + " (cell.isalpha() and cell.islower()) or cell.isnumeric()\n", + " )\n", + " \n", + " def move_player(self,dx,dy):\n", + " assert self.player_alive\n", + " assert abs(dx)+abs(dy) == 1\n", + " (x,y) = self.player_pos\n", + " (newx,newy) = (x+dx,y+dy)\n", + " assert self.is_free(newx,newy)\n", + " self.player_pos = (x+dx,y+dy)\n", + " cell = self.grid[y+dy][x+dx]\n", + " if cell == \"?\" and random.random() < 0.3:\n", + " self.player_alive = False\n", + " if cell == \"!\" and random.random() < 0.6:\n", + " self.player_alive = False\n", + " \n", + " def available_moves(self):\n", + " if not self.player_alive:\n", + " return []\n", + " (x,y) = self.player_pos\n", + " can_switch = self.grid[y][x].isnumeric()\n", + " return [(dx,dy) for (dx,dy) in [(-1,0),(1,0),(0,-1),(0,1)] if self.is_free(x+dx,y+dy)] + (\n", + " [\"switch\"] if can_switch else []\n", + " )\n", + " \n", + " def is_at_exit(self):\n", + " return self.player_alive and self.player_pos == self.exit_pos\n", + " \n", + " \n", + " def draw(self):\n", + " fig1 = plt.figure()\n", + " ax1 = fig1.add_subplot(1,1,1, aspect='equal')\n", + " ax1.set_axis_bgcolor('sienna')\n", + " height = len(self.grid)\n", + " width = len(self.grid[0])\n", + " ax1.set_xlim([0,width])\n", + " ax1.set_ylim([0,height])\n", + " for y in range(0,height):\n", + " for x in range(0,width):\n", + " cell = self.grid[y][x]\n", + " if cell == \"#\": continue\n", + " is_door = cell.isalpha() and cell.lower() != \"x\"\n", + " is_pit = cell == \"?\" or cell == \"!\"\n", + " is_open = is_door and cell.islower()\n", + " is_switch = cell.isnumeric()\n", + " ax1.add_patch(\n", + " patches.Rectangle((x, y),\n", + " 1,1,\n", + " fill=True,\n", + " facecolor=Maze.Colors[cell.lower()],\n", + " edgecolor=\"black\",\n", + " hatch=\"/\" if is_switch else (\"-\" if (is_door and not is_open) else None),\n", + " label=cell)\n", + " )\n", + " ax1.add_patch(\n", + " patches.Rectangle(self.player_pos,\n", + " 1,1,\n", + " fill=True,\n", + " hatch=\"x\" if not self.player_alive else None,\n", + " facecolor=Maze.Colors[\"@\"] if self.player_alive else \"black\",\n", + " edgecolor=Maze.Colors[\"@\"] if self.player_alive else \"white\")\n", + " )\n", + " plt.show(fig1)\n", + "\n", + "sample=Maze([\n", + " \"##X#\",\n", + " \"#.A#\",\n", + " \"#0?#\",\n", + " \"a@##\"\n", + " ])\n", + "sample.move_player(0,1)\n", + "print(sample.available_moves())\n", + "sample.move_player(1,0)\n", + "sample.draw()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Assignment 1\n", + "\n", + "Write a function to solve pathfinding and switch-and-door puzzles with one of the heuristic search algorithms described during the lecture. Try it on the provided sample puzzles; if a puzzle gives your algorithm trouble, try to explain why that happens. Make sure the path you're getting is the actual shortest path!\n", + "\n", + "Try to get this assignment done by Friday; the other two may take a little longer but the sooner you attempt them the earlier you can get feedback!\n", + "\n", + "You may also try visualizing paths through the maze, implementing several different heuristic searches, comparing against aheuristic search, etc.\n", + "\n", + "Generating mazes automatically would also be a great exercise!" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def distance(x,y):\n", + " return abs(x[0]-y[0]) + abs(x[1] - y[1])\n", + "\n", + "def heuristic(maze):\n", + " \n", + " maze_queue = PriorityQueue()\n", + " init_maze = maze\n", + " maze_queue.put((0,init_maze, [], 0)) \n", + " goal = maze.exit_pos\n", + " go = maze.player_pos\n", + " searched_mazes = {} \n", + " \n", + " \n", + " while not maze_queue.empty():\n", + " (priority, current_maze, path, cost) = maze_queue.get()\n", + " if current_maze.is_at_exit():\n", + " return path\n", + " \n", + " for k in current_maze.available_moves():\n", + " copy_maze = current_maze.clone() \n", + " \n", + " if k is \"switch\":\n", + " copy_maze.toggle()\n", + " update_path = list(path) \n", + " update_path.append(\"switch\")\n", + " if copy_maze not in searched_mazes:\n", + " priority = cost + distance(copy_maze.player_pos, goal)\n", + " maze_queue.put((priority, copy_maze, update_path, cost))\n", + " searched_mazes[copy_maze] = 1\n", + " \n", + " \n", + " else: \n", + " copy_maze.move_player(k[0], k[1])\n", + " update_path = list(path)\n", + " update_path.append((copy_maze.player_pos[0], copy_maze.player_pos[1]))\n", + " if copy_maze not in searched_mazes:\n", + " searched_mazes[copy_maze] = 1\n", + " priority = cost + distance(copy_maze.player_pos, goal)\n", + " maze_queue.put((priority, copy_maze, update_path, cost + 1))\n", + " \n", + " \n", + " return []\n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAOIAAAEACAYAAACu66rqAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAADgdJREFUeJzt3V+MXHd5xvHvs3bi3fU2Cy12CpiYoMpKgoIcq00iTFqo\nAzUBBWGpgoAUOaroRWkdpTUQ5SbxRS9AQjRSK1UREAM1EGW7blIp0BiCQFA1dmI72cTr0sZJ7fyz\njQBbazvIjt9ezHHlrnc9Z9fnN3l3z/ORVjuzOvP7vWfGj8+Zc2beo4jAzN5YfW90AWbmIJql4CCa\nJeAgmiXgIJol4CCaJVAriJJulzRW/WwoXZRZ23QNoqR3A38G/D6wEviopHeVLsysTepsEa8EHo+I\n30TE68BPgHVlyzJrlzpBfAa4QdKbJQ0CNwHvKFuWWbss7LZAROyV9EVgGzAB7AJeL12YWZtopp81\nlfS3wIGI+MdJf/eHVs2mEBHqtkzXLSKApCURcVjSZcDHgeunWm7zuqtnVuEMbN1zkI9fdWmx8T1H\nrjnmwzoArB8dq7VcrSAC/yzpt4GTwF9ExNHZFmZm56oVxIj4w9KFmLXZnPlkzRVLFnuOFs0xH9Zh\nJmZ8sGbagaQo+R7RbC5aPzpW62DNnNkims1nDqJZAg6iWQIOolkCDqJZAg6iWQIOolkCDqJZAg6i\nWQIOolkCDqJZAg6iWQIOolkCDqJZAnUbDN8h6RlJT0vaIuni0oWZtUmdBsNvA/4KWBUR76Hzrf5P\nli7MrE3q9qxZACyWdBoYBF4uV5JZ+3TdIkbEy8CXgf3AS8CvI+IHpQsza5OuW0RJbwI+BiwHjgAj\nkj4VEd+evOzWPQf/7/YVSxZz5ZKhxgrd8G/jHD12qrHxpjLQ38+J114rOsfS4SG+tObyonN8/ofP\nc+jIRNE5Bgb6OXGi3HNVenwo81qMH55g7+FjM35cnV3TG4F9EfFLAEmjwHuBc4JYskfk0WOn4J5i\nwwNw4p7XaKqHz3Skru1LLtihIxM9WY+Sc5Qe/8wcTbtyydD/2wA9tPdQrcfVOWq6H7heUr86la8B\nxmdTpJlNrc57xO3ACJ1rXjwFCLivcF1mrVK3wfAmYFPhWsxay5+sMUvAQTRLwEE0S8BBNEvAQTRL\nwEE0S8BBNEvAQTRLwEE0S8BBNEvAQTRLwEE0S8BBNEvAQTRLwEE0S8BBNEugTl/TFZJ2SdpZ/T4i\naUMvijNri67f0I+InwPXAEjqA14Ethauy6xVZrpreiPwXEQcKFGMWVvNNIifAL5TohCzNqvbch9J\nFwE3A3dOt0zJBsO6COKexoab0qL+RcX7ji4dbu45mc7AQH/x9ejvLztH6fGh8zw1rWSD4TM+DDwZ\nEYenW6Bkg+E4SU8azm5ed3XROXrhxIneNEou+VytHx1zg+Fp3IJ3S82KqHt9xEE6B2pGy5Zj1k51\nGwwfB5YUrsWstfzJGrMEHESzBBxEswQcRLMEHESzBBxEswQcRLMEHESzBBxEswQcRLMEHESzBBxE\nswQcRLMEHESzBBxEswQcRLME6n5Df1jSg5LGJT0r6brShZm1Sd3mUfcCj0TEn0paCAwWrMmsdboG\nUdIlwA0RsR4gIk4BRwvXZdYqdXZNLwd+Ien+6voX90kaKF2YWZvU2TVdCKwCPhsRT0j6OzpNhu+e\nvGDJBsO9aJpbouHsZJ//4fMcOjJRdI652px38vhzcR1KNhh+ETgQEU9U90eAL0y1YMkGw71qmlva\noSMTPVmPuf5czdXXu1iD4Yg4CByQtKL60xpgzyxqNLNp1D1qugHYUl3/Yh9wW7mSzNqnboPhp4A/\nKFyLWWv5kzVmCTiIZgk4iGYJOIhmCTiIZgk4iGYJOIhmCTiIZgk4iGYJOIhmCTiIZgk4iGYJOIhm\nCTiIZgk4iGYJ1Po+oqQXgCPAaeBkRFxbsiiztqn7Df3TwPsj4lclizFrq7q7pprBsmY2Q3XDFcA2\nSTskfaZkQWZtVHfXdHVEvCJpCZ1AjkfET0sWZtYmdZtHvVL9PixpK3AtcE4Q53qD4f7+ftaPjhWf\noxfrMReb804efy6uQ7EGw5IGgb6ImJC0GPgQsGmqZedDg2HPUX+OktrWYLjOFvFSYKukqJbfEhGP\nzqZIM5ta1yBGxPPAyh7UYtZaPiVhloCDaJaAg2iWgINoloCDaJaAg2iWgINoloCDaJaAg2iWgINo\nloCDaJaAg2iWgINoloCDaJaAg2iWgINolkDtIErqk7RT0sMlCzJro5lsEW8H9pQqxKzNagVR0jLg\nJuCrZcsxa6e6W8SvAJ+j02jYzBrWNYiSPgIcjIjddFrvl+2jZ9ZCddoprgZulnQTMAD8lqRvRsSt\nkxecDw2Ge9HUdj6sR+lmzHO1SXKxBsMRcRdwF4CkPwL+ZqoQwvxoMLx53dVF5+iF9aNjc76J8Vxt\nkjzbBsM+j2iWQN2L0AAQET8GflyoFrPW8hbRLAEH0SwBB9EsAQfRLAEH0SwBB9EsAQfRLAEH0SwB\nB9EsAQfRLAEH0SwBB9EsAQfRLAEH0SwBB9EsAQfRLIGuXwyWtAj4CXBxtfxIRGwqXZhZm9TpWfMb\nSR+IiOOSFgA/k/S9iNjeg/rMWqHWrmlEHK9uLqITXvc3NWtQ3U7ffZJ2Aa8C2yJiR9myzNqlVvOo\niDgNXCPpEuBfJF0VEedcB2M+9DUt2asTYOnwEF9ac3nROeZD79Re9DVdOtzcv88zivU1PVtEHJX0\nI2AtU1yQZj70NZ2LvTQnmw/P1VztMVusr6mkt0garm4PAB8E9s6uTDObSp0t4luBb0jqoxPcByLi\nkbJlmbVLndMXY8CqHtRi1lr+ZI1ZAg6iWQIOolkCDqJZAg6iWQIOolkCDqJZAg6iWQIOolkCDqJZ\nAg6iWQIOolkCDqJZAg6iWQIOolkCDqJZAnVaZSyT9JikZyWNSdrQi8LM2qROq4xTwF9HxG5JQ8CT\nkh6NCPetMWtI1y1iRLwaEbur2xPAOPD20oWZtcmM3iNKeiewEni8RDFmbVW7r2m1WzoC3F5tGc9R\nssHw0uGhOd80FzrNf0ubDw2GN27cyAtDzTcAPtvxY8e46rnvNzpm0QbDkhbSCeG3IuKh6ZYr2WC4\ndHdsgPWjY24wXFPpBsObNpW/4Njg4sWNj1mswXDl68CeiLh35qWZWTd1Tl+sBj4N/LGkXZJ2Slpb\nvjSz9qjTYPhnwIIe1GLWWv5kjVkCDqJZAg6iWQIOolkCDqJZAg6iWQIOolkCDqJZAg6iWQIOolkC\nDqJZAg6iWQIOolkCDqJZAg6iWQIOolkCdb6h/zVJByU93YuCzNqozhbxfuBPShdi1mZ1Ggz/FPhV\nD2oxay2/RzRLoHaD4TpKNhjuhV40MV46XP456cV6lG5ivHHjRoZ60GC4abNtMKw6TWIlLQf+NSLe\nc55lYvO6q2dcgNl8VjWt7vo/Vt1dU1U/ZlZAndMX3wb+HVghab+k28qXZdYudRoMf6oXhZi1mY+a\nmiXgIJol4CCaJeAgmiXgIJol4CCaJeAgmiXgIJol4CCaJeAgmiXgIJol4CCaJeAgmiXgIJol4CCa\nJVAriJLWStor6eeSvlC6KLO2qfMN/T7g7+n0Nn03cIukK0oXNtn44QnP0aI55sM6zESdLeK1wH9F\nxP9ExEngu8DHypZ1rtl0xvIcc3eO+bAOM1EniG8HDpx1/8Xqb2bWEB+sMUuga19TSdcD90TE2ur+\nnUBExBcnLde9QapZC9Xpa1oniAuA/wTWAK8A24FbImK8iSLNrF47xdcl/SXwKJ1d2a85hGbNqtVy\n38zKuuCDNaVP9vfiQqmSlkl6TNKzksYkbSgwxyJJj0vaVc1xd9NzVPP0Sdop6eFC478g6alqPbYX\nmmNY0oOSxqvX5LqGx19R1b+z+n2k6ddc0h2SnpH0tKQtki4+7wMiYtY/dIL838By4CJgN3DFhYw5\nxRzvA1YCTzc57qQ5fhdYWd0eovOeuNH1qMYerH4vAP4DuLbAHHcA/wQ8XOi52ge8udRrUc2xGbit\nur0QuKTgXH3Ay8A7GhzzbdXzdHF1/wHg1vM95kK3iMVP9kcPLpQaEa9GxO7q9gQwToFzpRFxvLq5\niM4/sEbfF0haBtwEfLXJcSdPQ8HTXpIuAW6IiPsBIuJURBwtNR9wI/BcRBzouuTMLAAWS1oIDNIJ\n+7Qu9Amddyf7Jb2Tzhb48QJj90naBbwKbIuIHQ1P8RXgczQc8EkC2CZph6TPFBj/cuAXku6vdh3v\nkzRQYJ4zPgF8p8kBI+Jl4MvAfuAl4NcR8YPzPcYn9M8iaQgYAW6vtoyNiojTEXENsAy4TtJVTY0t\n6SPAwWrLXvIyeqsjYhWdLe9nJb2v4fEXAquAf6jmOQ7c2fAcAEi6CLgZeLDhcd9EZ89wOZ3d1CFJ\n572Y04UG8SXgsrPuL6v+NudUuxAjwLci4qGSc1W7Wj8C1jY47GrgZkn76PwP/wFJ32xwfAAi4pXq\n92FgK523J016ETgQEU9U90foBLOEDwNPVuvSpBuBfRHxy4h4HRgF3nu+B1xoEHcAvydpeXVU6JNA\niaN1vbhQ6teBPRFxb4nBJb1F0nB1ewD4ILC3qfEj4q6IuCwi3kXndXgsIm5tanwASYPVXgOSFgMf\nAp5pco6IOAgckLSi+tMaYE+Tc5zlFhreLa3sB66X1K/O9c3X0DnuMK2uJ/TPJ3pwsr+6UOr7gd+R\ntB+4+8wb+QbnWA18Ghir3sMFcFdEfL/Bad4KfKP6Wlkf8EBEPNLg+L1wKbC1+jjjQmBLRDxaYJ4N\nwJZq13Ef0PjFcSUN0tly/XnTY0fEdkkjwC7gZPX7vvPWUx1eNbM3kA/WmCXgIJol4CCaJeAgmiXg\nIJol4CCaJeAgmiXgIJol8L9rYl7TkKjgYwAAAABJRU5ErkJggg==\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\nR8AbDLvtAJBAeQJAAuUJAAmUJwAkUJ4AkEB5AkAC5QkACZQnACRQngCQQHkCQALlCQAJlCcAJFCe\nAJDQqDxt77A9afu/bH+hVCgAqF26PG2fJ+lvJV0r6XJJH7W9pVSw1TQxM9vrCCuqPZ9Uf8ba80n1\nZ6w9n7S6GZtsef6+pGci4qcR8Yqkb0vaWSbW6pqcmet1hBXVnk+qP2Pt+aT6M9aeT1rdjE3K822S\njs07/nz3NAB4w+MNIwBIcETkftC+UtJtEbGje/wWSRERX110vtwFAEAFImLJwVJNyvN8SU9L2i7p\nfyQ9LOmjETGRDQkA/SI9AC4ifm37LyQdUGf3/26KE8Bakd7yBIC1rLU3jGr/AL3tTbYP2X7K9hHb\nu3qdaSm2z7P9qO0Hep1lKbbX2/6O7YnubfneXmdazPanbT9p+wnb99l+cwWZ7rY9ZfuJeae91fYB\n20/bfsj2+sry7e7ez4dtf9f2hb3Kt1zGef/3Wduv2v7Nti6/lfLskw/Qn5L0mYi4XNIfSPpkhRkl\n6WZJ470OsYI7JX0vIkYl/Y6kql66sX2xpE9J2hYR71HnpaobeptKknSPOo+P+W6RdDAi3iXpkKQv\nrnqq/7dUvgOSLo+IKyQ9o97mk5bOKNubJF0j6adtXnhbW57Vf4A+Il6KiMPdw7PqPOir+pxq95fg\ng5K+0essS+luebw/Iu6RpIg4FREv9zjWUs6XNGR7naQLJL3Y4zyKiB9K+sWik3dKurd7+F5JH17V\nUPMslS8iDkbEq92j/yFp06oHW5hnqdtQkr4u6XNtX35b5dlXH6C3famkKyT9uLdJznL6l6DWF6Y3\nS/qZ7Xu6Ly3cZXuw16Hmi4gXJX1N0lFJL0j6ZUQc7G2qZW2IiCmp8+QuaUOP86zkzyQ92OsQi9m+\nTtKxiDjS9mWt+Q/J2x6WtEfSzd0t0CrY/pCkqe7Wsbv/arNO0jZJfxcR2yT9Sp1dz2rYfos6W3SX\nSLpY0rDtG3ub6pxV+aRp+y8lvRIR9/c6y3zdJ+5bJX1p/sltXV5b5fmCpLfPO76pe1pVurtxeyT9\nU0Ts73WeRa6SdJ3tZyX9s6Q/sv2PPc602PPqPMs/0j2+R50yrcnVkp6NiJ9HxK8l7ZX0vh5nWs6U\n7Y2SZPsiSdM9znMW22PqvJRU4xPQOyVdKulx28+p0zs/sd3KFnxb5fmfkn7L9iXddzZvkFTju8Xf\nlDQeEXf2OshiEXFrRLw9It6hzu13KCI+3utc83V3MY/Zvqx70nbV9+bWUUlX2h6wbXUy1vKm1uI9\nigckjXUPf0JSr5/QF+SzvUOdl5Gui4j/7Vmqhc5kjIgnI+KiiHhHRGxW58n9dyOilSehVsqz+wx/\n+gP0T0n6dm0foLd9laSPSfqA7ce6r9nt6HWuPrRL0n22D6vzbvtXepxngYh4WJ0t4sckPa7OA+2u\nnoaSZPt+ST+SdJnto7ZvknS7pGtsn/7Lvdsry/c3koYl/Vv38fL3vcq3Qsb5Qi3utvMheQBIWPNv\nGAFABuUJAAmUJwAkUJ4AkEB5AkAC5QkACZQnACRQngCQ8H/AGJvttLXzoQAAAABJRU5ErkJggg==\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAU8AAAD7CAYAAADq4RYlAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAADutJREFUeJzt3W+MnXWZxvHrgmo6zCzVTaYl2AjVDXZKdNkmKisxm3Ug\nNJiAmGyCmGjZt64lalTEF+KbDTYYl/33gogVN7AmdtuUbHTp1iYmrllZhEJhZlizEFtgmRmjlsxY\nDJV7X5wz3ZnpzLS9n98z53eY7ydpcub09Pdc50+v8zznnDm3I0IAgPNzQa8DAEA/ojwBIIHyBIAE\nyhMAEihPAEigPAEgYV3bG7DNZ6EA9K2I8FLnt16ekvTtj757NTaTtn9sUjdv29TrGMuqPZ9Uf8ba\n80n1Z6w9n1Q+4859R5f9Ow7bASCB8gSABMpT0tbhwV5HWFHt+aT6M9aeT6o/Y+35pNXN6LZ/t912\n1P6aJwAsZee+o8u+YcSeJwAkUJ4AkEB5AkAC5QkACZQnACRQngCQQHkCQALlCQAJlCcAJJy1PG3f\nb3vS9lPzznur7YO2n7X9iO0N7cYEgLqcy57nHknXLzrvDkmHIuJdkg5L+lLpYABQs7OWZ0T8WNKv\nF519k6QHuqcfkPSRwrkAoGrZ1zw3RsSkJEXEy5I2losEAPUr9YYRozYArCnZMRyTtjdFxKTtSyRN\nrXTh/WOTp09vHR7UyPBQcrPSrkfG9crsqfS/X8rFg+v0t9ePFFtv7J07dNFgue8VnJmZ0T333FNs\nvY0bhrR7dEux9STpCz98XlMnZoqtVzpj6XySNDCwXidPvlrtemvxNmx6ncenZzQxPXtOlz3X8nT3\nz5yHJe2U9DVJn5R0YKV/XHKmyCuzp6S7ii3XWfOusmVcsjglaWhoSCW/d9Ve8usJG5k6MVN1xtL5\npE7G0teZ27D5ek2MDA8t2Lk7MLH8fuG5fFTpIUk/kXSF7WO2b5N0t6TrbD8rabT7MwCsGWfd84yI\nW5f5q2sLZwGAvsFvGAFAAuUJAAmUJwAkUJ4AkEB5AkAC5QkACZQnACRQngCQQHkCQALlCQAJlCcA\nJFCeAJBAeQJAAuUJAAmUJwAkUJ4AkJCdYdQzfpMUd5Vfs6Tfzs4Wn2FUcqTC+vXrtXPf0WLrza1Z\nc8bS+dpYk9uwuYGB9cXWOpu+K894Ta3MUSlp2//8W9H1du47WvWsnDbWrH29uTW//dF3F1uv9vu5\nXx43q4XDdgBIoDwBIIHyBIAEyhMAEihPAEigPAEggfIEgATKEwASKE8ASKA8ASCB8gSABMoTABIo\nTwBIoDwBIKFRedr+jO2nbT9l+0Hbby4VDABqli5P25dK+rSk7RHxHnW+G/SWUsEAoGZNvwz5QkmD\ntl+XdJGkl5pHAoD6pfc8I+IlSV+XdEzSi5J+ExGHSgUDgJql9zxtv0XSTZIuk3RC0l7bt0bEQ4sv\nu39s8vTprcODGhkeym5WAwPl56iUnnvyhR8+r6kTM8XWK32d+2EWTe3rSeUfN7Xfz/3wuGl6n4xP\nz2hievacLtvksP1aSc9FxK8kyfY+SR+QdEZ53rxtU4PNLHTy5KvVzzCaOjFTfC5LzbNypPoztjV/\np6TSj+025gOVvI+ldu7nJkaGhxbs3B2YmFr2sk3ebT8m6Wrb691JPCppvMF6ANA3mrzm+aikvZKe\nkPSkJEu6r1AuAKhao3fbI+Krkr5aKAsA9A1+wwgAEihPAEigPAEggfIEgATKEwASKE8ASKA8ASCB\n8gSABMoTABIoTwBIoDwBIIHyBIAEyhMAEihPAEigPAEggfIEgISmo4dXXT8MgCudsfZ8c2uWXq8f\nhpft3He06Ho1X+eBgbLXV6pvANz56Lvy7IcBcG0M8ipprd6GbVznmjPWPpRPauc6rxYO2wEggfIE\ngATKEwASKE8ASKA8ASCB8gSABMoTABIoTwBIoDwBIIHyBIAEyhMAEihPAEigPAEggfIEgIRG5Wl7\ng+3v2R63/Yzt95cKBgA1a/p9nvdK+n5E/IXtdZIuKpAJAKqXLk/bF0v6YETslKSIOCXplUK5AKBq\nTQ7bt0j6pe09th+3fZ/tgVLBAKBmTQ7b10naLulTEfGY7b+RdIekryy+4P6xydOntw4PamR4KL3R\nNubvlJ5FUzrjxg3522sp/XAb1j7Pp40121iv5vukjTWbzjAan57RxPTsOV22SXm+IOl4RDzW/Xmv\npC8udcGbt21qsJmF2pq/U/PsmNL65Tas/T4pPdOnH27DfnjcNDEyPLRg5+7AxNSyl00ftkfEpKTj\ntq/onjUqaSy7HgD0k6bvtu+S9KDtN0l6TtJtzSMBQP0alWdEPCnpvYWyAEDf4DeMACCB8gSABMoT\nABIoTwBIoDwBIIHyBIAEyhMAEihPAEigPAEggfIEgATKEwASKE8ASKA8ASCB8gSABMoTABKafhny\nqmtr/k7pOSolZ8ds3DCk3aNbiq5X+21Y+zyfuTVrv841r9fGmk1nGJ2PvivPtubvlJxv08Zsm5JK\nFvGctTbPp401++Fx2A+34WrhsB0AEihPAEigPAEggfIEgATKEwASKE8ASKA8ASCB8gSABMoTABIo\nTwBIoDwBIIHyBIAEyhMAEihPAEhoXJ62L7D9uO2HSwQCgH5QYs/zdkljBdYBgL7RqDxtb5Z0g6Rv\nlokDAP2h6Z7nNyR9XlLZr5cGgMqly9P2hyVNRsQRSe7+AYA1ockMo2sk3Wj7BkkDkv7A9nci4hOL\nL7h/bPL06a3DgxoZHkpvtI0BcKWHRpXOWHp42cDAep08+Wqx9ebWrHnYWL8MLyt5P6/V27CJ8ekZ\nTUzPntNl0+UZEXdKulOSbP+ZpM8tVZySdPO2TdnNnKGtAXAllc7YL8PQ1uLwsrV0nUtfX6m+YYkj\nw0MLdu4OTEwte1k+5wkACUVGD0fEjyT9qMRaANAP2PMEgATKEwASKE8ASKA8ASCB8gSABMoTABIo\nTwBIoDwBIIHyBIAEyhMAEihPAEigPAEggfIEgATKEwASKE8ASKA8ASChyJchr6aNG4aKj83YuCE/\nU2m59UrPZemHWTRrbf7OWps5VPo+nluzphlG56PvynP36JZeRzir2jOWnhsj1T9nqV/m76yl9dpY\ns/QT5Eo4bAeABMoTABIoTwBIoDwBIIHyBIAEyhMAEihPAEigPAEggfIEgATKEwASKE8ASKA8ASCB\n8gSABMoTABLS5Wl7s+3Dtp+xfdT2rpLBAKBmTb7P85Skz0bEEdtDkn5m+2BETBTKBgDVSu95RsTL\nEXGke3pG0rikt5UKBgA1K/Kap+3LJV0l6acl1gOA2jUew9E9ZN8r6fbuHugZ9o9Nnj69dXhQI8Nl\nZwbh/LQxB6r0nKU21qt9/k7t65W+T9pYs+k8svHpGU1Mz57TZd1kfojtdZL+VdIPIuLeZS4TpWfH\nAOeLuU3I6D5ulmz3poft35I0tlxxAsAbVZOPKl0j6eOSPmT7CduP295RLhoA1Cv9mmdE/IekCwtm\nAYC+wW8YAUAC5QkACZQnACRQngCQQHkCQALlCQAJlCcAJFCeAJBAeQJAAuUJAAmUJwAkUJ4AkEB5\nAkAC5QkACZQnACRQngCQ0HgAHNAP1uLQu6bD0LAyyhNrwu7RLb2OgDcYDtsBIIHyBIAEyhMAEihP\nAEigPAEggfIEgATKEwASKE8ASKA8ASCB8gSABMoTABIoTwBIoDwBIKFRedreYXvC9n/b/mKpUABQ\nu3R52r5A0t9Lul7SlZI+ZntrqWCraXx6ptcRVlR7Pqn+jLXnk+rPWHs+aXUzNtnzfJ+kn0fELyLi\nNUnflXRTmVira2J6ttcRVlR7Pqn+jLXnk+rPWHs+aXUzNinPt0k6Pu/nF7rnAcAbHm8YAUCCIyL3\nD+2rJd0VETu6P98hKSLia4sul9sAAFQgIpYcLNWkPC+U9KykUUn/K+lRSR+LiPFsSADoF+kBcBHx\ne9t/JemgOof/91OcANaK9J4nAKxlrb1hVPsH6G1vtn3Y9jO2j9re1etMS7F9ge3HbT/c6yxLsb3B\n9vdsj3dvy/f3OtNitj9j+2nbT9l+0PabK8h0v+1J20/NO++ttg/aftb2I7Y3VJZvd/d+PmL7X2xf\n3Kt8y2Wc93efs/267T9sa/utlGeffID+lKTPRsSVkv5U0qcqzChJt0sa63WIFdwr6fsRMSLpjyVV\n9dKN7UslfVrS9oh4jzovVd3S21SSpD3q/P+Y7w5JhyLiXZIOS/rSqqf6f0vlOyjpyoi4StLP1dt8\n0tIZZXuzpOsk/aLNjbe151n9B+gj4uWIONI9PaPOf/qqPqfafRDcIOmbvc6ylO6exwcjYo8kRcSp\niHilx7GWcqGkQdvrJF0k6aUe51FE/FjSrxedfZOkB7qnH5D0kVUNNc9S+SLiUES83v3xPyVtXvVg\nC/MsdRtK0jckfb7t7bdVnn31AXrbl0u6StJPe5vkDHMPglpfmN4i6Ze293RfWrjP9kCvQ80XES9J\n+rqkY5JelPSbiDjU21TL2hgRk1LnyV3Sxh7nWclfSvpBr0MsZvtGSccj4mjb21rzH5K3PSRpr6Tb\nu3ugVbD9YUmT3b1jd//UZp2k7ZL+ISK2S/qtOoee1bD9FnX26C6TdKmkIdu39jbVOavySdP2lyW9\nFhEP9TrLfN0n7jslfWX+2W1tr63yfFHS2+f9vLl7XlW6h3F7Jf1TRBzodZ5FrpF0o+3nJP2zpD+3\n/Z0eZ1rsBXWe5R/r/rxXnTKtybWSnouIX0XE7yXtk/SBHmdazqTtTZJk+xJJUz3OcwbbO9V5KanG\nJ6B3Srpc0pO2n1end35mu5U9+LbK878k/ZHty7rvbN4iqcZ3i78laSwi7u11kMUi4s6IeHtEvEOd\n2+9wRHyi17nm6x5iHrd9RfesUdX35tYxSVfbXm/b6mSs5U2txUcUD0va2T39SUm9fkJfkM/2DnVe\nRroxIn7Xs1QLnc4YEU9HxCUR8Y6I2KLOk/ufREQrT0KtlGf3GX7uA/TPSPpubR+gt32NpI9L+pDt\nJ7qv2e3oda4+tEvSg7aPqPNu+1/3OM8CEfGoOnvET0h6Up3/aPf1NJQk2w9J+omkK2wfs32bpLsl\nXWd77jf37q4s399JGpL0793/L//Yq3wrZJwv1OJhOx+SB4CENf+GEQBkUJ4AkEB5AkAC5QkACZQn\nACRQngCQQHkCQALlCQAJ/wcU+HVoCQewRQAAAABJRU5ErkJggg==\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "def maze1():\n", + " return Maze([\n", + " \"########\",\n", + " \"#X.#...#\",\n", + " \"#.##.#.#\",\n", + " \"#.#..#.#\",\n", + " \"#....#.#\",\n", + " \"#.##...#\",\n", + " \"#..#..##\",\n", + " \"##.#..@#\",\n", + " \"########\"\n", + " ])\n", + "\n", + "maze1().draw()\n", + "\n", + "def maze2():\n", + " return Maze([\n", + " \"###############\",\n", + " \"#X#@.#.#...#..#\",\n", + " \"#.##.....#....#\",\n", + " \"#.#.#.#..#..#.#\",\n", + " \"#...#.#....#..#\",\n", + " \"#.#.#.........#\",\n", + " \"#.#.##.#..#...#\",\n", + " \"#.....#..#..#.#\",\n", + " \"#####...#.....#\",\n", + " \"########...####\",\n", + " \"###############\"\n", + " ])\n", + "\n", + "maze2().draw()\n", + "\n", + "def mazeUnsolvable1():\n", + " return Maze([\n", + " \"###############\",\n", + " \"#X#@.#.#...#..#\",\n", + " \"#.##.....#....#\",\n", + " \"#.#.#.#..#..#.#\",\n", + " \"#.#.#.#....#..#\",\n", + " \"#..##...#.....#\",\n", + " \"#.#.##....#...#\",\n", + " \"#.#...#..#..#.#\",\n", + " \"#####...#.....#\",\n", + " \"########...####\",\n", + " \"###############\"\n", + " ])\n", + "\n", + "mazeUnsolvable1().draw()" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[(5, 1), (4, 1), (4, 2), (4, 3), (4, 4), (3, 4), (2, 4), (1, 4), (1, 5), (1, 6), (1, 7)]\n", + "[(4, 9), (4, 8), (5, 8), (6, 8), (7, 8), (7, 7), (7, 6), (8, 6), (8, 5), (8, 4), (8, 3), (7, 3), (7, 2), (6, 2), (5, 2), (5, 3), (4, 3), (3, 3), (3, 4), (3, 5), (3, 6), (2, 6), (1, 6), (1, 7), (1, 8), (1, 9)]\n", + "[]\n" + ] + } + ], + "source": [ + "print(heuristic(maze1()))\n", + "print(heuristic(maze2()))\n", + "print(heuristic(mazeUnsolvable1()))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You also have to be able to handle switch and door puzzles:" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/png": "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\nG6OvTDFBAAAAAElFTkSuQmCC\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "def maze3():\n", + " return Maze([\n", + " \"###############\",\n", + " \"#X#@.#.#...#.1#\",\n", + " \"#.##.....#....#\",\n", + " \"#A#.#.#..#..#.#\",\n", + " \"#.a.#C#....#..#\",\n", + " \"#.#.#0C.......#\",\n", + " \"#.#.##.#..#...#\",\n", + " \"#.B...#.2#..#.#\",\n", + " \"#####...#.....#\",\n", + " \"########...####\",\n", + " \"###############\"\n", + " ])\n", + "\n", + "maze3().draw()\n", + "\n", + "def maze4():\n", + " return Maze([\n", + " \"########\",\n", + " \"#@0#.01#\",\n", + " \"#A1#C#a#\",\n", + " \"#0#..#.#\",\n", + " \"#aBc2#.#\",\n", + " \"#B##c..#\",\n", + " \"#..#bb##\",\n", + " \"##1#..X#\",\n", + " \"########\"\n", + " ])\n", + "\n", + "maze4().draw()" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[(4, 9), (4, 8), (5, 8), (6, 8), (7, 8), (8, 8), (8, 9), (9, 9), (10, 9), (10, 8), (11, 8), (12, 8), (12, 9), (13, 9), 'switch', (12, 9), (12, 8), (11, 8), (10, 8), (10, 9), (9, 9), (8, 9), (8, 8), (8, 7), (8, 6), (8, 5), (8, 4), (8, 3), 'switch', (8, 4), (8, 5), (7, 5), (6, 5), (5, 5), 'switch', (6, 5), (7, 5), (8, 5), (8, 4), (8, 3), 'switch', (7, 3), (7, 2), (6, 2), (5, 2), (5, 3), (4, 3), (3, 3), (2, 3), (1, 3), (1, 4), (1, 5), (1, 6), (1, 7), (1, 8), (1, 9)]\n", + "[(2, 7), 'switch', (2, 6), 'switch', (1, 6), (1, 5), 'switch', (1, 4), (2, 4), (3, 4), (4, 4), 'switch', (4, 5), (4, 6), (4, 7), (5, 7), (6, 7), 'switch', (6, 6), (6, 5), (6, 4), (6, 3), (5, 3), (5, 2), (5, 1), (6, 1)]\n" + ] + } + ], + "source": [ + "print(heuristic(maze3()))\n", + "print(heuristic(maze4()))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Assignment 2\n", + "\n", + "Once you have this working, write an agent which finds a policy for a \"blind\" puzzle using MCTS. \"Blind\" puzzles are just like the puzzles above, only (a) you don't get to see the whole puzzle or know the goal states in advance, and (b) some nodes are trap doors with a chance of dropping the player into a bottomless pit! Try different policies for deciding between exploit/explore and for doing rollouts and compare them. Plot graphs on how learning improves with more rollouts.\n", + "\n", + "Of course, it should also be able to solve the earlier maze puzzles!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def mcts(maze,iterations):\n", + " # Return the expected value (a number between 0 for \"player dead\", 1 for \"made it to the end\")\n", + " # for a budget of `iterations` rollouts.\n", + " # Should also return the best found path (the one most likely to lead to success).\n", + " # Here, don't look at maze.exit_pos or maze.grid:\n", + " # you're only allowed to query `maze.available_moves()`, `maze.player_alive`, and `maze.is_at_exit`.\n", + "\n", + " # After training for `iterations` rollouts, run an agent through the maze using that learned policy \n", + " # for a large number of times and return the average reward:\n", + " # (best_path, expected_reward, test_reward)\n", + "\n", + " return ([], 0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def maze5():\n", + " return Maze([\n", + " \"#######\",\n", + " \"#@???X#\",\n", + " \"#.....#\",\n", + " \"#######\"\n", + " ])\n", + "\n", + "maze5().draw()\n", + "\n", + "def maze6():\n", + " return Maze([\n", + " \"#######\",\n", + " \"#@?!?X#\",\n", + " \"#.???.#\",\n", + " \"#.....#\",\n", + " \"#######\"\n", + " ])\n", + "\n", + "maze6().draw()\n", + "\n", + "def maze7():\n", + " return Maze([\n", + " \"########\",\n", + " \"#@0#?01#\",\n", + " \"#A1#C#a#\",\n", + " \"#0#.?#!#\",\n", + " \"#aBc2#.#\",\n", + " \"#B##c.?#\",\n", + " \"#.!#bb##\",\n", + " \"##1#.?X#\",\n", + " \"########\"\n", + " ])\n", + "\n", + "maze7().draw()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Assignment 3\n", + "\n", + "Do assignment 2 again, but with reinforcement learning! Compare various approaches and parameters (e.g.\\ different discounting rates, Sarsa vs Q-learning, etc) against your MCTS agents in terms of iterations required to reach certain levels of performance. Plot graphs showing how learning improves with more iterations. Print or draw out (at least some of) the state-value or action-value matrix.\n", + "\n", + "Read as much as you care to of Sutton & Barto---[section 2](https://webdocs.cs.ualberta.ca/~sutton/book/ebook/node39.html) is especially useful.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def rl(maze,iterations):\n", + " # Return the best path (most likely to lead to success) along with its expected value and a validated value\n", + " # for a budget of `iterations` experiments.\n", + " # As above, don't look at maze.exit_pos or maze.grid:\n", + " # you're only allowed to query `maze.available_moves()`, `maze.player_alive`, and `maze.is_at_exit`.\n", + "\n", + " # After training for `iterations` experiments, run an agent through the maze using that learned policy \n", + " # for a large number of times and return the average reward:\n", + " # (best_path, expected_reward, test_reward)\n", + "\n", + " return ([],0,0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Bonus Assignment\n", + "\n", + "Make an adversary for the maze who is trying to eat the player. Try to get the best performing adversary possible!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "anaconda-cloud": {}, + "kernelspec": { + "display_name": "Python [Root]", + "language": "python", + "name": "Python [Root]" + }, + "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.5.2" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/projects/5-emojiworld/Chappidi.json b/projects/5-emojiworld/Chappidi.json new file mode 100644 index 0000000..25e32ad --- /dev/null +++ b/projects/5-emojiworld/Chappidi.json @@ -0,0 +1 @@ + {"meta":{"description":"When making your sim, remember the KISS Principle: Keep It Simple, Sucka.\n\nAt the bottom of this sidebar, you can SAVE and SHARE your sim. Have fun! 😘","draw":4,"fps":12,"play":true},"states":[{"actions":[{"actions":[{"stateID":1,"type":"go_to_state","actions":[]}],"probability":0.001,"type":"if_random"}],"description":"Grow Wheat","icon":"","id":0,"name":"empty spot"},{"actions":[{"actions":[{"stateID":"2","type":"go_to_state","actions":[]}],"probability":0.002,"type":"if_random"}],"description":"Grow Tomato","icon":"🌾","id":1,"name":"wheat "},{"actions":[{"actions":[{"stateID":"3","type":"go_to_state","actions":[]}],"num":1,"sign":">=","stateID":"2","type":"if_neighbor"}],"description":"Turn Tomato and Wheat into Spaghetti","icon":"🍅","id":2,"name":"tomatoes"},{"actions":[{"actions":[{"stateID":"4","type":"go_to_state","actions":[]}],"probability":0.03,"type":"if_random"},{"actions":[{"stateID":"4","type":"go_to_state","actions":[]}],"num":1,"sign":">=","stateID":"4","type":"if_neighbor"}],"description":"Humans eat lots of spaghetti","icon":"🍝","id":3,"name":"[new thing]"},{"actions":[{"stateID":0,"type":"go_to_state","actions":[]}],"description":"Done Eating ","icon":"😋","id":4,"name":"Satisfied Human"}],"world":{"neighborhood":"moore","proportions":[{"stateID":0,"parts":100},{"stateID":1,"parts":0},{"stateID":2,"parts":0},{"stateID":3,"parts":0},{"stateID":4,"parts":0}],"size":{"height":33,"width":40},"update":"simultaneous"}} \ No newline at end of file diff --git a/projects/6-perceptron/Chappidi.ipynb b/projects/6-perceptron/Chappidi.ipynb new file mode 100644 index 0000000..31b275b --- /dev/null +++ b/projects/6-perceptron/Chappidi.ipynb @@ -0,0 +1,352 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import numpy as np\n", + "from numpy import dot\n", + "from random import uniform, choice\n", + "import matplotlib.pyplot as plt\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def plot_xys(xy_l_tuples,sz=15):\n", + " t_yes = [a[0] for a in xy_l_tuples if a[1] == 1]\n", + " t_no = [a[0] for a in xy_l_tuples if a[1] == 0]\n", + " plt.plot([x for (x,y) in t_yes],[y for (x,y) in t_yes],'go',markersize=sz)\n", + " plt.plot([x for (x,y) in t_no],[y for (x,y) in t_no],'ro',markersize=sz)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def tuple_append(tpl,elt):\n", + " return tuple(list(tpl)+[elt])\n", + "\n", + "def perceptron(training, epochs):\n", + " # some parameters, maybe interesting to make these arguments\n", + " rate = 1.0\n", + " # how many weights do we need?\n", + " feature_count = len(training[0][0])\n", + " # pad each training example with a dummy 1 input\n", + " training = [(tuple_append(ins,1), label) for (ins,label) in training]\n", + " # initialize weights to random values\n", + " weights = [uniform(0,0.05) for _r in range(0,feature_count+1)]\n", + " # let's store the errors found during training\n", + " errors = []\n", + " for i in range(0,epochs):\n", + " # in each epoch, pick a subset of the training set (just one for now)\n", + " (example,actual) = choice(training)\n", + " # calculate the perceptron activation and the predicted category\n", + " activation = dot(example, weights)\n", + " # Note: You can use dot(vec1, vec2) to get the dot product between two sequential collections.\n", + " if activation >= 0:\n", + " predicted = 1\n", + " else:\n", + " predicted = 0\n", + " # calculate the error between predicted and actual and add it to errors\n", + " error = actual - predicted\n", + " errors.append(error)\n", + " # update each weight according to the perceptron update rule\n", + " for i in range(0, len(weights)):\n", + " weights[i] += example[i] * error\n", + " return (errors,weights)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXkAAAEACAYAAABWLgY0AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAADzpJREFUeJzt3H+I3Hedx/Hnq8ZKDW2hFgMmtnfXXCyKNYomAQs3tnJN\nBYn4z7X1KhaVwF1U8A9TK22X1qr548Bri0rugiKnRLDC5TzFinSR3jUxQrbRM+kmVWKTSrz6o8Ze\neqThfX/sXDpdk8zs7uxs9pPnAwb2O/PZ77z5svvMN9+Z2VQVkqQ2XbDQA0iS5o+Rl6SGGXlJapiR\nl6SGGXlJapiRl6SG9Y18km1JjibZe5Y19yc5kGQiyerhjihJmq1BzuS/DNxwpgeT3AhcVVV/CWwE\nvjSk2SRJc9Q38lX1KPC7syzZAHy1u3YXcGmSZcMZT5I0F8O4Jr8ceKpn+0j3PknSAvOFV0lq2JIh\n7OMI8Nqe7RXd+/5EEv9QjiTNQlVlNt836Jl8urfT2QG8HyDJOuD3VXX0TDuqM9weWrqUiYkJquq8\nuN19990LPsO5cvNYeCzO92OxZ88eXvm3r4QxTn+bg75n8km+DnSAVyX5JXA3cCFQVbW1qr6T5F1J\nDgLPAbfNZpA9y5dz46pVs/lWSVrUXve617Hif1YwyeTQ99038lV1ywBrNs1liD8AL1+3josuumgu\nu5GkRemiiy5i7WvXMvm/k/CK4e77nHjh9Z+XLeN9d9650GOMVKfTWegRzhkeixd5LF50vh2Luzbd\nxbInhv/u81SN7rXQJH/ybDsuuYT/3ryZD95xx8jmkKRz0X3/eB9bJrZw7M+OvfSBsfl/4XXo/gD8\nw7JlBl6Suj71sU9x++rbWbZ3GTw/nH2O/Ez+oaVLmVixgpevXcstd97JVStXjuz5JWkxOHjwIPc+\neC87f7mTI0uP8Ny/PDfrM/mRR35iYoJVq1b5Iqsk9XH8+HEmJydZvXr14on8KJ9PklqQZPFdk5ck\nzT8jL0kNM/KS1DAjL0kNM/KS1DAjL0kNM/KS1DAjL0kNM/KS1DAjL0kNM/KS1DAjL0kNM/KS1DAj\nL0kNM/KS1DAjL0kNM/KS1DAjL0kNM/KS1DAjL0kNM/KS1DAjL0kNM/KS1DAjL0kNM/KS1DAjL0kN\nM/KS1DAjL0kNM/KS1DAjL0kNGyjySdYn2Z9kMsnm0zx+SZIdSSaS/CTJB4Y+qSRpxlJVZ1+QXABM\nAtcDTwO7gZuqan/Pmk8Cl1TVJ5NcDjwBLKuqF6btq/o9nyTppZJQVZnN9w5yJr8GOFBVh6rqBLAd\n2DBtTQEXd7++GPjN9MBLkkZvkMgvB57q2T7cva/Xg8DrkzwNPA58bDjjSZLmYsmQ9nMDsKeqrkty\nFfD9JNdU1R+nLxwbGzv1dafTodPpDGkESWrD+Pg44+PjQ9nXINfk1wFjVbW+u307UFW1pWfNt4HP\nVtV/dLd/AGyuqh9P25fX5CVphub7mvxuYGWSK5NcCNwE7Ji25hDwzu4wy4BVwM9nM5AkaXj6Xq6p\nqpNJNgEPM/WPwraq2pdk49TDtRX4NPCVJHu73/aJqvrtvE0tSRpI38s1Q30yL9dI0ozN9+UaSdIi\nZeQlqWFGXpIaZuQlqWFGXpIaZuQlqWFGXpIaZuQlqWFGXpIaZuQlqWFGXpIaZuQlqWFGXpIaZuQl\nqWFGXpIaZuQlqWFGXpIaZuQlqWFGXpIaZuQlqWFGXpIaZuQlqWFGXpIaZuQlqWFGXpIaZuQlqWFG\nXpIaZuQlqWFGXpIaZuQlqWFGXpIaZuQlqWFGXpIaZuQlqWFGXpIaNlDkk6xPsj/JZJLNZ1jTSbIn\nyU+TPDLcMSVJs5GqOvuC5AJgErgeeBrYDdxUVft71lwK/Cfw11V1JMnlVfXMafZV/Z5PkvRSSaiq\nzOZ7BzmTXwMcqKpDVXUC2A5smLbmFuChqjoCcLrAS5JGb5DILwee6tk+3L2v1yrgsiSPJNmd5NZh\nDShJmr0lQ9zPW4DrgKXAY0keq6qDQ9q/JGkWBon8EeCKnu0V3ft6HQaeqarngeeT/BB4E/AnkR8b\nGzv1dafTodPpzGxiSWrc+Pg44+PjQ9nXIC+8vgx4gqkXXn8F/Ai4uar29ay5GngAWA+8AtgF/E1V\n/WzavnzhVZJmaC4vvPY9k6+qk0k2AQ8zdQ1/W1XtS7Jx6uHaWlX7k3wP2AucBLZOD7wkafT6nskP\n9ck8k5ekGZvvt1BKkhYpIy9JDTPyktQwIy9JDTPyktQwIy9JDTPyktQwIy9JDTPyktQwIy9JDTPy\nktQwIy9JDTPyktQwIy9JDTPyktQwIy9JDTPyktQwIy9JDTPyktQwIy9JDTPyktQwIy9JDTPyktQw\nIy9JDTPyktQwIy9JDTPyktQwIy9JDTPyktQwIy9JDTPyktQwIy9JDTPyktQwIy9JDTPyktQwIy9J\nDRso8knWJ9mfZDLJ5rOse1uSE0neO7wRJUmz1TfySS4AHgRuAN4A3Jzk6jOs+xzwvWEPKUmanUHO\n5NcAB6rqUFWdALYDG06z7iPAN4FfD3E+SdIcDBL55cBTPduHu/edkuQ1wHuq6otAhjeeJGkuhvXC\n6+eB3mv1hl6SzgFLBlhzBLiiZ3tF975ebwW2JwlwOXBjkhNVtWP6zsbGxk593el06HQ6MxxZkto2\nPj7O+Pj4UPaVqjr7guRlwBPA9cCvgB8BN1fVvjOs/zLwb1X1rdM8Vv2eT5L0UkmoqlldIel7Jl9V\nJ5NsAh5m6vLOtqral2Tj1MO1dfq3zGYQSdLw9T2TH+qTeSYvSTM2lzN5P/EqSQ0z8pLUMCMvSQ0z\n8pLUMCMvSQ0z8pLUMCMvSQ0z8pLUMCMvSQ0z8pLUMCMvSQ0z8pLUMCMvSQ0z8pLUMCMvSQ0z8pLU\nMCMvSQ0z8pLUMCMvSQ0z8pLUMCMvSQ0z8pLUMCMvSQ0z8pLUMCMvSQ0z8pLUMCMvSQ0z8pLUMCMv\nSQ0z8pLUMCMvSQ0z8pLUMCMvSQ0z8pLUMCMvSQ0z8pLUsIEin2R9kv1JJpNsPs3jtyR5vHt7NMkb\nhz+qJGmmUlVnX5BcAEwC1wNPA7uBm6pqf8+adcC+qno2yXpgrKrWnWZf1e/5JEkvlYSqymy+d5Az\n+TXAgao6VFUngO3Aht4FVbWzqp7tbu4Els9mGEnScA0S+eXAUz3bhzl7xD8EfHcuQ0mShmPJMHeW\n5B3AbcC1Z1ozNjZ26utOp0On0xnmCJK06I2PjzM+Pj6UfQ1yTX4dU9fY13e3bweqqrZMW3cN8BCw\nvqqePMO+vCYvSTM039fkdwMrk1yZ5ELgJmDHtAGuYCrwt54p8JKk0et7uaaqTibZBDzM1D8K26pq\nX5KNUw/XVuBO4DLgC0kCnKiqNfM5uCSpv76Xa4b6ZF6ukaQZm+/LNZKkRcrIS1LDjLwkNczIS1LD\njLwkNczIS1LDjLwkNczIS1LDjLwkNczIS1LDjLwkNczIS1LDjLwkNczIS1LDjLwkNczIS1LDjLwk\nNczIS1LDjLwkNczIS1LDjLwkNczIS1LDjLwkNczIS1LDjLwkNczIS1LDjLwkNczIS1LDjLwkNczI\nS1LDjLwkNczIS1LDRh75iYkJjh8/PuqnlaRF5/jx40xMTMxpH0uGNMvAfvH2t/OtFStYsnYt77vr\nLq5auXLUI0jSOe3Jgwf52j338MKuXbz58OE57StVNaSxBniy5NSzHQP+adkyLv3oR/ngHXeMbAZJ\nOpdtu+8+nn3gAT589CgXd+8LUFWZzf4GulyTZH2S/Ukmk2w+w5r7kxxIMpFkdb99Xgx8/OhRXv25\nz7HtM5+Z4diS1J5t993Hq7ds4eM9gZ+rvpFPcgHwIHAD8Abg5iRXT1tzI3BVVf0lsBH40qADvPvY\nMZ69/36ePHhwRoMvduPj4ws9wjnDY/Eij8WLzrdj8eTBgzz7wAO8+9ixoe53kDP5NcCBqjpUVSeA\n7cCGaWs2AF8FqKpdwKVJlg06xIeOHuVr99476PImnG8/wGfjsXiRx+JF59ux+No99/Dho0eHvt9B\nIr8ceKpn+3D3vrOtOXKaNWd0CXBi507fdSPpvHT8+HFe2LVraJdoep0z75N/85EjTE5OLvQYkjRy\nTzzxxJzfRXMmfd9dk2QdMFZV67vbtwNVVVt61nwJeKSqvtHd3g/8VVUdnbav0b2VR5IaMtt31wzy\nPvndwMokVwK/Am4Cbp62Zgfw98A3uv8o/H564OcypCRpdvpGvqpOJtkEPMzU5Z1tVbUvycaph2tr\nVX0nybuSHASeA26b37ElSYMY6YehJEmjNS8vvM7Hh6cWq37HIsktSR7v3h5N8saFmHMUBvm56K57\nW5ITSd47yvlGacDfkU6SPUl+muSRUc84KgP8jlySZEe3FT9J8oEFGHPeJdmW5GiSvWdZM/NuVtVQ\nb0z9w3EQuBJ4OTABXD1tzY3Av3e/XgvsHPYc58JtwGOxDri0+/X68/lY9Kz7AfBt4L0LPfcC/lxc\nCvwXsLy7fflCz72Ax+KTwGf//zgAvwGWLPTs83AsrgVWA3vP8PisujkfZ/Lz/uGpRaTvsaiqnVX1\nbHdzJzP4fMEiM8jPBcBHgG8Cvx7lcCM2yLG4BXioqo4AVNUzI55xVAY5FgWn3kJ+MfCbqnphhDOO\nRFU9CvzuLEtm1c35iPy8f3hqERnkWPT6EPDdeZ1o4fQ9FkleA7ynqr7I1N9katUgPxergMuSPJJk\nd5JbRzbdaA1yLB4EXp/kaeBx4GMjmu1cM6tujvxPDev0kryDqXclXbvQsyygzwO912RbDn0/S4C3\nANcBS4HHkjxWVefXH3macgOwp6quS3IV8P0k11TVHxd6sMVgPiJ/BLiiZ3tF977pa17bZ00LBjkW\nJLkG2Aqsr6qz/XdtMRvkWLwV2J4kTF17vTHJiaraMaIZR2WQY3EYeKaqngeeT/JD4E1MXb9uySDH\n4jbgswBV9WSSXwBXAz8eyYTnjll1cz4u15z68FSSC5n68NT0X9IdwPvh1CdqT/vhqQb0PRZJrgAe\nAm6tqicXYMZR6Xssquovurc/Z+q6/N81GHgY7HfkX4Frk7wsySuZeqFt34jnHIVBjsUh4J0A3WvQ\nq4Cfj3TK0Qln/h/srLo59DP58sNTpwxyLIA7gcuAL3TPYE9U1ZqFm3p+DHgsXvItIx9yRAb8Hdmf\n5HvAXuAksLWqfraAY8+LAX8uPg18peethZ+oqt8u0MjzJsnXgQ7wqiS/BO4GLmSO3fTDUJLUsHPm\nr1BKkobPyEtSw4y8JDXMyEtSw4y8JDXMyEtSw4y8JDXMyEtSw/4P4LBAXZvwSAcAAAAASUVORK5C\nYII=\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\naQAAAABJRU5ErkJggg==\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "and_set = [((0,0),0), ((0,1),0), ((1,0),0), ((1,1),1)]\n", + "plot_xys(and_set)\n", + "\n", + "(errs,_) = perceptron(and_set,100)\n", + "plt.figure()\n", + "plt.plot(errs)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXkAAAEACAYAAABWLgY0AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAD1ZJREFUeJzt3X+M3HWdx/HnC3sYJECC5JrYWu6OWohGqEbbJhBvBHMU\nkwvGfw644yI5kyZngeRysYgBNyAqf1yi0KjppdGYO4OJmNjzNGIMG4JHa01Y0LNlu+hhW0wN/iAI\n7aWS9/2xc+2wtp3Z3dnZ7qfPR7JhZ+az33nnk93nTr8zs6SqkCS16azFHkCStHCMvCQ1zMhLUsOM\nvCQ1zMhLUsOMvCQ1rG/kk2xPcijJ06dY80CSfUkmkqwd7oiSpLka5JH8l4BrT3ZjkuuAS6rqLcAm\n4ItDmk2SNE99I19VjwO/PcWS64GvdNfuAi5Isnw440mS5mMY5+RXAPt7Lh/sXidJWmQ+8SpJDVs2\nhGMcBN7cc3ll97o/ksQ/lCNJc1BVmcvXDRr5dD9OZAfwEeBrSTYAv6uqQyc90tiJrz536lx+8M8/\n4IorrhhwpKVtbGyMsbGxxR7jtOBeHOdeHHcm7cXExARX/suVvLL6lRMvGJv7sftGPslXgQ7wxiS/\nAD4BnA1UVW2rqm8neX+SKeBl4Ja5DLLi5RWsWbNmLl8qSUvapZdeyspXVjLJ5NCP3TfyVXXTAGs2\nz2uKI7Bh1QbOOeeceR1Gkpaic845h/VvXs/k/07C64d77NPiidflk8u5a/Ndiz3GSHU6ncUe4bTh\nXhznXhx3pu3F3ZvvZvkzw3/1+aJH/vyfn89t77mN1atXL/YoI3WmfQOfintxnHtx3Jm2F6tXr+bW\n99zKef9z3lCPu3iRPwLLn1rOlnds4c7b71y0MSTpdPHx2z/OHWvvYPnTy+HIcI6ZUf7v/5LUuX93\nLitfWcn6Veu56yN3nXGP4CWpn6mpKe7dei87f7GTg+ce5OV/e3nOL6EceeQnJiZYs2aNT7JKUh+H\nDx9mcnKStWvXLp3I+z8Ol6TZSTLnyC/6E6+SpIVj5CWpYUZekhpm5CWpYUZekhpm5CWpYUZekhpm\n5CWpYUZekhpm5CWpYUZekhpm5CWpYUZekhpm5CWpYUZekhpm5CWpYUZekhpm5CWpYUZekhpm5CWp\nYUZekhpm5CWpYUZekhpm5CWpYUZekhpm5CWpYUZekhpm5CWpYUZekhpm5CWpYQNFPsnGJHuTTCbZ\ncoLbz0+yI8lEkh8n+dDQJ5UkzVqq6tQLkrOASeAa4HlgN3BDVe3tWfMx4Pyq+liSi4BngOVV9YcZ\nx6p+9ydJeq0kVFXm8rWDPJJfB+yrqueq6ijwEHD9jDUFnNf9/Dzg1zMDL0kavUEivwLY33P5QPe6\nXluBtyZ5HngKuH0440mS5mPZkI5zLfBkVV2d5BLge0kur6rfz1w4NjZ27PNOp0On0xnSCJLUhvHx\nccbHx4dyrEHOyW8AxqpqY/fyHUBV1f09a74FfLqqftC9/H1gS1X9aMaxPCcvSbO00OfkdwOrk1yc\n5GzgBmDHjDXPAe/rDrMcWAP8bC4DSZKGp+/pmqp6Nclm4BGmfylsr6o9STZN31zbgE8CX07ydPfL\nPlpVv1mwqSVJA+l7umaod+bpGkmatYU+XSNJWqKMvCQ1zMhLUsOMvCQ1zMhLUsOMvCQ1zMhLUsOM\nvCQ1zMhLUsOMvCQ1zMhLUsOMvCQ1zMhLUsOMvCQ1zMhLUsOMvCQ1zMhLUsOMvCQ1zMhLUsOMvCQ1\nzMhLUsOMvCQ1zMhLUsOMvCQ1zMhLUsOMvCQ1zMhLUsOMvCQ1zMhLUsOMvCQ1zMhLUsOMvCQ1zMhL\nUsOMvCQ1zMhLUsMGinySjUn2JplMsuUkazpJnkzykySPDndMSdJcpKpOvSA5C5gErgGeB3YDN1TV\n3p41FwD/BfxVVR1MclFVvXCCY1W/+5MkvVYSqipz+dpBHsmvA/ZV1XNVdRR4CLh+xpqbgIer6iDA\niQIvSRq9QSK/Atjfc/lA97pea4ALkzyaZHeSm4c1oCRp7pYN8TjvBK4GzgWeSPJEVU0N6fiSpDkY\nJPIHgVU9l1d2r+t1AHihqo4AR5I8BlwB/FHkx8bGjn3e6XTodDqzm1iSGjc+Ps74+PhQjjXIE6+v\nA55h+onXXwI/BG6sqj09ay4DHgQ2Aq8HdgF/U1U/nXEsn3iVpFmazxOvfR/JV9WrSTYDjzB9Dn97\nVe1Jsmn65tpWVXuTfBd4GngV2DYz8JKk0ev7SH6od+YjeUmatYV+CaUkaYky8pLUMCMvSQ0z8pLU\nMCMvSQ0z8pLUMCMvSQ0z8pLUMCMvSQ0z8pLUMCMvSQ0z8pLUMCMvSQ0z8pLUMCMvSQ0z8pLUMCMv\nSQ0z8pLUMCMvSQ0z8pLUMCMvSQ0z8pLUMCMvSQ0z8pLUMCMvSQ0z8pLUMCMvSQ0z8pLUMCMvSQ0z\n8pLUMCMvSQ0z8pLUMCMvSQ0z8pLUMCMvSQ0z8pLUsIEin2Rjkr1JJpNsOcW6dyc5muSDwxtRkjRX\nfSOf5CxgK3At8DbgxiSXnWTdZ4DvDntISdLcDPJIfh2wr6qeq6qjwEPA9SdYdyvwdeBXQ5xPkjQP\ng0R+BbC/5/KB7nXHJHkT8IGq+gKQ4Y0nSZqPYT3x+lmg91y9oZek08CyAdYcBFb1XF7Zva7Xu4CH\nkgS4CLguydGq2jHzYGNjY8c+73Q6dDqdWY4sSW0bHx9nfHx8KMdKVZ16QfI64BngGuCXwA+BG6tq\nz0nWfwn4j6r6xgluq373J0l6rSRU1ZzOkPR9JF9VrybZDDzC9Omd7VW1J8mm6Ztr28wvmcsgkqTh\n6/tIfqh35iN5SZq1+TyS9x2vktQwIy9JDTPyktQwIy9JDTPyktQwIy9JDTPyktQwIy9JDTPyktQw\nIy9JDTPyktQwIy9JDTPyktQwIy9JDTPyktQwIy9JDTPyktQwIy9JDTPyktQwIy9JDTPyktQwIy9J\nDTPyktQwIy9JDTPyktQwIy9JDTPyktQwIy9JDTPyktQwIy9JDTPyktQwIy9JDTPyktQwIy9JDTPy\nktQwIy9JDRso8kk2JtmbZDLJlhPcflOSp7ofjyd5+/BHlSTNVqrq1AuSs4BJ4BrgeWA3cENV7e1Z\nswHYU1UvJtkIjFXVhhMcq/rdnyTptZJQVZnL1w7ySH4dsK+qnquqo8BDwPW9C6pqZ1W92L24E1gx\nl2EkScM1SORXAPt7Lh/g1BH/MPCd+QwlSRqOZcM8WJL3ArcAV51szdjY2LHPO50OnU5nmCNI0pI3\nPj7O+Pj4UI41yDn5DUyfY9/YvXwHUFV1/4x1lwMPAxur6tmTHMtz8pI0Swt9Tn43sDrJxUnOBm4A\ndswYYBXTgb/5ZIGXJI1e39M1VfVqks3AI0z/UtheVXuSbJq+ubYBdwEXAp9PEuBoVa1byMElSf31\nPV0z1DvzdI0kzdpCn66RJC1RRl6SGmbkJalhRl6SGmbkJalhRl6SGmbkJalhRl6SGmbkJalhRl6S\nGmbkJalhRl6SGmbkJalhRl6SGmbkJalhRl6SGmbkJalhRl6SGmbkJalhRl6SGmbkJalhRl6SGmbk\nJalhRl6SGmbkJalhRl6SGmbkJalhRl6SGmbkJalhRl6SGmbkJalhRl6SGjbyyE9MTHD48OFR360k\nLTmHDx9mYmJiXsdYNqRZBvbzK6/kGytXsmz9ev727ru5ZPXqUY8gSae1qakp7tl6D7v27+LAGw7M\n61ipqiGNNcCdJcfu7SXgX5cv54LbbuMf7rxzZDNI0unsvs/dx4OPPcihSw/B67tXjkFVZS7HG+h0\nTZKNSfYmmUyy5SRrHkiyL8lEkrX9jnke8E+HDvGnn/kM2z/1qVmOLUntue9z93H/xP0curwn8PPU\nN/JJzgK2AtcCbwNuTHLZjDXXAZdU1VuATcAXBx3gr196iRcfeIBnp6ZmNfhSNz4+vtgjnDbci+Pc\ni+POtL2Ympriwcce5KU/e2moxx3kkfw6YF9VPVdVR4GHgOtnrLke+ApAVe0CLkiyfNAhPnzoEP9+\n772DLm/CmfYNfCruxXHuxXFn2l7cs/We6VM0QzZI5FcA+3suH+hed6o1B0+w5qTOB47u3OmrbiSd\nkQ4fPsyu/buGdoqm12nzOvl3HDzI5OTkYo8hSSP3zDPPzPtVNCfT99U1STYAY1W1sXv5DqCq6v6e\nNV8EHq2qr3Uv7wX+sqoOzTjW6F7KI0kNmeurawZ5nfxuYHWSi4FfAjcAN85YswP4CPC17i+F380M\n/HyGlCTNTd/IV9WrSTYDjzB9emd7Ve1Jsmn65tpWVd9O8v4kU8DLwC0LO7YkaRAjfTOUJGm0FuSJ\n14V489RS1W8vktyU5Knux+NJ3r4Yc47CIN8X3XXvTnI0yQdHOd8oDfgz0knyZJKfJHl01DOOygA/\nI+cn2dFtxY+TfGgRxlxwSbYnOZTk6VOsmX03q2qoH0z/4pgCLgb+BJgALpux5jrgP7ufrwd2DnuO\n0+FjwL3YAFzQ/XzjmbwXPeu+D3wL+OBiz72I3xcXAP8NrOhevmix517EvfgY8On/3wfg18CyxZ59\nAfbiKmAt8PRJbp9TNxfikfyCv3lqCem7F1W1s6pe7F7cySzeX7DEDPJ9AXAr8HXgV6McbsQG2Yub\ngIer6iBAVb0w4hlHZZC9KKb/Egrd//66qv4wwhlHoqoeB357iiVz6uZCRH7B3zy1hAyyF70+DHxn\nQSdaPH33IsmbgA9U1ReAll+JNcj3xRrgwiSPJtmd5OaRTTdag+zFVuCtSZ4HngJuH9Fsp5s5dXPk\nf2pYJ5bkvUy/KumqxZ5lEX0W6D0n23Lo+1kGvBO4GjgXeCLJE1V1Zv2Rp2nXAk9W1dVJLgG+l+Ty\nqvr9Yg+2FCxE5A8Cq3our+xeN3PNm/usacEge0GSy4FtwMaqOtU/15ayQfbiXcBDScL0udfrkhyt\nqh0jmnFUBtmLA8ALVXUEOJLkMeAKps9ft2SQvbgF+DRAVT2b5OfAZcCPRjLh6WNO3VyI0zXH3jyV\n5Gym3zw184d0B/D3cOwdtSd881QD+u5FklXAw8DNVfXsIsw4Kn33oqr+ovvx50yfl//HBgMPg/2M\nfBO4KsnrkryB6Sfa9ox4zlEYZC+eA94H0D0HvQb42UinHJ1w8n/BzqmbQ38kX7556phB9gK4C7gQ\n+Hz3EezRqlq3eFMvjAH34jVfMvIhR2TAn5G9Sb4LPA28Cmyrqp8u4tgLYsDvi08CX+55aeFHq+o3\nizTygknyVaADvDHJL4BPAGczz276ZihJathp81coJUnDZ+QlqWFGXpIaZuQlqWFGXpIaZuQlqWFG\nXpIaZuQlqWH/B+0+jLk322bvAAAAAElFTkSuQmCC\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "or_set = [((0,0),0), ((0,1),1), ((1,0),1), ((1,1),1)]\n", + "plot_xys(or_set)\n", + "\n", + "(errs,_) = perceptron(or_set,100)\n", + "plt.figure()\n", + "plt.plot(errs)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXkAAAEACAYAAABWLgY0AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAADzZJREFUeJzt3H+I3Hedx/Hnq+YqbWkLvWLAxPTumkuLYq2iScDCja1c\n0wOJeH9cW61YlAtoVLg/TK20XVqr5p9D26JeJCiCEsEKl/MUK9Kl9GxihGyrZ9JNaolJKpH6oxd7\nKcTwvj92Lp2uSWZ2d3Y2+8nzAUP3O/PZ77z5svvMt9+Z2VQVkqQ2nbfQA0iS5o+Rl6SGGXlJapiR\nl6SGGXlJapiRl6SG9Y18kq1JjiR56gxrHkiyL8lEkmuHO6IkabYGOZP/KnDj6R5MchNwZVX9LbAB\n+PKQZpMkzVHfyFfV48Dvz7BkPfD17tqdwKVJlg5nPEnSXAzjmvwy4GDP9uHufZKkBeYLr5LUsCVD\n2Mdh4HU928u79/2ZJP6hHEmaharKbL5v0DP5dG+nsh14P0CStcAfqurIafc0durbRe+7iImJCarq\nnLjdc889Cz7D2XLzWHgszvVjsXv3br5z4YUUnPI2F4O8hfKbwI+BVUl+leT2JBuS/DNAVX0PeDbJ\nfuDfgA/PZpBlLy5j1apVs/lWSVrUrrrqKnYvXz4v++57uaaqbh1gzcY5TfESrF2xlgsuuGBOu5Gk\nxeiCCy5gyZo1HJ2c5OIh7/useOF16eRS7tp410KPMVKdTmehRzhreCxe5rF42bl2LN579918Zenw\n332eqtG9FpqkGHvlfZc8ewmb3ryJOz9+58jmkKSz0db77+c1mzfzrqNHX3F/mP8XXofvJVj65FID\nL0ldH/zUp/jNHXfwr0uX8j9D2ufIz+Qvet9FLP/f5axZsYa7PnIXK1euHNnzS9Ji8Mz+/Xzjvvs4\nvmMHbz58mH988cVZn8mPPPITExOsWrXKF1klqY9jx44xOTnJtddeu3giP8rnk6QWJFmE1+QlSfPO\nyEtSw4y8JDXMyEtSw4y8JDXMyEtSw4y8JDXMyEtSw4y8JDXMyEtSw4y8JDXMyEtSw4y8JDXMyEtS\nw4y8JDXMyEtSw4y8JDXMyEtSw4y8JDXMyEtSw4y8JDXMyEtSw4y8JDXMyEtSw4y8JDXMyEtSw4y8\nJDXMyEtSw4y8JDXMyEtSwwaKfJJ1SfYmmUyy6RSPX5Jke5KJJD9L8oGhTypJmrFU1ZkXJOcBk8AN\nwHPALuDmqtrbs+aTwCVV9ckklwNPA0ur6k/T9lX9nk+S9EpJqKrM5nsHOZNfDeyrqgNVdRzYBqyf\ntqaAi7tfXwz8dnrgJUmjN0jklwEHe7YPde/r9RDw+iTPAU8CHx/OeJKkuVgypP3cCOyuquuTXAn8\nMMk1VfXH6QvHxsZOft3pdOh0OkMaQZLaMD4+zvj4+FD2Ncg1+bXAWFWt627fAVRVbe5Z813gs1X1\nX93tHwGbquqn0/blNXlJmqH5via/C1iZ5Iok5wM3A9unrTkAvLM7zFJgFfDL2QwkSRqevpdrqupE\nko3AI0z9o7C1qvYk2TD1cG0BPg18LclT3W/7RFX9bt6mliQNpO/lmqE+mZdrJGnG5vtyjSRpkTLy\nktQwIy9JDTPyktQwIy9JDTPyktQwIy9JDTPyktQwIy9JDTPyktQwIy9JDTPyktQwIy9JDTPyktQw\nIy9JDTPyktQwIy9JDTPyktQwIy9JDTPyktQwIy9JDTPyktQwIy9JDTPyktQwIy9JDTPyktQwIy9J\nDTPyktQwIy9JDTPyktQwIy9JDTPyktQwIy9JDTPyktQwIy9JDRso8knWJdmbZDLJptOs6STZneTn\nSR4d7piSpNlIVZ15QXIeMAncADwH7AJurqq9PWsuBX4M/H1VHU5yeVU9f4p9Vb/nkyS9UhKqKrP5\n3kHO5FcD+6rqQFUdB7YB66etuRV4uKoOA5wq8JKk0Rsk8suAgz3bh7r39VoFXJbk0SS7ktw2rAEl\nSbO3ZIj7eQtwPXAR8ESSJ6pq/5D2L0mahUEifxhY0bO9vHtfr0PA81X1EvBSkseANwF/FvmxsbGT\nX3c6HTqdzswmlqTGjY+PMz4+PpR9DfLC66uAp5l64fXXwE+AW6pqT8+aq4EHgXXAq4GdwD9V1S+m\n7csXXiVphubywmvfM/mqOpFkI/AIU9fwt1bVniQbph6uLVW1N8kPgKeAE8CW6YGXJI1e3zP5oT6Z\nZ/KSNGPz/RZKSdIiZeQlqWFGXpIaZuQlqWFGXpIaZuQlqWFGXpIaZuQlqWFGXpIaZuQlqWFGXpIa\nZuQlqWFGXpIaZuQlqWFGXpIaZuQlqWFGXpIaZuQlqWFGXpIaZuQlqWFGXpIaZuQlqWFGXpIaZuQl\nqWFGXpIaZuQlqWFGXpIaZuQlqWFGXpIaZuQlqWFGXpIaZuQlqWFGXpIaZuQlqWFGXpIaZuQlqWED\nRT7JuiR7k0wm2XSGdW9LcjzJe4Y3oiRptvpGPsl5wEPAjcAbgFuSXH2adZ8DfjDsISVJszPImfxq\nYF9VHaiq48A2YP0p1n0U+DbwmyHOJ0mag0Eivww42LN9qHvfSUleC7y7qr4EZHjjSZLmYlgvvH4e\n6L1Wb+gl6SywZIA1h4EVPdvLu/f1eiuwLUmAy4Gbkhyvqu3TdzY2Nnby606nQ6fTmeHIktS28fFx\nxsfHh7KvVNWZFySvAp4GbgB+DfwEuKWq9pxm/VeB/6iq75ziser3fJKkV0pCVc3qCknfM/mqOpFk\nI/AIU5d3tlbVniQbph6uLdO/ZTaDSJKGr++Z/FCfzDN5SZqxuZzJ+4lXSWqYkZekhhl5SWqYkZek\nhhl5SWqYkZekhhl5SWqYkZekhhl5SWqYkZekhhl5SWqYkZekhhl5SWqYkZekhhl5SWqYkZekhhl5\nSWqYkZekhhl5SWqYkZekhhl5SWqYkZekhhl5SWqYkZekhhl5SWqYkZekhhl5SWqYkZekhhl5SWqY\nkZekhhl5SWqYkZekhhl5SWqYkZekhhl5SWqYkZekhg0U+STrkuxNMplk0ykevzXJk93b40neOPxR\nJUkzlao684LkPGASuAF4DtgF3FxVe3vWrAX2VNULSdYBY1W19hT7qn7PJ0l6pSRUVWbzvYOcya8G\n9lXVgao6DmwD1vcuqKodVfVCd3MHsGw2w0iShmuQyC8DDvZsH+LMEf8Q8P25DCVJGo4lw9xZkncA\ntwPXnW7N2NjYya87nQ6dTmeYI0jSojc+Ps74+PhQ9jXINfm1TF1jX9fdvgOoqto8bd01wMPAuqp6\n5jT78pq8JM3QfF+T3wWsTHJFkvOBm4Ht0wZYwVTgbztd4CVJo9f3ck1VnUiyEXiEqX8UtlbVniQb\nph6uLcBdwGXAF5MEOF5Vq+dzcElSf30v1wz1ybxcI0kzNt+XayRJi5SRl6SGGXlJapiRl6SGGXlJ\napiRl6SGGXlJapiRl6SGGXlJapiRl6SGGXlJapiRl6SGGXlJapiRl6SGGXlJapiRl6SGGXlJapiR\nl6SGGXlJapiRl6SGGXlJapiRl6SGGXlJapiRl6SGGXlJapiRl6SGGXlJapiRl6SGGXlJapiRl6SG\nGXlJapiRl6SGjTzyExMTHDt2bNRPK0mLzrFjx5iYmJjTPpYMaZaBPfv2t/Od5ctZsmYN7737bq5c\nuXLUI0jSWW3//v3c+9C97Dy4k0MXHprTvlJVQxprgCdLTj7bUeArS5dy6cc+xgfvvHNkM0jS2ez+\nL9zPg489yJGrjsCru3eOQVVlNvsb6HJNknVJ9iaZTLLpNGseSLIvyUSSa/vt82LgX44c4TWf+xxb\nP/OZGY4tSe25/wv3s3liM0eu6Qn8HPWNfJLzgIeAG4E3ALckuXrampuAK6vqb4ENwJcHHeBdR4/y\nwgMP8Mz+/TMafLEbHx9f6BHOGh6Ll3ksXnauHYv9+/fz4GMPcvSvjg51v4Ocya8G9lXVgao6DmwD\n1k9bsx74OkBV7QQuTbJ00CE+dOQI37jvvkGXN+Fc+wE+E4/FyzwWLzvXjsW9D907dYlmyAaJ/DLg\nYM/2oe59Z1pz+BRrTusS4PiOHb7rRtI56dixY+w8uHNol2h6nTXvk3/z4cNMTk4u9BiSNHJPP/30\nnN9Fczp9312TZC0wVlXrutt3AFVVm3vWfBl4tKq+1d3eC/xdVR2Ztq/RvZVHkhoy23fXDPI++V3A\nyiRXAL8GbgZumbZmO/AR4FvdfxT+MD3wcxlSkjQ7fSNfVSeSbAQeYeryztaq2pNkw9TDtaWqvpfk\nH5LsB14Ebp/fsSVJgxjph6EkSaM1Ly+8zseHpxarfsciya1JnuzeHk/yxoWYcxQG+bnorntbkuNJ\n3jPK+UZpwN+RTpLdSX6e5NFRzzgqA/yOXJJke7cVP0vygQUYc94l2ZrkSJKnzrBm5t2sqqHemPqH\nYz9wBfAXwARw9bQ1NwH/2f16DbBj2HOcDbcBj8Va4NLu1+vO5WPRs+5HwHeB9yz03Av4c3Ep8N/A\nsu725Qs99wIei08Cn/3/4wD8Fliy0LPPw7G4DrgWeOo0j8+qm/NxJj/vH55aRPoei6raUVUvdDd3\nMIPPFywyg/xcAHwU+Dbwm1EON2KDHItbgYer6jBAVT0/4hlHZZBjUUz9JRS6//1tVf1phDOORFU9\nDvz+DEtm1c35iPy8f3hqERnkWPT6EPD9eZ1o4fQ9FkleC7y7qr4EtPxOrEF+LlYBlyV5NMmuJLeN\nbLrRGuRYPAS8PslzwJPAx0c029lmVt0c+Z8a1qkleQdT70q6bqFnWUCfB3qvybYc+n6WAG8Brgcu\nAp5I8kRVnVt/5GnKjcDuqro+yZXAD5NcU1V/XOjBFoP5iPxhYEXP9vLufdPXvK7PmhYMcixIcg2w\nBVhXVWf637XFbJBj8VZgW5Iwde31piTHq2r7iGYclUGOxSHg+ap6CXgpyWPAm5i6ft2SQY7F7cBn\nAarqmSTPAlcDPx3JhGePWXVzPi7XnPzwVJLzmfrw1PRf0u3A++HkJ2pP+eGpBvQ9FklWAA8Dt1XV\nMwsw46j0PRZV9Tfd218zdV3+ww0GHgb7Hfl34Lokr0pyIVMvtO0Z8ZyjMMixOAC8E6B7DXoV8MuR\nTjk64fT/Bzurbg79TL788NRJgxwL4C7gMuCL3TPY41W1euGmnh8DHotXfMvIhxyRAX9H9ib5AfAU\ncALYUlW/WMCx58WAPxefBr7W89bCT1TV7xZo5HmT5JtAB/jLJL8C7gHOZ47d9MNQktSws+avUEqS\nhs/IS1LDjLwkNczIS1LDjLwkNczIS1LDjLwkNczIS1LD/g9SqDiemnPSywAAAABJRU5ErkJggg==\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\nrkJggg==\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "xor_set = [((0,0),0), ((0,1),1), ((1,0),1), ((1,1),0)]\n", + "plot_xys(xor_set)\n", + "\n", + "(errs,_) = perceptron(xor_set,100)\n", + "plt.figure()\n", + "plt.plot(errs)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation error: 0.0\n" + ] + }, + { + "data": { + "image/png": "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\nMKATESXE/wMMl/sJoN5h8wAAAABJRU5ErkJggg==\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\nXXkODZYAAAAASUVORK5CYII=\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "noise_chance = 0.0\n", + "N = 100\n", + "xys = [(uniform(0,10),uniform(0,10)) for _r in range(0,N)]\n", + "secret_f = lambda x: x*2 - 1\n", + "dataset = [(xy,(1 if (secret_f(xy[0]) <= xy[1] or uniform(0,1)\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0mlabels_index\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m{\u001b[0m\u001b[0;34m}\u001b[0m \u001b[0;31m# dictionary mapping label name to numeric id\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mlabels\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;31m# list of label ids\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0;32mfor\u001b[0m \u001b[0mname\u001b[0m \u001b[0;32min\u001b[0m \u001b[0msorted\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mos\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlistdir\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mTEXT_DATA_DIR\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 5\u001b[0m \u001b[0mpath\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mos\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpath\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mTEXT_DATA_DIR\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mos\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpath\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0misdir\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpath\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mNameError\u001b[0m: name 'os' is not defined" + ] + } + ], + "source": [ + "texts = [] # list of text samples\n", + "labels_index = {} # dictionary mapping label name to numeric id\n", + "labels = [] # list of label ids\n", + "for name in sorted(os.listdir(TEXT_DATA_DIR)):\n", + " path = os.path.join(TEXT_DATA_DIR, name)\n", + " if os.path.isdir(path):\n", + " label_id = len(labels_index)\n", + " labels_index[name] = label_id\n", + " for fname in sorted(os.listdir(path)):\n", + " if fname.isdigit():\n", + " fpath = os.path.join(path, fname)\n", + " f = open(fpath)\n", + " texts.append(f.read())\n", + " f.close()\n", + " labels.append(label_id)\n", + "\n", + "print('Found %s texts.' % len(texts))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "anaconda-cloud": {}, + "kernelspec": { + "display_name": "Python [Root]", + "language": "python", + "name": "Python [Root]" + }, + "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.5.2" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/projects/PAPER.txt b/projects/PAPER.txt new file mode 100644 index 0000000..f958eac --- /dev/null +++ b/projects/PAPER.txt @@ -0,0 +1,65 @@ +Sentiment Analysis + +1. Background +The exponential growth of users on social media platforms inevitably generates vast amounts of public opinion, ranging from product reviews to concerns about political changes. Government bodies and companies can gain significant insight by analyzing the attitudes of these comments. This automated mining of text to deduce the attitude of the writer is known as sentiment analysis or opinion mining. Research in natural language processing has led to comparative studies on the specific approaches that are applied throughout sentiment analysis. + +Often times in the online community, the online reputation of a product dictates its performance in the market. Companies can mine product reviews and forums to track the complaints of dissatisfied customers or to track the popular trends that people are inclined to be satisfied with. Sentiment analysis is often used to track the sentiment of bloggers because they play a large role in shifting the opinions of their readers. Governments and political parties search forums to see the shifts in public opinion towards a certain idea or political figure. This concept can also be used to track threats that are directed towards the government by analyzing text for large amounts of negative polarity. Another application that is being slowly implement can also be to search online discussion boards for those at risk of suicide by and severe depression. The applications of sentiment analysis are endless and are continuing to be implemented in various fields. + +2. Branches +Sentiment analysis falls under the larger canopy of natural language processing, a branch of artificial intelligence. Natural language processing focuses on human and computer interaction and branches out into a variety of fields such as parsing, speech recognition, and other fields including sentiment analysis. Sentiment analysis itself, also branches into various subfields. + +All of the sub branches of sentiment analysis all have specific tasks regarding sentiment. Subjectivity definition analyzes the text to see if the text contains any opinions. Aspect based sentiment summarization assigns star ratings or scores to a product based on the text it analyzes. Text summarization for opinions analyzes large segments of text and generates sentences to summarize it. Another branch known as contrastive viewpoint summarization emphasizes contradicting opinions apparent in the text. Product feature extraction specifically analyzes reviews and extracts the features of the product from the text. Opinion spam sifts through text to identify fake or bogus opinions. And lastly, there is sentiment prediction, which determines the polarity of the text. Often times sentiment prediction is referred to as sentiment analysis and there is no differentiation between the branches. + +2.1 Approaches +Sentiment analysis or more specifically, “sentiment prediction”, groups the emotions of a text into three categories: positive, negative, or neutral. Classification can occur on three levels, document level, sentence level, or word/feature level. This classification correlates to how the input will be broken down. There are various approaches that can be taken to break down text but the three main families are lexical based, machine learning, and hybrid. This paper will expand individually on lexical and machine approaches. + +3. Lexical +Lexical means relating to the words of a language, so the process relies on individual words of the input. This approach is able to cover a broader range of words because it has access to such a large network of words but also when using lexicons there are finite number words in the lexicon, which can also prove to be a disadvantage. Lexical approach is also unsupervised learning because there are no data sets involved. + +The lexical approach is one broad format and there are two specific techniques that can be used called dictionary based or corpus based approach. In a basic lexical format there is a certain text inputted and each word is tokenized, meaning that each word is identified and given a token. Each token is then matched to a word in the dictionary and if the word is correlated to positive then a score is incremented, but if the word is negative then the score is decremented. At the end if the score is above a certain threshold then the overall polarity of the input is positive. But if the majority of the words registered as neutral than the input is registered as neutral overall. + +3.1 Dictionary Based + The dictionary-based approach only affects the word bank in which the words are compared in the lexical approach. In the dictionary approach, an expert picks a group of opinion words, known as seeds, which are already tagged with polarities. Then the program uses Word Net to expand on the collection, by collecting synonyms and antonyms to the words, which correlate to the polarities of the word. Then it proceeds to iterate through all the words till it exhausts its options. Afterwards the same process of tokenizing, word matching to the new dictionary, and score incrementing occurs. + +3.2 Corpus Based +The corpus based differs from the dictionary based because instead of a group of pre picked words, the word bank comes from a corpus with tagged sentiments. Corpus based has an advantage over dictionary based because it is better able to pick up the polarities of slang and online jargon, which the dictionary based approach would not be able to tackle because the dictionary only expands off of previously picked words. + +It is important to realize that the dictionary and corpus based approaches only differ in the word bank that the lexical approach uses and the rest of the lexical process is the same for both techniques. + +4. Machine Learning + +The machine learning approach to sentiment analysis is often viewed as a more efficient because it can be trained to for specific purposes and domains. This approach requires two data sets, a training data set to learn as well as test data set to validate the performance of the algorithm. But unlike the lexicon approach is has a hard time being applied to new data because it needs to have a new set of training data. In machine learning the algorithm trains to find patterns that it can then apply to random data that it has never seen before. There are a variety of techniques used in machine learning for sentiment analysis such as: bayseian networks, support vector machines, neural networks, etc. + +In sentiment analysis, especially for micro blogs such as twitter, the input data is pre-processed meaning the data is cleaned up. One step is called stop word removal, so small words or prepositions (the, and, before, while, so, etc.) are removed. Another stem called stemming takes all the different tenses of a word and condenses them to the root tense. Words such a walker or walking would be condensed to the word walk. + +5. Conclusion + +Sentiment Analysis is a constantly growing field because it is proven to be such a valuable technique to apply to user generated content. New techniques are being explored to generate more efficient sentiment analysis processes. This paper only expanded on one particular technique but there are many others to explore. + + + + + + + + + + + + + +References + +[1] Agarwal, Apoorv, Boyi Xie, Ilia Vovsha, Owen Rambow, and Rebecca Passonneau. "Sentiment Analysis Based on Dictionary Approach." (2016): 1-9. Columbia University. Web. + +[2] Collomb, Anais, Crina Costea, Damien Joyeux, Omar Hasan, and Lionel Brunie. "A Study and Comparison of Sentiment Analysis Methods for Reputation Evaluation." (n.d.): 5-10. Web. + +[3] Vohra, S.M., and J.B Teraiya. "A Comparative Study of Sentiment Analysis Techniques." Journal of Information, Knowledge, and Research in Computer Engineering 02.02 (2015): 313-17. Web. + +[4] Thakkar, Harsh, and Dhiren Patel. "Approaches for Sentiment Analysis on Twitter: A State-of-Art Study." (n.d.): 1-6. Web. + +[5] D'Andrea, Alessia, Fernando Ferri, and Patrizia Grifoni. "Approaches, Tools and Applications for Sentiment Analysis Implementation." Trans. Tiziana Guzzo. International Journal of Computer Applications 125.3 (2015): 26-33. Web. + +[6] Bhonde, Reshma, Binita Bhagwat, Sayali Ingulkar, and Apeksha Pande. "Sentiment Analysis Based on Dictionary Approach." International Journal of Emerging Engineering Research and Technology 3.1 (2015): 51-54. Web. + + diff --git a/projects/class-projects/Chappidi.txt b/projects/class-projects/Chappidi.txt new file mode 100644 index 0000000..d8ce4b7 --- /dev/null +++ b/projects/class-projects/Chappidi.txt @@ -0,0 +1,13 @@ +Project Proposal + +Group: Individual + +Topic: Paper on Sentiment Analysis + +Goal: + +1. Discuss Sentiment Analysis in a Broad perspective 2. Detail and Compare Systems, Approaches, and Techniques used in Sentiment Analysis 3. Discuss why people use this (surveillance, customer service, etc. ), How it fits into NLP + +How: Reading alot of papers? and reseraching + +Halfway: Doing 1, 2, 3 of the goal