2016-08-13 4 views
2

Есть ли метод в scipy для аналитического интегрирования кусочной функции? Например, у меня есть:Scipy аналитически интегрировать кусочную функцию

xrange_one, xrange_two = np.arange(0,4), np.arange(3,7) 

part_one = lambda x: x + 3 
part_two = lambda x: -2*x + 2 

Я хотел бы интегрировать в первый момент этой функции кусочно:

func_one = lambda x: x * (x + 3) 
func_two = lambda x: x * (-2*x + 2) 

Есть ли способ с SciPy integrate.quad или какой-либо другой аналитической функции интеграции, которые делают что-то вроде этого:

total = integrate.quad(func_one, 0, 3, func_two, 3, 6) 

Я не хочу просто интегрировать две части отдельно.

+0

"Analytical" и «SciPy «не будет смешиваться очень хорошо. Если вам нужна аналитическая интеграция, используйте 'sympy'. Напротив, 'scipy' предназначен для численных задач и численного интегрирования. –

+0

Что вы подразумеваете под «аналитическим»? 'quad' - это числовая интеграция. Он не вычисляет выражение '1/3 * x ** 3 + 3/2 * x ** 2'. 'np.polyint' может выполнять неопределенное полиномиальное интегрирование этих двух выражений. – hpaulj

+0

Хорошо, так что аналитику или использование чего-то типа quad отлично там, где функция передается для интеграции. – user2520932

ответ

4

Scipy не будет выполнять аналитическую интеграцию для вас, так как он предназначен для решения численных задач. SymPy, с другой стороны, может обрабатывать простые символические проблемы именно:

>>> import sympy as sym 
>>> x = sym.symbols('x') 
>>> f = sym.Piecewise((x*(x+3),x<3), (x*(-2*x+2),True)) 
>>> sym.integrate(f,(x,0,6)) 
-153/2 

Сравнить

>>> import scipy.integrate as integrate 
>>> integrate.quad(lambda x:x*(x+3),0,3)[0] + integrate.quad(lambda x:x*(-2*x+2),3,6)[0] 
-76.5 
>>> -153/2. 
-76.5 

Вы также можете определить исходную функцию кусочно-первых, а затем умножить его с символическим x, затем интегрировать этот новая функция аналитически.

Другая альтернатива, возможно, ближе к духу вашего вопроса, может заключаться в том, чтобы определить кусочную функцию численно и использовать scipy в конце концов. Это будет по-прежнему сохранять вашу работу, но не будет строго аналитический:

>>> f = lambda x: x*(x+3) if x<3 else x*(-2*x+2) 
>>> integrate.quad(f,0,6)[0] 
-76.5 

Наиболее полная установка с этим подходом:

>>> f = lambda x: x+3 if x<3 else -2*x+2 
>>> xf = lambda x: x*f(x) 
>>> first_mom = integrate.quad(xf,0,6)[0] 
>>> print(first_mom) 
-76.5 

Сначала определим кусочно лямбда для f, то подынтегральное первого момента, умножив его на x. Тогда мы выполняем интеграцию.


Обратите внимание, что многие не могут привязать лямбда к переменным.Если вы хотите, чтобы сделать это правильно, вы, вероятно, следует определить функцию с именем для функции кусочно-, и использовать только лямбда внутри интеграции (если иначе вы бы не использовать эту подынтегральное):

import scipy.integrate as integrate 
def f(x): 
    return x+3 if x<3 else -2*x+2 

first_mom = integrate.quad(lambda x: x*f(x),0,6)[0] 
1

После игры с в numpypoly функции, я придумал:

integrate.quad(lambda x:np.piecewise(x, [x < 3, x >= 3], 
    [lambda x: np.polyval([1,3,0],x), 
     lambda x: np.polyval([-2,2,0],x)]), 
    0,6) 

имеет значение:

(-76.5, 1.3489209749195652e-12) 

Существует polyint сделать полиномиальное интеграции

In [1523]: np.polyint([1,3,0]) 
Out[1523]: array([ 0.33333333, 1.5  , 0.  , 0.  ]) 
In [1524]: np.polyint([-2,2,0]) 
Out[1524]: array([-0.66666667, 1.  , 0.  , 0.  ]) 

Это

x*(x+3) => x**2 + 3*x => np.poly1d([1,3,0]) => 1/3 x**3 + 3/2 x**2 

Так analytical решение соответствующих конечных точек различия для этих двух polyint объектов:

In [1619]: np.diff(np.polyval(np.polyint([1,3,0]),[0,3])) + 
      np.diff(np.polyval(np.polyint([-2,2,0]),[3,6])) 
Out[1619]: array([-76.5]) 

In [1621]: [np.polyval(np.polyint([1,3,0]),[0,3]), 
      np.polyval(np.polyint([-2,2,0]),[3,6])] 
Out[1621]: [array([ 0. , 22.5]), array([ -9., -108.])] 
+0

Я даже не знал, что 'np.piecewise' была вещь, очень хорошая. (И я очень рад, что я не единственный с археологическими историями ipython.) –