Você está na página 1de 30

Métodos Computacionais da Astronomia

11. Interpolação

Helio J. Rocha-Pinto

Observatório do Valongo – UFRJ

v.2019/2

OVL232
Razões para interpolar dados

MV Φ(MV )/104 pc3 A tabela nos fornece a Função de


-6 0.0001 Luminosidade da Galáxia, que
indica o número médio (por pc3 )
-5 0.0006
de estrelas que têm magnitude
-4 0.0029 absoluta MV .
-3 0.013
Como podemos estimar desta
-2 0.05
tabela o número de estrelas por
-1 0.25 pc3 que tenham, digamos,
0 1 MV = 4.47?
+1 3
Problemas de interpolação
+2 6 surgem quando temos (n + 1)
+3 12 pares de pontos (x, f (x)) e
+4 19 precisamos estimar f (xm ), sendo
+5 34 xm um ponto intermediário entre
+6 42 os pontos x conhecidos.

OVL232
Interpolação polinomial I
A interpolação polinomial consiste em obter uma função polinomial
g (x) tal que
g (xj ) : pn (xj ) = f (xj ), ∀xj , j = 0, . . . , n
g (x) será o polinômio de grau ≤ n tal que a condição acima valha.
Por ser um polinômio de grau n, sua forma será
pn (x) = a0 + a1 x + a2 x 2 + . . . + an x n
Assim, devemos obter os coeficientes aj , j = 0, . . . , n. Da condição
acima, temos
a0 + a1 x0 + a2 x02 + . . . + an x0n = f (x0 )
a0 + a1 x1 + a2 x12 + . . . + an x1n = f (x1 )
.. .. .. .. ..
. . . . .
a0 + a1 xn + a2 xn2 + . . . + an xnn = f (xn )

OVL232
Interpolação polinomial II

Essas equações convertem o problema de interpolação no de


uma solução para o sistema de (n + 1) equações e (n + 1)
incógnitas, que pode ser escrito matricialmente como

