Skip to content
The Lumenary
Grades 9–12Ages 15–18 75 min

Functions and their graphs (precalculus)

Learn a few graphs well and you know thousands — by shifting, stretching, reflecting, composing and inverting them.

Formally verified · 14 LeanComputationally tested · 2 PythonAI-drafted · awaiting human reviewMathematically reviewed: Awaiting human review

Your guides: Chloe, Margaret, Gideon

MotivationH

Knowing one graph means knowing many

A student in Lagos and her cousin in Toronto compare the weather by video call. She thinks in degrees Celsius, he in Fahrenheit. The conversion

F=95 C+32F = \tfrac95\,C + 32

is a function: one input, exactly one output. Its graph is a straight line. To convert back, he needs the inverse function C=59(F−32)C = \tfrac59(F - 32), whose graph is the first line reflected in the diagonal. If the forecast says "1010 degrees warmer tomorrow", that is another function, C↦C+10C \mapsto C + 10. Doing one function after another is composition.

This lesson is about seeing functions whole. If you know the graph of y=x2y = x^2, you know the graph of y=2(x−3)2+1y = 2(x - 3)^2 + 1 without plotting a single new point. If you know the graph of ff, you know the graph of f−1f^{-1} for free. And from a formula like 2x+1x−3\dfrac{2x + 1}{x - 3} you will be able to predict where its graph shoots off to infinity and what it looks like far away.

IntuitionH

A graph is a portrait of a function

In the lesson on functions we met a function as a rule that gives every input in its domain exactly one output. For real functions, we can draw all the pairs (input, output) at once as points (x,f(x))(x, f(x)) in the plane. That picture is the graph.

The graph lets you read off properties at a glance:

  • the domain is the shadow of the graph on the xx-axis, and the range is its shadow on the yy-axis;
  • the zeros are where it meets the xx-axis;
  • increasing means the graph climbs as you move right;
  • a vertical line meets the graph of a function at most once (one input, one output) — the vertical line test;
  • a horizontal line meets it at most once exactly when the function is injective — the horizontal line test — and that, we will prove, is what an inverse needs.
DefinitionsH

Definitions

Definition— real function, natural domain, graph

A real function ff assigns to each number xx in its domain D⊆RD \subseteq \R exactly one real number f(x)f(x). When a function is given only by a formula, its natural domain is the set of all real xx for which the formula makes sense. The graph of ff is the set of points

graph⁡f={ (x,f(x)):x∈D }⊆R×R.\operatorname{graph} f = \{\, (x, f(x)) : x \in D \,\} \subseteq \R \times \R.

The range is the set of outputs {f(x):x∈D}\{ f(x) : x \in D \}.

For example, x−1\sqrt{x - 1} has natural domain [1,∞)[1, \infty), 1x2−4\dfrac{1}{x^2 - 4} has natural domain R∖{−2,2}\R \setminus \{-2, 2\}, and every polynomial has natural domain R\R.

Definition— increasing, even and odd

ff is strictly increasing on a set SS if x<yx < y implies f(x)<f(y)f(x) < f(y) for all x,y∈Sx, y \in S (and strictly decreasing if it implies f(x)>f(y)f(x) > f(y)). On a domain symmetric about 00, ff is even if f(−x)=f(x)f(-x) = f(x) for all xx, and odd if f(−x)=−f(x)f(-x) = -f(x) for all xx.

The graph of an even function is symmetric in the yy-axis (x2x^2, ∣x∣|x|, x4−3x2x^4 - 3x^2). The graph of an odd function is symmetric under a half-turn about the origin (x3x^3, 1/x1/x, x3−5xx^3 - 5x). Most functions, such as x2+xx^2 + x, are neither.

Definition— composition and inverse

The composite g∘fg \circ f is the function (g∘f)(x)=g(f(x))(g \circ f)(x) = g(f(x)). Its natural domain is the set of xx in the domain of ff with f(x)f(x) in the domain of gg. A function g:B→Ag : B \to A is an inverse of f:A→Bf : A \to B if

g(f(x))=x for all x∈Aandf(g(y))=y for all y∈B.g(f(x)) = x \text{ for all } x \in A \quad\text{and}\quad f(g(y)) = y \text{ for all } y \in B.

We then write g=f−1g = f^{-1}.

Definition— asymptotes and end behaviour (informal)

The line y=Ly = L is a horizontal asymptote of ff if f(x)f(x) gets as close to LL as we like once xx is large enough (or once xx is negative enough); we write f(x)→Lf(x) \to L as x→∞x \to \infty (or −∞-\infty). The line x=ax = a is a vertical asymptote if ∣f(x)∣|f(x)| grows beyond every bound as xx approaches aa from at least one side. The end behaviour of ff describes what f(x)f(x) does as x→±∞x \to \pm\infty.

These last definitions use the idea of a limit informally. It is made precise in calculus, and the Lean proof below uses the precise version.

Worked examplesH

A gallery of function families

Example— The basic shapes

  • Linear y=mx+cy = mx + c: a straight line with slope mm (see linear relationships).
  • Quadratic y=ax2+bx+cy = ax^2 + bx + c: a parabola (see quadratics).
  • Powers y=xny = x^n: for even nn U-shaped and even; for odd nn S-shaped, odd and strictly increasing.
  • Absolute value y=∣x∣y = |x|: a V with its corner at the origin; ∣x∣=x|x| = x for x≥0x \ge 0 and ∣x∣=−x|x| = -x for x<0x < 0.
  • Square root y=xy = \sqrt{x} on [0,∞)[0, \infty): half of a sideways parabola.
  • Reciprocal y=1/xy = 1/x on x≠0x \ne 0: a hyperbola with asymptotes x=0x = 0 and y=0y = 0.

Example— A piecewise function: a block tariff

Many electricity and water utilities charge in blocks. Here is an illustrative tariff in the style used by several municipalities in southern Africa: the first 5050 kWh in a month cost 1.201.20 per kWh and each further kWh costs 1.801.80. The monthly bill for xx kWh is

