Returning the integral of a vector - python

I am trying to create a function, which returns a vector and then integrating it element by element. This is what I have so far
def int1(b):
j = 1
for q in range(0,len(alpha)):
j = j + alpha[q]*(b**q)
p = np.exp(-j);
inu = np.zeros(len(alpha))
for q in range(0,len(alpha)):
inu[q] = np.exp(-j)*(b**q)
return inu
This works if I type something like
print int1(0.1)[2]
However
print sp.integrate.quad(int1(b)[2], 1e-16, 1, epsrel=1e-20)[0]
does not work, or any reasonable variant I can think of. How can I get it to work?
either i get TypeError: 'function' object has no attribute 'getitem' if i leave out the b or ValueError: invalid callable given if I have it in.

The first argument of quad must be a function, something that call be called. Something that you can put (0.1) after and it will make sense. Does int1(b)[2](0.1) make sense? To me neither.
The form quad(int1, 1e-16, 1, epsrel=1e-20)[0] is syntactically correct but quad only allows scalar outputs of the function, so it won't work with your int1. Instead, you need to make a new function that uses int1 but then returns only one of its components. Instead of having another def somewhere, it's better to make such a function right where it is needed, using lambda syntax:
quad(lambda b: int1(b)[2], 1e-16, 1, epsrel=1e-20)[0]
This says: take b, put it in int1, keep the index-2 entry of the returned array.

Related

Getting error saying the truth value of an array with more than one element is ambiguous

...and a suggestion to Use a.any() or a.all().
I am new to python and i am trying to implement a sabr model. I have defined a function with the following parameters:
def haganimpliedvol(a,f,k,B,v,t,p):
if k != f:
z = v/a*math.pow(f*k,(1-B)/2)*math.log(f/k)
xz = math.log((math.sqrt(1-2*p*z+math.pow(z,2))+z-p)/(1-p))
sigma = a/math.pow(f*k,(1-B)/2)*(1 + math.pow(1-B,2)/24* math.pow(math.log(f/k),2)+\
math.pow(1-B,4)/1920* math.pow(math.log(f/k),4))*\
xz*\
(1+(math.pow(1-B,2)/24*math.pow(a,2)/math.pow(f/k,1-B)+1/4*(p*B*v*a)/math.pow(f/k,(1-B)/2)+\
(2-3*math.pow(p,2))/24*math.pow(v,2)))*t
else:
sigma = a/math.pow(f,1-B)*\
(1+(math.pow(1-B,2)/24*math.pow(a,2)/math.pow(f,(2-2*B))+\
1/4*(p*B*a*v)/math.pow(f,1-B)+(2-3*math.pow(p,2))/24*math.pow(v,2)))*t
return(sigma)
Now I define another function to and call the haganimpliedvol() function
params = [0.4,0.6,0.1,-0.4]
def objective(params):
global k,sigma_iv,t,f
a = params[0]
B = params[1]
v = params[2]
p = params[1]
for (i,j,k) in zip(k,t,f):
calc_vols = np.array([haganimpliedvol(a,f,k,B,v,t,p)])
return(calc_vols)
As can be seen, a few parameters in the functions are list. I want to get an array as an output. However, I keep getting the message in the subject line.
Pay attention to the variables in this call:
for (i,j,k) in zip(k,t,f):
calc_vols = np.array([haganimpliedvol(a,f,k,B,v,t,p)])
for the zip to work, k,t, f have to be lists or arrays of matching size;
Done use k for an iteration variable; it is already used in the zip. I think you are just being careless here; or confused.
And the arguments to the hagen... function. Are the f, k, t supposed to be variables used in the zip? It would make more sense to use the iteration variables (i,j,?). Again, this just looks like you are careless, or don't care what happens.
As for the ambiguity error, that most likely arises in the
if k != f:
If either k or f is an array (or both) the k!=f will be a boolean array. That can't be used in if, which requires a simple True or False value. It does not iterate on the conditions. It is a basic Python if - a switch.
This ambiguity error comes up frequently, in various contexts, but all with the same basic issue - using an array in a context that requires a scalar T/F. A simple web search should provide lots of examples.
#hpaulj thank you for leading me on the right path. I vectorized my function and made some edits and now it is working fine.
haganimpliedvol = np.vectorize(haganimpliedvol,excluded = ['a','B','v','p'])
params = [0.2,0.7,0.01,-0.4]
def objective(params):
global k,sigma_iv,t,f
a = params[0]
B = params[1]
v = params[2]
p = params[1]
calc_vols = haganimpliedvol(a,f,k,B,v,t,p)
return(calc_vols)
Are you sure you want to pass arrays into the haganimpliedvol() function?
The general convention is to write functions which take a single input type.
Maybe call it one per item in the array?
Or write the function in a way that, if it sees the input is a list it iterates and if it sees the inputs arent lists then it just calculates it one time.
See this thread for ideas
How to make a function that can handle single inputs or lists of inputs

