I made this class that computes some operations for 3d vectors, is there anyway I can change the code so that it computes the same operations but for vectors of any dimension n?
import sys
class Vector:
def __init__(self,x,y,z):
self.x= x
self.y= y
self.z= z
def __repr__(self):
return "(%f,%f,%f)"%(self.x,self.y,self.z)
def __add__(self,other):
return (self.x+other.x,self.y+other.y,self.z+other.z)
def __sub__(self,other):
return (self.x-other.x,self.y-other.y,self.z-other.z)
def __norm__(self):
return (self.x**2+self.y**2+self.z**2)**0.5
def escalar(self,other):
return (self.x*other.x+self.y*other.y+self.z*other.z)
def __mod__(self,other):
return (self.x%other.x,self.y%other.y,self.z%other.z)
def __neg__(self):
return (-self.x,-self.y,-self.z)
As an example, for a n dimensional vector, something like
class Vector:
def __init__(self, components):
self.components = components # components should be a list
def __add__(self, other):
assert len(other.components) == len(self.components)
added_components = []
for i in range(len(self.components)):
added_components.append(self.components[i] + other.components[i])
return Vector(added_components)
def dimensions(self):
return len(self.components)
would be possible. Note that the __add__ override returns a new Vector instance, not a tuple as in your case. Then adapt your other methods likewise.
There are more 'clever' ways of adding elements from two lists, into a third. You should really not do it this way if performance is an issue though (or in any other case but an exercise, IMO). Look into numpy.
Use a list to store the coefficients rather than explicit variables. For negating, adding, subtracting etc. you just iterate over the lists.
In terms of initialisation, you need to use *args for the input. Have a look at this post for an explanation of how it works: https://stackoverflow.com/a/3394898/1178052
Related
I am facing a challenging issue in order to make my Python3 code more elegant.
Suppose I have a number function with variable number of different inputs, for example something like this:
def fun1(a,b):
return a+b
def fun2(c,d,e):
return c*d + e
def fun3(x):
return x*x
These functions needs to be agglomerated in a single function that needs to be used as the optimization function of a numerical solver.
However I need to create different combinations of various operations with these functions, like for example multiplying the output of the first two functions and summing by the third.
The manual solution is to create a specific lambda function:
fun = lambda x : fun1(x[0],x[1])*fun2(x[2],x[3],x[4]) + fun3(x[4])
but the number of functions I have is large and I need to produce all the possibile combinations of them.
I would like to systematically be able to compose these functions and always knowing the mapping from the arguments of higher level function fun to the lower level arguments of each single function.
In this case I manually specified that x[0] corresponds to the argument a of fun1, x[1] corresponds to argument b of fun1 etcetera.
Any idea?
It sounds like you are trying to do what is known as symbolic regression. This problem is often solved via some variation on genetic algorithms which encode the functional relationships in the genes and then optimise based on a fitness function which includes the prediction error as well as a term which penalises more complicated relationships.
Here are two libraries which solve this problem for you:
GPLearn
dcgpy
The following classes provide a rudimentary way of composing functions and keeping track of the number of arguments each one requires, which appears to be the main problem you have:
class Wrapper:
def __init__(self, f):
self.f = f
self.n = f.__code__.co_argcount
def __call__(self, x):
return self.f(*x)
def __add__(self, other):
return Add(self, other)
def __mul__(self, other):
return Mul(self, other)
class Operator:
def __init__(self, left, right):
self.left = left
self.right = right
self.n = left.n + right.n
class Mul(Operator):
def __call__(self, x):
return self.left(x[:self.left.n]) * self.right(x[self.left.n:])
class Add(Operator):
def __call__(self, x):
return self.left(x[:self.left.n]) + self.right(x[self.left.n:])
To use them, you first create wrappers for each of your functions:
w1 = Wrapper(fun1)
w2 = Wrapper(fun2)
w3 = Wrapper(fun3)
Then you can add and multiply the wrappers to get a new function-like object:
(w1 + w2*w3)([1, 2, 3, 4, 5, 6])
This could be a solution:
def fun1(a,b):
return a+b
def fun2(c,d,e):
return c+d+e
def compose(f1,f2):
n1 = len(f1.__code__.co_varnames)
n2 = len(f2.__code__.co_varnames)
F1 = lambda x : f1(*[x[i] for i in range(0,n1)])*f2(*[x[i] for i in range(n1,n1+n2)])
return F1
print(compose(fun1,fun2)([1,2,3,4,5]))
How do you go about overloading the addition, subtraction, and multiplication operator so we can add, subtract, and multiply two vectors of different or identical sizes? For example, if the vectors are different sizes we must be able to add, subtract, or multiply the two vectors according to the smallest vector size?
I've created a function that allows you to modify different vectors, but now I'm struggling to overload the operators and haven't a clue on where to begin. I will paste the code below. Any ideas?
def __add__(self, y):
self.vector = []
for j in range(len(self.vector)):
self.vector.append(self.vector[j] + y.self.vector[j])
return Vec[self.vector]
You define the __add__, __sub__, and __mul__ methods for the class, that's how. Each method takes two objects (the operands of +/-/*) as arguments and is expected to return the result of the computation.
Nothing wrong with the accepted answer on this question but I'm adding some quick snippets to illustrate how this can be used. (Note that you could also "overload" the method to handle multiple types.)
"""Return the difference of another Transaction object, or another
class object that also has the `val` property."""
class Transaction(object):
def __init__(self, val):
self.val = val
def __sub__(self, other):
return self.val - other.val
buy = Transaction(10.00)
sell = Transaction(7.00)
print(buy - sell)
# 3.0
"""Return a Transaction object with `val` as the difference of this
Transaction.val property and another object with a `val` property."""
class Transaction(object):
def __init__(self, val):
self.val = val
def __sub__(self, other):
return Transaction(self.val - other.val)
buy = Transaction(20.00)
sell = Transaction(5.00)
result = buy - sell
print(result.val)
# 15
"""Return difference of this Transaction.val property and an integer."""
class Transaction(object):
def __init__(self, val):
self.val = val
def __sub__(self, other):
return self.val - other
buy = Transaction(8.00)
print(buy - 6.00)
# 2
docs have the answer. Basically there are functions that get called on an object when you add or multiple, etc. for instance __add__ is the normal add function.
import numpy as np
""" A project on beamtracer """
class beam:
def __init__(self,x = np.array([1,2,3]),v = np.array([2,3,4])):
self.x = np.array(x)
self.v = np.array(v)
self.X = [self.x]
self.V = [self.v]
self.z = [(self.X,self.V)]
def p(self):
return self.x
def k(self):
return self.v
def append(self,(self.x,self.v)):
return self.z(append(self.x,self.v))
def coll(self):
return self.z
I was trying to create a beamtracer, so that I can store the 3dimensional position, as well as 3dimensional direction vector at each point, I want self.z to be a list that I can append a 2 elements tuple ( self.x,self.v ) at a time where x and v are 3d arrays
Lastly, I wanted to return all the pairs of points I had stored before, I can't really see what my codes are doing wrong. Thanks everyone.
This won't work:
def append(self,(self.x,self.v)):
return self.z(append(self.x,self.v))
self.x does not make sense until self has a value, which is not the case when the append definition is parsed.
Also, self.z(append...) should be self.z.append.
You could use
def append(self, x, v):
return self.z.append([x, v])
instead.
Warning: you might want to reconsider using lots of small NumPy arrays. The overall performance of such code tends to be disappointing (no better and sometimes worse than if you had just used Python lists or tuples).
To get good performance out of NumPy, you generally want to try to arrange your calculation to use the fewest number of NumPy function calls possible (ideally with no Python loops) and apply those function calls to a single large array, rather than lots of function calls on lots of small arrays.
How do you go about overloading the addition, subtraction, and multiplication operator so we can add, subtract, and multiply two vectors of different or identical sizes? For example, if the vectors are different sizes we must be able to add, subtract, or multiply the two vectors according to the smallest vector size?
I've created a function that allows you to modify different vectors, but now I'm struggling to overload the operators and haven't a clue on where to begin. I will paste the code below. Any ideas?
def __add__(self, y):
self.vector = []
for j in range(len(self.vector)):
self.vector.append(self.vector[j] + y.self.vector[j])
return Vec[self.vector]
You define the __add__, __sub__, and __mul__ methods for the class, that's how. Each method takes two objects (the operands of +/-/*) as arguments and is expected to return the result of the computation.
Nothing wrong with the accepted answer on this question but I'm adding some quick snippets to illustrate how this can be used. (Note that you could also "overload" the method to handle multiple types.)
"""Return the difference of another Transaction object, or another
class object that also has the `val` property."""
class Transaction(object):
def __init__(self, val):
self.val = val
def __sub__(self, other):
return self.val - other.val
buy = Transaction(10.00)
sell = Transaction(7.00)
print(buy - sell)
# 3.0
"""Return a Transaction object with `val` as the difference of this
Transaction.val property and another object with a `val` property."""
class Transaction(object):
def __init__(self, val):
self.val = val
def __sub__(self, other):
return Transaction(self.val - other.val)
buy = Transaction(20.00)
sell = Transaction(5.00)
result = buy - sell
print(result.val)
# 15
"""Return difference of this Transaction.val property and an integer."""
class Transaction(object):
def __init__(self, val):
self.val = val
def __sub__(self, other):
return self.val - other
buy = Transaction(8.00)
print(buy - 6.00)
# 2
docs have the answer. Basically there are functions that get called on an object when you add or multiple, etc. for instance __add__ is the normal add function.
I have a 3-dimensional point class whose hash function, according to the profiler, would be a good place to do some optimizing. Right now, I'm just passing a tuple of the coordinates to the built-in hash function:
def __hash__(self):
return hash((self.x, self.y, self.z))
How can I make this faster? I'm assuming constructing a tuple each time isn't good. The coordinates are real-valued.
Using a tuple instead of your own class will be much faster.
If you really want to write p.x instead of p[0] then you can make your class a subclass of tuple and have accessors. It will still be much faster than implementing your own tuple.
class Point3d(tuple):
#property
def x(self):
return self[0]
#property
def y(self):
return self[1]
#property
def z(self):
return self[2]
Try using a named tuple instead of your own class.