From 8ce1a91559a71b60f325665695e159a2a034ad6e Mon Sep 17 00:00:00 2001 From: Benjamin Phillips Date: Wed, 13 May 2015 18:07:43 -0400 Subject: [PATCH 1/5] Added matrix_math.py and tests --- matrix_math.py | 121 ++++++++++++++++++++++++++ test_matrix_math.py | 202 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 323 insertions(+) create mode 100644 matrix_math.py create mode 100644 test_matrix_math.py diff --git a/matrix_math.py b/matrix_math.py new file mode 100644 index 0000000..81437b3 --- /dev/null +++ b/matrix_math.py @@ -0,0 +1,121 @@ +import math + +class ShapeException(Exception): + pass + +class Vector: + def __init__(self, values): + self.values = self.is_vector(values) + self.shape = len(self.values), + + def __eq__(self, other): + return self.values == other.values + + def __add__(self, other): + if self.shape != other.shape: + raise ShapeException() + else: + return Vector([self.values[index] + other.values[index] + for index in range(len(self.values))]) + + def __sub__(self, other): + if self.shape != other.shape: + raise ShapeException() + + else: + return Vector([self.values[index] - other.values[index] + for index in range(len(self.values))]) + + def __mul__(self, other): + return Vector([self.values[index] * other + for index in range(len(self.values))]) + + def dot(self, other): + if self.shape != other.shape: + raise ShapeException() + else: + return sum([self.values[index] * other.values[index] + for index in range(len(self.values))]) + + def mag(self): + return math.sqrt(sum([coefficient ** 2 + for coefficient in self.values])) + + def is_vector(self, a_list): + if type(a_list) != list: + raise ValueError( + "Must make Vector with numerical list") + else: + for item in a_list: + if not isinstance(item, (int, float)): + raise ValueError( + "Must make Vector with numerical list") + return a_list + + +############################################################################### + + +class Matrix: + def __init__(self, values): + self.values = self.is_matrix(values) + self.shape = len(self.values),len(self.values[0]) + + def __eq__(self, other): + return self.values == other.values + + def __add__(self, other): + if self.shape != other.shape: + raise ShapeException() + else: + return Matrix([[self.values[row][index] + other.values[row][index] + for index in range(len(self.values[0]))] + for row in range(len(self.values))]) + + def __sub__(self, other): + if self.shape != other.shape: + raise ShapeException() + else: + return Matrix([[self.values[row][index] - other.values[row][index] + for index in range(len(self.values[0]))] + for row in range(len(self.values))]) + + def __mul__(self, other): + if isinstance(other, (int, float)): + return Matrix([[self.values[row][index] * other + for index in range(len(self.values[0]))] + for row in range(len(self.values))]) + + elif isinstance(other, Vector): + return Vector([other.dot(Vector(row)) for row in self.values]) + + elif isinstance(other, Matrix): + return Matrix([(other.transpose() * Vector(row)).values + for row in self.values]) + + def transpose(self): + return Matrix([[row[index] + for row in self.values] + for index in range(len(self.values[0]))]) + + def is_matrix(self, a_list): + if type(a_list) != list: + raise ValueError( + "Must make Matrix with list of numerical lists") + else: + for index in range(len(a_list)): + if type(a_list[index]) != list or \ + len(a_list[index]) != len(a_list[(index-1)]): + raise ValueError( + "Must make Matrix with list of numerical lists") + else: + for value in a_list[index]: + if not isinstance(value, (int, float)): + raise ValueError( + "Must make Matrix with list of numerical lists") + return a_list + + @classmethod + def from_function(cls, rows, columns, function): + return cls([[function(x, y) for y in range(columns)] + for x in range(rows)]) diff --git a/test_matrix_math.py b/test_matrix_math.py new file mode 100644 index 0000000..35091c7 --- /dev/null +++ b/test_matrix_math.py @@ -0,0 +1,202 @@ +from matrix_math import ShapeException, Vector, Matrix +from nose.tools import raises +import math + + +def test_vector_has_content(): + v1 = Vector([1, 2, 3]) + assert v1.values == [1, 2, 3] + + +def test_vector_has_shape(): + v1 = Vector([1, 2, 3]) + v2 = Vector([1, 2]) + assert v1.shape == (3,) + assert v2.shape == (2,) + + +def test_vector_equality(): + v1 = Vector([1, 2, 3]) + v2 = Vector([1, 2, 3]) + assert v1 == v2 + + +def test_can_add_vector_objects(): + v1 = Vector([1, 2, 3]) + v2 = Vector([4, 5, 6]) + assert v1 + v2 == Vector([5, 7, 9]) + assert v2 + v1 == Vector([5, 7, 9]) + + +@raises(ShapeException) +def test_vector_add_raises_shape_exception(): + v1 = Vector([1, 2, 3]) + v2 = Vector([1, 2]) + v1 + v2 + + +def test_can_subtract_vector_objects(): + v1 = Vector([1, 2, 3]) + v2 = Vector([4, 5, 6]) + assert v1 - v2 == Vector([-3, -3, -3]) + assert v2 - v1 == Vector([3, 3, 3]) + + +@raises(ShapeException) +def test_vector_subtract_raises_shape_exception(): + v1 = Vector([1, 2, 3]) + v2 = Vector([1, 2]) + v1 - v2 + + +def test_vector_multiplication(): + v1 = Vector([1, 2, 3]) + assert v1 * 2 == Vector([2, 4, 6]) + + +def test_vector_dot(): + v1 = Vector([1, 2, 3]) + v2 = Vector([4, 5, 6]) + assert v1.dot(v2) == 32 + + +@raises(ShapeException) +def test_vector_dot_raises_shape_exception(): + v1 = Vector([1, 2, 3]) + v2 = Vector([1, 2]) + v1.dot(v2) + + +def test_vector_magnitude(): + v1 = Vector([3, 4]) + v2 = Vector([1, 3, 0]) + v3 = Vector([10, 20, 30]) + v4 = Vector([0, 0, 0]) + assert v1.mag() == 5 + assert v2.mag() == math.sqrt(10) + assert v3.mag() == math.sqrt(1400) + assert v4.mag() == 0 + + +def test_vector_works_with_floats(): + v1 = Vector([1.0, 2.0, 3.0]) + v2 = Vector([4.0, 5.0, 6.0]) + assert v1 + v2 == Vector([5.0, 7.0, 9.0]) + assert v2 + v1 == Vector([5.0, 7.0, 9.0]) + + +@raises(ValueError) +def test_vector_creation(): + v1 = Vector([1, 2, "3"]) + +m1 = Matrix([[1, 0, 0], + [0, 1, 0], + [0, 0, 1]]) + +m2 = Matrix([[1, 2, 3], + [4, 5, 6], + [7, 8, 9]]) + +m3 = Matrix([[1, 2], + [2, 1], + [1, 2]]) + +m4 = Matrix([[1, 2, 3], + [3, 2, 1]]) + +def test_matrix_has_content(): + assert m1.values == [[1, 0, 0], + [0, 1, 0], + [0, 0, 1]] + + +def test_matrix_has_shape(): + assert m1.shape == (3,3) + assert m3.shape == (3,2) + assert m4.shape == (2,3) + + +def test_matrix_equality(): + assert m1 == Matrix([[1, 0, 0], + [0, 1, 0], + [0, 0, 1]]) + + +def test_matrix_addition(): + assert m1 + m2 == Matrix([[2, 2, 3], [4, 6, 6], [7, 8, 10]]) + + +@raises(ShapeException) +def test_matrix_add_raises_ShapeException(): + m1 + m3 + + +def test_matrix_subtraction(): + assert m2 - m1 == Matrix([[0, 2, 3], [4, 4, 6], [7, 8, 8]]) + + +@raises(ShapeException) +def test_matrix_sub_raises_ShapeException(): + m1 - m3 + + +def test_matrix_scalar_multiply(): + assert m1 * 3 == Matrix([[3, 0, 0], + [0, 3, 0], + [0, 0, 3]]) + assert m3 * 3 == Matrix([[3, 6], + [6, 3], + [3, 6]]) +v1 = Vector([2, 5, 4]) +v2 = Vector([1, 2, 3]) +v3 = Vector([3, 4]) +v4 = Vector([0, 1, 2]) +def test_matrix_vector_multiply(): + assert m1 * v1 == Vector([2, 5, 4]) + assert m2 * v2 == Vector([14, 32, 50]) + assert m3 * v3 == Vector([11, 10, 11]) + assert m4 * v4 == Vector([8, 4]) + + +@raises(ShapeException) +def test_matrix_vector_multiply_raises_ShapeException(): + m1 * v3 + + +def test_matrix_transpose(): + assert m2.transpose() == Matrix([[1, 4, 7], + [2, 5, 8], + [3, 6, 9]]) + + +def test_matrix_matrix_multiply(): + assert m1 * m2 == m2 + assert m2 * m3 == Matrix([[8, 10], + [20, 25], + [32, 40]]) + assert m3 * m4 == Matrix([[7, 6, 5], + [5, 6, 7], + [7, 6, 5]]) + assert m4 * m3 == Matrix([[8, 10], + [8, 10]]) + assert Matrix([[1,2],[3,4]]) * Matrix([[1, 2, 3], [4, 5, 6]]) == \ + Matrix([[9, 12, 15], [19, 26, 33]]) + +@raises(ShapeException) +def test_matrix_matrix_multiply_checks_shapes(): + m1 * m4 + + +@raises(ValueError) +def test_matrix_creation(): + #m1 = Matrix([[3, 4, 5], [2, 5, 7], [1, 2, "3"]]) + m2 = Matrix([[3, 4, 5], [2], [1, 2, 3]]) + +def test_from_function(): + def diagonal_ones(x, y): + if x == y: + return 1 + else: + return 0 + assert Matrix.from_function(2, 2, diagonal_ones) == Matrix([[1, 0], + [0, 1]]) From 9b7e5d21ec0cf2ddc6a89a79e74958425b56d7e2 Mon Sep 17 00:00:00 2001 From: Benjamin Phillips Date: Wed, 13 May 2015 18:08:21 -0400 Subject: [PATCH 2/5] Added solution for fire drake population growth exercise --- Population Growth.ipynb | 146 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) diff --git a/Population Growth.ipynb b/Population Growth.ipynb index 6ae6009..209060d 100644 --- a/Population Growth.ipynb +++ b/Population Growth.ipynb @@ -225,6 +225,152 @@ "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": 1, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "from matrix_math import ShapeException, Vector, Matrix" + ] + }, + { + "cell_type": "code", + "execution_count": 77, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "leslie = 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], \\\n", + " [0, 0, 0.9, 0, 0, 0], [0, 0, 0, 0.9, 0, 0], [0, 0, 0, 0, 0.5, 0]])" + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[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]]\n" + ] + } + ], + "source": [ + "print(leslie.values)" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "dragons = Vector([10, 0, 0, 0, 0, 0])" + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "for i in range(20):\n", + " dragons = leslie * dragons" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[6.149914942919132, 4.182186803339321, 3.8477209681295763, 3.283445777563774, 2.841646230444824, 1.4082839376892242]\n" + ] + } + ], + "source": [ + "print(dragons.values)" + ] + }, + { + "cell_type": "code", + "execution_count": 82, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "test = Matrix([[.25, .5],[0, .95]])" + ] + }, + { + "cell_type": "code", + "execution_count": 83, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "leslie20 = leslie" + ] + }, + { + "cell_type": "code", + "execution_count": 84, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[0.6407182838330322, 0.9533865528483813, 0.8694631478701617, 0.5726496552122178, 0.09224872414378701, 0.0], [0.4304940460043394, 0.6407182838330322, 0.589207447887139, 0.38925308434056616, 0.06273280205008984, 0.0], [0.3973077463172356, 0.5842419195773176, 0.5361636137495489, 0.35706936411382273, 0.05771581452194364, 0.0], [0.34629488713166195, 0.5108242452650171, 0.4623621114070214, 0.3053003556617743, 0.04925168666345661, 0.0], [0.2955101199807398, 0.445236283454994, 0.4061729376245585, 0.265355364753195, 0.042624693456672365, 0.0], [0.1420823115222412, 0.21107865712909984, 0.19694480404940706, 0.13093009099881617, 0.021124259065338366, 0.0]]\n" + ] + } + ], + "source": [ + "for _ in range(20):\n", + " leslie20 *= leslie\n", + "print(leslie20.values)" + ] + }, + { + "cell_type": "code", + "execution_count": 89, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[6.407182838330322, 4.304940460043394, 3.973077463172356, 3.4629488713166197, 2.9551011998073977, 1.420823115222412]\n" + ] + } + ], + "source": [ + "print((leslie20 * Vector([10,0,0,0,0,0])).values)" + ] + }, { "cell_type": "code", "execution_count": null, From 22e79ac558f09bc21913f1f2dd466b44fb1c0c73 Mon Sep 17 00:00:00 2001 From: Benjamin Phillips Date: Wed, 13 May 2015 18:37:41 -0400 Subject: [PATCH 3/5] Allowed the vector to come first in matrix/vector multiplication (+new tests). Also added docstrings --- matrix_math.py | 88 ++++++++++++++++++++++++++++++++++----------- test_matrix_math.py | 2 ++ 2 files changed, 69 insertions(+), 21 deletions(-) diff --git a/matrix_math.py b/matrix_math.py index 81437b3..b5e26f7 100644 --- a/matrix_math.py +++ b/matrix_math.py @@ -1,16 +1,23 @@ import math + class ShapeException(Exception): pass + class Vector: + def __init__(self, values): self.values = self.is_vector(values) self.shape = len(self.values), +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # + def __eq__(self, other): return self.values == other.values +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # + def __add__(self, other): if self.shape != other.shape: raise ShapeException() @@ -18,6 +25,8 @@ def __add__(self, other): return Vector([self.values[index] + other.values[index] for index in range(len(self.values))]) +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # + def __sub__(self, other): if self.shape != other.shape: raise ShapeException() @@ -26,96 +35,133 @@ def __sub__(self, other): return Vector([self.values[index] - other.values[index] for index in range(len(self.values))]) +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # + def __mul__(self, other): - return Vector([self.values[index] * other - for index in range(len(self.values))]) + if isinstance(other, Matrix): + return Vector([self.dot(Vector(row)) for row in other.values]) + else: + return Vector([self.values[index] * other + for index in range(len(self.values))]) + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # def dot(self, other): + """takes the dot product of the vector and another vector""" if self.shape != other.shape: raise ShapeException() else: return sum([self.values[index] * other.values[index] for index in range(len(self.values))]) +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # + def mag(self): + """Returns the magnitude of the vector""" return math.sqrt(sum([coefficient ** 2 - for coefficient in self.values])) + for coefficient in self.values])) + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # def is_vector(self, a_list): - if type(a_list) != list: - raise ValueError( + """Checks to ensure the vector is initialized with a list of numbers""" + if type(a_list) != list: + raise ValueError( "Must make Vector with numerical list") - else: - for item in a_list: - if not isinstance(item, (int, float)): - raise ValueError( + else: + for item in a_list: + if not isinstance(item, (int, float)): + raise ValueError( "Must make Vector with numerical list") - return a_list + return a_list ############################################################################### class Matrix: + def __init__(self, values): self.values = self.is_matrix(values) - self.shape = len(self.values),len(self.values[0]) + self.shape = len(self.values), len(self.values[0]) + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # def __eq__(self, other): return self.values == other.values +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # + def __add__(self, other): if self.shape != other.shape: raise ShapeException() else: return Matrix([[self.values[row][index] + other.values[row][index] - for index in range(len(self.values[0]))] + for index in range(len(self.values[0]))] for row in range(len(self.values))]) +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # + def __sub__(self, other): if self.shape != other.shape: raise ShapeException() else: return Matrix([[self.values[row][index] - other.values[row][index] - for index in range(len(self.values[0]))] + for index in range(len(self.values[0]))] for row in range(len(self.values))]) +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # + def __mul__(self, other): + """Checks if the matrix is being multiplied by a scalar, vector, + or other matrix and performs the corresponding operation.""" if isinstance(other, (int, float)): return Matrix([[self.values[row][index] * other for index in range(len(self.values[0]))] - for row in range(len(self.values))]) + for row in range(len(self.values))]) elif isinstance(other, Vector): return Vector([other.dot(Vector(row)) for row in self.values]) elif isinstance(other, Matrix): return Matrix([(other.transpose() * Vector(row)).values - for row in self.values]) + for row in self.values]) + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # def transpose(self): + """Returns a matrix where the rows and columns of the current matrix + have been transposed""" return Matrix([[row[index] for row in self.values] - for index in range(len(self.values[0]))]) + for index in range(len(self.values[0]))]) + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # def is_matrix(self, a_list): + """Checks to ensure the matrix is initialized with a list of + lists of numbers""" if type(a_list) != list: raise ValueError( - "Must make Matrix with list of numerical lists") + "Must make Matrix w/list of numerical lists") else: for index in range(len(a_list)): if type(a_list[index]) != list or \ - len(a_list[index]) != len(a_list[(index-1)]): + len(a_list[index]) != len(a_list[(index - 1)]): raise ValueError( - "Must make Matrix with list of numerical lists") + "Must make Matrix w/list of numerical lists") else: for value in a_list[index]: if not isinstance(value, (int, float)): raise ValueError( - "Must make Matrix with list of numerical lists") + "Must make Matrix w/list of numerical lists") return a_list +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # + @classmethod def from_function(cls, rows, columns, function): + """Allows creation of a matrix from the number of rows, number of + columns, and an identity function.""" return cls([[function(x, y) for y in range(columns)] - for x in range(rows)]) + for x in range(rows)]) diff --git a/test_matrix_math.py b/test_matrix_math.py index 35091c7..ddf0ae0 100644 --- a/test_matrix_math.py +++ b/test_matrix_math.py @@ -52,6 +52,7 @@ def test_vector_subtract_raises_shape_exception(): def test_vector_multiplication(): v1 = Vector([1, 2, 3]) assert v1 * 2 == Vector([2, 4, 6]) + assert v1 * 2 == Vector([2, 4, 6]) def test_vector_dot(): @@ -153,6 +154,7 @@ def test_matrix_scalar_multiply(): v4 = Vector([0, 1, 2]) def test_matrix_vector_multiply(): assert m1 * v1 == Vector([2, 5, 4]) + assert v1 * m1 == Vector([2, 5, 4]) assert m2 * v2 == Vector([14, 32, 50]) assert m3 * v3 == Vector([11, 10, 11]) assert m4 * v4 == Vector([8, 4]) From 33700630063d3b11f578bd78b18664302ee5a0b3 Mon Sep 17 00:00:00 2001 From: Benjamin Phillips Date: Thu, 14 May 2015 09:15:45 -0400 Subject: [PATCH 4/5] Made self.shape property of Vector and Matrix classes a method with the property decorator. --- matrix_math.py | 14 ++++++++++++-- test_matrix_math.py | 17 +++++++++++------ 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/matrix_math.py b/matrix_math.py index b5e26f7..d7d35b0 100644 --- a/matrix_math.py +++ b/matrix_math.py @@ -9,7 +9,12 @@ class Vector: def __init__(self, values): self.values = self.is_vector(values) - self.shape = len(self.values), + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # + + @property + def shape(self): + return len(self.values), # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # @@ -83,7 +88,12 @@ class Matrix: def __init__(self, values): self.values = self.is_matrix(values) - self.shape = len(self.values), len(self.values[0]) + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # + + @property + def shape(self): + return len(self.values), len(self.values[0]) # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # diff --git a/test_matrix_math.py b/test_matrix_math.py index ddf0ae0..8f5474b 100644 --- a/test_matrix_math.py +++ b/test_matrix_math.py @@ -105,6 +105,7 @@ def test_vector_creation(): m4 = Matrix([[1, 2, 3], [3, 2, 1]]) + def test_matrix_has_content(): assert m1.values == [[1, 0, 0], [0, 1, 0], @@ -112,9 +113,9 @@ def test_matrix_has_content(): def test_matrix_has_shape(): - assert m1.shape == (3,3) - assert m3.shape == (3,2) - assert m4.shape == (2,3) + assert m1.shape == (3, 3) + assert m3.shape == (3, 2) + assert m4.shape == (2, 3) def test_matrix_equality(): @@ -152,6 +153,8 @@ def test_matrix_scalar_multiply(): v2 = Vector([1, 2, 3]) v3 = Vector([3, 4]) v4 = Vector([0, 1, 2]) + + def test_matrix_vector_multiply(): assert m1 * v1 == Vector([2, 5, 4]) assert v1 * m1 == Vector([2, 5, 4]) @@ -181,8 +184,9 @@ def test_matrix_matrix_multiply(): [7, 6, 5]]) assert m4 * m3 == Matrix([[8, 10], [8, 10]]) - assert Matrix([[1,2],[3,4]]) * Matrix([[1, 2, 3], [4, 5, 6]]) == \ - Matrix([[9, 12, 15], [19, 26, 33]]) + assert Matrix([[1, 2], [3, 4]]) * Matrix([[1, 2, 3], [4, 5, 6]]) == \ + Matrix([[9, 12, 15], [19, 26, 33]]) + @raises(ShapeException) def test_matrix_matrix_multiply_checks_shapes(): @@ -191,9 +195,10 @@ def test_matrix_matrix_multiply_checks_shapes(): @raises(ValueError) def test_matrix_creation(): - #m1 = Matrix([[3, 4, 5], [2, 5, 7], [1, 2, "3"]]) + m1 = Matrix([[3, 4, 5], [2, 5, 7], [1, 2, "3"]]) m2 = Matrix([[3, 4, 5], [2], [1, 2, 3]]) + def test_from_function(): def diagonal_ones(x, y): if x == y: From 31b3bc76c78bd4c723259df7d391e793114c1964 Mon Sep 17 00:00:00 2001 From: Benjamin Phillips Date: Thu, 14 May 2015 10:44:46 -0400 Subject: [PATCH 5/5] Added tests to complete coverage --- test_matrix_math.py | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/test_matrix_math.py b/test_matrix_math.py index 8f5474b..a8eda11 100644 --- a/test_matrix_math.py +++ b/test_matrix_math.py @@ -87,9 +87,19 @@ def test_vector_works_with_floats(): @raises(ValueError) -def test_vector_creation(): +def test_vector_creation_list_not_all_numbers(): v1 = Vector([1, 2, "3"]) + +@raises(ValueError) +def test_vector_creation_not_a_list(): + v2 = Vector("hello") + + +@raises(ValueError) +def test_vector_creation2(): + v3 = Vector(1) + m1 = Matrix([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) @@ -194,11 +204,20 @@ def test_matrix_matrix_multiply_checks_shapes(): @raises(ValueError) -def test_matrix_creation(): +def test_matrix_creation_not_all_list_items_are_numbers(): m1 = Matrix([[3, 4, 5], [2, 5, 7], [1, 2, "3"]]) + + +@raises(ValueError) +def test_matrix_creation_not_all_lists_the_same_length(): m2 = Matrix([[3, 4, 5], [2], [1, 2, 3]]) +@raises(ValueError) +def test_matrix_creation_not_a_list(): + m2 = Matrix("hello") + + def test_from_function(): def diagonal_ones(x, y): if x == y: