1
0
pwr_project/src/vector_mpi.py

85 lines
2.8 KiB
Python
Raw Normal View History

2024-04-27 18:21:33 +02:00
import math
import numpy
from matrix_mpi import MatrixMPI
2024-04-09 17:25:42 +02:00
from vector import Vector
class VectorMPI(MatrixMPI):
def __init__(self, data=None, shape=None):
2024-04-27 18:21:33 +02:00
if isinstance(data, Vector):
self.__data__ = data
else:
self.__data__ = Vector(data=data, shape=shape)
2024-04-23 17:55:18 +02:00
2024-04-27 18:21:33 +02:00
# Calculate how much rows are delegated to the rank
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()
2024-04-27 18:21:33 +02:00
# Store the delegated rows explicitly for calculations
self.__rank_subdata__ = Vector(self.__data__[self.__chunk__])
2024-04-27 18:21:33 +02:00
@staticmethod
def of(vector: Vector):
return VectorMPI(vector)
def transpose(self):
"""
:return: the transpose of the vector
"""
return VectorMPI.of(self.__data__.transpose())
def T(self):
return self.transpose()
2024-04-27 18:21:33 +02:00
def __str__(self):
return str(self.__data__)
def __neg__(self):
return VectorMPI.of(-self.__data__)
def __add__(self, other):
if isinstance(other, VectorMPI):
2024-04-27 18:21:33 +02:00
other = other.__rank_subdata__
return VectorMPI.of(Vector.flatten(self.__mpi_comm__.allgather(self.__rank_subdata__ + other)))
def __mul__(self, other):
if isinstance(other, VectorMPI):
other = other.__data__
2024-04-27 18:21:33 +02:00
if isinstance(other, int) or isinstance(other, float):
result = Vector.flatten(self.__mpi_comm__.allgather(self.__rank_subdata__ * other))
else:
result = self.__data__ * other
return VectorMPI.of(result) if isinstance(result, Vector) else result
def __rmul__(self, other):
if isinstance(other, MatrixMPI):
2024-04-27 18:21:33 +02:00
return VectorMPI.of(Vector.flatten(self.__mpi_comm__.allgather(other.get_rank_subdata() * self.get_data())))
return self * other
def __truediv__(self, other):
if isinstance(other, VectorMPI):
2024-04-27 18:21:33 +02:00
other = other.__rank_subdata__
return VectorMPI.of(Vector.flatten(self.__mpi_comm__.allgather(self.__rank_subdata__ / 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
"""
2024-04-27 18:21:33 +02:00
return math.sqrt(self.__mpi_comm__.allreduce(self.__rank_subdata__.get_abs_sum_of_squares()))
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
"""
2024-04-27 18:21:33 +02:00
return VectorMPI.of(Vector.flatten(self.__mpi_comm__.allgather(self.__rank_subdata__ / self.norm())))