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 ε=105\varepsilon = 10^{-5} no exemplo do post anterior, precisamos de 17 iterações. Para ε=1010\varepsilon = 10^{-10}, seriam 33. O número de iterações cresce com log2(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+x6=0x^2 + x - 6 = 0:

  • x=6x2x = 6 - x^2, ou seja, φ1(x)=6x2\varphi_1(x) = 6 - x^2
  • x=6xx = \sqrt{6 - x}, ou seja, φ2(x)=6x\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+1xkxk+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.

Método do Ponto Fixo - x² + x − 6 = 0 (raiz ξ = 2)
Diagrama de teia: a sequência xk+1 = φ(xk) encontra onde φ(x) cruza y = x
0123401234y = xφ(x)ξ = 2x₀
x₀ (inicial)
3.000000
xₖ (k = 0)
3.000000
|xₖ − ξ| (erro)
1.000000
|φ′(2)| = ¼ < 1 -> converge
Iteração 0 / 8
φ(x) y = x raiz ξ = 2 teia xₖ₊₁ = φ(xₖ)

Alterne entre as duas funções de iteração para a mesma equação x2+x6=0x^2 + x - 6 = 0. Com φ2(x)=6x\varphi_2(x) = \sqrt{6-x} a sequência espirala para ξ=2\xi = 2. Com φ1(x)=6x2\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
  • x0Ix_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)=6x\varphi_2(x) = \sqrt{6-x}:

φ2(x)=126x    φ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)=6x2\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 ε=105\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 por si só, é que ele serve de base para métodos mais rápidos.