Lecture 003

Recursion and Induction

Standard Induction

See Lecture_010.md in 21-127

Strong Induction

See Lecture_011.md in 21-127

Reduction

(* square : int -> int
REQUIRES: true
ENSURES: square(n) => n^2
*)
fun square (n : int) : int = n*n

Below shows execution sequence:

square 7
=> [environment where square was defined] (fn (n:int) => n * n) 7
=> [env.] [7/n] (n * n)
=> [env.] [7/n] (7 * n)
=> [env.] [7/n] (7 * 7)
=> [env.] [7/n] 49 = 49 // once we got a value, environment is not important

or write it simpler:

square 7 // this is also fine
=> 7 * 7
=> 49

Typing Rule

(* even: int -> bool
REQUIRES: true
ENSURES: even k (tailedarror => to value) {true if k even; false if k odd}
fun even (k : int) : bool = (k mod 2) = 0
*)

In if e1 then e2 else e3 : t, e2 and e3 has to be the same type t.

Equivalently, in the following code e2 and e3 has to be the same type.

case e1 of
    true => e2
  | false => e3

If...then...else is only good for bool Always use case will ensure you don't make mistake

Recursion (two complexity with induction)

(* power: (int * int) -> int
REQUIRES: k >= 0
ENSURES: power (n, k) (tailedarror) n^k (where 0^0 = 1)
*)
fun power (n : int, 0 : int) : int = 1
  | power (n, k) = n * power (n, k-1)
(* 3^7 = 3*3*3*3*3*3*3 *)
(* complexity: O(k) by recursive calls *)

fun power (n : int, 0 : int) : int = 1
  | power (n, k) =
         if even k
         then square (power (n, k div 2))
         else n * power (n, k-1)
(* 3^7 = 3(3(3*1)^2)^2 *)
(* complexity: O(log k) *)

Theorem: for all VALUES (because they might have on value) n:int, k:int where k>=0, power (n, k) |-> n^k Proof(1): By standard (weak) induction on k Base Case: k=0 WTS power (n, 0) |-> n^0 = 1 for all values n:int. power (n, 0) => 1 [first clause of power] Induction Step: prove k+1 holds using k hold induction hypothesis: power (n, k) -> n^k hold for all values n : int, for some fixed k >= 0 WTS: power (n, k+1) |-> n^{k+1} for all value n : int power (n, k+1) => n * power (n, k+1-1) [2nd clause] => n * power (n, k) [math] => n * n^k [induction hypothesis] => n^{k+1} [math] Since base case and inductive case are proved, the result follows by induction.

Proof(2): By strong induction on k Base Case: k=0 WTS power (n, 0) |-> n^0 = 1 for all values n:int. power (n, 0) => 1 [first clause of power] Induction Step: prove k hold using for all 0 <= k' < k, k' hold induction hypothesis: power (n, k) -> n^k hold for k' : int with 0 <= k' < k, and n : int WTS: power (n, k) |-> n^{k} for all value n : int power (n, k) => if even k then square (power (n, k div 2)) else n * power (n, k - 1) [2nd clause] case: k even: => square (power (n, k div 2)) [if-then-else] k = 2 * k' (for some k') and even k |=> true then k' = k/2, then k' < k [by math since k>0 and even] => square (power (n, k')) [math] => square (n^k') [IH] => n^k' * n^k' [by square] => n^k [math] case: k odd: => n * power (n, k-1) [if-then-else] ... (change k+1 to k)...

Structure Induction

Structured induction is just induction but with code.

List

Type: t list (is a list for any type t)

Values: [v1, ..., vn] where each vi is a value of type t and n>= 0 - when n = 0, [] = nil

Expressions: - [] or nil - e :: es (where e:t and es: t list) - :: is pronounced as "con" stands for concat - val 1::[2, 3] = [1, 2, 3]

Type Checking rule: - [] : t list - e :: es : t list if e : t and es : t list

Code

(*
length: int list -> int
REQUIRES: true
ENSURES: length L returns the length of L
*)
fun length ([] : int list) : int = 0
  | length (x :: xs) = 1 + length xs

Theorem: length is total (ie. length L |-> something, for all L : int list) Proof: by structure induction on L Base Case: when L = [] WTS length [] |-> something length [] => 0 [first clause] Inductive Step: when L = x::xs for some value x:int and xs:int list IH: length xs |-> v for some v WIS: length (x::xs) |-> v' for some v' length (x::xs) => 1 + length xs [second clause] => 1 + v [IH] => (v + 1) [math] let v' = v+1, since v is a type int, v' is value

Table of Content