O método de Müller para a determinação de raízes de equações é uma extensão do método da secante e pode ser utilizado para aproximar raízes complexas. A ideia é partir de três aproximações iniciais:
e
e calcular
como a raiz da parábola que passa pelos pontos
e
. Para isso, considere a parábola, dada por:
. As constantes
e
são determinadas pelas equações:
Para determinar
e
, substituímos
nas equações (1) e (2) e dividindo as expressões, respectivamente, por
e
, obtemos:
Fazendo (4) - (5) obtemos
,
e
. Substituindo
na equação (4), obtemos
. Note que as raízes de
são dadas por,
Para evitar possíveis erros de arredondamento racionalizamos o numerador da expressão, ou seja, multiplicamos numerador e denominador por
. Assim obtemos,
No Método de Müller a próxima aproximação da raiz é escolhida de acordo com o sinal do coeficiente
. Esta escolha garante que o denominador será maior em magnitude e resultará na aproximação da raiz mais próxima da raiz anterior. Dessa forma,
sendo
. Portanto, a sequência de aproximações é dada por,
com os coeficientes
e
, calculados com
e
. Note que são necessárias três aproximações iniciais:
e
.
Implemente o método de Müller para resolver uma equação algébrica.
Implemente o método de Müller para resolver uma equação algébrica.
Passo 1
Então, o exercício pede para a gente implementar em código o Método de Müller, que é uma variante do método da secante, mas que ao invés de usar apenas duas aproximações constrói uma parábola passando por três pontos $(x_{n-2},f(x_{n-2}))$, $(x_{n-1},f(x_{n-1}))$ e $(x_{n},f(x_{n}))$ e toma como nova aproximação a raiz dessa parábola mais próxima de $x_n$.
Conteúdo: interpolação por quadrática e raiz de equação algébrica.
O que vamos precisar:
Conteúdo: interpolação por quadrática e raiz de equação algébrica.
O que vamos precisar:
- Programar uma função que receba $f$, três palpites iniciais $(x_0,x_1,x_2)$, tolerância e máximo de iterações.
- Dentro dela, em cada iteração calcular os coeficientes $a,b,c$ da parábola
- Extrair a raiz escolhendo o sinal adequado com \
- Verificar convergência e parar
A partir do próximo passo, a gente já parte pra mão na massa.
Passo 2
Vamos começar definindo as quantidades intermediárias que aparecem na dedução do método:
- Definimos\
- Calculamos as diferenças quocientes (como na secante):\
- Aí o coeficiente $a$ da parábola sai de\
- Depois $b$ e $c$ vêm de\
Passo 3
Com $a,b,c$ em mãos, a gente quer a raiz da parábola
\
As soluções formais seriam
\
mas para evitar cancelamentos numéricos a gente “racionaliza” e chega na fórmula do Müller:
\
Aqui \
garante que o denominador seja o maior em módulo, escolhendo a raiz da parábola mais próxima de $x_2$.
Passo 4
Hora do loop em Python:
- A cada iteração a gente tem três valores $(x_0,x_1,x_2)$, calcula $(h_1,h_2,\delta_1,\delta_2,a,b,c)$, obtém $x_3$.
- Checa se \
; se sim, retorna. - Senão, “desliza” as variáveis: \
e repete. - Se bater no máximo de iterações, avisa que não convergiu.
Passo 5
Agora é só empacotar tudo numa função bem didática em Python. A gente usa o módulo
cmath
pra lidar automático com possíveis raízes complexas.Passo 6
h1 = x1 - x0
h2 = x2 - x1
δ1 = (f(x1) - f(x0)) / h1
δ2 = (f(x2) - f(x1)) / h2
h2 = x2 - x1
δ1 = (f(x1) - f(x0)) / h1
δ2 = (f(x2) - f(x1)) / h2
# coeficientes da parábola
a = (δ2 - δ1) / (h2 + h1)
b = a*h2 + δ2
c = f(x2)
# discriminante e sinal
disc = cmath.sqrt(b*b - 4*a*c)
signo = b/abs(b) if b != 0 else 1
# próximo palpite pelo Müller
denom = b + signo*disc
if denom == 0:
raise ZeroDivisionError("Denominador zero no método de Müller")
dx = -2*c / denom
x3 = x2 + dx
# critério de parada
if abs(x3 - x2) < tol:
return x3, i
# prepara próxima iteração
x0, x1, x2 = x1, x2, x3
# se saiu do loop sem convergir
raise RuntimeError(f"Método de Müller não convergiu em {maxiter} iterações")
Resposta
import cmath
def muller(f, x0, x1, x2, tol=1e-8, maxiter=50):
"""
Método de Müller para achar uma raiz de f(z)=0,
permitindo solução complexa.
Entrada:
f = função que retorna número (real ou complexo)
x0,x1,x2 = 3 palpites iniciais (podem ser complexos)
tol = tolerância para |x3 - x2|
maxiter = número máximo de iterações
Retorna:
raiz aproximada x, número de iterações realizadas
"""
for i in range(1, maxiter+1):