Change type of Matrix data from list to numpy.ndarray;
Restructure tests to use directly == on a Matrix using ==.all() from numpy.ndarray; Further implementation of the Matrix class
This commit is contained in:
		| @@ -2,10 +2,37 @@ import numpy | ||||
|  | ||||
|  | ||||
| class Matrix: | ||||
|     __data__ = [] | ||||
|     __shape__ = () | ||||
|     """ | ||||
|     This Matrix class represents a real 2D-matrix. | ||||
|     """ | ||||
|     __data__: numpy.ndarray | ||||
|     __shape__: (int, int) | ||||
|  | ||||
|     def __init__(self, data=None, shape=None, structure=None, model=None, size=None): | ||||
|     def __init__(self, data=None, shape=None, structure=None, model=None, n=None): | ||||
|         """ | ||||
|         Creates a new matrix. | ||||
|         Thy type of the matrix depends on the signature and arguments. | ||||
|  | ||||
|         - ``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, 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 | ||||
|  | ||||
|  | ||||
|         :param data: Either a list or an numpy ndarray | ||||
|         :param shape: A tuple containing the amount of rows and columns | ||||
|         :param structure: Either \"unity\", \"diagonal\" or \"tridiagonal\" | ||||
|         :param model: TODO | ||||
|         :param n: Amount of rows of a square matrix or offset in case of diagonal structure | ||||
|  | ||||
|         :type data: list | numpy.ndarray | ||||
|         :type shape: (int, int) | ||||
|         :type structure: str | ||||
|         :type model: str | ||||
|         :type n: int | ||||
|  | ||||
|         :rtype: Matrix | ||||
|         """ | ||||
|         if isinstance(data, numpy.ndarray): | ||||
|             try: | ||||
|                 data.shape[1] | ||||
| @@ -13,23 +40,61 @@ class Matrix: | ||||
|                 self.__shape__ = (data.shape[0], 1) | ||||
|             else: | ||||
|                 self.__shape__ = data.shape | ||||
|             self.__data__ = data.tolist() | ||||
|             self.__data__ = data | ||||
|         elif isinstance(data, list) and isinstance(shape, tuple): | ||||
|             self.__shape__ = shape | ||||
|             self.__data__ = numpy.array(data).reshape(shape).tolist() | ||||
|         elif isinstance(data, list) and isinstance(structure, str) and isinstance(size, int): | ||||
|             ... | ||||
|         elif isinstance(model, str) and isinstance(size, int): | ||||
|             ... | ||||
|             self.__data__ = numpy.array(data).reshape(shape) | ||||
|         elif isinstance(data, list) and isinstance(structure, str) and isinstance(n, int): | ||||
|             if structure == "unity": | ||||
|                 ...  # TODO: what does it mean? | ||||
|             elif structure == "diagonal": | ||||
|                 diag = numpy.diag(data, n) | ||||
|                 self.__data__ = diag | ||||
|                 self.__shape__ = diag.shape | ||||
|             elif structure == "tridiagonal": | ||||
|                 if len(data) != 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([data[2]] * (n-1), 1) | ||||
|                 self.__data__ = tridiag | ||||
|                 self.__shape__ = tridiag.shape | ||||
|         elif isinstance(model, str) and isinstance(n, int): | ||||
|             ...  # TODO: what shall one do here? | ||||
|         else: | ||||
|             raise ValueError("Only following signatures are allowed: " | ||||
|                              "(numpy.ndarray), (list, tuple), (list, str, int), (str, int)") | ||||
|             raise ValueError("Only following signatures are allowed: (numpy.ndarray), (list, tuple), (list, str, int), (str, int)") | ||||
|  | ||||
|     def get_data(self): | ||||
|         """ | ||||
|         :return: the data of the matrix as a ``numpy.ndarray`` | ||||
|         """ | ||||
|         return self.__data__ | ||||
|  | ||||
|     def shape(self): | ||||
|         """ | ||||
|         :return: the shape of the matrix, which is ``(rows, columns)`` | ||||
|         """ | ||||
|         return self.__shape__ | ||||
|  | ||||
|     def transpose(self): | ||||
|         """ | ||||
|         :return: the transpose of the matrix | ||||
|         """ | ||||
|         return Matrix(self.__data__.transpose()) | ||||
|  | ||||
|     def __eq__(self, other): | ||||
|         return self.__data__ == other.__data__ | ||||
|         """ | ||||
|         Return ``self==value`` | ||||
|  | ||||
|         :param other: The object to compare to; must be either a ``Matrix``, a ``list`` or a ``numpy.ndarray`` | ||||
|         :return: True if data in the matrix is totally equal to the given data in other, otherwise False | ||||
|         """ | ||||
|         if isinstance(other, Matrix): | ||||
|             return (self.__data__ == other.__data__).all() | ||||
|         elif isinstance(other, list): | ||||
|             return (self.__data__ == numpy.array(other)).all() | ||||
|         elif isinstance(other, numpy.ndarray): | ||||
|             return (self.__data__ == other).all() | ||||
|         else: | ||||
|             raise ValueError("Matrix type is not comparable to type of given ``other``") | ||||
|  | ||||
|     def __str__(self): | ||||
|         return str(self.__data__) | ||||
|   | ||||
| @@ -1,3 +1,5 @@ | ||||
| import numpy | ||||
|  | ||||
| from matrix import Matrix | ||||
|  | ||||
|  | ||||
| @@ -5,6 +7,11 @@ class Vector(Matrix): | ||||
|     __data__ = [] | ||||
|  | ||||
|     def __init__(self, data): | ||||
|         """ | ||||
|  | ||||
|         :type data: list | int | ||||
|         """ | ||||
|         super().__init__(numpy.array([0]))  # TODO: remove in future | ||||
|         if isinstance(data, list): | ||||
|             self.__data__ = data | ||||
|         elif isinstance(data, int): | ||||
|   | ||||
| @@ -8,48 +8,88 @@ from matrix import Matrix | ||||
| class TestMatrix(TestCase): | ||||
|     def test_should_create_matrix_from_numpy_array_with_shape_3_2(self): | ||||
|         data = numpy.array([[0, 1], [2, 3], [4, 5]]) | ||||
|         m = Matrix(data) | ||||
|         actual = Matrix(data) | ||||
|  | ||||
|         actual_shape = m.shape() | ||||
|         actual_shape = actual.shape() | ||||
|         expected_shape = (3, 2) | ||||
|         self.assertEqual(expected_shape, actual_shape) | ||||
|  | ||||
|         actual_data = m.get_data() | ||||
|         expected_data = [[0, 1], [2, 3], [4, 5]] | ||||
|         self.assertEqual(expected_data, actual_data) | ||||
|         expected = [[0, 1], [2, 3], [4, 5]] | ||||
|         self.assertEqual(expected, actual) | ||||
|  | ||||
|     def test_should_create_matrix_from_numpy_array_with_shape_1_3(self): | ||||
|         data = numpy.array([[0, 1, 2]]) | ||||
|         m = Matrix(data) | ||||
|         actual = Matrix(data) | ||||
|  | ||||
|         actual_shape = m.shape() | ||||
|         actual_shape = actual.shape() | ||||
|         expected_shape = (1, 3) | ||||
|         self.assertEqual(expected_shape, actual_shape) | ||||
|  | ||||
|         actual_data = m.get_data() | ||||
|         expected_data = [[0, 1, 2]] | ||||
|         self.assertEqual(expected_data, actual_data) | ||||
|         expected = [[0, 1, 2]] | ||||
|         self.assertEqual(expected, actual) | ||||
|  | ||||
|     def test_should_create_vectorlike_matrix_from_numpy_array_with_shape_3_1(self): | ||||
|         data = numpy.array([0, 1, 2]) | ||||
|         m = Matrix(data) | ||||
|         actual = Matrix(data) | ||||
|  | ||||
|         actual_shape = m.shape() | ||||
|         actual_shape = actual.shape() | ||||
|         expected_shape = (3, 1) | ||||
|         self.assertEqual(expected_shape, actual_shape) | ||||
|  | ||||
|         actual_data = m.get_data() | ||||
|         expected_data = [0, 1, 2] | ||||
|         self.assertEqual(expected_data, actual_data) | ||||
|         expected = [0, 1, 2] | ||||
|         self.assertEqual(expected, actual) | ||||
|  | ||||
|     def test_should_create_matrix_from_list_with_shape_2_2(self): | ||||
|         data = [0, 1, 2, 3] | ||||
|         m = Matrix(data, shape=(2, 2)) | ||||
|         actual = Matrix(data, shape=(2, 2)) | ||||
|  | ||||
|         actual_shape = m.shape() | ||||
|         actual_shape = actual.shape() | ||||
|         expected_shape = (2, 2) | ||||
|         self.assertEqual(expected_shape, actual_shape) | ||||
|  | ||||
|         actual_data = m.get_data() | ||||
|         expected_data = [[0, 1], [2, 3]] | ||||
|         self.assertEqual(expected_data, actual_data) | ||||
|         expected = [[0, 1], [2, 3]] | ||||
|         self.assertEqual(expected, actual) | ||||
|  | ||||
|     def test_should_create_diagonal_matrix_from_list(self): | ||||
|         data = [1, 1, 1] | ||||
|         actual = Matrix(data, structure="diagonal", n=0) | ||||
|  | ||||
|         actual_shape = actual.shape() | ||||
|         expected_shape = (3, 3) | ||||
|         self.assertEqual(expected_shape, actual_shape) | ||||
|  | ||||
|         expected = [[1, 0, 0], [0, 1, 0], [0, 0, 1]] | ||||
|         self.assertEqual(expected, actual) | ||||
|  | ||||
|     def test_should_create_diagonal_matrix_from_list_with_offset_1(self): | ||||
|         data = [1, 1, 1] | ||||
|         actual = Matrix(data, structure="diagonal", n=1) | ||||
|  | ||||
|         actual_shape = actual.shape() | ||||
|         expected_shape = (4, 4) | ||||
|         self.assertEqual(expected_shape, actual_shape) | ||||
|  | ||||
|         expected = [[0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1], [0, 0, 0, 0]] | ||||
|         self.assertEqual(expected, actual) | ||||
|  | ||||
|     def test_should_raise_value_error_while_creating_tridiagonal_matrix(self): | ||||
|         self.assertRaises(ValueError, lambda: Matrix([-1, 1, -1, 0], structure="tridiagonal", n=1)) | ||||
|  | ||||
|     def test_should_create_tridiagonal_matrix_from_list_with_size_4(self): | ||||
|         data = [-1, 1, -1] | ||||
|         actual = Matrix(data, structure="tridiagonal", n=4) | ||||
|  | ||||
|         actual_shape = actual.shape() | ||||
|         expected_shape = (4, 4) | ||||
|         self.assertEqual(expected_shape, actual_shape) | ||||
|  | ||||
|         expected = [[1, -1, 0, 0], [-1, 1, -1, 0], [0, -1, 1, -1], [0, 0, -1, 1]] | ||||
|         self.assertEqual(expected, actual) | ||||
|  | ||||
|     def test_should_transpose_matrix(self): | ||||
|         data = [1, 2, 3, 4, 5, 6, 7, 8, 9] | ||||
|         actual = Matrix(data, (3, 3)) | ||||
|  | ||||
|         actual = actual.transpose() | ||||
|         expected = [[1, 4, 7], [2, 5, 8], [3, 6, 9]] | ||||
|         self.assertEqual(expected, actual) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user