Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Mathematics Primer

This guide accompanies Real Analysis Review. It supplies the complete definitions, proofs and computations behind the shorter handout. Start with quadratic coordinates, sets and sequences, continuity and derivatives, convexity, or Taylor and finite differences. Linear algebra definitions and factorization diagnostics have their primary home in Linear Algebra Review and SciPy Basics.

# Load the numerical tools and the course's shared figure style.
import sys
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import mpmath as mp
from scipy import linalg
from matplotlib import cm
if 'google.colab' in sys.modules:
    import urllib.request
    urllib.request.urlretrieve('https://raw.githubusercontent.com/ndcbe/optimization/main/notebooks/helper.py', 'helper.py')
else:
    sys.path.insert(0, '../')
import helper
helper.set_plotting_style()

Quadratic objectives in eigenvector coordinates

For a real symmetric B∈Rn×n\mathbf B\in\mathbb R^{n\times n}, consider

f(x)=c+aTx+12xTBx.f(\mathbf x)=c+\mathbf a^{\mathsf T}\mathbf x+\tfrac12\mathbf x^{\mathsf T}\mathbf B\mathbf x.

The symmetric spectral theorem gives B=VΛVT\mathbf B=\mathbf V\boldsymbol\Lambda\mathbf V^{\mathsf T}, with VTV=I\mathbf V^{\mathsf T}\mathbf V=\mathbf I and Λ=diag⁡(λ1,…,λn)\boldsymbol\Lambda=\operatorname{diag}(\lambda_1,\ldots,\lambda_n). Define the coordinates z=VTx\mathbf z=\mathbf V^{\mathsf T}\mathbf x and the transformed function q(z)=f(Vz)q(\mathbf z)=f(\mathbf V\mathbf z). The function value is preserved; the coordinate vector changes. Write aˉ=VTa\bar{\mathbf a}=\mathbf V^{\mathsf T}\mathbf a. Then

q(z)=c+aTVz+12zTVTVΛVTVz=c+aˉTz+12zTΛz=c+∑jaˉjzj+12∑jλjzj2.\begin{aligned} q(\mathbf z)&=c+\mathbf a^{\mathsf T}\mathbf V\mathbf z +\tfrac12\mathbf z^{\mathsf T}\mathbf V^{\mathsf T}\mathbf V\boldsymbol\Lambda\mathbf V^{\mathsf T}\mathbf V\mathbf z\\ &=c+\bar{\mathbf a}^{\mathsf T}\mathbf z+\tfrac12\mathbf z^{\mathsf T}\boldsymbol\Lambda\mathbf z =c+\sum_j\bar a_j z_j+\tfrac12\sum_j\lambda_j z_j^2. \end{aligned}

Each column of V\mathbf V supplies a coordinate direction. Diagonal Λ\boldsymbol\Lambda removes cross terms. See Biegler (2010), §2.2.2, Eqs.(2.8)–(2.10), pp.22–23.

Stationary points and square completion

Stationarity requires aˉj+λjzj=0\bar a_j+\lambda_j z_j=0 for every jj. Let J0={j:λj=0}J_0=\{j:\lambda_j=0\}. A stationary point exists exactly when aˉj=0\bar a_j=0 for every j∈J0j\in J_0. In that case

zj∗=−aˉj/λj(j∉J0),zj∗ is arbitrary(j∈J0),x∗=Vz∗.z_j^*=-\bar a_j/\lambda_j\quad(j\notin J_0),\qquad z_j^*\text{ is arbitrary}\quad(j\in J_0),\qquad \mathbf x^*=\mathbf V\mathbf z^*.

Setting the free coordinates to zero selects one representative; it does not establish uniqueness. If a null coordinate has aˉj≠0\bar a_j\ne0, moving along that coordinate makes the affine term arbitrarily positive or negative.

For every j∉J0j\notin J_0, the full square completion is

12λjzj2+aˉjzj=12λj(zj+aˉjλj)2−aˉj22λj=12λj(zj−zj∗)2−aˉj22λj.\tfrac12\lambda_j z_j^2+\bar a_jz_j =\tfrac12\lambda_j\left(z_j+\frac{\bar a_j}{\lambda_j}\right)^2 -\frac{\bar a_j^2}{2\lambda_j} =\tfrac12\lambda_j(z_j-z_j^*)^2-\frac{\bar a_j^2}{2\lambda_j}.

Consequently, with cˉ=c−∑j∉J0aˉj2/(2λj)\bar c=c-\sum_{j\notin J_0}\bar a_j^2/(2\lambda_j),

q(z)=cˉ+∑j∈J0aˉjzj+12∑j∉J0λj(zj−zj∗)2.q(\mathbf z)=\bar c+\sum_{j\in J_0}\bar a_jz_j +\tfrac12\sum_{j\notin J_0}\lambda_j(z_j-z_j^*)^2.

This formula also describes the case with no stationary point: the null-coordinate linear term remains. It avoids dividing by a zero eigenvalue.

The change of coordinates rotates the same quadratic contour into its eigenvector axes.

Curvature and global classification

The exact eigenvalue signs give the following cases. For a singular matrix, the compatibility condition is aˉj=0\bar a_j=0 on J0J_0.

Eigenvalues of B\mathbf BStationary pointsGlobal behavior
all positiveunique global minimumbounded below
all negativeunique global maximumbounded above
both signs, none zerounique saddleunbounded above and below
some zero, remaining positive, compatibleaffine family of global minimaflat along the null space
some zero, remaining negative, compatibleaffine family of global maximaflat along the null space
some zero, both signs, compatibleaffine family of saddlesunbounded above and below
all zero and a=0\mathbf a=\mathbf0every point is stationary, a minimum and a maximumconstant function
singular and incompatibleno stationary pointunbounded above and below along a null direction

A stationary point is a saddle here when arbitrarily close points have both larger and smaller values. In a compatible singular case, its family has dimension dim⁡Null⁡(B)\dim\operatorname{Null}(\mathbf B). These conclusions follow directly from the square completion. See Biegler (2010), pp.23–25.

Quadratic contours with four prescribed eigenvalue pairs and common eigenvector directions.

All four pictured objectives have a=0\mathbf a=\mathbf0 and c=0c=0; their eigenvectors are rotated by 30 degrees. They compare signs, while the separate conditioning picture compares positive eigenvalue magnitudes. For a positive-definite quadratic, contour semiaxes at a fixed positive objective increment are proportional to 1/λj1/\sqrt{\lambda_j}.

Numerical analysis and plotting helper

The helper below requires an explicitly symmetric real matrix and uses the symmetric eigensolver. Its relative threshold identifies numerically small eigenvalues. It analyzes the thresholded model and prints the residual in the original stored system. Neither thresholding nor a small residual proves the exact rank of a nearly singular matrix. If the thresholded stationarity equations are incompatible, the code draws the surface about a plotting center and does not mark that center as a stationary point.

