Assign result of calculation in sympy to function - python

I looked through several questions here on SO, but I could not find a solution for this problem:
I calculate a fourier transformation in sympy with fourier_transform(exp(-tau*abs(t)), t, w). I assigned tau, t and w with tau, t, w = symbols('tau t w'). How can I put the result of the FT into a function, e.g. something like
g(tau, w) = fourier_transform(exp(-tau*abs(t)), t, w)
? When I write it like that, I get the error can't assign to function call. When I do it like
g = fourier_transform(exp(-tau*abs(t)), t, w)
then I can not call it (as usually) with g(tau, w) or something similar. Is there a way to do that?
Edit: What I want to have as a final result is:
g(tau, w) = 2*tau/(tau**2 + 4*pi**2*w**2)
and I can call g simply with (f.eks) g(2, 3).
Edit II: Python call:
>>> fourier_transform(exp(-tau*abs(t)), t, w)
2*tau/(tau**2 + 4*pi**2*w**2)

Just if you want an inline solution, you can use lambda to approach so:
g = lambda tau,w: ourier_transform(exp(-tau*abs(t)), t, w)
Assuming the t is a local variable.
By the way, you can also use the standard function definition, but never try to define a function as a variable.

So you create your g method and use the fourier_transform inside the g method like this:
But you have to provide the t also
def g(tau, w):
return fourier_transform(exp(-tau*abs(t)), t, w)

Related

'NoneType' object is not iterable - where is an error?

My aim is to take a triple (A, B, C), compute three "neighbours", and then output the maximum of each of those neighbours to a list.
For example, the neighbours of (sqrt(6), 4*sqrt(3), 9*sqrt(2)) are
(sqrt(3)*sqrt(2), 3*sqrt(2), 4*sqrt(3))
(4*sqrt(3), 35*sqrt(3)*sqrt(2), 9*sqrt(2))
(sqrt(3)*sqrt(2), 9*sqrt(2), 14*sqrt(3))
so the values 14*sqrt(3), 36*sqrt(6), 4*sqrt(3) would be the output.
When I try this:
A = 1*sqrt(6)
B = 4*sqrt(3)
C = 9*sqrt(2)
def nbhs_1(triple):
X = triple[0]
Y = triple[1]
Z = triple[2]
print((X.canonicalize_radical(), (X * Y - Z).canonicalize_radical(), Y.canonicalize_radical()))
def nbhs_2(triple):
X = triple[0]
Y = triple[1]
Z = triple[2]
print((Y.canonicalize_radical(), (Y * Z - X).canonicalize_radical(), Z.canonicalize_radical()))
def nbhs_3(triple):
X = triple[0]
Y = triple[1]
Z = triple[2]
print((X.canonicalize_radical(), Z.canonicalize_radical(), (X * Z - Y).canonicalize_radical()))
result_1 = nbhs_1((A, B, C))
result_2 = nbhs_2((A, B, C))
result_3 = nbhs_3((A, B, C))
print(result_1)
print(result_2)
print(result_3)
l = [max(result_1), max(result_2), max(result_3)]
I get 'NoneType' object is not iterable.
The main problem is that you are not structuring the function properly:
It is recommended that you expose your arguments within the function call. Don't def nbhs_1(triple), do instead def nbhs_1(X, Y, Z). In this way you can actually have one single function that does what you want (easier to maintain)
Return your result. At the moment you are printing the outcome of the function call but you are not returning those results.
I'm also not sure the canonicalize_radical() call is also done properly. Python is object-oriented and by writing var.canonicalize_radical() you are inferring that var should itself know about this function (e.g. the function is part of var) but that sounds wrong. The correct call may be canonicalize_radical(var)
Basically, this should be closer to a correct solution:
A=1*sqrt(6)
B=4*sqrt(3)
C=9*sqrt(2)
def nbhs(X, Y, Z):
out1 = canonicalize_radical(X)
out2 = canonicalize_radical(X*Y-Z)
out3 = canonicalize_radical(Y)
return out1, out2, out3
l = [max(nbhs(A, B, C)), max(nbhs(B, A, C)), max(nbhs(C, B, A))]
The problem is that you are not calling the functions nbhs_1, nbhs_2, and nbhs_3 and also the functions aren't returning any values
from math import sqrt
A=1*sqrt(6)
B=4*sqrt(3)
C=9*sqrt(2)
triple = (A, B, C)
def nbhs_1(triple):
X=triple[0]
Y=triple[1]
Z=triple[2]
return (X.canonicalize_radical(),(X*Y-Z).canonicalize_radical(),Y.canonicalize_radical())
def nbhs_2(triple):
X=triple[0]
Y=triple[1]
Z=triple[2]
return (Y.canonicalize_radical(),(Y*Z-X).canonicalize_radical(),Z.canonicalize_radical())
def nbhs_3(triple):
X=triple[0]
Y=triple[1]
Z=triple[2]
return (X.canonicalize_radical(),Z.canonicalize_radical(),(X*Z-Y).canonicalize_radical())
l=[max(nbhs_1(triple)),max(nbhs_2(triple)),max(nbhs_3(triple))]

