Differentiation Example — Numerical Derivatives of sin(x)¶
This example demonstrates integrationdifferentiation.differentiate()
(IMSL DERIV) using Richardson-extrapolated central differences:
Compute 1st, 2nd, and 3rd derivatives of \(f(x) = \sin x\)
Compare numerical results against analytical derivatives (\(\cos x\), \(-\sin x\), \(-\cos x\))
Report maximum absolute errors over \(x \in [0.5,\, 3\pi - 0.5]\)
Example Code¶
"""IMSL DERIV example: numerical differentiation via Richardson extrapolation.
Demonstrates :func:`integrationdifferentiation.differentiate` (IMSL DERIV):
- Compute 1st, 2nd, and 3rd derivatives of ``f(x) = sin(x)``
- Compare numerical results against analytical derivatives
- Report maximum absolute errors across a range of x values
- Produce a 2-panel SVG: function/derivative curves and per-point errors
Outputs:
- Table printed to stdout
- SVG plot saved to ``test_output/example_imsl_differentiation.svg``
"""
from __future__ import annotations
from pathlib import Path
from typing import Dict
import matplotlib.pyplot as plt
import numpy as np
from integrationdifferentiation import differentiate
def run_demo_imsl_differentiation() -> Dict[str, object]:
"""Run numerical differentiation examples for f(x) = sin(x).
Computes 1st, 2nd, and 3rd derivatives using Richardson-extrapolated
central differences and compares against analytical values.
Args:
None
Returns:
Dict[str, object]: Keys ``max_errors`` (dict of order → max error),
``plot_path`` (str).
"""
x_vals = np.linspace(0.5, 3.0 * np.pi - 0.5, 120)
# Numerical derivatives at each x
d1_num = np.array([differentiate(np.sin, float(x), order=1) for x in x_vals])
d2_num = np.array([differentiate(np.sin, float(x), order=2) for x in x_vals])
d3_num = np.array([differentiate(np.sin, float(x), order=3) for x in x_vals])
# Analytical derivatives: sin′=cos, sin″=-sin, sin‴=-cos
d1_exact = np.cos(x_vals)
d2_exact = -np.sin(x_vals)
d3_exact = -np.cos(x_vals)
err1 = np.abs(d1_num - d1_exact)
err2 = np.abs(d2_num - d2_exact)
err3 = np.abs(d3_num - d3_exact)
max_errors = {1: float(err1.max()), 2: float(err2.max()), 3: float(err3.max())}
print("\nIMSL DERIV Example: Numerical Differentiation of sin(x)")
print("=" * 65)
print(f"{'Derivative order':<22} {'Max absolute error':>20}")
print("-" * 65)
for order, err in max_errors.items():
label = f"Order {order}"
print(f"{label:<22} {err:>20.3e}")
print("=" * 65)
print("\nAnalytical: sin′(x)=cos(x), sin″(x)=−sin(x), sin‴(x)=−cos(x)")
# ------------------------------------------------------------------ plot
output_dir = Path("test_output")
output_dir.mkdir(parents=True, exist_ok=True)
plot_path = output_dir / "example_imsl_differentiation.svg"
colors = {"f": "#1d4ed8", "d1": "#059669", "d2": "#d97706", "d3": "#dc2626"}
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(11, 8), sharex=True)
# Panel 1: function and its derivatives
ax1.plot(x_vals, np.sin(x_vals), color=colors["f"], lw=2.0, label=r"$f(x)=\sin x$")
ax1.plot(x_vals, d1_num, color=colors["d1"], lw=1.8, ls="--", label=r"$f'$ (numerical)")
ax1.plot(x_vals, d1_exact, color=colors["d1"], lw=0.8, ls="-", alpha=0.45, label=r"$f'$ (exact)")
ax1.plot(x_vals, d2_num, color=colors["d2"], lw=1.8, ls="--", label=r"$f''$ (numerical)")
ax1.plot(x_vals, d2_exact, color=colors["d2"], lw=0.8, ls="-", alpha=0.45, label=r"$f''$ (exact)")
ax1.plot(x_vals, d3_num, color=colors["d3"], lw=1.8, ls="--", label=r"$f'''$ (numerical)")
ax1.plot(x_vals, d3_exact, color=colors["d3"], lw=0.8, ls="-", alpha=0.45, label=r"$f'''$ (exact)")
ax1.axhline(0, color="black", lw=0.6)
ax1.set_ylabel("Value")
ax1.set_title(r"$f(x)=\sin x$ and its numerical derivatives (Richardson-extrapolated)")
ax1.legend(ncol=4, fontsize=8, loc="upper right")
ax1.grid(True, alpha=0.3)
# Panel 2: absolute errors
ax2.semilogy(x_vals, err1 + 1e-20, color=colors["d1"], lw=1.8, label=r"$|e_{f'}|$")
ax2.semilogy(x_vals, err2 + 1e-20, color=colors["d2"], lw=1.8, label=r"$|e_{f''}|$")
ax2.semilogy(x_vals, err3 + 1e-20, color=colors["d3"], lw=1.8, label=r"$|e_{f'''}|$")
ax2.set_xlabel("x")
ax2.set_ylabel("Absolute error (log scale)")
ax2.set_title("Absolute errors vs analytical derivatives")
ax2.legend(fontsize=9)
ax2.grid(True, alpha=0.3, which="both")
fig.suptitle("IMSL DERIV: Numerical Differentiation of sin(x)", fontsize=13, fontweight="bold")
fig.tight_layout()
fig.savefig(plot_path, format="svg")
plt.close(fig)
return {"max_errors": max_errors, "plot_path": str(plot_path)}
if __name__ == "__main__":
run_demo_imsl_differentiation()
Plot Output¶
Top panel: \(f(x) = \sin x\) and its 1st, 2nd, and 3rd numerical derivatives overlaid on the analytical curves. Bottom panel: per-point absolute errors on a log scale.¶
Console Output¶
IMSL DERIV Example: Numerical Differentiation of sin(x)
=================================================================
Derivative order Max absolute error
-----------------------------------------------------------------
Order 1 2.198e-12
Order 2 6.243e-08
Order 3 9.123e-04
=================================================================
Analytical: sin′(x)=cos(x), sin″(x)=−sin(x), sin‴(x)=−cos(x)