Issue with jax.lax.scan - python

I am supposed to use Jax.lax.scan instead of a for loop with 100 iterations at line 22. I am supposed to update S and append it to S_list. I am unsure how to fix the jax.lax.scan. The error that keeps popping up is missing the required XS. When I put a value for XS it says that my length argument doesn't line up with the axis sizes. Here is my code. Can you help me?

You're not calling scan with the correct signature. You can find more information on the call signature in the jax.lax.scan docs. It makes clear, for example, that your step function must accept two arguments and return two arguments.
From looking at your code, it looks like you're intending to do something like this:
#jax.jit
def simulate():
key = jax.random.PRNGKey(0)
def step(S, _):
dZ = jax.random.normal(key, shape=(S.size,)) * jnp.sqrt(dt)
dS = r * S * dt + σ * S * dZ
return S + dS, S
S0 = jnp.ones(20000)
_, S_array = jax.lax.scan(step, S0, xs=None, length=m)
return S_array
In particular, from the docs you can see that the S_list.append(...) and S_array = jnp.stack(S_list) are effectively part of the scan function itself, so you don't have to do that yourself after calling it.
Hope that helps!

Related

Finding root of a function with two outputs specified in return statement

I am currently writing a code in Python where the objective is to find the root of the output of a function with respect to input variable x. The code looks like this:
def Compound_Correlation_Function(x):
# Here comes a long part of the code...
Equity_Solve = Tranches.loc[0, 'Par_Spread_bps'] - Market_Data.iloc[0,0]
Mezzanine_Solve = Tranches.loc[1, 'Par_Spread_bps'] - Market_Data.iloc[1,0]
return Equity_Solve, Mezzanine_Solve
Correlation_Value = optimize.root(Compound_Correlation_Function, x0 = 0.3)
As can be seen in the code block above, there are two outputs specified:
Equity_Solve
Mezzanine_Solve
I now want to find the root for both outputs separately. If I comment out the Mezzanine_Solve part in the return statement, then the the optimize procedure gives me the solution I want. Obviously, I want to automate my code as much as possible. Is it possible to specify the output for which I want to find the root in the optimize statement?
I tried the following, without success:
Correlation_Value = optimize.root(Compound_Correlation_Function[0], x0 = 0.3)
Correlation_Value = optimize.root(Compound_Correlation_Function(x)[0], x0 = 0.3)
Correlation_Value = optimize.root(Compound_Correlation_Function()[], x0 = 0.3)
Any help is appreciated. Thank you in advance!
I think the problem is that your function returns a tuple of numbers, but root is expecting a single number.
Assuming you want to solve each equation separately, then you could include an argument in Compound_Correlation_Function to switch between the functions:
def Compound_Correlation_Function(x, return_equity=True):
# Here comes a long part of the code...
if return_equity:
Equity_Solve = Tranches.loc[0, 'Par_Spread_bps'] - Market_Data.iloc[0,0]
return Equity_Solve
else:
Mezzanine_Solve = Tranches.loc[1, 'Par_Spread_bps'] - Market_Data.iloc[1,0]
return Mezzanine_Solve
Then pass the return_equity argument in as an extra argument via args, i.e. call
root(Compound_Correlation_Function, x0=0.3, args=(True,))
to solve Equity_Solve, and set args=(False,) to solve Mezzanine_Solve.
You could also define a function wrapper that calls Compound_Correlation_Function and returns only one of the values.
surely you're overthinking it. Just define two new functions:
def equity_solve(x):
return Compound_Correlation_Function(x)[0]
def mezzanine_solve(x):
return Compound_Correlation_Function(x)[1]

How can I use a calculated value of a function in another function in another Python file?

