Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Caderno 13

Integração Numérica: Regras de Newton-Cotes

As fórmulas de Newton-Cotes são os esquemas mais comuns de integração numérica. Elas são baseadas na estratégia de substituir uma função complicada ou dados tabulados por uma função aproximadora simples que seja fácil de integrar:

I=abf(x)dxabfn(x)dx(1)I = \int _a^b f(x)dx \cong \int _a^b f_n (x)dx \qquad (1)

em que fn(x)f_n (x) é um polinômio da forma

fn(x)=a0+a1x++an1xn1+anxnf_n (x) = a_0 + a_1 x + \dots + a_{n-1} x^{n-1} + a_n x^n

em que nn é o grau do polinômio.

A Regra do Trapézio

A regra do trapézio corresponde ao caso no qual o polinômio na Equação (1) é de primeiro grau:

I=abf(x)dxabf1(x)dxI = \int _a^b f(x)dx \cong \int _a^b f_1 (x)dx

onde

f1(x)=f(a)+f(b)f(a)ba(xa)f_1 (x) = f(a) + \dfrac{f(b) - f(a)}{b - a} (x - a)

O resultado da integração é

I=(ba)f(a)+f(b)2(2)I = (b - a) \dfrac{f(a) + f(b)}{2} \qquad (2)

Geometricamente, a regra dos trapézios é equivalente a aproximar a integral pela área do trapézio sob a reta ligando f(a)f(a) e f(b)f(b) (conforme figura abaixo). Portanto, a estimativa da integral pode ser representada por

Ilargura×altura meˊdiaI(ba)×altura meˊdiaI \cong \text{largura} \times \text{altura média} \\ I \cong (b - a) \times \text{altura média}

em que, para a regra dos trapézios, a altura média é a média dos valores da função nas extremidades, ou [f(a)+f(b)]/2[f (a) + f (b)]/2, conforme Equação (2).

import numpy as np
import matplotlib.pyplot as plt
import sympy as sy
import scipy as sp
from scipy import interpolate
from scipy import integrate
%matplotlib inline
# Representação geométrica da regra do trapézio

def f(x):
    return -x**2 + 15*x - 10

x = np.linspace(0.5,10,100)
y = f(x)

plt.plot(x,y, label = 'f(x)')
plt.plot([2,8], [f(2),f(8)], 'r', label = 'f1(x)')
plt.plot(2,f(2), 'o', label = 'f(a)')
plt.plot(8,f(8), 'o', label = 'f(b)')
plt.plot(np.mean([2,8]), np.mean([f(2),f(8)]), 'o', label = 'Altura Média')
plt.fill([2, 2, 8, 8],[0, f(2), f(8), 0],color='r',alpha=0.4, label = 'Área do Trapézio')
plt.legend()
plt.axvline(x=0,color='k',linewidth=0.6,linestyle='--')
plt.axhline(y=0,color='k',linewidth=0.6,linestyle='--');
<Figure size 432x288 with 1 Axes>

Aplicação Múltipla da Regra do Trapézio

Uma maneira de melhorar a acurácia da regra do trapézio é dividir o intervalo de integração de aa a bb em diversos segmentos e aplicar o método a cada segmento (conforme figura abaixo). As áreas correspondentes aos segmentos individuais podem então ser somadas parafornecer a integral para o intervalo inteiro. As equações resultantes são chamadas fórmulas de integração por aplicações múltiplas ou compostas.

Existem n+1n + 1 pontos base igualmente espaçados (x0,x1,x2,,xn)(x_0, x_1, x_2, \dots , x_n). Consequentemente, existem nn segmentos de largura igual:

h=ban(3)h = \dfrac{b − a}{n} \qquad (3)

Se aa e bb forem designados por x0x_0 e xnx_n, respectivamente, a integral total pode ser representada como

I=x0x1f(x)dx+x1x2f(x)dx++xn1xnf(x)dxI = \int _{x_0}^{x_1} f(x)dx + \int _{x_1}^{x_2} f(x)dx + \dots + \int _{x_{n - 1}}^{x_n} f(x)dx

