"Nenhuma grande descoberta jamais foi feita sem um palpite ousado." (Isaac Newton)
Objetivos de aprendizagem¶
Compreender o funcionamento do método de Newton, seu algoritmo e as condições necessárias para sua aplicação;
Aplicar o método de Newton na resolução de equações não lineares;
Analisar o comportamento da convergência do método de Newton, sua precisão e limitações;
Reconhecer variantes do Método de Newton para problemas de otimização, bem como o Método de Halley.
Método de Newton: Sair pela Tangente sem Perder o Rumo¶
O método de Newton, também conhecido como método de Newton-Raphson, é uma técnica iterativa poderosa para encontrar aproximações das raízes de equações não lineares. Sua ideia central é usar a reta tangente à curva da função em um ponto de aproximação inicial para estimar onde essa reta cruza o eixo , fornecendo assim uma nova aproximação. Esse processo é repetido até que a diferença entre iterações sucessivas seja suficientemente pequena, indicando convergência para uma raiz.
Apesar de ser um método rápido e eficiente com convergência quadrática quando a aproximação inicial está suficientemente próxima da raiz, ele também apresenta desafios. Ele exige que a derivada esteja disponível e bem comportada. Além disso, se o ponto inicial estiver longe da raiz, ou se a função tiver pontos de inflexão ou derivadas próximas de zero, o método pode divergir ou oscilar. Por isso, é comum combiná-lo com outras técnicas, como a inspeção gráfica ou métodos mais estáveis (como bisseção) para estimar bons pontos iniciais.