X ~a ~
fx
z }| { z }| { z }| {
x02 . . . x0n

1 x0 a0 f (x0 )
 1 x1 x12 . . . x1n   a1   f (x1 ) 
  ..  =  ..
    
.. .. .. . . .
. ..
 
 . . .  .   . 
1 xn xn2 . . . xnn an f (xn )

Portanto, se os pontos xi forem distintos, det X 6= 0, e o


sistema terá solução única.
Desta forma, para encontrar os coeficientes ai , basta que
~ usando as técnicas de cálculo
resolvamos o sistema X~a = fx
matricial já vistas.
OVL232
Interpolação polinomial III

Tentemos resolver isso com os comandos padrões do Python.


from numpy import *

x = [] Amplie esse programa para que


fx = []
ele:
# dados que serao interpolados
1 Leia dados (quaisquer
data = [[2,5],[3,4],[4,2.5],[5,0]]

n = len(data)
dados desde que no
formato xy) de um
# construcao da matriz X e vetor fx
for i in range(0,n): arquivo (formatado sob a
linha = []
for j in range(0,n):
forma de colunas)
linha.append(data[i][0]**float(j)) 2 Grafique, via comandos
x.append(linha)
fx.append(data[i][1]) Matplotlib, os pontos
# adaptacao da lista para um array numpy originais a serem
x = array(x)
fx = array(fx)
interpolados e a função
interpoladora.
a = linalg.solve(x,fx)

OVL232
Interpolação de Lagrange I

Seja o polinômio interpolador pn (x). Podemos representá-lo


como

pn (x) = y0 L0 (x) + y1 L1 (x) + . . . + yn Ln (x)

onde Lk é um polinômio de grau n.


Sejam x0 , . . ., xn , (n + 1) pontos distintos, e yi = f (xi ),
i = 0, . . . , n. Queremos garantir que

pn (xi ) = y0 L0 (xi ) + y1 L1 (xi ) + . . . + yn Ln (xi ) = yi .

OVL232
Interpolação de Lagrange II

A forma mais simples para obter essa condição é impor que


(
0 se k =6 i
Lk (xi ) =
1 se k = i.

onde
(x − x0 )(x − x1 ) . . . (x − xk−1 )(x − xk+1 ) . . . (x − xn )
Lk (x) =
(xk − x0 )(xk − x1 ) . . . (xk − xk−1 )(xk − xk+1 ) . . . (xk − xn )

Verifica-se facilmente que Lk (xk ) = 1 e Lk (xi ) = 0, ∀i 6= k.

OVL232
Interpolação de Lagrange III

Dado que o numerador de Lk é um produto de n binômios


(x − xi ), Lk será um polinômio de grau n, e pn (x) terá grau
≤ n:
Qn
(x − xj )
n n j=0
X X j6=k
pn (x) = yk Lk (x) = yk n
Q
k=0 k=0 (xk − xj )
j=0
j6=k

OVL232
Exemplo de interpolação pelo Método de Lagrange

f (x) x −1 0 2
f (x) 4 1 −1
• 4.0 –
p2 (x) = y0 L0 (x) + y1 L1 (x) + y2 L2 (x)

3.0 – y0 L0

(x − x1 )(x − x2 ) x 2 − 2x
2.0 – L0 (x) =
(x0 − x1 )(x0 − x2 )
=
3
y1 L1
1.0 •– p2 (x) (x − x0 )(x − x2 ) x2 − x − 2
L1 (x) = =
(x1 − x0 )(x1 − x2 ) −2

| | | | | x (x − x0 )(x − x1 ) x2 + x
L2 (x) = =
y2 L2 1.0 2.0 3.0 4.0 (x2 − x0 )(x2 − x1 ) 6

• 7 2
p2 (x) = 1 − x + x 2
3 3

OVL232
Interpolação de Lagrange em Python
import numpy as np
import matplotlib.pyplot as plt

xList = np.array([0., 1., 2., 3.8])


yList = np.array([1., 2., 4., -4.])
n = len(xList)

# Calcula o polinomio de Lagrange em cada x


m = 1000 # passos
xinterp = [] ; yinterp = []
for k in range(m):
x = ((xList.max()+2) - (xList.min()-2)) * k / (m - 1) + (xList.min()-2)
xinterp.append(x) ; yinterp.append(Pn(x))

plt.plot(xList,yList,’ob’)
plt.xlim(xList.min()-4,xList.max()+4) ; plt.ylim(yList.min()-4,yList.max()+4)
plt.plot(xinterp,yinterp,’r--’) ; plt.show()

def LagrangePol(x,i):
mult = 1
for j in range(n):
if j != i:
mult *= (x - xList[j]) / float(xList[i] - xList[j])
return mult

def Pn(x):
total = 0
for i in range(n):
total += yList[i] * LagrangePol(x,i)
return total

OVL232
Fórmula interpoladora de Newton I
Newton propõe a seguinte fórmula interpoladora:

pn (x) = d0 +d1 (x −x0 )+d2 (x −x0 )(x −x1 )+. . .+dn (x −x0 )(x −x1 ) . . . (x −xn−1 ),

onde os dk são os operadores de diferenças divididas:

d0 = f [x0 ] = f (x0 )
f [x1 ] − f [x0 ]
d1 = f [x0 , x1 ] =
x1 − x0
f [x1 , x2 ] − f [x0 , x1 ]
d2 = f [x0 , x1 , x2 ] =
x2 − x0
f [x1 , x2 , x3 ] − f [x0 , x1 , x2 ]
d3 = f [x0 , x1 , x2 , x3 ] =
x3 − x0
..
.
f [x1 , x2 , . . . , xn ] − f [x0 , x1 , . . . , xn−1 ]
dn = f [x0 , x1 , . . . , xn ] =
xn − x0

OVL232
Fórmula interpoladora de Newton II
Dizemos que f [x0 , x1 , . . . , xn ] é a diferença dividida de ordem
k da função f (x) sobre os k + 1 pontos x0 , x1 , . . . , xn . Assim,
de posse de n + 1 pares de valores (xi , f (xi )) podemos
construir a tabela

OVL232
Fórmula interpoladora de Newton III

A fórmula de Newton para o polinômio interpolador requer que f (x)


seja contı́nua em [a, b] e tenha tantas derivadas quanto for possı́vel
neste intervalo. Construiremos essa fórmula em partes.
Seja p0 (x) o polinômio de grau zero que interpola f (x) em x0 .

p0 (x) = f (x0 ) = f [x0 ]

Para todo x ∈ [a, b], x 6= x0 ,

f [x] − f [x0 ] f (x) − f (x0 )


f [x0 , x] = =
x − x0 x − x0
que pode ser rearranjado como

f (x) = f (x0 ) + (x − x0 )f [x0 , x1 ]


| {z } | {z }
p0 (x) E0 (x)→ erro

OVL232
Fórmula interpoladora de Newton IV

Agora, construamos p1 (x):

f [x0 , x] − f [x1 , x0 ]
f [x0 , x1 , x] = f [x1 , x0 , x] =
x − x1
f (x) − f (x0 )
− f [x1 , x0 ]
x − x0
=
x − x1
f (x) − f (x0 ) − (x − x0 )f [x1 , x0 ]
=
(x − x0 )(x − x1 )

Assim

f (x) = f (x0 ) + (x − x0 )f [x1 , x0 ] + (x − x0 )(x − x1 )f [x0 , x1 , x]


| {z } | {z }
p1 (x) E1 (x)→ erro

OVL232
Fórmula interpoladora de Newton V

Aplicando o mesmo raciocı́nio para o polinômio de grau n,


teremos
pn (x) = f (x0 ) + (x − x0 )f [x0 , x1 ]
+ (x − x0 )(x − x1 )f [x0 , x1 , x2 ]
+ ...
+ (x − x0 )(x − x1 ) . . . (x − xn−1 )f [x0 , x1 , . . . , xn ]

com erro dado por

En (x) = (x − x0 )(x − x1 ) . . . (x − xn )f [x0 , x1 , . . . , xn , x]

OVL232
Erro de interpolação I

Ao aproximar uma função por um polinômio interpolante de


grau ≤ n, comete-se o erro

En (x) = f (x) − pn (x), ∀x ∈ [x0 , xn ]

Na figura, p1 (x) serve como


interpolador tanto de f1 ,
quanto de f2 , nos pontos x0
e x1 . O erro que cometemos
na interpolação dessas
funções por p1 (x) dependerá
da concavidade da função
original entre x0 e x1 .

OVL232
Erro de interpolação II

A forma exata desse erro será

f (n+1) (ξx )
En (x) = f (x) − pn (x) = (x − x0 )(x − x1 ) . . . (x − xn )
(n + 1)!

onde ξx ∈ [x0 , xn ].
Uma vez que não sabemos o valor de ξx , podemos encontrar
um limitante para o erro:

Mn+1
|En (x)| ≤ |(x − x0 )(x − x1 ) . . . (x − xn )| ·
(n + 1)!

onde Mn+1 = max f (n+1) (x) , I = [x0 , xn ].
x∈I

OVL232
Erro de interpolação III

Comparando a estimativa teórica do erro com o cálculo feito


pelo operador diferenças divididas, temos que

f (n+1) (ξx )
= f [x0 , x1 , . . . , xn , x]
(n + 1)!

Usando essa relação, temos que o limitante estimado para o


erro En (x) é

|En (x)| ≈ |(x − x0 )(x − x1 ) . . . (x − xn )| · (max |dn+1 |)

OVL232
Exemplo de interpolação de Newton I

Seja f (x) dada por

x 0.2 0.34 0.4 0.52 0.6 0.72


f (x) 0.16 0.22 0.27 0.29 0.32 0.37

Queremos obter f (0.47) usando um p2 (x), assim como


estimar o erro nesta interpolação.
O primeiro passo é construir a tabela de diferenças divididas.

OVL232
Exemplo de interpolação de Newton II
x Ordem 0 Ordem 1 Ordem 2 Ordem 3
0.2 0.16
0.4286
0.34 0.22 2.0235
0.8333 -17.8963
0.4 0.27 -3.7033
0.1667 18.2494
0.52 0.29 1.0415
0.3750 -2.6031
0.6 0.32 0.2085
0.4167
0.72 0.37

OVL232
Exemplo de interpolação de Newton II
x Ordem 0 Ordem 1 Ordem 2 Ordem 3
0.2 0.16
0.4286
0.34 0.22 2.0235
0.8333 -17.8963
0.4 0.27 -3.7033
0.1667 18.2494
0.52 0.29 1.0415
0.3750 -2.6031
0.6 0.32 0.2085
0.4167
0.72 0.37

p2 (x) = f (x0 ) + (x − x0 )f [x0 , x1 ] + (x − x0 )(x − x1 )f [x0 , x1 , x2 ]


= 0.27 + 0.1667(x − 0.4) + 0.10415(x − 0.4)(x − 0.52)

f (0.47) ≈ p2 (0.47) = 0.2780

OVL232
Exemplo de interpolação de Newton II

E2 (x) = (x − x0 )(x − x1 )(x − x2 )f [x0 , x1 , x2 , x]

Para estimar o erro, tomamos o valor absoluto máximo das


diferenças divididas de ordem n + 1 (no caso do nosso
exemplo, ordem 3).
Olhando a tabela, vemos que esse valor é 18.2494, que será
tomado como valor máximo de f [x0 , x1 , x2 , x].

|E2 (0.47)| ≈ |(0.47 − 0.4)(0.47 − 0.52)(0.47 − 0.6)| · |18.2494|


≈ 8.303 × 10−3

OVL232
Recursão na interpolação de Newton

Além de oferecer uma estimativa do erro, a fórmula de


Newton traz a vantagem computacional da recursão.
Note que o polinômio é formado por
n
Y
pn+1 (x) = pn (x) + f [x0 , x1 , . . . , xn+1 ] (x − xi )
i=0

n
P f (xk )
sendo f [x0 , x1 , . . . , xn+1 ] = n
k=0
Q
(xk − xj )
j=0
j6=k

OVL232
Interpolação de Newton em Python

def NewtonDifDiv(x, fx, at):


grau = len(x)-1
#
def prodjk(k,n): A função ao lado calcula o
produto = 1 valor de pn (at), sendo at o
for j in range(n+1):
if (j != k): produto *= (x[k] - x[j])
ponto para o qual se deseja
return produto a interpolação. Os n + 1
# valores x e f (x) conhecidos
def prod(n):
produto = 1
são fornecidos na chamada
for i in range(n+1): à função.
produto *= (at - x[i])
return produto Verifique como usamos as
# fórmulas iterativas e
def divdif(n): recursivas anteriores para
soma = 0
for k in range(n+1): escrever essa função.
soma += fx[k]/float(prodjk(k,n))
return soma Teste essa rotina com
#
def pn(x,n): pontos diferentes, usando o
if (n == 0): return fx[0]
return ( pn(x,n-1) + divdif(n)*prod(n-1) ) matplotlib.
#
return pn(at,grau)

OVL232
Interpolação inversa

Dada a tabela
x x0 x1 x2 · · · xn
f (x) y0 y1 y2 · · · yn
queremos obter qual o valor de x̄ que produz um determinado
ȳ .
Há duas formas de resolver o problema:
1 Obter pn (x) que interpola f (x) em x0 , x1 , . . . , xn e, em
seguida, encontrar x̄ tal que pn (x̄) = ȳ .
2 Se f (x) for inversı́vel no intervalo que contém ȳ , pode-se fazer
a interpolação x = f −1 (y ).

OVL232
Fenômeno de Runge

O fenômeno de Runge é um problema de oscilação nas bordas de


um intervalo, que ocorre quando se usa interpolação polinomial com
polinômios de ordem elevada (por exemplo, quando usamos um
número grande de pontos para a interpolação).
−1
Considere a função f (x) = 1 + 25x 2 . Se fizermos a
interpolação desta função em pontos equidistantes entre -1 e 1 tais
que:
2
xi = −1 + (i − 1) , i ∈ {1, 2, · · · n + 1}
n
com um polinômio de grau ≤ n, os valores interpolados oscilam
perto de -1 e 1. Pode ser mostrado que
 
lim max |f (x) − pn (x)| = ∞
n→∞ −1≤x≤1

OVL232
Interpolação por splines

Devido ao Fenômeno de Runge, a interpolação de n pontos por um


polinômio de n graus pode ser desastrosa. Uma alternativa a isso é
interpolar f (x) em grupos de poucos pontos, obtendo-se um polinômio de
menor ordem, e impor condições de continuidade essa interpolação e
outra feita para o grupo de poucos pontos seguintes.

Na figura, interpolamos cada par


de pontos da função por
segmentos de polinômios de grau
menor (respectivamente, 1 e 3).
Essas funções de interpolação
segmentadas são denominadas
splines. Note que a spline cúbica
segue bem a função original.

OVL232
Interpolação por splines vs. interpolação polinomial

OVL232
Interpolação por splines via Python I

O módulo scipy oferece duas formas para realizar a


interpolação por splines: uma procedural (i.e., via função) e
outra orientada a objeto:
import numpy as np
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.pyplot as plt
import scipy.interpolate as itp
import scipy.interpolate as itp
x = np.arange(0,2*np.pi+np.pi/4,2*np.pi/8)
x = np.arange(0,2*np.pi+np.pi/4,2*np.pi/8)
y = np.sin(x)
y = np.sin(x)
tck = itp.splrep(x,y,s=0)
s = itp.InterpolatedUnivariateSpline(x,y)
xnew = np.arange(0,2*np.pi,np.pi/50)
xnew = np.arange(0,2*np.pi,np.pi/50)
ynew = s(xnew)
ynew = itp.splev(xnew,tck,der=0)
plt.figure()
plt.figure()
plt.plot(x,y,’xb’,xnew,ynew,’r’)
plt.plot(x,y,’xb’,xnew,ynew,’r’)
plt.axis([-0.05,6.33,-1.05,1.05])
plt.axis([-0.05,6.33,-1.05,1.05])
plt.show()
plt.show()

OVL232
Interpolação por splines via Python II

Em ambos os casos (seja


interpolação feita
proceduralmente ou via
objeto), teremos a mesma
solução gráfica apresentada ao
lado.

Com base nos dados apresentados no primeiro slide desta aula,


calcule o valor da função de luminosidade geral em MV = 4.47,
usando interpolação por splines.

OVL232

Você também pode gostar