1. Introdução

Apesar dos livros de análise numérica se dividirem em distintas seções para representar diversas técnicas de resolução de problemas, problemas numéricos são, geralmente, reduzidos aos modelos apresentados nos posts anteriores (busca de raízes, solução de sistemas, regressão e interpolação). Os métodos de integração e diferenciação numérica são casos específicos de interpolação de funções.

Uma vez que na interpolação nós nos estudamos os casos onde a função é representada por uma tabela de valores, na derivação numérica nós buscamos ajustar a derivada da função a partir de valores gerados pela função em si. Para observarmos a relação entre a derivação numérica e a interpolação, inicialmente veremos como obter a diferenciação numérica a partir dos dados. Em seguida, estudaremos como é feita a derivação numérica de uma função a partir dela mesma.

 

2. Derivação Numérica dos Dados

Quando uma função é representada por uma tabela de valores, a abordagem mais óbvia é diferenciar a fórmula interpoladora de Lagrange, apresentada no post 3.1.3. Isso nos dá que

$$ f^{(k)}(x) = \sum_{j=1}^{n} l_{j}^{(k)}(x) f(a_j) + \frac{d^k}{dx^k} \left[ \frac{p_n(x)}{n!} f^{(n)}(\xi) \right] = y^{(k)}(x) + \frac{d^k}{dx^k} \left[ E(x) \right] $$

Em particular, para , temos

$$ f'(x) = \sum_{j=1}^{n} l’_j(x) f(a_k) + \frac{d}{dx} \left[ \frac{p_n(x)}{n!} f^{(n)}(\xi) \right] $$

onde a derivada pode ser facilmente obtida pela interpolação de Lagrange, conforme mostramos no post 3.1.3. A determinação do erro é obtida por

$$ \frac{d^k}{dx^k} \left[ E(x) \right] = \frac{f^{(n)}(\xi)}{(n – k)!} \prod_{j=1}^{n-k} (x – \eta_j) $$

onde os pontos distintos são independentes de e são conhecidos nos intervalos

$$ a_j < \eta_j < a_{j+k} $$

em , é o menos intervalo que contém e . Se, no caso dos valores da função serem dados nos pontos de dados, são dados os valores das funções derivadas em alguns pontos. Assim, podemos derivar os coeficientes pela fórmula

$$ f^{(k)}(x) \approx \sum_{j=1}^{n} \sum_{i=0}^{m_j} w_{ij}^{(k)}(x) f^{(i)}(a_j) $$

Uma abordagem alternativa para determinar a diferenciação numérica de dados para aproximação da primeira e segunda derivada é computar a interpolação spline cúbica e diferenciá-la. Para qualquer valor de , nós podemos determinar dois nós e tal que . Assim, e , onde é o pedaço da spline interpoladora — um polinômio de terceiro grau definido em . A partir do que foi demonstrado no post 3.1.7, assumimos que, assintóticamente, temos , a distância máxima entre dois nós da spline,

$$ max |f^{(k)}(x) – S^k(x) | = O(h^{4-k}) $$

para . Isso indica que a primeira e a segunda derivada da spline interpoladora é aproximadamente a derivada da função. Podemos ver isso mais claramente quando assumimos que os espaços são igualmente espaçados nos pontos amostrados. Temos, então, que

$$ y^{(k)}(x) = \frac{1}{h^k} \sum_{j=1}^{n} l_j^{(k)}(m) f(a_i) $$

onde , a diferenciação de em relação à vem do fato de que

$$ \frac{dy}{dx} = \frac{dy}{dm} \frac{dm}{dx} = \frac{1}{m} \frac{dy}{dm} $$

De formula similar, podemos derivar outras fórmulas de interpolação e obter a derivada como a diferença dos valores interpolados. Por exemplo, quando usamos a fórmula de Newton, temos que

$$ \frac{d^k}{dx^k} y(a_0 + hm) = \frac{1}{h^k} \frac{d^k}{dm^k} y(a_0 + hm) = \frac{1}{h^k} \sum_{j=0}^{n} \frac{d^k}{dm^k} \binom{m}{j} \Delta^j f_0 = \frac{1}{h^k} \sum_{j=k}^{n} \frac{d^k}{dm^k} \binom{m}{j} \Delta^j f_0 $$

