    # Vectors using NumPy

A vector is an object that has both a magnitude or size and a direction. “Geometrically, we can picture a vector as a directed line segment, whose length is the magnitude of the vector and with an arrow indicating the direction,” An introduction to vectors, Math Insight. ``````user@pc:~\$ python # Let's work with vectors in Python
Python 3.8.10 (default, Jun  2 2021, 10:49:15)
>>> import numpy as np # NumPy is a library that supports vectors and matrices in an optimized way.
``````
• First, we define two vectors: v: [3, 4, 5] and w: [2, 7, 1];
``````>>> v = np.array([3, 4, 5]) # Data manipulation in Python is almost synonymous with NumPy array manipulation.
>>> w = np.array([2, 7, 1])
``````
• Next, we perform some operations on them. Let’s add both vectors: v+w. Observe that adding the respective components of two vectors yields a vector which is the sum of both vectors. Let u = [u1, u2, u3] and v = [v1, v2, v3]. Then u + v = [u1+v1, u2+v2, u3+v3]. Vector subtraction: u - v = [u1-v1, u2-v2, u3-v3]. Scalar multiplication: 3.v. Multiplying all the components of a vector by a constant is equivalent to multiplying the vector by that constant, k u = [ku1, ku2, k*u3]
``````>>> np.add(v, w) # numpy.add adds arguments element-wise: v+w.
array([ 5, 11,  6])
>>> np.subtract(v, w) # numpy.subtract subtracts arguments element-wise: v-w.
array([ 1, -3,  4])
>>> v*3
array([ 9, 12, 15])
``````
• The dot product or scalar product of two vectors is obtained by multiplying their magnitudes with the cosine of the angle between them: u.v=||u|| ||v|| cosθ = u1v1 + u2v2 + u3*v3. Thus, v.w = 6 + 28 + 5 = 39.
``````>>> np.dot(v, w) # It calculates the dot product or scalar product of v and w.
39
``````
• The magnitude or Euclidean norm (or Euclidean length) of a vector, denoted by ||v||, is the length of the vector. ||v|| = sqrt(v1^2 + v2^2 + v3^2) = sqrt(v.v) = sqrt(9 + 16 + 25)= sqrt(50) =sqrt(52 *2) = 5√2.
``````>>> np.linalg.norm(v) # It computes the magnitude or Euclidean norm of v.
7.0710678118654755 # = sqrt(50)
>>> np.cross(v, w) # numpy.cross returns the cross product of two vectors.
array([-31,   7,  13])
>>> x = np.array([4, 2, 4])
>>> x/np.linalg.norm(x) # It normalizes the vector.
array([0.66666667, 0.33333333, 0.66666667]) # {2/3,1/3,2/3}
``````

# Our own 2d vector class

``````import math
from settings import * # It defines the constant THRESHOLD
import copy
class myVector(object):
""" It defines a two-dimensional vector with Cartesian coordinates."""
def __init__(self, x=0, y=0):
self.x = x
self.y = y

## It implements the addition of two vectors.
# @params other is the vector from which self is to be added.
# @return the new vector object that is the result of self + other.
if isinstance(other, int):
other = myVector(other)

return myVector(self.x + other.x, self.y + other.y)

``````

radd is called if the left object does not have an add method or that method does not know how to add the two objects, e.g., v1 = myVector(2, 3), print(2 + v1) prints 4i + 3j.

``````    ## It implements the subtraction of two vectors.
# @params other is the vector from which self is to be subtracted.
# @return the new vector object that is the result of self - other.
def __sub__(self, other):
if isinstance(other, int):
other = myVector(other)

return myVector(self.x - other.x, self.y - other.y)

def __rsub__(self, other):
return myVector(other) - self

def __neg__(self):
return myVector(-self.x, -self.y)

## It implements the multiplication of a scalar by a vector.
def __mul__(self, scalar):
if isinstance(scalar, int) or isinstance(scalar, float):
return myVector(self.x * scalar, self.y * scalar)
raise NotImplementedError('You can only multiply a vector by a scalar')

