lecture_2: THEORY BEGIN % % Exercise 1 % % The PVS prelude includes the following definitions: % % expt(r, n): RECURSIVE real = % IF n = 0 THEN 1 % ELSE r * expt(r, n-1) % ENDIF % MEASURE n; % % ^(r: real, i:{i:int | r /= 0 OR i >= 0}): real % = IF i >= 0 THEN expt(r, i) ELSE 1/expt(r, -i) ENDIF % Ex Ponent Facto(rial) % { 1 , if n = 0 % n! = { % { n * (n - 1)! , otherwise factorial(n : nat): RECURSIVE posnat = IF n = 0 THEN 1 ELSE n * factorial(n - 1) ENDIF MEASURE n % discharge factorial_TCC1 with (grind-reals) % From the prelude, we have: % % gt_times_gt_pos1: LEMMA % x >= py AND z > nnw IMPLIES x * z > py * nnw % % This lemma may be used in a proof of the following. % You will have to provide explicit instantiations. % Consider the following substitutions*: % nnw <- exp2(j!1) % py <- 2 % x <- (j!1 + 1) % z <- factorial(j!1) % *use j!1 for _nat, ja!1 for _above3 % You may also need to rewrite with the following two prelude results % at an appropriate proof step. % expt_x1: LEMMA x^1 = x % expt_plus: LEMMA n0x^(i + j) = n0x^i * n0x^j m,n : VAR nat factorial_gt_expt2_nat: LEMMA % DO NOT USE (induct-and-simplify "n"). n > 3 IMPLIES factorial(n) > 2 ^ n x: var above(3) factorial_gt_expt2_above3: LEMMA % DO NOT USE (induct-and-simplify "x"). factorial(x) > 2 ^ x % % Exercise 2 % % Ackermann ack(m,n) : RECURSIVE nat = IF m = 0 THEN n+1 ELSIF n = 0 THEN ack(m-1,1) ELSE ack(m-1,ack(m,n-1)) ENDIF MEASURE lex2(m,n) % Hint: You may need two inductions ack_simple_property : THEOREM FORALL(m,n): ack(m,n) > m+n % % Exercise 3 % % Example of for loops IMPORTING MyNAS, structures@for_iterate % /* Pre: nas is non empty */ % ac = nas[1] % for (int i=1; i < n; i++) { % /* Inv: ac = max(ac[1..i]) */ % ac = max(ac,nas[i+1]); % } % /* Post: ac = max(nas[1..n]) */ fastest(nas:(nonemptynas?)) : Aircraft % = ... % Hint: You may need the following invariant % LAMBDA(i:upto(nas`n-1),ac:Aircraft): % FORALL (k:subrange(1,i+1)): ac`gs >= nas`seq(k)`gs fastest_correct : THEOREM FORALL (nas:(nonemptynas?),i:subrange(1,nas`n)): fastest(nas)`gs >= nas`seq(i)`gs % Example inductive definitions % Sample inductive definitions, use M-x ppe to see automatically % generated induction schemas even(n:nat): INDUCTIVE bool = n = 0 OR (n > 1 AND even(n - 2)) odd(n:nat): INDUCTIVE bool = n = 1 OR (n > 1 AND odd(n - 2)) % use (rule-induct "even") even_odd: LEMMA even(n) => odd(n + 1) % use (rule-induct "odd") odd_even: LEMMA odd(n) => even(n + 1) % use (induct-and-simplify "n") % then use the preceding two lemmas even_or_odd: LEMMA even(n) OR odd(n) % % Exercise 4 % %% PVS DOES NOT (DIRECTLY) SUPPORT MUTUAL RECURSION % my_even?(n) : INDUCTIVE bool = % n = 0 OR n > 0 AND my_odd?(n-1) % % my_odd?(n) : INDUCTIVE bool = % n = 1 OR n > 1 AND my_even?(n-1) %% Mutual recursion can be simulated using regular recursion even_f?(fodd:[nat->bool],n) : bool = n = 0 OR n > 0 AND fodd(n-1) my_odd?(n) : INDUCTIVE bool = n = 1 OR n > 1 AND even_f?(my_odd?,n-1) my_even?(n) : bool = even_f?(my_odd?,n) % Hint: Use induction on "n" and lemmas even_odd and odd_even my_even_my_odd : THEOREM my_even?(n) = even(n) AND my_odd?(n) = odd(n) % % Exercise 5 % Tree : DATATYPE BEGIN nulltree : nulltree? constree(val:nat,left:Tree,right:Tree) : constree? END Tree height(t:Tree) : RECURSIVE nat = CASES t OF nulltree : 0 ELSE 1+max(height(left(t)),height(right(t))) ENDCASES MEASURE t BY << monotonetree?(t:Tree): INDUCTIVE bool = nulltree?(t) OR (constree?(left(t)) IMPLIES val(t) > val(left(t))) AND (constree?(right(t)) IMPLIES val(t) > val(right(t))) AND monotonetree?(left(t)) AND monotonetree?(right(t)) consotonetree?(t:Tree): MACRO bool = constree?(t) AND monotonetree?(t) height_monotone: THEOREM FORALL (t:(consotonetree?)): height(t) <= val(t)+1 % % More Exercises % f: VAR [nat -> nat] % Fun with summation sum(n): RECURSIVE nat = IF n = 0 THEN 0 ELSE n + sum(n - 1) ENDIF MEASURE n closed_form: THEOREM sum(n) = (n * (n + 1)) / 2 sum(n, f) : RECURSIVE nat = IF n = 0 THEN f(0) ELSE f(n) + sum(n - 1, f) ENDIF MEASURE n % Reminder: id is the identity function, id(x) = x closed_form2: THEOREM sum(n, id) = (n * (n + 1)) / 2 square(n: nat) : nat = n * n cube(n: nat) : nat = n*n*n sum_of_squares: LEMMA sum(n, square) = (n * (n + 1) * (2 * n + 1)) / 6 sum_of_cubes: LEMMA % hint: try (rewrite "closed_form") when you get stuck. sum(n, cube) = square(sum(n)) times_distributes_over_sum: LEMMA m * sum(n, f) = sum(n, (LAMBDA (n1 : nat) : m * f(n1))) expt2(n) : nat = 2 ^ n sum_expt2: LEMMA % use (induct-and-simplify$ "n") to illustrate strategy sum(n, expt2) = 2 ^ (n + 1) - 1 % % Functional equivalence of algorithms % % A Tail of Two Fibonacci's % i, j, k: VAR nat % ith Fibonacci fib(i): RECURSIVE nat = IF i = 0 THEN 1 ELSIF i = 1 THEN 1 ELSE (fib(i - 1) + fib(i - 2)) ENDIF MEASURE i % tail recursive definition of Fibonacci tfib(i, j, k): RECURSIVE nat = IF i = 0 THEN j ELSE tfib(i - 1, k, j + k) ENDIF MEASURE i % Reminder: (induct-and-simplify "i") occasionally takes you down an % unfortunate path. In this case, it is better to simply use (induct "i"), % and manually control the expansion of "tfib" fib_tfib: LEMMA tfib(i + 2, j, k) = tfib(i + 1, j, k) + tfib(i, j, k) % Reminder: The proof of tfib_fib requires strong induction. % The first step is (induct "i" :name "NAT_induction") tfib_fib: THEOREM fib(i) = tfib(i, 1, 1) END lecture_2