## Correctness

How can we convince ourselves (and others) that a program is correct?

``````let sum_to n =
let rec tr_sum i acc =
if i=0 then acc
else tr_sum i-1 acc+i in
tr_sum n 0``````
``````let fib n =
let rec tr_fib i f0 f1 =
if i=0 then f0
else tr_fib (i-1) f1 (f1+f0) in
tr_fib n 0 1``````

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

``````let rec sum_to n =
if n = 0 then 0 else n + (sum_to (n-1))``````

Prove: for all `𝓃 ≥ 0`, `sum_to 𝓃` ≡ ∑i≤𝓃 i.

Here `P(𝓃)` = `sum_to 𝓃` ≡ ∑i≤𝓃 i, so we need to prove:

1. Base Case: `sum_to 0` ≡ 0 [✓, eval. `sum_to`]
2. Inductive (step) Case:
if `sum_to 𝓃` ≡ ∑i≤𝓃 i ( Inductive Hypothesis )
then `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]

# using lemmas

``````let sum_to n =
let rec tr_sum i acc =
if i=0 then acc
else tr_sum i-1 acc+i in
tr_sum n 0``````

In order to prove that for all 𝓃, `(sum_to 𝓃)` ≡ ∑i≤𝓃i, we need to prove a lemma about `tr_sum`:

For all 𝓃≥0, for all 𝒶, `tr_sum 𝓃 𝒶` ≡ 𝒶 + ∑i≤𝓃i.
``````  let rec tr_sum i acc =
if i=0 then acc
else tr_sum i-1 acc+i``````
For all 𝓃≥0, for all 𝒶, `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]

``````let fib n =
let rec tr_fib i f0 f1 =
if i=0 then f0
else tr_fib (i-1) f1 (f1+f0) in
tr_fib n 0 1``````

In order to prove that for all `n`, `fib n` ≡ F`n`, we prove a lemma about `tr_fib`:

For all i≥0, for all n, `tr_fib` i F`n-i` F`n-i+1` ≡ F`n`
``````  let rec tr_fib i f0 f1 =
if i=0 then f0
else tr_fib (i-1) f1 (f1+f0) in``````
For all i≥0, for all n, `tr_fib` i F`n-i` F`n-i+1` ≡ F`n`

Base Case: `tr_fib 0` F`n` F`n+1` ≡ F`n`, by evaluation.

Inductive Case:

`tr_fib (i+1)` F`n-i-1` F`n-i`

`tr_fib` `i` F`n-i` (F`n-i` + F`n-i-1`)`    `[eval. `tr_fib`]

`tr_fib` `i` F`n-i` F`(n-i)+1`≡ F`n``     `[✓, algebra, IH]

# Referential Transparency

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`

// reveal.js plugins