Using two theano functions together - python

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.

Related

How to find roots of an equation where a variable is an output from a function, having target variable as an argument itself?

I am trying to solve an equation for variable 'X' in python where some of the variables in the equation ('ABC, PQR') are output from a function 'calculations'. The problem is, in order to get an output from the function, I need to pass variable X as an argument itself. I am kind of stuck in a loop here. I tried two different approaches but didn't get any success. Is there a way I can solve the equation?
Any help/direction is really appreciated.
My first approach is to start with a small value and run a loop. I tried to use math.isclose() but receive 'math bound error' once the values go off the range and it runs into an infinite loop.
The second approach is to write the complete expression and use scipy.optimize fsolve() but I am unable to understand how to properly implement it.
# function
def calculations(X, a, b, c):
ABC = X*a*b + c
XYZ = X*b*c + a
PQR = X*a*c + b
return ABC, XYZ, PQR
# ABC, PQR is the output from a function which uses X as input
# solve for X
func = 2*ABC + sqrt(PQR*ABC) + X*100*0.5
# Approach 1
X = 0.001
step = 0.001
while True:
# function call
Var_ABC, Var_XYZ, Var_PQR = calculations(X, a, b, c)
func = 2*Var_ABC + math.sqrt(Var_PQR * Var_ABC) + X*100*0.5
if (math.isclose(func, 0.0, rel_tol=0.1) == True):
break
else:
X = X + step
# Approach 2
# Since I don't know the value of X, how can I get the output from the function and then solve it again?
func_output[0] = calculations(X, a, b, c) # ABC
func_output[2] = calculations(X, a, b, c) # PQR
func = 2* func_output[0] + math.sqrt (func_output[0] * func_output[2] ) + X*100*0.5
from scipy.optimize import fsolve
desired_output_X = fsolve(func, [0.01, 1])
This may help you getting started with fsolve:
# function of X
def func(X):
func_output = calculations(X, a, b, c)
func = 2* func_output[0] + math.sqrt (func_output[0] * func_output[2]) + X*100*0.5
return func
# extra arguments for calculations function, dummy values used: set them as desired
a,b,c = 1,2,6
# initiating X = 0.01 and solve for X
desired_output_X = fsolve(func, x0 = 0.01)

multiple values of a variable in same equation

A = [18.0,10.0]; B = [13.0,15.0]; C = [10.5,12.0];
these are the variables and think about function like
def hlf(A,B,C):
return A**(-1.0/2.0)-0.2*B-43+C
print "T:"
hlf(A,B,C)
Firstly, I want to use first values of the A B and C in the equation. After I want to use second values. How can I do this ?
map + list
Note map can take multiple iterable arguments:
res = map(hlf, A, B, C)
[-34.86429773960448, -33.68377223398316]
In Python 2.7, map returns a list. In Python 3.x map returns an iterator, so you can either iterate lazily or exhaust via list, i.e. list(map(hfl, A, B, C)).
Reference:
map(function, iterable, ...)
...If additional iterable arguments are passed, function must
take that many arguments and is applied to the items from all
iterables in parallel.
zip + list comprehension
You can use zip within a list comprehension. For clarity, you should avoid naming your arguments the same as your variables.
A = [18.0,10.0]; B = [13.0,15.0]; C = [10.5,12.0];
def hlf(x, y, z):
return x**(-1.0/2.0) - 0.2*y - 43 + z
res = [hlf(*vars) for vars in zip(A, B, C)]
[-34.86429773960448, -33.68377223398316]
Vectorize with Numpy. Best Performace
Normally its much better try to vectorize this kind of operations with numpy, because the best performance results. When you vectorize instead to use a loop, you are using all your cores, and its the fastest solution. You should vectorize the operation with numpy. Something like this:
import numpy as np
A = [18.0,10.0]; B = [13.0,15.0]; C = [10.5,12.0];
a = np.array(A)
b = np.array(B)
c = np.array(C)
And now your function with the new vectors like arguments:
def hlf(a_vector,b_vector,c_vector):
return a_vector**(-1.0/2.0)-0.2*b_vector-43+c_vector
And finally call your new function vectorized:
print (hlf(a_vector = a,b_vector = b,c_vector = c))
Output:
>>> array([-34.86429774, -33.68377223])
If you want to keep your function as is, you should call it N times with:
for i in range(N):
result = hlf(A[i], B[i], C[i])
print(result)
Another interesting method is to make a generator with your function:
A = [18.0,10.0]
B = [13.0,15.0]
C = [10.5,12.0];
def hlf(*args):
i=0
while i < len(args[0]):
yield args[0][i]**(-1.0/2.0) - 0.2*args[1][i] - 43 + args[2][i]
i += 1
results = hlf(A, B, C)
for r in results:
print(r)
Output:
-34.86429773960448
-33.68377223398316
Last one is rather edicational if you want to practice python generators.