def quad_analyze(c, a, B):
    """Plot a real symmetric quadratic and report a numerical stationary candidate.

    Returns a dictionary with the eigenpairs, threshold, residual, and candidate.
    A None candidate means the thresholded stationarity equations are incompatible;
    exact rank and compatibility near the threshold require further analysis.
    """
    if np.iscomplexobj(c) or np.iscomplexobj(a) or np.iscomplexobj(B):
        raise ValueError('The quadratic coefficients must be real')
    a = np.asarray(a, dtype=float)
    B = np.asarray(B, dtype=float)
    if a.ndim != 1 or B.shape != (a.size, a.size) or a.size == 0:
        raise ValueError('a must be a nonempty vector and B a matching square matrix')
    if not np.isfinite(c) or not np.all(np.isfinite(a)) or not np.all(np.isfinite(B)):
        raise ValueError('All coefficients must be finite')
    if not np.array_equal(B, B.T):
        raise ValueError('B must be symmetric; form the symmetric part explicitly if intended')
    eigenvalues, V = linalg.eigh(B)
    abar = V.T @ a
    scale = float(np.max(np.abs(eigenvalues)))
    threshold = a.size * np.finfo(float).eps * scale
    small = np.abs(eigenvalues) <= threshold
    rhs_tolerance = a.size * np.finfo(float).eps * np.linalg.norm(a)
    compatible = bool(np.all(np.abs(abar[small]) <= rhs_tolerance))
    zcenter = np.zeros(a.size)
    zcenter[~small] = -abar[~small] / eigenvalues[~small]
    center = V @ zcenter
    residual = a + B @ center
    candidate = center.copy() if compatible else None
    print('B =\n', B, '\na =', a, '\nc =', c)
    print('eigenvalues =', eigenvalues, '\neigenvectors (columns) =\n', V)
    print('transformed linear coefficient =', abar)
    print('near-zero threshold =', threshold)
    print('numerically small eigenvalues =', eigenvalues[small])
    if candidate is None:
        print('Thresholded stationarity equations are incompatible; no stationary marker is drawn.')
        print('Plot center =', center)
    else:
        print('Numerical stationary candidate =', candidate)
        if np.any(small):
            print('Free coordinates in the thresholded model are set to zero for this representative.')
    print('gradient at center =', residual)
    print('gradient 2-norm =', np.linalg.norm(residual))
    if a.size == 2:
        grid = np.linspace(-5., 5., 81)
        X1, X2 = np.meshgrid(center[0] + grid, center[1] + grid)
        F = c + a[0]*X1 + a[1]*X2 + .5*(B[0,0]*X1**2 + 2*B[0,1]*X1*X2 + B[1,1]*X2**2)
        fig = plt.figure(figsize=(8, 6))
        ax = fig.add_subplot(projection='3d')
        ax.plot_surface(X1, X2, F, cmap=cm.viridis, linewidth=0)
        if candidate is not None:
            value = c + a @ candidate + .5*candidate @ B @ candidate
            ax.scatter(*candidate, value, marker='o', color='#D55E00', edgecolor='black', s=65,
                       label='numerical stationary candidate')
            ax.legend(fontsize=10)
        ax.set(xlabel='$x_1$', ylabel='$x_2$', zlabel=r'$f(\mathbf{x})$')
        plt.show()
    return dict(eigenvalues=eigenvalues, eigenvectors=V, transformed_linear=abar,
                threshold=threshold, small_eigenvalues=small,
                candidate=candidate, plot_center=center, gradient=residual)

Example 2.8 in Biegler (2010)

c = 0
a = np.array([1, 1])
B = np.array([[2, 1], [1, 2]])

quad_analyze(c, a, B)
B =
 [[2. 1.]
 [1. 2.]] 
a = [1. 1.] 
c = 0
eigenvalues = [1. 3.] 
eigenvectors (columns) =
 [[-0.70710678  0.70710678]
 [ 0.70710678  0.70710678]]
transformed linear coefficient = [0.         1.41421356]
near-zero threshold = 1.3322676295501878e-15
numerically small eigenvalues = []
Numerical stationary candidate = [-0.33333333 -0.33333333]
gradient at center = [2.22044605e-16 2.22044605e-16]
gradient 2-norm = 3.1401849173675503e-16
<Figure size 800x600 with 1 Axes>
{'eigenvalues': array([1., 3.]), 'eigenvectors': array([[-0.70710678, 0.70710678], [ 0.70710678, 0.70710678]]), 'transformed_linear': array([0. , 1.41421356]), 'threshold': np.float64(1.3322676295501878e-15), 'small_eigenvalues': array([False, False]), 'candidate': array([-0.33333333, -0.33333333]), 'plot_center': array([-0.33333333, -0.33333333]), 'gradient': array([2.22044605e-16, 2.22044605e-16])}

Activity 1

Classify the stationary point for f(x)=x1+x2f(\mathbf{x}) = x_1 + x_2.

# Add your solution here

Activity 2

Classify the stationary point for f(x)=x12+x22−2x1x2+0x1−0x2+3f(\mathbf{x}) = x_1^2 + x_2^2 - 2x_1 x_2 + 0 x_1 - 0 x_2 + 3.

Hint: B\mathbf{B} needs to be symmetric.

# Add your solution here

Sets, sequences, regularity and convexity

The definitions below use finite-dimensional Euclidean spaces and the 2-norm unless another norm is specified. The full proofs support the handout activities.

Balls, neighborhoods, interior, boundary and closure

For xˉ∈Rn\bar{\mathbf x}\in\mathbb R^n and r>0r>0, the open and closed balls are

B(xˉ,r)={x:∥x−xˉ∥<r},B‾(xˉ,r)={x:∥x−xˉ∥≤r}.\mathcal B(\bar{\mathbf x},r)=\{\mathbf x:\|\mathbf x-\bar{\mathbf x}\|<r\},\qquad \overline{\mathcal B}(\bar{\mathbf x},r)=\{\mathbf x:\|\mathbf x-\bar{\mathbf x}\|\le r\}.

A set SS is open if every x∈S\mathbf x\in S has a ball B(x,r)⊆S\mathcal B(\mathbf x,r)\subseteq S. A neighborhood of a point is an open set containing that point. In particular, an open ball is a neighborhood; a neighborhood need not be a ball.

Open and closed balls and a neighborhood containing a smaller open ball.

For S⊆RnS\subseteq\mathbb R^n:

  • x\mathbf x is an interior point if some ball about it is contained in SS; the interior is int⁡S\operatorname{int}S.

  • x\mathbf x is a boundary point if every ball about it meets both SS and its complement; the boundary is ∂S\partial S.

  • x\mathbf x is in the closure cl⁡S\operatorname{cl}S if every ball about it meets SS.

Thus cl⁡S=S∪∂S\operatorname{cl}S=S\cup\partial S. The interior is the largest open subset of SS; the closure is the smallest closed set containing SS. A boundary point need not belong to SS: for S=(0,1)S=(0,1), the boundary is {0,1}\{0,1\} and the closure is [0,1][0,1].

Interior, boundary and an approaching sequence distinguish membership from proximity.

See Nocedal & Wright (2006), pp.620–621. The empty set and the whole space are both open and closed; these properties are not opposites.

Sequences, subsequences and closed sets

A sequence assigns a point xk∈Rn\mathbf x^k\in\mathbb R^n to each positive integer kk. It converges to xˉ\bar{\mathbf x} if

∀ϵ>0 ∃K ∀k≥K:∥xk−xˉ∥<ϵ.\forall\epsilon>0\ \exists K\ \forall k\ge K:\quad\|\mathbf x^k-\bar{\mathbf x}\|<\epsilon.

A subsequence has indices k1<k2<⋯k_1<k_2<\cdots. A limit point of a sequence is the limit of one of its subsequences. A convergent sequence has exactly one limit point. The nonconvergent sequence xk=((−1)k,1/k)T\mathbf x^k=((-1)^k,1/k)^{\mathsf T} has the two limit points (1,0)T(1,0)^{\mathsf T} and (−1,0)T(-1,0)^{\mathsf T}, obtained from the even and odd subsequences. See Nocedal & Wright (2006), pp.617–618.

A set is closed if its complement is open. Equivalently, it contains every limit of every convergent sequence of its points.

Proof that closed sets contain such limits. Suppose xk∈S\mathbf x^k\in S, xk→xˉ\mathbf x^k\to\bar{\mathbf x}, and xˉ∉S\bar{\mathbf x}\notin S. The open complement contains a ball B(xˉ,r)\mathcal B(\bar{\mathbf x},r) disjoint from SS. Convergence puts every sufficiently late iterate in the smaller ball of radius r/2r/2, hence in both SS and its complement, a contradiction. Therefore xˉ∈S\bar{\mathbf x}\in S.

