1
0

Finalize matrix_mpi.py; Add more vector_mpi.py

This commit is contained in:
Niklas Birk 2024-04-16 23:21:56 +02:00
parent 987de6acf7
commit 6848bc7b26
8 changed files with 291 additions and 502 deletions

View File

@ -1,6 +1,26 @@
# m1 = MatrixMPI(numpy.random.uniform(0, 1, 1_000_000), (1000, 1000)) # m1 = MatrixMPI(numpy.random.uniform(0, 1, 1_000_000), (1000, 1000))
from mpi4py import MPI
from matrix_mpi import MatrixMPI from matrix_mpi import MatrixMPI
from vector_mpi import VectorMPI
m1 = MatrixMPI([1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6], (5, 3)) comm = MPI.COMM_WORLD
rank = comm.Get_rank()
size = comm.Get_size()
print(m1 + m1) m1 = MatrixMPI(list(range(1, 21)), (4, 5))
m2 = MatrixMPI(list(range(1, 16)), (5, 3))
m_mul = m1 * m2
v1 = VectorMPI(list(range(1, 21)))
v2 = VectorMPI(list(reversed(list(range(1, 21)))))
v_add = v1 + v2
v_mul = v1.T() * v2
if rank == 0:
print(m_mul)
print("---")
print(v_add)
print(v_mul)

View File

@ -210,10 +210,19 @@ class Matrix:
else: else:
raise ValueError("A ``Matrix`` can only be divided ba a number") raise ValueError("A ``Matrix`` can only be divided ba a number")
def __mul_rowmatrix_matrix__internal__(self, other):
cols = other.__shape__[1]
new_data = [0] * 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:
return self.__mul_rowmatrix_matrix__internal__(other)
rows = self.__shape__[0] rows = self.__shape__[0]
cols = other.__shape__[1] cols = other.__shape__[1]
new_data = [([0] * rows) for _ in range(cols)] 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):
new_data[i][k] = sum([self.__data__[i][j] * other.__data__[j][k] for j in range(self.__shape__[1])]) new_data[i][k] = sum([self.__data__[i][j] * other.__data__[j][k] for j in range(self.__shape__[1])])

View File

@ -5,21 +5,17 @@ from matrix import Matrix
class MatrixMPI: class MatrixMPI:
__mpi_comm__ = None __mpi_comm__ = MPI.COMM_WORLD
__mpi_size__ = None __mpi_size__ = __mpi_comm__.Get_size()
__mpi_rank__ = None __mpi_rank__ = __mpi_comm__.Get_rank()
__matrix__: Matrix = None __data__: Matrix = None
__chunk__: list = None __chunk__: list = None
def __init__(self, mpi_comm, data=None, shape=None, structure=None, model=None, offset=None, n=None): def __init__(self, data=None, shape=None, structure=None, model=None, offset=None, n=None):
self.__mpi_comm__ = mpi_comm self.__data__ = Matrix(data=data, shape=shape, structure=structure, model=model, offset=offset, n=n)
self.__mpi_size__ = self.__mpi_comm__.Get_size()
self.__mpi_rank__ = self.__mpi_comm__.Get_rank()
self.__matrix__ = Matrix(data=data, shape=shape, structure=structure, model=model, offset=offset, n=n) total_amount_of_rows = self.__data__.shape()[0]
total_amount_of_rows = self.__matrix__.shape()[0]
chunks = numpy.array_split(list(range(total_amount_of_rows)), self.__mpi_size__) chunks = numpy.array_split(list(range(total_amount_of_rows)), self.__mpi_size__)
self.__chunk__ = chunks[self.__mpi_rank__].tolist() self.__chunk__ = chunks[self.__mpi_rank__].tolist()
@ -28,18 +24,24 @@ class MatrixMPI:
return MatrixMPI(matrix.get_data(), matrix.shape()) return MatrixMPI(matrix.get_data(), matrix.shape())
def __str__(self): def __str__(self):
return str(self.__matrix__) return str(self.__data__)
def shape(self):
return self.__data__.shape()
def get_rank_submatrix(self): def get_rank_submatrix(self):
rows = len(self.__chunk__) rows = len(self.__chunk__)
cols = self.__matrix__.shape()[1] cols = self.__data__.shape()[1]
return Matrix(self.__matrix__[self.__chunk__], (rows, cols)) return Matrix(self.__data__[self.__chunk__], (rows, cols))
def get_data(self):
return self.__data__
def transpose(self): def transpose(self):
""" """
:return: the transpose of the matrix :return: the transpose of the matrix
""" """
return MatrixMPI.of(self.__matrix__.transpose()) return MatrixMPI.of(self.__data__.transpose())
def T(self): def T(self):
""" """
@ -57,9 +59,9 @@ 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.__matrix__ == other.__matrix__ return self.__data__ == other.__data__
else: else:
return self.__matrix__ == other return self.__data__ == other
def __neg__(self): def __neg__(self):
gathered_data = self.__mpi_comm__.gather(-self.get_rank_submatrix()) gathered_data = self.__mpi_comm__.gather(-self.get_rank_submatrix())
@ -89,9 +91,10 @@ class MatrixMPI:
def __mul__(self, other): def __mul__(self, other):
if isinstance(other, MatrixMPI): if isinstance(other, MatrixMPI):
return self.__matrix__ * other.__matrix__ other = other.get_data()
else: gathered_data = self.__mpi_comm__.gather(self.get_rank_submatrix() * other)
return self.__matrix__ * other data = self.__mpi_comm__.bcast(gathered_data)
return MatrixMPI.of(Matrix.flatten(data))
def __rmul__(self, other): def __rmul__(self, other):
return self * other return self * other
@ -107,11 +110,10 @@ class MatrixMPI:
:return: the norm as a number :return: the norm as a number
""" """
return self.__matrix__.norm(f) return self.__data__.norm(f)
def __getitem__(self, key): def __getitem__(self, key):
return self.__matrix__[key] return self.__data__[key]
def __setitem__(self, key, value): def __setitem__(self, key, value):
self.__matrix__[key] = value self.__data__[key] = value

View File

