10.3.2 First Example#
For the first example, the goal will be to implement addition via a function called “add”. The general form should be:
fun add :: "nat ⇒ nat ⇒ nat" where
"base case"
"recursive case"
where two natural numbers are added, and the result is a natural number that is the sum of the two input numbers. For example, sum m n should return the sum of m and n.
We first want to start off by defining the base case. Basically, if we add some arbitrary number n by 0, then it should return n.
"add 0 n = n"
General Proof Structure for a Proof by Induction#
Isabelle provides a general structure for how to approach and construct your proof. For this exercise, we will be using a proof by induction; first by proving a base case, and then by proving the sucessor case by using the induction hypothesis.
We start the proof by adding the command proof(induction m) after the lemma command. When we examine the output of this, we find that Isabele actually provides us with the overall goal, subgoals (such as the base case and successor cases), and the general proof outline
For example, for the associative property lemma, we get this:
goal (2 subgoals):
1. add (add 0 n) p = add 0 (add n p)
2. ⋀m. add (add m n) p = add m (add n p) ⟹ add (add (Suc m) n) p = add (Suc m) (add n p)
Proof outline with cases:
case 0
then show ?case sorry
next
case (Suc m)
then show ?case sorry
qed
10.3.3 First Exercise#
For the first exercise, we will be proving the associative and commutative properties of a custom add function in Isabelle. This exercise comes from Exercise 2.2 of Concrete Semantics Exercises
The custom add function is defined here:
fun add :: "nat ⇒ nat ⇒ nat" where
"add 0 n = n" |
"add (Suc m) n = Suc(add m n)"
We use 2 lemmas to prove each part of the exercise, namely:
lemma add_assoc: "add (add m n) p = add m (add n p)"
lemma add_comm: "add m n = add n m"
Associative Property Proof#
We first start off by proving the associative property of addition, and we do this by declaring the lemma and its goal:
lemma add_assoc: "add (add m n) p = add m (add n p)"
We then add the type of proof, which in this case will be a simple induction proof via the proof command:
proof (induction m)
We then set the base case with:
case 0
which will set m = 0 as the base case, and then will update the goal to:
add (add 0 n) p = add 0 (add n p)
We then use:
show ?case by simp
in order to simplify that new goal to:
add n p = add n p
Next, we perform the inductive step in order to prove that if the associative property holds for m, it must also hold for it’s successor of Suc m
We introduce the inductive step:
next
case (Suc m)
This creates 2 things:
A goal of:
add (add (Suc m) n) p = add (Suc m) (add n p)An induction hypothesis (Suc.IH) that assumes the property holds for m:
add (add m n) p = add m (add n p)
show ?case by (simp add: Suc.IH)
Here, simp first expands both sides of the equation using the recursive definition
add (Suc m) n = Suc (add m n)
This reduces the goal to
Suc (add (add m n) p) = Suc (add m (add n p))
The induction hypothesis (Suc.IH) is then applied to replace
add (add m n) p with add m (add n p),
making both sides identical.
The expression simplifies to Suc (…) = Suc (…) and completes the inductive step.
The full lemma proof for associativity is here:
lemma add_assoc: "add (add m n) p = add m (add n p)"
proof (induction m)
case 0
show ?case by simp
next
case (Suc m)
show ?case by (simp add: Suc.IH)
qed
Communative Property Proof#
Next, to prove the communative property, we will first prove 2 helper lemmas:
lemma add_0_right: "add m 0 = m"
lemma add_Suc_right: "add m (Suc n) = Suc (add m n)"
These proofs follow the same general format for induction:
lemma add_0_right: "add m 0 = m"
proof (induction m)
case 0
show ?case by simp
next
case (Suc m)
show ?case by (simp add: Suc.IH)
qed
lemma add_Suc_right: "add m (Suc n) = Suc (add m n)"
proof (induction m)
case 0
show ?case by simp
next
case (Suc m)
show ?case by (simp add: Suc.IH)
qed
With the helper lemmas proven, we will use them to prove the commutative property
lemma add_comm: "add m n = add n m"
proof (induction m)
case 0
show ?case
by (simp add: add_0_right)
next
case (Suc m)
show ?case
by (simp add: Suc.IH add_Suc_right)
qed
where we use the add_0_right lemma in the base case and then the add_Suc_right lemma in the inductive step.