# `latmath.optimize` — Optimization Root-finding, gradient-based, and discrete optimization for scalar and multivariate functions. Pure stdlib, zero dependencies. --- ## Root-Finding ```python from latpy.latmath.optimize import bisection, newton ``` ### Bisection | Signature | Description | |-----------|-------------| | `bisection(f, a, b, tol=1e-12, max_iter=100) -> float` | Bracketed root via interval halving | Robust but slow (linear convergence). Requires `f(a)` and `f(b)` to have opposite signs. ```python from latpy.latmath.optimize import bisection root = bisection(lambda x: x * x - 4.0, 0.0, 5.0) print(root) # 2.0 ``` **Edge cases:** Raises `ValueError` if `f(a)` and `f(b)` have the same sign. ### Newton | Signature | Description | |-----------|-------------| | `newton(f, df, x0, tol=1e-12, max_iter=100) -> float` | Newton-Raphson iteration | Fast (quadratic convergence) but requires the derivative `df` and a good initial guess. ```python from latpy.latmath.optimize import newton root = newton(lambda x: x * x - 4.0, lambda x: 2.0 * x, 3.0) print(root) # 2.0 ``` **Edge cases:** Raises `ValueError` if the derivative is zero at any step. --- ## Gradient Descent ```python from latpy.latmath.optimize import gradient_descent ``` | Signature | Description | |-----------|-------------| | `gradient_descent(f, df, x0, lr=0.01, tol=1e-6, max_iter=1000) -> (x_min, f_min)` | First-order scalar optimization | Steps in the negative gradient direction with fixed learning rate `lr`. Returns the minimizing point and function value. ```python from latpy.latmath.optimize import gradient_descent x_min, f_min = gradient_descent( lambda x: x * x, lambda x: 2.0 * x, x0=5.0, lr=0.1, ) print(x_min) # ≈ 0.0 print(f_min) # ≈ 0.0 ``` **Edge cases:** May oscillate if `lr` is too large; may converge slowly if `lr` is too small. --- ## Discrete Optimization ```python from latpy.latmath.optimize import grid_search, random_search ``` ### Grid Search | Signature | Description | |-----------|-------------| | `grid_search(f, bounds, n_points=100) -> (x_min, f_min)` | Exhaustive grid over bounded domain | Evaluates `f` at every point on a regular grid with `n_points` per dimension. Guaranteed to find the global minimum on the grid, but scales exponentially with dimension. ```python from latpy.latmath.optimize import grid_search best_x, best_f = grid_search( lambda x, y: (x - 1.0) ** 2 + (y + 1.0) ** 2, [(-5.0, 5.0), (-5.0, 5.0)], n_points=200, ) print(best_x) # ≈ (1.0, -1.0) ``` **Edge cases:** Raises `ValueError` if `bounds` is empty. ### Random Search | Signature | Description | |-----------|-------------| | `random_search(f, bounds, n_iter=1000, seed=None) -> (x_min, f_min)` | Random sampling over bounded domain | Samples uniformly from the bounded domain. Does not scale with dimension. Pass `seed` for reproducibility. ```python from latpy.latmath.optimize import random_search best_x, best_f = random_search( lambda x: (x - 3.0) ** 2, [(0.0, 6.0)], n_iter=5000, seed=42, ) print(best_x[0]) # ≈ 3.0 ``` **Edge cases:** `seed=None` produces non-deterministic results; same seed produces identical results.