Converse. If xˉ∈cl⁡S\bar{\mathbf x}\in\operatorname{cl}S, choose xk∈S∩B(xˉ,1/k)\mathbf x^k\in S\cap\mathcal B(\bar{\mathbf x},1/k). This sequence converges to xˉ\bar{\mathbf x}. A set containing all such limits therefore contains its closure and is closed. This also proves the sequence characterization of closure. See Nocedal & Wright (2006), pp.620–621.

The hypothetical outside limit has a ball disjoint from the closed set, contradicting a late iterate in that ball.

Bounded and compact sets

S⊆RnS\subseteq\mathbb R^n is bounded if some M>0M>0 satisfies ∥x∥≤M\lVert\mathbf x\rVert\le M for every x∈S\mathbf x\in S. It is compact if every sequence in SS has a subsequence converging to a point of SS. In Rn\mathbb R^n, compactness is equivalent to being closed and bounded. The finite-dimensional hypothesis matters. See Nocedal & Wright (2006), pp.620–621.

A bounded open set can lose a limiting point; a closed unbounded set can lose all bounded subsequences.

The four sets below are subsets of R2\mathbb R^2. Convexity means that the entire segment between any two member points remains in the set; its formal definition and proof examples appear below.

Open disk, closed disk, nonnegative quadrant and closed annulus.
SetOpenClosedBoundedCompactConvex
{x:∥x∥<1}\{\mathbf x:\lVert\mathbf x\rVert<1\}yesnoyesnoyes
{x:∥x∥≤1}\{\mathbf x:\lVert\mathbf x\rVert\le1\}noyesyesyesyes
{x:x1≥0, x2≥0}\{\mathbf x:x_1\ge0,\ x_2\ge0\}noyesnonoyes
{x:1≤∥x∥≤2}\{\mathbf x:1\le\lVert\mathbf x\rVert\le2\}noyesyesyesno

For the annulus, (1,0)T(1,0)^{\mathsf T} and (−1,0)T(-1,0)^{\mathsf T} belong to the set, but their midpoint does not. For the open disk, (1−1/k,0)T(1-1/k,0)^{\mathsf T} approaches a missing boundary point. In the quadrant, (k,0)T(k,0)^{\mathsf T} has no convergent subsequence.

Weierstrass theorem and a minimizing sequence

A continuous real-valued function on a nonempty compact set S⊆RnS\subseteq\mathbb R^n attains a minimum and a maximum. See Rapcsák, “Smooth Nonlinear Nonconvex Optimization,” in Encyclopedia of Optimization, 2nd ed. (2009), p.3623. The cited statement gives the minimum; applying it to the negative function gives the maximum.

Here is the complete sequential argument. Write m=inf⁡x∈Sϕ(x)m=\inf_{\mathbf x\in S}\phi(\mathbf x).

  1. If mm is finite, choose xk∈S\mathbf x^k\in S with m≤ϕ(xk)<m+1/km\le\phi(\mathbf x^k)<m+1/k. If m=−∞m=-\infty, choose ϕ(xk)<−k\phi(\mathbf x^k)<-k. These choices are permitted by the definition of infimum.

  2. Compactness supplies a subsequence xki→x^∈S\mathbf x^{k_i}\to\hat{\mathbf x}\in S. Continuity implies ϕ(xki)→ϕ(x^)\phi(\mathbf x^{k_i})\to\phi(\hat{\mathbf x}), a finite real number.

  3. The m=−∞m=-\infty alternative contradicts that finite limit. Hence mm is finite, and the same subsequence has function values tending to mm. Uniqueness of a real limit gives ϕ(x^)=m\phi(\hat{\mathbf x})=m.

The maximum follows from the minimum of −ϕ-\phi. This is a compactness-plus-continuity proof, not a derivative test.

Without the hypotheses the conclusion can fail. The function ϕ(x)=x\phi(x)=x on (0,1)(0,1) has no minimum; exe^x on R\mathbb R has infimum zero but no minimizer. Compactness alone is insufficient: on [0,1][0,1], define ϕ(0)=1\phi(0)=1 and ϕ(x)=x\phi(x)=x for x>0x>0. Its infimum is zero, is not attained, and the function is discontinuous at zero.

For x squared on the unit interval, a minimizing subsequence converges in the domain and continuity identifies the minimum value.

Limits and continuity on a domain

Let ϕ:D⊆Rn→R\phi:D\subseteq\mathbb R^n\to\mathbb R. At an accumulation point xˉ\bar{\mathbf x} of DD, the limit is ℓ\ell if

∀ϵ>0 ∃δ>0:x∈D, 0<∥x−xˉ∥<δ ⟹ ∣ϕ(x)−ℓ∣<ϵ.\forall\epsilon>0\ \exists\delta>0:\quad \mathbf x\in D,\ 0<\|\mathbf x-\bar{\mathbf x}\|<\delta \ \Longrightarrow\ |\phi(\mathbf x)-\ell|<\epsilon.

The function is continuous at xˉ∈D\bar{\mathbf x}\in D if the same implication, with ℓ=ϕ(xˉ)\ell=\phi(\bar{\mathbf x}), holds for all x∈D\mathbf x\in D with ∥x−xˉ∥<δ\|\mathbf x-\bar{\mathbf x}\|<\delta. It is continuous on DD when it is continuous at every point of DD. The domain is part of the definition. See Biegler (2010), Def.2.9, p.25; Nocedal & Wright (2006), Eq.(A.38), p.623.

A small input window keeps the graph inside a prescribed output band.

The formula 1/x1/x is continuous on R∖{0}\mathbb R\setminus\{0\}, and in particular on (0,∞)(0,\infty). It is undefined at zero. Since ∣1/x∣|1/x| is unbounded near zero, no assigned finite value at zero gives a continuous extension. This does not make the function discontinuous at a point outside its stated domain.

Lipschitz continuity and derivative bounds

ϕ:D→R\phi:D\to\mathbb R is Lipschitz continuous on N⊆DN\subseteq D if one finite constant L>0L>0 satisfies

∣ϕ(x)−ϕ(y)∣≤L∥x−y∥for every x,y∈N.|\phi(\mathbf x)-\phi(\mathbf y)|\le L\|\mathbf x-\mathbf y\| \qquad\text{for every }\mathbf x,\mathbf y\in N.

The constant is selected before the pair of points. It may depend on the set NN. Local Lipschitz continuity at an interior point means that such a neighborhood NN exists. This uses Nocedal & Wright (2006), Eq.(A.42), p.624; the quantifier order in Biegler’s Def.2.10, p.25, does not impose a single constant on the set.

Lines of slopes plus and minus L bound every secant from a graph point.Secants from zero to positive points on the square-root graph grow steeper as the points approach zero.

The continuous function x\sqrt{x} is not Lipschitz on [0,∞)[0,\infty). Setting x=0x=0 and y=a>0y=a>0 would require a≤La\sqrt a\le La, hence L≥1/aL\ge1/\sqrt a for every a>0a>0, which is impossible. On [1,∞)[1,\infty),

∣x−y∣=∣x−y∣x+y≤12∣x−y∣.|\sqrt{x}-\sqrt{y}|=\frac{|x-y|}{\sqrt{x}+\sqrt{y}}\le\tfrac12|x-y|.

Thus L=1/2L=1/2 works there. The derivative 1/(2x)1/(2\sqrt{x}) becomes unbounded toward zero, consistent with the first result.

