I'm trying to compute the upper incomplete gamma function defined like in this post. If I use
from scipy.special import gamma,gammainc
from numpy import linspace
a = 0
z = (2+3j)*np.linspace(0,10)
gamma(a)*(1-gammainc(a,z))
where z is a complex vector I get an error
TypeError: ufunc 'gammainc' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''
Is there an alternative function to do the calculation? There doesn't seem to be a problem when I try to do this with WolframAlpha's Gamma function.
When SciPy is not enough for tricky special functions, mpmath usually comes to the rescue. Compare
>>> mpmath.gammainc(0, 2+3j)
mpc(real='-0.024826207944199364', imag='0.020316674911044622')
and the same from Wolfram Alpha.
Being written in Python, it is slower than SciPy; it is also not vectorized. So with your data it would work like
import mpmath
result = np.array([mpmath.gammainc(w) for w in z[1:]], dtype=np.complex)
Note that I avoid passing 0 as the argument (it's a pole). The return type of mpmath.gammainc is its own mpc object type, but it can be converted back to NumPy as above.
Related
I tried giving numba a go, as I was told it works very well for numerical/scientific computing applications. However, it seems that I've already run into a problem in the following scenario:
I have a function that computes a 12x12 Jacobian matrix, represented by a numpy array, and then returns this Jacobian. However, when I attempt to decorate said function with #numba.njit, I get the following error:
This is not usually a problem with Numba itself but instead often caused by
the use of unsupported features or an issue in resolving types.
As a basic example of my usage, the following code tries to declare a 12x12 numpy zero matrix, but it fails:
import numpy as np
import numba
#numba.njit
def numpy_matrix_test():
A = np.zeros([12,12])
return A
A_out = numpy_matrix_test()
print(A_out)
Since I assumed declaring numpy arrays in such a way was common enough that numba would be able to handle them, I'm quite surprised.
The assumption that the functions called in a numba jitted function are the same functions when not used in a numba function is actually wrong (but understandable). In reality numba (behind the scenes) delegates to its own functions instead of using the "real" NumPy functions.
So it's not really np.zeros that is called in the jitted function, it's their own function. So some differences between Numba and NumPy are unavoidable.
For example you cannot use a list for the shape, it has to be a tuple (lists and arrays produce the exception you've encountered). So the correct syntax would be:
#numba.njit
def numpy_matrix_test():
A = np.zeros((12, 12))
return A
Something similar applies to the dtype argument. It has to be a real NumPy/numba type, a Python type cannot be used:
#numba.njit
def numpy_matrix_test():
A = np.zeros((12, 12), dtype=int) # to make it work use numba.int64 instead of int here
return A
Even if "plain" NumPy allows it:
np.zeros((12, 12), dtype=int)
Do you perhaps mean numpy.zeros((12,12)), because you want a shape of 12 rows and 12 columns?
Numpy Zeros reference
numba.jit() allows entering a type signature but I can't figure out what the signature for a zero dimensional array is.
For example:
numba.jit('void(float32, float32[:])')
says the function return is void and the input arguments are float32 scalar and float32 1-D array.
But what is instead of a scalar I want to pass in a 0-dimensional array. What's the type signature? I tried the obvious float32[] but that didn't seem to work.
In case you are wondering how one gets a 0-D array in numpy you do it like this:
a = numpy.array(2)
which is different than
a = numpy.array([2])
the latter is a 1-D array.
This is how you can do it using numba.types.Array:
import numba as nb
import numpy as np
# |---------0d int array---------|
#nb.njit(nb.types.Array(nb.int64, 0, "C")())
def func():
return np.array(2)
Here I used that the returned value will be a C-contiguous int64 array with 0 dimensions. Adjust these as needed.
In my experience there is rarely a use-case (see "Benefit and Limitations of Ahead-of-Time compilation") for explicitly typed functions in numba - except for compilation times or in case one needs to avoid numba using already inferred types when it should compile a new function. So, personally, I wouldn't use these signatures.
numpy.copysign
I know how this function works, but I can't fully understand what this title description mean.
Like
x2[, out]
what does this parameter mean? Is it a datatype in python?
and
" = < ufunc 'copysign'> "
I have see something like this several times when I look through the documents.
Can anybody help? Thank you so much.
The brackets are standard Python documentation syntax for optional parameters to a function call. From the Python Language Reference Introduction:
a phrase enclosed in square brackets ([ ]) means zero or one occurrences (in other words, the enclosed phrase is optional)
You'll notice it all over the place in Python & its libraries' documentation.
The = <ufunc 'func_name'> bit is to let you know that the function is an instance of the numpy.ufunc class. From the NumPy docs on Universal Functions:
A universal function (or ufunc for short) is a function that operates
on ndarrays in an element-by-element fashion, supporting array
broadcasting, type casting, and several other standard features. That
is, a ufunc is a “vectorized” wrapper for a function that takes a
fixed number of scalar inputs and produces a fixed number of scalar
outputs.
In NumPy, universal functions are instances of the numpy.ufunc class. Many of the built-in functions are implemented in compiled C code, but ufunc instances can also be produced using the frompyfunc factory function.
I'm building a function to calculate the Reliability of a given component/subsystem. For this, I wrote the following in a script:
import math as m
import numpy as np
def Reliability (MTBF,time):
failure_param = pow(MTBF,-1)
R = m.exp(-failure_param*time)
return R
The function works just fine for any time values I call in the function. Now I wanna call the function to calculate the Reliability for a given array, let's say np.linspace(0,24,25). But then I get errors like "Type error: only length-1 arrays can be converted to Python scalars".
Anyone that could help me being able to pass arrays/vectors on a Python function like that?
Thank you very much in advance.
The math.exp() function you are using knows nothing about numpy. It expects either a scalar, or an iterable with only one element, which it can treat as a scalar. Use the numpy.exp() instead, which accepts numpy arrays.
To be able to work with numpy arrays you need to use numpy functions:
import numpy as np
def Reliability (MTBF,time):
return np.exp(-(MTBF ** -1) * time)
If possible you should always use numpy functions instead of math functions, when working with numpy objects.
They do not only work directly on numpy objects like arrays and matrices, but they are highly optimized, i.e using vectorization features of the CPU (like SSE). Most functions like exp/sin/cos/pow are available in the numpy module. Some more advanced functions can be found in scipy.
Rather than call Reliability on the vector, use list comprehension to call it on each element:
[Reliability(MTBF, test_time) for test_time in np.linspace(0,24,25)]
Or:
map(Reliability, zip([MTBF]*25, linspace(0,24,25))
The second one produces a generator object which may be better for performance if the size of your list starts getting huge.
I would like to lambdify sympy's exp, but I run into funny issues when trying to evaluate the function at a sympy.Symbol. This
import sympy
t = sympy.Symbol('t')
f = sympy.lambdify(t, t**2)
f(t) # no problem
works fine, but this
t = sympy.Symbol('t')
f = sympy.lambdify(t, sympy.exp(t))
f(t)
gives
AttributeError: 'Symbol' object has no attribute 'exp'
The same goes for all other native sympy functions I've tried (log, sin, etc.).
Any idea what's going on?
You should specify modules you want to use with modules argument of the lambdify function:
f = sympy.lambdify(t, sympy.exp(t), modules=["sympy"])
The main use of lambdify is to allow for a fast numerical evaluation of expressions.
This is achieved by replacing abstract and slow SymPy functions (like sympy.exp) with faster ones intended for numbers (like math.exp or numpy.exp).
These cannot handle SymPy symbols (like your t) as an argument, which is not what lambdify is intended for anyway.
If you call lambdify with dummify=False as an additional argument, you get a more meaningful error, when calling f(t), namely:
TypeError: can't convert expression to float
The expression that cannot be converted here is your argument t.
If you want to use a lambdified function with symbols as an argument for some reason, you need to pass modules=["sympy"] as an additional argument to lambdify.
This argument specifies which module lambdify uses to replace SymPy functions (like sympy.exp) – in this case, it’s sympy again, so nothing actually happens.