SymPy: Evaluate given expression with given variables

I have a sympy expression involving two variables a, b. I would now like to evaluate this expression for specific values of a and b. Using a lambda like
import sympy
def get_expression(a, b):
# Complex function with a simple result. I have no control here.
return a*b + 2
a = sympy.Symbol('a')
b = sympy.Symbol('b')
z = get_expression(a, b)
f = lambda a, b: z
print(f(1, 1))
only gives
a*b + 2
though.
Any hints?
Turns out that lambdify is what I need:
f = sympy.lambdify([a, b], z)
print(f(1, 1))

SymPy: Swap two variables

In an expression like
import sympy
a = sympy.Symbol('a')
b = sympy.Symbol('b')
x = a + 2*b
I'd like to swap a and b to retrieve b + 2*a. I tried
y = x.subs([(a, b), (b, a)])
y = x.subs({a: b, b: a})
but neither works; the result is 3*a in both cases as b, for some reason, gets replaced first.
Any hints?
There is a simultaneous argument you can pass to the substitution, which will ensure that all substitutions happen simultaneously and don't interfere with one another as they are doing now.
y = x.subs({a:b, b:a}, simultaneous=True)
Outputs:
2*a + b
From the docs for subs:
If the keyword simultaneous is True, the subexpressions will not be evaluated until all the substitutions have been made.

Plotting with SymPy

With SymPy, I can plot a function with:
f, a = symbols('f a')
f = a + 10
plot(f)
However, if I define the function as:
f, a, b = symbols('f a b')
f = a + b
b = 10
plot(f)
Then I get an error stating:
ValueError: The same variable should be used in all univariate
expressions being plotted.
How can I plot f if I define f = a + b, considering that b is assigned a constant value before plotting the function?
The lines
f, a, b = symbols('f a b')
f = a + b
b = 10
don't change b in the expression. If you print f you'll see that it is still defined as a + b.
You are confusing Python variables with SymPy symbols. In the first line, the Python variable b points to a SymPy symbol named b (in fact, they need not be the same name; you could have also written x = Symbol('b') and y = a + x). In the second line, the variable f points to a SymPy expression containing the symbol b. In the third line, the variable b points to the integer 10. This doesn't not change any previous lines that used the variable b, since they have already been run. It's no different than if you ran
a = 1
b = 1
c = a + b
b = 2
You would expect the value of c at the end to be 2, not 3. Similarly, when b points to a Symbol, expressions you create with it use a Symbol, but if you change it to point to a number, it doesn't affect previous lines from when it was a Symbol.
The recommended way to deal with this in SymPy is to avoid assigning the same variable to a symbol and then later to a non-symbol (it's worth pointing out that your definition of f in the first line is completely useless, since you immediately redefine it in the second line). To replace a symbol in an expression, use subs:
a, b = symbols('a b')
f = a + b
f1 = f.subs(b, 10)
Note that subs does not change the original f. It returns a new expression.
This document may also help clear this confusion up.
If you didn't want to use substitution as in the other answer, you could make f an actual function of course
def f(a, b):
return a + b
a = symbols('a')
b = 10
plot(f(a,b))
You must substitute b into f:
plot(f.subs('b', b))

Categories

Resources