Substituindo cada integral pela regra do trapézio, obtém-se

I=hf(x0)+f(x1)2+hf(x1)+f(x2)2++hf(xn1)+f(xn)2I = h \dfrac{f(x_0) + f(x_1)}{2} + h \dfrac{f(x_1) + f(x_2)}{2} + \dots + h \dfrac{f(x_{n - 1}) + f(x_n)}{2}

ou, agrupando termos,

I=h2[f(x0)+2i=1n1f(xi)+f(xn)](4)I = \dfrac{h}{2} \left[ f(x_0) + 2 \sum _{i = 1} ^{n - 1} f(x_i) + f(x_n) \right] \qquad (4)
# Representação geométrica da aplicação múltipla da regra do trapézio
# É possível observar, visualmente, que houve uma redução do erro do resultado em comparação com o caso anterior

xd = np.array([2,5,8])
yd = f(xd)

plt.plot(x,y, label = 'f(x)')
plt.plot(xd,yd, 'r')
plt.plot(2,f(2), 'o', label = 'f(x0)')
plt.plot(5,f(5), 'o', label = 'f(x1)')
plt.plot(8,f(8), 'o', label = 'f(x2)')
plt.fill([2, 2, 5, 5],[0, f(2), f(5), 0], color='r', alpha=0.6, label = 'Área do Trapézio 1')
plt.fill([5, 5, 8, 8],[0, f(5), f(8), 0], color='r', alpha=0.3, label = 'Área do Trapézio 2')
plt.legend()
plt.axvline(x=0,color='k',linewidth=0.6,linestyle='--')
plt.axhline(y=0,color='k',linewidth=0.6,linestyle='--'); 
<Figure size 432x288 with 1 Axes>

A Regra 1/3 de Simpson

A regra 1/3 de Simpson é obtida quando um polinômio interpolador de segundo grau é substituído na Equação (1):

I=abf(x)dxabf2(x)dxI = \int _a^b f(x)dx \cong \int _a^b f_2 (x)dx

Se aa e bb forem designados por x0x_0 e x2x_2 e se f2(x)f_2(x) for representado por um polinômio de Lagrange de segundo grau, a integral se torna

I=x0x2[(xx1)(xx2)(x0x1)(x0x2)f(x0)+(xx1)(xx2)(x0x1)(x0x2)f(x1)+(xx1)(xx2)(x0x1)(x0x2)f(x2)]dxI = \int _{x_0}^{x_2} \left[ \dfrac{(x - x_1)(x - x_2)}{(x_0 - x_1)(x_0 - x_2)} f(x_0) + \dfrac{(x - x_1)(x - x_2)}{(x_0 - x_1)(x_0 - x_2)} f(x_1) + \dfrac{(x - x_1)(x - x_2)}{(x_0 - x_1)(x_0 - x_2)} f(x_2) \right] dx

Depois da integração e de manipulações algébricas, obtém-se a seguinte fórmula:

Ih3[f(x0)+4f(x1)+f(x2)](5)I \cong \dfrac{h}{3} [f(x_0) + 4 f(x_1) + f(x_2)] \qquad (5)

em que, para esse caso

h=ba2(6)h = \dfrac{b − a}{2} \qquad (6)
# Descrição gráfica da regra 1/3 de Simpson: ela consiste em tomar a área sob uma parábola ligando três pontos

def f(x):
    return 0.6*np.sin(x+np.pi/2) + 0.2*x + 2

def f2(x):
    return -0.127382111059529*x**2 + 1.73647155618593*x - 2.0569711669823 # Obtido pelo MMQ

x = np.linspace(2,10,100)
y = f(x)

xc = np.linspace(2,10,100)
yc = f2(xc)

xf = np.linspace(3,9,100)
yf = f2(xf)

xf = np.concatenate((np.array([3]), xf, np.array([9])))
yf = np.concatenate((np.array([0]), yf, np.array([0])))

