85 lines
2.8 KiB
Python
85 lines
2.8 KiB
Python
import math
|
|
|
|
import numpy
|
|
|
|
from matrix_mpi import MatrixMPI
|
|
from vector import Vector
|
|
|
|
|
|
class VectorMPI(MatrixMPI):
|
|
def __init__(self, data=None, shape=None):
|
|
if isinstance(data, Vector):
|
|
self.__data__ = data
|
|
else:
|
|
self.__data__ = Vector(data=data, shape=shape)
|
|
|
|
# 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()
|
|
|
|
# Store the delegated rows explicitly for calculations
|
|
self.__rank_subdata__ = Vector(self.__data__[self.__chunk__])
|
|
|
|
@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()
|
|
|
|
def __str__(self):
|
|
return str(self.__data__)
|
|
|
|
def __neg__(self):
|
|
return VectorMPI.of(-self.__data__)
|
|
|
|
def __add__(self, other):
|
|
if isinstance(other, VectorMPI):
|
|
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__
|
|
|
|
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):
|
|
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):
|
|
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
|
|
"""
|
|
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
|
|
"""
|
|
return VectorMPI.of(Vector.flatten(self.__mpi_comm__.allgather(self.__rank_subdata__ / self.norm())))
|