Fixed-Point Iteration Example — Cobweb Diagram¶
This example finds the fixed point of \(g(x) = \cos(x)\), known as the Dottie number (\(x^* \approx 0.7391\)), by solving:
\[h(x) = \cos(x) - x = 0, \quad x \in [0, 1]\]
via nonlinearequations.zero_univariate() (IMSL ZUNI).
After the root is located, the classic cobweb diagram of the fixed-point iteration \(x_{n+1} = \cos(x_n)\) is reconstructed from \(x_0 = 0\) to illustrate the spiral convergence of the iteration.
Example Code¶
"""Fixed-point iteration example using IMSL ZUNI (zero_univariate).
Finds the fixed point of g(x) = cos(x), i.e. the solution of g(x) - x = 0,
known as the Dottie number (x* ≈ 0.7390851332).
The fixed point is located by bracketing the equation h(x) = cos(x) - x = 0
with :func:`nonlinearequations.zero_univariate` (IMSL ZUNI). The classic
cobweb diagram is then drawn to show how the fixed-point iteration
x_{n+1} = cos(x_n) converges to x*.
Outputs:
- Table printed to stdout
- SVG cobweb diagram of fixed-point convergence
- Saved to test_output/example_imsl_fixed_point.svg
"""
from __future__ import annotations
import math
from pathlib import Path
from typing import Dict, List
import matplotlib.pyplot as plt
import numpy as np
from nonlinearequations import zero_univariate
def run_demo_imsl_fixed_point() -> Dict[str, object]:
"""Run fixed-point iteration example via IMSL ZUNI (zero_univariate).
Solves h(x) = cos(x) - x = 0 on [0, 1] with Brent/ZUNI, then
reconstructs the classic cobweb diagram of x_{n+1} = cos(x_n).
Args:
None
Returns:
Dict[str, object]: Result dict with keys ``fixed_point`` (float),
``n_iter_cobweb`` (int), ``fval`` (float), ``n_fev`` (int), and
``plot_path`` (str).
"""
def h(x: float) -> float:
"""Fixed-point equation h(x) = cos(x) - x.
Args:
x (float): Input value.
Returns:
float: cos(x) - x.
"""
return math.cos(x) - x
result = zero_univariate(h, 0.0, 1.0)
x_star = float(result.x[0])
# Build cobweb iteration history starting from x0 = 0.0
x_current = 0.0
iterates: List[float] = [x_current]
max_cobweb_steps = 20
for _ in range(max_cobweb_steps):
x_next = math.cos(x_current)
iterates.append(x_next)
if abs(x_next - x_star) < 1e-6:
break
x_current = x_next
n_iter_cobweb = len(iterates) - 1
print("\nIMSL ZUNI Fixed-Point Example: g(x) = cos(x)")
print(" Solving h(x) = cos(x) - x = 0 on [0, 1]")
print("-" * 55)
print(f"{'Parameter':<30} {'Value':>20}")
print("-" * 55)
print(f"{'Fixed point x*':<30} {x_star:>20.10f}")
print(f"{'cos(x*) - x*':<30} {result.fval:>20.2e}")
print(f"{'ZUNI function evals':<30} {result.n_fev:>20}")
print(f"{'Converged (ZUNI)':<30} {str(result.success):>20}")
print(f"{'Cobweb steps to 1e-6':<30} {n_iter_cobweb:>20}")
print("-" * 55)
# ------------------------------------------------------------------
# Plot: cobweb diagram
# ------------------------------------------------------------------
output_dir = Path("test_output")
output_dir.mkdir(parents=True, exist_ok=True)
plot_path = output_dir / "example_imsl_fixed_point.svg"
x_plot = np.linspace(0.0, 1.1, 400)
g_plot = np.cos(x_plot)
fig, ax = plt.subplots(figsize=(7, 6))
# g(x) = cos(x) and the identity y = x
ax.plot(x_plot, g_plot, color="#0e7490", linewidth=2.0, label=r"$g(x) = \cos(x)$")
ax.plot(x_plot, x_plot, color="#888888", linewidth=1.4, linestyle="--", label=r"$y = x$")
# Cobweb path
cobweb_x: List[float] = []
cobweb_y: List[float] = []
x_n = iterates[0]
cobweb_x.append(x_n)
cobweb_y.append(0.0)
for x_n1 in iterates[1:]:
# Vertical: (x_n, x_n) → (x_n, g(x_n)) = (x_n, x_{n+1})
cobweb_x.append(x_n)
cobweb_y.append(x_n1)
# Horizontal: (x_n, x_{n+1}) → (x_{n+1}, x_{n+1})
cobweb_x.append(x_n1)
cobweb_y.append(x_n1)
x_n = x_n1
ax.plot(cobweb_x, cobweb_y, color="#0891b2", linewidth=1.0, alpha=0.75, label="Cobweb path")
ax.scatter([x_star], [x_star], color="#d62728", s=100, zorder=5,
label=f"Fixed point x* ≈ {x_star:.6f}")
ax.scatter([iterates[0]], [0.0], color="#2ca02c", s=60, zorder=5, label=f"Start x₀ = {iterates[0]:.1f}")
ax.set_xlim(0.0, 1.1)
ax.set_ylim(0.0, 1.1)
ax.set_xlabel("x")
ax.set_ylabel("g(x) / x")
ax.set_title("Fixed-Point Iteration: g(x) = cos(x) (cobweb diagram)")
ax.legend(fontsize=9)
ax.grid(True, alpha=0.25)
fig.tight_layout()
fig.savefig(plot_path, format="svg")
plt.close(fig)
return {
"fixed_point": x_star,
"n_iter_cobweb": n_iter_cobweb,
"fval": result.fval,
"n_fev": result.n_fev,
"plot_path": str(plot_path),
}
if __name__ == "__main__":
run_demo_imsl_fixed_point()
Plot Output¶
Cobweb path of \(x_{n+1} = \cos(x_n)\) starting from \(x_0 = 0\) (green dot). The iteration spirals inward to the fixed point \(x^*\) (red dot) where \(y = g(x)\) meets the diagonal \(y = x\).¶
Console Output¶
IMSL ZUNI Fixed-Point Example: g(x) = cos(x)
Solving h(x) = cos(x) - x = 0 on [0, 1]
-------------------------------------------------------
Parameter Value
-------------------------------------------------------
Fixed point x* 0.7390851346
cos(x*) - x* 2.26e-09
ZUNI function evals 9
Converged (ZUNI) True
Cobweb steps to 1e-6 20
-------------------------------------------------------