np.trapz функции

#python #integration

#python #интеграция

Вопрос:

У меня возникли проблемы с пониманием np.trapz. Я должен сам написать трапециевидное правило, а затем сравнить его с np.trapz Однако есть одна загвоздка. Скажем, интеграл равен от a до b. Я должен найти интеграл для a = 1 b = 1, a = 0 b = 2, a = 0 b = 3… a = 0 b = 10 и постройте график этих значений. Вот мой код для трапециевидной функции, которую я создал:

 ## trapezoidal ##
import numpy as np
import matplotlib.pyplot as plt

def f(x):
    o1 = 0.3 ## matter density of universe
    o2 = 0.7 ## density of dark enerrgy
    o3 = 0 ## density of radiation
    c = 3*10**3 ## constant
    return c/((o1*(1 x)**3   o3*(1 x)**2   o2)**(1/2))

data = [] ## data array

for b in range (0, 10):## for loop going through z2 as b

    ## definitions 
    a = 0
    N = 100
    h = (b-a)/N
    integral = 0

    integral = 0.5*(f(a)   f(b)) ## endpoints

    for i in range(1,N):
        integral  = f(a   (i*h))
    integral = integral*h
    integral = integral/(1 b)
    data.append(integral) ## appending each itteration into data array

 print(data)

plt.plot([1,2,3,4,5,6,7,8,9,10],data)
plt.xlabel('z')
plt.ylabel('DA')
  

и вот что я попытался для np.trapz, хотя я думаю, что я безнадежно ошибаюсь.
## np.trapz ##
импортировать numpy как np
импортировать matplotlib.pyplot как plt

 def f(x):
    o1 = 0.3 ## matter density of universe
    o2 = 0.7 ## density of dark enerrgy
    o3 = 0 ## density of radiation
    c = 3*10**3 ## constant
    return c/((o1*(1 x)**3   o3*(1 x)**2   o2)**(1/2))

x = np.arange(1,10,1)
##area = []

for i in range (0,10):
    x = [0,i]
    y = f/(1 i)
    area.append(np.trapz(y,x))

print(area)

plt.plot([1,2,3,4,5,6,7,8,9,10],area)
plt.xlabel('z')
plt.ylabel('DA')
  

Комментарии:

1. Оба ваших фрагмента используют np.trapz и выглядят ужасно похожими.

2. Мне так жаль! Это были разные версии того, что я пробовал. Я только что обновил его правильным кодом. Спасибо

3. Не могли бы вы, возможно, попытаться объяснить, в чем проблема? Мне не совсем ясно, нужна ли вам помощь в реализации правила трапеции или помощь в использовании numpy.trapz ?

4. @sydneeod Вы решили свою проблему или, возможно, какие-то новые детали?

Ответ №1:

Я попытаюсь показать, как реализовать правило трапеции, и сравнить его с его реализацией numpy . Итак, у вас есть функция def f(x) , которую вы хотите интегрировать из a в b .

Вы ничего не указали о принятии ошибок / допусков, но при сравнении различных методов численной оценки интегралов (.., уравнений или аналогичных) часто часто сравнивается масштаб их ошибок при увеличении размера системы, количества шагов итерации и так далее.

Правило трапеции является распространенным методом учебника, и существует множество бесплатной литературы (например, в Википедии). Следовательно, вы легко проверяете правильность своей реализации, потому что ее поведение уже хорошо известно. Кроме того, всегда полезно протестировать свой метод на задаче, которую можно решить аналитически (с помощью ручки и бумаги). Это быстро выявит ошибки в вашем коде / реализации.

Итак, давайте сделаем это! Рассмотрим тривиальную функцию g(x) = x . Интеграция g(x) из 0 в 10 легко выполняется и приводит к (1/2) * (10^2 - 0^2) = 50 . Вот g(x) в python,

 def g(x):
  return x
  

Теперь мы реализуем функцию для вычисления интеграла от любой функции func , используя правило трапеции, как определено в Википедии (ссылка выше),

 def my_trapz(func, a, b, n_steps):
  X = np.linspace(a,b,n_steps)
  integral = (func(a) func(b))/2.0   sum([func(x) for x in X])
  return integral * (b-a)/n_steps
  

Здесь func находится функция python ( def ), которая принимает ровно один аргумент. a является нижней и b верхней границей интеграла, в то время n_steps как количество значений x для оценки в пределах диапазона [a,b] . Чем больше n_steps , тем точнее будет интеграл. numpy.linspace(a,b,n) Функция создает массив n линейно расположенных чисел между a и b . теперь мы можем вызвать,

 a = 0.0
b = 10.0
n_steps = 100

integral = my_trapz(g, a, b, n_steps)
print(integral) # outputs 50.4999999..
  

Вы заметите, что чем выше значение, которое вы вводите n_steps , тем ближе результат 50 , как и ожидалось. Теперь мы хотим сравнить нашу реализацию с той numpy , что есть. Прочитав его документацию, мы видим, что интеграл вычисляется по,

 X = np.linspace(a,b,n_steps)

integral = np.trapz([g(x) for x in X], dx=(b-a)/n_steps)
print(integral) # outputs 49.9023437.., slightly better than out implementation
  

Здесь мы использовали понимание списка непосредственно в вызове функции. В качестве альтернативы, мы могли бы вместо этого сделать

 g_values = []
for x in :
  g_values.append(g(x))
integral = np.trapz(g_values, dx=(b-a)/n_steps)
  

Мы можем сравнить их, согласовав набор различных n_steps и исследуя, как работают два метода: для каждого значения n_steps в списке n_steps_list вычислите соответствующий интеграл, используя оба numpy и наш собственный метод. Затем постройте интегральный результат как функцию n_steps . Это,

 a = 0.0
b = 10.0
n_steps_list = [2**n for n in range(3,10)] # =[8, 16, 32, ..., 1024]

integral_np = []
integral_my = []

for n_steps in n_steps_list:
  X = np.linspace(a,b,n_steps)
  dx = (b-a)/n_steps
  integral_np.append(np.trapz([g(x) for x in X], dx=dx))
  integral_my.append(my_trapz(g, a, b, n_steps))

plt.scatter(n_steps_list, integral_np, color='g', label='np')
plt.scatter(n_steps_list, integral_my, color='r', label='my')
plt.xlabel('number of steps (resolution)')
plt.ylabel('Integral result')
plt.legend()
plt.show()
  

Результирующий график показан ниже,
trapz

Мы видим, что оба метода сходятся экспоненциально к ожидаемому значению, 50 . Это согласуется с анализом ошибок, представленным в статье Википедии.

Теперь я предлагаю вам попробовать повторить этот процесс, но заменив мою тривиальную g(x) на вашу исходную функцию f(x) и выяснить, что происходит.

 def f(x):
    o1 = 0.3 ## matter density of universe
    o2 = 0.7 ## density of dark enerrgy
    o3 = 0 ## density of radiation
    c = 3*10**3 ## constant
    return c/((o1*(1 x)**3   o3*(1 x)**2   o2)**(1/2))