Explicação do algoritmo¶
O processo iterativo do método é dado pela seguinte função de iteração:
onde:
é a aproximação atual.
é o valor atual da função.
é o valor atual da primeira derivada da função.
A ideia é que a interseção da tangente à curva no ponto com o eixo forneça uma nova aproximação . O Método de Newton é uma ferramenta essencial no arsenal de métodos numéricos, oferecendo uma abordagem eficiente e poderosa para a solução de uma ampla variedade de problemas matemáticos.
O algoritmo funciona da seguinte forma:
Inicialize (chute inicial)
Para de 1 até :
a. Calcule
b. Calcule (derivada da função no ponto )
c. Se , retorne erro (derivada zero, o método falha)
d. Calcule (como o processo iterativo acima)
e. Se , então a solução foi encontrada com a precisão desejada. Retorne .
Se o número máximo de iterações for atingido, retorne a última aproximação .
Um caso clássico¶
Considere que desejamos calcular a raiz enésima de um número real positivo , ou seja, . Podemos fazer isto utilizando o método de Newton de uma forma muito simples, mas “diferente”. Em primeiro lugar, note que buscamos a solução da equação , tal que
Calculando derivada, obtemos
Utilizando ambas na função de iteração do método de Newton, chegamos a
que, finalmente, pode ser simplificada no processo iterativo
Se um “palpite” razoável for dado para , a convergência para o valor real será rápida.
Exemplo numérico¶
Vamos calcular – claramente, e – com um chute inicial .
A função de iteração para este exemplo é dada por
Partindo de , desenvolvemos as seguintes iterações
Com apenas 4 iteradas chegamos à resposta.
Implementação do algoritmo¶
No algoritmo proposto abaixo, a função newton requererá 5 argumentos:
a estimativa inicial, representada pela variável
x0;a função propriamente dita, representada por
f;a derivada , representada por
df;o erro relativo assumido, representado por
tol;o número máximo de iterações para tentativa de solução, representado por
nmax.
Source
import inspect, re, numpy as np
from matplotlib.pyplot import plot
from prettytable import PrettyTable as pt
def newton(x0,f,df,tol,N):
"""Algoritmo para determinação de raízes pelo método de Newton.
Parâmetros:
x0: estimativa inicial
f: string dependendo de uma variável, i.e., a função-alvo
(e.g., 'x**2 - 1', 'x**2*cos(x)', etc.)
df: string dependendo de uma variável, i.e., a derivada da função-alvo
tol: erro desejado (tolerância)
N: número máximo de iterações a repetir
Retorno:
x: aproximação para a raiz da função
"""
# construtor de tabela
table = pt()
# substitui expressões da string pelas chamadas das funções do numpy
f = re.sub('(sin|sinh|cos|cosh|tan|tanh|exp|log|sqrt|log10|arcsin|arccos|arctan|arcsinh|arccosh|arctanh)', r'np.\1', f)
df = re.sub('(sin|sinh|cos|cosh|tan|tanh|exp|log|sqrt|log10|arcsin|arccos|arctan|arcsinh|arccosh|arctanh)', r'np.\1', df)
# identifica a variável independente em f
var = re.search(r'([a-zA-Z][\w]*) ?([\+\-\/*]|$|\))', f).group(1)
# cria função
f = eval('lambda ' + var + ' :' + f)
# checa se a função é de uma variável, senão lança erro
try:
len(inspect.getfullargspec(f).args) - 1 > 0
except:
raise ValueError('O código é válido apenas para uma variável.')
finally:
# cria função derivada
df = eval('lambda ' + var + ' :' + df)
it = 0 # contador de iteracoes
# cabeçalho de tabela
table.field_names = ['i','x','f(x)','f\'(x)','ER']
# imprime estimativa inicial
print(f'Estimativa inicial: x0 = {x0:.6f}\n')
# Loop
for i in range(0,N):
x = x0 - f(x0)/df(x0) # funcao de iteracao
e = abs(x-x0)/abs(x) # erro
# tabela
# impressão de tabela
table.add_row([i,np.round(x,8),np.round(f(x),8),np.round(df(x),4),f'{e:e}'])
table.align = 'c';
if e < tol:
break
x0 = x
print(table)
if i == N:
print(f'Solução não obtida em {N:d} iterações')
else:
print(f'Solução obtida: x = {x:.6f}')
return xPlayground interativo¶
Utilize o playground interativo abaixo para testar o método da bisseção para funções não lineares quaisquer. Como dado de entrada para , utilize funções escritas nos moldes de Python científico como um tipo str. Para os parâmetros do intervalo inicial e de erro, utilize float.
Aplicações¶
Exemplo: Resolva o problema , para , no intervalo e .
# Chamada da função
xm = newton(-0.1,
'-arccos(x) + 4*sin(x) + 1.7',
'4*cos(x) - 1/(1 - x**2)**1/2',
1e-3,
30)Estimativa inicial: x0 = -0.100000
+----+-------------+-------------+--------+--------------+
| i | x | f(x) | f'(x) | ER |
+----+-------------+-------------+--------+--------------+
| 0 | 0.00656144 | 0.16201076 | 3.4999 | 1.624055e+01 |
| 1 | -0.03972877 | -0.06940881 | 3.4961 | 1.165156e+00 |
| 2 | -0.01987529 | 0.02983116 | 3.499 | 9.989026e-01 |
| 3 | -0.02840088 | -0.01278928 | 3.498 | 3.001876e-01 |
| 4 | -0.02474469 | 0.00548778 | 3.4985 | 1.477564e-01 |
| 5 | -0.02631332 | -0.0023538 | 3.4983 | 5.961326e-02 |
| 6 | -0.02564047 | 0.00100976 | 3.4984 | 2.624162e-02 |
| 7 | -0.02592911 | -0.00043314 | 3.4983 | 1.113178e-02 |
| 8 | -0.02580529 | 0.00018581 | 3.4983 | 4.798023e-03 |
| 9 | -0.0258584 | -7.97e-05 | 3.4983 | 2.053976e-03 |
| 10 | -0.02583562 | 3.419e-05 | 3.4983 | 8.818630e-04 |
+----+-------------+-------------+--------+--------------+
Solução obtida: x = -0.025836
Exemplo: Resolva o problema , para , no intervalo e .
Como no exemplo anterior, para utilizarmos o método de Newton é preciso saber a derivada da função . Vamos encontrá-la utilizando o módulo de computação simbólica sympy.
# Importa variável z como símbolo
from sympy.abc import z
import sympy as sym
# Derivada
dh = sym.diff(-z/(1 - 2*z) - sym.tan(z+1))
# Impressão
print(dh)-2*z/(1 - 2*z)**2 - tan(z + 1)**2 - 1 - 1/(1 - 2*z)
A partir daí, utilizamos a expressão normalmente na função.
zm = newton(5,
'z/(1 - 2*z) - tan(z+1)',
'-2*z/(1 - 2*z)**2 - tan(z + 1)**2 - 1 - 1/(1 - 2*z)',
1e-5,30)Estimativa inicial: x0 = 5.000000
+---+------------+------------+---------+--------------+
| i | x | f(x) | f'(x) | ER |
+---+------------+------------+---------+--------------+
| 0 | 4.75884953 | 0.01963205 | -1.3483 | 5.067411e-02 |
| 1 | 4.77341064 | 0.00056164 | -1.3262 | 3.050462e-03 |
| 2 | 4.77383412 | 1.173e-05 | -1.3256 | 8.870850e-05 |
| 3 | 4.77384296 | 2.4e-07 | -1.3256 | 1.852869e-06 |
+---+------------+------------+---------+--------------+
Solução obtida: x = 4.773843
Compare a quantidade de iterações obtidas com o mesmo exemplo resolvido com o algoritmo da bisseção.
Derivação para otimização¶
O método de Newton, originalmente desenvolvido para encontrar raízes de equações, pode ser adaptado com grande eficácia para problemas de otimização. Nesse contexto, seu objetivo é encontrar os pontos críticos de uma função — ou seja, valores onde a derivada é nula e que podem corresponder a mínimos, máximos ou pontos de sela. A ideia central é usar uma aproximação quadrática da função por meio da série de Taylor de segunda ordem. O processo pode ser resumido nos passos a seguir:
Função Objetivo (FO): seja uma função escalar diferenciável cujo mínimo queremos encontrar.
Expansão de Taylor de Segunda Ordem: expandimos em torno de um ponto usando a série de Taylor até a segunda ordem:
onde é a primeira derivada (gradiente) de em e é a segunda derivada (Hessiana) de em .
Condição de otimização: para encontrar o ponto que minimiza , devemos encontrar um ponto onde a derivada da função seja zero. Definimos a direção de descida como :
Derivada da expansão: para minimizar , tomamos a derivada da expressão acima em relação a e igualamos a zero:
Uma vez que não depende de , é uma constante. Assim obtemos:
_solução para a direção : resolvendo para , temos:
Atualização da Iteração: a próxima aproximação é obtida somando ao ponto atual :
A derivada indica a inclinação da função em . A segunda derivada fornece informações sobre a curvatura da função. Se , estamos em um ponto onde a função está curvando para cima (mínimo local), enquanto indica um ponto onde a função está curvando para baixo (máximo local). O passo determina a magnitude e a direção do ajuste necessário para aproximar-se do ponto de mínimo (ou máximo).
Método de Halley¶
O método de Halley é uma extensão do método de Newton e utiliza até a terceira derivada da função. Enquanto o método de Newton tem convergência quadrática, o método de Halley converge mais rapidamente e alcança convergência cúbica, pois usa mais informações sobre a curvatura da função. De maneira similar ao que já fizemos, vamos derivar a fórmula partindo diretamente da expansão de Taylor:
Expansão de Taylor: expandimos a função em torno de um ponto :
Estimativa da raiz: supondo que é a nova estimativa da raiz, então queremos . Substituindo na expansão de Taylor e igualando a zero, temos:
Isolamento do passo: a solução para (que nos dá a atualização para ) é dada pela fórmula:
Iteração do Método de Halley: a fórmula iterativa do método de Halley é então:
As vantagens do método de Halley sobre o método de Newton são a taxa de convergência e o alcance de uma solução mais precisa com menos iterações em comparação. Por outro lado, o cálculo das derivadas de ordem superior pode ser computacionalmente custoso e complexo, especialmente para funções complicadas. A precisão do método também depende da precisão das derivadas de segunda e terceira ordem. Portanto, erros nessas derivadas podem afetar a convergência e a precisão da solução.
Problemas propostos¶
Crie um código genérico que implemente o algoritmo do método de Newton de modo que a derivada seja calculada diretamenta por computação simbólica, sem intervenção manual, quando for possível. Dica: use
sympy.lambdify.Faça uma implementação do método de Newton para otimização e uma para o método de Halley. Em seguida, incorpore a capacidade de cálculo das derivadas de maneira automática.