I have wrote the following code in derivation.py:
def Interpolation(ableitungWinkel,x_values):
z = medfilt(derivation,3)
diff = abs(derivation-z)
new_smootheddata = np.where(diff>3,z,derivation)
x=np.arange(0,len(x_values[:-2]))
f = interp1d(x,new_smootheddata,kind="linear")
xnew = np.arange(0, len(x_values[:-3]),0.01)
ynew = f(xnew)
s=plt.plot(x, z,"o",xnew, ynew, "-")
return s
In my project there is also integration.py. In this Python file I need the values which z calculates in the function def interpolation for this calculation:
def horizontalAcceleration(strideData):
resultsHorizontal = list()
for i in range (len(strideData)):
yAngle = z
xAcceleration = strideData.to_numpy()[i, 4]
yAcceleration = strideData.to_numpy()[i, 5]
a = ((m.cos(m.radians(yAngle)))*yAcceleration)-((m.sin(m.radians(yAngle)))*xAcceleration)
resultsHorizontal.append(a)
resultsHorizontal.insert(0, 0)
return resultsHorizontal
As you can see I have already added z to the function def horizontalAcceleration at the place where it should go.
To use z there, I tried the following: from derivation import z
But that doesn't work. Because then I get the error: ImportError: cannot import name 'z' from 'derivation'
Have anybody an idea how I can solve this problem? Thanks for helping me.
I think that your misunderstanding is because you think a function is like a script that has been run and modified a.global state. That's not what a function is. A function is a series of actions performed on its inputs (ignoring closures for a minute) which returns some results. You can call it many times, but without calling it, it never executes. Once it stops executing all its variables go out of scope.
You can import and call a function though. So you can change the return type of Interpolation to return everything you need somewhere else. E.g.
def Interpolation(...):
...
return {'z': z, 's': s}
Then somewhere you import that function, call it, get back all the data you need, then pass that to your other function.
import Interpolation from derivation
# get z and s in a dict result
result = Interpolation(...)
# pass s as well as the other argument to your other function
horizontalAcceleration(strideData, result['s'])

multiple functions as arguments in python

I have the following problem: I have two sets of data (set T and set F). And the following functions:
x(T) = arctan(T-c0), A(x(T)) = arctan(x(T) -c1),
B(x(T)) = arctan(x(T) -c2)
and Y(x(t),F) = ((A(x(t)) - B(x(t)))/2 - A(x(t))arctan(F-c3) + B(x(t))arctan(F-c4))
# where c0,c1,c2,c3,c4 are constants
Now I want to create a surface plot of Y. And for that I would like to implement Y as a python (numpy) function what turns out to be quite complicated, because Y takes other functions as input.
Another idea of mine was to evaluate x, B and A on the data separately and store the results in numpy arrays. With those I also could get the output of the function Y , but I don't know which way is better in order to plot the data and I really would like to know how to write Y as a python function.
Thank you very much for your help
It is absolutely possible to use functions as input parameters to other functions. A use case could look like:
def plus_one(standard_input_parameter_like_int):
return standard_input_parameter_like_int + 1
def apply_function(function_as_input, standard_input_parameter):
return function_as_input(standard_input_parameter)
if(__name__ == '__main__'):
print(apply_function(plus_one, 1))
I hope that helps to solve your specific problem.
[...] somethin like def s(x,y,z,*args,*args2): will yield an
error.
This is perfectly normal as (at least as far as I know) there is only one variable length non-keyword argument list allowed per function (that has to be exactly labeled as *args). So if you remove the asterisks (*) you should actually be able to run s properly.
Regarding your initial question you could do something like:
c = [0.2,-0.2,0,0,0,0]
def x(T):
return np.arctan(T-c[0])
def A(xfunc,T):
return np.arctan(xfunc(T) - c[1])
def B(xfunc,T):
return np.arctan(xfunc(T) - c[2])
def Y(xfunc,Afunc,Bfunc,t,f):
return (Afunc(xfunc,t) - Bfunc(xfunc,t))/2.0 - Afunc(xfunc,t) * np.arctan(f - c[3]) + Bfunc(xfunc,t)*np.arctan(f-c[4])
_tSet = np.linspace(-1,1,20)
_fSet = np.arange(-1,1,20)
print Y(x,A,B,_tSet,_fSet)
As you can see (and probably already tested by yourself judging from your comment) you can use functions as arguments. And as long as you don't use any 'if' conditions or other non-vectorized functions in your 'sub'-functions the top-level function should already be vectorized.

TypeError: 'numpy.ndarray' object is not callable on Euler's method LTE calculation

