Finalize matrix_mpi.py; Add more vector_mpi.py
This commit is contained in:
24
src/main.py
24
src/main.py
@ -1,6 +1,26 @@
|
||||
# m1 = MatrixMPI(numpy.random.uniform(0, 1, 1_000_000), (1000, 1000))
|
||||
|
||||
from mpi4py import MPI
|
||||
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)
|
||||
|
@ -210,10 +210,19 @@ class Matrix:
|
||||
else:
|
||||
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):
|
||||
if self.__shape__[0] == 1:
|
||||
return self.__mul_rowmatrix_matrix__internal__(other)
|
||||
rows = self.__shape__[0]
|
||||
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 k in range(cols):
|
||||
new_data[i][k] = sum([self.__data__[i][j] * other.__data__[j][k] for j in range(self.__shape__[1])])
|
||||
|
@ -5,21 +5,17 @@ from matrix import Matrix
|
||||
|
||||
|
||||
class MatrixMPI:
|
||||
__mpi_comm__ = None
|
||||
__mpi_size__ = None
|
||||
__mpi_rank__ = None
|
||||
__mpi_comm__ = MPI.COMM_WORLD
|
||||
__mpi_size__ = __mpi_comm__.Get_size()
|
||||
__mpi_rank__ = __mpi_comm__.Get_rank()
|
||||
|
||||
__matrix__: Matrix = None
|
||||
__data__: Matrix = None
|
||||
__chunk__: list = None
|
||||
|
||||
def __init__(self, mpi_comm, data=None, shape=None, structure=None, model=None, offset=None, n=None):
|
||||
self.__mpi_comm__ = mpi_comm
|
||||
self.__mpi_size__ = self.__mpi_comm__.Get_size()
|
||||
self.__mpi_rank__ = self.__mpi_comm__.Get_rank()
|
||||
def __init__(self, data=None, shape=None, structure=None, model=None, offset=None, n=None):
|
||||
self.__data__ = Matrix(data=data, shape=shape, structure=structure, model=model, offset=offset, n=n)
|
||||
|
||||
self.__matrix__ = Matrix(data=data, shape=shape, structure=structure, model=model, offset=offset, n=n)
|
||||
|
||||
total_amount_of_rows = self.__matrix__.shape()[0]
|
||||
total_amount_of_rows = self.__data__.shape()[0]
|
||||
chunks = numpy.array_split(list(range(total_amount_of_rows)), self.__mpi_size__)
|
||||
self.__chunk__ = chunks[self.__mpi_rank__].tolist()
|
||||
|
||||
@ -28,18 +24,24 @@ class MatrixMPI:
|
||||
return MatrixMPI(matrix.get_data(), matrix.shape())
|
||||
|
||||
def __str__(self):
|
||||
return str(self.__matrix__)
|
||||
return str(self.__data__)
|
||||
|
||||
def shape(self):
|
||||
return self.__data__.shape()
|
||||
|
||||
def get_rank_submatrix(self):
|
||||
rows = len(self.__chunk__)
|
||||
cols = self.__matrix__.shape()[1]
|
||||
return Matrix(self.__matrix__[self.__chunk__], (rows, cols))
|
||||
cols = self.__data__.shape()[1]
|
||||
return Matrix(self.__data__[self.__chunk__], (rows, cols))
|
||||
|
||||
def get_data(self):
|
||||
return self.__data__
|
||||
|
||||
def transpose(self):
|
||||
"""
|
||||
:return: the transpose of the matrix
|
||||
"""
|
||||
return MatrixMPI.of(self.__matrix__.transpose())
|
||||
return MatrixMPI.of(self.__data__.transpose())
|
||||
|
||||
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
|
||||
"""
|
||||
if isinstance(other, MatrixMPI):
|
||||
return self.__matrix__ == other.__matrix__
|
||||
return self.__data__ == other.__data__
|
||||
else:
|
||||
return self.__matrix__ == other
|
||||
return self.__data__ == other
|
||||
|
||||
def __neg__(self):
|
||||
gathered_data = self.__mpi_comm__.gather(-self.get_rank_submatrix())
|
||||
@ -89,9 +91,10 @@ class MatrixMPI:
|
||||
|
||||
def __mul__(self, other):
|
||||
if isinstance(other, MatrixMPI):
|
||||
return self.__matrix__ * other.__matrix__
|
||||
else:
|
||||
return self.__matrix__ * other
|
||||
other = other.get_data()
|
||||
gathered_data = self.__mpi_comm__.gather(self.get_rank_submatrix() * other)
|
||||
data = self.__mpi_comm__.bcast(gathered_data)
|
||||
return MatrixMPI.of(Matrix.flatten(data))
|
||||
|
||||
def __rmul__(self, other):
|
||||
return self * other
|
||||
@ -107,11 +110,10 @@ class MatrixMPI:
|
||||
|
||||
:return: the norm as a number
|
||||
"""
|
||||
return self.__matrix__.norm(f)
|
||||
return self.__data__.norm(f)
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self.__matrix__[key]
|
||||
return self.__data__[key]
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
self.__matrix__[key] = value
|
||||
|
||||
self.__data__[key] = value
|
||||
|
@ -86,7 +86,7 @@ class Vector(Matrix):
|
||||
return Vector(self.__mul_vector_same_shape_internal__(other))
|
||||
elif self.__shape__ == tuple(reversed(other.__shape__)):
|
||||
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
|
||||
new_data, shape = self.__mul_tensor_internal__(other)
|
||||
return Matrix(new_data, shape)
|
||||
@ -95,10 +95,19 @@ class Vector(Matrix):
|
||||
elif isinstance(other, int) or isinstance(other, float):
|
||||
return Vector(super().__mul_scalar_internal__(other))
|
||||
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")
|
||||
|
||||
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):
|
||||
if isinstance(other, Matrix):
|
||||
return Vector(self.__mul_matrix_vector_internal__(other))
|
||||
return self * other
|
||||
|
||||
def __truediv_vector_internal__(self, other):
|
||||
|
@ -1,378 +1,88 @@
|
||||
import numpy
|
||||
from mpi4py import MPI
|
||||
from matrix_mpi import MatrixMPI
|
||||
from vector import Vector
|
||||
|
||||
|
||||
class VectorMPI:
|
||||
__mpi_comm__ = None
|
||||
__mpi_size__ = None
|
||||
__mpi_rank__ = None
|
||||
class VectorMPI(MatrixMPI):
|
||||
__data__: Vector = 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):
|
||||
self.__mpi_comm__ = mpi_comm
|
||||
self.__mpi_size__ = self.__mpi_comm__.Get_size()
|
||||
self.__mpi_rank__ = self.__mpi_comm__.Get_rank()
|
||||
@staticmethod
|
||||
def of(vector: Vector):
|
||||
return VectorMPI(vector.get_data(), vector.shape())
|
||||
|
||||
self.__vector__ = Vector(data=data, shape=shape)
|
||||
def get_vector(self):
|
||||
return self.__data__
|
||||
|
||||
# class Vector:
|
||||
# start_idx = 0 # Nullter Eintrag des Vektors auf dem aktuellen Rang
|
||||
# end_idx = 0 # Letzer Eintrag des Vektors auf dem aktuellen Rang
|
||||
# rank_size = 0 # Dimension des Vektors der auf dem aktuellen Rang gespeichert wird
|
||||
# kind = '' # Art des Vektors, Zeilen oder Spaltenvektor
|
||||
# vec = np.arange(rank_size)
|
||||
# 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
|
||||
#
|
||||
# comm = MPI.COMM_WORLD
|
||||
# size = comm.Get_size()
|
||||
# rank = comm.Get_rank()
|
||||
#
|
||||
# # Konstruktor
|
||||
# def __init__(self, array):
|
||||
#
|
||||
# if isinstance(array, np.ndarray):
|
||||
# form = array.shape
|
||||
# if len(array) < self.size:
|
||||
# raise ValueError("ERROR_3: Die Dimension des Vektors ist kleiner als die Anzahl der benutzten Ränge.")
|
||||
#
|
||||
# if len(form) > 2:
|
||||
# raise ValueError("ERROR_2: Falsche Dimension, kann kein 1 x n oder n x 1 Vektor sein.")
|
||||
# # Array ist Zeilenvektor:
|
||||
# if len(form) == 1 or (len(form) == 2 and form[0] == 1):
|
||||
# self.vshape[0] = 1
|
||||
# self.vshape[1] = len(array) # Shape des Vectors
|
||||
# self.start_idx = int(self.rank * len(array) / self.size)
|
||||
# self.end_idx = int(len(array) / self.size + self.rank * len(array) / self.size) - 1
|
||||
# self.rank_size = (
|
||||
# self.end_idx - self.start_idx) + 1 # Größe des Teilvektors auf dem akt. Rang: Differenz zw. Start- und Endindex + 1
|
||||
# self.vec = array[
|
||||
# self.start_idx: self.end_idx + 1] # Auf jedem Rang werden die Einträge vom Start bis zum Endindex gespeichert
|
||||
# self.kind = 'row'
|
||||
# self.dim = len(array)
|
||||
#
|
||||
# # Array ist Spaltenvektor
|
||||
# if len(form) == 2 and form[1] == 1:
|
||||
# self.vshape[0] = len(array)
|
||||
# self.vshape[1] = 1
|
||||
# self.start_idx = int(self.rank * len(array) / self.size)
|
||||
# self.end_idx = int(len(array) / self.size + self.rank * len(array) / self.size) - 1
|
||||
# self.rank_size = (
|
||||
# self.end_idx - self.start_idx) + 1 # Größe des Teilvektors auf dem akt. Rang: Differenz zw. Start- und Endindex + 1
|
||||
# self.vec = array[
|
||||
# self.start_idx: self.end_idx + 1] # Auf jedem Rang werden die Einträge vom Start bis zum Endindex gespeichert
|
||||
# self.kind = 'column'
|
||||
# self.dim = len(array)
|
||||
#
|
||||
# elif isinstance(array, list):
|
||||
# self.vshape[0] = 1
|
||||
# self.vshape[1] = len(array)
|
||||
# self.start_idx = int(self.rank * len(array) / self.size)
|
||||
# self.end_idx = int(len(array) / self.size + self.rank * len(array) / self.size) - 1
|
||||
# self.rank_size = (self.end_idx - self.start_idx) + 1
|
||||
# self.vec = np.array(array[self.start_idx:self.end_idx + 1])
|
||||
# self.kind = 'row'
|
||||
# self.dim = len(array)
|
||||
# else:
|
||||
# raise ValueError(
|
||||
# "ERROR_1: Die übergebene Variable ist kein Numpy-Array, Keine Initialisierung der Vector-Klasse möglich.")
|
||||
#
|
||||
# def __add__(self, other): # Überschreibung der Addition
|
||||
# if isinstance(self, Vector) and isinstance(other, Vector):
|
||||
# Add_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):
|
||||
# Add_Vec.vec[i] = self.vec[i] + other.vec[i]
|
||||
# else:
|
||||
# raise ValueError("Die Dimensionen der Vektoren stimmen nicht überein, Addition nicht möglich.")
|
||||
# elif 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
|
||||
# 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)
|
||||
def shape(self):
|
||||
return self.__data__.shape()
|
||||
|
||||
def __eq__(self, other):
|
||||
"""
|
||||
Return ``self==value``
|
||||
|
||||
: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
|
||||
"""
|
||||
if isinstance(other, VectorMPI):
|
||||
return self.__data__ == other.__data__
|
||||
else:
|
||||
return self.__data__ == other
|
||||
|
||||
def transpose(self):
|
||||
"""
|
||||
:return: the transpose of the vector
|
||||
"""
|
||||
return VectorMPI.of(self.__data__.transpose())
|
||||
|
||||
def T(self):
|
||||
return self.transpose()
|
||||
|
||||
def __neg__(self):
|
||||
return VectorMPI.of(-self.__data__)
|
||||
|
||||
def __add__(self, other):
|
||||
if isinstance(other, VectorMPI):
|
||||
other = other.__data__
|
||||
return VectorMPI.of(self.__data__ + other)
|
||||
|
||||
def __mul__(self, other):
|
||||
if isinstance(other, VectorMPI):
|
||||
other = other.__data__
|
||||
result = self.__data__ * other
|
||||
return VectorMPI.of(result) if isinstance(result, Vector) else result
|
||||
|
||||
def __rmul__(self, other):
|
||||
if isinstance(other, MatrixMPI):
|
||||
return VectorMPI.of(other.get_data() * self.get_vector())
|
||||
return self * other
|
||||
|
||||
def __truediv__(self, other):
|
||||
if isinstance(other, VectorMPI):
|
||||
other = other.__data__
|
||||
return VectorMPI.of(self.__data__ / other)
|
||||
|
||||
def norm(self, **kwargs):
|
||||
"""
|
||||
Computes the 2-norm of the vector which is the Frobenius-Norm of a nx1 matrix.
|
||||
|
||||
:param kwargs: ignored
|
||||
:return: the 2-norm of the vector
|
||||
"""
|
||||
return self.__data__.norm()
|
||||
|
||||
def normalize(self):
|
||||
"""
|
||||
A normalized vector has the length (norm) 1.
|
||||
To achieve that the vector is divided by the norm of itself.
|
||||
|
||||
:return: the normalized vector
|
||||
"""
|
||||
return VectorMPI.of(self.__data__ / self.norm())
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self.__data__[key]
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
self.__data__[key] = value
|
||||
|
Reference in New Issue
Block a user