Integração Numérica: Quadratura Gaussiana¶
Uma característica das fórmulas de Newton-Cotes é estimar a integral com base em valores da função tomados em nós igualmente espaçados. Consequentemente, a posição desses nós é predeterminada, isto é, fixada.
Agora, suponhamos que a restrição de ter nós fixados seja removida e que pudéssemos escolher arbitrariamente as posições por eles ocupadas. Com uma escolha adequada, será que conseguiríamos reduzir o erro de integração?
De fato, o método da Quadratura Gaussiana permite-nos estabelecer um conjunto mínimo de nós e pesos que realizam uma espécie de “balanceamento” do erro (subestimação vs. superestimação) e determinam aproximações numéricas de integrais com alta ordem.
As figuras abaixo mostram, por exemplo, como a integral de uma função é melhor calculada através da colocação de pontos em posições “especiais”. A regra do trapézio é posta em contraste com uma outra regra, que aprenderemos, cujo par de pontos, embora defina também um trapézio, ajuda a estimar melhor a integral de do que o observado no primeiro caso.
Em particular, daremos enfoque à chamada Quadratura de Gauss-Legendre.
import matplotlib.pyplot as plt
import numpy.polynomial.legendre as leg
import numpy as npdef f(x):
return -x**2 + 15*x - 10
x = np.linspace(0.5,10,100)
y = f(x)
# Representação geométrica da regra do trapézio
plt.figure()
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.fill([2, 2, 8, 8],[0, f(2), f(8), 0],color='r',alpha=0.4, label = 'I')
plt.title('Regra 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='--')
# Representação geométrica da quadratura de Gauss
def f1(x):
return 5.0*x + 11.0
plt.figure()
plt.plot(x,y, label = 'f(x)')
plt.plot([2,8], [f1(2),f1(8)], 'r', label = 'f1(x)')
plt.plot(3,f(3), 'o', label = 'f(a)')
plt.plot(7,f(7), 'o', label = 'f(b)')
plt.fill([2, 2, 8, 8],[0, f1(2), f1(8), 0],color='r',alpha=0.4, label = 'I')
plt.title('Quadratura de Gauss')
plt.legend()
plt.axvline(x=0,color='k',linewidth=0.6,linestyle='--')
plt.axhline(y=0,color='k',linewidth=0.6,linestyle='--');

Dedução da Fórmula de Gauss-Legendre para Dois Pontos¶
O objetivo da quadratura de Gauss-Legendre é determinar os coeficientes de uma equação da forma
em que os ’s são coeficientes desconhecidos. Entretanto, em contraste com a regra do trapézio que usa extremidades fixas e , os argumentos da função e não são fixados nas extremidades, mas são incógnitas. Assim, agora temos um total de quatro incógnitas que devem ser calculadas e necessitamos de quatro condições para determiná-las exatamente.
Podemos obter duas dessas condições, supondo que a Equação (1) calcula a integral de uma função constante e de uma função linear exatamente. Então, para chegar a duas outras condições, simplesmente estendemos esse raciocínio supondo que ele também calculará a integral de uma função parabólica () e de uma cúbica () exatamente. Fazendo isso, determinamos todas as quatro incógnitas e, de quebra, deduzimos uma fórmula de integração linear de dois pontos que é exata para funções cúbicas. As quatro equações a serem resolvidas são:
As Equações (2) até (5) podem ser resolvidas simultaneamente por
o que pode ser substituído na Equação (1) para fornecer a fórmula de Gauss-Legendre de dois pontos
Logo, chegamos ao interessante resultado que uma simples adição de valores da função em e fornece uma estimativa da integral que tem acurácia de terceira ordem.
Observe que os extremos de integração nas Equações (2) até (5) são de a 1. Isso foi feito para simplificar a matemática e tornar a formulação tão geral quanto possível. Uma simples mudança de variável pode ser usada para transformar outros extremos de integração para essa fórmula, o que se faz supondo que uma nova variável está relacionada à variável original de uma forma linear como em
Se o extremo inferior, , corresponder a , esses valores podem ser substituídos na Equação (7) para fornecer
Analogamente, o extremo superior, , corresponde a , e fornece
As Equações (8) e (9) podem ser resolvidas simultaneamente por
e
o que pode ser substituído na Equação (7) para fornecer
Essa equação pode ser derivada para dar
Os valores de e , nas Equações (10) e (11), respectivamente, podem ser substituídos na equação a ser integrada. Essas substituições transformam efetivamente o intervalo de integração sem mudar o valor da integral.
Fórmulas com Mais Pontos¶
Além da fórmula de dois pontos descrita acima, versões com mais pontos podem ser desenvolvidas na forma geral
em que é o número de pontos. Os valores para os ’s e os ’s para até (e incluindo) a fórmula de quatro pontos estão resumidos na tabela abaixo.
| Pontos | Fatores de Peso | Argumentos da Função |
|---|---|---|
| 3 | = 0.5555556 | = - 0.774596669 |
| = 0.8888889 | = 0.0 | |
| = 0.5555556 | = 0.774596669 | |
| 4 | = 0.3478548 | = - 0.861136312 |
| = 0.6521452 | = - 0.339981044 | |
| = 0.6521452 | = 0.339981044 | |
| = 0.3478548 | = 0.861136312 |
Implementação¶
Vamos implementar abaixo o código para gerar a tabela de pontos (nós) e pesos para integração numérica consoante as fórmulas de quadratura de Gauss-Legendre.
def f(x):
return np.exp(x) + x
def g(t):
return
def F(x):
return np.exp(x) + x**2/2
# \int_a^b f(x) dx;
a = - 1
b = 1
I = F(b) - F(a)
I
import matplotlib.pyplot as plt
xx = np.linspace(a,b)
plt.plot(xx, f(xx), 'r-')
plt.plot(xx, 0*xx, 'k-')
plt.plot(-0.577, 0, 'sg')
plt.plot(-0.577, f(-0.577), 'og')
plt.plot(0.577, 0, 'sg')
plt.plot(0.577, f(0.577), 'og')
# QG3
plt.plot(-0.774, 0, 'sb')
plt.plot(-0.774, f(-0.774), 'ob')
plt.plot(0, 0, 'sb')
plt.plot(0, f(0), 'ob')
plt.plot(0.774, 0, 'sb')
plt.plot(0.774, f(0.774), 'sb')
# número de pontos de quadratura
n = 2
# pontos e pesos
(pontos,pesos) = leg.leggauss(n)
def QG2(f):
(pontos,pesos) = leg.leggauss(2)
w0 = pontos[0]
w1 = pontos[1]
f0 = f(pontos[0])
f1 = f(pontos[1])
return w0*f0 + w1*f1
def QG3(f):
(pontos,pesos) = leg.leggauss(3)
w0 = pontos[0]
w1 = pontos[1]
w2 = pontos[2]
f0 = f(pontos[0])
f1 = f(pontos[1])
f2 = f(pontos[2])
return w0*f0 + w1*f1 + w2*f2
(pontos,pesos) = leg.leggauss(4)
def QG4(f):
(pontos,pesos) = leg.leggauss(4)
w0 = pontos[0]
w1 = pontos[1]
w2 = pontos[2]
w3 = pontos[3]
f0 = f(pontos[0])
f1 = f(pontos[1])
f2 = f(pontos[2])
f3 = f(pontos[3])
return w0*f0 + w1*f1 + w2*f2 + w3*f3
def QG(f,n):
(pontos,pesos) = leg.leggauss(n)
s = 0
for i in range(n):
s += pesos[i]*F(pontos[i])
return s
for n in range(1,10):
A = QG(f,n)
print(f"ordem {2*n+1}")
print(f"QG{n} = {A}")
ordem 3
QG1 = 2.0
ordem 5
QG2 = 2.676029421243064
ordem 7
QG3 = 2.6836702620133455
ordem 9
QG4 = 2.68373542548971
ordem 11
QG5 = 2.68373571979616
ordem 13
QG6 = 2.683735720619367
ordem 15
QG7 = 2.683735720620936
ordem 17
QG8 = 2.6837357206209362
ordem 19
QG9 = 2.6837357206209367
def F(t):
return 5.1*np.exp(5.1*t + 1.1)
def QG2(F):
(pontos,pesos) = leg.leggauss(2)
print(pontos,pesos)
return pesos[0]*F(pontos[0]) + pesos[1]*F(pontos[1])
def QG3(F):
(pontos,pesos) = leg.leggauss(3)
print(pontos,pesos)
return pesos[0]*F(pontos[0]) + pesos[1]*F(pontos[1]) + pesos[2]*F(pontos[2])
def QG4(F):
(pontos,pesos) = leg.leggauss(4)
print(pontos,pesos)
return pesos[0]*F(pontos[0]) + pesos[1]*F(pontos[1]) \
+ pesos[2]*F(pontos[2]) + pesos[3]*F(pontos[3])
def QG(F,n):
(pontos,pesos) = leg.leggauss(n)
s = 0
for i in range(n):
s += pesos[i]*F(pontos[i])
return s
for i in range(1,20):
print(f'QG{i} = {QG(F,i)}')QG1 = 30.642493444253617
QG2 = 291.9238277183161
QG3 = 456.0422383934014
QG4 = 488.96142750746253
QG5 = 492.48121331764094
QG6 = 492.71920635748165
QG7 = 492.7303338909227
QG8 = 492.73071525454685
QG9 = 492.73072524440545
QG10 = 492.7307254508673
QG11 = 492.7307254543184
QG12 = 492.73072545436776
QG13 = 492.73072545436753
QG14 = 492.73072545436855
QG15 = 492.7307254543701
QG16 = 492.73072545436673
QG17 = 492.7307254543697
QG18 = 492.7307254543684
QG19 = 492.73072545437
Isto é, para a regra de 2 pontos, os nós de Gauss-Legendre sãoprint(pontos)[-0.57735027 0.57735027]
e os pesos correspondentes são:
print(pesos)[1. 1.]
plt.plot(pontos,pesos)
plt.autoscale;
Tabela de pesos/pontos - Quadratura de Gauss-Legendre¶
Para gerarmos uma tabela de pontos e pesos, basta fazer:
# número máximo de pontos
N = 16
for i in range(1,N+1):
(pontos,pesos) = leg.leggauss(i)
print('REGRA DE {0} PONTO(S):\n-> Pontos:'.format(i))
print(pontos)
print('-> Pesos:')
print(pesos)
print('\n')REGRA DE 1 PONTO(S):
-> Pontos:
[0.]
-> Pesos:
[2.]
REGRA DE 2 PONTO(S):
-> Pontos:
[-0.57735027 0.57735027]
-> Pesos:
[1. 1.]
REGRA DE 3 PONTO(S):
-> Pontos:
[-0.77459667 0. 0.77459667]
-> Pesos:
[0.55555556 0.88888889 0.55555556]
REGRA DE 4 PONTO(S):
-> Pontos:
[-0.86113631 -0.33998104 0.33998104 0.86113631]
-> Pesos:
[0.34785485 0.65214515 0.65214515 0.34785485]
REGRA DE 5 PONTO(S):
-> Pontos:
[-0.90617985 -0.53846931 0. 0.53846931 0.90617985]
-> Pesos:
[0.23692689 0.47862867 0.56888889 0.47862867 0.23692689]
REGRA DE 6 PONTO(S):
-> Pontos:
[-0.93246951 -0.66120939 -0.23861919 0.23861919 0.66120939 0.93246951]
-> Pesos:
[0.17132449 0.36076157 0.46791393 0.46791393 0.36076157 0.17132449]
REGRA DE 7 PONTO(S):
-> Pontos:
[-0.94910791 -0.74153119 -0.40584515 0. 0.40584515 0.74153119
0.94910791]
-> Pesos:
[0.12948497 0.27970539 0.38183005 0.41795918 0.38183005 0.27970539
0.12948497]
REGRA DE 8 PONTO(S):
-> Pontos:
[-0.96028986 -0.79666648 -0.52553241 -0.18343464 0.18343464 0.52553241
0.79666648 0.96028986]
-> Pesos:
[0.10122854 0.22238103 0.31370665 0.36268378 0.36268378 0.31370665
0.22238103 0.10122854]
REGRA DE 9 PONTO(S):
-> Pontos:
[-0.96816024 -0.83603111 -0.61337143 -0.32425342 0. 0.32425342
0.61337143 0.83603111 0.96816024]
-> Pesos:
[0.08127439 0.18064816 0.2606107 0.31234708 0.33023936 0.31234708
0.2606107 0.18064816 0.08127439]
REGRA DE 10 PONTO(S):
-> Pontos:
[-0.97390653 -0.86506337 -0.67940957 -0.43339539 -0.14887434 0.14887434
0.43339539 0.67940957 0.86506337 0.97390653]
-> Pesos:
[0.06667134 0.14945135 0.21908636 0.26926672 0.29552422 0.29552422
0.26926672 0.21908636 0.14945135 0.06667134]
REGRA DE 11 PONTO(S):
-> Pontos:
[-0.97822866 -0.8870626 -0.73015201 -0.51909613 -0.26954316 0.
0.26954316 0.51909613 0.73015201 0.8870626 0.97822866]
-> Pesos:
[0.05566857 0.12558037 0.18629021 0.23319376 0.26280454 0.27292509
0.26280454 0.23319376 0.18629021 0.12558037 0.05566857]
REGRA DE 12 PONTO(S):
-> Pontos:
[-0.98156063 -0.90411726 -0.76990267 -0.58731795 -0.3678315 -0.12523341
0.12523341 0.3678315 0.58731795 0.76990267 0.90411726 0.98156063]
-> Pesos:
[0.04717534 0.10693933 0.16007833 0.20316743 0.23349254 0.24914705
0.24914705 0.23349254 0.20316743 0.16007833 0.10693933 0.04717534]
REGRA DE 13 PONTO(S):
-> Pontos:
[-0.98418305 -0.9175984 -0.80157809 -0.64234934 -0.44849275 -0.23045832
0. 0.23045832 0.44849275 0.64234934 0.80157809 0.9175984
0.98418305]
-> Pesos:
[0.040484 0.0921215 0.13887351 0.17814598 0.20781605 0.22628318
0.23255155 0.22628318 0.20781605 0.17814598 0.13887351 0.0921215
0.040484 ]
REGRA DE 14 PONTO(S):
-> Pontos:
[-0.98628381 -0.92843488 -0.82720132 -0.6872929 -0.51524864 -0.31911237
-0.10805495 0.10805495 0.31911237 0.51524864 0.6872929 0.82720132
0.92843488 0.98628381]
-> Pesos:
[0.03511946 0.08015809 0.12151857 0.15720317 0.1855384 0.20519846
0.21526385 0.21526385 0.20519846 0.1855384 0.15720317 0.12151857
0.08015809 0.03511946]
REGRA DE 15 PONTO(S):
-> Pontos:
[-0.98799252 -0.93727339 -0.84820658 -0.72441773 -0.57097217 -0.39415135
-0.20119409 0. 0.20119409 0.39415135 0.57097217 0.72441773
0.84820658 0.93727339 0.98799252]
-> Pesos:
[0.03075324 0.07036605 0.10715922 0.13957068 0.16626921 0.186161
0.19843149 0.20257824 0.19843149 0.186161 0.16626921 0.13957068
0.10715922 0.07036605 0.03075324]
REGRA DE 16 PONTO(S):
-> Pontos:
[-0.98940093 -0.94457502 -0.8656312 -0.75540441 -0.61787624 -0.45801678
-0.28160355 -0.09501251 0.09501251 0.28160355 0.45801678 0.61787624
0.75540441 0.8656312 0.94457502 0.98940093]
-> Pesos:
[0.02715246 0.06225352 0.09515851 0.12462897 0.14959599 0.16915652
0.18260342 0.18945061 0.18945061 0.18260342 0.16915652 0.14959599
0.12462897 0.09515851 0.06225352 0.02715246]
A partir daí, podemos organizar uma tabela para a regra de até 8 pontos/pesos como segue:
# número máximo de pontos
N = 8
header='| Regra | nó(s) | peso(s) |\n|---|---|---|'
print(header)
for i in range(1,N+1):
(pontos,pesos) = leg.leggauss(i)
p = ', '.join([str(p) for p in pontos])
w = ', '.join([str(p) for p in pesos])
row = '|' + str(i) + '|' + p + '|' + w + '|'
print(row) | Regra | nó(s) | peso(s) |
|---|---|---|
|1|0.0|2.0|
|2|-0.5773502691896257, 0.5773502691896257|1.0, 1.0|
|3|-0.7745966692414834, 0.0, 0.7745966692414834|0.5555555555555557, 0.8888888888888888, 0.5555555555555557|
|4|-0.8611363115940526, -0.33998104358485626, 0.33998104358485626, 0.8611363115940526|0.3478548451374537, 0.6521451548625462, 0.6521451548625462, 0.3478548451374537|
|5|-0.906179845938664, -0.5384693101056831, 0.0, 0.5384693101056831, 0.906179845938664|0.23692688505618942, 0.4786286704993662, 0.568888888888889, 0.4786286704993662, 0.23692688505618942|
|6|-0.932469514203152, -0.6612093864662645, -0.23861918608319693, 0.23861918608319693, 0.6612093864662645, 0.932469514203152|0.17132449237916975, 0.36076157304813894, 0.46791393457269137, 0.46791393457269137, 0.36076157304813894, 0.17132449237916975|
|7|-0.9491079123427585, -0.7415311855993945, -0.4058451513773972, 0.0, 0.4058451513773972, 0.7415311855993945, 0.9491079123427585|0.12948496616887065, 0.2797053914892766, 0.3818300505051183, 0.41795918367346896, 0.3818300505051183, 0.2797053914892766, 0.12948496616887065|
|8|-0.9602898564975362, -0.7966664774136267, -0.525532409916329, -0.18343464249564978, 0.18343464249564978, 0.525532409916329, 0.7966664774136267, 0.9602898564975362|0.10122853629037669, 0.22238103445337434, 0.31370664587788705, 0.36268378337836177, 0.36268378337836177, 0.31370664587788705, 0.22238103445337434, 0.10122853629037669|
Tabela de quadratura de Gauss-Legendre¶
| Regra | nó(s) | peso(s) |
|---|---|---|
| 1 | 0.0 | 2.0 |
| 2 | -0.57735026919, 0.57735026919 | 1.0, 1.0 |
| 3 | -0.774596669241, 0.0, 0.774596669241 | 0.555555555556, 0.888888888889, 0.555555555556 |
| 4 | -0.861136311594, -0.339981043585, 0.339981043585, 0.861136311594 | 0.347854845137, 0.652145154863, 0.652145154863, 0.347854845137 |
| 5 | -0.906179845939, -0.538469310106, 0.0, 0.538469310106, 0.906179845939 | 0.236926885056, 0.478628670499, 0.568888888889, 0.478628670499, 0.236926885056 |
| 6 | -0.932469514203, -0.661209386466, -0.238619186083, 0.238619186083, 0.661209386466, 0.932469514203 | 0.171324492379, 0.360761573048, 0.467913934573, 0.467913934573, 0.360761573048, 0.171324492379 |
| 7 | -0.949107912343, -0.741531185599, -0.405845151377, 0.0, 0.405845151377, 0.741531185599, 0.949107912343 | 0.129484966169, 0.279705391489, 0.381830050505, 0.417959183673, 0.381830050505, 0.279705391489, 0.129484966169 |
| 8 | -0.960289856498, -0.796666477414, -0.525532409916, -0.183434642496, 0.183434642496, 0.525532409916, 0.796666477414, 0.960289856498 | 0.10122853629, 0.222381034453, 0.313706645878, 0.362683783378, 0.362683783378, 0.313706645878, 0.222381034453, 0.10122853629 |
Transformação de variáveis¶
Uma integral sobre arbitrário ser transformada em uma integral em utilizando a mudança de variáveis:
x = np.linspace(2,4)
y = x - 3
plt.plot(x,y);
plt.plot(x,x*0);
plt.xticks([2,4],['a','b']);
plt.yticks([-1,1],['-1','1']);
plt.annotate('$t = \dfrac{2x - a - b}{b - a}$',(2.8,0.5));

Tarefa¶
Defina uma função como a seguinte que retorne output, tal que type(output) seja str.
def print_gauss_legendre_table(N):
header='| Regra | nó(s) | peso(s) |\n|---|---|---|'
print(header)
for i in range(1,N+1):
(pontos,pesos) = leg.leggauss(i)
p = ', '.join([str(p) for p in pontos])
w = ', '.join([str(p) for p in pesos])
row = '|' + str(i) + '|' + p + '|' + w + '|'
print(row) Então, reimprima a tabela para 8 pesos/pontos anterior com o código.
output = print_gauss_legendre_table(8)Em seguida, use o código abaixo para converter a saída da célula de código do Jupyter diretamente para Markdown.
from IPython.display import display, Markdown
display(Markdown(output))Por último, incorpore esta funcionalidade em print_gauss_legendre_table(N), para N dado.
| Regra | nó(s) | peso(s) |
|---|---|---|
| 1 | 0.0 | 2.0 |
| 2 | -0.57735026919, 0.57735026919 | 1.0, 1.0 |
| 3 | -0.774596669241, 0.0, 0.774596669241 | 0.555555555556, 0.888888888889, 0.555555555556 |
| 4 | -0.861136311594, -0.339981043585, 0.339981043585, 0.861136311594 | 0.347854845137, 0.652145154863, 0.652145154863, 0.347854845137 |
| 5 | -0.906179845939, -0.538469310106, 0.0, 0.538469310106, 0.906179845939 | 0.236926885056, 0.478628670499, 0.568888888889, 0.478628670499, 0.236926885056 |
| 6 | -0.932469514203, -0.661209386466, -0.238619186083, 0.238619186083, 0.661209386466, 0.932469514203 | 0.171324492379, 0.360761573048, 0.467913934573, 0.467913934573, 0.360761573048, 0.171324492379 |
| 7 | -0.949107912343, -0.741531185599, -0.405845151377, 0.0, 0.405845151377, 0.741531185599, 0.949107912343 | 0.129484966169, 0.279705391489, 0.381830050505, 0.417959183673, 0.381830050505, 0.279705391489, 0.129484966169 |
| 8 | -0.960289856498, -0.796666477414, -0.525532409916, -0.183434642496, 0.183434642496, 0.525532409916, 0.796666477414, 0.960289856498 | 0.10122853629, 0.222381034453, 0.313706645878, 0.362683783378, 0.362683783378, 0.313706645878, 0.222381034453, 0.10122853629 |
| 9 | -0.968160239508, -0.836031107327, -0.613371432701, -0.324253423404, 0.0, 0.324253423404, 0.613371432701, 0.836031107327, 0.968160239508 | 0.0812743883616, 0.180648160695, 0.260610696403, 0.31234707704, 0.330239355001, 0.31234707704, 0.260610696403, 0.180648160695, 0.0812743883616 |
| 10 | -0.973906528517, -0.865063366689, -0.679409568299, -0.433395394129, -0.148874338982, 0.148874338982, 0.433395394129, 0.679409568299, 0.865063366689, 0.973906528517 | 0.0666713443087, 0.149451349151, 0.219086362516, 0.26926671931, 0.295524224715, 0.295524224715, 0.26926671931, 0.219086362516, 0.149451349151, 0.0666713443087 |
| 11 | -0.978228658146, -0.887062599768, -0.730152005574, -0.519096129207, -0.269543155952, 0.0, 0.269543155952, 0.519096129207, 0.730152005574, 0.887062599768, 0.978228658146 | 0.0556685671162, 0.125580369465, 0.186290210928, 0.233193764592, 0.26280454451, 0.272925086778, 0.26280454451, 0.233193764592, 0.186290210928, 0.125580369465, 0.0556685671162 |
| 12 | -0.981560634247, -0.90411725637, -0.769902674194, -0.587317954287, -0.367831498998, -0.125233408511, 0.125233408511, 0.367831498998, 0.587317954287, 0.769902674194, 0.90411725637, 0.981560634247 | 0.0471753363865, 0.106939325995, 0.160078328543, 0.203167426723, 0.233492536538, 0.249147045813, 0.249147045813, 0.233492536538, 0.203167426723, 0.160078328543, 0.106939325995, 0.0471753363865 |