Evaluate Derivative of Function at a Point Python 2.7

I have the following function:
import sympy as sp
def inverted(q, m, a, nu):
return (-1)**(m+1)*(a/m)**m*sp.exp(m)*q**(-nu)*sp.diff(1/(sp.sqrt(a**2+q**2))*(sp.sqrt(a**2+q**2)-a)**(nu), a, m+1)
I want to define some lambda function such that
f100 = lambda a, q: inverted(q, 100, a, 0)
However, when I try to examine
q = sp.symbols('q')
f100(1000.0, q)
I get the following output:
ValueError:
Can't calculate 101st derivative wrt 10.
Obviously, what is happening is when I call f100(1000.0, q), the function refers back to inverted and the issue arises. I was hoping for a way around this.
Seems like you have to make a a variable first so diff works. It doesn't work if you fix a before (I think because you differentiate with respect to a). You can substitute a with 1000 afterwards.
import sympy as sp
def inverted(q, m, a, nu):
return (-1)**(m+1)*(a/m)**m*sp.exp(m)*q**(-nu)*sp.diff(1/(sp.sqrt(a**2+q**2))*(sp.sqrt(a**2+q**2)-a)**(nu), a, m+1)
f100 = lambda a, q: inverted(q, 100, a, 0)
q, a = sp.symbols('q, a')
print(f100(a, q).subs(a, 1000))

Using two theano functions together

If I had something like:
import theano.tensor as T
from theano import function
a = T.dscalar('a')
b = T.dscalar('b')
first_func = a * b
second_func = a - b
first = function([a, b], first_func)
second = function([a, b], second_func)
and I wanted to create a third function that was first_func(1,2) + second_func(3,4), is there a way to do this and create a function that is passed these two smaller functions as input?
I want to do something like:
third_func = first(a, b) + second(a,b)
third = function([a, b], third_func)
but this does not work. What is the correct way to break my functions into smaller functions?
I guess the only way to decompose function is in-terms of tensor variables, rather than function calls. This should work:
import theano.tensor as T
from theano import function
a = T.dscalar('a')
b = T.dscalar('b')
first_func = a * b
second_func = a - b
first = function([a, b], first_func)
second = function([a, b], second_func)
third_func = first_func + second_func
third = function([a, b], third_func)
third_func = first(a, b) + second(a,b) does not work because function call need real values whereas a and b are tensor/symbolic variables. Basically one should define mathematical operations with tensors and then use function to evaluate values of these tensors.

How to do function composition in Sympy?

