Major changes preparing to satisfy given test_serial.py
This commit is contained in:
parent
c837b75604
commit
e914001d8d
@ -87,6 +87,14 @@ class Matrix:
|
|||||||
"""
|
"""
|
||||||
return Matrix(self.__data__.transpose())
|
return Matrix(self.__data__.transpose())
|
||||||
|
|
||||||
|
def T(self):
|
||||||
|
"""
|
||||||
|
Same as ``matrix.transpose()``
|
||||||
|
|
||||||
|
:return: see ``matrix.transpose()``
|
||||||
|
"""
|
||||||
|
return self.transpose()
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
"""
|
"""
|
||||||
Return ``self==value``
|
Return ``self==value``
|
||||||
|
@ -1,13 +1,17 @@
|
|||||||
|
import numpy
|
||||||
|
|
||||||
from matrix import Matrix
|
from matrix import Matrix
|
||||||
|
|
||||||
|
|
||||||
class Vector(Matrix):
|
class Vector(Matrix):
|
||||||
def __init__(self, data: list | int):
|
def __init__(self, data):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
:type data: list | int
|
:type data: numpy.ndarray | list | int
|
||||||
"""
|
"""
|
||||||
if isinstance(data, list):
|
if isinstance(data, numpy.ndarray):
|
||||||
|
super().__init__(data)
|
||||||
|
elif isinstance(data, list):
|
||||||
super().__init__(data, (len(data), 1))
|
super().__init__(data, (len(data), 1))
|
||||||
elif isinstance(data, int):
|
elif isinstance(data, int):
|
||||||
self.__init__([0] * data)
|
self.__init__([0] * data)
|
||||||
@ -17,11 +21,16 @@ class Vector(Matrix):
|
|||||||
def get_dimension(self):
|
def get_dimension(self):
|
||||||
return super().shape()[0]
|
return super().shape()[0]
|
||||||
|
|
||||||
|
def transpose(self):
|
||||||
|
return Vector(self.__data__.reshape(self.__shape__[1], self.__shape__[0]))
|
||||||
|
|
||||||
def __mul__(self, other):
|
def __mul__(self, other):
|
||||||
if isinstance(other, Vector):
|
if isinstance(other, Vector):
|
||||||
return (super().transpose().__mul__(other))[0][0]
|
if self.shape() == other.shape():
|
||||||
|
return Vector(self.__data__ * other.__data__)
|
||||||
|
return super().__mul__(other)[0][0]
|
||||||
elif isinstance(other, int) or isinstance(other, float):
|
elif isinstance(other, int) or isinstance(other, float):
|
||||||
return super().__mul__(other)
|
return Vector(super().__mul__(other).__data__)
|
||||||
else:
|
else:
|
||||||
raise ValueError("A vector can only be multiplied with an vector (dot product) or a scalar")
|
raise ValueError("A vector can only be multiplied with an vector (dot product) or a scalar")
|
||||||
|
|
||||||
@ -29,7 +38,19 @@ class Vector(Matrix):
|
|||||||
return self * other
|
return self * other
|
||||||
|
|
||||||
def norm(self, **kwargs):
|
def norm(self, **kwargs):
|
||||||
|
"""
|
||||||
|
Computes the 2-norm of the vector which is the Frobenius-Norm of a nx1 matrix.
|
||||||
|
|
||||||
|
:param kwargs: ignored
|
||||||
|
:return: the 2-norm of the vector
|
||||||
|
"""
|
||||||
return super().norm()
|
return super().norm()
|
||||||
|
|
||||||
def normalize(self):
|
def normalize(self):
|
||||||
|
"""
|
||||||
|
A normalized vector has the length (norm) 1.
|
||||||
|
To achieve that the vector is divided by the norm of itself.
|
||||||
|
|
||||||
|
:return: the normalized vector
|
||||||
|
"""
|
||||||
return self / self.norm()
|
return self / self.norm()
|
||||||
|
@ -98,7 +98,7 @@ class TestMatrix(TestCase):
|
|||||||
|
|
||||||
self.assertNotEqual(m1, m2)
|
self.assertNotEqual(m1, m2)
|
||||||
|
|
||||||
def test_should_transpose_matrix(self):
|
def test_should_transpose_square_matrix(self):
|
||||||
data = [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
data = [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||||
actual = Matrix(data, (3, 3))
|
actual = Matrix(data, (3, 3))
|
||||||
|
|
||||||
@ -106,6 +106,14 @@ class TestMatrix(TestCase):
|
|||||||
expected = [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
|
expected = [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
|
||||||
self.assertEqual(expected, actual)
|
self.assertEqual(expected, actual)
|
||||||
|
|
||||||
|
def test_should_transpose_nonsquare_matrix(self):
|
||||||
|
data = [1, 2, 3, 4, 5, 6]
|
||||||
|
actual = Matrix(data, (2, 3))
|
||||||
|
|
||||||
|
actual = actual.transpose()
|
||||||
|
expected = [[1, 4], [2, 5], [3, 6]]
|
||||||
|
self.assertEqual(expected, actual)
|
||||||
|
|
||||||
def test_should_negate_matrix(self):
|
def test_should_negate_matrix(self):
|
||||||
m = Matrix([1, 2, 3, 4], (2, 2))
|
m = Matrix([1, 2, 3, 4], (2, 2))
|
||||||
|
|
||||||
|
216
test/test_serial.py
Normal file
216
test/test_serial.py
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from matrix import Matrix
|
||||||
|
from vector import Vector
|
||||||
|
|
||||||
|
np.random.seed(0)
|
||||||
|
###############
|
||||||
|
# Testing the vector class
|
||||||
|
print("\n\nTesting the vector class -----------------------------------\n\n")
|
||||||
|
###############
|
||||||
|
|
||||||
|
### 1a Initialization
|
||||||
|
print("Start 1a initialization")
|
||||||
|
# from list
|
||||||
|
x1 = [1, 2, 3, 4, 5]
|
||||||
|
vec_x1 = Vector(x1)
|
||||||
|
# from numpy array
|
||||||
|
x2 = np.random.uniform(0, 1, 10000)
|
||||||
|
vec_x2 = Vector(x2)
|
||||||
|
print("End 1a\n")
|
||||||
|
|
||||||
|
### 1b __str__ function, string representation
|
||||||
|
print("Start 1b string representation")
|
||||||
|
print(f"vec_x1 values: {str(vec_x1)}")
|
||||||
|
print(f"vec_x2 values: {str(vec_x2)}")
|
||||||
|
print("End 1b\n")
|
||||||
|
|
||||||
|
### 1c shape and transpose
|
||||||
|
print("Start 1c shape and transpose")
|
||||||
|
# shape property of the vector
|
||||||
|
print(f"vec_x1 has shape {vec_x1.shape()} | must be (5,1)") # Hint: numpy.reshape
|
||||||
|
# transposition (property) of the vector, only "cosmetic" change
|
||||||
|
print(f"vec_x2.T() has shape {vec_x2.T().shape()} | must be (1,10000)")
|
||||||
|
print(f"vec_x2.T().T() has shape {vec_x2.T().T().shape()} | must be (10000,1)")
|
||||||
|
print("End 1c\n")
|
||||||
|
|
||||||
|
### 1d addition and substraction
|
||||||
|
print("Start 1d addition and substraction")
|
||||||
|
# intitialization
|
||||||
|
a = Vector([1, 3, 5, 7, 9])
|
||||||
|
b = Vector([-2, 5, 1, 0, -3])
|
||||||
|
# computation
|
||||||
|
x = a + b
|
||||||
|
print(f"a + b = {str(x)} | must be {np.array([1, 3, 5, 7, 9]) + np.array([-2, 5, 1, 0, -3])}")
|
||||||
|
y = a - b
|
||||||
|
print(f"a - b = {str(y)} | must be {np.array([1, 3, 5, 7, 9]) - np.array([-2, 5, 1, 0, -3])}")
|
||||||
|
try:
|
||||||
|
x_false = a + b.T()
|
||||||
|
except ValueError as e:
|
||||||
|
print("The correct result is this error: " + str(e))
|
||||||
|
else:
|
||||||
|
print("It is required to raise a system error, e. g., ValueError, since dimensions mismatch!")
|
||||||
|
try:
|
||||||
|
x_false = a - b.T()
|
||||||
|
except ValueError as e:
|
||||||
|
print("The correct result is this error: " + str(e))
|
||||||
|
else:
|
||||||
|
print("It is required to raise a system error, e. g., ValueError, since dimensions mismatch!")
|
||||||
|
print("End 1d\n")
|
||||||
|
|
||||||
|
### 1e multiplication
|
||||||
|
print("Start 1e multiplication")
|
||||||
|
# intitialization
|
||||||
|
a = Vector([1, 3, 5, 7, 9])
|
||||||
|
b = Vector([-2, 5, 1, 0, -3])
|
||||||
|
# computation with vectors
|
||||||
|
x = a.T() * b # scalar
|
||||||
|
print(f"a.T() * b = {str(x)} | must be {np.sum(np.array([1, 3, 5, 7, 9]) * np.array([-2, 5, 1, 0, -3]))}")
|
||||||
|
y = a * b # vector
|
||||||
|
print(f"a * b = {str(y)} | must be {np.array([1, 3, 5, 7, 9]) * np.array([-2, 5, 1, 0, -3])}")
|
||||||
|
z = b * a.T() # matrix
|
||||||
|
print(f"b * a.T() = \n{str(z)} | must be \n{np.outer(np.array([-2, 5, 1, 0, -3]), np.array([1, 3, 5, 7, 9]))}")
|
||||||
|
# computation with scalars
|
||||||
|
x = a * 5
|
||||||
|
print(f"a * 5 = {str(x)} | must be {np.array([1, 3, 5, 7, 9]) * 5}")
|
||||||
|
y = 0.1 * b.T()
|
||||||
|
print(f"0.1 * b.T()= {str(y)} | must be {0.1 * np.array([-2, 5, 1, 0, -3])}")
|
||||||
|
print("End 1e\n")
|
||||||
|
|
||||||
|
### 1f divison
|
||||||
|
print("Start 1f divison")
|
||||||
|
# intitialization
|
||||||
|
a = Vector([1, 3, 5, 7, 9])
|
||||||
|
b = Vector([-2, 5, 1, 7, -3])
|
||||||
|
# computation with vectors
|
||||||
|
x = a / b
|
||||||
|
print(f"a / b = str{x} | must be {np.array([1, 3, 5, 7, 9]) / np.array([-2, 5, 1, 7, -3])}")
|
||||||
|
y = a / 5
|
||||||
|
print(f"a / 5 = str{y} | must be {np.array([1, 3, 5, 7, 9]) / 5} ")
|
||||||
|
print("End 1f\n")
|
||||||
|
|
||||||
|
### 1g norm
|
||||||
|
print("Start 1g norm")
|
||||||
|
# intitialization
|
||||||
|
a = Vector([1, 3, 5, 7, 9])
|
||||||
|
a_norm, a_normalized = a.normalize()
|
||||||
|
print(f"a_norm = {a_norm} | must be {np.linalg.norm([1, 3, 5, 7, 9])}")
|
||||||
|
print(f"a_normalize = {str(a_normalized)} | must be {np.array([1, 3, 5, 7, 9]) / np.linalg.norm([1, 3, 5, 7, 9])}")
|
||||||
|
print("End 1g\n")
|
||||||
|
|
||||||
|
### 1h negation
|
||||||
|
print("Start 1h negation")
|
||||||
|
# intitialization
|
||||||
|
a = Vector([1, 3, 5, 7, 9])
|
||||||
|
x = -a
|
||||||
|
print(f"-a = {str(x)} | must be {-np.array([1, 3, 5, 7, 9])}")
|
||||||
|
print("End 1h\n")
|
||||||
|
|
||||||
|
### 1i manipulation
|
||||||
|
print("Start 1i manipulation")
|
||||||
|
# intitialization
|
||||||
|
a = Vector([1, 3, 5, 7, 9])
|
||||||
|
print(
|
||||||
|
f"a[{str([1, 2, 4])}] = {str(a[1, 2, 4].reshape(3, ))} | must be {np.array([1, 3, 5, 7, 9]).reshape(5, 1)[np.array([1, 2, 4])].reshape(3, )}")
|
||||||
|
a[1, 2, 4] = [-1, -1, -1]
|
||||||
|
print(f"a = {str(a)} | must be {np.array([1, -1, -1, 5, 7, -1])}")
|
||||||
|
print("End 1i\n")
|
||||||
|
|
||||||
|
###############
|
||||||
|
# Testing the matrix class
|
||||||
|
print("\n\nTesting the matrix class -----------------------------------\n\n")
|
||||||
|
###############
|
||||||
|
|
||||||
|
### 1a Initialization
|
||||||
|
print("Start 2a initialization")
|
||||||
|
a_list = np.array([[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], 2 * np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])])
|
||||||
|
A = Matrix(a_list)
|
||||||
|
B = Matrix(structure="tridiagonal", given_size=11)
|
||||||
|
c_list = [[(i + 1) / (index + 1) for index in range(10)] for i in range(10)]
|
||||||
|
C = Matrix(c_list, given_shape=(10, 10))
|
||||||
|
print("End 2a\n")
|
||||||
|
|
||||||
|
### 1b __str__ function, string representation
|
||||||
|
print("Start 2b string representation")
|
||||||
|
# print(B.__str__(full = True))
|
||||||
|
print(str(A))
|
||||||
|
print(str(B))
|
||||||
|
print(str(C))
|
||||||
|
print("End 2b\n")
|
||||||
|
|
||||||
|
### 1c shape and transpose
|
||||||
|
print("Start 2c shape and transpose")
|
||||||
|
# Initialization
|
||||||
|
A = Matrix(np.array([i for i in range(12)]).reshape(-1, 1), given_shape=(4, 3))
|
||||||
|
print(f"A has shape {A.shape()} | must be (4,3)")
|
||||||
|
print(f"A.T() has shape {A.T().shape()} | must be (3,4)")
|
||||||
|
print(f"A.T().T() has shape {A.T().T().shape()} | must be (4,3)")
|
||||||
|
print("End 2c\n")
|
||||||
|
|
||||||
|
### 1d addition and substraction
|
||||||
|
print("Start 2d addition and substraction")
|
||||||
|
# Initialization
|
||||||
|
A = Matrix(structure="diagonal", given_values=[3], offset=0, given_size=10)
|
||||||
|
print(str(A))
|
||||||
|
A21 = Matrix(structure="diagonal", given_values=[-1], offset=-1, given_size=10)
|
||||||
|
print(str(A21))
|
||||||
|
A12 = Matrix(structure="diagonal", given_values=[-1], offset=+1, given_size=10)
|
||||||
|
print(str(A12))
|
||||||
|
B = Matrix(structure="diagonal", given_values=[1], offset=0, given_size=10)
|
||||||
|
print(str(B))
|
||||||
|
# computation
|
||||||
|
C = A + A21 + A12 - B
|
||||||
|
print(str(C) + f"must be\n{Matrix(structure='tridiagonal', given_values=[-1, 2, -1], given_size=10)}")
|
||||||
|
print(str(5 + A - 3))
|
||||||
|
print("End 2d\n")
|
||||||
|
|
||||||
|
### 1e multiplication
|
||||||
|
print("Start 2e multiplication")
|
||||||
|
# initialization
|
||||||
|
a_mat = [[(i0 + 1) / (i1 + 1) for i1 in range(3)] for i0 in range(10)]
|
||||||
|
b_mat = [[(i0 + 1) / (i1 + 1) for i1 in range(10)] for i0 in range(3)]
|
||||||
|
A = Matrix(a_mat)
|
||||||
|
B = Matrix(b_mat)
|
||||||
|
# computation
|
||||||
|
# print(f"A * B =\n{str(A*B)}must be\n{str(np.round(np.array(a_mat) @ np.array(b_mat),decimals=3))}")
|
||||||
|
print(f"Norm of (A*B - np.(A*B)) is {(A * B - Matrix(np.array(a_mat) @ np.array(b_mat))).norm()} | must be < 1e-8")
|
||||||
|
# print(f"A.T() * A =\n{str(A.T()*A)}must be\n{str(np.round(np.array(a_mat).T@np.array(a_mat),decimals=3))}")
|
||||||
|
print(
|
||||||
|
f"Norm of (A.T()*A - np(A.T()*A)) is {(A.T() * A - Matrix(np.array(a_mat).T @ np.array(a_mat))).norm()} | must be < 1e-8")
|
||||||
|
# print(f"A * A.T() =\n{str(A*A.T())}must be\n{str(np.round(np.array(a_mat)@np.array(a_mat).T,decimals=3))}")
|
||||||
|
print(
|
||||||
|
f"Norm of (A*A.T() - np(A*A.T())) is {(A * A.T() - Matrix(np.array(a_mat) @ np.array(a_mat).T)).norm()} | must be < 1e-8")
|
||||||
|
# print(f"B.T() * A.T() =\n{str(B.T()*A.T())}must be\n{str(np.round(np.array(b_mat).T @ np.array(a_mat).T,decimals=3))}")
|
||||||
|
print(
|
||||||
|
f"Norm of (B.T()*A.T() - np.(B.T()*A.T())) is {(B.T() * A.T() - Matrix(np.array(b_mat).T @ np.array(a_mat).T)).norm()} | must be < 1e-8")
|
||||||
|
print("End 2e\n")
|
||||||
|
|
||||||
|
### 1f divison
|
||||||
|
print("Start 2f divison")
|
||||||
|
# initialization
|
||||||
|
A = Matrix(a_mat)
|
||||||
|
# computation
|
||||||
|
print(f"Norm of (A/5 - np.(A/5)) is {(A / 5 - Matrix(np.array(a_mat) / 5)).norm()} | must be < 1e-8")
|
||||||
|
print("End 2f\n")
|
||||||
|
|
||||||
|
### 1g norm
|
||||||
|
print("Start 2g norm")
|
||||||
|
A = Matrix(structure="tridiagonal", given_size=50, given_values=[-1, 2, -1])
|
||||||
|
print(f"Frobenius norm of tridiagonal matrix: {A.norm('frobenius')} | must be 17.263")
|
||||||
|
print(f"Row sum norm of tridiagonal matrix: {A.norm('row sum')} | must be 2")
|
||||||
|
print(f"Col sum norm of tridiagonal matrix: {A.norm('col sum')} | must be 2")
|
||||||
|
print("End 2g\n")
|
||||||
|
|
||||||
|
### 1h negation
|
||||||
|
print("Start 2h negation")
|
||||||
|
A = Matrix(structure="tridiagonal", given_size=50, given_values=[-1, 2, 1])
|
||||||
|
print(f"Norm of (A + (-A)) is {(A + (-A)).norm('frobenius')} | must be < 1e-8")
|
||||||
|
print("End 2h\n")
|
||||||
|
|
||||||
|
### 1i manipulation
|
||||||
|
print("Start 2i manipulation")
|
||||||
|
A = Matrix(structure="tridiagonal", given_size=10, given_values=[-1, 2, 1])
|
||||||
|
A[1, 1] = 4
|
||||||
|
A[[1, 2, 3], 2] = [-5, -10, 100]
|
||||||
|
print(str(A))
|
||||||
|
print("End 2i\n")
|
@ -22,6 +22,14 @@ class TestVector(TestCase):
|
|||||||
|
|
||||||
self.assertEqual(expected, actual)
|
self.assertEqual(expected, actual)
|
||||||
|
|
||||||
|
def test_should_transpose_vector(self):
|
||||||
|
data = [1, 2, 3, 4, 5, 6]
|
||||||
|
actual = Vector(data)
|
||||||
|
|
||||||
|
actual = actual.transpose()
|
||||||
|
expected = [[1, 2, 3, 4, 5, 6]]
|
||||||
|
self.assertEqual(expected, actual)
|
||||||
|
|
||||||
def test_should_neg_vector(self):
|
def test_should_neg_vector(self):
|
||||||
v = Vector([1, 2])
|
v = Vector([1, 2])
|
||||||
|
|
||||||
@ -96,12 +104,21 @@ class TestVector(TestCase):
|
|||||||
|
|
||||||
self.assertEqual(expected, actual)
|
self.assertEqual(expected, actual)
|
||||||
|
|
||||||
def test_should_mul_vectors(self):
|
def test_should_mul_same_shape_vectors(self):
|
||||||
|
v1 = Vector([1, 2])
|
||||||
|
v2 = Vector([3, 4])
|
||||||
|
|
||||||
|
expected = Vector([3, 8])
|
||||||
|
actual = v1 * v2
|
||||||
|
|
||||||
|
self.assertEqual(expected, actual)
|
||||||
|
|
||||||
|
def test_should_mul_vectors_dot(self):
|
||||||
v1 = Vector([1, 2])
|
v1 = Vector([1, 2])
|
||||||
v2 = Vector([3, 4])
|
v2 = Vector([3, 4])
|
||||||
|
|
||||||
expected = 11
|
expected = 11
|
||||||
actual = v1 * v2
|
actual = v1.T() * v2
|
||||||
|
|
||||||
self.assertEqual(expected, actual)
|
self.assertEqual(expected, actual)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user