ZUNI Example — Univariate Zero-Finding¶
This example uses Brent’s bracketing method (IMSL ZUNI) to find the zeros of two functions:
\(f(x) = x^3 - x - 2\) on \([1, 2]\) → root ≈ 1.5214
\(f(x) = \cos(x)\) on \([1, 2]\) → root ≈ \(\pi/2 \approx 1.5708\)
Example Code¶
"""IMSL ZUNI example: zero of a univariate function using Brent's method.
Demonstrates two zero-finding problems:
1. f(x) = x^3 - x - 2 on [1, 2] → root ≈ 1.5214
2. f(x) = cos(x) on [1, 2] → root ≈ π/2 ≈ 1.5708
Outputs:
- Table printed to stdout
- SVG plot of both functions with roots marked
- Saved to test_output/demo_imsl_zuni.svg
"""
from __future__ import annotations
import math
from pathlib import Path
from typing import Dict
import matplotlib.pyplot as plt
import numpy as np
from nonlinearequations import zero_univariate
def run_demo_imsl_zuni() -> Dict[str, object]:
"""Run IMSL ZUNI example: zero of x^3-x-2 and cos(x).
Args:
None
Returns:
Dict[str, object]: Result dict with keys ``root1`` (float),
``root2`` (float), and ``plot_path`` (str).
"""
def f1(x: float) -> float:
return x**3 - x - 2.0
def f2(x: float) -> float:
return math.cos(x)
r1 = zero_univariate(f1, 1.0, 2.0)
r2 = zero_univariate(f2, 1.0, 2.0)
print("\nIMSL ZUNI Example: Zero of Univariate Functions")
print("-" * 68)
print(f"{'Function':<22} {'Bracket':>12} {'Root':>14} {'|f(root)|':>12} {'n_fev':>6}")
print("-" * 68)
print(f"{'x^3 - x - 2':<22} {'[1, 2]':>12} {r1.x[0]:>14.10f} {r1.fval:>12.2e} {r1.n_fev:>6}")
print(f"{'cos(x)':<22} {'[1, 2]':>12} {r2.x[0]:>14.10f} {r2.fval:>12.2e} {r2.n_fev:>6}")
print("-" * 68)
print(f"{'Expected (f1)':<22} {'':>12} {1.5213797068:>14.10f}")
print(f"{'Expected (f2 = π/2)':<22} {'':>12} {math.pi/2:>14.10f}")
print("-" * 68)
output_dir = Path("test_output")
output_dir.mkdir(parents=True, exist_ok=True)
plot_path = output_dir / "demo_imsl_zuni.svg"
x_vals = np.linspace(0.8, 2.2, 400)
y1 = np.array([f1(xi) for xi in x_vals])
y2 = np.array([f2(xi) for xi in x_vals])
fig, axes = plt.subplots(1, 2, figsize=(11, 5))
ax1 = axes[0]
ax1.plot(x_vals, y1, color="#0e7490", linewidth=2.0, label=r"$f(x) = x^3 - x - 2$")
ax1.axhline(0, color="#888888", linewidth=0.8)
ax1.axvline(r1.x[0], color="#d62728", linestyle="--", linewidth=1.5, label=f"Root≈{r1.x[0]:.6f}")
ax1.scatter([r1.x[0]], [f1(r1.x[0])], color="#d62728", s=60, zorder=5)
ax1.set_xlabel("x")
ax1.set_ylabel("f(x)")
ax1.set_title("Zero of $x^3 - x - 2$")
ax1.legend(fontsize=9)
ax1.grid(True, alpha=0.25)
ax2 = axes[1]
ax2.plot(x_vals, y2, color="#0891b2", linewidth=2.0, label=r"$f(x) = \cos(x)$")
ax2.axhline(0, color="#888888", linewidth=0.8)
ax2.axvline(r2.x[0], color="#d62728", linestyle="--", linewidth=1.5, label=f"Root≈{r2.x[0]:.6f} (π/2)")
ax2.scatter([r2.x[0]], [f2(r2.x[0])], color="#d62728", s=60, zorder=5)
ax2.set_xlabel("x")
ax2.set_ylabel("f(x)")
ax2.set_title(r"Zero of $\cos(x)$")
ax2.legend(fontsize=9)
ax2.grid(True, alpha=0.25)
fig.suptitle("IMSL ZUNI: Univariate Zero-Finding", fontsize=13)
fig.tight_layout()
fig.savefig(plot_path, format="svg")
plt.close(fig)
return {"root1": float(r1.x[0]), "root2": float(r2.x[0]), "plot_path": str(plot_path)}
if __name__ == "__main__":
run_demo_imsl_zuni()
Plot Output¶
Left: zero of \(x^3 - x - 2\) at \(x \approx 1.5214\). Right: zero of \(\cos(x)\) at \(x \approx \pi/2\). Both roots are marked with red dashed vertical lines.¶
Console Output¶
IMSL ZUNI Example: Zero of Univariate Functions
--------------------------------------------------------------------
Function Bracket Root |f(root)| n_fev
--------------------------------------------------------------------
x^3 - x - 2 [1, 2] 1.5213797067 4.90e-10 11
cos(x) [1, 2] 1.5707963258 1.02e-09 8
--------------------------------------------------------------------
Expected (f1) 1.5213797068
Expected (f2 = π/2) 1.5707963268
--------------------------------------------------------------------