@ -86,7 +86,7 @@ class Vector(Matrix):
return Vector(self.__mul_vector_same_shape_internal__(other)) return Vector(self.__mul_vector_same_shape_internal__(other))
elif self.__shape__ == tuple(reversed(other.__shape__)): elif self.__shape__ == tuple(reversed(other.__shape__)):
if self.__shape__[0] == 1: # Case (_ ... _) * (_\n...\n_) = scalar if self.__shape__[0] == 1: # Case (_ ... _) * (_\n...\n_) = scalar
return super().__mul_matrix_internal__(other)[0][0] return super().__mul_matrix_internal__(other)[0]
else: # Case (_\n...\n_) * (_ ... _) = Matrix else: # Case (_\n...\n_) * (_ ... _) = Matrix
new_data, shape = self.__mul_tensor_internal__(other) new_data, shape = self.__mul_tensor_internal__(other)
return Matrix(new_data, shape) return Matrix(new_data, shape)
@ -95,10 +95,19 @@ class Vector(Matrix):
elif isinstance(other, int) or isinstance(other, float): elif isinstance(other, int) or isinstance(other, float):
return Vector(super().__mul_scalar_internal__(other)) return Vector(super().__mul_scalar_internal__(other))
else: else:
raise ValueError("A ``Vector`` can only be multiplied with an ``Vector`` (dot product or tensor)," raise ValueError("A ``Vector`` can only be multiplied with an ``Vector`` (dot product or tensor), "
"a compatible ``Matrix`` or a scalar") "a compatible ``Matrix`` or a scalar")
def __mul_matrix_vector_internal__(self, other):
rows = other.__shape__[0]
new_data = [0] * 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))
return self * other return self * other
def __truediv_vector_internal__(self, other): def __truediv_vector_internal__(self, other):

View File

