34 Hence the function @{text"value"} takes an additional parameter, an |
34 Hence the function @{text"value"} takes an additional parameter, an |
35 \emph{environment} of type @{typ"nat => bool"}, which maps variables to their |
35 \emph{environment} of type @{typ"nat => bool"}, which maps variables to their |
36 values: |
36 values: |
37 *} |
37 *} |
38 |
38 |
39 consts value :: "boolex \\<Rightarrow> (nat \\<Rightarrow> bool) \\<Rightarrow> bool"; |
39 consts value :: "boolex \<Rightarrow> (nat \<Rightarrow> bool) \<Rightarrow> bool"; |
40 primrec |
40 primrec |
41 "value (Const b) env = b" |
41 "value (Const b) env = b" |
42 "value (Var x) env = env x" |
42 "value (Var x) env = env x" |
43 "value (Neg b) env = (\\<not> value b env)" |
43 "value (Neg b) env = (\<not> value b env)" |
44 "value (And b c) env = (value b env \\<and> value c env)"; |
44 "value (And b c) env = (value b env \<and> value c env)"; |
45 |
45 |
46 text{*\noindent |
46 text{*\noindent |
47 \subsubsection{If-expressions} |
47 \subsubsection{If-expressions} |
48 |
48 |
49 An alternative and often more efficient (because in a certain sense |
49 An alternative and often more efficient (because in a certain sense |
56 |
56 |
57 text{*\noindent |
57 text{*\noindent |
58 The evaluation if If-expressions proceeds as for @{typ"boolex"}: |
58 The evaluation if If-expressions proceeds as for @{typ"boolex"}: |
59 *} |
59 *} |
60 |
60 |
61 consts valif :: "ifex \\<Rightarrow> (nat \\<Rightarrow> bool) \\<Rightarrow> bool"; |
61 consts valif :: "ifex \<Rightarrow> (nat \<Rightarrow> bool) \<Rightarrow> bool"; |
62 primrec |
62 primrec |
63 "valif (CIF b) env = b" |
63 "valif (CIF b) env = b" |
64 "valif (VIF x) env = env x" |
64 "valif (VIF x) env = env x" |
65 "valif (IF b t e) env = (if valif b env then valif t env |
65 "valif (IF b t e) env = (if valif b env then valif t env |
66 else valif e env)"; |
66 else valif e env)"; |
71 The type @{typ"boolex"} is close to the customary representation of logical |
71 The type @{typ"boolex"} is close to the customary representation of logical |
72 formulae, whereas @{typ"ifex"} is designed for efficiency. It is easy to |
72 formulae, whereas @{typ"ifex"} is designed for efficiency. It is easy to |
73 translate from @{typ"boolex"} into @{typ"ifex"}: |
73 translate from @{typ"boolex"} into @{typ"ifex"}: |
74 *} |
74 *} |
75 |
75 |
76 consts bool2if :: "boolex \\<Rightarrow> ifex"; |
76 consts bool2if :: "boolex \<Rightarrow> ifex"; |
77 primrec |
77 primrec |
78 "bool2if (Const b) = CIF b" |
78 "bool2if (Const b) = CIF b" |
79 "bool2if (Var x) = VIF x" |
79 "bool2if (Var x) = VIF x" |
80 "bool2if (Neg b) = IF (bool2if b) (CIF False) (CIF True)" |
80 "bool2if (Neg b) = IF (bool2if b) (CIF False) (CIF True)" |
81 "bool2if (And b c) = IF (bool2if b) (bool2if c) (CIF False)"; |
81 "bool2if (And b c) = IF (bool2if b) (bool2if c) (CIF False)"; |
105 repeatedly replacing a subterm of the form @{term"IF (IF b x y) z u"} by |
105 repeatedly replacing a subterm of the form @{term"IF (IF b x y) z u"} by |
106 @{term"IF b (IF x z u) (IF y z u)"}, which has the same value. The following |
106 @{term"IF b (IF x z u) (IF y z u)"}, which has the same value. The following |
107 primitive recursive functions perform this task: |
107 primitive recursive functions perform this task: |
108 *} |
108 *} |
109 |
109 |
110 consts normif :: "ifex \\<Rightarrow> ifex \\<Rightarrow> ifex \\<Rightarrow> ifex"; |
110 consts normif :: "ifex \<Rightarrow> ifex \<Rightarrow> ifex \<Rightarrow> ifex"; |
111 primrec |
111 primrec |
112 "normif (CIF b) t e = IF (CIF b) t e" |
112 "normif (CIF b) t e = IF (CIF b) t e" |
113 "normif (VIF x) t e = IF (VIF x) t e" |
113 "normif (VIF x) t e = IF (VIF x) t e" |
114 "normif (IF b t e) u f = normif b (normif t u f) (normif e u f)"; |
114 "normif (IF b t e) u f = normif b (normif t u f) (normif e u f)"; |
115 |
115 |
116 consts norm :: "ifex \\<Rightarrow> ifex"; |
116 consts norm :: "ifex \<Rightarrow> ifex"; |
117 primrec |
117 primrec |
118 "norm (CIF b) = CIF b" |
118 "norm (CIF b) = CIF b" |
119 "norm (VIF x) = VIF x" |
119 "norm (VIF x) = VIF x" |
120 "norm (IF b t e) = normif b (norm t) (norm e)"; |
120 "norm (IF b t e) = normif b (norm t) (norm e)"; |
121 |
121 |
131 The proof is canonical, provided we first show the following simplification |
131 The proof is canonical, provided we first show the following simplification |
132 lemma (which also helps to understand what @{term"normif"} does): |
132 lemma (which also helps to understand what @{term"normif"} does): |
133 *} |
133 *} |
134 |
134 |
135 lemma [simp]: |
135 lemma [simp]: |
136 "\\<forall>t e. valif (normif b t e) env = valif (IF b t e) env"; |
136 "\<forall>t e. valif (normif b t e) env = valif (IF b t e) env"; |
137 (*<*) |
137 (*<*) |
138 apply(induct_tac b); |
138 apply(induct_tac b); |
139 by(auto); |
139 by(auto); |
140 |
140 |
141 theorem "valif (norm b) env = valif b env"; |
141 theorem "valif (norm b) env = valif b env"; |
148 |
148 |
149 But how can we be sure that @{term"norm"} really produces a normal form in |
149 But how can we be sure that @{term"norm"} really produces a normal form in |
150 the above sense? We define a function that tests If-expressions for normality |
150 the above sense? We define a function that tests If-expressions for normality |
151 *} |
151 *} |
152 |
152 |
153 consts normal :: "ifex \\<Rightarrow> bool"; |
153 consts normal :: "ifex \<Rightarrow> bool"; |
154 primrec |
154 primrec |
155 "normal(CIF b) = True" |
155 "normal(CIF b) = True" |
156 "normal(VIF x) = True" |
156 "normal(VIF x) = True" |
157 "normal(IF b t e) = (normal t \\<and> normal e \\<and> |
157 "normal(IF b t e) = (normal t \<and> normal e \<and> |
158 (case b of CIF b \\<Rightarrow> True | VIF x \\<Rightarrow> True | IF x y z \\<Rightarrow> False))"; |
158 (case b of CIF b \<Rightarrow> True | VIF x \<Rightarrow> True | IF x y z \<Rightarrow> False))"; |
159 |
159 |
160 text{*\noindent |
160 text{*\noindent |
161 and prove @{term"normal(norm b)"}. Of course, this requires a lemma about |
161 and prove @{term"normal(norm b)"}. Of course, this requires a lemma about |
162 normality of @{term"normif"}: |
162 normality of @{term"normif"}: |
163 *} |
163 *} |
164 |
164 |
165 lemma[simp]: "\\<forall>t e. normal(normif b t e) = (normal t \\<and> normal e)"; |
165 lemma[simp]: "\<forall>t e. normal(normif b t e) = (normal t \<and> normal e)"; |
166 (*<*) |
166 (*<*) |
167 apply(induct_tac b); |
167 apply(induct_tac b); |
168 by(auto); |
168 by(auto); |
169 |
169 |
170 theorem "normal(norm b)"; |
170 theorem "normal(norm b)"; |
171 apply(induct_tac b); |
171 apply(induct_tac b); |
172 by(auto); |
172 by(auto); |
173 (*>*) |
173 (*>*) |
174 |
174 |
175 text{*\medskip |
175 text{*\medskip |
176 How does one come up with the required lemmas? Try to prove the main theorems |
176 How do we come up with the required lemmas? Try to prove the main theorems |
177 without them and study carefully what @{text auto} leaves unproved. This has |
177 without them and study carefully what @{text auto} leaves unproved. This |
178 to provide the clue. The necessity of universal quantification |
178 can provide the clue. The necessity of universal quantification |
179 (@{text"\<forall>t e"}) in the two lemmas is explained in |
179 (@{text"\<forall>t e"}) in the two lemmas is explained in |
180 \S\ref{sec:InductionHeuristics} |
180 \S\ref{sec:InductionHeuristics} |
181 |
181 |
182 \begin{exercise} |
182 \begin{exercise} |
183 We strengthen the definition of a @{term normal} If-expression as follows: |
183 We strengthen the definition of a @{term normal} If-expression as follows: |