summaryrefslogtreecommitdiff
path: root/assignment7/E.pvs
blob: 5f02082f9ed2f51cbc98511025ae5d2d90182211 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
%%%    NAME/LOGIN-ID    Camil Staps / s4498062
%%%    ACKNOWLEDGMENTS:

th_E: THEORY

BEGIN

%%%
%%% Standard development of iterative factorial-with-accumulator.
%%% Start with a "specification" of the factorial function.
%%%

fac(n:nat): RECURSIVE nat = 
  IF n = 0
   THEN 1
   ELSE fac(n-1) * n
  ENDIF
  MEASURE n 

%%%
%%% A few simple facts about the factorial function.
%%%

thm_E_0: LEMMA (FORALL (k:nat): k>=1 IMPLIES fac(k) < fac(k+1))

thm_E_1: THEOREM (FORALL (k:nat): 1 <= fac(k))
thm_E_2: THEOREM (FORALL (k:nat): k <= fac(k))

%%%
%%% In tfac, below, all recursive calls are in the tail position. In operational terms,
%%% tfac "improves" fac because a no space is needed for a recursion stack.  In other
%%% words, tfac is and instance of the "implementation model" for sequential execution.
%%%

tfac(n:nat, m:nat): RECURSIVE nat =
  IF n = 0
   THEN m
   ELSE tfac(n - 1, m * n)
  ENDIF
 MEASURE n

%%%
%%% We should prove, though, that tfac is equivalent to fac.  They are not "equal" because,
%%% for one thing, tfac takes two arguments and fac takes only one.  In fact, tfac(n, m)
%%% only computes fac(n) when m = 1.
%%%
%%% However, in trying to prove this, we run into a problem...
%%% In the inductive case, we'll get something like this:
%%%
%%%   [-1] fac(J) = tfac(J, 1)
%%%      |------------------------
%%%   [1]  (J+1) * fac(J) = tfac(J, J+1)
%%%
%%% To complete the proof, we need to "distribute" J+1 outside fact.  But attempting
%%% to prove this, for just "J+1" will fail.  A _generalization_ is needed...
%%%

lemma_E_3: LEMMA  (FORALL (m:nat, n:nat): tfac(m, n) = n * fac(m))

%%%
%%% On the strength of this lemma, we can prove the correctness of tfac.

th_E_4: THEOREM  (FORALL (k:nat): fac(k) = tfac(k, 1))

%%%
%%% Below, we'll do the same standard development for iterative the Fibonacci function.
%%% Except this time, YOU have to find the appropriate lemma!  Although there are several
%%% reasonable possibilities for the needed lemma, it is not easy to think of one.
%%%
%%% Remember that the lemma must GENERALIZE the desired result.
%%%

fib(n:nat): RECURSIVE nat =
  (IF    n = 0 THEN 1
   ELSIF n = 1 THEN 1
               ELSE fib(n - 1) + fib(n - 2)
   ENDIF)
  MEASURE n

%%%
%%% Tail-recursive version of fib.
%%%

tfib(n:nat, m:nat, p:nat): RECURSIVE nat =
  (IF n = 0
    THEN m
    ELSE tfib(n - 1, p, p + m)
    ENDIF)
  MEASURE n

%%%
%%% YOU will need to discover a nontrivial lemma to prove thm.
%%% Place your lemma just below, before thm_E_6.
%%%

lem_E_Camil_2: LEMMA
  (FORALL (i:nat, m:nat, p:nat):
    tfib(i, m, p) =
      IF    i = 0 THEN m
      ELSIF i = 1 THEN p
                  ELSE fib(i-2)*m + fib(i-1)*p
      ENDIF)

thm_E_6: THEOREM
  (FORALL (i:nat):
    tfib(i, 1, 1) = fib(i))

END th_E