How can I add a f(x) as an argument on Python function?

I'm trying to find the maximum of any function f(x) in a certain range and in which x this happens. The arguments of the python function would be (f(x),[a,b]). f(x) being any function and [a,b] the range we will be studying.
For now I've tried a few things but none of them worked. The one I liked the most was a failure because of trying to convert a string onto a float.
def maxf(function,interval):
maxresult = 0
for x in range(interval[0]-1,interval[1]+1):
result=float(function.replace("x",str(x)))
if result >= maxresult:
maxresult = result
maxresultx = x
return maxresult,maxresultx
print(maxf("x**2",[1,3]))
This one returns:
Traceback (most recent call last):
File "main.py", line 10, in <module>
print(maxf("x**2",[1,3]))
File "main.py", line 4, in maxf
result=float(function.replace("x",str(x)))
ValueError: could not convert string to float: '0**2'
I don't know if there is an easier way to do it or how to correct the code so that I can convert that string.
Your problem is that float() accepts a string that already represents a float (eg float("1.23"), not an expression that will result in one (eg float("2**3")). So, you must first evaluate the string.
float(eval("3**2"))
eval() will run any code contained in the string, so don't use it on code you don't trust.
Use this:
def maxf(function,interval):
maxresult = 0
for x in range(interval[0]-1,interval[1]+1):
result=float(function(x))
if result >= maxresult:
maxresult = result
maxresultx = x
return maxresult,maxresultx
print(maxf(lambda x: x**2,[1,3]))
lambda defines a function (an anonymous one) that is passed as parameter, thus maxf can call it as needed.
Python is (also) a functional language, which means that you can use functions as you use ints or floats, etc. A function is just a bunch of callable code, you can associate an identifier to a function or not (just like int values referred by identifiers or as constant in code).
-----EDIT----- suggested by #bacjist
If you don't want to use lambda, then you may define the function as usual:
def f(x):
return x**2
and then call:
print(maxf(f,[1,3]))
The problem is your string is not actually being evaluated. It is just being converted to float so as the error suggests what you are doing is converting "0**2" to float which is not possible what you can do is make use of eval function to evaluate any given string and then compare the result.
You just need to make a small change like this:
result=eval(function.replace("x",str(x)))
This yet not the best way to do this you should use generator there:
def maxf(function,interval):
maxresult = 0
for x in range(interval[0]-1,interval[1]+1):
yield eval(function.replace("x",str(x))), x
print(max(maxf("x**2", [1, 3])))
A more pythonic approach would be using lambda with max function as a key
a_list = [1,3]
max_item = max(a_list, key=lambda x: eval("x**2"))
print(eval("x**2".replace("x", str(max_item))), max_item)

Problem with scipy.optimize.newton(): "Add" object is not callable

I'm writing a function that takes 2 lists and creates a polynomial function to later be solved by optimization.
I'm trying to create a string that looks like a function, convert it into a function by using sympy.sympify() and then pass it into optimize.newton().
However it keeps throwing a TypeError "Add" object is not callable while I already think that sympify has correctly returned a function.
I think I'm missing something very basic, maybe there is a function to turn my variable function0 into a function type for scipy to interpret correctly maybe?
def poly_build(coefficient_list, power_list):
'''
coefficient_list & power_list must be iterable objects of the same length, preferably a list
'''
if len (coefficient_list) != len(power_list):
return False
function = ""
for n in range(0, len(coefficient_list)):
if n != len(coefficient_list) - 1:
function += f'{coefficient_list[n]}*x**{power_list[n]} +'
else:
function += f'{coefficient_list[n]}*x**{power_list[n]}'
function0 = (sympy.sympify(function))
function1 = sympy.diff(function0)
function2 = sympy.diff(function1)
return scipy.optimize.newton(function0, 1.5)
A sympy function isn't a Python function as scipy.optimize.newton expects it. To convert:
pyfunction0 = sympy.lambdify(x, function0)

How do we check if a function returns mutiple values in Python?

This question was already asked, but I wish to ask something subtly different.
How do we determine if a python function returns multiple values, without calling the function? Is there some way to find out at something more like compile-time instead of at run-time? (I realize that python is an interpreted language)
The following is out of the question:
r = demo_function(data) # takes more than 5 minutes to run
if (not len(r) == 2) or (not isinstance(r, tuple)):
raise ValueError("I was supposed to return EXACTLY two things")
So is:
try:
i, j = demo_function(data)
# I throw TypeError: 'int' object is not iterable
except ValueError:
raise ValueError("Hey! I was expecting two values.")
except TypeError:
s1 = "Hey! I was expecting two values."
s2 = "Also, TypeError was thrown, not ValueError"
raise ValueError(s1 + s2)
The following sort of works, but is extremely inelegant:
r = demo_function(extremely_pruned_down_toy_data) # runs fast
if len(r) != 2:
raise ValueError("There are supposed to be two outputs")
# Now we run it for real
r = demo_function(data) # takes more than 5 minutes to run
There are tools already in python which do similar things. For example, we can find out if a class object has a certain attribute:
prop_str = 'property'
if not hasattr(obj, prop_str):
raise ValueError("There is no attribute named" + prop_str + " NOOOOoooo! ")
Also, we can find out how many INPUTS a function has:
from inspect import signature
sig = signature(demo_function)
p = sig.parameters
if len(p)) != 2:
raise ValueError("The function is supposed to have 2 inputs, but it has" + str(p))
I basically want the following:
p = nargout(demo_function)
if p != 2:
raise ValueError("The function is supposed to have 2 outputs, but it has" + str(p))
Asking what a function returns is one of the most basic things questions one can ask about a function. It feels really weird that I'm having trouble finding out.
EDIT:
juanpa.arrivillaga wrote,
[...] fundamentally, this points to a deeper, underlying design flaw: why do you have functions that can return different length containers when you are expecting a specific length?
Well, let me explain. I have something like this:
def process_data(data_processor, data):
x, y = data_processor(data)
return x, y
A precondition of the process_data function is that the input data_processor MUST return two items. As such, I want to write some error checking code to enforce the precondition.
def process_data(data_processor, data):
# make sure data_processor returns exactly two things!
verify_data_processor(data_processor)
x, y = data_processor(data)
return x, y
However, it looks like that's not easily doable.
A function really only has a single return value. It can return a container, such as a tuple, of whatever length. But there is no inherent way for a Python function to know the length of such a value, Python is much too dynamic. Indeed, in general, the interpreter does not know the nature of the return value of a function. But even if we stick to just considering functions that return containers, consider the following function:
def howmany(n):
return n*('foo',)
Well, what should nargout(howmany) return?
And python does not special case something like return x, y, nor should it, because then what should be the behavior when the length of the returned container is indeterminate, such as return n*(1,)? No, it is up to the caller to deal with the case of a function returning a container, in one of the ways you've already illustrated.
And fundamentally, this points to a deeper, underlying design flaw: why do you have functions that can return different length containers when you are expecting a specific length?

