Интеграция 2D-образцов на прямоугольной сетке с использованием SciPy

SciPy имеет три метода для выполнения 1D-интегралов по выборкам (trapz, simps и romb) и один из способов сделать 2D-интеграл по функции (dblquad), но, похоже, у него нет методов для выполнения 2D-интеграла над образцами - четными на прямоугольной сетке.

Ближайшая вещь, которую я вижу, это scipy.interpolate.RectBivariateSpline.integral - вы можете создать RectBivariateSpline из данных на прямоугольной сетке и затем интегрировать ее. Однако это не очень быстро.

Я хочу что-то более точное, чем метод прямоугольника (т.е. просто суммируя все). Я мог бы, скажем, использовать двумерное правило Симпсона, создав массив с правильными весами, умножив его на массив, который я хочу интегрировать, и затем суммируя результат.

Однако я не хочу изобретать велосипед, если там уже что-то лучше. Есть?

Ответы

Ответ 1

Используйте правило 1D дважды.

>>> from scipy.integrate import simps
>>> import numpy as np
>>> x = np.linspace(0, 1, 20)
>>> y = np.linspace(0, 1, 30)
>>> z = np.cos(x[:,None])**4 + np.sin(y)**2
>>> simps(simps(z, y), x)
0.85134099743259539
>>> import sympy
>>> xx, yy = sympy.symbols('x y')
>>> sympy.integrate(sympy.cos(xx)**4 + sympy.sin(yy)**2, (xx, 0, 1), (yy, 0, 1)).evalf()
0.851349922021627

Ответ 2

Если вы имеете дело с истинным двумерным интегралом по прямоугольнику, у вас будет что-то вроде этого

>>> import numpy as np
>>> from scipy.integrate import simps
>>> x_min,x_max,n_points_x = (0,1,50)
>>> y_min,y_max,n_points_y = (0,5,50)
>>> x = np.linspace(x_min,x_max,n_points_x)
>>> y = np.linspace(y_min,y_max,n_points_y)
>>> def F(x,y):
>>>     return x**4 * y
# We reshape to use broadcasting
>>> zz = F(x.reshape(-1,1),y.reshape(1,-1))
>>> zz.shape 
(50,50)
# We first integrate over x and then over y
>>> simps([simps(zz_x,x) for zz_x in zz],y) 
2.50005233

Вы можете сравнить с истинным результатом, который