More generally, a differentiable scalar function with ∥∇ϕ∥≤L\|\nabla\phi\|\le L along every segment in a convex set is Lipschitz there, provided the function is continuous on each segment and differentiable in its interior. Apply the scalar mean value theorem along the segment and Cauchy–Schwarz. Conversely, where an LL-Lipschitz function is differentiable, taking directional limits gives ∣∇ϕTp∣≤L∥p∥|\nabla\phi^{\mathsf T}\mathbf p|\le L\|\mathbf p\|. Lipschitz continuity does not require differentiability everywhere; ∣x∣|x| is an example.

Derivatives, gradients, Hessians and level sets

For a scalar function, ϕ′(a)=lim⁡h→0[ϕ(a+h)−ϕ(a)]/h\phi'(a)=\lim_{h\to0}[\phi(a+h)-\phi(a)]/h when the limit exists; the second derivative is the derivative of ϕ′\phi'. For ϕ:D⊆Rn→R\phi:D\subseteq\mathbb R^n\to\mathbb R at an interior point, the coordinate partial derivatives are

∂iϕ(x)=lim⁡h→0ϕ(x+hei)−ϕ(x)h,∂i∂jϕ=∂∂xi(∂ϕ∂xj).\partial_i\phi(\mathbf x)=\lim_{h\to0}\frac{\phi(\mathbf x+h\mathbf e_i)-\phi(\mathbf x)}{h},\qquad \partial_i\partial_j\phi=\frac{\partial}{\partial x_i}\left(\frac{\partial\phi}{\partial x_j}\right).

The gradient is the column of first partials and the Hessian collects second partials:

∇ϕ=(∂1ϕ,…,∂nϕ)T,[∇2ϕ]ij=∂i∂jϕ.\nabla\phi=(\partial_1\phi,\ldots,\partial_n\phi)^{\mathsf T},\qquad [\nabla^2\phi]_{ij}=\partial_i\partial_j\phi.

Differentiability at x\mathbf x means that the linear model has a remainder negligible relative to the step:

ϕ(x+p)=ϕ(x)+∇ϕ(x)Tp+o(∥p∥)(p→0).\phi(\mathbf x+\mathbf p)=\phi(\mathbf x)+\nabla\phi(\mathbf x)^{\mathsf T}\mathbf p+o(\|\mathbf p\|) \quad(\mathbf p\to\mathbf0).

Existence of all coordinate partials alone does not imply this property. A function is C1C^1 if its first partials exist and are continuous, and C2C^2 if its second partials exist and are continuous. For a differentiable function, the two-sided directional derivative is

lim⁡h→0ϕ(x+hp)−ϕ(x)h=∇ϕ(x)Tp.\lim_{h\to0}\frac{\phi(\mathbf x+h\mathbf p)-\phi(\mathbf x)}{h} =\nabla\phi(\mathbf x)^{\mathsf T}\mathbf p.

A real C2C^2 function has a symmetric Hessian. This permits real eigenvalues, an orthogonal eigenbasis and symmetric factorizations. Cholesky additionally requires positive definiteness; symmetry alone is insufficient. Symmetry also permits storing one triangle, containing n(n+1)/2n(n+1)/2 entries rather than n2n^2; the factor tends to one half as nn grows. See Biegler (2010), Defs.2.11–2.12, pp.25–27; Nocedal & Wright (2006), pp.626–628.

The gradient is normal to a smooth level curve and gives the directional slope.

For α∈R\alpha\in\mathbb R, a level set is {x∈D:ϕ(x)=α}\{\mathbf x\in D:\phi(\mathbf x)=\alpha\} and a sublevel set is {x∈D:ϕ(x)≤α}\{\mathbf x\in D:\phi(\mathbf x)\le\alpha\}. At a regular point with nonzero gradient, differentiate ϕ(x(t))=α\phi(\mathbf x(t))=\alpha to obtain ∇ϕTx′(t)=0\nabla\phi^{\mathsf T}\mathbf x'(t)=0. This proves the normal-direction statement; a zero gradient does not specify a normal direction.

A level boundary and its filled sublevel region.

Mean value and implicit function theorems

If ϕ\phi is continuous on [a,b][a,b] and differentiable on (a,b)(a,b), with a<ba<b, then

ϕ(b)−ϕ(a)=ϕ′(ξ)(b−a)for some ξ∈(a,b).\phi(b)-\phi(a)=\phi'(\xi)(b-a)\qquad\text{for some }\xi\in(a,b).

For a C1C^1 scalar-valued function on a neighborhood of a segment from x\mathbf x to x+p\mathbf x+\mathbf p, apply this theorem to g(t)=ϕ(x+tp)g(t)=\phi(\mathbf x+t\mathbf p). Then g′(t)=∇ϕ(x+tp)Tpg'(t)=\nabla\phi(\mathbf x+t\mathbf p)^{\mathsf T}\mathbf p. See Nocedal & Wright (2006), Eqs.(A.54)–(A.55), p.629.

There need not be one common mean-value point for a vector-valued function. For g(t)=(t2,t3)T\mathbf g(t)=(t^2,t^3)^{\mathsf T} on [0,1][0,1], the two components would require 2ξ=12\xi=1 and 3ξ2=13\xi^2=1, respectively. Those values of ξ\xi differ. The integral form used for gradients below avoids that claim.

Implicit function theorem. Let h:Rn×Rm→Rn\mathbf h:\mathbb R^n\times\mathbb R^m\to\mathbb R^n be C1C^1 near (z∗,0)(\mathbf z^*,\mathbf0), with h(z∗,0)=0\mathbf h(\mathbf z^*,\mathbf0)=\mathbf0 and nonsingular ∇zh\nabla_{\mathbf z}\mathbf h there. Then product neighborhoods exist on which the nearby roots are exactly the graph of a unique C1C^1 function z(t)\mathbf z(\mathbf t) with z(0)=z∗\mathbf z(\mathbf0)=\mathbf z^*. Using the course’s derivative arrays, whose row indexes the input component,

[∇zh]ij=∂hj∂zi,[∇th]ij=∂hj∂ti,∇z=−∇th [∇zh]−1.[\nabla_{\mathbf z}\mathbf h]_{ij}=\frac{\partial h_j}{\partial z_i},\quad [\nabla_{\mathbf t}\mathbf h]_{ij}=\frac{\partial h_j}{\partial t_i},\quad \nabla\mathbf z=-\nabla_{\mathbf t}\mathbf h\,[\nabla_{\mathbf z}\mathbf h]^{-1}.

The dimensions are n×nn\times n, m×nm\times n and m×nm\times n, respectively; evaluate the derivative arrays at (z(t),t)(\mathbf z(\mathbf t),\mathbf t). The formula follows by differentiating h(z(t),t)=0\mathbf h(\mathbf z(\mathbf t),\mathbf t)=\mathbf0. See Nocedal & Wright (2006), Thm.A.2, p.631.

For h(z,t)=z2+t−1h(z,t)=z^2+t-1 near (1,0)(1,0), hz=2≠0h_z=2\ne0, so the local branch is z(t)=1−tz(t)=\sqrt{1-t} and z′(0)=−ht/hz=−1/2z'(0)=-h_t/h_z=-1/2. There is another branch near (−1,0)(-1,0); local uniqueness near z=1z=1 does not assert a unique root globally. At (0,1)(0,1) the nonsingularity hypothesis fails.

A secant and tangent share a slope; a separate implicit equation has a locally unique branch near t equals zero, z equals one.

Convex combinations, hulls, half-spaces and polyhedra

A convex combination of x1,…,xm\mathbf x_1,\ldots,\mathbf x_m is ∑iθixi\sum_i\theta_i\mathbf x_i with θi≥0\theta_i\ge0 and ∑iθi=1\sum_i\theta_i=1. Their convex hull is the set of all these combinations. A set SS is convex if

