There is a MATLAB function quadgk
that can compute complex integrals, or at least functions with poles and singularities. In Python, there is a general-purpose scipy.integrate.quad
which is handy for integration along the real axis. Is there a Python equivalent to MATLAB's quadgk
? All I could find was dr jimbob's code in another SO question, which doesn't seem to work on Python 3.4 any more.
Asked
Active
Viewed 4,412 times
1

Community
- 1
- 1

Medulla Oblongata
- 3,771
- 8
- 36
- 75
-
I suggest that you emphasize that you need a complex *contour*. For a real contour you could still use `scipy.integrate.quad` to compute the real and imaginary parts separately. If all else fails, you could do it by hand still: define a front-end function that defines the linear path `a1+i*a2` and `b1+i*b2` for two complex limits, with a real parameter between them, and use `quad` on the resulting real and imaginary parts... I admit it's far from pretty, and I hope there's a simpler, ready-made solution:) – Andras Deak -- Слава Україні Dec 08 '15 at 13:58
1 Answers
1
I don't think SciPy does provide an equivalent of MATLAB's quadgk
, but for what it's worth the code you link to in this question can be made to work in Python 3 with only minor changes:
import scipy
from scipy import array
def quad_routine(func, a, b, x_list, w_list):
c_1 = (b-a)/2.0
c_2 = (b+a)/2.0
eval_points = map(lambda x: c_1*x+c_2, x_list)
func_evals = list(map(func, eval_points)) # Python 3: make a list here
return c_1 * sum(array(func_evals) * array(w_list))
def quad_gauss_7(func, a, b):
x_gauss = [-0.949107912342759, -0.741531185599394, -0.405845151377397, 0, 0.405845151377397, 0.741531185599394, 0.949107912342759]
w_gauss = array([0.129484966168870, 0.279705391489277, 0.381830050505119, 0.417959183673469, 0.381830050505119, 0.279705391489277,0.129484966168870])
return quad_routine(func,a,b,x_gauss, w_gauss)
def quad_kronrod_15(func, a, b):
x_kr = [-0.991455371120813,-0.949107912342759, -0.864864423359769, -0.741531185599394, -0.586087235467691,-0.405845151377397, -0.207784955007898, 0.0, 0.207784955007898,0.405845151377397, 0.586087235467691, 0.741531185599394, 0.864864423359769, 0.949107912342759, 0.991455371120813]
w_kr = [0.022935322010529, 0.063092092629979, 0.104790010322250, 0.140653259715525, 0.169004726639267, 0.190350578064785, 0.204432940075298, 0.209482141084728, 0.204432940075298, 0.190350578064785, 0.169004726639267, 0.140653259715525, 0.104790010322250, 0.063092092629979, 0.022935322010529]
return quad_routine(func,a,b,x_kr, w_kr)
class Memoize: # Python 3: no need to inherit from object
def __init__(self, func):
self.func = func
self.eval_points = {}
def __call__(self, *args):
if args not in self.eval_points:
self.eval_points[args] = self.func(*args)
return self.eval_points[args]
def quad(func,a,b):
''' Output is the 15 point estimate; and the estimated error '''
func = Memoize(func) # Memoize function to skip repeated function calls.
g7 = quad_gauss_7(func,a,b)
k15 = quad_kronrod_15(func,a,b)
# I don't have much faith in this error estimate taken from wikipedia
# without incorporating how it should scale with changing limits
return [k15, (200*scipy.absolute(g7-k15))**1.5]
For example,
print(quad(lambda x: scipy.exp(1j*x), 0,scipy.pi/2.0))
[(0.99999999999999711+0.99999999999999689j), 9.6120083407040365e-19]
-
I think the problem is with a complex contour, like integrating from `-i` to `i`. Does the solution work for that case as well? – Andras Deak -- Слава Україні Dec 08 '15 at 14:13
-
1What if my limits of integration go to infinity, like `print(quadgk(lambda x: scipy.exp(1j*x), -np.inf,0))`? Then I get `[(nan+nan*j), nan]`. – Medulla Oblongata Dec 08 '15 at 14:40