Rewrite matrix.py to match test_serial.py and to be less dependent on numpy
This commit is contained in:
parent
e914001d8d
commit
91f4191a65
170
src/matrix.py
170
src/matrix.py
@ -1,3 +1,5 @@
|
|||||||
|
import math
|
||||||
|
|
||||||
import numpy
|
import numpy
|
||||||
from numpy import linalg
|
from numpy import linalg
|
||||||
|
|
||||||
@ -6,16 +8,18 @@ class Matrix:
|
|||||||
"""
|
"""
|
||||||
This Matrix class represents a real 2D-matrix.
|
This Matrix class represents a real 2D-matrix.
|
||||||
"""
|
"""
|
||||||
__data__: numpy.ndarray
|
__data__: list
|
||||||
__shape__: (int, int)
|
__shape__: (int, int)
|
||||||
|
|
||||||
def __init__(self, data=None, shape=None, structure=None, model=None, n=None):
|
def __init__(self, data=None, shape=None, structure=None, model=None, offset=None, n=None):
|
||||||
"""
|
"""
|
||||||
Creates a new matrix.
|
Creates a new matrix.
|
||||||
Thy type of the matrix depends on the signature and arguments.
|
The type of the matrix depends on the signature and arguments.
|
||||||
|
|
||||||
|
- ``Matrix(list)``: will create a new matrix with the given data in the list and its shape.
|
||||||
- ``Matrix(numpy.ndarray)``: will create a new matrix with the given data in ndarray and its shape.
|
- ``Matrix(numpy.ndarray)``: will create a new matrix with the given data in ndarray and its shape.
|
||||||
- ``Matrix(list, (int,int))``: will create a new nxm matrix with the given rows and columns and data in list.
|
- ``Matrix(list, (int,int))``: will create a new nxm matrix with the given rows and columns and data in list.
|
||||||
|
- ``Matrix(list, str, int, int)``: will create a new square matrix of given size and structure of \"diagonal\"
|
||||||
- ``Matrix(list, str, int)``: will create a new square matrix of given size and structure of either \"unity\", \"diagonal\" or \"tridiagonal\"
|
- ``Matrix(list, str, int)``: will create a new square matrix of given size and structure of either \"unity\", \"diagonal\" or \"tridiagonal\"
|
||||||
- ``Matrix(str, int)``: will create a new square matrix of given size and TODO
|
- ``Matrix(str, int)``: will create a new square matrix of given size and TODO
|
||||||
|
|
||||||
@ -24,12 +28,14 @@ class Matrix:
|
|||||||
:param shape: A tuple containing the amount of rows and columns
|
:param shape: A tuple containing the amount of rows and columns
|
||||||
:param structure: Either \"unity\", \"diagonal\" or \"tridiagonal\"
|
:param structure: Either \"unity\", \"diagonal\" or \"tridiagonal\"
|
||||||
:param model: TODO
|
:param model: TODO
|
||||||
|
:param offset: Offset to diagonal axis
|
||||||
:param n: Amount of rows of a square matrix or offset in case of diagonal structure
|
:param n: Amount of rows of a square matrix or offset in case of diagonal structure
|
||||||
|
|
||||||
:type data: list | numpy.ndarray
|
:type data: list | numpy.ndarray
|
||||||
:type shape: (int, int)
|
:type shape: (int, int)
|
||||||
:type structure: str
|
:type structure: str
|
||||||
:type model: str
|
:type model: str
|
||||||
|
:type offset: int
|
||||||
:type n: int
|
:type n: int
|
||||||
|
|
||||||
:rtype: Matrix
|
:rtype: Matrix
|
||||||
@ -37,41 +43,46 @@ class Matrix:
|
|||||||
# Case Matrix(str, int)
|
# Case Matrix(str, int)
|
||||||
if n is not None and model is not None:
|
if n is not None and model is not None:
|
||||||
... # TODO: what shall one do here?
|
... # TODO: what shall one do here?
|
||||||
|
# Case: Matrix(list, str, int, int)
|
||||||
|
elif n is not None and offset is not None and structure == "diagonal" and data is not None:
|
||||||
|
diag = numpy.diag(data * (n - abs(offset)), offset)
|
||||||
|
self.__data__ = diag.tolist()
|
||||||
|
self.__shape__ = diag.shape
|
||||||
# Case: Matrix(list, str, int)
|
# Case: Matrix(list, str, int)
|
||||||
elif n is not None and structure is not None and data is not None:
|
elif n is not None and structure is not None and data is not None:
|
||||||
if structure == "unity":
|
if structure == "unity":
|
||||||
... # TODO: what does it mean?
|
... # TODO: what does it mean?
|
||||||
elif structure == "diagonal":
|
|
||||||
diag = numpy.diag(data, n)
|
|
||||||
self.__data__ = diag
|
|
||||||
self.__shape__ = diag.shape
|
|
||||||
elif structure == "tridiagonal":
|
elif structure == "tridiagonal":
|
||||||
if len(data) != 3:
|
if len(data) != 3:
|
||||||
raise ValueError("If structure is tridiagonal, then the given data must be of length 3")
|
raise ValueError("If structure is tridiagonal, then the given data must be of length 3")
|
||||||
tridiag = numpy.diag([data[0]] * (n - 1), -1) + numpy.diag([data[1]] * n, 0) + numpy.diag(
|
tridiag = numpy.diag([data[0]] * (n - 1), -1) + numpy.diag([data[1]] * n, 0) + numpy.diag(
|
||||||
[data[2]] * (n - 1), 1)
|
[data[2]] * (n - 1), 1)
|
||||||
self.__data__ = tridiag
|
self.__data__ = tridiag.tolist()
|
||||||
self.__shape__ = tridiag.shape
|
self.__shape__ = tridiag.shape
|
||||||
# Case: Matrix(list, str, int)
|
# Case: Matrix(list, (int,int))
|
||||||
elif shape is not None and data is not None:
|
elif shape is not None and data is not None:
|
||||||
self.__shape__ = shape
|
self.__shape__ = shape
|
||||||
self.__data__ = numpy.array(data).reshape(shape)
|
self.__data__ = numpy.array(data).reshape(shape).tolist()
|
||||||
# Case: Matrix(numpy.ndarray)
|
# Case: Matrix(numpy.ndarray) or Matrix(list)
|
||||||
elif data is not None:
|
elif data is not None:
|
||||||
try:
|
if isinstance(data, numpy.ndarray):
|
||||||
data.shape[1]
|
try:
|
||||||
except IndexError:
|
data.shape[1]
|
||||||
self.__shape__ = (data.shape[0], 1)
|
except IndexError:
|
||||||
else:
|
self.__shape__ = (data.shape[0], 1)
|
||||||
self.__shape__ = data.shape
|
else:
|
||||||
|
self.__shape__ = (data.shape[0], data.shape[1])
|
||||||
|
elif isinstance(data, list):
|
||||||
|
self.__shape__ = (len(data), len(data[0]))
|
||||||
self.__data__ = data
|
self.__data__ = data
|
||||||
else:
|
else:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"Only following signatures are allowed: (numpy.ndarray), (list, tuple), (list, str, int), (str, int)")
|
"Only following signatures are allowed: "
|
||||||
|
"(list), (numpy.ndarray), (list, tuple), (list, str, int), (list, str, int, int), (str, int)")
|
||||||
|
|
||||||
def get_data(self):
|
def get_data(self):
|
||||||
"""
|
"""
|
||||||
:return: the data of the matrix as a ``numpy.ndarray``
|
:return: the data of the matrix as a ``list``
|
||||||
"""
|
"""
|
||||||
return self.__data__
|
return self.__data__
|
||||||
|
|
||||||
@ -85,7 +96,16 @@ class Matrix:
|
|||||||
"""
|
"""
|
||||||
:return: the transpose of the matrix
|
:return: the transpose of the matrix
|
||||||
"""
|
"""
|
||||||
return Matrix(self.__data__.transpose())
|
rows = self.__shape__[0]
|
||||||
|
cols = self.__shape__[1]
|
||||||
|
|
||||||
|
transposed_data = [[0 for _ in range(rows)] for _ in range(cols)]
|
||||||
|
|
||||||
|
for i in range(rows):
|
||||||
|
for j in range(cols):
|
||||||
|
transposed_data[j][i] = self.__data__[i][j]
|
||||||
|
|
||||||
|
return Matrix(transposed_data, (cols, rows))
|
||||||
|
|
||||||
def T(self):
|
def T(self):
|
||||||
"""
|
"""
|
||||||
@ -103,28 +123,49 @@ class Matrix:
|
|||||||
:return: True if data in the matrix are equal to the given data in other for each component, otherwise False
|
:return: True if data in the matrix are equal to the given data in other for each component, otherwise False
|
||||||
"""
|
"""
|
||||||
if isinstance(other, Matrix):
|
if isinstance(other, Matrix):
|
||||||
to_compare = other.__data__
|
data_to_compare = other.__data__
|
||||||
|
if self.__shape__ != other.__shape__:
|
||||||
|
return False
|
||||||
elif isinstance(other, list):
|
elif isinstance(other, list):
|
||||||
to_compare = numpy.array(other)
|
data_to_compare = other
|
||||||
|
if self.__shape__[0] != len(other) or self.__shape__[1] != len(other[0]):
|
||||||
|
return False
|
||||||
elif isinstance(other, numpy.ndarray):
|
elif isinstance(other, numpy.ndarray):
|
||||||
to_compare = other
|
data_to_compare = other.tolist()
|
||||||
else:
|
else:
|
||||||
raise ValueError("Matrix type is not comparable to type of given ``other``")
|
raise ValueError("Matrix type is not comparable to type of given ``other``")
|
||||||
return (self.__data__ == to_compare).all()
|
|
||||||
|
for i in range(len(self.__data__)):
|
||||||
|
for j in range(len(self.__data__[i])):
|
||||||
|
if self.__data__[i][j] != data_to_compare[i][j]:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return str(self.__data__)
|
return str(numpy.array(self.__data__))
|
||||||
|
|
||||||
def __neg__(self):
|
def __neg__(self):
|
||||||
return Matrix(-self.__data__)
|
rows = range(self.__shape__[0])
|
||||||
|
cols = range(self.__shape__[1])
|
||||||
|
return Matrix([[-(self.__data__[i][j]) for j in cols] for i in rows], self.__shape__)
|
||||||
|
|
||||||
|
def __add_matrix_internal__(self, other):
|
||||||
|
rows = self.__shape__[0]
|
||||||
|
cols = self.__shape__[1]
|
||||||
|
return [[(self.__data__[i][j] + other.__data__[i][j]) for j in range(cols)] for i in range(rows)]
|
||||||
|
|
||||||
|
def __add_scalar_internal__(self, other):
|
||||||
|
rows = self.__shape__[0]
|
||||||
|
cols = self.__shape__[1]
|
||||||
|
return [[(self.__data__[i][j] + other) for j in range(cols)] for i in range(rows)]
|
||||||
|
|
||||||
def __add__(self, other):
|
def __add__(self, other):
|
||||||
if isinstance(other, Matrix):
|
if isinstance(other, Matrix):
|
||||||
if self.__shape__ != other.__shape__:
|
if self.__shape__ != other.__shape__:
|
||||||
raise ValueError("The shape of the operands must be the same")
|
raise ValueError("The shape of the operands must be the same")
|
||||||
return Matrix(self.__data__ + other.__data__)
|
return Matrix(self.__add_matrix_internal__(other), self.__shape__)
|
||||||
elif isinstance(other, int) or isinstance(other, float):
|
elif isinstance(other, int) or isinstance(other, float):
|
||||||
return Matrix(self.__data__ + other)
|
return Matrix(self.__add_scalar_internal__(other), self.__shape__)
|
||||||
else:
|
else:
|
||||||
raise ValueError("Only a number or another ``Matrix`` can be added to a ``Matrix``")
|
raise ValueError("Only a number or another ``Matrix`` can be added to a ``Matrix``")
|
||||||
|
|
||||||
@ -137,26 +178,47 @@ class Matrix:
|
|||||||
def __rsub__(self, other):
|
def __rsub__(self, other):
|
||||||
return -self + other
|
return -self + other
|
||||||
|
|
||||||
|
def __truediv_scalar_internal__(self, other):
|
||||||
|
rows = self.__shape__[0]
|
||||||
|
cols = self.__shape__[1]
|
||||||
|
return [[(self.__data__[i][j] / other) for j in range(cols)] for i in range(rows)]
|
||||||
|
|
||||||
|
def __truediv__(self, other):
|
||||||
|
if isinstance(other, int) or isinstance(other, float):
|
||||||
|
return Matrix(self.__truediv_scalar_internal__(other), self.__shape__)
|
||||||
|
else:
|
||||||
|
raise ValueError("A ``Matrix`` can only be divided ba a number")
|
||||||
|
|
||||||
|
def __mul_matrix_internal__(self, other):
|
||||||
|
rows = self.__shape__[0]
|
||||||
|
cols = other.__shape__[1]
|
||||||
|
|
||||||
|
new_data = [[0 for _ in range(rows)] for _ in range(cols)]
|
||||||
|
|
||||||
|
for i in range(rows):
|
||||||
|
for k in range(cols):
|
||||||
|
new_data[i][k] = sum([self.__data__[i][j] * other.__data__[j][k] for j in range(self.__shape__[1])])
|
||||||
|
return new_data
|
||||||
|
|
||||||
|
def __mul_scalar_internal__(self, other):
|
||||||
|
cols = range(self.__shape__[1])
|
||||||
|
rows = range(self.__shape__[0])
|
||||||
|
return [[(self.__data__[i][j] * other) for j in cols] for i in rows]
|
||||||
|
|
||||||
def __mul__(self, other):
|
def __mul__(self, other):
|
||||||
if isinstance(other, Matrix):
|
if isinstance(other, Matrix):
|
||||||
if self.__shape__[1] != other.__shape__[0]:
|
if self.__shape__[1] != other.__shape__[0]:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"The amount of columns of the first operand must match the amount of rows of the second operand")
|
"The amount of columns of the first operand must match the amount of rows of the second operand")
|
||||||
return Matrix(self.__data__ @ other.__data__)
|
return Matrix(self.__mul_matrix_internal__(other), (self.__shape__[0], other.__shape__[1]))
|
||||||
elif isinstance(other, int) or isinstance(other, float):
|
elif isinstance(other, int) or isinstance(other, float):
|
||||||
return Matrix(other * self.__data__)
|
return Matrix(self.__mul_scalar_internal__(other), self.__shape__)
|
||||||
else:
|
else:
|
||||||
raise ValueError("Only a number or another ``Matrix`` can be multiplied to a ``Matrix``")
|
raise ValueError("Only a number or another ``Matrix`` can be multiplied to a ``Matrix``")
|
||||||
|
|
||||||
def __rmul__(self, other):
|
def __rmul__(self, other):
|
||||||
return self * other
|
return self * other
|
||||||
|
|
||||||
def __truediv__(self, other):
|
|
||||||
if isinstance(other, int) or isinstance(other, float):
|
|
||||||
return Matrix(self.__data__ / other)
|
|
||||||
else:
|
|
||||||
raise ValueError("A ``Matrix`` can only be divided ba a number")
|
|
||||||
|
|
||||||
def norm(self, f: str = "frobenius"):
|
def norm(self, f: str = "frobenius"):
|
||||||
"""
|
"""
|
||||||
Calculates the norm of the matrix.
|
Calculates the norm of the matrix.
|
||||||
@ -168,15 +230,35 @@ class Matrix:
|
|||||||
|
|
||||||
:return: the norm as a number
|
:return: the norm as a number
|
||||||
"""
|
"""
|
||||||
t = "fro"
|
norm = 0
|
||||||
if f == "colsum":
|
|
||||||
t = 1
|
rows = self.__shape__[0]
|
||||||
elif f == "rowsum":
|
cols = self.__shape__[1]
|
||||||
t = numpy.inf
|
|
||||||
return linalg.norm(self.__data__, t)
|
if f == "frobenius":
|
||||||
|
abs_sum = 0
|
||||||
|
for i in range(rows):
|
||||||
|
for j in range(cols):
|
||||||
|
abs_sum += abs(self.__data__[i][j])**2
|
||||||
|
norm = math.sqrt(abs_sum)
|
||||||
|
elif f == "col sum":
|
||||||
|
row_sum = [0 for _ in range(cols)]
|
||||||
|
for j in range(cols):
|
||||||
|
for i in range(rows):
|
||||||
|
row_sum[j] += abs(self.__data__[i][j])
|
||||||
|
norm = max(row_sum)
|
||||||
|
elif f == "row sum":
|
||||||
|
col_sum = [0 for _ in range(rows)]
|
||||||
|
for i in range(rows):
|
||||||
|
for j in range(cols):
|
||||||
|
col_sum[i] += abs(self.__data__[i][j])
|
||||||
|
norm = max(col_sum)
|
||||||
|
return norm
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
return self.__data__[key]
|
return numpy.array(self.__data__)[key].tolist()
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
def __setitem__(self, key, value):
|
||||||
self.__data__[key] = value
|
manipulated_data = numpy.array(self.__data__)
|
||||||
|
manipulated_data[key] = value
|
||||||
|
self.__data__ = manipulated_data.tolist()
|
||||||
|
@ -28,17 +28,6 @@ class TestMatrix(TestCase):
|
|||||||
expected = [[0, 1, 2]]
|
expected = [[0, 1, 2]]
|
||||||
self.assertEqual(expected, actual)
|
self.assertEqual(expected, actual)
|
||||||
|
|
||||||
def test_should_create_vectorlike_matrix_from_numpy_array_with_shape_3_1(self):
|
|
||||||
data = numpy.array([0, 1, 2])
|
|
||||||
actual = Matrix(data)
|
|
||||||
|
|
||||||
actual_shape = actual.shape()
|
|
||||||
expected_shape = (3, 1)
|
|
||||||
self.assertEqual(expected_shape, actual_shape)
|
|
||||||
|
|
||||||
expected = [0, 1, 2]
|
|
||||||
self.assertEqual(expected, actual)
|
|
||||||
|
|
||||||
def test_should_create_matrix_from_list_with_shape_2_2(self):
|
def test_should_create_matrix_from_list_with_shape_2_2(self):
|
||||||
data = [0, 1, 2, 3]
|
data = [0, 1, 2, 3]
|
||||||
actual = Matrix(data, shape=(2, 2))
|
actual = Matrix(data, shape=(2, 2))
|
||||||
@ -50,9 +39,20 @@ class TestMatrix(TestCase):
|
|||||||
expected = [[0, 1], [2, 3]]
|
expected = [[0, 1], [2, 3]]
|
||||||
self.assertEqual(expected, actual)
|
self.assertEqual(expected, actual)
|
||||||
|
|
||||||
|
def test_should_create_matrix_from_matrixlike_list_with_shape_2_3(self):
|
||||||
|
data = [[0, 1, 2], [3, 4, 5]]
|
||||||
|
actual = Matrix(data, shape=(2, 3))
|
||||||
|
|
||||||
|
actual_shape = actual.shape()
|
||||||
|
expected_shape = (2, 3)
|
||||||
|
self.assertEqual(expected_shape, actual_shape)
|
||||||
|
|
||||||
|
expected = [[0, 1, 2], [3, 4, 5]]
|
||||||
|
self.assertEqual(expected, actual)
|
||||||
|
|
||||||
def test_should_create_diagonal_matrix_from_list(self):
|
def test_should_create_diagonal_matrix_from_list(self):
|
||||||
data = [1, 1, 1]
|
data = [1]
|
||||||
actual = Matrix(data, structure="diagonal", n=0)
|
actual = Matrix(data, structure="diagonal", offset=0, n=3)
|
||||||
|
|
||||||
actual_shape = actual.shape()
|
actual_shape = actual.shape()
|
||||||
expected_shape = (3, 3)
|
expected_shape = (3, 3)
|
||||||
@ -62,8 +62,8 @@ class TestMatrix(TestCase):
|
|||||||
self.assertEqual(expected, actual)
|
self.assertEqual(expected, actual)
|
||||||
|
|
||||||
def test_should_create_diagonal_matrix_from_list_with_offset_1(self):
|
def test_should_create_diagonal_matrix_from_list_with_offset_1(self):
|
||||||
data = [1, 1, 1]
|
data = [1]
|
||||||
actual = Matrix(data, structure="diagonal", n=1)
|
actual = Matrix(data, structure="diagonal", offset=1, n=4)
|
||||||
|
|
||||||
actual_shape = actual.shape()
|
actual_shape = actual.shape()
|
||||||
expected_shape = (4, 4)
|
expected_shape = (4, 4)
|
||||||
@ -188,6 +188,15 @@ class TestMatrix(TestCase):
|
|||||||
|
|
||||||
self.assertEqual(expected, actual)
|
self.assertEqual(expected, actual)
|
||||||
|
|
||||||
|
def test_should_div_matrix_by_scalar(self):
|
||||||
|
m = Matrix([5, 10, 15, 20], (2, 2))
|
||||||
|
s = 5
|
||||||
|
|
||||||
|
actual = m / s
|
||||||
|
expected = Matrix([1, 2, 3, 4], (2, 2))
|
||||||
|
|
||||||
|
self.assertEqual(expected, actual)
|
||||||
|
|
||||||
def test_should_raise_value_missmatch_error_while_dividing_with_other_than_scalar(self):
|
def test_should_raise_value_missmatch_error_while_dividing_with_other_than_scalar(self):
|
||||||
m = Matrix([1, 2, 3, 4], (2, 2))
|
m = Matrix([1, 2, 3, 4], (2, 2))
|
||||||
o = ""
|
o = ""
|
||||||
@ -195,20 +204,29 @@ class TestMatrix(TestCase):
|
|||||||
self.assertRaises(ValueError, lambda: m / o)
|
self.assertRaises(ValueError, lambda: m / o)
|
||||||
|
|
||||||
def test_should_mul_matrices_1(self):
|
def test_should_mul_matrices_1(self):
|
||||||
m1 = Matrix([1, 2], (2, 1))
|
m1 = Matrix([1, 2, 3, 4], (2, 2))
|
||||||
m2 = Matrix([3, 4], (1, 2))
|
m2 = Matrix([4, 3, 2, 1], (2, 2))
|
||||||
|
|
||||||
actual = m1 * m2
|
actual = m1 * m2
|
||||||
expected = Matrix([3, 4, 6, 8], (2, 2))
|
expected = Matrix([8, 5, 20, 13], (2, 2))
|
||||||
|
|
||||||
self.assertEqual(expected, actual)
|
self.assertEqual(expected, actual)
|
||||||
|
|
||||||
def test_should_mul_matrices_2(self):
|
def test_should_mul_matrices_2(self):
|
||||||
m1 = Matrix([1, 2], (1, 2))
|
m1 = Matrix([1, 2, 3, 4, 5, 6], (2, 3))
|
||||||
m2 = Matrix([3, 4], (2, 1))
|
m2 = Matrix([6, 5, 4, 3, 2, 1], (3, 2))
|
||||||
|
|
||||||
actual = m1 * m2
|
actual = m1 * m2
|
||||||
expected = Matrix([11], (1, 1))
|
expected = Matrix([20, 14, 56, 41], (2, 2))
|
||||||
|
|
||||||
|
self.assertEqual(expected, actual)
|
||||||
|
|
||||||
|
def test_should_mul_matrices_3(self):
|
||||||
|
m1 = Matrix([1, 2, 3, 4, 5, 6], (3, 2))
|
||||||
|
m2 = Matrix([6, 5, 4, 3, 2, 1], (2, 3))
|
||||||
|
|
||||||
|
actual = m1 * m2
|
||||||
|
expected = Matrix([12, 9, 6, 30, 23, 16, 48, 37, 26], (3, 3))
|
||||||
|
|
||||||
self.assertEqual(expected, actual)
|
self.assertEqual(expected, actual)
|
||||||
|
|
||||||
@ -236,15 +254,6 @@ class TestMatrix(TestCase):
|
|||||||
|
|
||||||
self.assertEqual(expected, actual)
|
self.assertEqual(expected, actual)
|
||||||
|
|
||||||
def test_should_div_matrix_by_scalar(self):
|
|
||||||
m = Matrix([5, 10, 15, 20], (2, 2))
|
|
||||||
s = 5
|
|
||||||
|
|
||||||
actual = m / s
|
|
||||||
expected = Matrix([1, 2, 3, 4], (2, 2))
|
|
||||||
|
|
||||||
self.assertEqual(expected, actual)
|
|
||||||
|
|
||||||
def test_should_return_frobenius_norm(self):
|
def test_should_return_frobenius_norm(self):
|
||||||
m = Matrix([1, 2, 3, 4], (2, 2))
|
m = Matrix([1, 2, 3, 4], (2, 2))
|
||||||
|
|
||||||
@ -256,7 +265,7 @@ class TestMatrix(TestCase):
|
|||||||
def test_should_return_colsum_norm(self):
|
def test_should_return_colsum_norm(self):
|
||||||
m = Matrix([1, 2, 3, 4], (2, 2))
|
m = Matrix([1, 2, 3, 4], (2, 2))
|
||||||
|
|
||||||
actual = m.norm("colsum")
|
actual = m.norm("col sum")
|
||||||
expected = 6
|
expected = 6
|
||||||
|
|
||||||
self.assertEqual(expected, actual)
|
self.assertEqual(expected, actual)
|
||||||
@ -264,7 +273,7 @@ class TestMatrix(TestCase):
|
|||||||
def test_should_return_rowsum_norm(self):
|
def test_should_return_rowsum_norm(self):
|
||||||
m = Matrix([1, 2, 3, 4], (2, 2))
|
m = Matrix([1, 2, 3, 4], (2, 2))
|
||||||
|
|
||||||
actual = m.norm("rowsum")
|
actual = m.norm("row sum")
|
||||||
expected = 7
|
expected = 7
|
||||||
|
|
||||||
self.assertEqual(expected, actual)
|
self.assertEqual(expected, actual)
|
||||||
@ -289,7 +298,7 @@ class TestMatrix(TestCase):
|
|||||||
m = Matrix([1, 2, 3, 4, 5, 6, 7, 8, 9], (3, 3))
|
m = Matrix([1, 2, 3, 4, 5, 6, 7, 8, 9], (3, 3))
|
||||||
|
|
||||||
actual = m[0]
|
actual = m[0]
|
||||||
expected = Matrix([1, 2, 3], (1, 3))
|
expected = [1, 2, 3]
|
||||||
|
|
||||||
self.assertEqual(expected, actual)
|
self.assertEqual(expected, actual)
|
||||||
|
|
||||||
@ -297,7 +306,7 @@ class TestMatrix(TestCase):
|
|||||||
m = Matrix([1, 2, 3, 4, 5, 6, 7, 8, 9], (3, 3))
|
m = Matrix([1, 2, 3, 4, 5, 6, 7, 8, 9], (3, 3))
|
||||||
|
|
||||||
actual = m[2, 0:2]
|
actual = m[2, 0:2]
|
||||||
expected = Matrix([7, 8], (1, 2))
|
expected = [7, 8]
|
||||||
|
|
||||||
self.assertEqual(expected, actual)
|
self.assertEqual(expected, actual)
|
||||||
|
|
||||||
@ -305,7 +314,7 @@ class TestMatrix(TestCase):
|
|||||||
m = Matrix([1, 2, 3, 4, 5, 6, 7, 8, 9], (3, 3))
|
m = Matrix([1, 2, 3, 4, 5, 6, 7, 8, 9], (3, 3))
|
||||||
|
|
||||||
actual = m[:, 1]
|
actual = m[:, 1]
|
||||||
expected = Matrix([2, 5, 8], (1, 3))
|
expected = [2, 5, 8]
|
||||||
|
|
||||||
self.assertEqual(expected, actual)
|
self.assertEqual(expected, actual)
|
||||||
|
|
||||||
@ -313,7 +322,7 @@ class TestMatrix(TestCase):
|
|||||||
m = Matrix([1, 2, 3, 4, 5, 6, 7, 8, 9], (3, 3))
|
m = Matrix([1, 2, 3, 4, 5, 6, 7, 8, 9], (3, 3))
|
||||||
|
|
||||||
actual = m[[0, 2], 0]
|
actual = m[[0, 2], 0]
|
||||||
expected = Matrix([1, 7], (1, 2))
|
expected = [1, 7]
|
||||||
|
|
||||||
self.assertEqual(expected, actual)
|
self.assertEqual(expected, actual)
|
||||||
|
|
||||||
|
@ -125,9 +125,9 @@ print("\n\nTesting the matrix class -----------------------------------\n\n")
|
|||||||
print("Start 2a 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_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)
|
A = Matrix(a_list)
|
||||||
B = Matrix(structure="tridiagonal", given_size=11)
|
B = Matrix([-1, 2, -1], structure="tridiagonal", n=11)
|
||||||
c_list = [[(i + 1) / (index + 1) for index in range(10)] for i in range(10)]
|
c_list = [[(i + 1) / (index + 1) for index in range(10)] for i in range(10)]
|
||||||
C = Matrix(c_list, given_shape=(10, 10))
|
C = Matrix(c_list, shape=(10, 10))
|
||||||
print("End 2a\n")
|
print("End 2a\n")
|
||||||
|
|
||||||
### 1b __str__ function, string representation
|
### 1b __str__ function, string representation
|
||||||
@ -141,7 +141,7 @@ print("End 2b\n")
|
|||||||
### 1c shape and transpose
|
### 1c shape and transpose
|
||||||
print("Start 2c shape and transpose")
|
print("Start 2c shape and transpose")
|
||||||
# Initialization
|
# Initialization
|
||||||
A = Matrix(np.array([i for i in range(12)]).reshape(-1, 1), given_shape=(4, 3))
|
A = Matrix(np.array([i for i in range(12)]).reshape(-1, 1), shape=(4, 3))
|
||||||
print(f"A has shape {A.shape()} | must be (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() 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(f"A.T().T() has shape {A.T().T().shape()} | must be (4,3)")
|
||||||
@ -150,17 +150,17 @@ print("End 2c\n")
|
|||||||
### 1d addition and substraction
|
### 1d addition and substraction
|
||||||
print("Start 2d addition and substraction")
|
print("Start 2d addition and substraction")
|
||||||
# Initialization
|
# Initialization
|
||||||
A = Matrix(structure="diagonal", given_values=[3], offset=0, given_size=10)
|
A = Matrix(structure="diagonal", data=[3], offset=0, n=10)
|
||||||
print(str(A))
|
print(str(A))
|
||||||
A21 = Matrix(structure="diagonal", given_values=[-1], offset=-1, given_size=10)
|
A21 = Matrix(structure="diagonal", data=[-1], offset=-1, n=10)
|
||||||
print(str(A21))
|
print(str(A21))
|
||||||
A12 = Matrix(structure="diagonal", given_values=[-1], offset=+1, given_size=10)
|
A12 = Matrix(structure="diagonal", data=[-1], offset=+1, n=10)
|
||||||
print(str(A12))
|
print(str(A12))
|
||||||
B = Matrix(structure="diagonal", given_values=[1], offset=0, given_size=10)
|
B = Matrix(structure="diagonal", data=[1], offset=0, n=10)
|
||||||
print(str(B))
|
print(str(B))
|
||||||
# computation
|
# computation
|
||||||
C = A + A21 + A12 - B
|
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(C) + f"must be\n{Matrix(structure='tridiagonal', data=[-1, 2, -1], n=10)}")
|
||||||
print(str(5 + A - 3))
|
print(str(5 + A - 3))
|
||||||
print("End 2d\n")
|
print("End 2d\n")
|
||||||
|
|
||||||
@ -195,21 +195,21 @@ print("End 2f\n")
|
|||||||
|
|
||||||
### 1g norm
|
### 1g norm
|
||||||
print("Start 2g norm")
|
print("Start 2g norm")
|
||||||
A = Matrix(structure="tridiagonal", given_size=50, given_values=[-1, 2, -1])
|
A = Matrix(structure="tridiagonal", n=50, data=[-1, 2, -1])
|
||||||
print(f"Frobenius norm of tridiagonal matrix: {A.norm('frobenius')} | must be 17.263")
|
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"Row sum norm of tridiagonal matrix: {A.norm('row sum')} | must be 4")
|
||||||
print(f"Col sum norm of tridiagonal matrix: {A.norm('col sum')} | must be 2")
|
print(f"Col sum norm of tridiagonal matrix: {A.norm('col sum')} | must be 4")
|
||||||
print("End 2g\n")
|
print("End 2g\n")
|
||||||
|
|
||||||
### 1h negation
|
### 1h negation
|
||||||
print("Start 2h negation")
|
print("Start 2h negation")
|
||||||
A = Matrix(structure="tridiagonal", given_size=50, given_values=[-1, 2, 1])
|
A = Matrix(structure="tridiagonal", n=50, data=[-1, 2, 1])
|
||||||
print(f"Norm of (A + (-A)) is {(A + (-A)).norm('frobenius')} | must be < 1e-8")
|
print(f"Norm of (A + (-A)) is {(A + (-A)).norm('frobenius')} | must be < 1e-8")
|
||||||
print("End 2h\n")
|
print("End 2h\n")
|
||||||
|
|
||||||
### 1i manipulation
|
### 1i manipulation
|
||||||
print("Start 2i manipulation")
|
print("Start 2i manipulation")
|
||||||
A = Matrix(structure="tridiagonal", given_size=10, given_values=[-1, 2, 1])
|
A = Matrix(structure="tridiagonal", n=10, data=[-1, 2, 1])
|
||||||
A[1, 1] = 4
|
A[1, 1] = 4
|
||||||
A[[1, 2, 3], 2] = [-5, -10, 100]
|
A[[1, 2, 3], 2] = [-5, -10, 100]
|
||||||
print(str(A))
|
print(str(A))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user