θxa+(1−θ)xb∈Sfor every xa,xb∈S, θ∈[0,1].\theta\mathbf x_a+(1-\theta)\mathbf x_b\in S \quad\text{for every }\mathbf x_a,\mathbf x_b\in S,\ \theta\in[0,1].

The convex hull is convex: a convex combination of two combinations has nonnegative coefficients summing to one. Any convex set containing all the original points contains every finite convex combination, by induction. Hence the hull is the smallest convex set containing them. See Nocedal & Wright (2006), p.621; Nesterov (2018), pp.141–142.

A segment and a finite-point convex hull are built from nonnegative weights summing to one.

For a≠0\mathbf a\ne\mathbf0, a hyperplane is {x:aTx=b}\{\mathbf x:\mathbf a^{\mathsf T}\mathbf x=b\}. The two closed half-spaces use ≤b\le b and ≥b\ge b. The normal a\mathbf a is perpendicular to the hyperplane. A polyhedron is an intersection of finitely many half-spaces and hyperplanes, equivalently {x:Ax≤b}\{\mathbf x:\mathbf A\mathbf x\le\mathbf b\} after writing an equality as two inequalities. A polyhedron can be empty or unbounded.

A normal vector distinguishes the boundary hyperplane from its two half-spaces.A polyhedron is an intersection of finitely many linear inequalities.A segment between two half-space points stays on the feasible side; weight the two linear bounds.

Proof for a half-space. If aTxa≤b\mathbf a^{\mathsf T}\mathbf x_a\le b and aTxb≤b\mathbf a^{\mathsf T}\mathbf x_b\le b, then

aT(θxa+(1−θ)xb)=θaTxa+(1−θ)aTxb≤θb+(1−θ)b=b.\mathbf a^{\mathsf T}(\theta\mathbf x_a+(1-\theta)\mathbf x_b) =\theta\mathbf a^{\mathsf T}\mathbf x_a+(1-\theta)\mathbf a^{\mathsf T}\mathbf x_b \le\theta b+(1-\theta)b=b.

A hyperplane uses the same computation with equality. Applying the inequality row by row proves the polyhedron is convex. Lecture 2 is the primary handout home for the half-space and intersection convexity proofs. The existing Introduction to Constrained Nonlinear Optimization guide collects the general intersection proof and convex-program formulation checklist. See Nocedal & Wright (2006), p.8; Nesterov (2018), Def.3.1.4, p.159.

Rays and cones

Using the positive-scaling convention, the ray through d≠0\mathbf d\ne\mathbf0 is {τd:τ>0}\{\tau\mathbf d:\tau>0\}. A cone CC satisfies

d∈C ⟹ τd∈Cfor every τ>0.\mathbf d\in C\ \Longrightarrow\ \tau\mathbf d\in C\qquad\text{for every }\tau>0.

This convention does not require the origin. A convex cone is also a convex set. The generated set {∑iτidi:τi≥0}\{\sum_i\tau_i\mathbf d_i:\tau_i\ge0\} contains the origin and is a convex cone: nonnegative scaling and convex combinations preserve nonnegative coefficients. The set {(x1,x2):x1≥0 or x2≥0}\{(x_1,x_2):x_1\ge0\text{ or }x_2\ge0\} is a cone but is not convex; the points (1,−2)(1,-2) and (−2,1)(-2,1) have a midpoint outside it. See Nocedal & Wright (2006), Eq.(A.36) and pp.621–622.

Positive scaling preserves rays. The pictured nonconvex cone uses x1 times x2 nonnegative, a second example alongside the union of half-spaces above.

A convex half-space need not be a cone

Convex combinations keep a point in a half-space, but positive scaling can leave it. For

H={x:x1+2x2≤4},xb=(2,1/2)T,H=\{\mathbf x:x_1+2x_2\le4\},\qquad \mathbf x_b=(2,1/2)^{\mathsf T},

we have aTxb=3≤4\mathbf a^{\mathsf T}\mathbf x_b=3\le4 for a=(1,2)T\mathbf a=(1,2)^{\mathsf T}, whereas aT(2xb)=6>4\mathbf a^{\mathsf T}(2\mathbf x_b)=6>4. Thus HH is convex and is not a cone.

Scaling a point in the shifted half-space by two crosses its boundary along the dashed ray.

More generally, for a≠0\mathbf a\ne\mathbf0, the closed half-space Hb={x:aTx≤b}H_b=\{\mathbf x:\mathbf a^{\mathsf T}\mathbf x\le b\} is a cone under the positive-scaling definition exactly when b=0b=0. If b=0b=0, multiplying the inequality by any τ>0\tau>0 preserves it. If b≠0b\ne0, choose the boundary point xb=ba/∥a∥22\mathbf x_b=b\mathbf a/\|\mathbf a\|_2^2. For b>0b>0, 2xb2\mathbf x_b has functional value 2b>b2b>b; for b<0b<0, xb/2\mathbf x_b/2 has value b/2>bb/2>b. Either case violates positive-scaling closure. This argument also applies under the convention that permits a cone to exclude the origin.

Convex functions and the first-order characterization

Let D⊆RnD\subseteq\mathbb R^n be convex. A function ϕ:D→R\phi:D\to\mathbb R is convex if for all xa,xb∈D\mathbf x_a,\mathbf x_b\in D and θ∈(0,1)\theta\in(0,1),

ϕ(θxa+(1−θ)xb)≤θϕ(xa)+(1−θ)ϕ(xb).\phi(\theta\mathbf x_a+(1-\theta)\mathbf x_b) \le\theta\phi(\mathbf x_a)+(1-\theta)\phi(\mathbf x_b).

It is strictly convex if the inequality is strict whenever xa≠xb\mathbf x_a\ne\mathbf x_b. On an open convex domain, a differentiable function is convex exactly when

ϕ(y)≥ϕ(x)+∇ϕ(x)T(y−x)(x,y∈D).\phi(\mathbf y)\ge\phi(\mathbf x)+\nabla\phi(\mathbf x)^{\mathsf T}(\mathbf y-\mathbf x) \qquad(\mathbf x,\mathbf y\in D).

Strict convexity is equivalent to the strict first-order inequality for distinct points. The excluded equal-point case matters: equality always holds at y=x\mathbf y=\mathbf x. See Biegler (2010), Def.2.13, p.27, with the distinct-point qualification in Nocedal & Wright (2006), p.8; Nesterov (2018), Thm.2.1.2, pp.62–63.

The chord lies above the graph and the tangent line lies below it.

First-order inequality implies the chord inequality

Two supporting inequalities based at the same convex combination have weighted displacement terms that cancel.

Set xc=θxa+(1−θ)xb\mathbf x_c=\theta\mathbf x_a+(1-\theta)\mathbf x_b. Apply the first-order inequality twice, both times based at xc\mathbf x_c:

ϕ(xa)≥ϕ(xc)+∇ϕ(xc)T(xa−xc),ϕ(xb)≥ϕ(xc)+∇ϕ(xc)T(xb−xc).\begin{aligned} \phi(\mathbf x_a)&\ge\phi(\mathbf x_c)+\nabla\phi(\mathbf x_c)^{\mathsf T}(\mathbf x_a-\mathbf x_c),\\ \phi(\mathbf x_b)&\ge\phi(\mathbf x_c)+\nabla\phi(\mathbf x_c)^{\mathsf T}(\mathbf x_b-\mathbf x_c). \end{aligned}

Multiply these inequalities by θ\theta and 1−θ1-\theta, both positive, and add. The gradient term is zero because