B(x)={1.2 x,0≤x≤50,60+1.8 (x−50),x>50.B(x) = \begin{cases} 1.2\,x, & 0 \le x \le 50, \\ 60 + 1.8\,(x - 50), & x > 50. \end{cases}

The two pieces agree at x=50x = 50 (both give 6060), so the graph has no jump, only a bend where the slope increases from 1.21.2 to 1.81.8.

Example— A rational function

r(x)=2x+1x−3r(x) = \dfrac{2x + 1}{x - 3} has natural domain x≠3x \ne 3. Dividing, r(x)=2+7x−3r(x) = 2 + \dfrac{7}{x - 3}. So:

  • as x→±∞x \to \pm\infty, 7x−3→0\tfrac{7}{x - 3} \to 0 and r(x)→2r(x) \to 2: horizontal asymptote y=2y = 2;
  • as x→3x \to 3, 7x−3\tfrac{7}{x - 3} becomes huge, positive just to the right of 33 and negative just to the left: vertical asymptote x=3x = 3;
  • the zero is at 2x+1=02x + 1 = 0, so x=−12x = -\tfrac12; the yy-intercept is r(0)=−13r(0) = -\tfrac13.

Its graph is the hyperbola y=7/xy = 7/x stretched and moved: right by 33 and up by 22.

Example— Holes are not asymptotes

x2−1x−1=(x−1)(x+1)x−1=x+1\dfrac{x^2 - 1}{x - 1} = \dfrac{(x - 1)(x + 1)}{x - 1} = x + 1 for every x≠1x \ne 1. Its graph is the line y=x+1y = x + 1 with the single point (1,2)(1, 2) missing — a hole, not an asymptote. A zero of the denominator gives a vertical asymptote only if it does not cancel against the numerator.

Example— End behaviour of polynomials

For large ∣x∣|x| the leading term wins. For p(x)=−2x3+50x2+7p(x) = -2x^3 + 50x^2 + 7,

p(x)=−2x3(1−25x−72x3),p(x) = -2x^3\left(1 - \frac{25}{x} - \frac{7}{2x^3}\right),

and the bracket tends to 11. So p(x)→−∞p(x) \to -\infty as x→∞x \to \infty and p(x)→+∞p(x) \to +\infty as x→−∞x \to -\infty, like −2x3-2x^3, even though p(10)=3007p(10) = 3007 is positive.

Worked examplesH

Transforming graphs

Starting from the graph of y=f(x)y = f(x):

New functionWhat happens to the graph
y=f(x)+ky = f(x) + kmoves up by kk
y=f(x−h)y = f(x - h)moves right by hh
y=a f(x)y = a\,f(x)stretches vertically by the factor ∣a∣\lvert a \rvert (and reflects in the xx-axis if a<0a < 0)
y=f(bx)y = f(bx)squeezes horizontally by the factor ∣b∣\lvert b \rvert (and reflects in the yy-axis if b<0b < 0)

Example— Building y = −2|x − 1| + 3 from y = |x|

Start with the V of y=∣x∣y = |x|, corner at (0,0)(0, 0). Replace xx by x−1x - 1: the corner moves right to (1,0)(1, 0). Multiply by −2-2: the V flips upside down and becomes twice as steep. Add 33: the corner rises to (1,3)(1, 3). The result is an upside-down V with its peak at (1,3)(1, 3), crossing the xx-axis where ∣x−1∣=32|x - 1| = \tfrac32, at x=−12x = -\tfrac12 and x=52x = \tfrac52.

Example— The order matters

y=f(2x−6)y = f(2x - 6) is y=f(2(x−3))y = f\big(2(x - 3)\big): squeeze by 22 and shift right by 33, not by 66. Always factor out bb first to read off hh.

ProofH

Proofs

Theorem— Transformation rule

Let b≠0b \ne 0. A point (x,y)(x, y) lies on the graph of y=f(x)y = f(x) if and only if the point (xb+h, ay+k)\left(\tfrac{x}{b} + h,\ a y + k\right) lies on the graph of y=a f(b(X−h))+ky = a\,f\big(b(X - h)\big) + k. In particular (a=b=1a = b = 1, k=0k = 0), the graph of y=f(x−h)y = f(x - h) is the graph of ff moved hh units to the right.

Proof

Write g(X)=af(b(X−h))+kg(X) = a f(b(X - h)) + k. If y=f(x)y = f(x) and X=xb+hX = \tfrac{x}{b} + h, then b(X−h)=xb(X - h) = x, so g(X)=af(x)+k=ay+kg(X) = a f(x) + k = ay + k: the moved point is on the graph of gg. Conversely, every point (X,g(X))(X, g(X)) of the graph of gg arises this way, from the point (x,f(x))(x, f(x)) with x=b(X−h)x = b(X - h). So the graph of gg is exactly the image of the graph of ff under the move.

For the shift: the output that ff produces at input x0x_0, the function x↦f(x−h)x \mapsto f(x - h) produces when x−h=x0x - h = x_0, that is, at x=x0+hx = x_0 + h — later by hh. That is why subtracting hh moves the graph to the right.

∎

Theorem— Inverses and bijections

A function f:A→Bf : A \to B has an inverse if and only if it is a bijection (injective and surjective). The inverse is then unique.

Proof

If gg is an inverse and f(x1)=f(x2)f(x_1) = f(x_2), then x1=g(f(x1))=g(f(x2))=x2x_1 = g(f(x_1)) = g(f(x_2)) = x_2, so ff is injective. Every y∈By \in B equals f(g(y))f(g(y)), so ff is surjective. Conversely, if ff is a bijection, each y∈By \in B is f(x)f(x) for exactly one x∈Ax \in A. Define g(y)g(y) to be that xx; then g(f(x))=xg(f(x)) = x and f(g(y))=yf(g(y)) = y. If g′g' is another inverse, then g′(y)=g′(f(g(y)))=g(y)g'(y) = g'(f(g(y))) = g(y) for every yy.

∎

Theorem— Strictly monotone functions are injective

If ff is strictly increasing (or strictly decreasing) on a set SS, then ff is injective on SS. So ff has an inverse from SS onto its range f(S)f(S), and if ff is strictly increasing so is f−1f^{-1}.

Proof

If x≠yx \ne y in SS, say x<yx < y, then f(x)<f(y)f(x) < f(y), so f(x)≠f(y)f(x) \ne f(y). For the inverse: let y1<y2y_1 < y_2 be in f(S)f(S) and suppose f−1(y1)≥f−1(y2)f^{-1}(y_1) \ge f^{-1}(y_2). Since ff is increasing, f(f−1(y1))≥f(f−1(y2))f(f^{-1}(y_1)) \ge f(f^{-1}(y_2)), that is, y1≥y2y_1 \ge y_2, a contradiction.

∎

This is how we invert functions that are not injective: restrict the domain to an interval where they are strictly monotone. f(x)=x2f(x) = x^2 is not injective on R\R (f(−3)=f(3)f(-3) = f(3)), but it is strictly increasing on [0,∞)[0, \infty), and there its inverse is x\sqrt{x}.

Theorem— The graph of the inverse is a reflection

If g=f−1g = f^{-1}, then (x,y)(x, y) lies on the graph of ff if and only if (y,x)(y, x) lies on the graph of gg. So the graph of f−1f^{-1} is the mirror image of the graph of ff in the line y=xy = x.

Proof

If y=f(x)y = f(x) then g(y)=g(f(x))=xg(y) = g(f(x)) = x, so (y,x)(y, x) is on the graph of gg. If x=g(y)x = g(y) then f(x)=f(g(y))=yf(x) = f(g(y)) = y. Finally, the reflection in the line y=xy = x is exactly the map (x,y)↦(y,x)(x, y) \mapsto (y, x): the midpoint (x+y2,x+y2)\left(\tfrac{x + y}{2}, \tfrac{x + y}{2}\right) of the two points lies on the line, and the segment joining them has direction (1,−1)(1, -1), perpendicular to the line.

∎

Example— Finding an inverse by algebra

To invert f(x)=2x+1x−3f(x) = \dfrac{2x + 1}{x - 3} (x≠3x \ne 3), solve y=2x+1x−3y = \dfrac{2x + 1}{x - 3} for xx:

y(x−3)=2x+1  ⟹  xy−2x=3y+1  ⟹  x=3y+1y−2(y≠2).y(x - 3) = 2x + 1 \;\Longrightarrow\; xy - 2x = 3y + 1 \;\Longrightarrow\; x = \frac{3y + 1}{y - 2} \quad (y \ne 2).

So f−1(y)=3y+1y−2f^{-1}(y) = \dfrac{3y + 1}{y - 2}, defined for y≠2y \ne 2. The value y=2y = 2, the horizontal asymptote of ff, is not in the range of ff, and it becomes the vertical asymptote of f−1f^{-1}. Reflection swaps the roles of horizontal and vertical.

Theorem— Even and odd parts

Every function f:R→Rf : \R \to \R can be written in exactly one way as f=e+of = e + o with ee even and oo odd, namely

e(x)=f(x)+f(−x)2,o(x)=f(x)−f(−x)2.e(x) = \frac{f(x) + f(-x)}{2}, \qquad o(x) = \frac{f(x) - f(-x)}{2}.

Proof

Existence: e(−x)=f(−x)+f(x)2=e(x)e(-x) = \tfrac{f(-x) + f(x)}{2} = e(x), o(−x)=f(−x)−f(x)2=−o(x)o(-x) = \tfrac{f(-x) - f(x)}{2} = -o(x), and e(x)+o(x)=f(x)e(x) + o(x) = f(x).

Uniqueness: if e1+o1=e2+o2e_1 + o_1 = e_2 + o_2, then d=e1−e2=o2−o1d = e_1 - e_2 = o_2 - o_1 is both even and odd, so d(x)=d(−x)=−d(x)d(x) = d(-x) = -d(x) and d(x)=0d(x) = 0 for every xx.

∎

For a polynomial, the even part collects the even powers and the odd part the odd powers: x3+2x2−x+5x^3 + 2x^2 - x + 5 splits as (2x2+5)+(x3−x)(2x^2 + 5) + (x^3 - x).

Formal mathematicsF

Graphs, inverses and symmetry in Lean

We define the graph of a function R→R\R \to \R as a set of pairs, exactly as in the definition:

graphLean 4Formally verified
/-- The **graph** of `f : ℝ → ℝ` is the set of points `(x, f x)` in the plane. -/
def graph (f : ℝ → ℝ) : Set (ℝ × ℝ) := {p | p.2 = f p.1}
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/FunctionsAndGraphs.leanTry it in the Lean web editor

The transformation rule says that one set is the image of another under a map of the plane, written (fun p => …) '' graph f:

graph_shiftLean 4Proved here from basic factsFormally verified
/-- **Shifting right.** The graph of `y = f(x − h)` is the graph of `y = f(x)` moved `h` units to
the **right**: it is the image of `graph f` under `(x, y) ↦ (x + h, y)`. (For `h > 0`, the input
`x − h` reaches the value `x₀` later, at `x = x₀ + h`.) -/
theorem graph_shift (f : ℝ → ℝ) (h : ℝ) :
    graph (fun x => f (x - h)) = (fun p : ℝ × ℝ => (p.1 + h, p.2)) '' graph f := by
  ext ⟨x, y⟩
  simp only [graph, Set.mem_ofPred_eq, Set.mem_image, Prod.mk.injEq, Prod.exists]
  constructor
  · intro hy
    exact ⟨x - h, y, hy, by ring, rfl⟩
  · rintro ⟨u, v, hv, rfl, rfl⟩
    simp [hv]
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/FunctionsAndGraphs.leanTry it in the Lean web editor
graph_transformLean 4Proved here from basic factsFormally verified
/-- **The transformation rule.** For `b ≠ 0`, the graph of `y = a f(b(x − h)) + k` is the image
of the graph of `f` under `(x, y) ↦ (x/b + h, a y + k)`: squeeze horizontally by the factor `b`,
shift right by `h`, stretch vertically by `a`, shift up by `k`. -/
theorem graph_transform (f : ℝ → ℝ) (a b h k : ℝ) (hb : b ≠ 0) :
    graph (fun x => a * f (b * (x - h)) + k) =
      (fun p : ℝ × ℝ => (p.1 / b + h, a * p.2 + k)) '' graph f := by
  ext ⟨x, y⟩
  simp only [graph, Set.mem_ofPred_eq, Set.mem_image, Prod.mk.injEq, Prod.exists]
  constructor
  · intro hy
    refine ⟨b * (x - h), f (b * (x - h)), rfl, ?_, hy.symm⟩
    field_simp
    ring
  · rintro ⟨u, v, hv, rfl, rfl⟩
    have hu : b * (u / b + h - h) = u := by field_simp; ring
    rw [hu, hv]
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/FunctionsAndGraphs.leanTry it in the Lean web editor

Inverses. Function.LeftInverse g f means g(f(x))=xg(f(x)) = x for all xx, and Function.RightInverse g f means f(g(y))=yf(g(y)) = y. Prod.swap is the map (x,y)↦(y,x)(x, y) \mapsto (y, x), the reflection in y=xy = x:

graph_inverseLean 4Proved here from basic factsFormally verified
/-- **The graph of an inverse is a reflection.** If `g` undoes `f` and `f` undoes `g`, then the
graph of `g` is the graph of `f` with the coordinates swapped, that is, reflected in the line
`y = x`: `(x, y)` lies on the graph of `f` exactly when `(y, x)` lies on the graph of `g`. -/
theorem graph_inverse (f g : ℝ → ℝ) (hgf : Function.LeftInverse g f)
    (hfg : Function.RightInverse g f) : graph g = Prod.swap '' graph f := by
  ext ⟨x, y⟩
  simp only [graph, Set.mem_ofPred_eq, Set.mem_image, Prod.exists, Prod.swap_prod_mk,
    Prod.mk.injEq]
  constructor
  · intro hy
    exact ⟨y, x, by rw [hy, hfg x], rfl, rfl⟩
  · rintro ⟨u, v, hv, rfl, rfl⟩
    rw [hv, hgf u]
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/FunctionsAndGraphs.leanTry it in the Lean web editor
bijective_iff_has_inverseLean 4Applies a library theoremFormally verified
/-- **A function has an inverse exactly when it is a bijection.** This applies Mathlib's
`Function.bijective_iff_has_inverse`. -/
theorem bijective_iff_has_inverse (f : ℝ → ℝ) :
    Function.Bijective f ↔ ∃ g, Function.LeftInverse g f ∧ Function.RightInverse g f :=
  Function.bijective_iff_has_inverse
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/FunctionsAndGraphs.leanTry it in the Lean web editor
injOn_of_strictMonoOnLean 4Proved here from basic factsFormally verified
/-- **A strictly increasing function is injective** on any set where it is strictly increasing.
If `x ≠ y`, one of them is smaller, say `x < y`; then `f x < f y`, so `f x ≠ f y`.
(Mathlib: `StrictMonoOn.injOn`.) -/
theorem injOn_of_strictMonoOn {f : ℝ → ℝ} {s : Set ℝ} (hf : StrictMonoOn f s) : Set.InjOn f s := by
  intro x hx y hy hxy
  rcases lt_trichotomy x y with hlt | heq | hgt
  · exact absurd hxy (ne_of_lt (hf hx hy hlt))
  · exact heq
  · exact absurd hxy (ne_of_gt (hf hy hx hgt))
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/FunctionsAndGraphs.leanTry it in the Lean web editor
injOn_libraryLean 4Applies a library theoremFormally verified
/-- The same fact, as stated in Mathlib: this applies `StrictMonoOn.injOn`. On the interval
`[0, ∞)` the function `x ↦ x²` is strictly increasing, which is why it has an inverse there
(the square root), although it has none on all of `ℝ`. -/
theorem injOn_library {f : ℝ → ℝ} {s : Set ℝ} (hf : StrictMonoOn f s) : Set.InjOn f s :=
  hf.injOn
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/FunctionsAndGraphs.leanTry it in the Lean web editor
strictMono_inverseLean 4Proved here from basic factsFormally verified
/-- **The inverse of a strictly increasing function is strictly increasing.** Suppose `y₁ < y₂`
but `g y₁ ≥ g y₂`. Applying the increasing function `f` gives `f (g y₁) ≥ f (g y₂)`, that is,
`y₁ ≥ y₂` — a contradiction. -/
theorem strictMono_inverse {f g : ℝ → ℝ} (hf : StrictMono f) (hfg : Function.RightInverse g f) :
    StrictMono g := by
  intro y₁ y₂ hy
  by_contra hle
  have h : f (g y₂) ≤ f (g y₁) := hf.monotone (not_lt.mp hle)
  rw [hfg y₁, hfg y₂] at h
  exact absurd hy (not_lt.mpr h)
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/FunctionsAndGraphs.leanTry it in the Lean web editor

The rational function of the examples and its inverse, including the facts that ff never takes the value 22 and f−1f^{-1} never takes the value 33:

mobius_inverseLean 4Proved here from basic factsFormally verified
/-- **An inverse found by algebra.** `f(x) = (2x + 1)/(x − 3)` (for `x ≠ 3`) and
`g(y) = (3y + 1)/(y − 2)` (for `y ≠ 2`) undo each other. To find `g`, solve `y = (2x + 1)/(x − 3)`
for `x`: `y(x − 3) = 2x + 1`, so `x(y − 2) = 3y + 1`. The value `y = 2` is never taken by `f`:
it is the horizontal asymptote. -/
theorem mobius_inverse :
    (∀ x : ℝ, x ≠ 3 → (2 * x + 1) / (x - 3) ≠ 2 ∧
        (3 * ((2 * x + 1) / (x - 3)) + 1) / ((2 * x + 1) / (x - 3) - 2) = x) ∧
      (∀ y : ℝ, y ≠ 2 → (3 * y + 1) / (y - 2) ≠ 3 ∧
        (2 * ((3 * y + 1) / (y - 2)) + 1) / ((3 * y + 1) / (y - 2) - 3) = y) := by
  constructor
  · intro x hx
    have hx3 : x - 3 ≠ 0 := sub_ne_zero.mpr hx
    have hne : (2 * x + 1) / (x - 3) - 2 ≠ 0 := by
      rw [div_sub' hx3]
      exact div_ne_zero (by ring_nf; norm_num) hx3
    refine ⟨fun h => hne (by rw [h]; ring), ?_⟩
    rw [div_eq_iff hne]
    field_simp
    ring
  · intro y hy
    have hy2 : y - 2 ≠ 0 := sub_ne_zero.mpr hy
    have hne : (3 * y + 1) / (y - 2) - 3 ≠ 0 := by
      rw [div_sub' hy2]
      exact div_ne_zero (by ring_nf; norm_num) hy2
    refine ⟨fun h => hne (by rw [h]; ring), ?_⟩
    rw [div_eq_iff hne]
    field_simp
    ring
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/FunctionsAndGraphs.leanTry it in the Lean web editor

The horizontal asymptote, stated with Mathlib's precise notion of limit (Tendsto … atTop (𝓝 2) reads "tends to 22 as x→∞x \to \infty"). The proof follows the lesson: rewrite as 2+7x−32 + \tfrac{7}{x - 3} for x>3x > 3:

horizontal_asymptoteLean 4Proved here from basic factsFormally verified
/-- **End behaviour:** `(2x + 1)/(x − 3) → 2` as `x → ∞`, so `y = 2` is a horizontal asymptote.
For `x ≠ 3`, `(2x + 1)/(x − 3) = 2 + 7/(x − 3)`, and `7/(x − 3) → 0` because `x − 3 → ∞`.
(The small library facts used are `tendsto_inv_atTop_zero` and the limit laws.) -/
theorem horizontal_asymptote :
    Tendsto (fun x : ℝ => (2 * x + 1) / (x - 3)) atTop (𝓝 2) := by
  have hden : Tendsto (fun x : ℝ => x - 3) atTop atTop :=
    tendsto_atTop_add_const_right _ _ tendsto_id
  have hsmall : Tendsto (fun x : ℝ => 7 * (x - 3)⁻¹) atTop (𝓝 0) := by
    simpa using (tendsto_inv_atTop_zero.comp hden).const_mul 7
  have hsum : Tendsto (fun x : ℝ => 2 + 7 * (x - 3)⁻¹) atTop (𝓝 2) := by
    simpa using hsmall.const_add 2
  refine hsum.congr' ?_
  filter_upwards [eventually_gt_atTop 3] with x hx
  have hx3 : x - 3 ≠ 0 := by linarith
  field_simp
  ring
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/FunctionsAndGraphs.leanTry it in the Lean web editor

Even and odd functions use Mathlib's own definitions Function.Even and Function.Odd:

even_odd_decompositionLean 4Proved here from basic factsFormally verified
/-- **Every function is even plus odd.** For `f : ℝ → ℝ` put
`e(x) = (f(x) + f(−x))/2` and `o(x) = (f(x) − f(−x))/2`. Then `e` is even, `o` is odd and
`f = e + o`. (For `f(x) = eˣ` this gives `cosh` and `sinh`.) -/
theorem even_odd_decomposition (f : ℝ → ℝ) :
    ∃ e o : ℝ → ℝ, Function.Even e ∧ Function.Odd o ∧ ∀ x, f x = e x + o x := by
  refine ⟨fun x => (f x + f (-x)) / 2, fun x => (f x - f (-x)) / 2, ?_, ?_, ?_⟩
  · intro x
    simp only [neg_neg]
    ring
  · intro x
    simp only [neg_neg]
    ring
  · intro x
    ring
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/FunctionsAndGraphs.leanTry it in the Lean web editor
even_odd_uniqueLean 4Proved here from basic factsFormally verified
/-- **The splitting is unique.** If `e₁ + o₁ = e₂ + o₂` with `e₁, e₂` even and `o₁, o₂` odd, then
`d = e₁ − e₂ = o₂ − o₁` is both even and odd, so `d(x) = d(−x) = −d(x)`, forcing `d(x) = 0`. -/
theorem even_odd_unique {e₁ o₁ e₂ o₂ : ℝ → ℝ} (he₁ : Function.Even e₁) (he₂ : Function.Even e₂)
    (ho₁ : Function.Odd o₁) (ho₂ : Function.Odd o₂) (h : ∀ x, e₁ x + o₁ x = e₂ x + o₂ x) :
    e₁ = e₂ ∧ o₁ = o₂ := by
  have hd : ∀ x, e₁ x - e₂ x = 0 := by
    intro x
    have h1 := h x
    have h2 := h (-x)
    rw [he₁ x, he₂ x, ho₁ x, ho₂ x] at h2
    linarith
  constructor
  · funext x
    linarith [hd x]
  · funext x
    linarith [hd x, h x]
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/FunctionsAndGraphs.leanTry it in the Lean web editor
odd_mul_oddLean 4Applies a library theoremFormally verified
/-- **Odd times odd is even** — like `(−1)·(−1) = 1`. For example `x · x³ = x⁴`. This applies
Mathlib's `Function.Odd.mul_odd`. -/
theorem odd_mul_odd {f g : ℝ → ℝ} (hf : Function.Odd f) (hg : Function.Odd g) :
    Function.Even (f * g) :=
  hf.mul_odd hg
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/FunctionsAndGraphs.leanTry it in the Lean web editor
comp_not_commLean 4Proved here from basic factsFormally verified
/-- **Order matters:** with `f(x) = x + 1` and `g(x) = x²`, `g ∘ f ≠ f ∘ g`, because
`(g ∘ f)(1) = 4` but `(f ∘ g)(1) = 2`. -/
theorem comp_not_comm :
    (fun x : ℝ => x ^ 2) ∘ (fun x : ℝ => x + 1) ≠ (fun x : ℝ => x + 1) ∘ (fun x : ℝ => x ^ 2) := by
  intro h
  have h1 := congrFun h 1
  norm_num at h1
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/FunctionsAndGraphs.leanTry it in the Lean web editor
ComputationC

Checking the rules, and inverting without a formula

Moving graphs and splitting functions into even and odd partsPythonExact computationExhaustive finite checkComputationally tested
"""Transformations of graphs and the even/odd splitting, checked exactly.

The lesson proves that the graph of y = a f(b(x - h)) + k is the graph of f
moved by the rule (x, y) -> (x/b + h, a y + k). Here we test that rule with
exact fractions on sample points, see which way y = f(x - 2) moves, and split
functions into even and odd parts, checking the parts on a grid of points.
"""

from fractions import Fraction

def transform(f, a, b, h, k):
    """The function x -> a f(b(x - h)) + k."""
    return lambda x: a * f(b * (x - h)) + k

def move_point(point, a, b, h, k):
    """Where the transformation rule sends the point (x, y)."""
    x, y = point
    return (x / b + h, a * y + k)

def rule_holds(f, a, b, h, k, xs):
    """True if every moved point (x/b + h, a f(x) + k) lies on the new graph."""
    g = transform(f, a, b, h, k)
    for x in xs:
        u, v = move_point((x, f(x)), a, b, h, k)
        if g(u) != v:
            return False
    return True

def even_part(f):
    """x -> (f(x) + f(-x)) / 2."""
    return lambda x: (f(x) + f(-x)) / 2

def odd_part(f):
    """x -> (f(x) - f(-x)) / 2."""
    return lambda x: (f(x) - f(-x)) / 2

def parity(f, xs):
    """'even', 'odd', 'zero' or 'neither', judged on the points xs only.

    A function that is both even and odd is 0 at every checked point.
    """
    is_even = all(f(-x) == f(x) for x in xs)
    is_odd = all(f(-x) == -f(x) for x in xs)
    if is_even and is_odd:
        return "zero"
    return "even" if is_even else ("odd" if is_odd else "neither")

GRID = [Fraction(n, 4) for n in range(-12, 13)]

def main():
    def f(x):
        return x ** 3 - x

    a, b, h, k = Fraction(-1), Fraction(2), Fraction(1), Fraction(3)
    print("f(x) = x^3 - x and g(x) = -f(2(x - 1)) + 3; rule (x, y) ->"
          " (x/2 + 1, -y + 3)")
    for x in [-2, -1, 0, 1, 2]:
        x = Fraction(x)
        u, v = move_point((x, f(x)), a, b, h, k)
        g = transform(f, a, b, h, k)
        print(f"  ({x}, {f(x)}) -> ({u}, {v});  g({u}) = {g(u)}")
    print(f"rule holds on all {len(GRID)} grid points:",
          rule_holds(f, a, b, h, k, GRID))
    print()

    def square(x):
        return x * x

    right = transform(square, 1, 1, 2, 0)
    zeros = ", ".join(str(x) for x in GRID if right(x) == 0)
    print(f"y = x^2 has its zero at x = 0; y = (x - 2)^2 has it at x = {zeros}:")
    print("  replacing x by x - 2 moves the graph 2 units to the RIGHT.")
    print()
    print(f"parity on the grid {GRID[0]}..{GRID[-1]} (steps of 1/4):")
    examples = [
        ("x^4 - 3x^2", lambda x: x ** 4 - 3 * x ** 2),
        ("x^3 - 5x", lambda x: x ** 3 - 5 * x),
        ("x^2 + x", lambda x: x ** 2 + x),
        ("1/(1 + x^2)", lambda x: 1 / (1 + x ** 2)),
        ("x/(1 + x^2) + 1", lambda x: x / (1 + x ** 2) + 1),
    ]
    for name, fn in examples:
        e, o = even_part(fn), odd_part(fn)
        two = Fraction(2)
        odd2 = f"({o(two)})" if o(two) < 0 else f"{o(two)}"
        print(f"  {name:16s} {parity(fn, GRID):8s} even part {parity(e, GRID):5s}"
              f" odd part {parity(o, GRID):5s} f(2) = {e(two)} + {odd2}")
    print()
    print("Epistemic status: every value above is exact rational arithmetic, but")
    print("only finitely many points are checked. A function could pass on the")
    print("grid and fail elsewhere; the lesson's proofs (and the Lean versions)")
    print("establish the transformation rule and the even/odd splitting for all")
    print("real numbers.")

if __name__ == "__main__":
    main()
Runs entirely in your browser, in an isolated worker. Nothing is sent to a server.

Checking a rule at 2525 points is evidence, not proof: a function could behave at the points we test and misbehave elsewhere. The proofs above, and their Lean versions, cover every real number.

Some functions are easy to invert by algebra. Others are not. f(x)=x3+xf(x) = x^3 + x is strictly increasing, so it has an inverse, but solving y=x3+xy = x^3 + x for xx requires the cubic formula. We can still evaluate the inverse to any accuracy by bisection: keep halving an interval that is guaranteed to contain the answer.

Evaluating an inverse function by bisectionPythonExact computationNumerical approximationComputationally tested
"""Inverting a function that has no simple formula for its inverse.

f(x) = x^3 + x is strictly increasing, so it is injective and has an inverse
on its whole range. To evaluate the inverse at y we search for the x with
f(x) = y by bisection, using exact fractions: each step halves an interval
that is guaranteed to contain the answer, so after n steps the error is at
most (initial width) / 2^n. The experiment also shows why x^2 needs its domain
restricted to [0, oo) before it can be inverted.
"""

from fractions import Fraction

def f(x):
    """The strictly increasing function x^3 + x."""
    return x ** 3 + x

def bisect_inverse(func, y, lo, hi, steps):
    """Find x in [lo, hi] with func(x) = y for an increasing ``func``.

    Requires func(lo) <= y <= func(hi). Returns (lo, hi) after ``steps``
    halvings; the true x always lies in the returned interval.
    """
    lo, hi = Fraction(lo), Fraction(hi)
    if not func(lo) <= y <= func(hi):
        raise ValueError("y is not between func(lo) and func(hi)")
    for _ in range(steps):
        mid = (lo + hi) / 2
        if func(mid) <= y:
            lo = mid
        else:
            hi = mid
    return lo, hi

def inverse(y, steps=40):
    """Approximate f^(-1)(y) as the midpoint of the final bisection interval."""
    bound = abs(Fraction(y)) + 1  # f(bound) >= bound >= |y|
    lo, hi = bisect_inverse(f, Fraction(y), -bound, bound, steps)
    return (lo + hi) / 2, (hi - lo) / 2

def collisions(func, points):
    """Pairs of different inputs among ``points`` with the same output."""
    pts = sorted(set(points))
    return [(a, b) for i, a in enumerate(pts) for b in pts[i + 1:]
            if func(a) == func(b)]

def main():
    print("f(x) = x^3 + x is strictly increasing, so it has an inverse g.")
    print("g(y) by 40 steps of exact bisection; error bound = half-width:")
    for y in [2, 10, 30, -10]:
        x, err = inverse(y)
        print(f"  g({y:3d}) ~ {float(x):.12f}   |error| <= {float(err):.1e}"
              f"   f(x) - y = {float(f(x) - y):.1e}")
    print("  exact values: g(2) = 1, g(10) = 2, g(30) = 3, g(-10) = -2")
    print()
    print("reflection: (a, f(a)) on the graph of f gives (f(a), a) on g's:")
    for a in [Fraction(1, 2), Fraction(3, 2)]:
        x, err = inverse(f(a))
        print(f"  a = {a}: f(a) = {f(a)}, g(f(a)) ~ {float(x):.10f}"
              f" (within {float(err):.1e} of {a})")
    print()
    grid = [Fraction(n, 2) for n in range(-6, 7)]
    sq = collisions(lambda t: t * t, grid)
    print(f"x^2 on -3..3 in steps of 1/2: {len(sq)} pairs with equal outputs,")
    print(f"  e.g. {sq[0][0]} and {sq[0][1]}: not injective, no inverse on R.")
    pos = collisions(lambda t: t * t, [t for t in grid if t >= 0])
    print(f"  restricted to x >= 0: {len(pos)} collisions; the inverse is sqrt.")
    print()
    print("Epistemic status: bisection with exact fractions gives a rigorous")
    print("enclosure: since f is increasing and continuous, the true inverse value")
    print("lies in the final interval, so the error bound is guaranteed, not")
    print("estimated. Only the printed decimals are rounded. The collision count")
    print("is an exhaustive check of a finite grid, not a proof for all reals.")

if __name__ == "__main__":
    main()
Runs entirely in your browser, in an isolated worker. Nothing is sent to a server.

Because the arithmetic is exact and ff is increasing and continuous, the error bounds here are guaranteed, not estimated. Each step halves the interval known to contain f−1(y)f^{-1}(y).

Explore

Explore: transformations, inverses and asymptotes

Use the sliders to transform y=∣x∣y = |x| (dashed reference) into y=a ∣b(x−h)∣+ky = a\,|b(x - h)| + k. Predict where the corner goes before you move a slider. What does a negative bb do to a V shape, and why? (Hint: ∣x∣|x| is even.)

Transforming y = |x|

Move the sliders and trace along the curves to read off values.

corner
  • y = a|b(x − h)| + k
  • y = |x|
  • y = a|b(x − h)| + k: y = 3
  • y = |x|: y = 1

A function and its inverse are mirror images in the line y=xy = x. Trace along the curves: y=x3y = x^3 passes through (1.5, 3.375)(1.5,\ 3.375), so the cube root passes through (3.375, 1.5)(3.375,\ 1.5).

A function, its inverse and the mirror line

Move the sliders and trace along the curves to read off values.

(1.5, 3.375)(3.375, 1.5)
  • y = x³
  • y = ∛x
  • y = x
  • y = x³: y = 1
  • y = ∛x: y = 1
  • y = x: y = 1

Finally the rational function 2x+1x−3\dfrac{2x + 1}{x - 3}, its horizontal asymptote y=2y = 2, and its inverse 3x+1x−2\dfrac{3x + 1}{x - 2}. The horizontal asymptote of one is the vertical asymptote of the other.

A rational function and its inverse

Move the sliders and trace along the curves to read off values.

  • y = (2x + 1)/(x − 3)
  • inverse: y = (3x + 1)/(x − 2)
  • y = 2
  • y = (2x + 1)/(x − 3): y = −1.5
  • inverse: y = (3x + 1)/(x − 2): y = −4
  • y = 2: y = 2
Exercises

Exercises

1. Functions and their graphs (precalculus)

Warm-upHuman

How is the graph of y=f(x+3)y = f(x + 3) obtained from the graph of y=f(x)y = f(x)?

Choose one

2. Functions and their graphs (precalculus)

Warm-upHuman

Let f(x)=2x+1f(x) = 2x + 1 and g(x)=x2g(x) = x^2. Compute (g∘f)(2)(g \circ f)(2).

3. Functions and their graphs (precalculus)

CoreHuman

What is the natural domain of h(x)=x−1x−3h(x) = \dfrac{\sqrt{x - 1}}{x - 3}?

Choose one

4. Functions and their graphs (precalculus)

CoreHuman

Let f(x)=x−1x+2f(x) = \dfrac{x - 1}{x + 2} for x≠−2x \ne -2. Which formula gives f−1(x)f^{-1}(x)?

Choose one

5. Functions and their graphs (precalculus)

CoreHuman

Find all vertical asymptotes x=ax = a of r(x)=x+1x2−1r(x) = \dfrac{x + 1}{x^2 - 1}. Enter the set of numbers aa, for example {2, 5}.

Write elements separated by commas. Order and repeats don’t matter — just like in a set!

6. Functions and their graphs (precalculus)

CoreHuman

Which of these functions are odd, meaning f(−x)=−f(x)f(-x) = -f(x) for every xx in the domain? Choose all that apply.

Choose all that apply

7. Functions and their graphs (precalculus)

StretchHuman

The function f(x)=1xf(x) = \dfrac{1}{x} is strictly decreasing on (−∞,0)(-\infty, 0) and on (0,∞)(0, \infty). Which statement is true on its whole domain x≠0x \ne 0?

Choose one

8. Functions and their graphs (precalculus)

CoreFormal

Which Lean statement says that the graph of y=f(x−h)y = f(x - h) is the graph of ff moved hh units to the right? Here graph f is the set of points (x, f x), and F '' S is the image of the set S under the map F.

Choose one

9. Functions and their graphs (precalculus)

StretchComputational

Write inverse_value(f, y, lo, hi, steps) that evaluates the inverse of a strictly increasing function f at y by bisection. Assume f(lo) <= y <= f(hi). Repeat steps times: look at the midpoint mid; if f(mid) <= y the answer is in [mid, hi], otherwise in [lo, mid]. Return the midpoint of the final interval.

Runs entirely in your browser, in an isolated worker. Nothing is sent to a server.
Common misconceptionsH

Common misconceptions

Misconception

"f−1(x)=1f(x)f^{-1}(x) = \dfrac{1}{f(x)}." The −1-1 in f−1f^{-1} means "undo ff", not "one over". For f(x)=x+1f(x) = x + 1, f−1(x)=x−1f^{-1}(x) = x - 1, but 1f(x)=1x+1\dfrac{1}{f(x)} = \dfrac{1}{x + 1}. At x=1x = 1 these are 00 and 12\tfrac12.

Misconception

"y=f(x−2)y = f(x - 2) moves the graph to the left." It moves it right. The new function reaches each old output 22 units later: at x=2x = 2 it does what ff did at 00. The transformation rule above proves it.

Misconception

"Composition is commutative." With f(x)=x+1f(x) = x + 1 and g(x)=x2g(x) = x^2, (g∘f)(x)=(x+1)2(g \circ f)(x) = (x + 1)^2 but (f∘g)(x)=x2+1(f \circ g)(x) = x^2 + 1; at x=1x = 1 they give 44 and 22. Even the domains can differ: x2−4\sqrt{x^2 - 4} is defined for ∣x∣≥2|x| \ge 2, but (x)2−4(\sqrt x)^2 - 4 only for x≥0x \ge 0. See composition.

Misconception

"A graph can never cross its horizontal asymptote." It can — the asymptote describes the far-away behaviour only. 2x2+xx2+1→2\dfrac{2x^2 + x}{x^2 + 1} \to 2 as x→±∞x \to \pm\infty, yet it equals 22 at x=2x = 2, where 2x2+x=2x2+22x^2 + x = 2x^2 + 2.

Misconception

"Every function has an inverse." Only bijections do. x2x^2 on R\R has none, because (−3)2=32(-3)^2 = 3^2. Its "inverse" x\sqrt{x} is the inverse of x2x^2 restricted to [0,∞)[0, \infty).

ViewpointsH

Many ways of seeing

Set theory— A function is its graph

In set theory a function from AA to BB is a subset G⊆A×BG \subseteq A \times B such that every a∈Aa \in A appears in exactly one pair (a,b)∈G(a, b) \in G. The vertical line test is that definition drawn in the plane. The inverse of a bijection is obtained by swapping every pair, which is the reflection of the graph in the line y=xy = x.

Geometry— Transformations form a group

The moves (x,y)↦(xb+h, ay+k)(x, y) \mapsto \left(\tfrac{x}{b} + h,\ ay + k\right) with a,b≠0a, b \ne 0 are transformations of the plane. Doing two of them in a row gives another of the same kind, each can be undone by another, and "do nothing" (a=b=1a = b = 1, h=k=0h = k = 0) is one of them. So they form a group acting on graphs. Felix Klein's Erlangen programme (1872) proposed studying a geometry through the group of transformations that preserve it (see transformation geometry). From this point of view, y=x2y = x^2 and y=2(x−3)2+1y = 2(x - 3)^2 + 1 are "the same shape" because one transformation in the group carries one graph to the other.

Topology— Continuity and inverses on intervals

Topology explains why restricting to intervals works so well. A continuous function on an interval that is injective must be strictly monotone. The proof uses the intermediate value theorem: a continuous function that went up and then down would take some value twice. Moreover, the inverse of a continuous, strictly monotone function on an interval is again continuous. So the function is a homeomorphism between two intervals: a stretching of one line segment onto another without tearing. The bisection method in the computation section relies on the same intermediate value theorem.

Analysis— Asymptotes are limits

"The graph approaches y=2y = 2" is shorthand for a precise statement: for every tolerance ε>0\varepsilon > 0 there is an NN such that ∣r(x)−2∣<ε|r(x) - 2| < \varepsilon whenever x>Nx > N. For r(x)=2+7x−3r(x) = 2 + \tfrac{7}{x - 3} we can take N=3+7εN = 3 + \tfrac{7}{\varepsilon}. Analysts study such estimates systematically, and the end behaviour of polynomials ("the leading term wins") is the first example of comparing rates of growth (see introductory calculus).

Wonder Trails

Wonder Trails

History & global context

History and global context

  • Graphs before functions. Around 1350, Nicole Oresme in Paris drew diagrams in which the "intensity" of a quality (such as speed) was plotted as a height above a line representing time.
  • Coordinates. In the 1630s René Descartes and Pierre de Fermat independently connected equations with curves, founding analytic geometry.
  • Functions as infinite expressions. In Kerala in the 14th and 15th centuries, Mādhava of Saṅgamagrāma and his successors expressed the sine, cosine and arctangent as infinite series. These were among the earliest descriptions of functions by power series.
  • The word "function". Gottfried Wilhelm Leibniz used the word in the late 17th century for quantities attached to a curve. Johann Bernoulli (1718) and Leonhard Euler made it mean an expression built from a variable, and Euler introduced the notation f(x)f(x) in the 1730s.
  • Arbitrary rules. In the 19th century, Nikolai Lobachevsky and Peter Gustav Lejeune Dirichlet (1830s) argued that a function may be any rule assigning outputs to inputs, given by a formula or not. That idea led to the set-theoretic definition used today.
Further reading

Further reading

  • I. M. Gelfand, E. G. Glagoleva and E. E. Shnol, Functions and Graphs (1969; English translation 1990) — a short, beautiful book on exactly this topic, written for school students.
  • I. M. Gelfand and A. Shen, Algebra (1993).
  • Sheldon Axler, Precalculus: A Prelude to Calculus (2009) — careful, with every definition and proof.
  • Richard Courant and Herbert Robbins, What Is Mathematics? (1941), chapter VI on functions and limits.