@ -1,378 +1,88 @@
import numpy from matrix_mpi import MatrixMPI
from mpi4py import MPI
from vector import Vector from vector import Vector
class VectorMPI: class VectorMPI(MatrixMPI):
__mpi_comm__ = None __data__: Vector = None
__mpi_size__ = None
__mpi_rank__ = None
__vector__: Vector = None def __init__(self, data=None, shape=None):
self.__data__ = Vector(data=data, shape=shape)
def __init__(self, mpi_comm, data=None, shape=None): @staticmethod
self.__mpi_comm__ = mpi_comm def of(vector: Vector):
self.__mpi_size__ = self.__mpi_comm__.Get_size() return VectorMPI(vector.get_data(), vector.shape())
self.__mpi_rank__ = self.__mpi_comm__.Get_rank()
self.__vector__ = Vector(data=data, shape=shape) def get_vector(self):
return self.__data__
# class Vector: def shape(self):
# start_idx = 0 # Nullter Eintrag des Vektors auf dem aktuellen Rang return self.__data__.shape()
# end_idx = 0 # Letzer Eintrag des Vektors auf dem aktuellen Rang
# rank_size = 0 # Dimension des Vektors der auf dem aktuellen Rang gespeichert wird def __eq__(self, other):
# kind = '' # Art des Vektors, Zeilen oder Spaltenvektor """
# vec = np.arange(rank_size) Return ``self==value``
# vshape = np.arange(2) # Array mit Länge 2, um die Shape des Vektors zu speichern
# dim = 0 # Gesamtdimension des Vektors, Länge des Vektors :param other: The object to compare to; must be either a ``Vector``, a ``list`` or a ``numpy.ndarray``
# :return: True if data in the same-shaped vectors are equal to the given data in other for each component otherwise False
# comm = MPI.COMM_WORLD """
# size = comm.Get_size() if isinstance(other, VectorMPI):
# rank = comm.Get_rank() return self.__data__ == other.__data__
# else:
# # Konstruktor return self.__data__ == other
# def __init__(self, array):
# def transpose(self):
# if isinstance(array, np.ndarray): """
# form = array.shape :return: the transpose of the vector
# if len(array) < self.size: """
# raise ValueError("ERROR_3: Die Dimension des Vektors ist kleiner als die Anzahl der benutzten Ränge.") return VectorMPI.of(self.__data__.transpose())
#
# if len(form) > 2: def T(self):
# raise ValueError("ERROR_2: Falsche Dimension, kann kein 1 x n oder n x 1 Vektor sein.") return self.transpose()
# # Array ist Zeilenvektor:
# if len(form) == 1 or (len(form) == 2 and form[0] == 1): def __neg__(self):
# self.vshape[0] = 1 return VectorMPI.of(-self.__data__)
# self.vshape[1] = len(array) # Shape des Vectors
# self.start_idx = int(self.rank * len(array) / self.size) def __add__(self, other):
# self.end_idx = int(len(array) / self.size + self.rank * len(array) / self.size) - 1 if isinstance(other, VectorMPI):
# self.rank_size = ( other = other.__data__
# self.end_idx - self.start_idx) + 1 # Größe des Teilvektors auf dem akt. Rang: Differenz zw. Start- und Endindex + 1 return VectorMPI.of(self.__data__ + other)
# self.vec = array[
# self.start_idx: self.end_idx + 1] # Auf jedem Rang werden die Einträge vom Start bis zum Endindex gespeichert def __mul__(self, other):
# self.kind = 'row' if isinstance(other, VectorMPI):
# self.dim = len(array) other = other.__data__
# result = self.__data__ * other
# # Array ist Spaltenvektor return VectorMPI.of(result) if isinstance(result, Vector) else result
# if len(form) == 2 and form[1] == 1:
# self.vshape[0] = len(array) def __rmul__(self, other):
# self.vshape[1] = 1 if isinstance(other, MatrixMPI):
# self.start_idx = int(self.rank * len(array) / self.size) return VectorMPI.of(other.get_data() * self.get_vector())
# self.end_idx = int(len(array) / self.size + self.rank * len(array) / self.size) - 1 return self * other
# self.rank_size = (
# self.end_idx - self.start_idx) + 1 # Größe des Teilvektors auf dem akt. Rang: Differenz zw. Start- und Endindex + 1 def __truediv__(self, other):
# self.vec = array[ if isinstance(other, VectorMPI):
# self.start_idx: self.end_idx + 1] # Auf jedem Rang werden die Einträge vom Start bis zum Endindex gespeichert other = other.__data__
# self.kind = 'column' return VectorMPI.of(self.__data__ / other)
# self.dim = len(array)
# def norm(self, **kwargs):
# elif isinstance(array, list): """
# self.vshape[0] = 1 Computes the 2-norm of the vector which is the Frobenius-Norm of a nx1 matrix.
# self.vshape[1] = len(array)
# self.start_idx = int(self.rank * len(array) / self.size) :param kwargs: ignored
# self.end_idx = int(len(array) / self.size + self.rank * len(array) / self.size) - 1 :return: the 2-norm of the vector
# self.rank_size = (self.end_idx - self.start_idx) + 1 """
# self.vec = np.array(array[self.start_idx:self.end_idx + 1]) return self.__data__.norm()
# self.kind = 'row'
# self.dim = len(array) def normalize(self):
# else: """
# raise ValueError( A normalized vector has the length (norm) 1.
# "ERROR_1: Die übergebene Variable ist kein Numpy-Array, Keine Initialisierung der Vector-Klasse möglich.") To achieve that the vector is divided by the norm of itself.
#
# def __add__(self, other): # Überschreibung der Addition :return: the normalized vector
# if isinstance(self, Vector) and isinstance(other, Vector): """
# Add_Vec = Vector(np.arange(self.dim)) return VectorMPI.of(self.__data__ / self.norm())
# if self.vshape[0] == other.vshape[0] and self.vshape[1] == other.vshape[1]:
# for i in range(0, self.rank_size): def __getitem__(self, key):
# Add_Vec.vec[i] = self.vec[i] + other.vec[i] return self.__data__[key]
# else:
# raise ValueError("Die Dimensionen der Vektoren stimmen nicht überein, Addition nicht möglich.") def __setitem__(self, key, value):
# elif isinstance(self, Vector) and isinstance(other, (int, float, complex)): self.__data__[key] = value
# Add_Vec = Vector(np.arange(self.dim))
# for i in range(0, self.rank_size):
# Add_Vec.vec[i] = self.vec[i] + other
# elif isinstance(self, (int, float, complex)) and isinstance(other, Vector):
# Add_Vec = Vector(np.arange(other.dim))
# for i in range(0, other.rank_size):
# Add_Vec.vec[i] = other.vec[i] + self
# else:
# raise ValueError("Ungeeigneter Datentyp für die Addition mit einem Vektor.")
# return Add_Vec
#
# def __radd__(self, other): # Überschreibung der Addition eines Vektors von rechts
# Vector(np.arange(self.dim))
# if isinstance(self, Vector) and isinstance(other, (int, float, complex)):
# Add_Vec = Vector(np.arange(self.dim))
# for i in range(0, self.rank_size):
# Add_Vec.vec[i] = self.vec[i] + other
# else:
# raise ValueError("Ungeeigneter Datentyp für die Addition mit einem Vektor.")
# return Add_Vec
#
# def __sub__(self, other): # Überschreibung der Subtraktion
# if isinstance(self, Vector) and isinstance(other, Vector):
# Sub_Vec = Vector(np.arange(self.dim))
# if self.vshape[0] == other.vshape[0] and self.vshape[1] == other.vshape[1]:
# for i in range(0, self.rank_size):
# Sub_Vec.vec[i] = self.vec[i] - other.vec[i]
# else:
# raise ValueError("Die Dimension der Vektoren stimmen nicht überein, Subtraktion nicht möglich.")
# elif isinstance(self, Vector) and isinstance(other, (int, float, complex)):
# Sub_Vec = Vector(np.arange(self.dim))
# for i in range(0, self.rank_size):
# Sub_Vec.vec[i] = self.vec[i] - other
# elif isinstance(self, (int, float, complex)) and isinstance(other, Vector):
# Sub_Vec = Vector(np.arange(self.dim))
# for i in range(0, other.rank_size):
# Sub_Vec.vec[i] = other.vec[i] - self
# else:
# raise ValueError("Ungeeigneter Datentyp für die Subtraktion mit einem Vektor.")
# return Sub_Vec
#
# def __rsub__(self, other): # Subtraktion einer Zahl von einem Vektor
# Sub_Vec = Vector(np.arange(self.dim))
# if isinstance(self, Vector) and isinstance(other, (float, int, complex)):
# for i in range(0, self.rank_size):
# Sub_Vec.vec[i] = self.vec[i] - other
# else:
# raise ValueError("Ungeeigneter Datentyp für die Subtraktion von einem Vektor.")
# return Sub_Vec
#
# def __mul__(self, other): # Überschreibung der Multiplikation
# if isinstance(self, Vector) and isinstance(other, Vector):
# Mult_Vec = Vector(np.arange(self.dim))
# if (self.vshape[0] == other.vshape[0] and self.vshape[1] == other.vshape[
# 1]): # Elementweise Multiplikation
# for i in range(0, self.rank_size):
# Mult_Vec.vec[i] = self.vec[i] * other.vec[i]
# elif self.vshape[1] == other.vshape[0] and self.vshape[0] == 1: # Inneres Produkt (Skalarprodukt)
# skal_prod = 0
# for i in range(0, self.rank_size):
# skal_prod = skal_prod + self.vec[i] * other.vec[i]
# return skal_prod
# elif self.vshape[0] == other.vshape[1] and self.vshape[1] == 1:
# raise ValueError("Kann erst implementiert werden, wenn Matrix-Klasse existiert.")
# else:
# raise ValueError("Die Dimensionen der Vektoren stimmen nicht überein, Multiplikation nicht möglich.")
# elif isinstance(self, Vector) and isinstance(other, (int, float, complex)):
# Mult_Vec = Vector(np.arange(self.dim))
# for i in range(0, self.rank_size):
# Mult_Vec.vec[i] = self.vec[i] * other
# elif isinstance(self, (int, float, complex)) and isinstance(other, Vector):
# Mult_Vec = Vector(np.arange(self.dim))
# for i in range(0, other.rank_size):
# Mult_Vec.vec[i] = other.vec[i] * self
# else:
# raise ValueError("Ungeeigneter Datentyp für die Multiplikation mit einem Vektor.")
# return Mult_Vec
#
# def __rmul__(self, other): # Rechtsseitige Multiplikation von einer Zahl an einen Vektor
# Mult_Vec = Vector(np.arange(self.dim))
# if isinstance(self, Vector) and isinstance(other, (int, float, complex)):
# for i in range(0, self.rank_size):
# Mult_Vec.vec[i] = self.vec[i] * other
# else:
# raise ValueError("Ungeeigneter Datentyp für die Multiplikation mit einem Vektor.")
# return Mult_Vec
#
# def __truediv__(self, other):
# Div_Vec = Vector(np.arange(self.dim, dtype=np.double))
# if isinstance(self, Vector) and isinstance(other, Vector):
# if self.vshape[0] == other.vshape[0] and self.vshape[1] == other.vshape[1]:
# for i in range(0, self.rank_size):
# if other.vec[i] == 0:
# raise ValueError("Ein Eintrag des Divisor-Vektors ist 0, Divion nicht möglich.")
# Div_Vec.vec[i] = self.vec[i] / other.vec[i]
# else:
# raise ValueError("Die Dimensionen der Vektoren stimmen nicht überein, Division nicht möglich.")
# elif isinstance(self, (int, float, complex)) and isinstance(other, Vector):
# for i in range(0, other.rank_size):
# if other.vec[i] == 0:
# raise ValueError("Ein Eintrag des Divisor-Vektors ist 0, Divion nicht möglich.")
# Div_Vec.vec[i] = self / other.vec[i]
# elif isinstance(self, Vector) and isinstance(other, (float, int, complex)):
# if other == 0:
# raise ValueError("Division durch Null ist nicht möglich.")
# else:
# for i in range(0, self.rank_size):
# Div_Vec.vec[i] = self.vec[i] / other
# else:
# raise ValueError("ERROR 11: Ungeeigneter Datentyp für die Division mit einem Vektor.")
# return Div_Vec
#
# def __rtruediv__(self, other):
# Div_Vec = Vector(np.arange(self.dim, dtype=np.double))
# if isinstance(self, Vector) and isinstance(other, (float, int, complex)):
# if other == 0:
# raise ValueError("Division durch Null ist nicht möglich.")
# else:
# for i in range(0, self.rank_size):
# Div_Vec.vec[i] = self.vec[i] / other
# else:
# raise ValueError("ERROR 10: Uneignete Datentyp, um einen Vektor durch diesen zu dividieren")
# return Div_Vec
#
# def __neg__(self):
# Neg_Vec = -1 * self
# return Neg_Vec
#
# def shape(self):
# if self.rank == 0:
# return self.vshape
#
# def T(self):
# Transpose = self
# if self.kind == 'row':
# Transpose.kind = 'column'
# else:
# Transpose.kind = 'row'
#
# # Tauschen der Dimensionen
# var_shift = self.vshape[0]
# Transpose.vshape[0] = self.vshape[1]
# Transpose.vshape[1] = var_shift
# return Transpose
#
# def str(self): # Rückgabe des gesamten Vektors als string
# str_rep = ''
#
# if self.rank == 0:
# if self.kind == 'row':
# str_rep = '[' + ','.join(map(str, self.vec))
# if self.kind == 'column':
# str_rep = '[' + '\n'.join(map(str, self.vec))
# if self.size > 1:
# self.comm.send(str_rep, dest=self.rank + 1)
#
# elif self.rank == self.size - 1:
# if self.kind == 'row':
# str_rep = self.comm.recv(source=self.rank - 1) + ',' + ','.join(map(str, self.vec))
# if self.kind == 'column':
# str_rep = self.comm.recv(source=self.rank - 1) + '\n' + '\n'.join(map(str, self.vec))
#
# else:
# if self.kind == 'row':
# str_rep = self.comm.recv(source=self.rank - 1) + ',' + ','.join(map(str, self.vec))
# if self.kind == 'column':
# str_rep = self.comm.recv(source=self.rank - 1) + '\n' + '\n'.join(map(str, self.vec))
# self.comm.send(str_rep, dest=self.rank + 1)
#
# str_rep = self.comm.bcast(str_rep, root=self.size - 1)
# if self.rank == 0:
# return str_rep + ']'
#
# def string(self, limit_entry): # Gibt den Vektor als String zurück bis zum Eintrag limit_entry
# str_rep = ''
#
# if limit_entry > self.vec_size:
# raise ValueError("ERROR_4: Die eingegebene Zahl ist größer, als der größte Index des Vectors.")
#
# # Rank 0
# if self.rank == 0 and limit_entry <= self.end_idx: # Limit_entry befindet sich im Rang 0
# if self.kind == 'row':
# str_rep = '[' + ','.join(map(str, self.vec[:limit_entry]))
# if self.kind == 'column':
# str_rep = '[' + '\n'.join(map(str, self.vec[:limit_entry]))
# if self.size > 1:
# self.comm.send(str_rep, dest=self.rank + 1)
# if self.rank == 0 and limit_entry > self.end_idx: # Limit_entry befindet sich nicht im Rang 0
# if self.kind == 'row':
# str_rep = '[' + ','.join(map(str, self.vec))
# if self.kind == 'column':
# str_rep = '[' + '\n'.join(map(str, self.vec))
# if self.size > 1:
# self.comm.send(str_rep, dest=self.rank + 1)
#
# # Rank im Intervall [1,size-1]
# if (
# 0 < self.rank < self.size - 1 and limit_entry <= self.start_idx): # wenn lim_ent == start_idx, dann wurden bereits alle relevanten Indizes im String gespeichert, da Vector nullinitialisiert ist
# str_rep = self.comm.recv(source=self.rank - 1)
# self.comm.send(str_rep, dest=self.rank + 1)
# if (
# 0 < self.rank < self.size - 1 and self.start_idx < limit_entry <= self.end_idx):
# if self.kind == 'row':
# str_rep = self.comm.recv(source=self.rank - 1) + ',' + ','.join(
# map(str, self.vec[:(limit_entry - self.start_idx)]))
# if self.kind == 'column':
# str_rep = self.comm.recv(source=self.rank - 1) + '\n' + '\n'.join(
# map(str, self.vec[:(limit_entry - self.start_idx)])) + ']'
# self.comm.send(str_rep, dest=self.rank + 1)
# if 0 < self.rank < self.size - 1 and limit_entry > self.end_idx:
# if self.kind == 'row':
# str_rep = self.comm.recv(source=self.rank - 1) + ',' + ','.join(map(str, self.vec))
# if self.kind == 'column':
# str_rep = self.comm.recv(source=self.rank - 1) + '\n' + '\n'.join(map(str, self.vec))
# self.comm.send(str_rep, dest=self.rank + 1)
#
# # Rank size-1
# if self.rank == self.size - 1 and limit_entry <= self.start_idx and self.rank > 1:
# str_rep = self.comm.recv(source=self.rank - 1)
#
# if self.rank == self.size - 1 and limit_entry >= self.start_idx and self.rank > 1:
# if self.kind == 'row':
# str_rep = self.comm.recv(source=self.rank - 1) + ',' + ','.join(
# map(str, self.vec[:(limit_entry - self.start_idx)]))
# if self.kind == 'column':
# str_rep = self.comm.recv(source=self.rank - 1) + '\n' + '\n'.join(
# map(str, self.vec[:(limit_entry - self.start_idx)]))
#
# str_rep = self.comm.bcast(str_rep, root=self.size - 1)
# if self.rank == 0:
# return str_rep + ']'
#
# def norm(self): # Berechnung der 2-Norm / euklidischen Norm
# 0
# sum_of_squares = 0
# if self.rank == 0:
# for i in range(0, self.rank_size):
# sum_of_squares = sum_of_squares + self.vec[i] ** 2
#
# if self.size > 1:
# self.comm.send(sum_of_squares, dest=self.rank + 1)
#
# elif self.rank == self.size - 1:
# sum_of_squares = self.comm.recv(source=self.rank - 1)
# for i in range(0, self.rank_size):
# sum_of_squares = sum_of_squares + self.vec[i] ** 2
#
# else:
# sum_of_squares = self.comm.recv(source=self.rank - 1)
# for i in range(0, self.rank_size):
# sum_of_squares = sum_of_squares + self.vec[i] ** 2
# self.comm.send(sum_of_squares, dest=self.rank + 1)
#
# sum_of_squares = self.comm.bcast(sum_of_squares, root=self.size - 1)
# norm = np.sqrt(sum_of_squares)
#
# return norm
#
# def normalize(self): # Normalisierung eines Vectors
# norm = self.norm()
# if norm == 0:
# return self
# normalized_vec = self / norm
# return normalized_vec
#
#
# # Main-Funktion
# x = Vector(np.arange(10))
# print(x.str(), x.shape())
# print(x.vshape[0], x.vshape[1])
# minus = -1 * x
# _x = -x
# print(_x.str())
# print(minus.str())
# y = Vector(2 * np.arange(10))
# print(y.str())
# z = x - y
# print(z.str())
# ae = x + 5
# print(ae.str())
# o = x * y
# print(o.str())
#
# a = Vector(np.array([[1], [2]]))
# b = Vector(np.array([1, 2]))
# print(a.shape())
# # c = a * b
# # print(c.vec)