θ(xa−xc)+(1−θ)(xb−xc)=θxa+(1−θ)xb−xc=0.\theta(\mathbf x_a-\mathbf x_c)+(1-\theta)(\mathbf x_b-\mathbf x_c) =\theta\mathbf x_a+(1-\theta)\mathbf x_b-\mathbf x_c=\mathbf0.

The remaining inequality is precisely the chord inequality. Strict first-order inequalities give the strict chord inequality for distinct endpoints.

Chord inequality implies the first-order inequality

Secants from a fixed base approach its tangent as the positive segment parameter tends to zero.

Fix x,y∈D\mathbf x,\mathbf y\in D and write p=y−x\mathbf p=\mathbf y-\mathbf x.

  1. Convexity gives ϕ(x+θp)≤(1−θ)ϕ(x)+θϕ(y)\phi(\mathbf x+\theta\mathbf p)\le(1-\theta)\phi(\mathbf x)+\theta\phi(\mathbf y).

  2. Subtract ϕ(x)\phi(\mathbf x) and divide by the positive θ\theta:

ϕ(x+θp)−ϕ(x)θ≤ϕ(y)−ϕ(x).\frac{\phi(\mathbf x+\theta\mathbf p)-\phi(\mathbf x)}{\theta} \le\phi(\mathbf y)-\phi(\mathbf x).
  1. Let θ↓0\theta\downarrow0. Differentiability at x\mathbf x makes the left side tend to ∇ϕ(x)Tp\nabla\phi(\mathbf x)^{\mathsf T}\mathbf p. A weak inequality survives the limit, giving the first-order inequality. Continuity of the gradient is not needed for this step.

A strict inequality does not automatically survive a limit. For the strict result, first obtain the weak supporting inequality just proved. At a distinct pair, strict convexity and that support bound imply

ϕ(x)+θ∇ϕ(x)Tp≤ϕ(x+θp)<(1−θ)ϕ(x)+θϕ(y).\phi(\mathbf x)+\theta\nabla\phi(\mathbf x)^{\mathsf T}\mathbf p \le\phi(\mathbf x+\theta\mathbf p) <(1-\theta)\phi(\mathbf x)+\theta\phi(\mathbf y).

Subtract and divide by θ>0\theta>0 to get the strict first-order inequality. These arguments also explain why negating a first-order inequality at one pair of points does not justify applying the failure at two prescribed directions.

Hessians, strong convexity and quasi-convexity

For a C2C^2 function on an open convex domain, convexity is equivalent to ∇2ϕ(x)⪰0\nabla^2\phi(\mathbf x)\succeq0 everywhere. Necessity follows by applying the supporting inequality to x±hp\mathbf x\pm h\mathbf p, adding, dividing by h2h^2 and taking h→0h\to0. This gives pT∇2ϕ(x)p≥0\mathbf p^{\mathsf T}\nabla^2\phi(\mathbf x)\mathbf p\ge0 for every p\mathbf p.

For sufficiency, the exact integral Taylor remainder is

ϕ(x+p)−ϕ(x)−∇ϕ(x)Tp=∫01(1−t)pT∇2ϕ(x+tp)p dt.\phi(\mathbf x+\mathbf p)-\phi(\mathbf x)-\nabla\phi(\mathbf x)^{\mathsf T}\mathbf p =\int_0^1(1-t)\mathbf p^{\mathsf T}\nabla^2\phi(\mathbf x+t\mathbf p)\mathbf p\,dt.

A positive-semidefinite Hessian makes the integral nonnegative. Pointwise positive definiteness makes it positive for p≠0\mathbf p\ne\mathbf0, so it is sufficient for strict convexity. It is not necessary: x4x^4 is strictly convex but has second derivative zero at zero.

A differentiable function on a convex domain is m-strongly convex, m>0m>0, if

ϕ(x+p)≥ϕ(x)+∇ϕ(x)Tp+m2∥p∥2\phi(\mathbf x+\mathbf p)\ge\phi(\mathbf x)+\nabla\phi(\mathbf x)^{\mathsf T}\mathbf p+\tfrac m2\|\mathbf p\|^2

for every segment in its domain. In the C2C^2 case this is equivalent to the uniform bound ∇2ϕ(x)⪰mI\nabla^2\phi(\mathbf x)\succeq m\mathbf I. A positive-definite Hessian at every point alone does not supply one uniform mm. For example, exe^x has positive second derivative everywhere on R\mathbb R, but the infimum of its second derivative is zero as x→−∞x\to-\infty. See Nesterov (2018), Def.2.1.3 and Thm.2.1.11, pp.74–75; this corrects the pointwise-Hessian condition in Biegler’s Def.2.13.

A common positive quadratic gap above the tangent is required at every base point.A uniform positive quadratic gap is stronger than a merely strict supporting inequality.

For ϕ(x)=x4\phi(x)=x^4, ϕ′(x)=4x3\phi'(x)=4x^3, ϕ′′(x)=12x2\phi''(x)=12x^2, and

ϕ(x+p)−ϕ(x)−ϕ′(x)p=p2[(p+2x)2+2x2]>0(p≠0).\phi(x+p)-\phi(x)-\phi'(x)p=p^2\bigl[(p+2x)^2+2x^2\bigr]>0\quad(p\ne0).
Property on R\mathbb RTest for x4x^4Result
convex12x2≥012x^2\ge0 for all xxyes
strictly convexthe displayed positive gap for every p≠0p\ne0yes
strongly convexwould require 12x2≥m>012x^2\ge m>0 for all xxno, since ϕ′′(0)=0\phi''(0)=0

A function is quasi-convex if each sublevel set is convex. Every convex function is quasi-convex: if ϕ(xa),ϕ(xb)≤α\phi(\mathbf x_a),\phi(\mathbf x_b)\le\alpha, convexity yields

ϕ(θxa+(1−θ)xb)≤θϕ(xa)+(1−θ)ϕ(xb)≤α.\phi(\theta\mathbf x_a+(1-\theta)\mathbf x_b) \le\theta\phi(\mathbf x_a)+(1-\theta)\phi(\mathbf x_b)\le\alpha.
Convexity puts the graph below a chord whose endpoints lie below the same sublevel height.

See Nesterov (2018), Lemma2.2.5, p.101. The converse fails. For ϕ(x)=1−e−x2\phi(x)=1-e^{-x^2}, the sublevel set for 0≤α<10\le\alpha<1 is

[−−ln⁡(1−α),−ln⁡(1−α)].[-\sqrt{-\ln(1-\alpha)},\sqrt{-\ln(1-\alpha)}].

It is empty for α<0\alpha<0 and all of R\mathbb R for α≥1\alpha\ge1. Every case is convex, but ϕ′′(x)=(2−4x2)e−x2<0\phi''(x)=(2-4x^2)e^{-x^2}<0 when ∣x∣>1/2|x|>1/\sqrt2. In contrast, x4−2x2x^4-2x^2 is not quasi-convex: at level −1/2-1/2 its sublevel set is two disjoint intervals, with ∣x∣|x| between 1−1/2\sqrt{1-1/\sqrt2} and 1+1/2\sqrt{1+1/\sqrt2}.

One interval versus two intervals distinguishes the two sublevel-set examples.

On R\mathbb R, x2x^2, x4x^4, xx, and 1−e−x21-e^{-x^2} distinguish the nested classes strongly convex, strictly convex, convex and quasi-convex, respectively.

Nested convexity classes with functions separating each implication.

Order notation and exact Taylor formulas

