From 71f6c19f51bca94ba551e63781c8ec5776d331f2 Mon Sep 17 00:00:00 2001 From: niklas Date: Sat, 13 Jan 2024 13:53:21 +0100 Subject: [PATCH] Finalize vector.py --- src/matrix.py | 7 +++--- src/vector.py | 53 +++++++++------------------------------ test/test_vector.py | 60 ++++++++++++++++++++++++++++++++------------- 3 files changed, 57 insertions(+), 63 deletions(-) diff --git a/src/matrix.py b/src/matrix.py index 4489d56..df98c10 100644 --- a/src/matrix.py +++ b/src/matrix.py @@ -114,9 +114,9 @@ class Matrix: if isinstance(other, Matrix): if self.__shape__ != other.__shape__: raise ValueError("The shape of the operands must be the same") - return self.__data__ + other.__data__ + return Matrix(self.__data__ + other.__data__) elif isinstance(other, int) or isinstance(other, float): - return self.__data__ + other + return Matrix(self.__data__ + other) else: raise ValueError("Only a number or another ``Matrix`` can be added to a ``Matrix``") @@ -145,7 +145,7 @@ class Matrix: def __truediv__(self, other): if isinstance(other, int) or isinstance(other, float): - return self.__data__ / other + return Matrix(self.__data__ / other) else: raise ValueError("A ``Matrix`` can only be divided ba a number") @@ -172,4 +172,3 @@ class Matrix: def __setitem__(self, key, value): self.__data__[key] = value - diff --git a/src/vector.py b/src/vector.py index 15254b4..a430d15 100644 --- a/src/vector.py +++ b/src/vector.py @@ -4,65 +4,34 @@ from matrix import Matrix class Vector(Matrix): - __data__ = [] - - def __init__(self, data): + def __init__(self, data: list | int): """ :type data: list | int """ - super().__init__(numpy.array([0])) # TODO: remove in future if isinstance(data, list): - self.__data__ = data + super().__init__(data, (len(data), 1)) elif isinstance(data, int): self.__init__([0] * data) else: raise ValueError("data must be a list or an integer for dimension") - def get_data(self): - return self.__data__ - def get_dimension(self): - return len(self.__data__) - - def __iter__(self): - return iter(self.__data__) - - def __eq__(self, other): - return self.__data__ == other.__data__ - - def __str__(self): - return f"{self.__data__}" - - def __neg__(self): - return Vector([-x for x in self.__data__]) - - def __add__(self, other): - if isinstance(other, Vector): - if self.get_dimension() != other.get_dimension(): - raise ValueError("The vectors to be added must have the same dimension") - return Vector([(x + y) for (x, y) in zip(self, other)]) - elif isinstance(other, int) or isinstance(other, float): - return Vector([(x + other) for x in self.__data__]) - else: - raise ValueError("A vector can only be multiplied with an vector (dot product) or a scalar") - - def __radd__(self, other): - return self + other - - def __sub__(self, other): - return self + (-other) - - def __rsub__(self, other): - return -self + other + return super().shape()[0] def __mul__(self, other): if isinstance(other, Vector): - return sum([(x * y) for (x, y) in zip(self, other)]) + return (super().transpose().__mul__(other))[0][0] elif isinstance(other, int) or isinstance(other, float): - return Vector([(other * x) for x in self.__data__]) + return super().__mul__(other) else: raise ValueError("A vector can only be multiplied with an vector (dot product) or a scalar") def __rmul__(self, other): return self * other + + def norm(self, **kwargs): + return super().norm() + + def normalize(self): + return self / self.norm() diff --git a/test/test_vector.py b/test/test_vector.py index 474cdf4..6b0f79f 100644 --- a/test/test_vector.py +++ b/test/test_vector.py @@ -5,25 +5,21 @@ from vector import Vector class TestVector(TestCase): def test_should_create_vector_dim_5(self): - vector = Vector(5) - - actual = vector.get_dimension() + actual = Vector(5).get_dimension() expected = 5 + self.assertEqual(expected, actual) def test_should_create_zero_vector(self): - vector = Vector(5) + actual = Vector(5) + expected = Vector([0, 0, 0, 0, 0]) - actual = vector.get_data() - expected = [0, 0, 0, 0, 0] self.assertEqual(expected, actual) def test_should_create_vector(self): - data = list(range(5)) - vector = Vector(data) + actual = Vector(list(range(5))) + expected = Vector([0, 1, 2, 3, 4]) - actual = vector.get_data() - expected = [0, 1, 2, 3, 4] self.assertEqual(expected, actual) def test_should_neg_vector(self): @@ -31,6 +27,7 @@ class TestVector(TestCase): expected = Vector([-1, -2]) actual = -v + self.assertEqual(expected, actual) def test_should_add_vectors(self): @@ -39,6 +36,7 @@ class TestVector(TestCase): expected = Vector([4, 6]) actual = v1 + v2 + self.assertEqual(expected, actual) def test_should_add_scalar_to_vector(self): @@ -47,6 +45,7 @@ class TestVector(TestCase): expected = Vector([3, 4]) actual = v + s + self.assertEqual(expected, actual) def test_should_radd_scalar_to_vector(self): @@ -55,67 +54,94 @@ class TestVector(TestCase): expected = Vector([3, 4]) actual = s + v + self.assertEqual(expected, actual) def test_should_raise_value_missmatch_error_while_adding_vectors(self): v1 = Vector(1) v2 = Vector(2) + self.assertRaises(ValueError, lambda: v1 + v2) def test_should_raise_dimension_error_while_adding_vectors(self): v1 = Vector(1) v2 = '0' + self.assertRaises(ValueError, lambda: v1 + v2) - def test_should_subtract_vectors(self): + def test_should_sub_vectors(self): v1 = Vector([1, 2]) v2 = Vector([3, 4]) expected = Vector([-2, -2]) actual = v1 - v2 + self.assertEqual(expected, actual) - def test_should_subtract_scalar_of_vector(self): + def test_should_sub_scalar_of_vector(self): v = Vector([1, 2]) s = 2 expected = Vector([-1, 0]) actual = v - s + self.assertEqual(expected, actual) - def test_should_rsubtract_scalar_of_vector(self): + def test_should_rsub_scalar_of_vector(self): v = Vector([1, 2]) s = 2 expected = Vector([1, 0]) actual = s - v + self.assertEqual(expected, actual) - def test_should_multiply_vectors(self): + def test_should_mul_vectors(self): v1 = Vector([1, 2]) v2 = Vector([3, 4]) expected = 11 actual = v1 * v2 + self.assertEqual(expected, actual) - def test_should_multiply_scalar_with_vector(self): + def test_should_mul_scalar_with_vector(self): v = Vector([1, 2]) s = 2 expected = Vector([2, 4]) actual = v * s + self.assertEqual(expected, actual) - def test_should_rmultiply_scalar_with_vector(self): + def test_should_rmul_scalar_with_vector(self): v = Vector([1, 2]) s = 2 expected = Vector([2, 4]) actual = s * v + self.assertEqual(expected, actual) - def test_should_raise_value_missmatch_error_while_multiplying_vectors(self): + def test_should_raise_value_missmatch_error_while_mul_vectors(self): v1 = Vector([1, 2]) v2 = '0' + self.assertRaises(ValueError, lambda: v1 * v2) + + def test_should_return_vector_norm(self): + v = Vector([1, 2]) + + actual = v.norm() + expected = 2.236 + + self.assertAlmostEqual(expected, actual, 3) + + def test_should_return_normalized_vector(self): + v = Vector([1, 2]) + + actual = v.normalize() + expected = [1 / 2.236, 2 / 2.236] + + self.assertAlmostEqual(expected[0], actual[0][0], 3) + self.assertAlmostEqual(expected[1], actual[1][0], 3)