I want to do something like h = f(g(x)) and be able to differentiate h, like h.diff(x). For just one function like h = cos(x) this is in fact possible and the documentation makes it clear.
But for function compositions it is not so clear. If you have done this, kindly show me an example or link me to the relevant document.
(If Sympy can't do this, do you know of any other packages that does this, even if it is non-python)
thank you.
It seems that function composition works as you would expect in sympy:
import sympy
h = sympy.cos('x')
g = sympy.sin(h)
g
Out[245]: sin(cos(x))
Or if you prefer
from sympy.abc import x,y
g = sympy.sin('y')
f = g.subs({'y':h})
Then you can just call diff to get your derivative.
g.diff()
Out[246]: -sin(x)*cos(cos(x))
It's named compose; although, I can't find it in the docs.
from sympy import Symbol, compose
x = Symbol('x')
f = x**2 + 2
g = x**2 + 1
compose(f,g)
Out: x**4 + 2*x**2 + 4

Dynamically build a lambda function in python

Supose that I want to generate a function to be later incorporated in a set of equations to be solved with scipy nsolve function. I want to create a function like this:
xi + xi+1 + xi+3 = 1
in which the number of variables will be dependent on the number of components. For example, if I have 2 components:
f = lambda x: x[0] + x[1] - 1
for 3:
f = lambda x: x[0] + x[1] + x[2] - 1
I specify the components as an array within the arguments of the function to be called:
def my_func(components):
for component in components:
.....
.....
return f
I can't just find a way of doing this. I've to be able to make it this way as this function and other functions need to be solved together with nsolve:
x0 = scipy.optimize.fsolve(f, [0, 0, 0, 0 ....])
Any help would be appreciated
Thanks!
Since I'm not sure which is the best way of doing this I will fully explain what I'm trying to do:
-I'm trying to generate this two functions to be later nsolved:
So I want to create a function teste([list of components]) that can return me this two equations (Psat(T) is a function I can call depending on the component and P is a constant(value = 760)).
Example:
teste(['Benzene','Toluene'])
would return:
xBenzene + xToluene = 1
xBenzenePsat('Benzene') + xToluenePsat('Toluene') = 760
in the case of calling:
teste(['Benzene','Toluene','Cumene'])
it would return:
xBenzene + xToluene + xCumene = 1
xBenzenePsat('Benzene') + xToluenePsat('Toluene') + xCumene*Psat('Cumene') = 760
All these x values are not something I can calculate and turn into a list I can sum. They are variables that are created as a function ofthe number of components I have in the system...
Hope this helps to find the best way of doing this
A direct translation would be:
f = lambda *x: sum(x) - 1
But not sure if that's really what you want.
You can dynamically build a lambda with a string then parse it with the eval function like this:
a = [1, 2, 3]
s = "lambda x: "
s += " + ".join(["x[" + str(i) + "]" for i in xrange(0, 3)]) # Specify any range
s += " - 1"
print s
f = eval(s)
print f(a)
I would take advantage of numpy and do something like:
def teste(molecules):
P = np.array([Psat(molecule) for molecule in molecules])
f1 = lambda x: np.sum(x) - 1
f2 = lambda x: np.dot(x, P) - 760
return f1, f2
Actually what you are trying to solve is a possibly underdetermined system of linear equations, of the form A.x = b. You can construct A and b as follows:
A = np.vstack((np.ones((len(molecules),)),
[Psat(molecule) for molecule in molecules]))
b = np.array([1, 760])
And you could then create a single lambda function returning a 2 element vector as:
return lambda x: np.dot(A, x) - b
But I really donĀ“t think that is the best approach to solving your equations: either you have a single solution you can get with np.linalg.solve(A, b), or you have a linear system with infinitely many solutions, in which case what you want to find is a base of the solution space, not a single point in that space, which is what you will get from a numerical solver that takes a function as input.
If you really want to define a function by building it up iteratively, you can. I can't think of any situation where this would be the best answer, or even a reasonable one, but it's what you asked for, so:
def my_func(components):
f = lambda x: -1
for component in components:
def wrap(f):
return lambda x: component * x[0] + f(x[1:])
f = wrap(f)
return f
Now:
>>> f = my_func([1, 2, 3])
>>> f([4,5,6])
44
Of course this will be no fun to debug. For example, look at the traceback from calling f([4,5]).
def make_constraint_function(components):
def constraint(vector):
return sum(vector[component] for component in components) - 1
return constraint
You could do it with a lambda, but a named function may be more readable. deffed functions can do anything lambdas can and more. Make sure to give the function a good docstring, and use variable and function names appropriate for your program.

Categories

Resources