O aparecimento do fator torna explícito o fato de que a diferenciação numérica consiste na aproximação da função derivada por divisão de pequenos intervalos. Portanto, deve ser um valor pequeno o suficiente para, considerando um erro de aproximação tolerado — lembrando que na solução analítica temos .

 

3. Derivação Numérica de Funções

Quando precisamos computar a derivada da uma função que pode ser avaliada em qualquer ponto em um dado intervalo , podemos construir os pontos utilizados na interpolação dessa função derivada. Se e estão contidos em , utilizamos a expansão da série de Taylor:

$$ f(x+h) = f(x) + h f'(x) + \frac{h^2}{2} f”(x) + \cdots $$

e

$$ f(x-h) = f(x) – h f'(x) + \frac{h^2}{2} f”(x) – \cdots $$

Subtraindo essas duas equações e dividindo por , os temos restantes são

$$ f'(x) = \frac{f(x+h) – f(x-h)}{2h} + \sum_{i=1}^{\infty} \frac{f^{(2i+1)}(x)}{(2i+1)!} h^{2i} $$

substituindo esse na série de Taylor e isolando , temos uma aproximação para a segunda derivada

$$ f”(x) = \frac{f(x+h) – 2f(x) + f(x-h)}{h^2} + \sum_{i=1}^{\infty} \frac{2 f^{(2i+2)}(x)}{(2i+2)!} h^{2i} $$

Portanto, para um suficiente pequeno, temos que o somatório de valores muito pequenos consiste de um resíduo, o que nos permite aproximar a primeira e a segunda derivada por

$$ f'(x) \approx \frac{f(x+h) – f(x-h)}{2h} $$

e

$$ f”(x) \approx \frac{f(x+h) – 2f(x) + f(x-h)}{h^2} $$

Assim, nossa estratégia consiste em avaliar as funções no ponto a partir de um valor suficientemente pequeno para o problema dado.

Note que podemos substituir e na série de Taylor para obter , que por sua vez pode ser utilizada para obter e assim sucessivamente até obtermos a derivada desejada. Note também que o resultado truncado da primeira e segunda derivada possui erro . Contudo, utilizando mais pontos, podemos ter uma aproximação mais acurada, com erro . Isto é, em vez de utilizarmos

$$ f'(x) = \frac{f(x+h) – f(x-h)}{2h} + O(h) $$

podemos utilizar a expressão

$$ f'(x) = \frac{-f(x+2h) + 4f(x+h) – 3f(x)}{2h} + O(h^2) $$

Observe que na equação acima utilizamos 3 pontos para obter a primeira derivada. Esse segundo termo vêm da utilização de na fórmula de Taylor, isolando-se . Além disso, utilizamos os pontos , e . A utilização de pontos sucessivos ao ponto de avaliação é chamada de diferenças divididas finitas progressivas. Contudo, podemos utilizar os pontos anteriores (regressiva) ou ambos (centrada). Quanto mais próximo do ponto de avaliação, mais precisa é a aproximação. Por isso, as diferenças divididas finitas centradas possuem maior acurácia.

Nas próximas subseções, listamos as fórmulas das primeiras quadro derivadas numéricas utilizando as três escolhas de pontos. Para facilitar a notação, definimos como e .

 

3.1. Diferença Dividida Finita Progressiva

  • Primeira derivada:
    • :
    • :
  • Segunda derivada:
    • :
    • :
  • Terceira derivada:
    • :
    • :
  • Quarta derivada:
    • :
    • :

 

3.2. Diferença Dividida Finita Regressiva

  • Primeira derivada:
    • :
    • :
  • Segunda derivada:
    • :
    • :
  • Terceira derivada:
    • :
    • :
  • Quarta derivada:
    • :
    • :

 

3.3. Diferença Dividida Finita Centrada

  • Primeira derivada:
    • :
    • :
  • Segunda derivada:
    • :
    • :
  • Terceira derivada:
    • :
    • :
  • Quarta derivada:
    • :
    • :

 

4. Implementação