For sequences with νk≠0\nu_k\ne0 eventually, ηk=O(νk)\eta_k=O(\nu_k) means that some finite CC bounds ∣ηk∣≤C∣νk∣|\eta_k|\le C|\nu_k| for every sufficiently large kk. The notation ηk=o(νk)\eta_k=o(\nu_k) means ηk/νk→0\eta_k/\nu_k\to0. Analogously, as h→0h\to0, r(h)=O(hp)r(h)=O(h^p) means ∣r(h)∣≤C∣h∣p|r(h)|\le C|h|^p for sufficiently small nonzero hh; r(h)=o(hp)r(h)=o(h^p) means r(h)/hp→0r(h)/h^p\to0. For example, h2=o(h)h^2=o(h) and h2=O(h)h^2=O(h), but hh is not o(h)o(h). See Nocedal & Wright (2006), pp.631–632.

The relevant limit is usually clear from context: an error O(h2)O(h^2) concerns h→0h\to0, while an operation count O(n3)O(n^3) concerns n→∞n\to\infty. Constants and units remain relevant. Order one in hh alone does not guarantee three correct digits at h=10−3h=10^{-3}. Convergence-rate definitions belong in the algorithm lectures that use them, rather than another rate table here.

Scalar expansion

If ff is Cr+1C^{r+1} near aa, its finite expansion is

f(a+h)=∑j=0rf(j)(a)j!hj+O(hr+1)(h→0).f(a+h)=\sum_{j=0}^r\frac{f^{(j)}(a)}{j!}h^j+O(h^{r+1})\quad(h\to0).

This statement does not assert convergence of an infinite Taylor series to ff. See LeVeque (2007), §1.1, p.5 and §1.5, p.10.

The tangent and quadratic approximation have different local remainder orders.

Scalar-valued multivariate mean-value forms

Suppose the entire segment x+tp\mathbf x+t\mathbf p, 0≤t≤10\le t\le1, lies in a neighborhood where ff is C1C^1. Then some t1∈(0,1)t_1\in(0,1) satisfies

f(x+p)=f(x)+∇f(x+t1p)Tp.f(\mathbf x+\mathbf p)=f(\mathbf x)+\nabla f(\mathbf x+t_1\mathbf p)^{\mathsf T}\mathbf p.

If ff is C2C^2 there, some t2∈(0,1)t_2\in(0,1) satisfies

f(x+p)=f(x)+∇f(x)Tp+12pT∇2f(x+t2p)p.f(\mathbf x+\mathbf p)=f(\mathbf x)+\nabla f(\mathbf x)^{\mathsf T}\mathbf p +\tfrac12\mathbf p^{\mathsf T}\nabla^2f(\mathbf x+t_2\mathbf p)\mathbf p.

The two points need not be the same. Both statements are exact. To prove them, apply the corresponding one-dimensional theorem to g(t)=f(x+tp)g(t)=f(\mathbf x+t\mathbf p), using g′(t)=∇fTpg'(t)=\nabla f^{\mathsf T}\mathbf p and g′′(t)=pT∇2f pg''(t)=\mathbf p^{\mathsf T}\nabla^2f\,\mathbf p. See Biegler (2010), Thm.2.14, pp.27–28 and its errata; the extraneous Hessian transpose in the printed formula is removed.

Integral forms

Componentwise fundamental theorem of calculus gives the exact vector identity

∇f(x+p)−∇f(x)=∫01∇2f(x+tp)p dt.\nabla f(\mathbf x+\mathbf p)-\nabla f(\mathbf x) =\int_0^1\nabla^2f(\mathbf x+t\mathbf p)\mathbf p\,dt.

Integrating the scalar derivative twice also gives

f(x+p)=f(x)+∇f(x)Tp+∫01(1−t)pT∇2f(x+tp)p dt.f(\mathbf x+\mathbf p)=f(\mathbf x)+\nabla f(\mathbf x)^{\mathsf T}\mathbf p +\int_0^1(1-t)\mathbf p^{\mathsf T}\nabla^2f(\mathbf x+t\mathbf p)\mathbf p\,dt.

For the first formula, differentiate each component of ∇f(x+tp)\nabla f(\mathbf x+t\mathbf p) and integrate from zero to one. For the second, integrate the change in g′(t)g'(t), then interchange the order over the triangular region 0≤s≤t≤10\le s\le t\le1. Neither argument asserts a common vector mean-value point.

For the symmetric quadratic, ∇f=a+Bx\nabla f=\mathbf a+\mathbf B\mathbf x and ∇2f=B\nabla^2f=\mathbf B, so the second-order Taylor model is exact with no remainder. The integral of 1−t1-t is 1/21/2, recovering the quadratic term directly.

Finite differences, truncation and evaluation error

Assume ff is C3C^3 near aa and h>0h>0. Forward, backward and central approximations are

D+(h)=f(a+h)−f(a)h,D−(h)=f(a)−f(a−h)h,D0(h)=f(a+h)−f(a−h)2h.\begin{aligned} D_+(h)&=\frac{f(a+h)-f(a)}h,\\ D_-(h)&=\frac{f(a)-f(a-h)}h,\\ D_0(h)&=\frac{f(a+h)-f(a-h)}{2h}. \end{aligned}

Taylor expansion gives D+(h)−f′(a)=12f′′(a)h+O(h2)D_+(h)-f'(a)=\tfrac12 f''(a)h+O(h^2) and D−(h)−f′(a)=−12f′′(a)h+O(h2)D_-(h)-f'(a)=-\tfrac12 f''(a)h+O(h^2). For central differences, write both expansions before subtracting:

f(a+h)=f(a)+f′(a)h+12f′′(a)h2+O(h3),f(a−h)=f(a)−f′(a)h+12f′′(a)h2+O(h3).\begin{aligned} f(a+h)&=f(a)+f'(a)h+\tfrac12f''(a)h^2+O(h^3),\\ f(a-h)&=f(a)-f'(a)h+\tfrac12f''(a)h^2+O(h^3). \end{aligned}

The constant and second-order terms cancel. Thus f(a+h)−f(a−h)=2f′(a)h+O(h3)f(a+h)-f(a-h)=2f'(a)h+O(h^3) and D0(h)−f′(a)=O(h2)D_0(h)-f'(a)=O(h^2). With the C3C^3 expansion to the cubic term, the leading central error is f(3)(a)h2/6+o(h2)f^{(3)}(a)h^2/6+o(h^2). See Nocedal & Wright (2006), §8.1, pp.195–197.

A quadratic illustrates the backward and forward secants and their exact averaging identity for the central formula.

Why a smaller step can give a worse derivative

If each function evaluation has absolute error bounded by η\eta, the evaluation contribution is at most 2η/h2\eta/h for a one-sided formula and η/h\eta/h for central differences, before accounting for arithmetic and argument-rounding errors. Subtracting nearby computed function values can expose those errors. In particular, a floating-point sum a+ha+h can round back to aa.

A useful scale model is

E(h)≈Chp+Dηh,h∗≈(DηpC)1/(p+1)(C,D,η>0).E(h)\approx C h^p+\frac{D\eta}{h},\qquad h_*\approx\left(\frac{D\eta}{pC}\right)^{1/(p+1)}\quad(C,D,\eta>0).

Differentiate the model to obtain pChp−1−Dη/h2=0pC h^{p-1}-D\eta/h^2=0. The orders are h∗∼η1/2h_*\sim\eta^{1/2} for one-sided differences and h∗∼η1/3h_*\sim\eta^{1/3} for central differences, with best modeled errors of orders η1/2\eta^{1/2} and η2/3\eta^{2/3}. Constants depend on function/derivative scales. When the evaluation scale is order one and η\eta is of unit-roundoff size, these suggest steps around 10-8 and 10-5.3 in binary64. They are scale estimates, not universal optimal steps or exact measured minima.

For a full gradient in nn variables, a reused base value gives n+1n+1 evaluations for forward differences; central differences use 2n2n. This cost comparison concerns gradients built by finite differences, not every derivative-free algorithm.

