Upper Incomplete Gamma Function of order 0 in scipy - python

I am trying to implement the upper incomplete gamma function of order zero in Python. Normally we use gammaincc function but according to the docs,it's defined only for positive a. Is there any way to implement it in python for a=0 case? Thanks.

SciPy implements the regularized incomplete gamma function, the one with division by Gamma(a). This division makes no sense when a=0, but the non-regularized upper gamma still makes sense. Unfortunately there is no flag like regularized=False in SciPy.
However, in the special case a=0 the upper incomplete gamma function agrees with the exponential integral exp1 which is available in SciPy:
>>> from scipy.special import exp1
>>> exp1(1.3)
0.13545095784912914
(Compare to Wolfram Alpha).
Alternatively, the mpmath library computes non-regularized incomplete gammas by default.
>>> import mpmath
>>> mpmath.gammainc(0, 1.3)
mpf('0.13545095784912914')

Related

Hypergeometric confluent function divergence with scipy

I have a problem with the hypergeometric confluent function of scipy.
The code is
from scipy import special
print special.hyp1f1(-0.5, 0.5, -705)
print special.hyp1f1(-0.5, 0.5, -706)
and I obtain the output
47.0619041347
inf
I don't understand why the function is divergent. The hypergeometric confluent function has an asymptotic expansion for large x, and there shouldn't be any pole for these values of the parameters. Am I wrong, or this is a bug? Thanks in advance for your help!
A (known) bug: scipy.special.hyp1f1(0.5, 1.5, -1000) fails.
See also pull request hyp1f1: better handling of large negative arguments for reasons (namely, exponent overflow).
Kummer's hypergeometric function has poles only in negative integers, so is well defined for your usecase.
Just FYI: you can use the excellent mpmath library to get a hyp1f1 function which does not have this issue. Without GMP/MPIR + gmpy2 installed the library will be a bit slower than the scipy function but you will have arbitrary precision available.
mpmath example:
In [19]: hyp1f1(-0.5, 0.5, -706)
Out[19]: mpf('47.1')
In [20]: mp.dps = 25
In [21]: hyp1f1(-0.5, 0.5, -706)
Out[21]: mpf('47.09526954413143632617966605')
IMPORTANT NOTE
This scipy function will not always return inf when it can not handle the size of the return value. The values (-0.5, 0.5, 706) simply returns an incorrect answer.

Derivative of a conjugate in sympy

When I try to differentiate a symbol with SymPy I get the following
In : x=Symbol('x')
In : diff(x,x)
Out: 1
When I differentiate the symbol respect to its conjugate the result is
In [55]: diff(x,x.conjugate())
Out[55]: 0
However, when I try to differentiate the conjugate of the symbol SymPy doesn't do it
In : diff(x.conjugate(),x)
Out: Derivative(conjugate(x), x)
This is still correct, but the result should be zero. How can I make SimPy perform the derivative of a conjugate?
I'm not sure about the mathematics if diff(conjugate(x), x) should be zero. The fact that diff(x,x.conjugate()) gives zero has nothing to do with mathematics (and might even be considered a SymPy bug). It gives zero simply because x does not contain conjugate(x) (symbolically), so it sees it as a constant with respect to it. This is probably wrong, since x is not a constant with respect to conjugate(x). The fact that SymPy lets you take derivatives with respect to defined functions is probably a bug, actually. It is supposed to allow things like diff(f(x)**2, f(x)), where f = Function('f') is an undefined function, but for defined functions, it is probably mathematically incorrect (or at least not what you expect).
See http://docs.sympy.org/latest/modules/core.html?highlight=derivative#sympy.core.function.Derivative, particularly the section on derivatives wrt non-Symbols. To paraphrase, taking derivatives with respect to a function is just a notational convenience and does not represent a mathematical chain rule. Rather, something like diff(x, conjugate(x)) should be thought of as something like diff(x.subs(conjugate(x), dummy), dummy).subs(dummy, conjugate(x)).
Regarding conjugate(x).diff(x), this gives an unevaluated derivative because no derivative is defined for conjugate. I'm not sure if any closed-form answer is possible here anyway. Probably this is the most useful thing that SymPy could return. I can't find any good answers anywhere as to what a reasonable answer for this should be (you should ask on math SE to get a better answer about it).

SymPy - apply limits to an indefinite integral