View File

@ -230,6 +230,51 @@ class TestMatrix(TestCase):
self.assertEqual(expected, actual) self.assertEqual(expected, actual)
def test_should_mul_matrices_4(self):
m1 = Matrix([1] * 6, (2, 3))
m2 = Matrix([1] * 15, (3, 5))
actual = m1 * m2
expected = Matrix([3] * 10, (2, 5))
self.assertEqual(expected, actual)
def test_should_mul_matrices_5(self):
m1 = Matrix([1] * 15, (3, 5))
m2 = Matrix([1] * 20, (5, 4))
actual = m1 * m2
expected = Matrix([5] * 12, (3, 4))
self.assertEqual(expected, actual)
def test_should_mul_matrices_6(self):
m1 = Matrix([1] * 15, (5, 3))
m2 = Matrix([1] * 12, (3, 4))
actual = m1 * m2
expected = Matrix([3] * 20, (5, 4))
self.assertEqual(expected, actual)
def test_should_mul_matrices_7(self):
m1 = Matrix(list(range(1, 21)), (4, 5))
m2 = Matrix(list(range(1, 16)), (5, 3))
actual = m1 * m2
expected = Matrix([135, 150, 165, 310, 350, 390, 485, 550, 615, 660, 750, 840], (4, 3))
self.assertEqual(expected, actual)
def test_should_mul_vector_matrix(self):
m1 = Matrix([1, 2, 3], (1, 3))
m2 = Matrix([6, 5, 4, 3, 2, 1], (3, 2))
actual = m1 * m2
expected = Matrix([20, 14], (1, 2))
self.assertEqual(expected, actual)
def test_should_raise_shape_missmatch_error_while_multiplying_matrices(self): def test_should_raise_shape_missmatch_error_while_multiplying_matrices(self):
m1 = Matrix([1, 2], (2, 1)) m1 = Matrix([1, 2], (2, 1))
m2 = Matrix([3, 4], (2, 1)) m2 = Matrix([3, 4], (2, 1))