plt.plot(x,y, label = 'f(x)')
plt.plot(xc,yc, ':r', label = 'f2(x)')
plt.plot(3,f(3), 'o', label = 'f(x0)')
plt.plot(6,f(6), 'o', label = 'f(x1)')
plt.plot(9,f(9), 'o', label = 'f(x2)')
plt.fill(xf,yf, color='r', alpha=0.4)
plt.legend()
plt.axvline(x=0,color='k',linewidth=0.6,linestyle='--')
plt.axhline(y=0,color='k',linewidth=0.6,linestyle='--');
<Figure size 432x288 with 1 Axes>

Aplicações Múltiplas da Regra 1/3 de Simpson

Do mesmo modo como no caso da regra do trapézio, a regra de Simpson pode ser melhorada dividindo-se o intervalo de integração em diversos segmentos de mesmo comprimento

h=ba2h = \dfrac{b − a}{2}

A integral total pode ser representada como

I=x0x2f(x)dx+x2x4f(x)dx++xn2xnf(x)dxI = \int _{x_0}^{x_2} f(x)dx + \int _{x_2}^{x_4} f(x)dx + \dots + \int _{x_{n - 2}}^{x_n} f(x)dx

Substituindo cada integral individual pela regra 1/3 de Simpson, obtemos

I2hf(x0)+4f(x1)+f(x2)6+2hf(x2)+4f(x3)+f(x4)6++2hf(xn2)+4f(xn1)+f(xn)6I \cong 2 h \dfrac{f(x_0) + 4 f(x_1) + f(x_2)}{6} + 2 h \dfrac{f(x_2) + 4 f(x_3) + f(x_4)}{6} + \dots + 2 h \dfrac{f(x_{n - 2}) + 4 f(x_{n - 1}) + f(x_n)}{6}

ou

I(ba)f(x0)+4i=1,3,5n1f(xi)+2i=2,4,6n2f(xj)+f(xn)3n(7)I \cong (b - a) \dfrac{ f(x_0) + 4 \sum _{i = 1, 3, 5}^{n-1} f(x_i) + 2 \sum _{i = 2, 4, 6}^{n-2} f(x_j) + f(x_n) }{3 n} \qquad (7)

Regra 3/8 de Simpson

De uma maneira parecida com a dedução da regra do trapézio e da regra 1/3 de Simpson, um polinômio de Lagrange de ordem três pode ser ajustado a quatro pontos e integrado

I=abf(x)dxabf3(x)dxI = \int _a^b f(x)dx \cong \int _a^b f_3 (x)dx

para fornecer

I3h8[f(x0)+3f(x1)+3f(x2)+f(x3)](8)I \cong \dfrac{3 h}{8} [f(x_0) + 3 f(x_1) + 3 f(x_2) + f(x_3)] \qquad (8)

em que

h=ba3(9)h = \dfrac{b − a}{3} \qquad (9)

Essa equação é chamada regra 3/8 de Simpson porque hh é multiplicada por 3/8.

# Descrição gráfica da regra 3/8 de Simpson: ela consiste em tomar a área sob uma equação cúbica ligando quatro pontos

def f3(x):
    return -0.0166482246490701*x**3 + 0.189467273747325*x**2 - 0.117878777555138*x + 1.10393743650415 # Obtido pelo MMQ

xc = np.linspace(2,10,100)
yc = f3(xc)

xf = np.linspace(3,9,100)
yf = f3(xf)

xf = np.concatenate((np.array([3]), xf, np.array([9])))
yf = np.concatenate((np.array([0]), yf, np.array([0])))

plt.plot(x,y, label = 'f(x)')
plt.plot(xc,yc, ':r', label = 'f3(x)')
plt.plot(3, f(3), 'o', label = 'f(x0)')
plt.plot(5, f(5), 'o', label = 'f(x1)')
plt.plot(7, f(7), 'o', label = 'f(x2)')
plt.plot(9, f(9), 'o', label = 'f(x3)')
plt.fill(xf,yf, color='r', alpha=0.4)
plt.legend()
plt.axvline(x=0,color='k',linewidth=0.6,linestyle='--')
plt.axhline(y=0,color='k',linewidth=0.6,linestyle='--');
<Figure size 432x288 with 1 Axes>

