diff --git a/agents.py b/agents.py index edab6891c..5375c723c 100644 --- a/agents.py +++ b/agents.py @@ -35,7 +35,7 @@ # # Speed control in GUI does not have any effect -- fix it. -from grid import distance_squared, turn_heading +from utils import distance_squared, turn_heading from statistics import mean import random diff --git a/grid.ipynb b/grid.ipynb deleted file mode 100644 index fa823d322..000000000 --- a/grid.ipynb +++ /dev/null @@ -1,362 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, - "source": [ - "# Grid\n", - "\n", - "The functions here are used often when dealing with 2D grids (like in TicTacToe)." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Heading\n", - "\n", - "With the `turn_heading`, `turn_left` and `turn_right` functions an agent can turn around in a grid. In a 2D grid the orientations normally are:\n", - "\n", - "* North: (0,1)\n", - "* South: (0,-1)\n", - "* East: (1,0)\n", - "* West: (-1,0)\n", - "\n", - "In code:" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "orientations = [(1, 0), (0, 1), (-1, 0), (0, -1)]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We signify a left turn with a +1 and a right turn with a -1.\n", - "\n", - "The functions `turn_left` and `turn_right` call `turn_heading`, which then turns the agent around according to the input.\n", - "\n", - "First the code for `turn_heading`:" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "def turn_heading(heading, inc, headings=orientations):\n", - " return headings[(headings.index(heading) + inc) % len(headings)]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can now use the function to turn left:" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(-1, 0)\n" - ] - } - ], - "source": [ - "print(turn_heading((0, 1), 1))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We were facing north and we turned left, so we are now facing west.\n", - "\n", - "Let's now take a look at the other two functions, which automate this process:" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "def turn_right(heading):\n", - " return turn_heading(heading, -1)\n", - "\n", - "def turn_left(heading):\n", - " return turn_heading(heading, +1)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The first one turns the agent right, so it passes -1 to `turn_heading`, while the second one turns the agent left, so it passes +1.\n", - "\n", - "Let's see what happens when we are facing north and want to turn left and right:" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(-1, 0)\n", - "(1, 0)\n" - ] - } - ], - "source": [ - "print(turn_left((0, 1)))\n", - "print(turn_right((0, 1)))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "When we turn left from north we end up facing west, while on the other hand if we turn right we end up facing east." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Distance\n", - "\n", - "The function returns the Euclidean Distance between two points in the 2D space." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "collapsed": true, - "deletable": true, - "editable": true - }, - "outputs": [], - "source": [ - "import math\n", - "\n", - "def distance(a, b):\n", - " \"\"\"The distance between two (x, y) points.\"\"\"\n", - " return math.hypot((a[0] - b[0]), (a[1] - b[1]))" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, - "source": [ - "For example:" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "5.0\n" - ] - } - ], - "source": [ - "print(distance((1, 2), (5, 5)))" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, - "source": [ - "### Distance Squared\n", - "\n", - "This function returns the square of the distance between two points." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "collapsed": true, - "deletable": true, - "editable": true - }, - "outputs": [], - "source": [ - "def distance_squared(a, b):\n", - " \"\"\"The square of the distance between two (x, y) points.\"\"\"\n", - " return (a[0] - b[0])**2 + (a[1] - b[1])**2" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, - "source": [ - "For example:" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "25\n" - ] - } - ], - "source": [ - "print(distance_squared((1, 2), (5, 5)))" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, - "source": [ - "### Vector Clip\n", - "\n", - "With this function we can make sure the values of a vector are within a given range. It takes as arguments three vectors: the vector to clip (`vector`), a vector containing the lowest values allowed (`lowest`) and a vector for the highest values (`highest`). All these vectors are of the same length. If a value `v1` in `vector` is lower than the corresponding value `v2` in `lowest`, then we set `v1` to `v2`. Similarly we \"clip\" the values exceeding the `highest` values." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "collapsed": true, - "deletable": true, - "editable": true - }, - "outputs": [], - "source": [ - "from utils import clip\n", - "\n", - "def vector_clip(vector, lowest, highest):\n", - " \"\"\"Return vector, except if any element is less than the corresponding\n", - " value of lowest or more than the corresponding value of highest, clip to\n", - " those values.\"\"\"\n", - " return type(vector)(map(clip, vector, lowest, highest))" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, - "source": [ - "For example:" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(0, 9)\n" - ] - } - ], - "source": [ - "print(vector_clip((-1, 10), (0, 0), (9, 9)))" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, - "source": [ - "The vector we wanted to clip was the tuple (-1, 10). The lowest allowed values were (0, 0) and the highest (9, 9). So, the result is the tuple (0,9)." - ] - } - ], - "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.5.2" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} diff --git a/grid.py b/grid.py deleted file mode 100644 index 7f3551e11..000000000 --- a/grid.py +++ /dev/null @@ -1,43 +0,0 @@ -# OK, the following are not as widely useful utilities as some of the other -# functions here, but they do show up wherever we have 2D grids: Wumpus and -# Vacuum worlds, TicTacToe and Checkers, and Markov Decision Processes. -# __________________________________________________________________________ -import math - -from utils import clip - -orientations = EAST, NORTH, WEST, SOUTH = [(1, 0), (0, 1), (-1, 0), (0, -1)] -turns = LEFT, RIGHT = (+1, -1) - - -def turn_heading(heading, inc, headings=orientations): - return headings[(headings.index(heading) + inc) % len(headings)] - - -def turn_right(heading): - return turn_heading(heading, RIGHT) - - -def turn_left(heading): - return turn_heading(heading, LEFT) - - -def distance(a, b): - """The distance between two (x, y) points.""" - xA, yA = a - xB, yB = b - return math.hypot((xA - xB), (yA - yB)) - - -def distance_squared(a, b): - """The square of the distance between two (x, y) points.""" - xA, yA = a - xB, yB = b - return (xA - xB)**2 + (yA - yB)**2 - - -def vector_clip(vector, lowest, highest): - """Return vector, except if any element is less than the corresponding - value of lowest or more than the corresponding value of highest, clip to - those values.""" - return type(vector)(map(clip, vector, lowest, highest)) diff --git a/mdp.py b/mdp.py index 012255e1e..6637108e5 100644 --- a/mdp.py +++ b/mdp.py @@ -6,8 +6,7 @@ dictionary of {state:number} pairs. We then define the value_iteration and policy_iteration algorithms.""" -from utils import argmax, vector_add -from grid import orientations, turn_right, turn_left +from utils import argmax, vector_add, orientations, turn_right, turn_left import random diff --git a/search.py b/search.py index f07e2454a..2d5d7a127 100644 --- a/search.py +++ b/search.py @@ -6,9 +6,9 @@ from utils import ( is_in, argmin, argmax, argmax_random_tie, probability, weighted_sampler, - memoize, print_table, DataFile, Stack, FIFOQueue, PriorityQueue, name + memoize, print_table, DataFile, Stack, FIFOQueue, PriorityQueue, name, + distance ) -from grid import distance from collections import defaultdict import math diff --git a/tests/test_grid.py b/tests/test_grid.py deleted file mode 100644 index 6cd5f6d24..000000000 --- a/tests/test_grid.py +++ /dev/null @@ -1,41 +0,0 @@ -import pytest -from grid import * - - -def compare_list(x, y): - return all([elm_x == y[i] for i, elm_x in enumerate(x)]) - - -def test_distance(): - assert distance((1, 2), (5, 5)) == 5.0 - - -def test_distance_squared(): - assert distance_squared((1, 2), (5, 5)) == 25.0 - - -def test_vector_clip(): - assert vector_clip((-1, 10), (0, 0), (9, 9)) == (0, 9) - - -def test_turn_heading(): - assert turn_heading((0, 1), 1) == (-1, 0) - assert turn_heading((0, 1), -1) == (1, 0) - assert turn_heading((1, 0), 1) == (0, 1) - assert turn_heading((1, 0), -1) == (0, -1) - assert turn_heading((0, -1), 1) == (1, 0) - assert turn_heading((0, -1), -1) == (-1, 0) - assert turn_heading((-1, 0), 1) == (0, -1) - assert turn_heading((-1, 0), -1) == (0, 1) - - -def test_turn_left(): - assert turn_left((0, 1)) == (-1, 0) - - -def test_turn_right(): - assert turn_right((0, 1)) == (1, 0) - - -if __name__ == '__main__': - pytest.main() diff --git a/tests/test_utils.py b/tests/test_utils.py index f90895799..25efa1c2c 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -2,6 +2,7 @@ from utils import * import random + def test_removeall_list(): assert removeall(4, []) == [] assert removeall(4, [1, 2, 3, 4]) == [1, 2, 3] @@ -162,6 +163,41 @@ def test_sigmoid_derivative(): assert sigmoid_derivative(value) == -6 +def compare_list(x, y): + return all([elm_x == y[i] for i, elm_x in enumerate(x)]) + + +def test_distance(): + assert distance((1, 2), (5, 5)) == 5.0 + + +def test_distance_squared(): + assert distance_squared((1, 2), (5, 5)) == 25.0 + + +def test_vector_clip(): + assert vector_clip((-1, 10), (0, 0), (9, 9)) == (0, 9) + + +def test_turn_heading(): + assert turn_heading((0, 1), 1) == (-1, 0) + assert turn_heading((0, 1), -1) == (1, 0) + assert turn_heading((1, 0), 1) == (0, 1) + assert turn_heading((1, 0), -1) == (0, -1) + assert turn_heading((0, -1), 1) == (1, 0) + assert turn_heading((0, -1), -1) == (-1, 0) + assert turn_heading((-1, 0), 1) == (0, -1) + assert turn_heading((-1, 0), -1) == (0, 1) + + +def test_turn_left(): + assert turn_left((0, 1)) == (-1, 0) + + +def test_turn_right(): + assert turn_right((0, 1)) == (1, 0) + + def test_step(): assert step(1) == step(0.5) == 1 assert step(0) == 1 diff --git a/utils.py b/utils.py index 1757526ff..aa24a55bd 100644 --- a/utils.py +++ b/utils.py @@ -65,6 +65,7 @@ def mode(data): [(item, count)] = collections.Counter(data).most_common(1) return item + # ______________________________________________________________________________ # argmin and argmax @@ -276,6 +277,48 @@ def isclose(a, b, rel_tol=1e-09, abs_tol=0.0): """Return true if numbers a and b are close to each other.""" return abs(a - b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol) + +# ______________________________________________________________________________ +# Grid Functions + + +orientations = EAST, NORTH, WEST, SOUTH = [(1, 0), (0, 1), (-1, 0), (0, -1)] +turns = LEFT, RIGHT = (+1, -1) + + +def turn_heading(heading, inc, headings=orientations): + return headings[(headings.index(heading) + inc) % len(headings)] + + +def turn_right(heading): + return turn_heading(heading, RIGHT) + + +def turn_left(heading): + return turn_heading(heading, LEFT) + + +def distance(a, b): + """The distance between two (x, y) points.""" + xA, yA = a + xB, yB = b + return math.hypot((xA - xB), (yA - yB)) + + +def distance_squared(a, b): + """The square of the distance between two (x, y) points.""" + xA, yA = a + xB, yB = b + return (xA - xB)**2 + (yA - yB)**2 + + +def vector_clip(vector, lowest, highest): + """Return vector, except if any element is less than the corresponding + value of lowest or more than the corresponding value of highest, clip to + those values.""" + return type(vector)(map(clip, vector, lowest, highest)) + + # ______________________________________________________________________________ # Misc Functions @@ -709,6 +752,7 @@ def __delitem__(self, key): if item == key: self.A.pop(i) + # ______________________________________________________________________________ # Useful Shorthands
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: