No post anterior eu implementei a bissecção, aquele método que divide o intervalo ao meio repetidamente até se aproximar da raiz. Ele é bem útil em muitos casos, pois sempre converge e consegue prever quantas iterações vai precisa.

O único problema dele é ser lento. Cada iteração reduz o erro pela metade, nem mais, nem menos, não importa o formato da função. A curva pode ser quase reta perto da raiz, o que daria pra convergir em 3 passos, mas a bissecção não sabe disso. Ela divide, olha o sinal, e divide de novo.

Para ε=10−5\varepsilon = 10^{-5} no exemplo do post anterior, precisamos de 17 iterações. Para ε=10−10\varepsilon = 10^{-10}, seriam 33. O número de iterações cresce com log⁡2(1/ε)\log_2(1/\varepsilon), cada casa decimal a mais custa 3,3 iterações.

O Método do Ponto Fixo é o próximo algoritmo. Troca a garantia de convergencia por velocidade na convergencia.

Método do Ponto Fixo (MPF)

A equação f(x)=0f(x) = 0 pode ser reescrita como x=φ(x)x = \varphi(x) de infinitas formas. Por exemplo, para x2+x−6=0x^2 + x - 6 = 0:

  • x=6−x2x = 6 - x^2, ou seja, φ1(x)=6−x2\varphi_1(x) = 6 - x^2
  • x=6−xx = \sqrt{6 - x}, ou seja, φ2(x)=6−x\varphi_2(x) = \sqrt{6-x}

Ambas são algebricamente equivalentes, porém o comportamento são diferentes.

Se ξ\xi é raiz de ff, então f(ξ)=0f(\xi) = 0, logo φ(ξ)=ξ\varphi(\xi) = \xi. A raiz que buscamos é um ponto fixo de φ\varphi, ou seja, o ponto onde a curva y=φ(x)y = \varphi(x) cruza a reta y=xy = x.

O algoritmo é: dado um chute inicial x0x_0, gera-se a sequência {xk}\{x_k\} pela relação de recorrência

xk+1=φ(xk)x_{k+1} = \varphi(x_k)

repetindo até o critério de parada:

∣xk+1−xk∣∣xk+1∣<ε\frac{|x_{k+1} - x_k|}{|x_{k+1}|} < \varepsilon
1
# Pseudo-código do Método do Ponto Fixo
2
3
x = x₀
4
enquanto verdadeiro:
5
x₁ = φ(x)
6
se |x₁ - x| / |x₁| < ε:
7
retorna x₁
8
x = x₁

Visualizando geometricamente

Uma forma interessante de ver o que acontece é plotar φ(x)\varphi(x) e a reta y=xy = x no mesmo gráfico. A raiz ξ\xi é o ponto de interseção entre as duas curvas, porque nesse ponto φ(ξ)=ξ\varphi(\xi) = \xi.

A sequência de iterações aparece como um caminho em espiral entre as duas curvas, você sobe até φ(xk)\varphi(x_k), depois anda horizontalmente até a diagonal y=xy = x, e aí esse ponto é xk+1x_{k+1}. Se a curva de φ\varphi “aperta” o caminho a cada passo, o método converge. Se ela “abre”, diverge.

0123401234y = xφ(x)ξ = 2x₀
x₀ = 3.000000x0 = 3.000000|xₖ − ξ| = 1.000000
|φ′(2)| = ¼ < 1 -> converge
iteração 0 de 8
Método do ponto fixo para x² + x − 6 = 0. Diagrama de teia: a sequência xk+1 = φ(xk) procura o ponto onde φ(x) cruza y = x, aqui em ξ = 2.━ φ(x)╌ y = x● raiz ξ = 2━ teia xₖ₊₁ = φ(xₖ)

Alterne entre as duas funções de iteração para a mesma equação x2+x−6=0x^2 + x - 6 = 0. Com φ2(x)=6−x\varphi_2(x) = \sqrt{6-x} a sequência espirala para ξ=2\xi = 2. Com φ1(x)=6−x2\varphi_1(x) = 6 - x^2 ela explode, veja o valor de xkx_k saltando para fora da região logo na segunda iteração.