Integração com Segmentos Desiguais

Até esse ponto, todas as fórmulas para integração numérica foram baseadas em dados igualmente espaçados. Na prática, existem muitas situações nas quais essa hipótese não é válida e precisamos lidar com segmentos de tamanhos distintos. Por exemplo, dados obtidos experimentalmente, muitas vezes, são desse tipo. Para tais casos, um método é aplicar a regra do trapézio para cada segmento e somar os resultados:

I=h1f(x0)+f(x1)2+h2f(x1)+f(x2)2++hnf(xn1)+f(xn)2I = h_1 \dfrac{f(x_0) + f(x_1)}{2} + h_2 \dfrac{f(x_1) + f(x_2)}{2} + \dots + h_n \dfrac{f(x_{n - 1}) + f(x_n)}{2}

em que hih_i é a largura do segmento ii.

Implementações de Newton-Cotes: Regra do Trapézio e 1/3 Simpson Generalizadas

''' Newton-Cotes: Regra do Trapezio
    assume Y igualmente espaçado e 
    com pelo menos 2 pontos 
'''
def integral_trapezio(h,Y):
    val = 0.0
    for i in range(1,Y.size-1):
        val += 2*Y[i]
    val = 0.5*h*( val + Y[0] + Y[-1] )
    return val

''' Newton-Cotes: Regra 1/3 de Simpson
    assume Y igualmente espaçado e 
    com pelo menos 3 pontos 
'''
def integral_onethird_simpson(h,Y):
    val = 0.0
    for i in range(1,Y.size-1,2):
        val += 4*Y[i]
    
    for i in range(2,Y.size-2,2):
        val += 2*Y[i]        
    
    val = h/3.0*( val + Y[0] + Y[-1] )
    return val

''' HELPER''' 
def print_metodo(flag):            
    print('*** Método de integração: ' + str.upper(flag) + ' ***')

# limites de integração
a = 0
b = 93

# integrando 
f = lambda v: 97000*v/(5*v**2 + 570000)

# pontos de integração (ímpares para testar com 1/3 simpson)
npi = [11,101,1001,10001,100001]

# integral exata
x = sy.Symbol('x')
vex = sy.integrate(f(x),(x,a,b))
print('Ingegral exata (simbólica): ' + str(vex))
vex = float(vex)
print('Integral exata (numérica): ' + str(vex))

metodos = ['trapezio','13simpson']
no = False

# integração numérica
for metodo in metodos:
    I = []
    EREL = []
    for n in npi:
        v = np.linspace(a,b,num=n,endpoint=True)
        fv = f(v)
        h = (b-a)/n    
                
        if metodo == 'trapezio':
            if no == False:
                print_metodo(metodo)
                no = True            
            val = integral_trapezio(h,fv)
            erel = abs((vex - val)/vex)*100
            I.append(val)
            EREL.append(erel)
            print("no. de pontos de integração = {0:d} \t I = {1:.10f} \t EREL = {2:.10f}%".format(n,val,erel) )

        elif metodo == '13simpson':
            if no == False:
                print_metodo(metodo)
                no = True
            val = integral_onethird_simpson(h,fv)
            erel = abs((vex - val)/vex)*100
            I.append(val)
            EREL.append(erel)        
            print("no. de pontos de integração = {0:d} \t I = {1:.10f} \t EREL = {2:.10f}%".format(n,val,erel) )
    
    no = False
Ingegral exata (simbólica): -9700*log(114000) + 9700*log(122649)
Integral exata (numérica): 709.3432392521672
*** Método de integração: TRAPEZIO ***
no. de pontos de integração = 11 	 I = 644.6326388025 	 EREL = 9.1226076276%
no. de pontos de integração = 101 	 I = 702.3175905243 	 EREL = 0.9904441657%
no. de pontos de integração = 1001 	 I = 708.6345799441 	 EREL = 0.0999035825%
no. de pontos de integração = 10001 	 I = 709.2723117737 	 EREL = 0.0099990350%
no. de pontos de integração = 100001 	 I = 709.3361458882 	 EREL = 0.0009999903%
*** Método de integração: 13SIMPSON ***
no. de pontos de integração = 11 	 I = 644.8576901994 	 EREL = 9.0908809000%
no. de pontos de integração = 101 	 I = 702.3200388852 	 EREL = 0.9900990068%
no. de pontos de integração = 1001 	 I = 708.6346046475 	 EREL = 0.0999000999%
no. de pontos de integração = 10001 	 I = 709.2723120210 	 EREL = 0.0099990001%
no. de pontos de integração = 100001 	 I = 709.3361458907 	 EREL = 0.0009999900%

