Three questions, three functions
- A taxi company in Nairobi charges a fixed fee plus an amount per kilometre. What will a km trip cost?
- A bus driver in Mumbai sees a child step into the road. How far does the bus travel before it stops, and how much farther at twice the speed?
- A family in Lima saves in an account that pays interest every year. When will their savings double?
Each question is about the real world, and each has an answer that comes from a function: linear for the taxi, quadratic for the stopping distance, exponential for the savings. But no formula is a taxi, a bus or a bank account. To get from the situation to a formula we must simplify: decide what matters, what to ignore and what to assume. To trust the answer we must check it against reality. This lesson is about that whole journey, which is called mathematical modelling.
The modelling cycle
- Simplify. Decide which features matter and state your assumptions ("the fare is the same at every time of day", "the road is dry", "the interest rate stays the same").
- Formulate. Choose variables and a function that links them.
- Solve. Do the mathematics: evaluate, solve an equation, find a maximum.
- Interpret. Translate the answer back: units, sensible ranges, what it means.
- Validate. Compare predictions with observations the model was not built from. If they disagree, revise the assumptions and go round again.
The statistician George Box put it memorably in 1979: "all models are wrong, but some are useful". A model leaves things out on purpose, and it is judged by whether it serves its purpose, not by whether it is "true".
Definitions
Definition— mathematical model
A mathematical model is a simplified mathematical description of a real situation, together with its assumptions. It relates variables (quantities that change, such as time or distance) through a function whose parameters (constants such as a rate or a starting value) are chosen to suit the situation.
Definition— fit, residual and validation
Fitting a model means choosing its parameters to match data. The residual of a data point is observed value minus predicted value. Validation compares a model's predictions with observations, preferably ones not used in fitting.
Definition— interpolation and extrapolation
Using a model inside the range of the data used to build it is interpolation; using it outside that range is extrapolation.
Fingerprints of three families
Suppose a quantity is measured at equally spaced times , giving values How can a table tell you which kind of function to try?
Theorem— Constant differences mean linear
If for every , then for every .
Proof
Induction: true for , and if then .
∎
Theorem— Constant ratios mean exponential
If for every , then for every .
Proof
Induction: .
∎
Theorem— Constant second differences mean quadratic
If the differences of the differences are constant, for every , then
a quadratic function of .
Proof
We prove the formula for and for together, by induction on . For both are immediate. If the formula holds for and , then , and substituting the two formulas and simplifying gives the formula for .
∎
Example— Reading a table
| 0 | 1 | 2 | 3 | 4 | |
|---|---|---|---|---|---|
| A | 7 | 10 | 13 | 16 | 19 |
| B | 2 | 5 | 10 | 17 | 26 |
| C | 3 | 6 | 12 | 24 | 48 |
Column A has constant differences : linear, . Column B has differences and constant second differences : quadratic, . Column C has constant ratio : exponential, . Real data are noisy, so in practice you look for differences or ratios that are roughly constant.
Theorem— Two points determine a line
If , there is exactly one line through and , namely and .
Proof
These values work: , and . If another line passes through both points, subtracting the two equations gives , so , and then .
∎
Theorem— Doubling time
A quantity with and continuous growth rate doubles in time , whatever its starting value. With yearly compounding at rate the doubling time is , which is at least as long.
Proof
. For yearly compounding, . Since , we have , and dividing by a smaller positive number gives a larger answer.
∎
At the doubling time is about years. This is the "rule of 70": divide by the percentage rate.
Building models
Example— Linear: the taxi fare (illustrative numbers)
Suppose a km trip costs shillings and a km trip costs . Assuming the fare is a fixed fee plus a constant amount per kilometre, the fare is linear in the distance . By the two-point theorem the slope is shillings per km, and the intercept is shillings. So , and a km trip costs shillings.
Interpret: is the price per kilometre and is the fixed fee. is the price of getting in and going nowhere. The model is meaningful only for , and it ignores waiting time, surge pricing and tolls.
Example— Quadratic: stopping distance
A vehicle's stopping distance has two parts. During the driver's reaction time the vehicle keeps its speed and travels . While braking with constant deceleration it travels . With the assumptions s and (a dry road),
At km/h ( m/s), m. At km/h ( m/s), m: doubling the speed doubles the reaction distance but quadruples the braking distance. On a wet road (, say) the braking distance would be much longer. Changing an assumption changes the prediction, and a good modeller reports both.
Example— Exponential: savings and a warning from biology
Savings growing at a year follow and double in years.
Exponential models can be spectacularly right for a while and then spectacularly wrong. In ideal laboratory conditions a bacterium such as E. coli can divide about every minutes. If that continued for hours, one cell would become cells, weighing far more than the Earth. In reality nutrients run out and growth slows. A better model then is the logistic model, in which the growth rate falls as the population approaches a limit (see mathematical biology).
Fitting a line to data: least squares
Real data never lie exactly on a line. Which line fits "best"? The standard answer, due to Legendre and Gauss, is the line that makes the sum of squared residuals
as small as possible. Squaring treats overshoots and undershoots alike and punishes large misses heavily.
Theorem— The best intercept is set by the means
Fix a slope and put , with mean . Then for every ,
So, for a given slope, the sum of squared residuals is smallest exactly when : the best line passes through the point of means .
Proof
Write and expand:
The middle sum is : deviations from the mean add up to zero. The last term is never negative and is zero only when .
∎
Now substitute . Writing , and , the sum of squares becomes
a quadratic in with positive leading coefficient (if the are not all equal). By the vertex formula of the quadratics lesson, its minimum is at
That is the least-squares line. To fit an exponential , take logarithms: is linear in , so fit a line to the points . This minimises errors on the logarithmic scale, which means roughly relative errors.
Validation: where models fail
A model earns trust by predicting what it was not built from. Three warnings:
- Fitting the past is not forecasting the future. In the computation section, a linear and an exponential model both fit world population for 1950–1980 closely, yet their forecasts for 2020 differ by more than billion people, and both miss.
- A perfect fit proves nothing. Through any data points with different -values there is a polynomial of degree less than passing exactly through all of them. A model with as many parameters as data points will always fit perfectly, and it typically forecasts nonsense. This is called overfitting.
- Data cannot decide extrapolation. The theorem below shows that infinitely many models agree exactly with any finite set of data and yet predict any value you like at a new point. What justifies an extrapolation is not the data alone but the reasons behind the model: a mechanism (such as Newton's law of cooling) or a well-tested assumption.
Theorem— Extrapolation is not determined by data
Let be any model and the points where we have data. For every number , the model
agrees with at every data point. At any new point (different from all ), choosing makes , for any value we like.
Proof
At the product contains the factor , so . At the product is a product of non-zero numbers, hence non-zero, so we may divide by it; substituting the chosen gives .
∎
Modelling facts, checked by Lean
Lean cannot check that a model suits a situation. That is a judgement about the world. But it can check the mathematics inside the modelling cycle. The fingerprints of the three families:
/-- **Constant differences mean a linear model.** If a quantity measured at times
`0, 1, 2, …` always changes by the same amount `d`, then `u n = u 0 + n d`. Induction on `n`. -/
theorem linear_of_const_diff (u : ℕ → ℝ) (d : ℝ) (h : ∀ n, u (n + 1) - u n = d) (n : ℕ) :
u n = u 0 + n * d := by
induction n with
| zero => simp
| succ n ih =>
have := h n
push_cast
linarith/-- **Constant ratios mean an exponential model.** If each value is `b` times the one before,
then `u n = u 0 · bⁿ`. Induction on `n`. -/
theorem exponential_of_const_ratio (u : ℕ → ℝ) (b : ℝ) (h : ∀ n, u (n + 1) = b * u n) (n : ℕ) :
u n = u 0 * b ^ n := by
induction n with
| zero => simp
| succ n ih => rw [h n, ih, pow_succ]; ring/-- **Constant second differences mean a quadratic model.** If the differences of the
differences are always `c`, then `u n = u 0 + n (u 1 − u 0) + c · n(n − 1)/2`, a quadratic in `n`.
We prove the formula for `n` and `n + 1` together, by induction. -/
theorem quadratic_of_const_second_diff (u : ℕ → ℝ) (c : ℝ)
(h : ∀ n, u (n + 2) - 2 * u (n + 1) + u n = c) (n : ℕ) :
u n = u 0 + n * (u 1 - u 0) + c * (n * (n - 1) / 2) := by
have key : ∀ n : ℕ, u n = u 0 + n * (u 1 - u 0) + c * (n * (n - 1) / 2) ∧
u (n + 1) = u 0 + (n + 1) * (u 1 - u 0) + c * ((n + 1) * n / 2) := by
intro n
induction n with
| zero => constructor <;> simp
| succ n ih =>
obtain ⟨h0, h1⟩ := ih
refine ⟨by push_cast; linarith, ?_⟩
have h2 := h n
push_cast
linear_combination h2 + 2 * h1 - h0
exact (key n).1Fitting. ∃! means "there exists exactly one", and ∑ i, … is a sum over the data points i : Fin n:
/-- **Two points with different `x` determine exactly one line** `y = m x + c`:
`m = (y₂ − y₁)/(x₂ − x₁)` and `c = y₁ − m x₁`. If two lines pass through both points, subtracting
gives `(m − m')(x₁ − x₂) = 0`, so `m = m'` and then `c = c'`. -/
theorem line_through_two_points {x₁ y₁ x₂ y₂ : ℝ} (hx : x₁ ≠ x₂) :
∃! p : ℝ × ℝ, p.1 * x₁ + p.2 = y₁ ∧ p.1 * x₂ + p.2 = y₂ := by
have hd : x₂ - x₁ ≠ 0 := sub_ne_zero.mpr (Ne.symm hx)
refine ⟨((y₂ - y₁) / (x₂ - x₁), y₁ - (y₂ - y₁) / (x₂ - x₁) * x₁), ⟨by ring, ?_⟩, ?_⟩
· field_simp
ring
· rintro ⟨m, c⟩ ⟨h₁, h₂⟩
have hm : m = (y₂ - y₁) / (x₂ - x₁) := by
field_simp
linear_combination h₂ - h₁
simp only [Prod.mk.injEq]
exact ⟨hm, by rw [← hm]; linarith⟩/-- **The best intercept is set by the means.** For data `r₁, …, rₙ` (in a line fit,
`rᵢ = yᵢ − m xᵢ` for a chosen slope `m`) and any `c`,
`Σ (rᵢ − c)² = Σ (rᵢ − c̄)² + n (c − c̄)²`, where `c̄ = (Σ rᵢ)/n` is the mean.
So the sum of squared errors is smallest exactly at `c = c̄`, that is,
`c = mean(y) − m · mean(x)`. The proof expands the square; the cross term vanishes because
the deviations from the mean add up to zero. -/
theorem least_squares_intercept {n : ℕ} (hn : 0 < n) (r : Fin n → ℝ) (c : ℝ) :
∑ i, (r i - c) ^ 2 =
∑ i, (r i - (∑ j, r j) / n) ^ 2 + n * (c - (∑ j, r j) / n) ^ 2 := by
set cbar := (∑ j, r j) / n with hcbar
have hn' : (n : ℝ) ≠ 0 := by exact_mod_cast hn.ne'
-- the deviations from the mean add up to zero
have hdev : ∑ i, (r i - cbar) = 0 := by
rw [Finset.sum_sub_distrib, Finset.sum_const, Finset.card_univ, Fintype.card_fin,
nsmul_eq_mul, hcbar]
field_simp
ring
have hexpand : ∀ i, (r i - c) ^ 2 = (r i - cbar) ^ 2 + 2 * (cbar - c) * (r i - cbar) +
(c - cbar) ^ 2 := fun i => by ring
simp_rw [hexpand, Finset.sum_add_distrib, ← Finset.mul_sum, hdev, Finset.sum_const,
Finset.card_univ, Fintype.card_fin, nsmul_eq_mul]
ring/-- **Corollary:** no intercept does better than the mean: `Σ (rᵢ − c̄)² ≤ Σ (rᵢ − c)²`. -/
theorem least_squares_min {n : ℕ} (hn : 0 < n) (r : Fin n → ℝ) (c : ℝ) :
∑ i, (r i - (∑ j, r j) / n) ^ 2 ≤ ∑ i, (r i - c) ^ 2 := by
rw [least_squares_intercept hn r c]
have : 0 ≤ (n : ℝ) * (c - (∑ j, r j) / n) ^ 2 := by positivity
linarithDoubling times, using the inequality from Mathlib:
/-- **Doubling time of continuous growth.** A quantity `A eʳᵗ` with `A > 0` and rate `r > 0`
doubles exactly when `t = ln 2 / r`: `A eʳᵗ = 2A ⇔ eʳᵗ = 2 ⇔ rt = ln 2`. At `r = 0.05` (5%) this
is about `13.9` time units: the "rule of 70" says `70/5 = 14`. -/
theorem doubling_time {A r : ℝ} (hA : 0 < A) (hr : 0 < r) (t : ℝ) :
A * exp (r * t) = 2 * A ↔ t = log 2 / r := by
constructor
· intro h
have h1 : exp (r * t) = 2 := by
have := mul_left_cancel₀ hA.ne' (h.trans (mul_comm 2 A))
exact this
have h2 : r * t = log 2 := by rw [← h1, log_exp]
field_simp
linarith
· intro ht
rw [ht, mul_div_cancel₀ _ hr.ne', exp_log (by norm_num)]
ring/-- **Yearly compounding doubles no faster than continuous growth at the same rate:**
`ln 2 / r ≤ ln 2 / ln(1 + r)` for `r > 0`. The key step is `ln(1 + r) ≤ r`, from Mathlib's
`Real.add_one_le_exp` (`1 + r ≤ eʳ`). -/
theorem yearly_doubling_slower {r : ℝ} (hr : 0 < r) : log 2 / r ≤ log 2 / log (1 + r) := by
have hlog_pos : 0 < log (1 + r) := log_pos (by linarith)
have hlog_le : log (1 + r) ≤ r := by
have h := add_one_le_exp r
calc log (1 + r) ≤ log (exp r) := log_le_log (by linarith) (by linarith)
_ = r := log_exp r
exact div_le_div_of_nonneg_left (log_nonneg (by norm_num)) hlog_pos hlog_le/-- `1 + x ≤ eˣ` for every real `x` (the tangent line at `0` lies below the graph). This applies
Mathlib's `Real.add_one_le_exp`. -/
theorem add_one_le_exp_library (x : ℝ) : x + 1 ≤ exp x :=
add_one_le_exp xAnd the two theorems about what data cannot tell us. The first comes from Mathlib (Lagrange interpolation); the second is proved here:
/-- **A perfect fit is always available.** For any `n` data points `(xᵢ, yᵢ)` with distinct
`xᵢ`, some polynomial passes through all of them (Lagrange interpolation; its degree can be
taken below `n`). This applies Mathlib's `Polynomial.exists_eval_eq_iff`. So a model that fits
the data perfectly has not yet earned our trust. -/
theorem perfect_fit_exists {n : ℕ} (x y : Fin n → ℝ) (hx : Function.Injective x) :
∃ q : Polynomial ℝ, ∀ i, q.eval (x i) = y i :=
(Polynomial.exists_eval_eq_iff x y).mpr fun i j hij => by rw [hx hij]/-- **Data cannot decide extrapolation.** Let `f` be any model and `S` the finite set of
`x`-values where we have data. The models `f(x) + k · ∏_{s ∈ S} (x − s)` agree with `f` at every
data point, for every `k`. At a new point `x₀ ∉ S` the product is not zero, so by choosing `k`
we can make the model predict *any* value `v` there. -/
theorem extrapolation_undetermined (f : ℝ → ℝ) (S : Finset ℝ) {x₀ : ℝ} (hx₀ : x₀ ∉ S) (v : ℝ) :
∃ k : ℝ, (∀ x ∈ S, f x + k * ∏ s ∈ S, (x - s) = f x) ∧
f x₀ + k * ∏ s ∈ S, (x₀ - s) = v := by
have hprod : ∏ s ∈ S, (x₀ - s) ≠ 0 := by
rw [Finset.prod_ne_zero_iff]
intro s hs h
exact hx₀ (sub_eq_zero.mp h ▸ hs)
refine ⟨(v - f x₀) / ∏ s ∈ S, (x₀ - s), ?_, ?_⟩
· intro x hx
have : ∏ s ∈ S, (x - s) = 0 := Finset.prod_eq_zero hx (sub_self x)
rw [this, mul_zero, add_zero]
· field_simp
ringValidating models against data
"""Linear or exponential? Fitting world population and testing the forecast.
We fit two models to approximate world population for 1950-1980 (UN
estimates, rounded to 0.1 billion): a straight line, and an exponential
P = A e^(r t) fitted as a straight line through (t, ln P). Then we compare
each model's forecasts for 1990-2020 with the later estimates. This is how a
model is validated: by predictions it was not built from.
"""
import math
#: World population in billions, approximate UN estimates rounded to 0.1.
YEARS = [1950, 1960, 1970, 1980, 1990, 2000, 2010, 2020]
POPULATION = [2.5, 3.0, 3.7, 4.4, 5.3, 6.1, 7.0, 7.8]
def fit_line(xs, ys):
"""Least-squares line y = m x + c; returns (m, c)."""
n = len(xs)
if n < 2 or len(set(xs)) < 2:
raise ValueError("need at least two different x-values")
mx, my = sum(xs) / n, sum(ys) / n
sxx = sum((x - mx) ** 2 for x in xs)
sxy = sum((x - mx) * (y - my) for x, y in zip(xs, ys))
m = sxy / sxx
return m, my - m * mx
def fit_exponential(ts, ps):
"""Fit P = A e^(r t) by a least-squares line through (t, ln P).
Returns (A, r).
"""
r, log_a = fit_line(ts, [math.log(p) for p in ps])
return math.exp(log_a), r
def doubling_time(r):
"""Time for e^(r t) to double: ln 2 / r."""
if r <= 0:
raise ValueError("growth rate must be positive")
return math.log(2) / r
def main():
k = 4 # fit on 1950-1980 only
ts = [y - 1950 for y in YEARS]
m, c = fit_line(ts[:k], POPULATION[:k])
a, r = fit_exponential(ts[:k], POPULATION[:k])
print("Models fitted to 1950-1980 (t = years after 1950, P in billions):")
print(f" linear: P = {c:.3f} + {m:.4f} t")
print(f" exponential: P = {a:.3f} e^({r:.4f} t)")
print(f" (growth {100 * r:.2f}% a year: doubling every"
f" {doubling_time(r):.0f} years)")
print()
print("year estimate linear error exponential error")
for year, t, p in zip(YEARS, ts, POPULATION):
lin, expo = c + m * t, a * math.exp(r * t)
tag = "fitted" if year <= 1980 else "forecast"
print(f"{year} {p:7.1f} {lin:8.2f} {lin - p:+6.2f} {expo:10.2f}"
f" {expo - p:+6.2f} {tag}")
print()
rates = [math.log(POPULATION[i + 1] / POPULATION[i]) / 10
for i in range(len(YEARS) - 1)]
print("average growth rate in each decade (% a year):")
print(" " + " ".join(f"{YEARS[i]}s {100 * g:.1f}" for i, g in
enumerate(rates[:4])))
print(" " + " ".join(f"{YEARS[i]}s {100 * g:.1f}" for i, g in
enumerate(rates[4:], start=4)))
print("The exponential model assumes a constant rate. The rate peaked in the")
print("1960s and has fallen since (decade rates from rounded data are rough),")
print("so its forecast overshoots. The line (a fixed yearly increase)")
print("undershoots.")
print()
print("Epistemic status: numerical computation on rounded estimates (which")
print("are themselves revised between UN editions). The comparison shows how")
print("two models fitted to the same past data can forecast differently; it")
print("is not a demographic projection.")
if __name__ == "__main__":
main()Both models fit the decades they were built from to within billion. Only the forecasts tell them apart, and both fail, in opposite directions. The exponential model's assumption of a constant growth rate broke down: the rate peaked in the 1960s and has fallen since. Population researchers use far more detailed models, built from birth rates, death rates and age structure.
Now an experiment where we know the truth, because we make the data ourselves. The readings below are synthetic: generated from Newton's law of cooling with small random errors added.
"""A perfect fit that predicts nonsense: overfitting a cooling cup of tea.
We generate SYNTHETIC data from Newton's law of cooling,
T(t) = 25 + 60 e^(-0.1 t) degrees C, add small seeded random "measurement
errors", and fit three models to the eight readings at t = 0, 2, ..., 14
minutes: a straight line, Newton's model (fitted through ln(T - 25)), and the
degree-7 polynomial that passes through every reading exactly. Then we ask
each model about t = 20 and t = 30 minutes, where the true curve is known.
"""
import math
import random
ROOM = 25.0
def true_temperature(t):
"""The synthetic 'truth': Newton's law with T0 = 85 C, room 25 C, k = 0.1."""
return ROOM + 60.0 * math.exp(-0.1 * t)
def synthetic_readings(seed=7, noise=0.4):
"""Eight readings at t = 0, 2, ..., 14 with seeded Gaussian noise."""
rng = random.Random(seed)
ts = list(range(0, 16, 2))
return ts, [true_temperature(t) + rng.gauss(0, noise) for t in ts]
def fit_line(xs, ys):
"""Least-squares line y = m x + c; returns (m, c)."""
n = len(xs)
mx, my = sum(xs) / n, sum(ys) / n
m = (sum((x - mx) * (y - my) for x, y in zip(xs, ys))
/ sum((x - mx) ** 2 for x in xs))
return m, my - m * mx
def fit_newton(ts, temps):
"""Fit T = ROOM + D e^(-k t) via a line through (t, ln(T - ROOM))."""
slope, intercept = fit_line(ts, [math.log(T - ROOM) for T in temps])
return math.exp(intercept), -slope
def lagrange(xs, ys, x):
"""Value at x of the polynomial of degree < len(xs) through all points."""
total = 0.0
for i, (xi, yi) in enumerate(zip(xs, ys)):
term = yi
for j, xj in enumerate(xs):
if j != i:
term *= (x - xj) / (xi - xj)
total += term
return total
def rms(errors):
"""Root-mean-square of a list of errors."""
return math.sqrt(sum(e * e for e in errors) / len(errors))
def main():
ts, temps = synthetic_readings()
m, c = fit_line(ts, temps)
d, k = fit_newton(ts, temps)
models = {
"line": lambda t: m * t + c,
"Newton": lambda t: ROOM + d * math.exp(-k * t),
"degree 7": lambda t: lagrange(ts, temps, t),
}
print("SYNTHETIC readings (minutes, degrees C):")
print(" " + " ".join(f"{t}:{T:.1f}" for t, T in zip(ts, temps)))
print(f"Newton fit: T = 25 + {d:.1f} e^(-{k:.4f} t) (truth: 60, 0.1)")
print()
print(f"{'model':>9} {'RMS error on data':>17} {'T(20)':>8} {'T(30)':>8}")
for name, f in models.items():
err = rms([f(t) - T for t, T in zip(ts, temps)])
print(f"{name:>9} {err:17.3f} {f(20):8.1f} {f(30):8.1f}")
print(f"{'truth':>9} {'':17} {true_temperature(20):8.1f}"
f" {true_temperature(30):8.1f}")
print()
print("The degree-7 polynomial fits the data perfectly (error 0) and")
print("forecasts temperatures no cup of tea could reach. The line looks")
print("reasonable on the data but predicts the tea will cool below room")
print("temperature. Newton's model, which encodes why tea cools, has small")
print("errors on the data and forecasts well.")
print()
print("Epistemic status: one experiment on synthetic data with a known")
print("truth and a fixed random seed. It illustrates overfitting and")
print("extrapolation risk; it does not measure how often such models fail,")
print("and real cooling also depends on things this model ignores.")
if __name__ == "__main__":
main()The polynomial with zero error on the data is the worst model of all. The model with a reason behind it, that tea cools in proportion to how much warmer it is than the room, extrapolates well.
Explore: fit the population data yourself
The points are the approximate population estimates (in billions) used above. Adjust and to fit the exponential model , and and for the linear model . Try fitting only the first four points, then look at the rest. Can either model fit all eight points well? Which parameter values describe 1990–2020?
World population: two models
Move the sliders and trace along the curves to read off values.
- exponential A·e^(r(x − 1950))
- linear m(x − 1950) + c
- exponential A·e^(r(x − 1950)): y = 2.0674
- linear m(x − 1950) + c: y = 1.8
Exercises
1. Mathematical modelling with functions
Warm-upHumanA quantity measured every hour gives . Which kind of model fits these values exactly?
2. Mathematical modelling with functions
Warm-upHumanA table of a quadratic model shows at . What value does the model give at ?
3. Mathematical modelling with functions
CoreHumanA km taxi ride costs shillings and an km ride costs shillings. Assuming a fixed fee plus a constant charge per km, what is the fixed fee, in shillings?
4. Mathematical modelling with functions
CoreHumanA town's population grows continuously at a year, . About how long does it take to double?
5. Mathematical modelling with functions
CoreHumanIn the model , the braking part is . If a driver doubles the speed (same road, same brakes), what happens to the braking distance?
6. Mathematical modelling with functions
StretchHumanA student fits a polynomial of degree through all data points of a sales record, with zero error. What can you conclude about its forecast for next year?
7. Mathematical modelling with functions
StretchHumanIn the proof that the best intercept is we expand . Why does the middle term vanish?
8. Mathematical modelling with functions
CoreFormalWhich Lean statement says “if each value is times the previous one, the model is exponential”? (Here u : ℕ → ℝ lists the measurements.)
9. Mathematical modelling with functions
StretchComputationalWrite fit_line(xs, ys) that returns the least-squares line as a pair (m, c), using and , where and .
Common misconceptions
Misconception
Treating a model's output as fact. "The model says the population will be billion in 2020" is a statement about the model's assumptions (here, a constant growth rate), not about the world. Always report predictions together with the assumptions they rest on.
Misconception
Choosing the model that best fits past data, whatever it is. A model with enough parameters can fit any data perfectly, and the fit says nothing about its forecasts. Prefer models with a plausible mechanism and few parameters, and test them on data they were not fitted to.
Misconception
"A good fit inside the data means it is safe to extrapolate far outside." Extrapolation is where models most often fail. The data constrain a model only where the data are, and the extrapolation theorem shows they cannot pin down predictions anywhere else.
Misconception
"Exponential growth can go on for ever." Every real exponential process eventually meets a limit — food, space, money or people. The exponential model describes a phase, not a destiny.
Many ways of seeing
Geometry— Least squares is a perpendicular
List the observations as one vector in -dimensional space. The predictions of all lines, , form a plane through the origin, spanned by and . The least-squares line picks the point of this plane closest to , which is the foot of the perpendicular from to the plane. Perpendicularity to says the residuals add up to zero (the "means" theorem above); perpendicularity to gives the slope formula. Fitting is projection (see linear algebra).
Probability— Why squares?
If each measurement equals the true value plus an independent random error with a normal ("bell curve") distribution, then the least-squares line is the line under which the observed data are most likely. Gauss justified least squares in roughly this way in 1809. With other kinds of error, for instance occasional wild outliers, other criteria such as minimising the sum of absolute residuals can be better. Statistics also says how uncertain the fitted parameters are, which is the next question a careful modeller asks (see statistical reasoning).
Physics— Models from mechanisms, and units as a check
Physicists prefer models derived from a mechanism. Newton's law of cooling assumes that heat flows out at a rate proportional to the temperature difference , and that assumption forces the exponential form . A cheap test of any model is units: in , both terms are lengths (m/s × s, and (m/s)² ÷ m/s²). A formula that adds metres to seconds is wrong before any data are consulted.
History and global context
- Interpolation in astronomy. Calendar makers needed values between their observations. In China, Liu Zhuo (around 600 CE) used second-order interpolation, equivalent to fitting quadratics through equally spaced values. Guo Shoujing's Shoushi calendar (1281) used third-order differences. In India, Brahmagupta's Khaṇḍakhādyaka (665 CE) gave a second-order interpolation rule for sine tables.
- Least squares. Adrien-Marie Legendre published the method of least squares in 1805. Carl Friedrich Gauss, who said he had used it since 1795, published his probabilistic justification in 1809, after famously predicting where the dwarf planet Ceres would reappear.
- Population and growth. Thomas Malthus (1798) contrasted populations that grow geometrically with food supplies that grow arithmetically. Pierre-François Verhulst (1838) proposed the logistic model, in which growth slows as a population approaches a limit. In 1927, William Kermack and Anderson McKendrick founded mathematical epidemiology with their model of epidemics.
- Newton's law of cooling was published, anonymously, by Isaac Newton in 1701.
Further reading
- Edward A. Bender, An Introduction to Mathematical Modeling (1978) — many short, varied models with honest discussion of their assumptions.
- Frank R. Giordano, Maurice D. Weir and William P. Fox, A First Course in Mathematical Modeling (several editions) — a standard textbook organised around the modelling cycle.
- COMAP and SIAM, Guidelines for Assessment and Instruction in Mathematical Modeling Education (GAIMME) (2016) — a free guide to modelling at school level.
- George E. P. Box, "Science and Statistics", Journal of the American Statistical Association (1976) — on the role of models in science.