The Matlab equivalent of Python's "None"

Is there a keyword in Matlab that is roughly equivalent to None in python?
I am trying to use it to mark an optional argument to a function. I am translating the following Python code
def f(x,y=None):
if y == None:
return g(x)
else:
return h(x,y)
into Matlab
function rtrn = f(x,y)
if y == []:
rtrn = g(x);
else
rtrn = h(x,y);
end;
end
As you can see currently I am using [] as None. Is there a better way to do this?
in your specific case. you may use nargin to determine how many input arguments here provided when calling the function.
from the MATLAB documentation:
The nargin and nargout functions
enable you to determine how many input
and output arguments a function is
called with. You can then use
conditional statements to perform
different tasks depending on the
number of arguments. For example,
function c = testarg1(a, b)
if (nargin == 1)
c = a .^ 2;
elseif (nargin == 2)
c = a + b;
end
Given a single input argument, this
function squares the input value.
Given two inputs, it adds them
together.
NaN while not equivalent, often serves the similar purpose.
nargin is definitely the easiest way of doing it. Also it is usually good practice to validate the number of input argument using nargchk:
function e = testFunc(a,b,c,d)
error( nargchk(2, 4, nargin, 'struct') );
% set default values
if nargin<4, d = 0; end
if nargin<3, c = 0; end
% ..
c = a*b + c*d;
end
... which acts as a way to ensure the correct number of arguments is passed. In this case, a minimum of two arguments are required, with a maximum of four.
If nargchk detects no error, execution resumes normally, otherwise an error is generated. For example, calling testFunc(1) generates:
Not enough input arguments.
UPDATE: A new function was introduced in R2011b narginchk, which replaces the use of the deprecated nargchk+error seen above:
narginchk(2,4);
You can use functions like: exist and isempty to check whether a variable exists and whether it is empty respectively:
if ~exist('c','var') || isempty(c)
c = 10;
end
which allows you to call your function such as: testFunc(1,2,[],4) telling it to use the default value for c but still giving a value for d
You could also use varargin to accept a variable number of arguments.
Finally a powerful way to parse and validate named inputs is to use inputParser
To see examples and other alternatives of passing arguments and setting default values, check out this post and its comments as well.
The equivalent to Python None in MATLAB is string(missing)
To test, type the following in your command window : py.type( string(missing) )
It returns <class 'NoneType'>
MATLAB to python data types documentation here
If you want to pass None into a Python function that you are calling from MATLAB, then you would pass in string(missing). This argument would show up as None in the Python function, for example, if you are detecting for None such as if arg1 == None.

Categories

Resources