Tarefa

Implemente uma função para realizar a integração numérica pela regra 3/8 de Simpson, use-a para calcular o valor de

a=0b=9397000v(5v2+570000)dx\int_{a=0}^{b=93} \frac{97000v}{(5v^2 + 570000)} \, dx

e compare o resultado com os obtidos pelas anteriores.

Integração simbólica

Vamos ver alguns exemplos de integração simbólica. Para termos uma impressão mais elegante de expressões, antes usamos a seguinte instrução:

sy.init_printing()

Regra quadratura de Simpson

Vamos usar símbolos para chegar à expressão da regra de quadratura de Simpson.

a,b,X = sy.symbols("a, b, x")
f = sy.Function("f")

Definimos tuplas para os pontos de amostra e pesos.

x = a, (a + b)/2, b # ponto médio 
w = [sy.symbols("w_%d" % i) for i in range(len(x))] # pesos 
q = sum([w[i] * f(x[i]) for i in range(len(x))])
q
Loading...

Para calcular valores aproximados dos pesos wiw_i, escolhemos a base polinomial

{ϕn(x)=xn}n=02\{ \phi_n(x) = x^n \}_{n=0}^2

para a interpolação de f(x)f(x) e um objeto simbólico para representar cada uma dessas funções.

phi = [sy.Lambda(X, X**n) for n in range(len(x))]
phi
Loading...

Agora temos que descobrir os valores dos pesos. A integral abϕn(x)dx\int_a^b \phi_n(x) \, dx pode ser calculada analiticamente para cada função de base. Isto nos ajuda a resolver o seguinte sistema:

i=02wiϕn(xi)=abϕn(x)dx\sum\limits_{i=0}^2 w_i \phi_n(x_i) = \int_a^b \phi_n(x) \, dx

O sistema pode ser construído no sympy da seguinte forma:

eqs = [q.subs(f, phi[n]) - sy.integrate(phi[n](X), (X, a, b)) for n in range(len(phi))]
eqs
Loading...

Em seguida, resolvemos o sistema para obter as expressões analíticas para os pesos:

w_sol = sy.solve(eqs,w)
w_sol
Loading...

Substituindo a solução na expressão simbólica para a regra de quadratura:

q.subs(w_sol).simplify()
Loading...

Podemos verificar no material que esta é, de fato, a expressão para a regra de quadratura de Simpson.

Integração múltipla

A integração em 2 ou mais variáveis pode ser feita usando as funções dblquad, tplquad e nquad, onde o número de funções e de limites de integração deve se adequar ao tipo de integral.

Abaixo, temos alguns exemplos:

Integração dupla

Neste exemplo, integramos

0101ex2y2dxdy\int_0^1\int_0^1 e^{-x^2 - y^2} \, dx dy
integrate.dblquad(lambda x, y: np.exp(-x**2-y**2), 0, 1, lambda x: 0, lambda x: 1)
Loading...

Integração tripla

Neste exemplo, integramos

010101ex2y2z2dxdydz\int_0^1\int_0^1\int_0^1 e^{-x^2 - y^2 - z^2} \, dx dy dz
def f(x, y, z): 
    return np.exp(-x**2-y**2-z**2) 

a, b = 0, 1
g, h = lambda x: 0, lambda x: 1
q, r = lambda x, y: 0, lambda x, y: 1
integrate.tplquad(f, 0, 1, g, h, q, r) 
Loading...
import numpy as np


(1 + 4*np.exp(1) + np.exp(1)**2)/3
6.42072780425561