How can we convince ourselves (and others) that a program is correct?
How can we convince ourselves that sum_to
and fib
are correct?
We can test any specific input, but for many programs, there are infinitely many possible inputs…
Principle of Natural Induction: Let P(n)
be a property of natural numbers. (i.e. for each natural number n
, either P(n)
is true or P(n)
is false.) If the following hold:
P(0)
and ∀𝓃, P(𝓃) ⇒ P(𝓃+1)
Then it must be true that for all n
, P(n)
.
CSci 2011 example: proving that ∀n, ∑i≤n i = n(n+1)/2
Prove: for all 𝓃 ≥ 0
, sum_to 𝓃
≡ ∑i≤𝓃 i.
Here P(𝓃)
= sum_to 𝓃
≡ ∑i≤𝓃 i, so we need to prove:
sum_to 0
≡ 0 [✓, eval. sum_to
]sum_to 𝓃
≡ ∑i≤𝓃 i ( Inductive Hypothesis )sum_to (𝓃+1)
≡ ∑i≤(𝓃+1) i ( Inductive Conclusion ):sum_to (𝓃+1) ≡ (𝓃+1) + (sum_to 𝓃)
[eval. sum_to
]
≡ (𝓃+1) +
∑i≤𝓃 i [I.H.]
≡
∑i≤(𝓃+1) i [✓, algebra]
In order to prove that for all 𝓃, (sum_to 𝓃)
≡ ∑i≤𝓃i, we need to prove a lemma about tr_sum
:
tr_sum 𝓃 𝒶
≡ 𝒶 + ∑i≤𝓃i.tr_sum 𝓃 𝒶
≡ 𝒶 + ∑i≤𝓃i.Base case: for all 𝒶, tr_sum 0 𝒶
≡ 𝒶 ≡ 𝒶 + 0.
Inductive case: notice tr_sum (𝓃+1) 𝒶 ≡ tr_sum 𝓃 (𝒶+(𝓃+1))
.
if for all 𝒶, (tr_sum 𝓃 𝒶)
≡ 𝒶 + ∑i≤𝓃i, (IH) then we also have
(tr_sum 𝓃 (𝒶+(𝓃+1)))
≡ (𝒶 + (𝓃+1)) + ∑i≤𝓃i,
so tr_sum (𝓃+1) 𝒶 ≡ tr_sum 𝓃 (𝒶+(𝓃+1))
[eval tr_sum
]
≡ (𝒶 + (𝓃+1)) + ∑i≤𝓃i = 𝒶 + ∑i≤(𝓃+1)i. [✓, algebra]
In order to prove that for all n
, fib n
≡ Fn
, we prove a lemma about tr_fib
:
tr_fib
i Fn-i
Fn-i+1
≡ Fn
tr_fib
i Fn-i
Fn-i+1
≡ Fn
Base Case: tr_fib 0
Fn
Fn+1
≡ Fn
, by evaluation.
Inductive Case:
tr_fib (i+1)
Fn-i-1
Fn-i
≡ tr_fib
i
Fn-i
(Fn-i
+ Fn-i-1
)
[eval. tr_fib
]
≡ tr_fib
i
Fn-i
F(n-i)+1
≡ Fn
[✓, algebra, IH]
In these proofs, we often replace one expression with another equivalent expression.
We are using the fact that OCaml expressions have referential transparency: if two expressions evaluate to the same normal form, then this is true in any context.
Alternatively, referential transparency means that evaluating an expression does not change the bindings (values) of variables.
For the substitution to be valid, evaluating both expressions should result in the same termination behavior in any context.
cs2041.org