Merge branch 'refs/heads/feature/mpi'
This commit is contained in:
commit
0fc5b61844
@ -85,11 +85,8 @@ class Matrix:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def flatten_internal(matrices):
|
def flatten_internal(matrices):
|
||||||
flattened_data = []
|
flattened_data = [element for matrix in matrices for row in matrix.get_data() for element in row]
|
||||||
rows = 0
|
rows = sum(matrix.__shape__[0] for matrix in matrices)
|
||||||
for matrix in matrices:
|
|
||||||
flattened_data.extend(matrix.get_data())
|
|
||||||
rows += matrix.__shape__[0]
|
|
||||||
cols = matrices[0].__shape__[1]
|
cols = matrices[0].__shape__[1]
|
||||||
return flattened_data, (rows, cols)
|
return flattened_data, (rows, cols)
|
||||||
|
|
||||||
@ -114,13 +111,8 @@ class Matrix:
|
|||||||
return self.__shape__
|
return self.__shape__
|
||||||
|
|
||||||
def __transpose_internal__(self):
|
def __transpose_internal__(self):
|
||||||
rows = self.__shape__[0]
|
rows, cols = self.__shape__
|
||||||
cols = self.__shape__[1]
|
return [[self.__data__[i][j] for i in range(rows)] for j in range(cols)], (cols, rows)
|
||||||
transposed_data = [([0] * rows) for _ in range(cols)]
|
|
||||||
for i in range(rows):
|
|
||||||
for j in range(cols):
|
|
||||||
transposed_data[j][i] = self.__data__[i][j]
|
|
||||||
return transposed_data, (cols, rows)
|
|
||||||
|
|
||||||
def transpose(self):
|
def transpose(self):
|
||||||
"""
|
"""
|
||||||
@ -144,6 +136,9 @@ class Matrix:
|
|||||||
:param other: The object to compare to; must be either a ``Matrix``, a ``list`` or a ``numpy.ndarray``
|
: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 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 not isinstance(other, (Matrix, list, numpy.ndarray)):
|
||||||
|
raise ValueError("Matrix type is not comparable to type of given ``other``")
|
||||||
|
data_to_compare = other
|
||||||
if isinstance(other, Matrix):
|
if isinstance(other, Matrix):
|
||||||
if self.__shape__ != other.__shape__:
|
if self.__shape__ != other.__shape__:
|
||||||
return False
|
return False
|
||||||
@ -154,45 +149,33 @@ class Matrix:
|
|||||||
return False
|
return False
|
||||||
elif isinstance(other, numpy.ndarray):
|
elif isinstance(other, numpy.ndarray):
|
||||||
data_to_compare = other.tolist()
|
data_to_compare = other.tolist()
|
||||||
else:
|
return all(value == other_value
|
||||||
raise ValueError("Matrix type is not comparable to type of given ``other``")
|
for row, other_row in zip(self.__data__, data_to_compare)
|
||||||
|
for value, other_value in zip(row, other_row))
|
||||||
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(numpy.array(self.__data__))
|
return str(numpy.array(self.__data__))
|
||||||
|
|
||||||
def __neg_internal__(self):
|
def __neg_internal__(self):
|
||||||
rows = range(self.__shape__[0])
|
return list(map(lambda row: [-value for value in row], self.__data__))
|
||||||
cols = range(self.__shape__[1])
|
|
||||||
return [[-(self.__data__[i][j]) for j in cols] for i in rows]
|
|
||||||
|
|
||||||
def __neg__(self):
|
def __neg__(self):
|
||||||
return Matrix(self.__neg_internal__(), self.__shape__)
|
return Matrix(self.__neg_internal__(), self.__shape__)
|
||||||
|
|
||||||
def __add_matrix_internal__(self, other):
|
def __add_matrix_internal__(self, other):
|
||||||
rows = self.__shape__[0]
|
return [list(map(sum, zip(*rows))) for rows in zip(self.__data__, other.__data__)]
|
||||||
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):
|
def __add_scalar_internal__(self, other):
|
||||||
rows = self.__shape__[0]
|
return [[value + other for value in row] for row in self.__data__]
|
||||||
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 not isinstance(other, (Matrix, int, float)):
|
||||||
|
raise ValueError("Only a number or another ``Matrix`` can be added to a ``Matrix``")
|
||||||
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.__add_matrix_internal__(other), self.__shape__)
|
return Matrix(self.__add_matrix_internal__(other), self.__shape__)
|
||||||
elif isinstance(other, int) or isinstance(other, float):
|
|
||||||
return Matrix(self.__add_scalar_internal__(other), self.__shape__)
|
return Matrix(self.__add_scalar_internal__(other), self.__shape__)
|
||||||
else:
|
|
||||||
raise ValueError("Only a number or another ``Matrix`` can be added to a ``Matrix``")
|
|
||||||
|
|
||||||
def __radd__(self, other):
|
def __radd__(self, other):
|
||||||
return self + other
|
return self + other
|
||||||
@ -204,28 +187,21 @@ class Matrix:
|
|||||||
return -self + other
|
return -self + other
|
||||||
|
|
||||||
def __truediv_scalar_internal__(self, other):
|
def __truediv_scalar_internal__(self, other):
|
||||||
rows = self.__shape__[0]
|
return [list(map(lambda value: value / other, row)) for row in self.__data__]
|
||||||
cols = self.__shape__[1]
|
|
||||||
return [[(self.__data__[i][j] / other) for j in range(cols)] for i in range(rows)]
|
|
||||||
|
|
||||||
def __truediv__(self, other):
|
def __truediv__(self, other):
|
||||||
if isinstance(other, int) or isinstance(other, float):
|
if not isinstance(other, (int, float)):
|
||||||
return Matrix(self.__truediv_scalar_internal__(other), self.__shape__)
|
|
||||||
else:
|
|
||||||
raise ValueError("A ``Matrix`` can only be divided ba a number")
|
raise ValueError("A ``Matrix`` can only be divided ba a number")
|
||||||
|
return Matrix(self.__truediv_scalar_internal__(other), self.__shape__)
|
||||||
|
|
||||||
def __mul_rowmatrix_matrix__internal__(self, other):
|
def __mul_rowmatrix_matrix__internal__(self, other):
|
||||||
cols = other.__shape__[1]
|
rows, cols = self.__shape__[1], other.__shape__[1]
|
||||||
new_data = [0] * cols
|
return [sum(self.__data__[0][j] * other.__data__[j][i] for j in range(rows)) for i in range(cols)]
|
||||||
for i in range(cols):
|
|
||||||
new_data[i] = sum([self.__data__[0][j] * other.__data__[j][i] for j in range(self.__shape__[1])])
|
|
||||||
return new_data
|
|
||||||
|
|
||||||
def __mul_matrix_internal__(self, other):
|
def __mul_matrix_internal__(self, other):
|
||||||
if self.__shape__[0] == 1:
|
if self.__shape__[0] == 1:
|
||||||
return self.__mul_rowmatrix_matrix__internal__(other)
|
return self.__mul_rowmatrix_matrix__internal__(other)
|
||||||
rows = self.__shape__[0]
|
rows, cols = self.__shape__[0], other.__shape__[1]
|
||||||
cols = other.__shape__[1]
|
|
||||||
new_data = [([0] * cols) for _ in range(rows)]
|
new_data = [([0] * cols) for _ in range(rows)]
|
||||||
for i in range(rows):
|
for i in range(rows):
|
||||||
for k in range(cols):
|
for k in range(cols):
|
||||||
@ -233,9 +209,7 @@ class Matrix:
|
|||||||
return new_data
|
return new_data
|
||||||
|
|
||||||
def __mul_scalar_internal__(self, other):
|
def __mul_scalar_internal__(self, other):
|
||||||
rows = range(self.__shape__[0])
|
return [list(map(lambda value: value * other, row)) for row in self.__data__]
|
||||||
cols = range(self.__shape__[1])
|
|
||||||
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):
|
||||||
@ -255,31 +229,13 @@ class Matrix:
|
|||||||
return self.__abs_sum_of_squares__()
|
return self.__abs_sum_of_squares__()
|
||||||
|
|
||||||
def __abs_sum_of_squares__(self):
|
def __abs_sum_of_squares__(self):
|
||||||
rows = self.__shape__[0]
|
return sum(abs(element) ** 2 for row in self.__data__ for element in row)
|
||||||
cols = self.__shape__[1]
|
|
||||||
abs_sum = 0
|
|
||||||
for i in range(rows):
|
|
||||||
for j in range(cols):
|
|
||||||
abs_sum += abs(self.__data__[i][j]) ** 2
|
|
||||||
return abs_sum
|
|
||||||
|
|
||||||
def __col_sums__(self):
|
def __col_sums__(self):
|
||||||
rows = self.__shape__[0]
|
return [sum(abs(row[j]) for row in self.__data__) for j in range(self.__shape__[1])]
|
||||||
cols = self.__shape__[1]
|
|
||||||
col_sums = [0] * cols
|
|
||||||
for j in range(cols):
|
|
||||||
for i in range(rows):
|
|
||||||
col_sums[j] += abs(self.__data__[i][j])
|
|
||||||
return col_sums
|
|
||||||
|
|
||||||
def __row_sums__(self):
|
def __row_sums__(self):
|
||||||
rows = self.__shape__[0]
|
return [sum(abs(value) for value in row) for row in self.__data__]
|
||||||
cols = self.__shape__[1]
|
|
||||||
row_sums = [0] * rows
|
|
||||||
for i in range(rows):
|
|
||||||
for j in range(cols):
|
|
||||||
row_sums[i] += abs(self.__data__[i][j])
|
|
||||||
return row_sums
|
|
||||||
|
|
||||||
def norm(self, f: str = "frobenius"):
|
def norm(self, f: str = "frobenius"):
|
||||||
"""
|
"""
|
||||||
|
@ -111,7 +111,7 @@ class MatrixMPI:
|
|||||||
: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, MatrixMPI):
|
if isinstance(other, MatrixMPI):
|
||||||
return self.__data__ == other.__data__
|
return all(self.__mpi_comm__.allgather(self.__rank_subdata__ == other.__rank_subdata__))
|
||||||
else:
|
else:
|
||||||
return self.__data__ == other
|
return self.__data__ == other
|
||||||
|
|
||||||
|
@ -80,8 +80,7 @@ class Vector(Matrix):
|
|||||||
raise ValueError("Only a number or another ``Vector`` can be added to a ``Vector``")
|
raise ValueError("Only a number or another ``Vector`` can be added to a ``Vector``")
|
||||||
|
|
||||||
def __mul_vector_same_shape_internal__(self, other):
|
def __mul_vector_same_shape_internal__(self, other):
|
||||||
rows = self.__shape__[0]
|
rows, cols = self.__shape__
|
||||||
cols = self.__shape__[1]
|
|
||||||
if rows >= cols:
|
if rows >= cols:
|
||||||
new_data = [(self.__data__[i][0] * other.__data__[i][0]) for i in range(rows)]
|
new_data = [(self.__data__[i][0] * other.__data__[i][0]) for i in range(rows)]
|
||||||
else:
|
else:
|
||||||
@ -89,8 +88,7 @@ class Vector(Matrix):
|
|||||||
return new_data
|
return new_data
|
||||||
|
|
||||||
def __mul_tensor_internal__(self, other):
|
def __mul_tensor_internal__(self, other):
|
||||||
rows = self.__shape__[0]
|
rows, cols = self.__shape__[0], other.__shape__[1]
|
||||||
cols = other.__shape__[1]
|
|
||||||
return [[self.__data__[i][0] * other.__data__[0][j] for j in range(cols)] for i in range(rows)], (rows, cols)
|
return [[self.__data__[i][0] * other.__data__[0][j] for j in range(cols)] for i in range(rows)], (rows, cols)
|
||||||
|
|
||||||
def __mul__(self, other):
|
def __mul__(self, other):
|
||||||
@ -112,31 +110,24 @@ class Vector(Matrix):
|
|||||||
"a compatible ``Matrix`` or a scalar")
|
"a compatible ``Matrix`` or a scalar")
|
||||||
|
|
||||||
def __mul_matrix_vector_internal__(self, other):
|
def __mul_matrix_vector_internal__(self, other):
|
||||||
rows = other.__shape__[0]
|
rows, vector_rows = other.__shape__[0], self.__shape__[0]
|
||||||
new_data = [0] * rows
|
return [sum([other.__data__[i][j] * self.__data__[j][0] for j in range(vector_rows)]) for i in range(rows)]
|
||||||
for i in range(rows):
|
|
||||||
new_data[i] = sum([other.__data__[i][j] * self.__data__[j][0] for j in range(self.__shape__[0])])
|
|
||||||
return new_data
|
|
||||||
|
|
||||||
def __rmul__(self, other):
|
def __rmul__(self, other):
|
||||||
if isinstance(other, Matrix):
|
return Vector(self.__mul_matrix_vector_internal__(other)) if isinstance(other, Matrix) else self * other
|
||||||
return Vector(self.__mul_matrix_vector_internal__(other))
|
|
||||||
return self * other
|
|
||||||
|
|
||||||
def __truediv_vector_internal__(self, other):
|
def __truediv_vector_internal__(self, other):
|
||||||
rows = self.__shape__[0]
|
rows, cols = self.__shape__
|
||||||
cols = self.__shape__[1]
|
|
||||||
return [[(self.__data__[i][j] / other.__data__[i][j]) for j in range(cols)] for i in range(rows)]
|
return [[(self.__data__[i][j] / other.__data__[i][j]) for j in range(cols)] for i in range(rows)]
|
||||||
|
|
||||||
def __truediv__(self, other):
|
def __truediv__(self, other):
|
||||||
|
if not isinstance(other, (Vector, int, float)):
|
||||||
|
raise ValueError("A ``Vector`` can only be divided ba a number or another same-shaped ``Vector``")
|
||||||
if isinstance(other, Vector):
|
if isinstance(other, Vector):
|
||||||
if self.__shape__ != other.__shape__:
|
if self.__shape__ != other.__shape__:
|
||||||
raise ValueError("The ``Vector``s to be divided must have the same shape")
|
raise ValueError("The ``Vector``s to be divided must have the same shape")
|
||||||
return Vector(self.__truediv_vector_internal__(other))
|
return Vector(self.__truediv_vector_internal__(other))
|
||||||
elif isinstance(other, int) or isinstance(other, float):
|
|
||||||
return Vector(super().__truediv_scalar_internal__(other))
|
return Vector(super().__truediv_scalar_internal__(other))
|
||||||
else:
|
|
||||||
raise ValueError("A ``Vector`` can only be divided ba a number or another same-shaped ``Vector``")
|
|
||||||
|
|
||||||
def norm(self, **kwargs):
|
def norm(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
Loading…
Reference in New Issue
Block a user