From 54163e8fedb40b228c4861a05521aada463483e8 Mon Sep 17 00:00:00 2001 From: Hannah Date: Wed, 13 May 2015 16:12:58 -0400 Subject: [PATCH 1/2] Working vector and matrix objects --- Formulas.ipynb | 973 ---------------------------------------- Population Growth.ipynb | 259 ----------- README.md | 105 +---- matrix_objects.py | 138 ++++++ test_matrix_objects.py | 136 ++++++ 5 files changed, 277 insertions(+), 1334 deletions(-) delete mode 100644 Formulas.ipynb delete mode 100644 Population Growth.ipynb create mode 100644 matrix_objects.py create mode 100644 test_matrix_objects.py diff --git a/Formulas.ipynb b/Formulas.ipynb deleted file mode 100644 index eaa440f..0000000 --- a/Formulas.ipynb +++ /dev/null @@ -1,973 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Vectors\n", - "\n", - "A _vector_ is a series of numbers, usually written like this:\n", - "\n", - "$$\n", - "\\begin{align}\n", - "v = \\begin{bmatrix}5 \\\\ 0\\end{bmatrix} \\\\\n", - "w = \\begin{bmatrix}3 \\\\ 4\\end{bmatrix}\n", - "\\end{align}\n", - "$$\n", - "\n", - "although we can write it horizontally as well:\n", - "\n", - "$$\n", - "\\begin{align}\n", - "v = \\begin{bmatrix}5 & 0\\end{bmatrix} \\\\\n", - "w = \\begin{bmatrix}3 & 4\\end{bmatrix}\n", - "\\end{align}\n", - "$$\n", - "\n", - "It shows motion in a coordinate space, which is not super-important for what you're learning here, but just to note: a two-element vector is motion on a 2-dimensional plane, with the first number being the movement on the X axis and the second number being the movement on the Y axis. We can visualize this on a grid." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "%matplotlib inline" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "image/png": [ - "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\n", - "rkJggg==\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "import matplotlib.pyplot as plt\n", - "\n", - "def draw_vector(x, y, start_x=0, start_y=0, **kwargs):\n", - " args = dict(head_width=0.15, head_length=0.3, \n", - " overhang=0.5, length_includes_head=True)\n", - " args.update(kwargs)\n", - " plt.arrow(start_x, start_y, start_x + x, start_y + y, **args)\n", - "\n", - "plt.figure(figsize=(7, 7))\n", - "\n", - "draw_vector(5, 0, color=\"blue\")\n", - "draw_vector(3, 4, color=\"red\")\n", - "\n", - "plt.grid(True)\n", - "plt.axis([-1, 7, -1, 7])\n", - "\n", - "plt.text(2.5, 0.3, r\"$v = \\left[\\stackrel{5}{0}\\right]$\", fontsize=20)\n", - "plt.text(1.5, 2.3, r\"$w = \\left[\\stackrel{3}{4}\\right]$\", fontsize=20)\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For what we will be doing with data, vectors come in very handy, but you need a new style of math to work with them.\n", - "\n", - "## Addition and subtraction\n", - "\n", - "Adding two vectors of the same size is easy:\n", - "\n", - "$$\\\n", - "\\begin{bmatrix}v_1 \\\\ v_2 \\end{bmatrix} +\n", - "\\begin{bmatrix}w_1 \\\\ w_2 \\end{bmatrix} =\n", - "\\begin{bmatrix}v_1 + w_1 \\\\ v_2 + w_2 \\end{bmatrix}\n", - "$$\n", - "\n", - "as is subtraction:\n", - "\n", - "$$\\\n", - "\\begin{bmatrix}v_1 \\\\ v_2 \\end{bmatrix} -\n", - "\\begin{bmatrix}w_1 \\\\ w_2 \\end{bmatrix} =\n", - "\\begin{bmatrix}v_1 - w_1 \\\\ v_2 - w_2 \\end{bmatrix}\n", - "$$" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "image/png": [ - "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\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.figure(figsize=(6, 6))\n", - "\n", - "draw_vector(5, 0, color=\"blue\")\n", - "draw_vector(3, 4, color=\"red\")\n", - "draw_vector(8, 4, color=\"purple\", linestyle=\"dotted\")\n", - "\n", - "plt.grid(True)\n", - "plt.axis([-1, 9, -1, 9])\n", - "\n", - "plt.text(2.5, 0.2, r\"$v$\", color=\"blue\", fontsize=20)\n", - "plt.text(1.5, 2.6, r\"$w$\", color=\"red\", fontsize=20)\n", - "plt.text(4, 2, r\"$v + w$\", color=\"purple\", fontsize=20)\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Multiplication by a scalar\n", - "\n", - "A _scalar_ is a single number. You can multiply a vector by a scalar.\n", - "\n", - "$$\n", - "\\begin{bmatrix}v_1 \\\\ v_2 \\\\ v_3\\end{bmatrix} \\times\n", - "c =\n", - "\\begin{bmatrix}v_1 \\times c \\\\ v_2 \\times c \\\\ v_3 \\times c\\end{bmatrix}\n", - "$$" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Mean of vectors\n", - "\n", - "With the ability to add vectors and multiply by a scalar, we can find the mean of several vectors.\n", - "\n", - "$$\n", - "mean = \n", - "\\left(\n", - "\\begin{bmatrix}v_{1_1} \\\\ v_{1_2} \\\\ v_{1_3}\\end{bmatrix} +\n", - "\\begin{bmatrix}v_{2_1} \\\\ v_{2_2} \\\\ v_{2_3}\\end{bmatrix} +\n", - "\\ldots +\n", - "\\begin{bmatrix}v_{n_1} \\\\ v_{n_2} \\\\ v_{n_3}\\end{bmatrix} +\n", - "\\right)\n", - "\\times\n", - "\\frac{1}{n}\n", - "$$" - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "image/png": [ - "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\n", - "pCL9fxreW+2HU8DjAAAAAElFTkSuQmCC\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.figure(figsize=(7, 7))\n", - "\n", - "draw_vector(5, 0, color=\"blue\")\n", - "draw_vector(3, 4, color=\"red\")\n", - "draw_vector(1, 5, color=\"green\")\n", - "draw_vector(3, 3, color=\"purple\")\n", - "\n", - "plt.grid(True)\n", - "plt.axis([-1, 7, -1, 7])\n", - "\n", - "plt.text(1.5, 1.4, r\"mean\", color=\"purple\", fontsize=20)\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Dot Product\n", - "\n", - "The _dot product_ is hard to describe geometrically. You may hear it called the length of the projection of _v_ onto _w_.\n", - "\n", - "Dot products are used a lot in prediction and analysis.\n", - "\n", - "The formula is easy:\n", - "\n", - "$$\n", - "v \\cdot w = \\left(v_1 w_1 + v_2 w_2 + \\ldots + v_n w_n\\right)\n", - "$$\n", - "\n", - "\n", - "This formula helps us figure out our next and last vector formula.\n", - "\n", - "## Magnitude\n", - "\n", - "Magnitude is the length of a vector. Its formula is $\\sqrt{v \\cdot v}$." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Matrices\n", - "\n", - "A _matrix_ is a two-dimensional collection of numbers. You can think of it as a collection of vectors.\n", - "\n", - "$$\n", - "A = \n", - "\\begin{bmatrix}\n", - "2 & 9 & 4 \\\\\n", - "7 & 5 & 3\n", - "\\end{bmatrix}\n", - "$$\n", - "\n", - "Variables for matrices generally are in uppercase.\n", - "\n", - "The _shape_ of a matrix is its number of rows and columns, always in that order. The number of rows is usually called _n_ and the number of columns called _k_. The matrix _A_ above is a 2 x 3 matrix.\n", - "\n", - "## Addition and Subtraction\n", - "\n", - "Matrix addition and subtraction works like vector addition and subtraction.\n", - "\n", - "$$\n", - "\\begin{bmatrix}\n", - "A_{1,1} & A_{1,2} \\\\\n", - "A_{2,1} & A_{2,2} \\\\\n", - "A_{3,1} & A_{3,2}\n", - "\\end{bmatrix}\n", - "+\n", - "\\begin{bmatrix}\n", - "B_{1,1} & B_{1,2} \\\\\n", - "B_{2,1} & B_{2,2} \\\\\n", - "B_{3,1} & B_{3,2}\n", - "\\end{bmatrix}\n", - "=\n", - "\\begin{bmatrix}\n", - "A_{1,1} + B_{1,1} & A_{1,2} + B_{1,2} \\\\\n", - "A_{2,1} + B_{2,1} & A_{2,2} + B_{2,2} \\\\\n", - "A_{3,1} + B_{3,1} & A_{3,2} + B_{3,2} \\\\\n", - "\\end{bmatrix}\n", - "$$\n", - "\n", - "## Multiplication by a scalar\n", - "\n", - "This also works the same way it did with a vector.\n", - "\n", - "$$\n", - "\\begin{bmatrix}\n", - "A_{1,1} & A_{1,2} & A_{1,3} \\\\ \n", - "A_{2,1} & A_{2,2} & A_{2, 3} \n", - "\\end{bmatrix} \n", - "\\times\n", - "c =\n", - "\\begin{bmatrix}\n", - "A_{1,1} \\times c & A_{1,2} \\times c & A_{1,3} \\times c \\\\ \n", - "A_{2,1} \\times c & A_{2,2} \\times c & A_{2, 3} \\times c \n", - "\\end{bmatrix} \n", - "$$" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Multiplication by a vector\n", - "\n", - "When you multiply a matrix by a vector, you get a new vector.\n", - "\n", - "In order to multiply a matrix by a vector, you must obey this _shape rule_:\n", - "\n", - "*Shape Rule: The number of rows of the vector must equal the number of columns of the matrix.*\n", - "\n", - "$$\n", - "\\begin{bmatrix}\n", - "A_{1,1} & A_{1,2} \\\\\n", - "A_{2,1} & A_{2,2} \\\\\n", - "A_{3,1} & A_{3,2}\n", - "\\end{bmatrix}\n", - "\\times\n", - "\\begin{bmatrix}\n", - "v_1 \\\\\n", - "v_2\n", - "\\end{bmatrix}\n", - "=\n", - "\\begin{bmatrix}\n", - "A_{1,1} \\times v_1 + A_{1,2} \\times v_2 \\\\\n", - "A_{2,1} \\times v_1 + A_{2,2} \\times v_2 \\\\\n", - "A_{3,1} \\times v_1 + A_{3,2} \\times v_2 \\\\\n", - "\\end{bmatrix}\n", - "$$\n", - "\n", - "or, maybe more clearly:\n", - "\n", - "$$\n", - "\\begin{bmatrix}\n", - "a & b \\\\\n", - "c & d \\\\\n", - "e & f\n", - "\\end{bmatrix}\n", - "\\times\n", - "\\begin{bmatrix}\n", - "m \\\\\n", - "n\n", - "\\end{bmatrix}\n", - "=\n", - "\\begin{bmatrix}\n", - "am + bn \\\\\n", - "cm + dn \\\\\n", - "em + fn \\\\\n", - "\\end{bmatrix}\n", - "$$\n", - "\n", - "Example:\n", - "\n", - "$$\n", - "\\begin{bmatrix}\n", - "3 & 2 \\\\\n", - "4 & 1 \\\\\n", - "0 & 4\n", - "\\end{bmatrix}\n", - "\\times\n", - "\\begin{bmatrix}\n", - "2 \\\\\n", - "3\n", - "\\end{bmatrix}\n", - "=\n", - "\\begin{bmatrix}\n", - "3 \\times 2 + 2 \\times 3 \\\\\n", - "4 \\times 2 + 1 \\times 3 \\\\\n", - "0 \\times 2 + 4 \\times 3\n", - "\\end{bmatrix}\n", - "=\n", - "\\begin{bmatrix}\n", - "12 \\\\\n", - "11 \\\\\n", - "12\n", - "\\end{bmatrix}\n", - "$$" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Multiplication by another matrix\n", - "\n", - "When you multiply a matrix by a matrix, you get a new matrix.\n", - "\n", - "*Shape Rule: The number of columns of the first matrix must equal the number of rows of the second matrix.*\n", - "\n", - "$$\n", - "\\begin{bmatrix}\n", - "A_{1,1} & A_{1,2} \\\\\n", - "A_{2,1} & A_{2,2} \\\\\n", - "A_{3,1} & A_{3,2}\n", - "\\end{bmatrix}\n", - "\\times\n", - "\\begin{bmatrix}\n", - "B_{1,1} & B_{1,2} \\\\\n", - "B_{2,1} & B_{2,2}\n", - "\\end{bmatrix}\n", - "=\n", - "\\begin{bmatrix}\n", - "A_{1,1}B_{1,1} + A_{1,2}B_{2,1} & A_{1,1}B_{1,2} + A_{1,2}B_{2,2} \\\\\n", - "A_{2,1}B_{1,1} + A_{2,2}B_{2,1} & A_{2,1}B_{1,2} + A_{2,2}B_{2,2} \\\\\n", - "A_{3,1}B_{1,1} + A_{3,2}B_{2,1} & A_{3,1}B_{1,2} + A_{3,2}B_{2,2} \\\\\n", - "\\end{bmatrix}\n", - "$$\n", - "\n", - "or, maybe more clearly:\n", - "\n", - "$$\n", - "\\begin{bmatrix}\n", - "a & b \\\\\n", - "c & d \\\\\n", - "e & f\n", - "\\end{bmatrix}\n", - "\\times\n", - "\\begin{bmatrix}\n", - "w & x \\\\\n", - "y & z\n", - "\\end{bmatrix}\n", - "=\n", - "\\begin{bmatrix}\n", - "aw + by & ax + bz \\\\\n", - "cw + dy & cx + dz \\\\\n", - "ew + fy & ex + fz \\\\\n", - "\\end{bmatrix}\n", - "$$\n", - "\n", - "Example:\n", - "\n", - "$$\n", - "\\begin{bmatrix}\n", - "3 & 2 \\\\\n", - "4 & 1 \\\\\n", - "0 & 4\n", - "\\end{bmatrix}\n", - "\\times\n", - "\\begin{bmatrix}\n", - "2 & 1 \\\\\n", - "3 & 0\n", - "\\end{bmatrix}\n", - "=\n", - "\\begin{bmatrix}\n", - "3 \\times 2 + 2 \\times 3 & 3 \\times 1 + 2 \\times 0 \\\\\n", - "4 \\times 2 + 1 \\times 3 & 4 \\times 1 + 1 \\times 0 \\\\\n", - "0 \\times 2 + 4 \\times 3 & 0 \\times 1 + 4 \\times 0\n", - "\\end{bmatrix}\n", - "=\n", - "\\begin{bmatrix}\n", - "12 & 3 \\\\\n", - "11 & 4 \\\\\n", - "12 & 0\n", - "\\end{bmatrix}\n", - "$$" - ] - } - ], - "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.4.3" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} diff --git a/Population Growth.ipynb b/Population Growth.ipynb deleted file mode 100644 index 6ae6009..0000000 --- a/Population Growth.ipynb +++ /dev/null @@ -1,259 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Imagine you are an adventurer in a world of fantasy, swords, and magic. You have captured 10 fire-drakes, newly hatched. You wish to know how many drakes you will have in 20 years, so you may grant them to your friends and family upon your death bed.\n", - "\n", - "Fire-drakes are not dragons, by the way. They only live to 12 years max and are very stupid, which is good because dragons are tricky and raising them only results in pain and suffering.\n", - "\n", - "Here's what we know about fire-drake fertility:\n", - "\n", - "* Between ages 0 and 2, drakes are not fertile.\n", - "* Between ages 2 and 4, each drake has a 25% chance to produce 1 offspring.\n", - "* Between ages 4 and 6, each drake has a 60% chance to produce 1 offspring.\n", - "* Between ages 6 and 8, each drake has a 80% chance to produce 1 offspring.\n", - "* Between ages 8 and 10, each drake has a 15% chance to produce 1 offspring.\n", - "* Between ages 10 and 12, drakes are not fertile.\n", - "\n", - "Here's what we know about fire-drake mortality:\n", - "\n", - "* Between ages 0 and 2, 30% of drakes die. Life is cruel.\n", - "* Between ages 2 and 4, only 5% of drakes die. If they've lived to 2, they're tough.\n", - "* Between ages 4 and 6, 10% of drakes die.\n", - "* Between ages 6 and 8, 10% of drakes die.\n", - "* Between ages 8 and 10, 50% of drakes die.\n", - "* Between ages 10 and 12, all drakes die.\n", - "\n", - "If you want to know how many drakes and of what age groups you'll have in 40 years, you could do a lot of math by hand. It will not be fun. Or, you can use matrices!\n", - "\n", - "There's a matrix type called a _Leslie matrix_ that can be used to predict population. You put birthrates in the first row and survival rates in a diagonal. For our drakes, it looks like this:\n", - "\n", - "$$\n", - "\\begin{bmatrix}\n", - "0 & 0.25 & 0.6 & 0.8 & 0.15 & 0 \\\\\n", - "0.7 & 0 & 0 & 0 & 0 & 0 \\\\\n", - "0 & 0.95 & 0 & 0 & 0 & 0 \\\\\n", - "0 & 0 & 0.9 & 0 & 0 & 0 \\\\\n", - "0 & 0 & 0 & 0.9 & 0 & 0 \\\\\n", - "0 & 0 & 0 & 0 & 0.5 & 0 \\\\\n", - "\\end{bmatrix}\n", - "$$\n", - "\n", - "Each row and column of this matrix corresponds to a 2-year period.\n", - "\n", - "Ok, so assuming I have 10 newly-hatched fire-drakes, how many will I have in 2 years? You set up a vector of population groups. I only have drakes in my 0-2 age group, so it looks like this:\n", - "\n", - "$$\n", - "\\begin{bmatrix}\n", - "10 \\\\\n", - "0 \\\\\n", - "0 \\\\\n", - "0 \\\\\n", - "0 \\\\\n", - "0 \\\\\n", - "\\end{bmatrix}\n", - "$$\n", - "\n", - "I can multiply these together to find out what I have:\n", - "\n", - "$$\n", - "\\begin{bmatrix}\n", - "0 & 0.25 & 0.6 & 0.8 & 0.15 & 0 \\\\\n", - "0.7 & 0 & 0 & 0 & 0 & 0 \\\\\n", - "0 & 0.95 & 0 & 0 & 0 & 0 \\\\\n", - "0 & 0 & 0.9 & 0 & 0 & 0 \\\\\n", - "0 & 0 & 0 & 0.9 & 0 & 0 \\\\\n", - "0 & 0 & 0 & 0 & 0.5 & 0 \\\\\n", - "\\end{bmatrix}\n", - "\\times\n", - "\\begin{bmatrix}\n", - "10 \\\\\n", - "0 \\\\\n", - "0 \\\\\n", - "0 \\\\\n", - "0 \\\\\n", - "0 \\\\\n", - "\\end{bmatrix}\n", - "=\n", - "\\begin{bmatrix}\n", - "0 \\\\\n", - "7 \\\\\n", - "0 \\\\\n", - "0 \\\\\n", - "0 \\\\\n", - "0 \\\\\n", - "\\end{bmatrix}\n", - "$$\n", - "\n", - "That wasn't so useful, but let me continue. These 7 drakes age another two years:\n", - "\n", - "$$\n", - "\\begin{bmatrix}\n", - "0 & 0.25 & 0.6 & 0.8 & 0.15 & 0 \\\\\n", - "0.7 & 0 & 0 & 0 & 0 & 0 \\\\\n", - "0 & 0.95 & 0 & 0 & 0 & 0 \\\\\n", - "0 & 0 & 0.9 & 0 & 0 & 0 \\\\\n", - "0 & 0 & 0 & 0.9 & 0 & 0 \\\\\n", - "0 & 0 & 0 & 0 & 0.5 & 0 \\\\\n", - "\\end{bmatrix}\n", - "\\times\n", - "\\begin{bmatrix}\n", - "0 \\\\\n", - "7 \\\\\n", - "0 \\\\\n", - "0 \\\\\n", - "0 \\\\\n", - "0 \\\\\n", - "\\end{bmatrix}\n", - "=\n", - "\\begin{bmatrix}\n", - "7 \\times 0.25 \\\\\n", - "0 \\\\\n", - "7 \\times 0.95 \\\\\n", - "0 \\\\\n", - "0 \\\\\n", - "0 \\\\\n", - "\\end{bmatrix}\n", - "=\n", - "\\begin{bmatrix}\n", - "1.75 \\\\\n", - "0 \\\\\n", - "6.65 \\\\\n", - "0 \\\\\n", - "0 \\\\\n", - "0 \\\\\n", - "\\end{bmatrix}\n", - "$$\n", - "\n", - "Obviously, I don't have 1.75 new drakes, but if I'm going to keep calculating, keeping the decimal is fine so I adhere to average rates.\n", - "\n", - "Let's keep doing this! At 6 years:\n", - "\n", - "$$\n", - "\\begin{bmatrix}\n", - "0 & 0.25 & 0.6 & 0.8 & 0.15 & 0 \\\\\n", - "0.7 & 0 & 0 & 0 & 0 & 0 \\\\\n", - "0 & 0.95 & 0 & 0 & 0 & 0 \\\\\n", - "0 & 0 & 0.9 & 0 & 0 & 0 \\\\\n", - "0 & 0 & 0 & 0.9 & 0 & 0 \\\\\n", - "0 & 0 & 0 & 0 & 0.5 & 0 \\\\\n", - "\\end{bmatrix}\n", - "\\times\n", - "\\begin{bmatrix}\n", - "1.75 \\\\\n", - "0 \\\\\n", - "6.65 \\\\\n", - "0 \\\\\n", - "0 \\\\\n", - "0 \\\\\n", - "\\end{bmatrix}\n", - "=\n", - "\\begin{bmatrix}\n", - "6.65 \\times 0.6 \\\\\n", - "1.75 \\times 0.7 \\\\\n", - "0 \\\\\n", - "6.65 \\times 0.9 \\\\\n", - "0 \\\\\n", - "0 \\\\\n", - "\\end{bmatrix}\n", - "=\n", - "\\begin{bmatrix}\n", - "3.99 \\\\\n", - "1.225 \\\\\n", - "0 \\\\\n", - "5.985 \\\\\n", - "0 \\\\\n", - "0 \\\\\n", - "\\end{bmatrix}\n", - "$$\n", - "\n", - "Ok, I started with 10 and still have about 10. Does this get better?\n", - "\n", - "$$\n", - "\\begin{bmatrix}\n", - "0 & 0.25 & 0.6 & 0.8 & 0.15 & 0 \\\\\n", - "0.7 & 0 & 0 & 0 & 0 & 0 \\\\\n", - "0 & 0.95 & 0 & 0 & 0 & 0 \\\\\n", - "0 & 0 & 0.9 & 0 & 0 & 0 \\\\\n", - "0 & 0 & 0 & 0.9 & 0 & 0 \\\\\n", - "0 & 0 & 0 & 0 & 0.5 & 0 \\\\\n", - "\\end{bmatrix}\n", - "\\times\n", - "\\begin{bmatrix}\n", - "3.99 \\\\\n", - "1.225 \\\\\n", - "0 \\\\\n", - "5.985 \\\\\n", - "0 \\\\\n", - "0 \\\\\n", - "\\end{bmatrix}\n", - "=\n", - "\\begin{bmatrix}\n", - "5.985 \\times 0.8 + 1.225 \\times 0.25 \\\\\n", - "3.99 \\times 0.7 \\\\\n", - "1.225 \\times 0.9 \\\\\n", - "0 \\\\\n", - "5.985 \\times 0.9 \\\\\n", - "0 \\\\\n", - "\\end{bmatrix}\n", - "=\n", - "\\begin{bmatrix}\n", - "5.09425 \\\\\n", - "2.793 \\\\\n", - "1.1025 \\\\\n", - "0 \\\\\n", - "5.3865 \\\\\n", - "0 \\\\\n", - "\\end{bmatrix}\n", - "$$\n", - "\n", - "Ok, it looks like I have about 14 drakes 8 years in. This is getting tedious, but it looks like I might be able to sustain a population of these creatures.\n", - "\n", - "If you didn't notice so far, this calculation ends up looking like the following, where _L_ is our Leslie matrix, _d_ is our original distribution, and _n_ is the number of 2-year cycles:\n", - "\n", - "$$\n", - "d_n = L^n \\times d\n", - "$$" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Using the above math plus your matrix library, calculate how many drakes of each age I will have in 20 2-year cycles." - ] - }, - { - "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.4.3" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} diff --git a/README.md b/README.md index 97f003e..8c40d66 100644 --- a/README.md +++ b/README.md @@ -1,104 +1,5 @@ # Vector and Matrix Objects -## Description - -Implement various vector and matrix math objects using no math libraries - -## Objectives - -### Learning Objectives - -After completing this assignment, you should understand: - -* List comprehensions -* Introductory linear algebra concepts -* Raising exceptions -* Creating classes -* Using `__` "magic" methods - -### Performance Objectives - -After completing this assignment, you should be able to: - -* Perform mathematical operations on complex list structures - -## Details - -### Deliverables - -* A Git repo called matrix-objects containing at least: - * `README.md` file explaining how to run your project - * a module called `matrix_math` - * tests for `matrix_math` - -### Requirements - -* Passing unit tests -* No PEP8 or Pyflakes warnings or errors -* No use of third-party libraries - only built in `+ - / *` operators and the `math` module - -## Normal Mode - -Implement two object types, `Matrix` and `Vector`. These objects should implement: - -* shape -* addition and subtraction -* multiplication by a scalar -* matrix multiplication by a vector -* matrix multiplication by a matrix -* vector dot product -* vector magnitude - -These functions are all defined in [the formulas notebook](Formulas.ipynb) included with this assignment. - -These functions must: - -* Check the shape of the incoming vector or matrix before any calculations - -You should think about how you create the initial objects. It is suggested that -you be able to write: - -```py -Matrix([[0, 1, 0], [1, 0, 0], [0, 0, 1]]) -Vector([1, 5]) -``` - -Also think about whether Vector might inherit from Matrix or vice-versa. -Vectors can often be treated as 1-dimensional matrices. - -Solve the problem in [the Population Growth notebook](Population Growth.ipynb). - -## Hard Mode - -Make sure your objects can be used with standard Python operators. The -following should all be valid: - -```python -Vector([1, 2]) + Vector([0, 4]) -Vector([1, 2]) - Vector([0, 4]) -Vector([1, 2]) * 3 - -Vector([1, 2]) == Vector([1, 2]) # results in True - -Matrix([[0, 1], [1, 0]]) + Matrix([[1, 1], [0, 0]]) -Matrix([[0, 1], [1, 0]]) - Matrix([[1, 1], [0, 0]]) -Matrix([[0, 1], [1, 0]]) * 3 -Matrix([[0, 1], [1, 0]]) * Vector([1, 2]) -Matrix([[1, 1, 1], [0, 0, 0]]) * Matrix([[1, 1], [2, 2], [3, 3]]) - -Matrix([[0, 1], [1, 0]]) == Matrix([[1, 1], [0, 0]]) # results in False -``` - -Add the following abilities to matrix objects: - -* matrix rotation - -Research static methods and add the following abilities on the Matrix class: - -* create a matrix from a size and a function - -## Reading - -* [A Guide to Python's Magic Methods](http://www.rafekettler.com/magicmethods.html) -* [Math Matters: Why Do I Need to Know This?](https://www.wku.edu/mathmatters/documents/mathmattersep13.pdf) - a great -explanation of how matrix math can help you with probabilities +All mathematical functions work with the objects. +Population calculation is in matrix_objects.py (answer prints to console) +rotation works, and static method works, although it's not very useful diff --git a/matrix_objects.py b/matrix_objects.py new file mode 100644 index 0000000..bb867e6 --- /dev/null +++ b/matrix_objects.py @@ -0,0 +1,138 @@ +import math +class ShapeException(Exception): + pass + +class Vector: + def __init__(self, a_list): + self.contents = a_list + + def shape(self): + return (len(self.contents),) + + def __eq__(self,other): + if type(other) == Vector: + return self.contents == other.contents + elif type(other) == list: + return self.contents == other + else: + raise TypeError("Can't compare those values") + + def __str__(self): + return str(self.contents) + + def __add__(self, other): + a = self.contents + b = other.contents + if self.shape() != other.shape(): + raise ShapeException() + return [a[i] + b[i] for i in range(len(a))] + + def __sub__(self, other): + a = self.contents + b = other.contents + if self.shape() != other.shape(): + raise ShapeException() + return [a[i] - b[i] for i in range(len(a))] + + def dot(self, other): + a = self.contents + b = other.contents + if self.shape() != other.shape(): + raise ShapeException() + return sum([(a[i] * b[i]) for i in range(len(a))]) + + def __mul__(self, scalar): + a = self.contents + return [a[i] * scalar for i in range(len(a))] + + def magnitude(self): + a = self.contents + return math.sqrt(sum([a[i]**2 for i in range(len(a))])) + + +class Matrix: + def __init__(self, some_lists): + self.contents = some_lists + + def __eq__(self,other): + if type(other) == Matrix: + return self.contents == other.contents + elif type(other) == list: + return self.contents == other + else: + raise TypeError("Can't compare those values") + + def __repr__(self): + return str(self.contents) + + def shape(self): + a = self.contents + return (len(a),len(a[1])) + + def __add__(self, other): + a = self.contents + b = other.contents + if self.shape() != other.shape(): + raise ShapeException() + return [Vector(a[i]) + Vector(b[i]) for i in range(len(a))] + + def __sub__(self, other): + a = self.contents + b = other.contents + if self.shape() != other.shape(): + raise ShapeException() + return [Vector(a[i]) - Vector(b[i]) for i in range(len(a))] + + def matrix_col(self, column_index): + a = self.contents + return [l[column_index] for l in a] + + def __mul__(self,other): + if type(other) == Vector: + if len(other.contents) != len(self.contents[1]): + raise ShapeException() + return[Vector.dot(Vector(self.contents[i]), other) for i in range(len(self.contents))] + elif type(other) == Matrix: + a = self.contents + b = other.contents + if len(a[0]) != len(b): + raise ShapeException() + return [[Vector.dot(Vector(a[i]),Vector([l[j] for l in b])) for j in range(len(b[0]))] for i in range(len(a))] + elif type(other) == int: + a = self.contents + return[Vector(i) * other for i in a] + else: + raise TypeError("Cannot multiply these values") + + def rotate_matrix(self): + a = self.contents + rot_mat = [] + for i in range(len(a[0])): + j = self.matrix_col(i) + new_row = j[::-1] + rot_mat.append(new_row) + return Matrix(rot_mat) + + @classmethod + def newMat(cls, size): + matrix = [] + for i in range(size): + matrix.append([0,0,0]) + return cls(matrix) + + +def find_population(l, d): + num_of_cycles = 20 + product = Vector(l * d) + while num_of_cycles > 0: + new_prod = l * product + product = Vector(new_prod) + num_of_cycles -= 1 + return product + +Leslie_mat = Matrix([[0, 0.25, 0.6, 0.8, 0.15, 0], [0.7, 0, 0, 0, 0, 0], [0, 0.95, 0, 0, 0, 0], + [0, 0, 0.9, 0, 0, 0], [0, 0, 0, 0.9, 0, 0], [0, 0, 0, 0, 0.5, 0]]) + +initial_group = Vector([10, 0, 0, 0, 0, 0]) + +print(find_population(Leslie_mat, initial_group)) diff --git a/test_matrix_objects.py b/test_matrix_objects.py new file mode 100644 index 0000000..bb79e66 --- /dev/null +++ b/test_matrix_objects.py @@ -0,0 +1,136 @@ +from matrix_objects import Vector,Matrix,ShapeException +from nose.tools import raises +import math + +a = Vector([1,2,3]) +b = Vector([0,4,3]) +c = Vector([2,4]) +d = Vector([3,1]) +e = Vector([1,-3]) +f = Vector([4,3,1]) +g = Vector([3,3,1]) + +def test_vector_shape(): + assert Vector.shape(a) == (3,) + assert Vector.shape(b) == (3,) + assert Vector.shape(c) == (2,) + +def test_vector_equality(): + assert a == Vector([1,2,3]) + +def test_vector_inequality(): + assert a != Vector([1,2,4]) + +@raises(TypeError) +def test_vector_equality_error(): + assert a == 4 + +def test_vector_add(): + assert a + b == [1, 6, 6] + assert c + d == [5, 5] + assert Vector([0,1,2]) + Vector([1,1,1]) == a + +def test_vector_add_is_communicative(): + assert a + b == b + a + +@raises(ShapeException) +def test_vector_add_checks_shapes(): + a + d + +def test_vector_sub(): + assert a - b == [1,-2,0] + assert c - d == [-1,3] + assert d - c == e + +@raises(ShapeException) +def test_vector_sub_checks_shapes(): + a - d + +def test_dot(): + assert Vector.dot(a, b) == 17 + assert Vector.dot(c, d) == 10 + assert Vector.dot(f, g) == 22 + +@raises(ShapeException) +def test_dot_checks_shapes(): + Vector.dot(a, c) + +def test_vector_multiply(): + assert a * 0.5 == [0.5, 1, 1.5] + assert b * 2 == [0, 8, 6] + +def test_magnitude(): + assert Vector.magnitude(a) == math.sqrt(14) + assert Vector.magnitude(b) == 5 + assert Vector.magnitude(c) == math.sqrt(20) + assert Vector.magnitude(d) == math.sqrt(10) + +A = Matrix([[1, 0, 0], + [0, 1, 0], + [0, 0, 1]]) +B = Matrix([[1, 2, 3], + [4, 5, 6], + [7, 8, 9]]) +C = Matrix([[1, 2], + [2, 1], + [1, 2]]) +D = Matrix([[1, 2, 3], + [3, 2, 1]]) +E = Matrix([[2, 1, 1], + [2, 3, 4], + [1, 6, 4]]) +F = Matrix([[7, 4, 1], + [8, 5, 2], + [9, 6, 3]]) + +def test_matrix_addition(): + assert A + B == [[2, 2, 3], [4, 6, 6], [7, 8, 10]] + assert A + E == [[3, 1, 1], [2, 4, 4], [1, 6, 5]] + +def test_matrix_subtraction(): + assert A - B == [[0, -2, -3], [-4, -4, -6], [-7, -8, -8]] + assert B - E == [[-1, 1, 2], [2, 2, 2], [6, 2, 5]] + +@raises(ShapeException) +def test_dot_checks_shapes(): + A + C + +@raises(ShapeException) +def test_dot_checks_shapes(): + A - C + +def test_matrix_scalar_multiply(): + assert C * 3 == [[3, 6], [6, 3], [3, 6]] + +def test_matrix_vector_multiply(): + assert A * Vector([2, 5, 4]) == [2, 5, 4] + assert B * Vector([1, 2, 3]) == [14, 32, 50] + assert C * Vector([3, 4]) == [11, 10, 11] + assert D * Vector([0, 1, 2]) == [8, 4] + +@raises(ShapeException) +def test_matrix_vector_multiply_checks_shapes(): + C * Vector([1, 2, 3]) + +def test_matrix_matrix_multiply(): + assert A * B == B + assert B * C == [[8, 10], + [20, 25], + [32, 40]] + assert C * D == [[7, 6, 5], + [5, 6, 7], + [7, 6, 5]] + assert D * C == [[8, 10], [8, 10]] + + +@raises(ShapeException) +def test_matrix_matrix_multiply_checks_shapes(): + A * D + +def test_matrix_rotation(): + assert Matrix.rotate_matrix(B) == F + assert Matrix.rotate_matrix(C) == [[1, 2, 1], [2, 1, 2]] + + +def test_static_method(): + assert Matrix.newMat(4) == Matrix([[0,0,0], [0,0,0], [0,0,0], [0,0,0]]) From cfacb8c167a441104aed9b0743fc4cd141eedb68 Mon Sep 17 00:00:00 2001 From: Hannah Date: Thu, 14 May 2015 10:09:23 -0400 Subject: [PATCH 2/2] Small changes --- matrix_objects.py | 3 ++- test_matrix_objects.py | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/matrix_objects.py b/matrix_objects.py index bb867e6..df692d6 100644 --- a/matrix_objects.py +++ b/matrix_objects.py @@ -1,4 +1,5 @@ import math +from numbers import Number class ShapeException(Exception): pass @@ -98,7 +99,7 @@ def __mul__(self,other): if len(a[0]) != len(b): raise ShapeException() return [[Vector.dot(Vector(a[i]),Vector([l[j] for l in b])) for j in range(len(b[0]))] for i in range(len(a))] - elif type(other) == int: + elif isinstance(other, Number): a = self.contents return[Vector(i) * other for i in a] else: diff --git a/test_matrix_objects.py b/test_matrix_objects.py index bb79e66..cbc65ed 100644 --- a/test_matrix_objects.py +++ b/test_matrix_objects.py @@ -101,6 +101,7 @@ def test_dot_checks_shapes(): def test_matrix_scalar_multiply(): assert C * 3 == [[3, 6], [6, 3], [3, 6]] + assert D * 0.5 == [[.5, 1, 1.5], [1.5, 1, 0.5]] def test_matrix_vector_multiply(): assert A * Vector([2, 5, 4]) == [2, 5, 4]