induction

Summary

The induction tactic will turn a goal of the form P n (with P a predicate on naturals, and n a natural) into two goals P 0 and d, P d P (succ d).

Overview

The induction tactic does exactly what you think it will do; it’s a tactic which reduces a goal which depends on a natural to two goals, the base case (always zero, in Lean) and the step case. In computer science it is very common to see a lot of other so-called inductive types (for example List and Expr) and the induction tactic can get quite a lot of use; however in this course we only ever use induction on naturals.

Example

We show \(\sum_{i=0}^{n-1}i^2=n(n-1)(2n-1)/6\) by induction on \(n\).

import Mathlib.Tactic

open BigOperators -- ∑ notation

open Finset -- so I can say `range n` for the finite set `{0,1,2,...,n-1}`

-- sum from i = 0 to n - 1 of i^2 is n(n-1)(2n-1)/6
-- note that I immediately coerce into rationals in the statement to get the correct subtraction and
-- division (natural number subtraction and division are pathological functions)
example (n : ) :  i in range n, (i : ) ^ 2 = (n : ) * (n - 1) * (2 * n - 1) / 6 := by
induction' n with d hd
· -- base case says that an empty sum is zero times something, and this sort of goal
   -- is perfect for the simplifier
   simp
·  -- inductive step
   rw [sum_range_succ] -- the lemma saying
                        -- `∑ i in range (n.succ), f i = (∑ i in range n, f i) + f n`
   rw [hd] -- the inductive hypothesis
   simp -- change `d.succ` into `d + 1`
   ring

Details

The definition of the natural numbers in Lean is this:

inductive Nat
| zero : Nat
| succ (n : Nat) : Nat

When this code is run, four new objects are created: the type Nat, the term Nat.zero, the function Nat.succ : Nat Nat and the recursor for the naturals, a statement automatically generated from the definition and which can be described as saying that to do something for all naturals, you only have to do it for zero and succ n, and in the succ n case you can assume you already did it for n. The induction tactic applies this recursor and then does some tidying up. This is why you end up with goals containing n.succ rather than the more mathematically natural n + 1. In the example above I use simp to change n.succ to n + 1 (and also to push casts as far in as possible).