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: x0, x1 e x2 e calcular x3 como a raiz da parábola que passa pelos pontos (x0, f(x0)),(x1, f(x1)) e (x2, f(x2)). Para isso, considere a parábola, dada por: p(x)=a(x-x2)^2+b(x-x2)+c. As constantes a, b e c são determinadas pelas equações:
Para determinar nf(x0)=a(x0-x2)^2+b(x0-x2)+c f(x1)=a(x1-x2)^2+b(x1-x2)+c f(x2)=a(x2-x2)^2+b(x2-x2)+c Longrightarrow c=f(x2) e a, substituímos b nas equações (1) e (2) e dividindo as expressões, respectivamente, por c e (x0-x2), obtemos:
Fazendo (4) - (5) obtemos (x1-x2), n& f(x0)-f(x2)x0-x2=a(x0-x2)+b, n& f(x1)-f(x2)x1-x2=a(x1-x2)+b e a=q0-q1x0-x1. Substituindo com q0=f(x0)-f(x2)x0-x2 na equação (4), obtemos q1=f(x1)-f(x2)x1-x2. Note que as raízes de a são dadas por,
b=q0(x2-x1)+q1(x0-x2)x0-x1
Para evitar possíveis erros de arredondamento racionalizamos o numerador da expressão, ou seja, multiplicamos numerador e denominador por p(x). Assim obtemos,
x-x2=-b pm raizb^2-4 a c2 a
No Método de Müller a próxima aproximação da raiz é escolhida de acordo com o sinal do coeficiente -b mp raizb^2-4 a c. 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,
alpha1-x2=-2 cb+raizb^2-4 a c e alpha2-x2=-2 cb-raizb^2-4 a c
sendo b. Portanto, a sequência de aproximações é dada por,
x3=x2-2 cb+sgn(b) raizb^2-4 a c
com os coeficientes sgn(b)=b /|b| e xn+1=xn-2 cb+sgn(b) raizb^2-4 a c, para n=2,3, ldots , calculados com a, b e c. Note que são necessárias três aproximações iniciais: x2=xn, x1=xn-1 e x0=xn-2.
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:
  • 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 \ (xn-2,f(xn-2))
  • 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:
  1. Definimos\ h1 = x1 - x0, h2 = x2 - x1
  2. Calculamos as diferenças quocientes (como na secante):\ de
  3. Aí o coeficiente $a$ da parábola sai de\ a
  4. Depois $b$ e $c$ vêm de\ a = de

Passo 3

Com $a,b,c$ em mãos, a gente quer a raiz da parábola
\ a,b,c
As soluções formais seriam
\ p(x) = a,(x - x2)^2 + b,(x - x2) + c = 0
mas para evitar cancelamentos numéricos a gente “racionaliza” e chega na fórmula do Müller:
\ x - x2 = -b pm raizb^2 - 4ac2a,
Aqui \ x3 = x2 ;-;2,c,b + sgn(b),raizb^2 - 4,a,c, 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 \ (x0,x1,x2); se sim, retorna.
  • Senão, “desliza” as variáveis: \ (h1,h2,de 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
    # 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):

Exercícios relacionados