Before anything, sorry any sppeling, english issues, english is not my mother tongue.
I'm doing an assgment on Euler's Method to calculate ODEs, and in the calculatrion of the LTE(Local truncation error) I keep receiving this error:
TypeError: 'numpy.ndarray' object is not callable
I took a look at previous questions with the same subject, but I didn't find exactly what I was looking for. Below the code for the euler's method and the error calculation.
def euler(f,y0,a,b,h):
t,y = a,y0
vet_s = np.array([])
vet_err = np.array([])
while t <= b:
#print t , y
vet_s = np.append(vet_s, y)
t += h
y += h * f(t,y)
vet_err = np.append(vet_err, erro(yn, y, t)) # The problem is here
return vet_s, vet_err
def y(t, y):
return lbd*y
def yn(t):
return np.exp(-1*t)
def erro(yn, un, t):
erro_local = abs(yn(t) - un)
return erro_local
When I call the error calculation inside the vet_err assigment function I receive the error displayed above.
I think that it's a simple fix, but i can't find it myself.
The main call for the Euler's method is this:
h = 30./60.
lbd = -1.0
t = np.arange(0, 30, h)
sol = erro = np.array([])
sol, erro = euler(y, 1.0, 0.0, 30.0, h)
Is there any syntax, code issue? Also any pointer in order to improve the code would be of great help. Thanks.
Some issues I see in your code -
I am assumming you have defined the function named erro first and then afterwards you are also doing -
erro = np.array([])
This causes the name erro to point to a np.array , which is what is causing the issue you are having, you should use a different name here , maybe something like erro1 (or some other good meaningful name).
Then in the function - euler(f,y0,a,b,h) - you are defining variable with name - y . But there is also a y function outside, (This does not directly cause issues, since you passed the reference to function y as the first argument to this function) .
But I would advice against doing this (As you may encounter issues later on). Always use different meaningful names, I do not think there is a shortage of words/letters in English for use :) .
Also there is no need to do -
sol = erro = np.array([])
Since you reassign it to return value of euler() functio in next line, you do not need to even define them before that (unless you want to use them , which does not seem like the case).

Python -- nondimensionalize

I'm writing a python module to allow me to make unit-based calculations, and I'm trying to implement unit-sensitive integration of functions. My idea is basically to write a wrapper for scipy.integrate -- take the function and arguments given, including the limits of integration, nondimensionalize them all, pass to scipy.integrate.quad or some such thing, get the answer, and then multiply by the correct units at the end.
To accomplish this, I'm trying to figure out how to nondimensionalize an arbitrary function. I've implemented units so that if you divide two quantities with the same units, it returns an ordinary number, so my first thought was to just do this:
def nonDimensionalize(func, *args):
val = func(*args)
dimensions = val / val.value
return lambda args : (func(args) / dimensions)
This works like a charm to nondimensionalize the function's output, but I'm having a harder time with the input. What I really need is to return a function that takes in ordinary numbers, multiplies them by the correct SI dimensions (which I can figure out how to do), gets the output, divides it by the correct SI dimensions, and returns that value as an ordinary number. Then I can pass said function to scipy.integrate (or scipy.fslove, etc.). I tried the following:
def nonDimensionalize(func, *args):
argDims = []
for arg in args:
aDim = arg / arg.value
argDims.append(aDim)
nDargs = []
index = 0
for arg in args:
nDargs.append(arg / argDims[index])
index += 1
val = func(*args)
dimensions = val / val.value
return lambda args : (func(args) / dimensions)
but it doesn't work; it has exactly the same effect as my four-line function above. I'm not sure how to proceed at this point. Help?
What I really need is to return a function that takes in ordinary numbers, multiplies them by the correct SI dimensions (which I can figure out how to do), gets the output, divides it by the correct SI dimensions, and returns that value as an ordinary number.
I'm not sure I understand exactly how you dimensionalize/non-dimensionalize values, so just modify the corresponding functions as necessary, but you could do it like this:
def dimensionalizeValue(nonDimValue, dimensions):
return nonDimValue * dimensions
def nonDimensionalizeValue(dimValue):
dimensions = dimValue / dimValue.value
return dimValue / dimensions
def nonDimensionalizeFunction(function):
def wrapper(*nonDimArgs):
# Figure out the correct dimensions.
dimensions = None
# Transform/dimensionalize the arguments.
dimArgs = [dimensionalizeValue(arg, dimensions) for arg in nonDimArgs]
# Get output using dimensionalized arguments.
dimVal = function(*dimArgs)
# Non-dimensionalize the output.
nonDimVal = nonDimensionalizeValue(dimVal)
return nonDimVal
return wrapper

Categories

Resources