def __rmul__(self, scalar):
"""__rmul__ needs to be implemented so scalar * vector also works."""
return self._mul__(scalar)

## It implements the division of the vector by a scalar.
def __div__(self, scalar):
if scalar != 0:
return myVector(self.x / float(scalar), self.y / float(scalar))
return None

def __truediv__(self, scalar):
return self._div__(scalar)
``````

__eq__ implements the comparison of two vectors: self and other. Typically, it would be something like return self.x == other.x and self.y == other.y.

However, rounding errors when using computers are to be expected and we want to be able to deal with them in a consistent manner. This will be useful when we code our Pacman clone.

``````    def __eq__(self, other):
return (self.x - other.x).magnitude() < THRESHOLD and (self.y - other.y).magnitude < THRESHOLD

def __ne__(self, other):
return not self._eq__(other)

def magnitude(self):
""" It returns the absolute value or magnitude of the vector."""
return math.sqrt(self.x**2 + self.y**2)

def distanceTo(self, other):
""" It calculates the distance between two vectors or points: self and other."""
return (self-other).magnitude()

def to_polar(self):
"""It calculates the vector in polar coordinates."""
return self.magnitude(), math.atan2(self.y, self.x)

def __repr__(self):
"""It returns a string representation of the vector."""
return repr((self.x, self.y))

def __str__(self):
"""It returns a string representation of the vector."""
return f"{self.x:.2f}i + {self.y:.2f}j"

@staticmethod
def distance(v1, v2):
""" It calculates the distance between two vectors."""
return (v1-v2).magnitude()

def __copy__(self):
""" It creates a new instance or clone of the object without touching the object itself."""
return myVector(self.x, self.y)

def getVector(self):
return self.x, self.y

def getVectorAsInt(self):
return int(self.x), int(self.y)

def dot(self, other):
"""It implements the scalar product of vectors. It returns the scalar or dot product of self and other. Both self and other must be vectors."""

if not isinstance(other, myVector):
raise TypeError('Both arguments need to be vectors.')
return self.x * other.x + self.y * other.y

# We want to alias the __matmul__ method to dot so we can use a @ b as well as a.dot(b).
__matmul__ = dot

def normalize(self):
""" It returns the normalized vector."""
return self.__class__(self.x/self.magnitude(), self.y/self.magnitude())

if __name__ == '__main__':
v1 = myVector(2, 3)
v2 = copy.copy(v1)
v2 = 2 + v1
print(v1) # 2.00i + 3.00j. We modify the copy but the original object remains unchanged.
print(v2) # 4.00i + 3.00j
v2 = myVector(3, -1.5)
print('repr(v2) = ', repr(v2)) # repr(v2) =  (3, -1.5)
print('v1 + v2 = ', v1 + v2) # v1 + v2 =  5.00i + 1.50j
print('v1 - v2 = ', v1 - v2) # v1 - v2 =  -1.00i + 4.50j
pprint('abs(v1) = ', myVector.magnitude(v1)) # abs(v1) =  3.605551275463989
print('-v2 = ', -v2) # -v2 = -3.00i + 1.50j
print('v1 * 3 = ', v1 * 3) # v1 * 3 =  6.00i + 9.00j
print(v1.normalize()) # 0.55i + 0.83j
print('7 * v1 = ', 7 * v1) # 7 * v1 =  14.00i + 21.00j
print('v2 / 2.5 = ', v2 / 2.5) # v2 / 2.5 =  1.20i + -0.60j
print('v1.dot(v2) = v1 @ v2 = ', v1 @ v2) # v1.dot(v2) = v1 @ v2 =  1.5
print("v1.distance_to(v2) = " + str(v1.distanceTo(v2))) # v1.distance_to(v2) = 4.6097722286464435
print('v1 as a polar vector, (r, theta) =', v1.to_polar()) # v1 as a polar vector, (r, theta) = (3.605551275463989, 0.982793723247329)
``````
Bitcoin donation 