Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions matrix_object.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
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)
#
# 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 a scalar or Vector.")

# 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):
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.")

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))]
129 changes: 129 additions & 0 deletions test_matrix_object.py
Original file line number Diff line number Diff line change
@@ -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]]