{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "Let's define our initial geometry." ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": true }, "outputs": [], "source": [ "A = -50 + 0j\n", "B = 50 + 0j\n", "M = 0 + 0j" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we compute the dividing points of the marsh sections." ] }, { "cell_type": "code", "execution_count": 182, "metadata": { "collapsed": true }, "outputs": [], "source": [ "from math import sqrt" ] }, { "cell_type": "code", "execution_count": 183, "metadata": { "collapsed": false }, "outputs": [], "source": [ "marsh_dx = 50 / sqrt(2) * 2 / 5" ] }, { "cell_type": "code", "execution_count": 184, "metadata": { "collapsed": true }, "outputs": [], "source": [ "marsh_middle = 50 / sqrt(2)" ] }, { "cell_type": "code", "execution_count": 185, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[-35.35533905932737,\n", " -21.213203435596423,\n", " -7.0710678118654755,\n", " 7.071067811865468,\n", " 21.21320343559642,\n", " 35.35533905932737]" ] }, "execution_count": 185, "metadata": {}, "output_type": "execute_result" } ], "source": [ "marsh_points = [i * marsh_dx - marsh_middle for i in range(6)]\n", "marsh_points" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can compute the $y$ coordinate of a point $x$ on marsh line $i$ using this formula:\n", "\n", "$$\n", "y = x - x_m^i\n", "$$\n", "\n", "Where $x_m^i$ is a seed point from the above list.\n", "\n", "This is the logic of the function below:" ] }, { "cell_type": "code", "execution_count": 188, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def compute_coordinate(x, line_index):\n", " \"\"\"Returns point on line defined by line_index and with given x coordinate.\"\"\"\n", " return x + 1j * (x - marsh_points[line_index])" ] }, { "cell_type": "code", "execution_count": 189, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(-35.35+0.005339059327369j)" ] }, "execution_count": 189, "metadata": {}, "output_type": "execute_result" } ], "source": [ "compute_coordinate(-35.35, 0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In each section of the marsh, the trajectories are straight lines. \n", "\n", "So the total time is computed as a sum of distances / speeds." ] }, { "cell_type": "code", "execution_count": 190, "metadata": { "collapsed": true }, "outputs": [], "source": [ "speeds = [10, 9, 8, 7, 6, 5, 10]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can use the `abs` function for computing the distances since we use complex numbers." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's see if we can replicate the travel time from the example." ] }, { "cell_type": "code", "execution_count": 191, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[(-50+0j),\n", " (-35.35533905932737+0j),\n", " (-21.213203435596423+0j),\n", " (-7.0710678118654755+0j),\n", " (7.071067811865468+0j),\n", " (21.21320343559642+0j),\n", " (35.35533905932737+0j),\n", " (50+0j)]" ] }, "execution_count": 191, "metadata": {}, "output_type": "execute_result" } ], "source": [ "points = [A] + [compute_coordinate(point, ind) for ind, point in enumerate(marsh_points)] + [B]\n", "points" ] }, { "cell_type": "code", "execution_count": 192, "metadata": { "collapsed": true }, "outputs": [], "source": [ "time = lambda points, speeds: sum(abs(from_ - to_) / speed_ for from_, to_, speed_ in zip(points[:-1], points[1:], speeds))" ] }, { "cell_type": "code", "execution_count": 193, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "13.473802361543434" ] }, "execution_count": 193, "metadata": {}, "output_type": "execute_result" } ], "source": [ "time(points, speeds)" ] }, { "cell_type": "code", "execution_count": 194, "metadata": { "collapsed": true }, "outputs": [], "source": [ "distance = lambda points: sum(abs(from_ - to_) for from_, to_ in zip(points[:-1], points[1:]))" ] }, { "cell_type": "code", "execution_count": 195, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "100.0" ] }, "execution_count": 195, "metadata": {}, "output_type": "execute_result" } ], "source": [ "distance(points)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ok, we're matching. So now, let's minimize this. It could definitely be interesting to do an autodiff with that." ] }, { "cell_type": "code", "execution_count": 196, "metadata": { "collapsed": true }, "outputs": [], "source": [ "from random import random, randint" ] }, { "cell_type": "code", "execution_count": 197, "metadata": { "collapsed": true }, "outputs": [], "source": [ "from math import exp" ] }, { "cell_type": "code", "execution_count": 198, "metadata": { "collapsed": false }, "outputs": [], "source": [ "random_sign = lambda : (lambda r: (r - 0.5)/abs(r - 0.5))(random())" ] }, { "cell_type": "code", "execution_count": 199, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "1.0" ] }, "execution_count": 199, "metadata": {}, "output_type": "execute_result" } ], "source": [ "random_sign()" ] }, { "cell_type": "code", "execution_count": 200, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def modify_points(points, index, dx):\n", " \"\"\"Modifies points and returns copy.\"\"\"\n", " new_points = [p for p in points]\n", " p = compute_coordinate(new_points[index].real + dx, index-1)\n", " new_points[index] = p\n", " return new_points" ] }, { "cell_type": "code", "execution_count": 201, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[(-50+0j),\n", " (-35.35533905932737+0j),\n", " (-21.213203435596423+0j),\n", " (-7.0710678118654755+0j),\n", " (7.071067811865468+0j),\n", " (21.21320343559642+0j),\n", " (35.35533905932737+0j),\n", " (50+0j)]" ] }, "execution_count": 201, "metadata": {}, "output_type": "execute_result" } ], "source": [ "points" ] }, { "cell_type": "code", "execution_count": 202, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[(-50+0j),\n", " (-35.35533905932737+0j),\n", " (-21.213203435596423+0j),\n", " (-7.0710678118654755+0j),\n", " (7.071067811865468+0j),\n", " (21.21320343559642+0j),\n", " (35.36533905932737+0.00999999999999801j),\n", " (50+0j)]" ] }, "execution_count": 202, "metadata": {}, "output_type": "execute_result" } ], "source": [ "modify_points(points, 6, 0.01)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Our improvement procedure is simple: choose a point, move it by dx and keep the arrangement if it's better than the previous one (hillclimbing, inspired by [Norvig's gesture typing](http://nbviewer.jupyter.org/url/norvig.com/ipython/Gesture%20Typing.ipynb))." ] }, { "cell_type": "code", "execution_count": 229, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def improve(initial_points, max_dx, steps=1000):\n", " \"\"\"Hillclimbing strategy to find best trajectory.\"\"\"\n", " points = initial_points\n", " current_time = time(points, speeds)\n", " for step in range(steps):\n", " dx = random_sign() * max_dx * exp(-step / steps * 20)\n", " new_points = modify_points(points, randint(1, 6), dx)\n", " if time(new_points, speeds) < current_time:\n", " current_time = time(new_points, speeds)\n", " points = new_points\n", " return points" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's now run our problem:" ] }, { "cell_type": "code", "execution_count": 230, "metadata": { "collapsed": true }, "outputs": [], "source": [ "initial_points = points\n", "new_points = improve(initial_points, 10., steps=100000)" ] }, { "cell_type": "code", "execution_count": 231, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "13.126510858558497" ] }, "execution_count": 231, "metadata": {}, "output_type": "execute_result" } ], "source": [ "time(new_points, speeds)" ] }, { "cell_type": "code", "execution_count": 232, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "102.13458074876188" ] }, "execution_count": 232, "metadata": {}, "output_type": "execute_result" } ], "source": [ "distance(new_points)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's look at the optimal solution that was found:" ] }, { "cell_type": "code", "execution_count": 233, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def plot_points(points):\n", " \"\"\"plots some points\"\"\"\n", " plt.plot([p.real for p in points], [p.imag for p in points], '-o')" ] }, { "cell_type": "code", "execution_count": 234, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "%matplotlib inline" ] }, { "cell_type": "code", "execution_count": 235, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(-55.0, 55.0, -4.5411298101973614, 5.6681232353269273)" ] }, "execution_count": 235, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\nAAAASUVORK5CYII=\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plot_points(points)\n", "plot_points(new_points)\n", "plt.axis('equal')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's round our answer to print it:" ] }, { "cell_type": "code", "execution_count": 236, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "13.1265108586" ] }, "execution_count": 236, "metadata": {}, "output_type": "execute_result" } ], "source": [ "round(time(new_points, speeds), 10)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.2" } }, "nbformat": 4, "nbformat_minor": 0 }