In SymPy, is it possible to apply limits to an indefinite integral and evaluate it?
import sympy
from sympy.abc import theta
y = sympy.sin(theta)
Y_indef = sympy.Integral(y)
Y_def = sympy.Integral(y, (theta, 0, sympy.pi / 2))
Y_def.evalf() produces a number.
I'm looking for something like Y_indef.evalf((theta, 0, sympy.pi/2)) to get the same answer.
I do not know of a direct way, however you can extract the information from Y_indef in order to create a definite integral:
>>> indef = Integral(x)
>>> to_be_integrated, (free_var,) = indef.args
>>> definite = Integral(to_be_integrated, (free_var, 1, 2))
.args is a general attribute containing anything needed to construct most SymPy objects.
Edit: To address the comments to the questions.
SymPy may succeed evaluating definite integral and at the same time fail to solve their indefinite version. This is due to the existence of additional algorithms to be applied to definite integrals.
Both definite and indefinite integrals are instances of the same class. The only difference is what they contain in their .args. The need for different classes is not yet felt, given that SymPy mostly uses Integral as a flag to say that it can not solve the integral (i.e. the integrate function returns Integral when all of the implemented algorithms fail).

incomplete gamma function in python?

the scipy.special.gammainc can not take negative values for the first argument. Are there any other implementations that could in python? I can do a manual integration for sure but I'd like to know if there are good alternatives that already exist.
Correct result: 1 - Gamma[-1,1] = 0.85
Use Scipy: scipy.special.gammainc(-1, 1) = 0
Thanks.
I typically reach for mpmath whenever I need special functions and I'm not too concerned about performance. (Although its performance in many cases is pretty good anyway.)
For example:
>>> import mpmath
>>> mpmath.gammainc(-1,1)
mpf('0.14849550677592205')
>>> 1-mpmath.gammainc(-1,1)
mpf('0.85150449322407795')
>>> mpmath.mp.dps = 50 # arbitrary precision!
>>> 1-mpmath.gammainc(-1,1)
mpf('0.85150449322407795208164000529866078158523616237514084')
I just had the same issue and ended up using the recurrence relations for the function when a<0.
http://en.wikipedia.org/wiki/Incomplete_gamma_function#Properties
Note also that the scipy functions gammainc and gammaincc give the regularized forms Gamma(a,x)/Gamma(a)
Still an issue in 2021, and they still haven't improved this in scipy. Especially it is frustrating that scipy does not even provide unregularised versions of the upper and lower incomplete Gamma functions. I also ended up using mpmath, which uses its own data type (here mpf for mpmath floating - which supports arbitrary precision). In order to cook up something quick for the upper and lower incomplete Gamma function that works with numpy arrays, and that behaves like one would expect from evaluating those integrals I came up with the following:
import numpy as np
from mpmath import gammainc
"""
In both functinos below a is a float and z is a numpy.array.
"""
def gammainc_up(a,z):
return np.asarray([gammainc(a, zi, regularized=False)
for zi in z]).astype(float)
def gammainc_low(a,z):
return np.asarray([gamainc(a, 0, zi, regularized=False)
for zi in z]).astype(float)
Note again, this is for the un-regularised functions (Eq. 8.2.1 and 8.2.2 in the DLMF), the regularised functions (Eq. 8.2.3 and 8.2.4) can be obtined in mpmath by setting the keyword regularized=True.

Does Python's random module have a substitute for numpy.random.exponential?

I've been using Numpy's numpy.random.exponential function for a while. I now see that Python's random module has many functions that I didn't know about. Does it have something that replaces numpy.random.exponential? It would be nice to drop the numpy requirement from my project.
If anything about random.expovariate() does not suit your needs, it's also easy to roll your own version:
def exponential(beta):
return -beta * math.log(1.0 - random.random())
It seems a bit of an overkill to have a dependency on NumPy just for this functionality.
Note that this function accepts the mean beta as a parameter, as does the NumPy version, whereas the parameter lambd of random.expovariate() is the inverse of beta.
http://docs.python.org/library/random.html#random.expovariate
random.expovariate(lambd)
Exponential distribution. lambd is 1.0
divided by the desired mean. It should
be nonzero. (The parameter would be
called “lambda”, but that is a
reserved word in Python.) Returned
values range from 0 to positive
infinity if lambd is positive, and
from negative infinity to 0 if lambd
is negative.

Categories

Resources