View File

@ -1,8 +1,8 @@
import numpy as np import numpy as np
from mpi4py import MPI from mpi4py import MPI
from matrix import Matrix from matrix_mpi import MatrixMPI
from vector import Vector from vector_mpi import VectorMPI
np.random.seed(0) np.random.seed(0)
############### ###############
@ -27,13 +27,11 @@ if rank == 0:
n_x1 = 10 n_x1 = 10
x1_list = [i0 for i0 in x1_list = [i0 for i0 in
range(n_x1)] # must work for 4 ranks, too, so even if entries are not evenly distributable between ranks range(n_x1)] # must work for 4 ranks, too, so even if entries are not evenly distributable between ranks
#vec_x1 = Vector(comm, x1_list) vec_x1 = VectorMPI(x1_list)
vec_x1 = Vector(x1_list)
# from numpy array # from numpy array
n_x2 = 10000 n_x2 = 10000
x2_list = np.random.uniform(0, 1, n_x2) x2_list = np.random.uniform(0, 1, n_x2)
#vec_x2 = Vector(comm, x2_list) vec_x2 = VectorMPI(x2_list)
vec_x2 = Vector(x2_list)
if rank == 0: if rank == 0:
print("End 1a\n") print("End 1a\n")
comm.Barrier() comm.Barrier()
@ -64,25 +62,21 @@ if rank == 0:
print("End 1c\n") print("End 1c\n")
comm.Barrier() comm.Barrier()
### 1d addition and substraction ### 1d addition and subtraction
if rank == 0: if rank == 0:
print("Start 1d addition and substraction") print("Start 1d addition and subtraction ")
# intitialization # initialization
n_a = 10 n_a = 10
n_b = 10 n_b = 10
a_list = [i0 for i0 in range(n_a)] a_list = [i0 for i0 in range(n_a)]
b_list = [1 / (i0 + 1) for i0 in range(n_b)] b_list = [1 / (i0 + 1) for i0 in range(n_b)]
#a = Vector(comm, a_list) a = VectorMPI(a_list)
a = Vector(a_list) b = VectorMPI(b_list)
#b = Vector(comm, b_list)
b = Vector(b_list)
# computation # computation
x = a + b x = a + b
y = a - b y = a - b
#numpy_x_compare_norm = (x - Vector(comm, np.array(a_list) + np.array(b_list))).norm() numpy_x_compare_norm = (x - VectorMPI(np.array(a_list) + np.array(b_list))).norm()
numpy_x_compare_norm = (x - Vector(np.array(a_list) + np.array(b_list))).norm() numpy_y_compare_norm = (y - VectorMPI(np.array(a_list) - np.array(b_list))).norm()
#numpy_y_compare_norm = (y - Vector(comm, np.array(a_list) - np.array(b_list))).norm()
numpy_y_compare_norm = (y - Vector(np.array(a_list) - np.array(b_list))).norm()
if rank == 0: if rank == 0:
print(f"norm(a + b - numpy) = {numpy_x_compare_norm} | must be < 1e-8") print(f"norm(a + b - numpy) = {numpy_x_compare_norm} | must be < 1e-8")
print(f"norm(a - b - numpy) = {numpy_x_compare_norm} | must be < 1e-8") print(f"norm(a - b - numpy) = {numpy_x_compare_norm} | must be < 1e-8")
@ -109,23 +103,19 @@ comm.Barrier()
### 1e multiplication ### 1e multiplication
if rank == 0: if rank == 0:
print("Start 1e multiplication") print("Start 1e multiplication")
# intitialization # initialization
n_a = 10 n_a = 10
n_b = 10 n_b = 10
a_list = [i0 for i0 in range(n_a)] a_list = [i0 for i0 in range(n_a)]
b_list = [1 / (i0 + 1) for i0 in range(n_b)] b_list = [1 / (i0 + 1) for i0 in range(n_b)]
#a = Vector(comm, a_list) a = VectorMPI(a_list)
a = Vector(a_list) b = VectorMPI(b_list)
#b = Vector(comm, b_list)
b = Vector(b_list)
# computation with vectors # computation with vectors
x = a.T() * b # scalar x = a.T() * b # scalar
y = a * b # vector y = a * b # vector
# z = b * a.T() # matrix
numpy_x_compare_norm = np.linalg.norm(x - np.sum(np.array(a_list) * np.array(b_list))) numpy_x_compare_norm = np.linalg.norm(x - np.sum(np.array(a_list) * np.array(b_list)))
#numpy_y_compare_norm = (y - Vector(comm, np.array(a_list) * np.array(b_list))).norm() numpy_y_compare_norm = (y - VectorMPI(np.array(a_list) * np.array(b_list))).norm()
numpy_y_compare_norm = (y - Vector(np.array(a_list) * np.array(b_list))).norm() # numpy_z_compare_norm = (z - MatrixMPI(comm,np.outer(np.array(a_list),np.array(b_list)))).norm()
# numpy_z_compare_norm = (z - Matrix(comm,np.outer(np.array(a_list),np.array(b_list)))).norm()
if rank == 0: if rank == 0:
print(f"norm(a.T() * b - numpy) = {numpy_x_compare_norm} | must be < 1e-8") print(f"norm(a.T() * b - numpy) = {numpy_x_compare_norm} | must be < 1e-8")
print(f"norm(a * b - numpy) = {numpy_y_compare_norm} | must be < 1e-8") print(f"norm(a * b - numpy) = {numpy_y_compare_norm} | must be < 1e-8")
@ -133,35 +123,29 @@ if rank == 0:
# computation with scalars # computation with scalars
x = a * 5 x = a * 5
y = 0.1 * b.T() y = 0.1 * b.T()
#numpy_x_compare_norm = (x - Vector(comm, np.array(a_list) * 5)).norm() numpy_x_compare_norm = (x - VectorMPI(np.array(a_list) * 5)).norm()
numpy_x_compare_norm = (x - Vector(np.array(a_list) * 5)).norm() numpy_y_compare_norm = (y - VectorMPI(np.array(b_list) * 0.1).T()).norm()
#numpy_y_compare_norm = (y - Vector(comm, np.array(b_list) * 0.1, transpose=True)).norm()
numpy_y_compare_norm = (y - Vector(np.array(b_list) * 0.1).T()).norm()
if rank == 0: if rank == 0:
print(f"norm(a * 5 - numpy) = {numpy_x_compare_norm} | must be < 1e-8") print(f"norm(a * 5 - numpy) = {numpy_x_compare_norm} | must be < 1e-8")
print(f"norm(0.1 * b.T() - numpy) = {numpy_y_compare_norm} | must be < 1e-8") print(f"norm(0.1 * b.T() - numpy) = {numpy_y_compare_norm} | must be < 1e-8")
print("End 1e\n") print("End 1e\n")
comm.Barrier() comm.Barrier()
### 1f divison ### 1f division
if rank == 0: if rank == 0:
print("Start 1f divison") print("Start 1f division")
# intitialization # initialization
n_a = 10 n_a = 10
n_b = 10 n_b = 10
a_list = [i0 for i0 in range(n_a)] a_list = [i0 for i0 in range(n_a)]
b_list = [1 / (i0 + 1) for i0 in range(n_b)] b_list = [1 / (i0 + 1) for i0 in range(n_b)]
#a = Vector(comm, a_list) a = VectorMPI(a_list)
a = Vector(a_list) b = VectorMPI(b_list)
#b = Vector(comm, b_list)
b = Vector(b_list)
# computation with vectors # computation with vectors
x = a / b x = a / b
y = a / 5 y = a / 5
#numpy_x_compare_norm = (x - Vector(comm, np.array(a_list) / np.array(b_list))).norm() numpy_x_compare_norm = (x - VectorMPI(np.array(a_list) / np.array(b_list))).norm()
numpy_x_compare_norm = (x - Vector(np.array(a_list) / np.array(b_list))).norm() numpy_y_compare_norm = (y - VectorMPI(np.array(a_list) / 5)).norm()
#numpy_y_compare_norm = (y - Vector(comm, np.array(a_list) / 5)).norm()
numpy_y_compare_norm = (y - Vector(np.array(a_list) / 5)).norm()
if rank == 0: if rank == 0:
print(f"norm(a / b - numpy) = {numpy_x_compare_norm} | must be < 1e-8") print(f"norm(a / b - numpy) = {numpy_x_compare_norm} | must be < 1e-8")
print(f"norm(a / 5 - numpy) = {numpy_y_compare_norm} | must be < 1e-8") print(f"norm(a / 5 - numpy) = {numpy_y_compare_norm} | must be < 1e-8")
@ -171,16 +155,14 @@ comm.Barrier()
### 1g norm ### 1g norm
if rank == 0: if rank == 0:
print("Start 1g norm") print("Start 1g norm")
# intitialization # initialization
a_list = [1 / (i0 + 1) for i0 in range(10)] a_list = [1 / (i0 + 1) for i0 in range(10)]
#a = Vector(comm, a_list) a = VectorMPI(a_list)
a = Vector(a_list)
# computation # computation
a_norm = a.norm() a_norm = a.norm()
a_normalized = a.normalize() a_normalized = a.normalize()
a_normalized_str = str(a_normalized) a_normalized_str = str(a_normalized)
#numpy_comparison_norm = (a_normalized - Vector(comm, np.array(a_list) / np.linalg.norm(a_list))).norm() numpy_comparison_norm = (a_normalized - VectorMPI(np.array(a_list) / np.linalg.norm(a_list))).norm()
numpy_comparison_norm = (a_normalized - Vector(np.array(a_list) / np.linalg.norm(a_list))).norm()
if rank == 0: if rank == 0:
print(f"a_norm = {a_norm} | must be {np.linalg.norm(a_list)}") print(f"a_norm = {a_norm} | must be {np.linalg.norm(a_list)}")
print(f"norm(a_normalize-np.a_normalize) = {numpy_comparison_norm} | must be < 1e-8") print(f"norm(a_normalize-np.a_normalize) = {numpy_comparison_norm} | must be < 1e-8")
@ -190,10 +172,9 @@ comm.Barrier()
### 1h negation ### 1h negation
if rank == 0: if rank == 0:
print("Start 1h negation") print("Start 1h negation")
# intitialization # initialization
a_list = [1 / (i0 + 1) for i0 in range(10)] a_list = [1 / (i0 + 1) for i0 in range(10)]
#a = Vector(comm, a_list) a = VectorMPI(a_list)
a = Vector(a_list)
# computation # computation
x = -a x = -a
x_str = str(x) x_str = str(x)
@ -205,11 +186,10 @@ comm.Barrier()
### 1i manipulation ### 1i manipulation
if rank == 0: if rank == 0:
print("Start 1i manipulation") print("Start 1i manipulation")
# intitialization # initialization
n_a = 10 n_a = 10
a_list = [1 / (i0 + 1) for i0 in range(n_a)] a_list = [1 / (i0 + 1) for i0 in range(n_a)]
#a = Vector(comm, a_list) a = VectorMPI(a_list)
a = Vector(a_list)
a_idx = [1, 2, 9, 7, 8] a_idx = [1, 2, 9, 7, 8]
a_values = a[a_idx] a_values = a[a_idx]
if rank == 0: if rank == 0:
@ -224,7 +204,6 @@ if rank == 0:
print("End 1i\n") print("End 1i\n")
comm.Barrier() comm.Barrier()
"""
############### ###############
# Testing the matrix class # Testing the matrix class
comm.Barrier() comm.Barrier()
@ -232,18 +211,18 @@ if rank == 0:
print("\n\nTesting the matrix class -----------------------------------\n\n") print("\n\nTesting the matrix class -----------------------------------\n\n")
############### ###############
### 2a Initialization ### 2a Initialization
if rank == 0: if rank == 0:
print("Start 2a initialization") print("Start 2a initialization")
n_a1 = 10 n_a1 = 10
n_a2 = 5 n_a2 = 5
a_list = np.array([[(i0 + 1) * (i1 + 1) for i0 in range(n_a1)] for i1 in range(n_a2)]) a_list = np.array([[(i0 + 1) * (i1 + 1) for i0 in range(n_a1)] for i1 in range(n_a2)])
A = Matrix(comm, a_list) A = MatrixMPI(a_list)
B = Matrix(comm, structure="tridiagonal", size=12) B = MatrixMPI(structure="tridiagonal", data=[-1, 2, -1], n=12)
c_list = [i0 for i0 in range(n_a1 * n_a1)] c_list = [i0 for i0 in range(n_a1 * n_a1)]
C = Matrix(comm, c_list, shape=(n_a1, n_a1)) C = MatrixMPI(c_list, shape=(n_a1, n_a1))
D = Matrix(comm, model="sheet1ex1", size=50) D = MatrixMPI(structure="tridiagonal", data=[-1, 2, -1], n=50)
# D = MatrixMPI(model="sheet1ex1", n=50)
if rank == 0: if rank == 0:
print("End 2a\n") print("End 2a\n")
comm.Barrier() comm.Barrier()
@ -284,29 +263,29 @@ comm.Barrier()
# if rank == 0: # if rank == 0:
# print(f"Matrix\n{str(mat)}\nlocal max each row {str(local_max_each_row)}") # print(f"Matrix\n{str(mat)}\nlocal max each row {str(local_max_each_row)}")
# # frobenius norm # # frobenius norm
# A = Matrix(comm,mat) # A = MatrixMPI(comm,mat)
# a_norm_fro = A.norm("frobenius") # a_norm_fro = A.norm("frobenius")
# if rank == 0: # if rank == 0:
# print(f"A.norm('frobenius') = {a_norm_fro} | must be {np.linalg.norm(np.array([[(i0+1)*(i1+1) for i0 in range(10)] for i1 in range(5)]),'fro')}") # print(f"A.norm('frobenius') = {a_norm_fro} | must be {np.linalg.norm(np.array([[(i0+1)*(i1+1) for i0 in range(10)] for i1 in range(5)]),'fro')}")
# # row sum norm # # row sum norm
# a_norm_row = A.norm("row sum") # a_norm_row = A.norm("row sum")
# if rank == 0: # if rank == 0:
# print(f"A.norm('row sum') = {a_norm_row} | must be {np.max(local_max_each_row)}") # print(f"A.norm('row sum') = {a_norm_row} | must be {np.max(local_max_each_row)}")
# # col sum norm # # col sum norm
### 2d addition and substraction ### 2d addition and subtraction
if rank == 0: if rank == 0:
print("Start 2d addition and substraction") print("Start 2d addition and subtraction ")
# Initialization # Initialization
n = 10 n = 10
A = Matrix(comm, structure="diagonal", diag_values=[3], offset=0, size=n) A = MatrixMPI(structure="diagonal", data=[3], offset=0, n=n)
A21 = Matrix(comm, structure="diagonal", diag_values=[-1], offset=-1, size=n) A21 = MatrixMPI(structure="diagonal", data=[-1], offset=-1, n=n)
A12 = Matrix(comm, structure="diagonal", diag_values=[-1], offset=+1, size=n) A12 = MatrixMPI(structure="diagonal", data=[-1], offset=+1, n=n)
B = Matrix(comm, structure="diagonal", diag_values=[1], offset=0, size=n) B = MatrixMPI(structure="diagonal", data=[1], offset=0, n=n)
# computation # computation
C = A + A21 + A12 - B C = A + A21 + A12 - B
D = C - Matrix(comm, structure='tridiagonal', diag_values=[-1, 2, -1], size=n) D = C - MatrixMPI(structure='tridiagonal', data=[-1, 2, -1], n=n)
d_norm = D.norm() d_norm = D.norm()
A_str = str(5 + A - 3) A_str = str(5 + A - 3)
if rank == 0: if rank == 0:
@ -324,19 +303,19 @@ a_mat = np.array([[(i0 + 1) / (i1 + 1) for i1 in range(8)] for i0 in range(n)])
b_mat = np.array([[(i0 + 1) / (i1 + 1) for i1 in range(n)] for i0 in range(8)]) b_mat = np.array([[(i0 + 1) / (i1 + 1) for i1 in range(n)] for i0 in range(8)])
c_mat = np.array([[(i0 + 1) / (i1 + 1) for i1 in range(n)] for i0 in range(n)]) c_mat = np.array([[(i0 + 1) / (i1 + 1) for i1 in range(n)] for i0 in range(n)])
d_mat = np.array([[(i0 + 1) / (i1 + 1) for i1 in range(17)] for i0 in range(n)]) d_mat = np.array([[(i0 + 1) / (i1 + 1) for i1 in range(17)] for i0 in range(n)])
A = Matrix(comm, a_mat) A = MatrixMPI(a_mat)
B = Matrix(comm, b_mat) B = MatrixMPI(b_mat)
C = Matrix(comm, c_mat) C = MatrixMPI(c_mat)
D = Matrix(comm, d_mat) D = MatrixMPI(d_mat)
x_vec = np.array([i0 + 1 for i0 in range(n)]) x_vec = np.array([i0 + 1 for i0 in range(n)])
y_vec = np.array([n * (i0 + 1) for i0 in range(n)]) y_vec = np.array([n * (i0 + 1) for i0 in range(n)])
x = Vector(comm, x_vec) x = VectorMPI(x_vec)
y = Vector(comm, y_vec) y = VectorMPI(y_vec)
# computation matrix scalar # computation matrix scalar
norm5 = (5 * A - Matrix(comm, 5 * np.array(a_mat))).norm() norm5 = (5 * A - MatrixMPI(5 * np.array(a_mat))).norm()
# computation matrix vector # computation matrix vector
norm6 = (C * x - Vector(comm, np.array(c_mat) @ np.array(x_vec))).norm() norm6 = (C * x - VectorMPI(np.array(c_mat) @ np.array(x_vec))).norm()
norm7 = (D.T() * x - Vector(comm, np.array(d_mat).T @ np.array(x_vec))).norm() norm7 = (D.T() * x - VectorMPI(np.array(d_mat).T @ np.array(x_vec))).norm()
y_shape = (D.T() * x).shape() y_shape = (D.T() * x).shape()
if rank == 0: if rank == 0:
print(f"Norm of (5*A - np.(5*A)) is {norm5} | must be < 1e-8") print(f"Norm of (5*A - np.(5*A)) is {norm5} | must be < 1e-8")
@ -347,10 +326,10 @@ A_str = str(A)
B_str = str(B) B_str = str(B)
if rank == 0: if rank == 0:
print(f"DEBUG: A\n{A_str}\nDEBUG: B\n{B_str}") print(f"DEBUG: A\n{A_str}\nDEBUG: B\n{B_str}")
norm1 = (A * B - Matrix(comm, np.array(a_mat) @ np.array(b_mat))).norm() norm1 = (A * B - MatrixMPI(np.array(a_mat) @ np.array(b_mat))).norm()
norm2 = (A.T() * A - Matrix(np.array(a_mat).T @ np.array(a_mat))).norm() norm2 = (A.T() * A - MatrixMPI(np.array(a_mat).T @ np.array(a_mat))).norm()
norm3 = (A * A.T() - Matrix(np.array(a_mat) @ np.array(a_mat).T)).norm() norm3 = (A * A.T() - MatrixMPI(np.array(a_mat) @ np.array(a_mat).T)).norm()
norm4 = (B.T() * A.T() - Matrix(np.array(b_mat).T @ np.array(a_mat).T)).norm() norm4 = (B.T() * A.T() - MatrixMPI(np.array(b_mat).T @ np.array(a_mat).T)).norm()
if rank == 0: if rank == 0:
print(f"Norm of (A*B - np.(A*B)) is {norm1} | must be < 1e-8") print(f"Norm of (A*B - np.(A*B)) is {norm1} | must be < 1e-8")
print(f"Norm of (A.T()*A - np(A.T()*A)) is {norm2} | must be < 1e-8") print(f"Norm of (A.T()*A - np(A.T()*A)) is {norm2} | must be < 1e-8")
@ -359,48 +338,44 @@ if rank == 0:
print("End 2e\n") print("End 2e\n")
comm.Barrier() comm.Barrier()
''' ### 2f division
### 2f divison
if rank == 0: if rank == 0:
print("Start 2f divison") print("Start 2f division")
# initialization # initialization
A = Matrix(a_mat) A = MatrixMPI(a_mat)
# computation # 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(f"Norm of (A/5 - np.(A/5)) is {(A / 5 - MatrixMPI(np.array(a_mat) / 5)).norm()} | must be < 1e-8")
if rank == 0: if rank == 0:
print("End 2f\n") print("End 2f\n")
comm.Barrier() comm.Barrier()
### 2g norm ### 2g norm
if rank == 0: if rank == 0:
print("Start 2g norm") print("Start 2g norm")
A = Matrix(structure="tridiagonal",given_size=50,given_values=[-1,2,-1]) A = MatrixMPI(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")
if rank == 0: if rank == 0:
print("End 2g\n") print("End 2g\n")
comm.Barrier() comm.Barrier()
### 2h negation ### 2h negation
if rank == 0: if rank == 0:
print("Start 2h negation") print("Start 2h negation")
A = Matrix(structure="tridiagonal", given_size=50, given_values=[-1,2,1]) A = MatrixMPI(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")
if rank == 0: if rank == 0:
print("End 2h\n") print("End 2h\n")
comm.Barrier() comm.Barrier()
### 2i manipulation ### 2i manipulation
if rank == 0: if rank == 0:
print("Start 2i manipulation") print("Start 2i manipulation")
A = Matrix(structure="tridiagonal", given_size=10, given_values=[-1,2,1]) A = MatrixMPI(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))
if rank == 0: if rank == 0:
print("End 2i\n") print("End 2i\n")
comm.Barrier() comm.Barrier()
'''
"""

View File

@ -1,5 +1,6 @@
from unittest import TestCase from unittest import TestCase
from matrix import Matrix
from vector import Vector from vector import Vector
@ -169,6 +170,24 @@ class TestVector(TestCase):
self.assertEqual(expected, actual) self.assertEqual(expected, actual)
def test_should_mul_matrix_vector(self):
m = Matrix([1, 2, 3, 4, 5, 6], (2, 3))
v = Vector([1, 2, 3])
expected = Vector([14, 32])
actual = m * v
self.assertEqual(expected, actual)
def test_should_mul_matrix_vector_2(self):
m = Matrix([1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4], (3, 4))
v = Vector([1, 2, 3, 4])
expected = Vector([30, 30, 30])
actual = m * v
self.assertEqual(expected, actual)
def test_should_raise_value_missmatch_error_while_mul_vectors(self): def test_should_raise_value_missmatch_error_while_mul_vectors(self):
v1 = Vector([1, 2]) v1 = Vector([1, 2])
v2 = '0' v2 = '0'