Using Python tuples as vectors

I need to represent immutable vectors in Python ("vectors", as in linear algebra, and not as in programming). The tuple seems like an obvious choice.

The problem is when I need to implement things like addition and scalar multiplication. If a and b are vectors and c is a number, the best I can think of:

 tuple(map(lambda x,y: x + y, a, b)) # add vectors 'a' and 'b' tuple(map(lambda x: x * c, a)) # multiply vector 'a' by scalar 'c' 

which seems inelegant; There should be a more understandable and simple way to do this, not to mention avoiding calling tuple , since map returns a list.

Is there a better option?

+4
source share
7 answers

NumPy supports various algebraic operations with its arrays.

+9
source

Continuous types are quite rare in Python and third-party extensions; The OP rightly states: โ€œfor linear algebra, use is enough that I don't seem to need to roll back my own,โ€ but all existing types that I know have mutable linear algebra! Thus, since the OP is adamant about immutability, there is nothing for it but a roll route.

Not that everything that was connected with a large number of operations, for example, if you need 2nd vectors:

 import math class ImmutableVector(object): __slots__ = ('_d',) def __init__(self, x, y): object.__setattr__(self, _d, (x, y)) def __setattr__(self, n, v): raise ValueError("Can't alter instance of %s" % type(self)) @property def x(self): return self._d[0] @property def y(self): return self._d[1] def __eq__(self, other): return self._d == other._d def __ne__(self, other): return self._d != other._d def __hash__(self): return hash(self._d) def __add__(self, other): return type(self)(self.x+other.x, self.y+other.y) def __mul__(self, scalar): return type(self)(self.x*scalar, self.y*scalar) def __repr__(self): return '%s(%s, %s)' % (type(self).__name__, self.x, self.y) def __abs__(self): return math.hypot(self.x, self.y) 

I โ€œthrew for freeโ€ several additional functions, such as the .x and .y R / O properties, a nice string representation, ease of use in sets or as keys in dicts (why else need immutability?), Low memory, abs(v) to give the length of the vector v . I am sure that you can think of other โ€œnot-it-cool-ifโ€ methods and operations, depending on your application field, and they will be just as easy. If you need other sizes, it will not be much more difficult, although less readable, since the .x , .y no longer applied ;-) (but I would use genexps, not map ).

+10
source

By inheriting a tuple, you can easily create a Vector class. There is enough code to ensure that vectors are added and the vector is multiplied by a scalar. It gives you arbitrary length vectors and can work with complex numbers, ints or float.

 class Vector(tuple): def __add__(self, a): # TODO: check lengths are compatable. return Vector(x + y for x, y in zip(self, a)) def __mul__(self, c): return Vector(x * c for x in self) def __rmul__(self, c): return Vector(c * x for x in self) a = Vector((1, 2, 3)) b = Vector((2, 3, 4)) print a + b print 3 * a print a * 3 
+8
source

Although using a library like NumPy seems to be a permission for OP, I think that in a simple solution there is still some value that does not require additional libraries and which you can remain unchanged with iterations.

Using the itertools and operators modules:

 imap(add, a, b) # returns iterable to sum of a and b vectors 

This implementation is simple. It does not use lambda not any list conversion, since it is based on an iterator.

 from itertools import imap from operator import add vec1 = (1, 2, 3) vec2 = (10, 20, 30) result = imap(add, vec1, vec2) print(tuple(result)) 

Productivity:

 (11, 22, 33) 
+5
source

Why not create your own class using two Cartesian member variables? (sorry if the syntax is a bit off, my python is rusty)

 class point: def __init__(self,x,y): self.x=x self.y=y #etc def add(self,p): return point(self.x + px, self.y + py) class vector: def __init__(self,a,b): self.pointA=a self.pointB=b #etc def add(self,v): return vector(self.pointA + v.pointA, self.pointB + v.pointB) 
+3
source

Since almost all sequence processing functions return lists, this is pretty much what you need to do.

0
source

For casual use, a Python 3 solution without repeating lambdas is possible using the standard statement package:

 from operator import add, mul a = (1, 2, 3) b = (4, 5, 6) print(tuple(map(add, a , b))) print(tuple(map(mul, a , b))) 

which prints:

 (5, 7, 9) (4, 10, 18) 

For serious calculations of linear algebra using numerical vectors is the canonical solution:

 import numpy as np a = np.array([1, 2, 3]) b = np.array([4, 5, 6]) print(a+b) print(a*b) 

which prints:

 [5 7 9] [ 4 10 18] 
0
source

Source: https://habr.com/ru/post/1305995/


All Articles