Noisy functions and component scaling

If simulation or iterative-solve error dominates roundoff, use its evaluation-error scale in the model. Shrinking hh below that noise scale can make the derivative less useful. For forward differences, a practical component magnitude is ηrelmax⁡(∣xj∣,typ⁡xj)\sqrt{\eta_{\rm rel}}\max(|x_j|,\operatorname{typ}x_j), with a positive typical variable scale supplied by the modeler; the typical scale avoids a zero step at xj=0x_j=0. A signed perturbation or a different formula may be required at a bound or domain edge. See Dennis & Schnabel (1996), §5.4, Eqs.(5.4.8)–(5.4.10), pp.96–98. The corresponding central scaling has a cube-root dependence under its smooth error model.

Executed experiment

The cells below evaluate f(x)=exf(x)=e^x at a=1a=1 and a=10a=10 with binary64 function calls and arithmetic. The derivative reference eae^a is evaluated at 100 decimal digits and checked at 160. Thus the reported error compares the actual stored derivative approximation with the analytic derivative, not with a rounded binary64 reference. The plot is built one curve at a time; the final figure and archived data are also used by the lecture notes.

The step grid is h=10−16,10−15.75,…,100h=10^{-16},10^{-15.75},\ldots,10^0, four points per decade including both endpoints. Measured minima are restricted to this finite grid and can vary with the numerical library. The table prints every formula’s minimizing grid step and error for both evaluation points.

def finite_difference_experiment(point):
    """Measure binary64 exp differences against a converged high-precision derivative."""
    steps = np.power(10., np.arange(-16., .25, .25))
    base = float(np.exp(point))
    plus = np.exp(point + steps)
    minus = np.exp(point - steps)
    approximations = {
        'forward': (plus-base)/steps,
        'backward': (base-minus)/steps,
        'central': (plus-minus)/(2*steps),
    }
    def measure(digits):
        with mp.workdps(digits):
            reference = mp.exp(mp.mpf(float(point)))
            return {name:[float(abs(mp.mpf(float(value))-reference)) for value in values]
                    for name,values in approximations.items()}
    errors = measure(100)
    repeated = measure(160)
    for name in errors:
        assert np.array_equal(errors[name], repeated[name])
    with mp.workdps(100):
        reference_text = mp.nstr(mp.exp(mp.mpf(float(point))), 95)
    return {'a':float(point),'h':steps.tolist(),'f_a':base,
            'f_plus':plus.tolist(),'f_minus':minus.tolist(),
            'approximations':{name:values.tolist() for name,values in approximations.items()},
            'errors':errors,'derivative_reference':reference_text}

results = {'function':'exp','cases':[finite_difference_experiment(1.),finite_difference_experiment(10.)],
           'reference_digits':[100,160], 'step_grid':'10**arange(-16,0.25,0.25)',
           'error':'absolute error against the analytic derivative of exp at the stored point'}
summary_rows = []
for case in results['cases']:
    h = np.asarray(case['h'])
    for method, errors in case['errors'].items():
        errors = np.asarray(errors)
        index = int(np.argmin(errors))
        window = (h>=1e-4)&(h<=1e-1)&(errors>0)
        slope = float(np.polyfit(np.log10(h[window]),np.log10(errors[window]),1)[0])
        summary_rows.append({'a':case['a'],'formula':method,'step_at_grid_minimum':float(h[index]),
                             'minimum_absolute_error':float(errors[index]),'truncation_slope':slope})
results['summary'] = summary_rows
helper.save_results('finite-difference-error',results,
    notebook='notebooks/6-dev/Math-Primer-2.ipynb',
    source_cells=[('notebooks/6-dev/Math-Primer-2.ipynb','results:finite-difference-error')],
    description='Binary64 exponential differences at 1 and 10 with 100/160-digit analytic derivative references',
    solver='NumPy exp and arithmetic; mpmath analytic references',quiet=True)
display(pd.DataFrame(summary_rows))
Loading...

Forward Finite Difference

ff′(a)=f(a+ϵ)−f(a)ϵf'_f(a) = \frac{f(a+\epsilon) - f(a)}{\epsilon}
case = results['cases'][0]
fig, ax = plt.subplots(figsize=(7.6,4.8))
ax.loglog(case['h'],case['errors']['forward'],label='forward',color='black',linestyle='-',marker='s',markevery=4,ms=5)
ax.set(xlabel='step size h',ylabel="absolute error in f'(1)",title='Forward difference: exp at a=1')
ax.legend(); ax.grid(which='major',alpha=.25)
fig.tight_layout(); plt.show()
<Figure size 760x480 with 1 Axes>

Backward Finite Difference

fb′(a)=f(a)−f(a−ϵ)ϵf'_b(a) = \frac{f(a) - f(a - \epsilon)}{\epsilon}
case = results['cases'][0]
fig, ax = plt.subplots(figsize=(7.6,4.8))
for method,color,style,marker in [('forward','black','-','s'),('backward','#0072B2','--','o')]:
    ax.loglog(case['h'],case['errors'][method],label=method,color=color,linestyle=style,marker=marker,markevery=4,ms=5)
ax.set(xlabel='step size h',ylabel="absolute error in f'(1)",title='One-sided differences: exp at a=1')
ax.legend(); ax.grid(which='major',alpha=.25)
fig.tight_layout(); plt.show()
<Figure size 760x480 with 1 Axes>

Central Finite Difference

fc′(a)=f(a+ϵ)−f(a−ϵ)2ϵf'_c(a) = \frac{f(a+\epsilon) - f(a - \epsilon)}{2 \epsilon}
# Canonical plot: only archived results are needed to reproduce it.
case = results['cases'][0]
fig, ax = plt.subplots(figsize=(7.6,5.1))
for method,color,style,marker in [('forward','black','-','s'),
                                  ('backward','#0072B2','--','o'),
                                  ('central','#E69F00','-.','^')]:
    ax.loglog(case['h'],case['errors'][method],label=method,color=color,linestyle=style,
              marker=marker,markevery=3,markersize=5,linewidth=2)
ax.set(xlabel='step size h',ylabel="absolute error in f'(1)",
       title='Exponential at a=1; analytic derivative reference',xlim=(1e-17,3),ylim=(1e-13,1e2))
ax.legend(fontsize=12)
ax.grid(which='major',alpha=.25)
fig.tight_layout()
helper.save_figure(fig,'finite-difference-error',quiet=True)
plt.show()
<Figure size 760x510 with 1 Axes>

Read and extend the experiment

  1. Compare the actual minimizing steps and errors in the table with the order estimates. A grid minimum need not occur at the model’s exact optimum.

  2. Read the right-hand slopes from the three curves and compare them with the computed regression slopes. On the left, cancellation and argument rounding produce a jagged branch, not an exact straight line.

  3. Compare a=1a=1 with a=10a=10 in the table. The derivative and function scale grow by e9e^9, so absolute-error statements change even when the formulas have the same truncation orders.

Original test: exponential at 1

Use the three rows with a=1 in the executed table. They report the measured minima on this run’s grid. The central formula uses a larger best grid step and achieves a lower absolute error than the one-sided formulas in this example.

Variant: exponential at 10

The three a=10 rows are computed by the same function, grid and reference procedure. They replace historical hand-entered guesses. Library changes can alter the final digits and the location of a grid minimum; read the actual output.

Another test function

To study a different function, supply both its evaluation routine and its analytic derivative reference. Reusing exp(a) as the reference after changing the function would measure the wrong error. State the function, point, precision, domain and step grid with the results.

Discussion

Explain which change would alter the truncation constant, the function-evaluation noise, or the number of evaluations. Use those quantities to select a step range; a single best step is not valid for every function, variable scale or solver tolerance.