Quando converge?

O Teorema do Ponto Fixo dá o critério, se ambas as condições abaixo são satisfeitas:

  • ∣φ′(x)∣≤M<1|\varphi'(x)| \leq M < 1 para todo xx em um intervalo II contendo ξ\xi
  • x0∈Ix_0 \in I

então a sequência {xk}\{x_k\} converge para ξ\xi.

Ou seja, a derivada de φ\varphi na vizinhança da raiz precisa ser menor que 1 em módulo. Quanto menor ∣φ′(ξ)∣|\varphi'(\xi)|, mais rápida a convergência.

Verificando o exemplo:

Para φ2(x)=6−x\varphi_2(x) = \sqrt{6-x}:

φ2′(x)=−126−x  ⟹  ∣φ2′(2)∣=14<1\varphi_2'(x) = -\frac{1}{2\sqrt{6-x}} \implies |\varphi_2'(2)| = \frac{1}{4} < 1

A cada iteração o erro cai por um fator de 0,25. Convergência linear com taxa 14\frac{1}{4}.

Para φ1(x)=6−x2\varphi_1(x) = 6 - x^2:

φ1′(x)=−2x  ⟹  ∣φ1′(2)∣=4>1\varphi_1'(x) = -2x \implies |\varphi_1'(2)| = 4 > 1

A cada iteração o erro multiplica por 4. Diverge.

A forma geral de toda função de iteração válida é

φ(x)=x+A(x)⋅f(x)\varphi(x) = x + A(x) \cdot f(x)

com A(ξ)≠0A(\xi) \neq 0.

Implementando em Python

ponto-fixo.py
1
import math
2
3
def phi(x):
4
return math.sqrt(6 - x)
5
6
def ponto_fixo(phi, x0, eps=1e-5):
7
x = x0
8
k = 0
9
while True:
10
x_novo = phi(x)
11
erro = abs(x_novo - x) / abs(x_novo)
12
k += 1
13
print(f"Iteração {k:2d}: x = {x_novo:.8f}, erro = {erro:.2e}")
14
if erro < eps:
15
return x_novo
16
x = x_novo
17
18
raiz = ponto_fixo(phi, x0=3)
19
print(f"\nRaiz encontrada: {raiz:.6f}")
1
Iteração 1: x = 1.73205081, erro = 7.32e-01
2
Iteração 2: x = 2.06590154, erro = 1.62e-01
3
Iteração 3: x = 1.98345619, erro = 4.16e-02
4
Iteração 4: x = 2.00413168, erro = 1.03e-02
5
Iteração 5: x = 1.99896681, erro = 2.58e-03
6
Iteração 6: x = 2.00025828, erro = 6.46e-04
7
Iteração 7: x = 1.99993543, erro = 1.61e-04
8
Iteração 8: x = 2.00001614, erro = 4.04e-05
9
Iteração 9: x = 1.99999596, erro = 1.01e-05
10
Iteração 10: x = 2.00000101, erro = 2.52e-06
11
12
Raiz encontrada: 2.000001

O padrão é claro é: o erro cai por um fator de aproximadamente 4 a cada iteração, exatamente o que ∣φ′(2)∣=0,25|\varphi'(2)| = 0,25 prevê. São 10 iterações para ε=10−5\varepsilon = 10^{-5}.

Vantagens e limitações

O método do ponto fixo tem convergência linear com taxa ∣φ′(ξ)∣|\varphi'(\xi)|. A bissecção também tem convergência linear com taxa 12\frac{1}{2}, mas sempre converge.

A vantagem real do MPF não é velocidade, é que ele serve de base para métodos mais rápidos, como o Método de Newton, que usa exatamente essa estrutura para forçar φ′(ξ)=0\varphi'(\xi) = 0 e obter convergência quadrática.