Conforme demonstrado, as diferenças finitas centradas produzem fórmulas mais acuradas. Sendo assim, o ideal é sempre implementarmos essas fórmulas. Portanto, seguem abaixo a implementação das funções diff1, diff2, diff3 e diff4, responsáveis por calcular a primeira, segunda, terceira e quarta derivada, respectivamente. No exemplo de utilização, que pode ser encontrado em http://www.sawp.com.br/code/derivatives/numerical_derivatives.py, observamos um caso em que a escolha de repercurte num problema as vezes comum na utilização de métodos numéricos: o problema do truncamento de ponto flutuante. No caso, vemos que a derivada de quarta ordem produz um erro muito grande, à limitação da precisão computacional. Assim, nos post seguinte demonstramos como esse problema pode ser minimizado.

def diff1(f, x, h=0.0001):
    """
    Return the 1st derivative function evaluated in point x.

    diff_f_xi = diff1(fun, x, h=0.001)

    INPUT:
      * f: function to derivate
      * x: evaluation point
      * h: step size

    return: f'(X=x)

    Author: Pedro Garcia [sawp@sawp.com.br]
    see: http://www.sawp.com.br

    License: Creative Commons
             http://creativecommons.org/licenses/by-nc-nd/2.5/br/

    Jun 2012
    """
    a = -f(x + 2 * h)
    b = 8 * f(x + h)
    c = -8 * f(x - h)
    d = f(x - 2 * h)
    diff = (a + b + c + d) / (12 * h)
    return diff
def diff2(f, x, h=0.00001):
    """
    Return the 2nd derivative function evaluated in point x.

    diff_f_xi = diff2(fun, x, h=0.001)

    INPUT:
      * f: function to derivate
      * x: evaluation point
      * h: step size

    return: f"(X=x)

    Author: Pedro Garcia [sawp@sawp.com.br]
    see: http://www.sawp.com.br

    License: Creative Commons
             http://creativecommons.org/licenses/by-nc-nd/2.5/br/

    Jun 2012
    """
    a = -f(x + 2 * h)
    b = 16 * f(x + h)
    c = -30 * f(x)
    d = 16 * f(x - h)
    e = -f(x - 2 * h)
    diff = (a + b + c + d + e) / (12 * h ** 2)
    return diff
def diff3(f, x, h=0.00001):
    """
    Return the 3rd derivative function evaluated in point x.

    diff_f_xi = diff3(fun, x, h=0.001)

    INPUT:
      * f: function to derivate
      * x: evaluation point
      * h: step size

    return: f"'(X=x)

    Author: Pedro Garcia [sawp@sawp.com.br]
    see: http://www.sawp.com.br

    License: Creative Commons
             http://creativecommons.org/licenses/by-nc-nd/2.5/br/

    Jun 2012
    """
    a = -f(x + 3 * h)
    b = 8 * f(x + 2 * h)
    c = -13 * f(x + h)
    d = 13 * f(x - h)
    e = -8 * f(x - 2 * h)
    ff = f(x - 3 * h)
    diff = (a + b + c + d + e + ff) / (8 * h ** 3)
    return diff
def diff4(f, x, h=0.0001):
    """
    Return the 4th derivative function evaluated in point x.

    diff_f_xi = diff4(fun, x, h=0.001)

    INPUT:
      * f: function to derivate
      * x: evaluation point
      * h: step size

    return: f""(X=x)

    Author: Pedro Garcia [sawp@sawp.com.br]
    see: http://www.sawp.com.br

    License: Creative Commons
             http://creativecommons.org/licenses/by-nc-nd/2.5/br/

    Jun 2012
    """
    a = f(x)
    b = -4 * f(x - h)
    c = 6 * f(x - 2 * h)
    d = -4 * f(x - 3 * h)
    e = f(x - 4 * h)
    diff = (a + b + c + d + e) / (h ** 4)
    return diff

 

Este documento é disponível sob a licença Creative Commons. As regras dos direitos de cópia deste conteúdo estão acessíveis em http://creativecommons.org/licenses/by-nc-nd/2.5/br/.

References

[1] Anthony Ralston and Philip Rabinowitz, A First Course in Numerical Analysis (2nd ed.), McGraw-Hill and Dover, (2001).
[2] N.B Franco, Cálculo Numérico, Pearson Prentice Hall (2006).
</fieldset>