From c9187151c9b92f416042d83b3738fca4cfa4ab59 Mon Sep 17 00:00:00 2001 From: Tripp Shealy Date: Wed, 13 May 2015 17:43:00 -0400 Subject: [PATCH 1/2] Vectors done still working on matrix multiply. --- matrix_object.py | 89 +++++++++++++++++++++++++++++ test_matrix_object.py | 129 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 218 insertions(+) create mode 100644 matrix_object.py create mode 100644 test_matrix_object.py diff --git a/matrix_object.py b/matrix_object.py new file mode 100644 index 0000000..b5c40e7 --- /dev/null +++ b/matrix_object.py @@ -0,0 +1,89 @@ +import math +from numbers import Number + +class ShapeException(Exception): + pass + + +class Vector: + + def __init__(self, row): + self.row = row + + @property + def shape(self): + return len(self.row), + + def __eq__(self, other): + if isinstance(other, list): + return self.row == other + else: + return self.row == other.row + + def __add__(self, other): + if self.shape != other.shape: + raise ShapeException("Vector must be same shape.") + row_add = [self.row[i] + other.row[i] for i in range(len(self.row))] + return Vector(row_add) + + def __sub__(self, other): + if self.shape != other.shape: + raise ShapeException("Vector must be same shape.") + row_sub = [self.row[i] - other.row[i] for i in range(len(self.row))] + return Vector(row_sub) + + def __mul__(self, other): + if isinstance(other, Number): + row_mul_scal = [self.row[i] * other for i in range(len(self.row))] + return Vector(row_mul_scal) + else: + raise ShapeException("Vector must be * by scalar.") + + # def __repr__(self): + # return "Vector: {}".format(self.row) + + def magnitude(self): + return math.sqrt(sum([num * num for num in self.row])) + + def dot(self, other): + """ + dot([a b], [c d]) = a * c + b * d + + dot(Vector, Vector) = Scalar + """ + if self.shape != other.shape: + raise ShapeException("Vector must be same shape.") + #return sum([self.row[i] * other.row[i] for i in range(len(self.row))]) + return sum([x * y for x, y in zip(self.row, other.row)]) + +class Matrix: + def __init__(self, rows): + self.rows = rows + + @property + def shape(self): + return len(self.rows), len(self.rows[0]) + + def __eq__(self, other): + if isinstance(other, list): + return self.rows == other + else: + return self.rows == other.rows + + def __mul__(self, other): + if isinstance(other, Number): + rows_mul_scal = [Vector(self.rows[i]) * other for i in range(len(self.rows))] + return Matrix(rows_mul_scal) + elif isinstance(other, Matrix): + pass + else: + raise ShapeException("Matrix must be * by scalar.") + + def matrix_col(self, column): + col = [i[column] for i in self.rows] + return Vector(col) + + # return [[sum(a*b for a,b in zip(matrix1_row, matrix2_col)) \ + # for matrix2_col in zip(*matrix2)] for matrix1_row in matrix1] + # + # return [[dot(a[i],matrix_col(b, j)) for j in range(len(b[0]))] for i in range(len(a))] diff --git a/test_matrix_object.py b/test_matrix_object.py new file mode 100644 index 0000000..92eaa6e --- /dev/null +++ b/test_matrix_object.py @@ -0,0 +1,129 @@ + +from matrix_object import * +from nose.tools import raises + +m = Vector([3, 4]) +n = Vector([5, 0]) + +v = Vector([1, 3, 0]) +w = Vector([0, 2, 4]) +u = Vector([1, 1, 1]) +y = Vector([10, 20, 30]) +z = Vector([0, 0, 0]) + +q = Vector([[1, 3, 0], [0, 2, 4]]) + +def test_shape(): + + assert m.shape == (len(m.row),) + +def test_vector_equality(): + + assert m == [3,4] + assert m == m + +# def test_vector_repr(): +# assert repr(m) == "Vector: [3, 4]" + +def test_vector_add(): + + assert v + w == Vector([1, 5, 4]) + assert v + w == [1, 5, 4] + +def test_vector_sub(): + + assert v - w == [1, 1, -4] + assert w - v == [-1, -1, 4] + assert y - z == y + +# @raises(ShapeException) +# def test_for_exception(): +# m * v + +def test_vector_mul_sum(): + + assert v * 0.5 == [0.5, 1.5, 0] + assert m * 2 == [6, 8] + +def test_magnitude(): + """ + magnitude([a b]) = sqrt(a^2 + b^2) + + magnitude(Vector) = Scalar + """ + assert m.magnitude() == 5 + assert v.magnitude() == math.sqrt(10) + assert y.magnitude() == math.sqrt(1400) + assert z.magnitude() == 0 + +# @raises(ShapeException) +def test_dot(): + """ + dot([a b], [c d]) = a * c + b * d + + dot(Vector, Vector) = Scalar + """ + assert w.dot(y) == 160 + assert m.dot(n) == 15 + assert u.dot(z) == 0 + +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]] + ) + +def test_shape_matrices(): + """shape should take a vector or matrix and return a tuple with the + number of rows (for a vector) or the number of rows and columns + (for a matrix.)""" + + assert A.shape == (3, 3) + assert C.shape == (3, 2) + assert D.shape == (2, 3) + + +def test_matrix_scalar_multiply(): + """ + [[a b] * Z = [[a*Z b*Z] + [c d]] [c*Z d*Z]] + + Matrix * Scalar = Matrix + """ + C_result = Matrix([[3, 6],[6, 3],[3, 6]]) + assert C * 3 == C_result + assert C * 3 == [[3, 6],[6, 3],[3, 6]] + +def test_matrix_matrix_multiply(): + """ + [[a b] * [[w x] = [[a*w+b*y a*x+b*z] + [c d] [y z]] [c*w+d*y c*x+d*z] + [e f]] [e*w+f*y e*x+f*z]] + + Matrix * Matrix = Matrix + """ + 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]] From 8e9d336057103e1cbecd67966f40965fbbbe8e2a Mon Sep 17 00:00:00 2001 From: Tripp Shealy Date: Thu, 14 May 2015 08:14:19 -0400 Subject: [PATCH 2/2] Matrix multiply test saying assertion error. --- matrix_object.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/matrix_object.py b/matrix_object.py index b5c40e7..7498ed5 100644 --- a/matrix_object.py +++ b/matrix_object.py @@ -36,8 +36,12 @@ def __mul__(self, other): if isinstance(other, Number): row_mul_scal = [self.row[i] * other for i in range(len(self.row))] return Vector(row_mul_scal) + # + # elif isinstance(other, Vector): + # vec_mul_vec = [self.row[i] * other.row[i] for i in range(len(self.row))] + # return Vector(vec_mul_vec) #is this needed? Or can just return func else: - raise ShapeException("Vector must be * by scalar.") + raise ShapeException("Vector must be * by a scalar or Vector.") # def __repr__(self): # return "Vector: {}".format(self.row) @@ -74,8 +78,11 @@ def __mul__(self, other): if isinstance(other, Number): rows_mul_scal = [Vector(self.rows[i]) * other for i in range(len(self.rows))] return Matrix(rows_mul_scal) + elif isinstance(other, Matrix): - pass + rows_mul_rows = [self.matrix_col(i) * Vector(self.rows[i]) for i in range(len(self.rows))] + return Matrix(rows_mul_rows) + else: raise ShapeException("Matrix must be * by scalar.")