diff --git a/matrix_math.py b/matrix_math.py index 7c55a83..dde26fa 100644 --- a/matrix_math.py +++ b/matrix_math.py @@ -1,2 +1,142 @@ +import math + + class ShapeException(Exception): pass + + +def shape(vector): + """ + with no regard for poorly made lists + returns the shape of the list + """ + if isinstance(vector[0], list): + return (len(vector), len(vector[0])) + return (len(vector), ) + + +def compare(vect1, vect2): + """ + Checks if the shapes of the two entries + are the same + """ + return shape(vect1) == shape(vect2) + + +def vector_add(vect1, vect2): + """ + Returns the sum of two vectors + if they are the same shape + """ + if compare(vect1, vect2): + return [coeff1 + coeff2 for (coeff1, coeff2) + in list(zip(vect1, vect2))] + + raise ShapeException + + +def vector_sub(vect1, vect2): + """ + Returns the difference of two vectors + if their shapes are the same + """ + return vector_add(vect1, [-num for num in vect2]) + + +def vector_sum(*vectors): + """ + Returns the sum of any number of vectors + if their shapes are the same + """ + vectors = list(vectors) + if len(vectors) > 1: + return vector_add(vectors.pop(), vector_sum(*vectors)) + else: + return vectors[0] + + +def dot(vect1, vect2): + """ + Returns the dot product of two vectors + if their shape is the same + """ + if compare(vect1, vect2): + return sum([coeff1 * coeff2 for (coeff1, coeff2) + in list(zip(vect1, vect2))]) + + raise ShapeException + + +def vector_multiply(vector, scalar): + """ + Returns the result of multiplying a vector + by a scalar + """ + return [entry * scalar for entry in vector] + + +def vector_mean(*vectors): + """ + Returns the mean of any set of vectors + if their shape is the same + """ + return vector_multiply(vector_sum(*vectors), 1/len(vectors)) + + +def magnitude(vector): + """ + Returns the magnitude of a vector + in the Euclidean metric + """ + return math.sqrt(sum([entry**2 for entry in vector])) + + +def matrix_row(matrix, row): + """ + returns a specified row of a matrix + """ + return matrix[row] + + +def transpose(matrix): + """ + returns the transpose of a matrix + """ + return [[row[i] for row in matrix] for i in range(len(matrix[0]))] + + +def matrix_col(matrix, col): + """ + returns a specified column of a matrix + """ + return matrix_row(transpose(matrix), col) + + +def matrix_scalar_multiply(matrix, scalar): + """ + Returns the matrix multiplied by a scalar + """ + return [vector_multiply(vect, scalar) for vect in matrix] + + +def matrix_vector_multiply(matrix, vector): + """ + Returns the result of multiplying + a given matrix by a given vector + if their shapes are appropriate + """ + if compare(matrix[0], vector): + return [dot(row, vector) for row in matrix] + raise ShapeException + + +def matrix_matrix_multiply(mat1, mat2): + """ + Returns the result of multiplying + a given two matrices + if their shapes are appropriate + """ + if shape(mat1)[1] == shape(mat2)[0]: + return [[dot(row, col) for col in transpose(mat2)] for row in mat1] + + raise ShapeException diff --git a/test_matrix_math.py b/test_matrix_math.py index a71ad36..265ca04 100644 --- a/test_matrix_math.py +++ b/test_matrix_math.py @@ -1,5 +1,6 @@ from matrix_math import * from nose.tools import raises +import nose def is_equal(x, y, tolerance=0.001): @@ -218,7 +219,7 @@ def test_matrix_matrix_multiply(): Matrix * Matrix = Matrix """ - assert matrix_matrix_multiply(A, B) == A + assert matrix_matrix_multiply(A, B) == B assert matrix_matrix_multiply(B, C) == [[8, 10], [20, 25], [32, 40]] @@ -233,3 +234,7 @@ def test_matrix_matrix_multiply_checks_shapes(): """Shape Rule: The number of columns of the first matrix must equal the number of rows of the second matrix.""" matrix_matrix_multiply(A, D) + + +if __name__ == '__main__': + nose.main()