{ "metadata": { "name": "", "signature": "sha256:7e1dc3d25d48ec2ab2e25d99d695040ec757bf56643bd635d7bab0a05c465e8f" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "code", "collapsed": false, "input": [ "%matplotlib inline\n", "import pylab as pl\n", "from IPython.html.widgets import interact" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 1 }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this post, we're going to tackle the following problem: \n", "\n", "> Given a sequence of bricks, what is the best way to stack them on top of each other so as to cover the greatest possible horizontal distance?\n", "\n", "By \"stack them on top of each other\", we mean two things:\n", "\n", "- the bricks lie on top of each other (no glue or any kind of support)\n", "- they're stable (gravity doesn't make the construction collapse)\n", "\n", "This problem has some similarity with the Jenga game (see picture below), where players remove blocks of woods from an initially stable pyramid, until it collapses. The collapse happening to Jenga towers is essentially due to gravity: removing one block changes the static properties of the structure and destroys it." ] }, { "cell_type": "code", "collapsed": false, "input": [ "from IPython.display import Image\n", "Image(url=\"http://kristinruffin.files.wordpress.com/2014/03/jenga-falling-for-web.jpg\")" ], "language": "python", "metadata": {}, "outputs": [ { "html": [ "" ], "metadata": {}, "output_type": "pyout", "prompt_number": 2, "text": [ "" ] } ], "prompt_number": 2 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Other examples of this sort of stacking exist. As an example we can cite the [Nubian vault technique](http://en.wikipedia.org/wiki/Nubian_vault), whose key advantage Wikipedia says is the ability to be built \"without any support or shuttering\"." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This post is comprised of several sections. We first describe our model and data representation of this problem in Python. We then move on to write some graphic functions before designing the meat of this post: the \"stacking algorithm\". Finally, we examine applications of our code." ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Modelling assumptions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this post, we'll work with \"bricks\" that we will stack. Our modelling assumptions are as follows:\n", "\n", "- a brick of width $w$ and height $h$ is modelled as tuple $(w, h)$\n", "- a sequence of bricks to be stacked in a given order (the first on bottom, the last on top) is modelled as a list of bricks as defined above" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next, we're going to write a simple function that generates regular sequences of bricks, much like with Jenga, which will be used in the examples to follow. The function takes as arguments:\n", "\n", "- the width and height of the brick sequence to be generated\n", "- the number of bricks to generate" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def generate_brick_sequence(width, height, n):\n", " return [(width, height) for i in range(n)]" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 3 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Below, we test the output on an example case, generating a sequence of five bricks with width 3 and height 4:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "generate_brick_sequence(3, 4, 5)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 4, "text": [ "[(3, 4), (3, 4), (3, 4), (3, 4), (3, 4)]" ] } ], "prompt_number": 4 }, { "cell_type": "markdown", "metadata": {}, "source": [ "To continue, we will do two things, that will in time be translated to two functions.\n", "\n", "- a way of plotting brick sequences \n", "- a way to compute how to stack the bricks in a stable way for maximum range given a sequence of bricks as input\n", "\n", "Among these two things, the first is easy. And fun. So we're starting with that." ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Plotting brick sequences" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Below, we write a function that plots bricks using `Rectangles`, a functionality already provided by matplotlib. \n", "\n", "The way it works is the following. We take inputs made of:\n", "\n", "- a brick sequence\n", "- the horizontal shifts to apply to each brick\n", "\n", "And then we loop and draw each brick on top of each other, starting with the first one at the bottom and applying the horizontal shift given as an input. To make this function generic, we keep track of the total height, so as to stack bricks exactly above each other." ] }, { "cell_type": "code", "collapsed": false, "input": [ "from matplotlib.patches import Rectangle\n", "\n", "def plot_brick_sequence(brick_sequence, shifts):\n", " ax = pl.gca()\n", " total_height = 0.\n", " for brick, shift in zip(brick_sequence, shifts):\n", " ax.add_patch(Rectangle((shift, total_height), brick[0], brick[1]))\n", " total_height += brick[1]" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 5 }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can immediately try our function on an exemple sequence (that I just made up: the stacking is NOT physcally acceptable)." ] }, { "cell_type": "code", "collapsed": false, "input": [ "bricks = [(1, 2), (2, 3), (3, 4)]\n", "shifts = [0, 0.5, 2]\n", "plot_brick_sequence(bricks, shifts)\n", "pl.xlim(0, 10)\n", "pl.ylim(0, 10)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 6, "text": [ "(0, 10)" ] }, { "metadata": {}, "output_type": "display_data", "png": "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\nRK5CYII=\n", "text": [ "" ] } ], "prompt_number": 6 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now on to the hard part: the \"stacking algorithm\"." ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Writing a function that computes the stacking" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "How does one write such a stacking function? Answer: this situation is described by static mechanics. \n", "\n", "Let's assume we have two blocks: a \"top\" and a \"bottom\" block. The horizontal shift for the top block is $x_i$. The forces that apply to the top block are:\n", "\n", "- gravity, which is proportional to its mass $m_i$\n", "- the reaction force due to the bottom block (a contact pressure)\n", "\n", "In our model, we will assume that the blocks are rigid and thus replace the contact pressure by a point force located at the right most point of the bottom block. This is illustrated by the figure below." ] }, { "cell_type": "code", "collapsed": false, "input": [ "from IPython.display import SVG\n", "SVG(filename='files/forces.svg')" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 7, "svg": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " image/svg+xml\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " center of gravity\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " contact pressure\n", " gravity force\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " gravity force\n", " pressure force\n", " Original problem\n", " Simplified problem\n", " \n", "" ], "text": [ "" ] } ], "prompt_number": 7 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Under these hypotheses, equilibrium has a simple expression:\n", "\n", "- if the center of gravity is located to the left of the pressure force, i.e. the edge of the bottom block, the structure is in a stable state\n", "- if the center of gravity is located to the right of the pressure force, i.e. the edge of the bottom block, the structure is in an unstable state and will collapse\n", "\n", "This is illustrated by the figure below:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "SVG(filename='files/forces_equilibrium.svg')" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 8, "svg": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " image/svg+xml\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " gravity force\n", " pressure force\n", " Stable\n", " Unstable\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " gravity force\n", " pressure force\n", " \n", " \n", " \n", " \n", " \n", "" ], "text": [ "" ] } ], "prompt_number": 8 }, { "cell_type": "markdown", "metadata": {}, "source": [ "So the algorithm is the following:\n", "\n", "- we loop over the bricks to stack in a reverse order, starting with the last brick which goes on top\n", "- we calculate the maximum shift we can apply to the brick at the bottom given the top brick and its mass\n", "- we define a new top brick that consists of the previous top brick plus the previous bottom brick but positioned on top of each other\n", "- we apply the same procedure as above to our new top and bottom bricks\n", "\n", "To follow this algorithm, we will need to compute the position of the new center of gravity obtained by assembling bricks together. This is coded below:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def compute_horizontal_center_of_mass(brick_sequence, shifts):\n", " compute_mass = lambda b: b[0] * b[1]\n", " sum_xi_mi = sum([(shifts[i] + brick_sequence[i][0]/2.) * compute_mass(brick_sequence[i]) for i in range(len(brick_sequence))])\n", " sum_mi = sum([compute_mass(brick_sequence[i]) for i in range(len(brick_sequence))])\n", " return sum_xi_mi / sum_mi " ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 9 }, { "cell_type": "markdown", "metadata": {}, "source": [ "And finally, the algorithm:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def compute_brick_shifts(brick_sequence):\n", " shifts = []\n", " reverse_brick_sequence = brick_sequence[::-1]\n", " for index, brick in enumerate(reverse_brick_sequence):\n", " if index == 0:\n", " shifts.append(0.)\n", " else:\n", " previous_center_of_mass = compute_horizontal_center_of_mass(reverse_brick_sequence[:index], shifts)\n", " shifts.append(previous_center_of_mass - brick[0])\n", " min_shift = min(shifts)\n", " return [s - min_shift for s in shifts[::-1]]" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 10 }, { "cell_type": "markdown", "metadata": {}, "source": [ "To test our algorithm, we're going to examine a couple of solutions obtained when stacking rectangular bricks on top of each other. First, we're doing this with an interactive plot:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def plot_nbricks(l, n):\n", " bricks = generate_brick_sequence(l, 1, n)\n", " plot_brick_sequence(bricks, compute_brick_shifts(bricks))\n", " pl.xlim(0, n)\n", " pl.ylim(0, n)\n", " pl.grid(True)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 11 }, { "cell_type": "code", "collapsed": false, "input": [ "interact(plot_nbricks,\n", " l=(0.1, 4, 0.1),\n", " n=(2, 20))" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 12, "text": [ "" ] }, { "metadata": {}, "output_type": "display_data", "png": "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\nRK5CYII=\n", "text": [ "" ] } ], "prompt_number": 12 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's check the solution for 10, 20 and 40 bricks of 2:1 aspect ratios:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "pl.figure(figsize=(10, 4))\n", "format_plot = lambda : pl.xlim(0, 8) and pl.ylim(0, 40) and pl.grid(True);\n", "\n", "pl.subplot(131)\n", "plot_nbricks(2, 4)\n", "format_plot()\n", "\n", "pl.subplot(132)\n", "plot_nbricks(2, 13)\n", "format_plot()\n", "\n", "pl.subplot(133)\n", "plot_nbricks(2, 40)\n", "format_plot()" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "display_data", "png": "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\n", "text": [ "" ] } ], "prompt_number": 13 }, { "cell_type": "markdown", "metadata": {}, "source": [ "As one can see, the more bricks we stack, the higher the tower gets and the larger vaults we can build by simply stacking these bricks on top of each other. \n", "\n", "This being said we can now move on to some practical questions." ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Applying our tools to practical questions" ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "How far can we get?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "One of the questions we can ask ourselves after having written this is: is there a maximum horizontal distance that we can cross with such a structure of stacked bricks? Or is there a limit that we cannot overcome inside our model? \n", "\n", "To examine this question, I'll plot the total distance covered as a function of the number of bricks stacked. " ] }, { "cell_type": "code", "collapsed": false, "input": [ "l = 1\n", "number_of_bricks = pl.linspace(1, 200, 50, pl.int32)\n", "distances = pl.zeros_like(number_of_bricks)\n", "for index, n in enumerate(number_of_bricks):\n", " bricks = generate_brick_sequence(l, 1, int(n))\n", " shifts = compute_brick_shifts(bricks)\n", " distances[index] = max(shifts) + l/2." ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 14 }, { "cell_type": "code", "collapsed": false, "input": [ "pl.plot(number_of_bricks, distances)\n", "pl.title(\"distance reached as a function of number of {0} width bricks\".format(l))\n", "pl.xlabel('brick unit width (a. u.)')\n", "pl.ylabel('distance covered (a. u.)')\n", "pl.grid(True)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "display_data", "png": "iVBORw0KGgoAAAANSUhEUgAAAYgAAAEZCAYAAACNebLAAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3XecFPX9x/EXIEVpRyT0chQVNeohioqFC4IJiFiiP3ty\n6i8ajb3EmETF/BI1tqhoLNF4iQVrVFAUDXqIoCBNMIACgiId4ahShP398Zll5/a2zN3N7MzevZ+P\nxzx2Z3d25rvfnZ3PfMt8B0RERERERERERERERERERERERERERMSDUuD/nOfHAvPCS0reKAMu8mld\nw4GnfVqXX04FlgAbgUNyuN1zgbE53F7c0cB87PsOC2H7bouB40PadlvgA2ADcHeOtpntmFNK4viU\nynCq9v/ZBXSvwvJe98mqpiOl+jVdQQBizgQwAejl4TPDid5BLZfceebHuqLmHuAyoDnwaUDbKMT+\nrO7/xLPATwLaXiZ/BB7Evu+oELbv5ue+VVUXA6uAFsANKd7/MfA+UA4s8mmb2Y457vwoxk5ckt8P\nktd90pd0RDFAANQLOwEB2CPsBOSpekAXYE4Otxe2XH7fXKnO/t8VmJvh/U3AE6QOHkHKtI8Euf80\nqMKyvqQjCgGiNzAdK0Y+DzRxvVdMxQh9I/CNs+w8YADwU+Am4EysSD7DWfYC7E+2AViInY241/sN\ncC2wElgGlLje3xO4Fytel2NnFfF0HQlMAtYBM4H+Gb7bYuA3wCwnbfWzfD5TmgFOdj6zHlgAnOB6\nrxD40PnsWGBv13uZttkNGO987h2gdYbvUwC8gZ3VrQVGAx1d75c46d4AfAmck2Y9fYGPnPQsA0YA\nDVMs1xjLtwZYyWG+83pysbyURLG/mKr9th9gv+0HzvvlTvqPdD43wfXZfsAnzjJTgKNc75VhZ/7p\nfoNkv3S+z7fA60B75/WFzncb7awnVb4sBq7D8qQc+980dt5LTjNUzK9S4G/AGCxvJwDtgAew32Mu\nUJT0+b7Af7Hf/B+ubQEMxfapdcBE4KCkdCbv/8nS5Wkp8HPn8xux/3qyT7Azai+lh39i+wTYPrsL\nK5UC9MB+B6h8zEl1fIoBewFvAR2c9G3AfsMY0MjZ3gbgM6BPlrSdiP3uq4G7SBzcS7A8vQ9Yg9WU\nlFDx9z0QeNdJ/wrsWJisITASeMl53heYih1HVmD/h0hqBHwFXIUdBH4GbMf+aFDxx9oP+BrbmcHO\nsuI7/a3Av5LWPQQ7+AEcB2zGfuz4endgGd4AGOy839J5/2HgPewHjx/UG2E71hosKAEMdObTHVQX\nYztXR+xPle7z8QNJpjT3xf5E8frgDliegB2cFgA9sR34feAO571s2/wIq8JpiNW/bqByXsb9AGsP\naAI0A14EXnXea4rtcPs4822BA9Ks51Dn+9THzhLnYPtAOskBIXn+KSruM9X5bbtSuYqphMSf8QfY\nQfBcZ5mzsANmK+f9MuyAn+o3SDYAOxgUOdt+EAvScYtIfUB0v/8x9l9oheXfJSnSHJccIFZj+1Vj\nYBy2n56HHZj+D8ufuMXYAb6js60PSQTj3lgQPtz57M+dtDV0fda9/yfLlqfu3zWTgWQPEheQqK47\nB/u/PO/MX0hiPy4mcczJdnzqT+UqpuHAd9j/rR5wO/YfS2cX9hsUAJ2Bz0m0J5Zg+/KvsfxpQsXf\ntzmwHLjGSWsz7H8VT8fTzmfexAJ7PPB8hOU5WKA7IkP6QnUcsDTptYmkDhA9sZ3xeCqfVQ0nexvE\nq8CVrvVuoeLBYCWJg9YWKp4Jxd1I5YPn29gfI5VFVDx7rern3Wl+jPSR/n3gd675S7Gzm2zb7ILt\ngHu63nsW7+05RdgfGixArANOS1qfF1cD/87wvpcA4S5BVOe3LSRzgDgfOyi7TQJ+4TzP9BskexK4\n0zXfFDvwdHHmvQQId+nsL8AjKdIc586vp7B9Ke5yrHQQdxD2O7q35S7JDsYOrjjbTD6Az8NONOKf\nLUn7LbLnqft3zcRLgOiB7av1sHRfTOLY8k9sH4SKx5yqHJ/ihmMl8bgDsH0unV1UrAm4FPiP87wE\nC1BuJSR+37OBaWnWeytWMh0P3J/03ngnnZlqC4Dwq5g6UPkHSM6QuAXYjzgc+8OPJFEsT2UwtvN9\ni+3wQ6hY5P8W+3HitmARuDUWdRemWGdX4AxnffHpaBKlmlTcO1C2z2dKc6c0aYpb4Xr+nfNdsm2z\ngzP/neuz6fIf7GzjMezMcD22o7XE/nSbsWq+X2HVOm+QKOEk29d5f7mznj+TuTqmqqrz22bTASvB\nun3lvB6X7jdI1p6K+bwZS3PH1Iun5HVbqaxyPd+aNJ9qXe59+GsS37krVtXl3rc6UTFPkg+gbl7y\n1C8LsXwuwgLYG9h+ui8WCMan+ExVjk9uK13Pt2D7XKZjbbr8TX4vWWesKjeVeljp+EfYCYTbRdj3\nnotV652YbgNhB4jlVP5TdM2w/Ejsx+2K1fXFv3hyi31j4BWsPq8NVmQdg7eGmzXYn6Znive+xs6u\nW7mm5s520nGnLdPns6V5SZo0ZZNpm8ud+b1cy8fzNpXrsB2rLxYY+jvpi6fxHexsqB12Jvn3NOt5\nBKsW6ems5/dUbV/ckpTmeN1vNpl+22yfX0rlfbMrlQ8gXizDSixxTbEAWZ11JdtMxbzJdPLiVZek\n5/F0fo0Fd/e+1Qx4wbV8pnz1M0+9GI+dLDXEfoPx2Bl5K6wdJVm241Oq71ad3kPp8jfb+r4mfRfZ\nGPZ/vBOrwmrjem8BVgL9IXYMfZk0pf6wA8Qk4HusGqUhVj1xeJpl98WK3Y2Bbdgffafz3grsDxc/\nUDVypjXYmeRgKhbjMtmF1dfdhx14GmANZ42AZ4CTnHU1wM4MivF+5pfp89nS/CRWjzoA+906UvEM\nPV3wy7TNr7DGqtuw/D8Ga3RMpxl2hrkeqz++1fVeG6wRvSlWbbWZxO+Taj0bsQN9L6xYXRUzsTrU\nBlhd73EeP5fpt13tvN8jzWffwvbBs7EeOWc6aX/DtYzXniMjsd/yEGx/vh0rOSafTVfHp1jD5SHY\nbz086f2q9m6ph9WBd8R+89+TCAB/x0qMfZ3lmmJno15LM2PInKfZ0loP+44NneeNsd8ynfFYlVq8\nQ0KZMz+B1Afij8h8fFqJBfYWSWmqqutJtEFcScUAm8mb2H58Ffbdm5Nog4in427gOSxIxEvp52HB\nAey/HKNiiXu3sAPEDizTS7Ai9v9gZ9Fu8R+uMdbotxqL7K1JtNi/5Dx+ix3wNmIZ/SJW73g2Vh+X\nar2pXA/MxnpJfOtstz7WO+ZkrK55FfaHvg7v+Zju8/U8pPkT7KDyV6yxuoyKZx6xpOfx+WxpPgdr\npFoL3ILVx6ZzP3amsQYL7m+5tlMfayxbiuXZsaQ/8F/vbHcD8DjWWJjp90h+7yos6K1z1vNqluWT\nt53829bDgtWfsTrmtVieuPPxWyx4Xod9/+ud+bWudaf7DZKNA27G9vVlWMeEszKkORv3tr7A6sj/\ngzV4Jh/8ktOVKp3J7z+LnY0uxBri/+S8Nw3rjfUQlg/zsbYtr2fRa8mcp9muweiP/W5vYgfX77D2\ntXQ+wIJXPEBMxPbnD5KWi29zO5mPT/OwYP+lk+Z4STZTfqbyOpaXM7Dg+KTrc6nWFX9tIzAI+y8s\nx3774hTL/Ql4Devt1Aq7juIz5/N/xfa9bVnS6LsmwGTsbG8OqXt0FGMRbIYz/SFXiRMRkXDF60L3\nwIrQxyS9X0z4V4qKiEgKQVcxxbt3NcLqe9emWCYKV66KiEiSoANEfayKaSXWTzx5+IAYdiXlp1iD\nVboLq0REpJZqiVUxFSe93pxENdRgrJFFREQiIJfVOzdjvQzuybDMImzckgpVUR06dIgtW7YswKSJ\niNRKC6ne9VNAsFVMrbG+vWBdyQaRGEgvri2JIBXvS12pnWLZsmXEYjFNPky33npr6GmoTZPyU/kZ\n5Yn01/V4EuQQ1O2xPvX1nelprP93fFCxx4DTsb7y32MN2jXpCy4eLF68OOwk1CrKT38pP6MlyAAx\nGxu1M5l7oLCHnUlERHyyaRP4EWt1E5s6pqSkJOwk1CrKT38pP73ZuRNWroQlS2DhQpsWLEg8rl8P\nPWpUuWTy5RqEmFOfJiJSq8VisG4dfP21BYDkxyVLYPlyaNUKOneG7t0tGPTsmXhs3x7q14d69epB\nDY7zChB1TFlZGcXFxWEno9ZQfvqrLuTnjh3wzTd2wP/qq4qP8UBQvz507WoBoHNn6NLFpvh8p07Q\nONUtmJLUNECoiklExEebN9sBP920apWd4ccP+l26QJ8+cMopiaDQsmX27eSCShAiIlUQbwBOnr76\nyh43bbKDfteuNhUWJp536QIdO8IeOTo1VxWTiIiPtm61A/2iRYlH9/MtW+xg362bHfzjASD+vE0b\nqBeRI6sChFRJXajjzSXlp79ykZ+7dsGyZfDll3bA//LLxPNFi2DNGjvT79YtEQTcj1EKANmoDUJE\nJMl339lBP94FdOHCRCBYvNh6AHXvblO3bnD88YmA0LEjNGgQ9jeIhjyJgypBiEhF5eXW59/d/z8e\nDL791s74e/SwKd4VtHt3e71p07BTnxuqYhKRWmvtWpg/3w7+8+cnni9cCNu2WZ//+BS/BqB7d5UC\n4hQgpEpUZ+4v5WfNbdyYOPiPHVvGjh3Fu+d37IB99rGpZ8/E8x498qstICxqgxCRyNuxwxqAv/gC\nPv/cpi++sKm83A7+++5rF38NHAiXXGKBQEEgXPmS9SpBiOSBtWth3jwLAPPmJZ4vXgwdOsB++9m0\n77427befVQfVD/relnWUqphEJKd27bLhIObOtSkeCObNs2sIevVKTPGA0LMnNGkSdsrrHgUIqRLV\nmfurtufnunUwdapNn31mAeHzz6GgAPbfv+LUqxe0a1ezKqHanp+5pjYIEfHF5s0wYwZ88kliWrEC\neveGww+HQYPgyistEERlrCAJlkoQInXM9u1WCvjss4rT8uVw4IEWDOLT/vuru2g+UxWTiKQUi9kA\ncrNnJ6ZZs+xq4sJC+NGPKk49euRuEDnJDQUIqRLV8forKvm5aZMFgE8/tWnWLCsVNGsGBx1k08EH\n22OvXtFtMI5KftYWaoMQqUNiMVi61NoKZs5MBISlS6066JBDbDrzTAsGe+8ddooln6kEIRJRO3fa\nhWTxYBB/rFfPGo6Limw6+GDrSqrqIUmmKiaRWuD772HOHJg+3aZp06xk0KYNHHpoIiD07m13I9PV\nxeKFAoRUiep4/VWd/Ny5064niF9fMHWqtR907my3njz0UJuKimxY6rpE+6e/1AYhEmGxmI08OmWK\nXVcwdapVE3XoAIcdZtOZZ1owaN487NSKVKQShIiPVq2yQDB5ciIoNGsGfftaMDj8cCsl6EIzyQVV\nMYmEZPt2ayf4+GObPvrIhqY4/HALCH372vP27cNOqdRVChBSJarjrb6VK2HSJJg40QLCzJnQpk0Z\ngwYVc+SRcNRRNkKpRiatPu2f/lIbhEgAdu2yXkUTJ9o0aZLdxvKoo6BfP7jtNishTJsGOp5JbRVk\nCaIJMB5oDDQCXgduSrHcg8BgYAtQAsxIsYxKEBKo7dutAXnCBJsmTrSLzI4+OjHtv79KB5Jfol7F\ntBd24N8D+BC43nmMGwJc7jweATwAHJliPQoQ4qstW6zNYPx4CwiffGJ3MDv22MTUrl3YqRSpmZoG\niKDPh7Y4j42ABsDapPeHAf90nk8GCoC2AaepTisrKws7CaHYsgXGjYObb7aDf5s2cMstdivMG26A\nb76xK5UffBDOOMN7cKir+RkU5We0BN0GUR+YDvQAHgHmJL3fEVjimv8G6ASsDDhdUstt324NyePG\nwfvv29XJhxxi7QW33GLtCE2bhp1KkWjLVS+mlsBY4LdAmev10cCdwERn/j/Ab7Cg4qYqJslo1y7r\nVTRunE2TJlmPooEDYcAAa0NQQJC6Jl96Ma0H3gQOo2KAWAp0ds13cl6rpKSkhMLCQgAKCgooKira\n3R0uXizVfN2a79GjmHfegWeeKWP6dGjfvpjjj4d+/cq47DIYNiyx/CefhJ9ezWs+6PmysjJKS0sB\ndh8vayLIEkRr4HugHNgTK0HcBoxzLeNupD4SuB81UgeqLI/7mW/ZYo3K77wDY8faVcuDBsEJJ9hj\np065T1M+52cUKT/9FeUSRHusAbq+Mz2NBYdLnPcfA8ZgwWEBsBm4IMD0SB5asADGjLFp4kQbxO6E\nE+Bf/7KRTXU7TJHg6EpqiZRt2+CDDxJBYcMGGDLEpkGDoEWLsFMokj+ifh2EXxQgarFvv4U334RR\no+Ddd+GAA+DEEy0oFBXp4jSR6or6dRASMfEGrbAtWAD33gv9+0O3bvDqqzB0KMyfbxew/eEPVp0U\n9eAQlfysLZSf0aKxmCRnNm2C556DRx+F5cth2DD4zW+sG+qee4adOhFJpiomCdxnn1lQeO45OO44\nuPRSa0+IeulAJN9FuReT1GFbt8K//w2PPAJffgn/+78wa1Y4XVFFpHp0DlfHBFnH+/33do3CBRfY\nTXKeegquvhoWL7bhsWtjcFCdub+Un9GiEoTUSCxmYx6NHAkvvghdusDZZ8Of/2z3XRaR/KU2CKmW\nhQvtYrWnn4ZGjeCccyww7LNP2CkTkTi1QUjObNwIL78MpaV2t7VzzoGXXrLuqPXy5VRDRDxTG0Qd\nU9U63l27bLjsX/wCOneG11+Ha66BpUvhgQegT5+6HRxUZ+4v5We0qAQhKa1ebSWFxx+3axQuvBDu\nvttutCMidUO+nPupDSIHYjEoK7Og8PbbcMopcMklcMQRdbuUIJKvNBaT1Fh5uXVJffRRaNjQgsL5\n50NBQdgpE5GaCHospobAicBfgBeA553nJ6LqqbzkruP9/HO4/HLo3h2mTrUgMXs2XHGFgoNXqjP3\nl/IzWjIFiJuBT4ChwDzgH9j9HT4HTgKmAn8IOoHir127rPpoyBAb9qJVKxsK49ln7T7NqkoSkbhM\nh4Nh2D2j09Xt1MeCxyi/E5WCqphqaOtWu27hr3+Fxo3hqqvsuoUmTcJOmYgERW0QktGGDda2cP/9\ndr3CDTdYyUElBZHaL6z7QVySfREJ06pVdk+F7t3h00+tWumNNyAWK1Nw8JHqzP2l/IwWXShXyyxZ\nYo3MvXrZndqmTLH2hYMPDjtlIpJv8uVcUlVMWaxYAXfcAc88Y0NrX3MNtGsXdqpEJEy5GIvp1hSv\nxYA/Vnej4p81a+Cuu+DJJ204jDlzoG3bsFMlIrWBlyqmzcAmZ9oJDAYKA0yTeFBeDrfcAvvtZ7fy\nnDUL7rsve3BQHa+/lJ/+Un5Gi5cSxD1J83cD7wSQFvFg+3Z4+GG4/XY46SS7wK1bt7BTJSK1UXXq\npn4ATAF6+pyWTOp8G0QsBqNHw/XXQ8+ecM89cMABYadKRKIsF20Qs13P6wNtUPtDTs2aBddeC8uX\nw4gR8JOfhJ0iEakLvLRBnOSafgJ0AEYEmSgxq1bZwHmDBsFpp9n1DDUNDqrj9Zfy01/Kz2jxEiAW\nu6ZvgB3BJUfAxkt69FE48EBo1gzmzYPLLoM9NDyiiOSQroOImDlz4OKLLUj8/e8WJEREqiOsoTbE\nZ9u2wfDh0L+/3ev5ww8VHEQkXEEGiM7A+8B/gc+AK1MsUwysB2Y4U50cPnzCBCgqgpkzYcYMq06q\nH9Avozpefyk//aX8jJbq1mr/HfhllmV2ANcAM4FmwDTgXWBu0nLjsaHF65zNm2101VGj4MEHrSFa\nRCQqqls3dRh2w6CqeA3r/TTO9VoxcB3WQyqTWtcGMXOm3Y/hsMOs66ru4CYifgurDaKqwaEQ6A1M\nTno9BvQDPgXGALX+0q9du+ymPYMGwe9/D08/reAgItHkpYqpDfAb4EAgfv+xGDDA4zaaAS8DV2Hj\nOblNx9oqtmBjPL0G7JtqJSUlJRQWFgJQUFBAUVERxcXFQKLeMurzvXoVU1ICX39dxgMPwDnn5D49\n7jresPOjNswrP5WfUZovKyujtLQUYPfxsia8FD3eBV4ArsduFFQCrMaCRjYNgTeAt4D7PSy/COgD\nrE16Pe+rmMaMgYsusqG4b7kFGjYMJx1lZWW7dyypOeWnv5Sf/srFLUenA4cCs4D4bWemYu0Q2db9\nT+BbrLE6lbbAKqxE0hd4kdQjxeZtgNi5E377W3jhBbtXw3HHhZ0iEakrcjEW03bncQUwFFgGtPLw\nuaOB87DAMsN57XdAF+f5Y8DpwKXA91g101meUp0n1q+3huht26z76t57h50iERHvvESWk4AJWFvB\nCKAFMBwYFVyyKsm7EsSCBTBsGAwYYI3SYVUpJVMR3l/KT38pP/2VixLEaOexHOuWKlm8956VHIYP\nh0svDTs1IiLVkymyDAceAVameb898CtS35LUb3lTgnjkEQsMI0da6UFEJCxBliCmAs8DjbCG6uXO\nhtphjdbbqHy3uTprxw64+mp4/32YONFu6iMiks8yXSj3BvBjrOF4ItaQvAP4EDgTuw5iTNAJzAfb\ntsEZZ8DChfDRR9EODu5+5lJzyk9/KT+jxUsbxBKsJCEpbN0KP/sZNG5sYyo1ahR2ikRE/KH7QdTA\nli1wyinQqpVd4xCVnkoiIqD7QYRm0yY48URo2xaefVbBQURqHwWIatiwAQYPhm7doLQ0v24Fqjpe\nfyk//aX8jJZMh7YRrucxKhZTYqS+AVCtV15uweGQQ+Bvfwvuxj4iImHLVDdV4jz2w4bhfsFZ/gzs\nLnG/CjRlFUWiDWL9ehg4EI46Ch54AOrlSwuOiNRJuRisbzJwDNbFFWyE1g+BI6q70WoIPUB8/z2c\ndBJ07WoXwyk4iEjU5aKRugAbfymuufNanXLttTYy64gR+R0cVMfrL+Wnv5Sf0eKlefVO7ErqMme+\nPzYMR53xt7/Bu+/aRXDqrSQidYXXc+H22P0awKqcVgSTnLRCq2J69104/3wbPqNHj1CSICJSLbmo\nYqoPDAQOAV7Hxmbqm/ETtcTcuXDuufDiiwoOIlL3eAkQfwOOAs525jc5r9Vqa9bA0KFw11216y5w\nquP1l/LTX8rPaPHSBnEE0JvEXeHWYj2Zaq1t2+C002wAvpKSsFMjIhIOr91c+2HDf/cGfgi84zzP\nlZy2QVx4IaxbB6+8ogvhRCR/5eKOciOAV4E2wO3YfaT/UN0NRt3LL1uD9PTpCg4iUrdlOwTWBxYB\nNwJ3AMuAk4EXA05XKNasgSuugKeegqZNw05NMFTH6y/lp7+Un9GSrQSxC3gYKALmBp+ccF19NZx1\nFvTrF3ZKRETC56Vu6h7gY+AVbJC+MATeBjF6NFxzDcyaBXvtFeimRERyIhdjMW0C9gJ2Alud12JU\nHH4jaIEGiPJy+NGP7KY/xcWBbUZEJKdycaFcM2e5htg4TM3JbXAI3LXXwskn143goDpefyk//aX8\njBYvvZjqA+cC3YA/Al2AdsCUANOVM2PHwnvvwezZYadERCRavBQ9HsUaqwcAvYAfYNdBHBZgupIF\nUsW0YQMcdBA88QQMGuT76kVEQpWL6yBq7ZXUN95ogUHBQUSkMi9tENuBBq75H2Ilirz23nvwxhtw\n771hpyS3VMfrL+Wnv5Sf0eIlQCRfST0Ru2gum87A+9jtST8j/T2sHwTmA5+So+E7du2yC+Ieegha\ntszFFkVE8o/Xuqn9geOd5+PwdtFcO2eaifWEmgackvTZIcDlzuMRwAPAkSnW5WsbxGuvwZ/+BJ98\nkt93hxMRySRXYzGNBB6q4rpXkLix0CYsMHSgYoAYBvzTeT4Zu5VpW2BlFbflWSwGt98ON92k4CAi\nkomXKqZp2OB8X2JXVVen91IhVn00Oen1jsAS1/w3QKdqrN+z996DjRvh1FOD3Ep0qY7XX8pPfyk/\no8VLCaLUmfYGTgPuwq6F6OlxG82Al4GrsJJEsuTz+JR1SSUlJRQWFgJQUFBAUVERxc6VbfGdysv8\nHXfAySeX8cEH3pbXvOY1r/l8mS8rK6O0tBRg9/GyJqpSyXIE8D9YO8Ic4CQPn2kIvAG8Bdyf4v1H\ngTLgeWd+HtCfylVMvrRBTJkCp58OCxZAo0Y1Xp2ISKTlYqiNu7BeRn/EeiP1wVtwqAc8iQWTVMEB\nYBTwc+f5kUA5AbY/3HEH3HCDgoOIiBdeAsSX2D2pfwI8hR3EvTgaOA/4MXaR3QxgMHCJMwGMcda/\nAHgMuMxrwqvqv/+FSZPgoouC2kJ+iBdHxR/KT38pP6PFSxvEo9hNgo5z5suA0R4+9yHeAtDlHpap\nsb/8Ba68UkN5i4h45aVu6k7gcOBZZ/mzsPtT3xRgupLVqA1i8WLo0wcWLoSCAv8SJSISZbm4H8Rs\n7I5yO535BtjFbwdVd6PVUKMA8etfQ/PmcOedPqZIRCTictFIHcMuYIsrILw7y1XZypUwcqTdLU5U\nx+s35ae/lJ/R4qUN4g5gOjauUj2sG+pvg0yUn+6/H84+G9q2DTslIiL5xWvRowPWDhHDbhS0IvPi\nvqtWFVN5OfToAdOmgQ/XjIiI5JVcVDGdCmwBXseuW9iKXSwXeU88AUOGKDiIiFSHlwAxnIrXPpQ7\nr0Xea6/BeeeFnYpoUR2vv5Sf/lJ+RouXAJGqeNIgxWuRsnYtzJoF/fuHnRIRkfzkpW7qKWAd8LCz\n/K+BVkBJcMmqpMptEM8/D88+C6O9XNInIlIL5aIN4gpgB/ACNqjeVixIRNpbb1n7g4iIVI+XALEJ\nuBG7D8Rh2BXUm4NMVE3t2mUBYvDgsFMSParj9Zfy01/Kz2jxEiDyzrRp0Lq1ei+JiNREvtx0s0pt\nELfdZneNu+eeAFMkIhJxuWiDyDtqfxARqTkvAWI/YBzwX2f+YOwe1ZG0ejXMnQvHHBN2SqJJdbz+\nUn76S/kZLV4CxN+B3wHbnfnZwNmBpaiGxo6FAQN01zgRkZryUjc1Feu9NAPo7bw2ExsCPFc8t0Gc\ncw78+Mfwy18GnCIRkYjLRRvEaqCna/50YHl1NxiknTvhnXfUvVVExA9ebwn6GNYWsQy4Brg0yERV\n15Qp0KEM0zL2AAAPT0lEQVQDdOoUdkqiS3W8/lJ++kv5GS1e7gexEDgeaIYFlA2BpqgGxoxR7yUR\nEb94qZu6A/gLiRFdWwHXkdueTJ7aIPr0gb/+FY47LgcpEhGJuFzckzpVg7S7wToXsgaIFStg//1h\n1Spo2DBHqRIRibBcNFLXB5q45vcEIteJ9O23YeBABYdsVMfrL+Wnv5Sf0eKlDeJZ7EK5f2CR6ALg\nX0EmqjrU/iAi4i+vRY/BwEDsntTvAmMDS1FqGauYduyANm1gzhxo3z6HqRIRibCaVjF5KUEAvOVM\nkfTRR9Ctm4KDiIifvLRB/AyYj3Vv3ehMkerqqsH5vFMdr7+Un/5SfkaLlwBxFzAMaAE0d6YWQSaq\nqtT+ICLiPy91UxOBo6u5/n8AJwKrgINSvF8MvA586cy/AvwpxXJp2yC++QYOOcS6tzZoUM1UiojU\nQrlog5iK3Y/6NRIjusaAf3v47FPACDL3ehqPlVCq5eOPbWhvBQcREX95qWJqCXwHnAAMdaaTPK5/\nArAuyzI1uqvdihXQsWNN1lC3qI7XX8pPfyk/o8VLCaIkwO3HgH7Ap8BS4HpgTlVWsGoVtG0bQMpE\nROo4LwFiT+Ai4ADnebwx4EIftj8d6Axswa61eA3YN9WCJSUlFBYWAlBQUEBRURHFxcWsXAl77VVG\nWRkUFxcDibMQzVeeLy4ujlR68n1e+an8jNJ8WVkZpaWlALuPlzXhpXrnZWAucC5wG3CeM3+lx20U\nAqNJ3UidbBHQB1ib9HraRupTT4Xzz4fTTvOYGhGROiIXYzH1BG4GNgH/BIYAR1R3g0nakkh8X+d5\ncnDIaNUqu4pavImfbYg/lJ/+Un5Gi5cqpnjPpfVYKWAF8EOP6x8J9AdaA0uAW4H4cHqPYXenuxT4\nHqtmOsvjendbuVIBQkQkCF6KHr/Erk84CCjFbhx0M/BocMmqJG0VU4sWsGQJtGyZw9SIiOSBXNwP\nojuJC9kyvRaklAHiu++gVSt7rFejzrIiIrVPLtogXk7x2kvV3aCf4u0PCg7eqY7XX8pPfyk/oyVT\nG8T+WNfWAuA0LArFsHGYmmT4XM6o/UFEJDiZAsS+2BXTLal45fRGrF0idLpIrurifafFH8pPfyk/\noyVTgHjdmY4CPspNcqpGJQgRkeB4aYM4DatWaojdenQNcH6QifJKJYiqUx2vv5Sf/lJ+RouXAHEC\ndoOgocBioAdwQ4Bp8kwlCBGR4HgJEPFqqKFYj6b1JMZjCpVKEFWnOl5/KT/9pfyMFi9XUo8G5gFb\nsaue2zjPQ6cShIhIcLyUIH6L3VGuDzbsxmbg5CAT5ZVKEFWnOl5/KT/9pfyMlkwliOOxRumfkahS\nil+S5vWOcoHSQH0iIsHJdA3ybdjgeqWkbnO4IIgEpVFpqI2dO6FJExtmYw8vFWUiInVMLsZiioJK\nAWLVKjjwQFi9OqQUiYhEXE0DRKZz7+ucx3Q9lu6r7kb9oAbq6ikrK1NPER8pP/2l/IyWTAGiORYc\n9gMOB0ZhkWgoMCX4pGWmBmoRkWB5KXpMwO4it9GZbw6MAY4NKlEpVKpieu45GDUKnn8+h6kQEckj\nuRjuuw2wwzW/w3ktVCpBiIgEy0uA+BdWpTQc69k0Gbs3dajUBlE96mfuL+Wnv5Sf0eKlg+ifgbex\nKqUYUALMCDBNnqxaBT16hJ0KEZHaK2+7uQ4dChdfDMOGhZQiEZGIy0UbRCSpDUJEJFh5HSDUBlF1\nquP1l/LTX8rPaMnLABGLqZFaRCRoedkGsXEjtG8PmzaFmCIRkYirk20QKj2IiAQvLwOEGqirT3W8\n/lJ++kv5GS15GSBUghARCV5etkE89hhMmwaPPx5iikREIi7qbRD/AFYCszMs8yAwH/gU6O1lpSpB\niIgEL+gA8RTw0wzvDwF6AvsAFwOPeFmp2iCqT3W8/lJ++kv5GS1BB4gJwLoM7w8jMfDfZKAAyHro\nVwlCRCR4YTdSdwSWuOa/ATpl+5BKENWnu3X5S/npL+VntIQdIKByA0q6W5zuphKEiEjwvAz3HaSl\nQGfXfCfntUpKSkooLCwE4KuvCpg/v4gDDigGEvWW8bMPzaefd9fxRiE9+T6v/FR+Rmm+rKyM0tJS\ngN3Hy5rIRTfXQmA0cFCK94YAlzuPRwL3O4/Jdndz3b4dmjaFbdugfhTKP3mmTDeF95Xy01/KT3/V\ntJtr0AFiJNAfaI11d70VaOi895jz+BDW02kzcAEwPcV6dgeIpUvhsMNg+fIAUy0iUgvUNEAEXcV0\ntodlLq/KCtVALSKSG3lXSaMG6ppx1/FKzSk//aX8jJa8CxAqQYiI5EbejcV0992wYgXce2/IKRIR\nibioj8XkO5UgRERyI+8ChNogakZ1vP5SfvpL+RkteRcgVIIQEcmNvGuD6N0bnngC+vQJOUUiIhGn\nNggREQlEXgWIWAxWr4Yf/jDslOQv1fH6S/npL+VntORVgFi3DvbaCxo3DjslIiK1X161QcybByef\nDJ9/HnZyRESir061QaiLq4hI7uRVgFADdc2pjtdfyk9/KT+jJa8ChEoQIiK5k1dtELfcAg0awK23\nhp0cEZHoUxuEiIgEIq8ChNogak51vP5SfvpL+RkteRUgVIIQEcmdvGqD6NkT3noL9tkn7OSIiESf\n2iBERCQQeRMgtmyBHTugRYuwU5LfVMfrL+Wnv5Sf0ZI3AWL1ais91MuXSjERkTyXL4fb2OTJMS67\nDKZODTspIiL5oc60QaiLq4hIbuVNgFADtT9Ux+sv5ae/lJ/RkjcBQiUIEZHcyps2iKuuitGlC1x7\nbdhJERHJD2qDEBGRQAQdIH4KzAPmAzemeL8YWA/McKY/pFuR2iD8oTpefyk//aX8jJYgA0QD4CEs\nSBwAnA3sn2K58UBvZ/pTupWpBOGPmTNnhp2EWkX56S/lZ7QEGSD6AguAxcAO4Hng5BTLeaofUwnC\nH+Xl5WEnoVZRfvpL+RktQQaIjsAS1/w3zmtuMaAf8CkwBitppLRuHbRu7XcSRUQknT0CXHfMwzLT\ngc7AFmAw8Bqwb6oFCwpgjyBTW0csXrw47CTUKspPfyk/oyXIbq5HAsOxNgiAm4BdwF8yfGYR0AdY\nm/T6AqCHz+kTEantFgI9w05EKntgiSsEGgEzqdxI3ZZEkOqLtVeIiEgdMBj4HCsB3OS8dokzAfwa\n+AwLHpOwUoeIiIiIiEj1ZLvQTrJbDMzCLkSc4rz2A+Bd4AvgHaAglJRF3z+AlcBs12uZ8u4mbF+d\nB5yQozTmk1T5ORzr4Ri/WHaw6z3lZ2adgfeB/2I1MVc6r9eJfbQBVjVVCDQkdRuGZLcI22Hc7gJ+\n4zy/EbgzpynKH8diF3C6D2jp8u4AbB9tiO2zC8ijoWxyJFV+3gqkGmFN+ZldO6DIed4Mq87fnzqy\njx4FvO2a/60zSdUsAvZOem0e1kEAbCebl9MU5ZdCKh7Q0uXdTVQs5b6N2tRSKaRygLguxXLKz6p7\nDRiIj/tolKOHlwvtJLsY8B9gKvBL57W2WFEf51GDmHiXLu86YPtonPZX767ALpZ9kkR1iPKzagqx\n0tlkfNxHoxwgvFxoJ9kdje04g7FeY8cmvR9DeV1d2fJO+ZrdI0A3rKpkOXBvhmWVn6k1A14BrgI2\nJr1Xo300ygFiKdYIE9eZitFPvFnuPK4GXsWuN1mJFT0B2gOrQkhXvkqXd8n7ayfnNclsFYmD2BPY\n/gnKT68aYsHhaayKCXzcR6McIKYC+5C40O5MYFSYCcpDewHNnedNsV4Ls7F8/IXz+i9I7FiSXbq8\nGwWche2r3bB9d0qlT0uy9q7np5Jon1B+ZlcPq5abA9zver3O7KOpLrQT77phvRZmYt3g4nn4A6xd\nQt1cMxsJLAO2Y+1hF5A5736H7avzgJ/kNKX5ITk/LwT+hXXD/hQ7kLnbw5SfmR2DDV80k0Q34Z+i\nfVRERERERERERERERERERERERERERESkpgqpOEBbJrcBx2d4vwQYUcP0pNvuAOf51cCeNVhPqvQX\nA6Od5/2xwSjjSoGfeVh3Y2A8wd4quDHwAdG+iFZyZI+wEyDiUh8b3TOToMbjcW/3Kmzogu9quJ50\nfoyNmfORM+/1O50LvFGF5atjGzABOAX4d4DbkTygswTJlT2AZ7BhAV4icYa+GBuvfhpwBhXPpg8H\nJmJXin6MDUrmPns+EbtVbfL9LoZTcQjpz4AuWElmLvC489pYoImzTHy7V2CjXr4PjEta7+HYuDcA\nJwNbnO/VBLv/uns9YFe1znW+26nOa12xW+5eA0zHroYFOM75rgtJX5o4G3jded4Uu1p2GnYl8rA0\nn3ErA/o4z1tjQ8GnMsrZltRxChCSK/sBD2M3LdkAXOa8HgPWYAeuF0gM3NYIeB67S1YRNs79dyTO\nnk/FxrYfDKxN2lbyGbZ7vifwEPAjoJzEwTi+3RHYcBDFVK4qmkHiBi3HYtVmfYEjsADmXk8TLBAN\ndb5bO+f1r4BHgfuAQ4EPsaDXDht5dyipb+DUwEnzF878VicP+mBVY5lGQY3zOnLvTKCfh+WkllOA\nkFxZQqJK5RkSZ85ggcGtHhZQlmNnyACbgJ3OewOwO2YNAdZXMR2LsDNunHUXVuGz32Nn+L2w0sR9\n2Jn/MVi1jDv9vZxtxUsWz1Cx9ON+HiMxoNpcUt+fozUVh3KuD9yBjWH0LlbqaVOF75LJNmf9TbIt\nKLWbAoTkivvMtV7S/OYsyye/vhCrbtovzTLfU3Hfdh/otrme76Tq7XAfYIFpB1YFdSyVA0Q8nW7Z\nGpa3e1jW/fq5WNA4FLvfxyqyH9Dd+ZJt2eTfSOogBQjJlS4kbm94DpUPqG4xbBTf9sBhzmvNsWqW\nelg1zenYSKAHpPj8YuzAifPYrYpp3Qi0SPPeBKyX0ySsamxvYF/sxvHu9M/DSifdndfcdfobSQzD\n7tUaLCjGtcCCwk6s0burh3UsJpGfp2dYrrGz3m0ZlpE6QAFCciF+wP811kjdEruTWPy9VHZg9wAZ\ngdWJxxuU4/Xon2Nn0S9ROQC8gjVcf+Zs8/OktCSnLdnj2P16kxupwcbPb4OVJMCqeFJ14d0GXAy8\niVVlrXRtazTWfuBupHanI1WadmLfJ15qehY72M8CzseqpuLeJHHDGLd7gEud7e7t2k4H5zNxvUlU\nB4qISB4ooeJN54NyO4leVyIikgcaYSWXXFwoF+Q2RERERERERERERERERERERERERERERKrr/wGd\nI7WvRn4LVAAAAABJRU5ErkJggg==\n", "text": [ "" ] } ], "prompt_number": 15 }, { "cell_type": "markdown", "metadata": {}, "source": [ "This looks like a logarithmic function. And it doesn't look like the growth stops at some point (even though, from this small sampling it looks like it slows down a lot).\n", "\n", "If anyone is interested, I found a reference in [this book](http://www.amazon.fr/physique-tous-jours-Istv%C3%A0n-Berkes/dp/2711771679) that says the growth is unbounded. Therefore you could build this sort of structure to cover any given distance. In practice, this is limited by the accuracy with which you can place your bricks (and also forces other than gravity...)." ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Dependency on the size of the bricks" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Another question we can ask of our model: how does the range covered by the vault change if we change the brick width?" ] }, { "cell_type": "code", "collapsed": false, "input": [ "brick_widths = pl.linspace(0.1, 10)\n", "distances = pl.zeros_like(brick_widths)\n", "for l in brick_widths:\n", " bricks = generate_brick_sequence(l, 1, 100)\n", " distances[brick_widths == l] = max(compute_brick_shifts(bricks)) + l/2." ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 16 }, { "cell_type": "code", "collapsed": false, "input": [ "pl.plot(brick_widths, distances)\n", "pl.xlabel('brick width (distance units)')\n", "pl.ylabel('distance units')\n", "pl.title('distance covered by stacking 100 bricks as a function of brick width')\n", "pl.grid(True)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "display_data", "png": "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\n", "text": [ "" ] } ], "prompt_number": 17 }, { "cell_type": "markdown", "metadata": {}, "source": [ "The relationship seems linear. We can compute the slope of the previous curve:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "(distances[-1] - distances[0])/(10 - 0.1)" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 18, "text": [ "3.08868875881981" ] } ], "prompt_number": 18 }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we increase the brick width by one unit, the we will increase the range of 100 stacked bricks of the same width by 3.088 units." ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Stacking non-uniform sized bricks" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To finish this post, I'll show how we can stack up arbitrarily shaped bricks. This is one of the nice features of the code we have written so far: it's generic to the point that you can stack bricks of different sizes. \n", "\n", "First, we write a function that gives back a sequence of arbitrarily shaped bricks." ] }, { "cell_type": "code", "collapsed": false, "input": [ "def generate_random_brick_sequence(n):\n", " return [(pl.rand(1), 0.2) for i in range(n)]" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 19 }, { "cell_type": "markdown", "metadata": {}, "source": [ "And then we write a function that just generates a sequence of `n` bricks, computes the optimal way to stack them and plots them." ] }, { "cell_type": "code", "collapsed": false, "input": [ "def plot_random_bricks(n):\n", " bricks = generate_random_brick_sequence(n)\n", " shifts = compute_brick_shifts(bricks)\n", " plot_brick_sequence(bricks, shifts)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 20 }, { "cell_type": "code", "collapsed": false, "input": [ "pl.figure(figsize=(11, 4))\n", "format_plot = lambda : pl.xlim(0, 2.5) and pl.ylim(0, 9) and pl.grid(True);\n", "\n", "pl.subplot(131)\n", "plot_random_bricks(40)\n", "format_plot()\n", "\n", "pl.subplot(132)\n", "plot_random_bricks(40)\n", "format_plot()\n", "\n", "pl.subplot(133)\n", "plot_random_bricks(40)\n", "format_plot()" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "display_data", "png": "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\nL7xDPRNJHw5Yw7q3qNr42wZvzPXjUs9EcdfPN0o6mX98W9X0Tcox5FLPRPHWERmrR77qka961vLl\nWtNEZIyMda9nohbryPVexi4X9nxa0o/NP/6YpCNJr3UtpCXXC422vrnzDn5R0m/VPB9z/bjUI8Vd\nP7+h6heeJL0k6bOSHl/7mpjryKUeKd46ImP1yFc98lXPWr5ca5LIWB0yVl+P1GIduR4QulzYc9PX\nvM61kJZc6iklfZeqt22fV3XLopRirh8XKdfPWNVffh9b+3yqdbStnpjriIzthnxdG4t8rbOWL9ea\nyNh2ZKy5nlbraN/xxUrHr1s/EnX9vrZcfu4vq5pj/6qqM8z+jaRvDVSPq1jrx0Wq9XNb0ockvVvV\nXzXrYq+junpiriMytjvyRb62sZYv159NxrYjY831tFpHru8Q/vr8hy68XtWRb93XvG7+uRBc6rmn\naiVI0r9X1aNxJ1A9LmKuHxcp1s9NSf9K0r9UNTDXxV5HTfXEXEdkbDfki3zVsZYv15rI2HZkLFHG\nXC7sudxM+YTCNlO61PNaXR+pv0lx7mc3lltDbuj141JP7PWzJ+kDkp6r+ZqY68ilnpjriIw1G4t8\nbUO+6lnLl2tNZIyM7VJPsHW06cKef3G+LPzQ/PlPSHqjrxfuWM+7VJ2KPZP0S6o2TkgflPSipJdV\n9RD8BaVdP031xF4/b5b06vz1FqfAv1Xp1pFLPbHXERnbjnzVI1/NrOXLpSYyRsZ2qSf2OgIAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAO/j/GcdP7WZUqEAAAAABJRU5ErkJggg==\n", "text": [ "" ] } ], "prompt_number": 21 }, { "cell_type": "heading", "level": 1, "metadata": {}, "source": [ "Bonus: an analytical formula for equal sized bricks" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "I first read about the \"brick stacking problem\" in a physics book called [\"la physique de tous les jours\"](http://www.amazon.fr/physique-tous-jours-Istv%C3%A0n-Berkes/dp/2711771679). The book chapter explains the stacking algorithm that inspired me to write the code in this notebook. In this section, I derive the analytical formula for stacking identical bricks on top of each other. The reasoning is carried out on unit length bricks, but is valid for any size of brick.\n", "\n", "In the following, we denote the shift of the left right border of brick $i$ by $s(i)$. The mass of brick of $i$ is written as $m_i$.\n", "\n", "The reasoning is the following: suppose you already know the shifts up to order $n$ and you're trying to determine the shift for brick $n+1$. You want the horizontal center of mass of bricks $[1:n]$ to be exactly equal to the shift of brick $n+1$. Thus our first equation:\n", "\n", "$$\n", "s(n+1) = c_{mass}([1:n])\n", "$$\n", "\n", "It turns out that the center of mass of the assembly of bricks $[1:n]$ can be computed from the previous shifts. In effect: the center of mass of bricks $[1:n]$ can be written as the center of mass of brick $n$ alone and of bricks $[1:n-1]$. Using the previous equation, we also know that the center of mass of bricks $[1:n-1]$ is equal to the shift $s(n)$. Thus the following formula, derived from the previous relation and weighted by the brick masses:\n", "\n", "$$\n", "c_{mass}([1:n]) = \\frac{(\\sum_{i=1}^{n-1} m_i)s(n) + m_n(s(n) + 1/2)}{\\sum_{i=1}^{n} m_i}\n", "$$\n", "\n", "Injecting this formula in our previous equation we obtain a recurrence equation of order 1 on $s(n)$:\n", "\n", "$$\n", "s(n+1) = \\frac{(\\sum_{i=1}^{n-1} m_i)s(n) + m_n(s(n) + 1/2)}{\\sum_{i=1}^{n} m_i}\n", "$$\n", "\n", "Assuming that all masses are actually equal, we obtain:\n", "$$\n", "s(n+1) = \\frac{n \\, s(n) + 1/2}{n}\n", "$$\n", "\n", "This relation is to be initialized with $s(1) = 0$. \n", "\n", "The following figure illustrates our demonstration:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "SVG(filename='files/forces_analytical_formula.svg')" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 22, "svg": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " image/svg+xml\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " brick n (mass 1)\n", " bricks 1 to n-1 (mass n-1)\n", " brick n+1\n", " \n", " axis from which the brick shifts are measured\n", " \n", " \n", " \n", " s(n-1)\n", " s(n)\n", " s(n+1)\n", " \n", " \n", " center of mass for bricks1 to n-1\n", " \n", " center of mass for brick n\n", " \n", " 1/2\n", " \n", " \n", " \n", "" ], "text": [ "" ] } ], "prompt_number": 22 }, { "cell_type": "markdown", "metadata": {}, "source": [ "The formula we derived can easily be coded and compared to what we previously computed." ] }, { "cell_type": "code", "collapsed": false, "input": [ "def analytical_shift(n):\n", " if n==1:\n", " return 0\n", " else:\n", " return 1./(n-1) * ((n-1) * analytical_shift(n-1) + 1/2.)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 23 }, { "cell_type": "code", "collapsed": false, "input": [ "print [analytical_shift(i) for i in range(1, 10)]" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "[0, 0.5, 0.75, 0.9166666666666666, 1.0416666666666665, 1.1416666666666664, 1.2249999999999996, 1.296428571428571, 1.358928571428571]\n" ] } ], "prompt_number": 24 }, { "cell_type": "code", "collapsed": false, "input": [ "bricks = generate_brick_sequence(1, 1, 10)\n", "shifts = compute_brick_shifts(bricks)\n", "shifts = shifts[::-1]\n", "print [elem - shifts[0] for elem in shifts]" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "[0.0, -0.5, -0.75, -0.9166666666666666, -1.0416666666666667, -1.1416666666666666, -1.225, -1.2964285714285715, -1.3589285714285715, -1.414484126984127]\n" ] } ], "prompt_number": 25 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Indeed, the results are identical, except for the minus sign that appears in our numerical version." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It turns out that the analytical formula can enable us to prove something we hinted at when examining convergence of a brick stack (subsection \"how far can we get?\"). We can rewrite the total extent of the arch as:\n", "\n", "$$\n", "l(n) = \\sum_{i=1}^n s(i+1) - s(i) = \\frac{1}{2}\\sum_{i=1}^n \\frac{1}{i}\n", "$$\n", "\n", "However, as it happens, the series on the right, called the harmonic is divergent. This means that if we stack enough bricks, we can end up with any arch extent we'd like! My physics book tells me that this was first proved by [Nicole Oresme](http://en.wikipedia.org/wiki/Nicole_Oresme), \"probably one of the most original thinkers of the 14th century\" (to quote Wikipedia)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This post was entirely written using the IPython notebook. You can see a static view or download this notebook with the help of nbviewer at [20140808_BricksAndArches.ipynb](http://nbviewer.ipython.org/urls/raw.github.com/flothesof/posts/master/20140808_BricksAndArches.ipynb)." ] } ], "metadata": {} } ] }