python scipy.integrate inverse ppf - python

Hello I would like what is the x value that would give me an specific numeric integral.
So far I am using scipy.integrate and works ok, but given a integral value is there a way to know what is the x that gave that result?
let say I have a function f(x) = |2-x| 1<=x<=3
I would like to know what is the x value that give me 0.25 (the first quartile).
What in scipy.stats for normal distribution is norm.ppf(), in this particular case I am using it for PDF (probability density function) but it can be any integral.
Thanks and regards

I use binary search to find answer in logarithmic time (very fast). You can also run code below online here.
import math, scipy.integrate, scipy.optimize
def f(x):
return math.sin(x)
a, b = 0, 10
integral_value = 0.5
res_x = scipy.optimize.bisect(
lambda x: scipy.integrate.quad(f, a, x)[0] - integral_value,
a, b
)
print(
'found point x', res_x, ', integral value at this point',
scipy.integrate.quad(f, a, res_x)[0]
)

Related

Python Scipy dblquad function giving wrong answer on short range

I want to integrate the following double integral:
I want to use the dblquad method from the scipy.integrate package, which allows you to do double integrals with limits of the inner integral as a function of the outer integral variable:
import scipy.integrate as spi
import numpy as np
x_limit = 0
y_limit = lambda x: np.arccos(np.cos(x))
integrand = lambda x, y: np.exp(-(2+np.cos(x)-np.cos(y)))
low_limit_y = 0 # inner integral
up_limit_y = y_limit
low_limit_x = x_limit # outer integral
up_limit_x = 2*np.pi-x_limit
integral = spi.dblquad(integrand, low_limit_x, up_limit_x, low_limit_y, up_limit_y)
print(integral)
Output:
(0.6934912861906996, 2.1067956428653226e-12)
The code runs, but does not give me the right answer. Using Wolfram Alpha I get the right answer: 3.58857
Wolfram Alpha method
The only thing I've noticed is that the values from the two methods agree when the signs on the cosines are switched from + to - and vice versa:
Wolfram Alpha method with signs on the cosines swapped
However, I have no plausible reason for why this should be the case. Does anyone have any clue what is going on here? I can separate the function out into the inner integral looping over all values of x and then summing the results which gives the right answer, but that is really quite slow.
Take another look at the docstring of dblquad; it says
Return the double (definite) integral of ``func(y, x)`` from ``x = a..b``
and ``y = gfun(x)..hfun(x)``.
Note the order of arguments of func(y, x): y first, then x.
If you change your definition of integrand to
integrand = lambda y, x: np.exp(-(2+np.cos(x)-np.cos(y)))
you get the expected answer. That is also (in effect) what you did when you changed the signs of the cos terms in the integrand.
(You're not the first one to get tripped up by the expected order of the arguments to func.)

Maximum of a Function using scipy.optimize

Function with an x-axis of "k value" (k is a three momentum difference) and an y-axis of cross-section. And need to find the maximum y-value of function (i.e. the maximum cross section value of the function) using scipy.optimize.minimize. Equation is a function of kappa (k and kappa are related) where values of a,b,c,d & e are constants. Drawing the graph on Desmos I know the answer I am looking for which is 245.
But issue lies in the fact that code I have written gives an answer much different than answer I am looking for. Code is written below and equation is at the bottom.
from scipy.optimize import minimize
def two_pion_deuteron(k_value):
a, b, c, d, e = 2.855e6, 1.311e1, 2.961e3 , 5.572e0, 1.416e6
Cross_section = (a*(k_value)**b)/((c-np.exp(d*k_value)**2) + e)
return Cross_section
Max_cross_section = minimize(lambda x: -two_pion_deuteron(x), 0, method = 'Nelder-Mead')
print(-Max_cross_section.fun)
Output is 9.49205479500129e+16 which is very far away from real answer of 245.
Change this line to:
Max_cross_section = minimize(two_pion_deuteron, 0, method = 'Nelder-Mead')
Then you will need to find your correct initial guess (x0).
Source
What makes you think that this function has a maximum? It clearly has a singularity at np.exp(d*k_value)**2 == c+e:
x = np.linspace(0, 3, 1000)
plt.plot(x, two_pion_deuteron(x))

How to calculate complex integral with parameter in Python? (CTFT)

I need to calculate CTFT (Continuous Time Fourier Transform) in Python. In other words: I need to calculate an integral with complex number and parameter.
I have function:
def x(t):
return (np.exp(-2*(t**2)+1))
and then I have to calculate integral from:
w is a parameter here.
where my x(t) is like I wrote before:
Do you have any advices how to calculate that?
I tried something like that:
from sympy.abc import x
w=Symbol('w')
f = exp(-(2*x**2-1-(1j)*w*x))
integrate(f, (x, -np.inf, np.inf))
but the result is not good:
thanks for any advices

Calculating expectation of functions across normal distribution

I want to compute the expectation of certain functions across a normal distribution.
An example:
mu = 100
k = 100
sigma = 10
val, err = quad(lambda x: norm.pdf((x - mu) / sigma) * x if x > k else 0, -math.inf, math.inf)
print(val)
This prints 4.878683842492743e-288 which is clearly not the correct answer.
I assume this is happening because SciPy is unable to integrate the Gaussian. How can I solve this? Ideally, I'd want a method that'd allows one to integrate all sorts of functions across Gaussian and is not specific to the example I have put in.
Thanks!
I think this is a problem with the quadrature (sometimes it doesn't really adapt), and doesn't like the if statement.
So I would suggest something like this (integrate from k to infinity):
def f(x):
return 1/sigma*norm.pdf((x - mu) / sigma)*x
val, err = quad(f, k, math.inf)
Notice, as implied by Jimmy, the correct form of the Gaussian needs 1/sigma.
Another way to do this integral would be to force quad to be careful at some points. My favorite way is to do something like
import numpy as np
from scipy.integrate import quad
#this is the Gaussian. Note that *0.5*(np.sign(x-k)+1) is 0 for x<k and 1 otherwise.
def f(x):
return 1/(np.sqrt(2*np.pi)*sigma)*np.exp(- 0.5*( (x-mu)/sigma )**2 ) *x*0.5*(np.sign(x-k)+1)
#use this to integrate from in (-1,1)
def G(u):
x=u/(1-u**2)
return f(x)*(1+u**2)/(1-u**2)**2
quad(G,-1,1,points=np.linspace(-0.999,0.999,25))
I would suggest to read this in order to get how you can optimize such integrals.

Numerical integration with singularities in python (principal value)

I'm trying to integrate a function with singularities using the quad function in scipy.integrate but I'm not getting the desired answer. Here is the code:
from scipy.integrate import quad
import numpy as np
def fun(x):
return 1./(1-x**2)
quad(fun, -2, 2, points=[-1, 1])
This results in IntegrationWarning and return value about 0.4.
The poles for the function are [-1,1]. The answer should be of roughly 1.09 (calculated using pen and paper).
The option weight='cauchy' can be used to efficiently compute the principal value of divergent integrals like this one. It means that the function provided to quad will be implicitly multiplied by 1/(x-wvar), so adjust that function accordingly (multiply it by x-wvar where wvar is the point of singularity).
i1 = quad(lambda x: -1./(x+1), 0, 2, weight='cauchy', wvar=1)[0]
i2 = quad(lambda x: -1./(x-1), -2, 0, weight='cauchy', wvar=-1)[0]
result = i1 + i2
The result is 1.0986122886681091.
With a simple function like this, you can also do symbolic integration with SymPy:
from sympy import symbols, integrate
x = symbols('x')
f = integrate(1/(1-x**2), x)
result = (f.subs(x, 2) - f.subs(x, -2)).evalf()
Result: 1.09861228866811. Without evalf() it would be log(3).
I also couldn't get it to work with the original function. I came up with this to evaluate the principal value in scipy:
def principal_value(func, a, b, poles, eps=10**(-6)):
#edges
res = quad(func,a,poles[0]-eps)[0]+quad(func,poles[-1]+eps,b)[0]
#inner part
for i in range(len(poles)-1):
res += quad(func, poles[i]+eps, poles[i+1]-eps)[0]
return res
Where func is your function handle, a and b are the limits, poles is a list of poles and eps is how near you want to approach the poles. You can make eps smaller and smaller to get a better result, but maybe sympy will be better for a problem like this.
With this function and the standard eps I get 1.0986112886023367 as a result, which is almost the same as wolframalpha gives.

Categories