12 \[ |
12 \[ |
13 \begin{array}{rcl} |
13 \begin{array}{rcl} |
14 |
14 |
15 \mathit{form} & ::= & |
15 \mathit{form} & ::= & |
16 \<open>(form)\<close> ~\mid~ |
16 \<open>(form)\<close> ~\mid~ |
17 @{const True} ~\mid~ |
17 \<^const>\<open>True\<close> ~\mid~ |
18 @{const False} ~\mid~ |
18 \<^const>\<open>False\<close> ~\mid~ |
19 @{prop "term = term"}\\ |
19 \<^prop>\<open>term = term\<close>\\ |
20 &\mid& @{prop"\<not> form"}\index{$HOL4@\isasymnot} ~\mid~ |
20 &\mid& \<^prop>\<open>\<not> form\<close>\index{$HOL4@\isasymnot} ~\mid~ |
21 @{prop "form \<and> form"}\index{$HOL0@\isasymand} ~\mid~ |
21 \<^prop>\<open>form \<and> form\<close>\index{$HOL0@\isasymand} ~\mid~ |
22 @{prop "form \<or> form"}\index{$HOL1@\isasymor} ~\mid~ |
22 \<^prop>\<open>form \<or> form\<close>\index{$HOL1@\isasymor} ~\mid~ |
23 @{prop "form \<longrightarrow> form"}\index{$HOL2@\isasymlongrightarrow}\\ |
23 \<^prop>\<open>form \<longrightarrow> form\<close>\index{$HOL2@\isasymlongrightarrow}\\ |
24 &\mid& @{prop"\<forall>x. form"}\index{$HOL6@\isasymforall} ~\mid~ @{prop"\<exists>x. form"}\index{$HOL7@\isasymexists} |
24 &\mid& \<^prop>\<open>\<forall>x. form\<close>\index{$HOL6@\isasymforall} ~\mid~ \<^prop>\<open>\<exists>x. form\<close>\index{$HOL7@\isasymexists} |
25 \end{array} |
25 \end{array} |
26 \] |
26 \] |
27 Terms are the ones we have seen all along, built from constants, variables, |
27 Terms are the ones we have seen all along, built from constants, variables, |
28 function application and \<open>\<lambda>\<close>-abstraction, including all the syntactic |
28 function application and \<open>\<lambda>\<close>-abstraction, including all the syntactic |
29 sugar like infix symbols, \<open>if\<close>, \<open>case\<close>, etc. |
29 sugar like infix symbols, \<open>if\<close>, \<open>case\<close>, etc. |
30 \begin{warn} |
30 \begin{warn} |
31 Remember that formulas are simply terms of type \<open>bool\<close>. Hence |
31 Remember that formulas are simply terms of type \<open>bool\<close>. Hence |
32 \<open>=\<close> also works for formulas. Beware that \<open>=\<close> has a higher |
32 \<open>=\<close> also works for formulas. Beware that \<open>=\<close> has a higher |
33 precedence than the other logical operators. Hence @{prop"s = t \<and> A"} means |
33 precedence than the other logical operators. Hence \<^prop>\<open>s = t \<and> A\<close> means |
34 \<open>(s = t) \<and> A\<close>, and @{prop"A\<and>B = B\<and>A"} means \<open>A \<and> (B = B) \<and> A\<close>. |
34 \<open>(s = t) \<and> A\<close>, and \<^prop>\<open>A\<and>B = B\<and>A\<close> means \<open>A \<and> (B = B) \<and> A\<close>. |
35 Logical equivalence can also be written with |
35 Logical equivalence can also be written with |
36 \<open>\<longleftrightarrow>\<close> instead of \<open>=\<close>, where \<open>\<longleftrightarrow>\<close> has the same low |
36 \<open>\<longleftrightarrow>\<close> instead of \<open>=\<close>, where \<open>\<longleftrightarrow>\<close> has the same low |
37 precedence as \<open>\<longrightarrow>\<close>. Hence \<open>A \<and> B \<longleftrightarrow> B \<and> A\<close> really means |
37 precedence as \<open>\<longrightarrow>\<close>. Hence \<open>A \<and> B \<longleftrightarrow> B \<and> A\<close> really means |
38 \<open>(A \<and> B) \<longleftrightarrow> (B \<and> A)\<close>. |
38 \<open>(A \<and> B) \<longleftrightarrow> (B \<and> A)\<close>. |
39 \end{warn} |
39 \end{warn} |
78 \end{warn} |
78 \end{warn} |
79 |
79 |
80 \section{Sets} |
80 \section{Sets} |
81 \label{sec:Sets} |
81 \label{sec:Sets} |
82 |
82 |
83 Sets of elements of type @{typ 'a} have type @{typ"'a set"}\index{set@\<open>set\<close>}. |
83 Sets of elements of type \<^typ>\<open>'a\<close> have type \<^typ>\<open>'a set\<close>\index{set@\<open>set\<close>}. |
84 They can be finite or infinite. Sets come with the usual notation: |
84 They can be finite or infinite. Sets come with the usual notation: |
85 \begin{itemize} |
85 \begin{itemize} |
86 \item \indexed{@{term"{}"}}{$IMP042},\quad \<open>{e\<^sub>1,\<dots>,e\<^sub>n}\<close> |
86 \item \indexed{\<^term>\<open>{}\<close>}{$IMP042},\quad \<open>{e\<^sub>1,\<dots>,e\<^sub>n}\<close> |
87 \item @{prop"e \<in> A"}\index{$HOLSet0@\isasymin},\quad @{prop"A \<subseteq> B"}\index{$HOLSet2@\isasymsubseteq} |
87 \item \<^prop>\<open>e \<in> A\<close>\index{$HOLSet0@\isasymin},\quad \<^prop>\<open>A \<subseteq> B\<close>\index{$HOLSet2@\isasymsubseteq} |
88 \item @{term"A \<union> B"}\index{$HOLSet4@\isasymunion},\quad @{term"A \<inter> B"}\index{$HOLSet5@\isasyminter},\quad @{term"A - B"},\quad @{term"-A"} |
88 \item \<^term>\<open>A \<union> B\<close>\index{$HOLSet4@\isasymunion},\quad \<^term>\<open>A \<inter> B\<close>\index{$HOLSet5@\isasyminter},\quad \<^term>\<open>A - B\<close>,\quad \<^term>\<open>-A\<close> |
89 \end{itemize} |
89 \end{itemize} |
90 (where @{term"A-B"} and \<open>-A\<close> are set difference and complement) |
90 (where \<^term>\<open>A-B\<close> and \<open>-A\<close> are set difference and complement) |
91 and much more. @{const UNIV} is the set of all elements of some type. |
91 and much more. \<^const>\<open>UNIV\<close> is the set of all elements of some type. |
92 Set comprehension\index{set comprehension} is written |
92 Set comprehension\index{set comprehension} is written |
93 @{term"{x. P}"}\index{$IMP042@@{term"{x. P}"}} rather than \<open>{x | P}\<close>. |
93 \<^term>\<open>{x. P}\<close>\index{$IMP042@\<^term>\<open>{x. P}\<close>} rather than \<open>{x | P}\<close>. |
94 \begin{warn} |
94 \begin{warn} |
95 In @{term"{x. P}"} the \<open>x\<close> must be a variable. Set comprehension |
95 In \<^term>\<open>{x. P}\<close> the \<open>x\<close> must be a variable. Set comprehension |
96 involving a proper term \<open>t\<close> must be written |
96 involving a proper term \<open>t\<close> must be written |
97 \noquotes{@{term[source] "{t | x y. P}"}}\index{$IMP042@\<open>{t |x. P}\<close>}, |
97 \noquotes{@{term[source] "{t | x y. P}"}}\index{$IMP042@\<open>{t |x. P}\<close>}, |
98 where \<open>x y\<close> are those free variables in \<open>t\<close> |
98 where \<open>x y\<close> are those free variables in \<open>t\<close> |
99 that occur in \<open>P\<close>. |
99 that occur in \<open>P\<close>. |
100 This is just a shorthand for @{term"{v. \<exists>x y. v = t \<and> P}"}, where |
100 This is just a shorthand for \<^term>\<open>{v. \<exists>x y. v = t \<and> P}\<close>, where |
101 \<open>v\<close> is a new variable. For example, @{term"{x+y|x. x \<in> A}"} |
101 \<open>v\<close> is a new variable. For example, \<^term>\<open>{x+y|x. x \<in> A}\<close> |
102 is short for \noquotes{@{term[source]"{v. \<exists>x. v = x+y \<and> x \<in> A}"}}. |
102 is short for \noquotes{@{term[source]"{v. \<exists>x. v = x+y \<and> x \<in> A}"}}. |
103 \end{warn} |
103 \end{warn} |
104 |
104 |
105 Here are the ASCII representations of the mathematical symbols: |
105 Here are the ASCII representations of the mathematical symbols: |
106 \begin{center} |
106 \begin{center} |
264 to find all the relevant lemmas first. But that is precisely what |
264 to find all the relevant lemmas first. But that is precisely what |
265 \isacom{sledgehammer} does for us. |
265 \isacom{sledgehammer} does for us. |
266 In this case lemma @{thm[source]append_eq_conv_conj} alone suffices: |
266 In this case lemma @{thm[source]append_eq_conv_conj} alone suffices: |
267 @{thm[display] append_eq_conv_conj} |
267 @{thm[display] append_eq_conv_conj} |
268 We leave it to the reader to figure out why this lemma suffices to prove |
268 We leave it to the reader to figure out why this lemma suffices to prove |
269 the above lemma, even without any knowledge of what the functions @{const take} |
269 the above lemma, even without any knowledge of what the functions \<^const>\<open>take\<close> |
270 and @{const drop} do. Keep in mind that the variables in the two lemmas |
270 and \<^const>\<open>drop\<close> do. Keep in mind that the variables in the two lemmas |
271 are independent of each other, despite the same names, and that you can |
271 are independent of each other, despite the same names, and that you can |
272 substitute arbitrary values for the free variables in a lemma. |
272 substitute arbitrary values for the free variables in a lemma. |
273 |
273 |
274 Just as for the other proof methods we have seen, there is no guarantee that |
274 Just as for the other proof methods we have seen, there is no guarantee that |
275 \isacom{sledgehammer} will find a proof if it exists. Nor is |
275 \isacom{sledgehammer} will find a proof if it exists. Nor is |
292 text\<open>In fact, \<open>auto\<close> and \<open>simp\<close> can prove many linear |
292 text\<open>In fact, \<open>auto\<close> and \<open>simp\<close> can prove many linear |
293 arithmetic formulas already, like the one above, by calling a weak but fast |
293 arithmetic formulas already, like the one above, by calling a weak but fast |
294 version of \<open>arith\<close>. Hence it is usually not necessary to invoke |
294 version of \<open>arith\<close>. Hence it is usually not necessary to invoke |
295 \<open>arith\<close> explicitly. |
295 \<open>arith\<close> explicitly. |
296 |
296 |
297 The above example involves natural numbers, but integers (type @{typ int}) |
297 The above example involves natural numbers, but integers (type \<^typ>\<open>int\<close>) |
298 and real numbers (type \<open>real\<close>) are supported as well. As are a number |
298 and real numbers (type \<open>real\<close>) are supported as well. As are a number |
299 of further operators like @{const min} and @{const max}. On @{typ nat} and |
299 of further operators like \<^const>\<open>min\<close> and \<^const>\<open>max\<close>. On \<^typ>\<open>nat\<close> and |
300 @{typ int}, \<open>arith\<close> can even prove theorems with quantifiers in them, |
300 \<^typ>\<open>int\<close>, \<open>arith\<close> can even prove theorems with quantifiers in them, |
301 but we will not enlarge on that here. |
301 but we will not enlarge on that here. |
302 |
302 |
303 |
303 |
304 \subsection{Trying Them All} |
304 \subsection{Trying Them All} |
305 |
305 |
318 |
318 |
319 Although automation is nice, it often fails, at least initially, and you need |
319 Although automation is nice, it often fails, at least initially, and you need |
320 to find out why. When \<open>fastforce\<close> or \<open>blast\<close> simply fail, you have |
320 to find out why. When \<open>fastforce\<close> or \<open>blast\<close> simply fail, you have |
321 no clue why. At this point, the stepwise |
321 no clue why. At this point, the stepwise |
322 application of proof rules may be necessary. For example, if \<open>blast\<close> |
322 application of proof rules may be necessary. For example, if \<open>blast\<close> |
323 fails on @{prop"A \<and> B"}, you want to attack the two |
323 fails on \<^prop>\<open>A \<and> B\<close>, you want to attack the two |
324 conjuncts \<open>A\<close> and \<open>B\<close> separately. This can |
324 conjuncts \<open>A\<close> and \<open>B\<close> separately. This can |
325 be achieved by applying \emph{conjunction introduction} |
325 be achieved by applying \emph{conjunction introduction} |
326 \[ @{thm[mode=Rule,show_question_marks]conjI}\ \<open>conjI\<close> |
326 \[ @{thm[mode=Rule,show_question_marks]conjI}\ \<open>conjI\<close> |
327 \] |
327 \] |
328 to the proof state. We will now examine the details of this process. |
328 to the proof state. We will now examine the details of this process. |
344 the unknowns in the theorem \<open>th\<close> from left to right with the terms |
344 the unknowns in the theorem \<open>th\<close> from left to right with the terms |
345 \<open>string\<^sub>1\<close> to \<open>string\<^sub>n\<close>. |
345 \<open>string\<^sub>1\<close> to \<open>string\<^sub>n\<close>. |
346 |
346 |
347 \item By unification. \conceptidx{Unification}{unification} is the process of making two |
347 \item By unification. \conceptidx{Unification}{unification} is the process of making two |
348 terms syntactically equal by suitable instantiations of unknowns. For example, |
348 terms syntactically equal by suitable instantiations of unknowns. For example, |
349 unifying \<open>?P \<and> ?Q\<close> with \mbox{@{prop"a=b \<and> False"}} instantiates |
349 unifying \<open>?P \<and> ?Q\<close> with \mbox{\<^prop>\<open>a=b \<and> False\<close>} instantiates |
350 \<open>?P\<close> with @{prop "a=b"} and \<open>?Q\<close> with @{prop False}. |
350 \<open>?P\<close> with \<^prop>\<open>a=b\<close> and \<open>?Q\<close> with \<^prop>\<open>False\<close>. |
351 \end{itemize} |
351 \end{itemize} |
352 We need not instantiate all unknowns. If we want to skip a particular one we |
352 We need not instantiate all unknowns. If we want to skip a particular one we |
353 can write \<open>_\<close> instead, for example \<open>conjI[of _ "False"]\<close>. |
353 can write \<open>_\<close> instead, for example \<open>conjI[of _ "False"]\<close>. |
354 Unknowns can also be instantiated by name using \indexed{\<open>where\<close>}{where}, for example |
354 Unknowns can also be instantiated by name using \indexed{\<open>where\<close>}{where}, for example |
355 \<open>conjI[where ?P = "a=b"\<close> \isacom{and} \<open>?Q = "False"]\<close>. |
355 \<open>conjI[where ?P = "a=b"\<close> \isacom{and} \<open>?Q = "False"]\<close>. |
417 the \indexed{\<open>intro\<close>}{intro} attribute, analogous to the \<open>simp\<close> attribute. In |
417 the \indexed{\<open>intro\<close>}{intro} attribute, analogous to the \<open>simp\<close> attribute. In |
418 that case \<open>blast\<close>, \<open>fastforce\<close> and (to a limited extent) \<open>auto\<close> will automatically backchain with those theorems. The \<open>intro\<close> |
418 that case \<open>blast\<close>, \<open>fastforce\<close> and (to a limited extent) \<open>auto\<close> will automatically backchain with those theorems. The \<open>intro\<close> |
419 attribute should be used with care because it increases the search space and |
419 attribute should be used with care because it increases the search space and |
420 can lead to nontermination. Sometimes it is better to use it only in |
420 can lead to nontermination. Sometimes it is better to use it only in |
421 specific calls of \<open>blast\<close> and friends. For example, |
421 specific calls of \<open>blast\<close> and friends. For example, |
422 @{thm[source] le_trans}, transitivity of \<open>\<le>\<close> on type @{typ nat}, |
422 @{thm[source] le_trans}, transitivity of \<open>\<le>\<close> on type \<^typ>\<open>nat\<close>, |
423 is not an introduction rule by default because of the disastrous effect |
423 is not an introduction rule by default because of the disastrous effect |
424 on the search space, but can be useful in specific situations: |
424 on the search space, but can be useful in specific situations: |
425 \<close> |
425 \<close> |
426 |
426 |
427 lemma "\<lbrakk> (a::nat) \<le> b; b \<le> c; c \<le> d; d \<le> e \<rbrakk> \<Longrightarrow> a \<le> e" |
427 lemma "\<lbrakk> (a::nat) \<le> b; b \<le> c; c \<le> d; d \<le> e \<rbrakk> \<Longrightarrow> a \<le> e" |
434 \label{sec:forward-proof} |
434 \label{sec:forward-proof} |
435 |
435 |
436 Forward proof means deriving new theorems from old theorems. We have already |
436 Forward proof means deriving new theorems from old theorems. We have already |
437 seen a very simple form of forward proof: the \<open>of\<close> operator for |
437 seen a very simple form of forward proof: the \<open>of\<close> operator for |
438 instantiating unknowns in a theorem. The big brother of \<open>of\<close> is |
438 instantiating unknowns in a theorem. The big brother of \<open>of\<close> is |
439 \indexed{\<open>OF\<close>}{OF} for applying one theorem to others. Given a theorem @{prop"A \<Longrightarrow> B"} called |
439 \indexed{\<open>OF\<close>}{OF} for applying one theorem to others. Given a theorem \<^prop>\<open>A \<Longrightarrow> B\<close> called |
440 \<open>r\<close> and a theorem \<open>A'\<close> called \<open>r'\<close>, the theorem \<open>r[OF r']\<close> is the result of applying \<open>r\<close> to \<open>r'\<close>, where \<open>r\<close> should be viewed as a function taking a theorem \<open>A\<close> and returning |
440 \<open>r\<close> and a theorem \<open>A'\<close> called \<open>r'\<close>, the theorem \<open>r[OF r']\<close> is the result of applying \<open>r\<close> to \<open>r'\<close>, where \<open>r\<close> should be viewed as a function taking a theorem \<open>A\<close> and returning |
441 \<open>B\<close>. More precisely, \<open>A\<close> and \<open>A'\<close> are unified, thus |
441 \<open>B\<close>. More precisely, \<open>A\<close> and \<open>A'\<close> are unified, thus |
442 instantiating the unknowns in \<open>B\<close>, and the result is the instantiated |
442 instantiating the unknowns in \<open>B\<close>, and the result is the instantiated |
443 \<open>B\<close>. Of course, unification may also fail. |
443 \<open>B\<close>. Of course, unification may also fail. |
444 \begin{warn} |
444 \begin{warn} |
535 fun evn :: "nat \<Rightarrow> bool" where |
535 fun evn :: "nat \<Rightarrow> bool" where |
536 "evn 0 = True" | |
536 "evn 0 = True" | |
537 "evn (Suc 0) = False" | |
537 "evn (Suc 0) = False" | |
538 "evn (Suc(Suc n)) = evn n" |
538 "evn (Suc(Suc n)) = evn n" |
539 |
539 |
540 text\<open>We prove @{prop"ev m \<Longrightarrow> evn m"}. That is, we |
540 text\<open>We prove \<^prop>\<open>ev m \<Longrightarrow> evn m\<close>. That is, we |
541 assume @{prop"ev m"} and by induction on the form of its derivation |
541 assume \<^prop>\<open>ev m\<close> and by induction on the form of its derivation |
542 prove @{prop"evn m"}. There are two cases corresponding to the two rules |
542 prove \<^prop>\<open>evn m\<close>. There are two cases corresponding to the two rules |
543 for @{const ev}: |
543 for \<^const>\<open>ev\<close>: |
544 \begin{description} |
544 \begin{description} |
545 \item[Case @{thm[source]ev0}:] |
545 \item[Case @{thm[source]ev0}:] |
546 @{prop"ev m"} was derived by rule @{prop "ev 0"}: \\ |
546 \<^prop>\<open>ev m\<close> was derived by rule \<^prop>\<open>ev 0\<close>: \\ |
547 \<open>\<Longrightarrow>\<close> @{prop"m=(0::nat)"} \<open>\<Longrightarrow>\<close> \<open>evn m = evn 0 = True\<close> |
547 \<open>\<Longrightarrow>\<close> \<^prop>\<open>m=(0::nat)\<close> \<open>\<Longrightarrow>\<close> \<open>evn m = evn 0 = True\<close> |
548 \item[Case @{thm[source]evSS}:] |
548 \item[Case @{thm[source]evSS}:] |
549 @{prop"ev m"} was derived by rule @{prop "ev n \<Longrightarrow> ev(n+2)"}: \\ |
549 \<^prop>\<open>ev m\<close> was derived by rule \<^prop>\<open>ev n \<Longrightarrow> ev(n+2)\<close>: \\ |
550 \<open>\<Longrightarrow>\<close> @{prop"m=n+(2::nat)"} and by induction hypothesis @{prop"evn n"}\\ |
550 \<open>\<Longrightarrow>\<close> \<^prop>\<open>m=n+(2::nat)\<close> and by induction hypothesis \<^prop>\<open>evn n\<close>\\ |
551 \<open>\<Longrightarrow>\<close> \<open>evn m = evn(n + 2) = evn n = True\<close> |
551 \<open>\<Longrightarrow>\<close> \<open>evn m = evn(n + 2) = evn n = True\<close> |
552 \end{description} |
552 \end{description} |
553 |
553 |
554 What we have just seen is a special case of \concept{rule induction}. |
554 What we have just seen is a special case of \concept{rule induction}. |
555 Rule induction applies to propositions of this form |
555 Rule induction applies to propositions of this form |
556 \begin{quote} |
556 \begin{quote} |
557 @{prop "ev n \<Longrightarrow> P n"} |
557 \<^prop>\<open>ev n \<Longrightarrow> P n\<close> |
558 \end{quote} |
558 \end{quote} |
559 That is, we want to prove a property @{prop"P n"} |
559 That is, we want to prove a property \<^prop>\<open>P n\<close> |
560 for all even \<open>n\<close>. But if we assume @{prop"ev n"}, then there must be |
560 for all even \<open>n\<close>. But if we assume \<^prop>\<open>ev n\<close>, then there must be |
561 some derivation of this assumption using the two defining rules for |
561 some derivation of this assumption using the two defining rules for |
562 @{const ev}. That is, we must prove |
562 \<^const>\<open>ev\<close>. That is, we must prove |
563 \begin{description} |
563 \begin{description} |
564 \item[Case @{thm[source]ev0}:] @{prop"P(0::nat)"} |
564 \item[Case @{thm[source]ev0}:] \<^prop>\<open>P(0::nat)\<close> |
565 \item[Case @{thm[source]evSS}:] @{prop"\<lbrakk> ev n; P n \<rbrakk> \<Longrightarrow> P(n + 2::nat)"} |
565 \item[Case @{thm[source]evSS}:] \<^prop>\<open>\<lbrakk> ev n; P n \<rbrakk> \<Longrightarrow> P(n + 2::nat)\<close> |
566 \end{description} |
566 \end{description} |
567 The corresponding rule is called @{thm[source] ev.induct} and looks like this: |
567 The corresponding rule is called @{thm[source] ev.induct} and looks like this: |
568 \[ |
568 \[ |
569 \inferrule{ |
569 \inferrule{ |
570 \mbox{@{thm (prem 1) ev.induct[of "n"]}}\\ |
570 \mbox{@{thm (prem 1) ev.induct[of "n"]}}\\ |
571 \mbox{@{thm (prem 2) ev.induct}}\\ |
571 \mbox{@{thm (prem 2) ev.induct}}\\ |
572 \mbox{@{prop"!!n. \<lbrakk> ev n; P n \<rbrakk> \<Longrightarrow> P(n+2)"}}} |
572 \mbox{\<^prop>\<open>!!n. \<lbrakk> ev n; P n \<rbrakk> \<Longrightarrow> P(n+2)\<close>}} |
573 {\mbox{@{thm (concl) ev.induct[of "n"]}}} |
573 {\mbox{@{thm (concl) ev.induct[of "n"]}}} |
574 \] |
574 \] |
575 The first premise @{prop"ev n"} enforces that this rule can only be applied |
575 The first premise \<^prop>\<open>ev n\<close> enforces that this rule can only be applied |
576 in situations where we know that \<open>n\<close> is even. |
576 in situations where we know that \<open>n\<close> is even. |
577 |
577 |
578 Note that in the induction step we may not just assume @{prop"P n"} but also |
578 Note that in the induction step we may not just assume \<^prop>\<open>P n\<close> but also |
579 \mbox{@{prop"ev n"}}, which is simply the premise of rule @{thm[source] |
579 \mbox{\<^prop>\<open>ev n\<close>}, which is simply the premise of rule @{thm[source] |
580 evSS}. Here is an example where the local assumption @{prop"ev n"} comes in |
580 evSS}. Here is an example where the local assumption \<^prop>\<open>ev n\<close> comes in |
581 handy: we prove @{prop"ev m \<Longrightarrow> ev(m - 2)"} by induction on @{prop"ev m"}. |
581 handy: we prove \<^prop>\<open>ev m \<Longrightarrow> ev(m - 2)\<close> by induction on \<^prop>\<open>ev m\<close>. |
582 Case @{thm[source]ev0} requires us to prove @{prop"ev(0 - 2)"}, which follows |
582 Case @{thm[source]ev0} requires us to prove \<^prop>\<open>ev(0 - 2)\<close>, which follows |
583 from @{prop"ev 0"} because @{prop"0 - 2 = (0::nat)"} on type @{typ nat}. In |
583 from \<^prop>\<open>ev 0\<close> because \<^prop>\<open>0 - 2 = (0::nat)\<close> on type \<^typ>\<open>nat\<close>. In |
584 case @{thm[source]evSS} we have \mbox{@{prop"m = n+(2::nat)"}} and may assume |
584 case @{thm[source]evSS} we have \mbox{\<^prop>\<open>m = n+(2::nat)\<close>} and may assume |
585 @{prop"ev n"}, which implies @{prop"ev (m - 2)"} because \<open>m - 2 = (n + |
585 \<^prop>\<open>ev n\<close>, which implies \<^prop>\<open>ev (m - 2)\<close> because \<open>m - 2 = (n + |
586 2) - 2 = n\<close>. We did not need the induction hypothesis at all for this proof (it |
586 2) - 2 = n\<close>. We did not need the induction hypothesis at all for this proof (it |
587 is just a case analysis of which rule was used) but having @{prop"ev n"} |
587 is just a case analysis of which rule was used) but having \<^prop>\<open>ev n\<close> |
588 at our disposal in case @{thm[source]evSS} was essential. |
588 at our disposal in case @{thm[source]evSS} was essential. |
589 This case analysis of rules is also called ``rule inversion'' |
589 This case analysis of rules is also called ``rule inversion'' |
590 and is discussed in more detail in \autoref{ch:Isar}. |
590 and is discussed in more detail in \autoref{ch:Isar}. |
591 |
591 |
592 \subsubsection{In Isabelle} |
592 \subsubsection{In Isabelle} |
593 |
593 |
594 Let us now recast the above informal proofs in Isabelle. For a start, |
594 Let us now recast the above informal proofs in Isabelle. For a start, |
595 we use @{const Suc} terms instead of numerals in rule @{thm[source]evSS}: |
595 we use \<^const>\<open>Suc\<close> terms instead of numerals in rule @{thm[source]evSS}: |
596 @{thm[display] evSS} |
596 @{thm[display] evSS} |
597 This avoids the difficulty of unifying \<open>n+2\<close> with some numeral, |
597 This avoids the difficulty of unifying \<open>n+2\<close> with some numeral, |
598 which is not automatic. |
598 which is not automatic. |
599 |
599 |
600 The simplest way to prove @{prop"ev(Suc(Suc(Suc(Suc 0))))"} is in a forward |
600 The simplest way to prove \<^prop>\<open>ev(Suc(Suc(Suc(Suc 0))))\<close> is in a forward |
601 direction: \<open>evSS[OF evSS[OF ev0]]\<close> yields the theorem @{thm evSS[OF |
601 direction: \<open>evSS[OF evSS[OF ev0]]\<close> yields the theorem @{thm evSS[OF |
602 evSS[OF ev0]]}. Alternatively, you can also prove it as a lemma in backwards |
602 evSS[OF ev0]]}. Alternatively, you can also prove it as a lemma in backwards |
603 fashion. Although this is more verbose, it allows us to demonstrate how each |
603 fashion. Although this is more verbose, it allows us to demonstrate how each |
604 rule application changes the proof state:\<close> |
604 rule application changes the proof state:\<close> |
605 |
605 |
625 lemma "ev m \<Longrightarrow> evn m" |
625 lemma "ev m \<Longrightarrow> evn m" |
626 apply(induction rule: ev.induct) |
626 apply(induction rule: ev.induct) |
627 by(simp_all) |
627 by(simp_all) |
628 |
628 |
629 text\<open>Both cases are automatic. Note that if there are multiple assumptions |
629 text\<open>Both cases are automatic. Note that if there are multiple assumptions |
630 of the form @{prop"ev t"}, method \<open>induction\<close> will induct on the leftmost |
630 of the form \<^prop>\<open>ev t\<close>, method \<open>induction\<close> will induct on the leftmost |
631 one. |
631 one. |
632 |
632 |
633 As a bonus, we also prove the remaining direction of the equivalence of |
633 As a bonus, we also prove the remaining direction of the equivalence of |
634 @{const ev} and @{const evn}: |
634 \<^const>\<open>ev\<close> and \<^const>\<open>evn\<close>: |
635 \<close> |
635 \<close> |
636 |
636 |
637 lemma "evn n \<Longrightarrow> ev n" |
637 lemma "evn n \<Longrightarrow> ev n" |
638 apply(induction n rule: evn.induct) |
638 apply(induction n rule: evn.induct) |
639 |
639 |
640 txt\<open>This is a proof by computation induction on \<open>n\<close> (see |
640 txt\<open>This is a proof by computation induction on \<open>n\<close> (see |
641 \autoref{sec:recursive-funs}) that sets up three subgoals corresponding to |
641 \autoref{sec:recursive-funs}) that sets up three subgoals corresponding to |
642 the three equations for @{const evn}: |
642 the three equations for \<^const>\<open>evn\<close>: |
643 @{subgoals[display,indent=0]} |
643 @{subgoals[display,indent=0]} |
644 The first and third subgoals follow with @{thm[source]ev0} and @{thm[source]evSS}, and the second subgoal is trivially true because @{prop"evn(Suc 0)"} is @{const False}: |
644 The first and third subgoals follow with @{thm[source]ev0} and @{thm[source]evSS}, and the second subgoal is trivially true because \<^prop>\<open>evn(Suc 0)\<close> is \<^const>\<open>False\<close>: |
645 \<close> |
645 \<close> |
646 |
646 |
647 by (simp_all add: ev0 evSS) |
647 by (simp_all add: ev0 evSS) |
648 |
648 |
649 text\<open>The rules for @{const ev} make perfect simplification and introduction |
649 text\<open>The rules for \<^const>\<open>ev\<close> make perfect simplification and introduction |
650 rules because their premises are always smaller than the conclusion. It |
650 rules because their premises are always smaller than the conclusion. It |
651 makes sense to turn them into simplification and introduction rules |
651 makes sense to turn them into simplification and introduction rules |
652 permanently, to enhance proof automation. They are named @{thm[source] ev.intros} |
652 permanently, to enhance proof automation. They are named @{thm[source] ev.intros} |
653 \index{intros@\<open>.intros\<close>} by Isabelle:\<close> |
653 \index{intros@\<open>.intros\<close>} by Isabelle:\<close> |
654 |
654 |
666 expresses both the positive information (which numbers are even) and the |
666 expresses both the positive information (which numbers are even) and the |
667 negative information (which numbers are not even) directly. An inductive |
667 negative information (which numbers are not even) directly. An inductive |
668 definition only expresses the positive information directly. The negative |
668 definition only expresses the positive information directly. The negative |
669 information, for example, that \<open>1\<close> is not even, has to be proved from |
669 information, for example, that \<open>1\<close> is not even, has to be proved from |
670 it (by induction or rule inversion). On the other hand, rule induction is |
670 it (by induction or rule inversion). On the other hand, rule induction is |
671 tailor-made for proving \mbox{@{prop"ev n \<Longrightarrow> P n"}} because it only asks you |
671 tailor-made for proving \mbox{\<^prop>\<open>ev n \<Longrightarrow> P n\<close>} because it only asks you |
672 to prove the positive cases. In the proof of @{prop"evn n \<Longrightarrow> P n"} by |
672 to prove the positive cases. In the proof of \<^prop>\<open>evn n \<Longrightarrow> P n\<close> by |
673 computation induction via @{thm[source]evn.induct}, we are also presented |
673 computation induction via @{thm[source]evn.induct}, we are also presented |
674 with the trivial negative cases. If you want the convenience of both |
674 with the trivial negative cases. If you want the convenience of both |
675 rewriting and rule induction, you can make two definitions and show their |
675 rewriting and rule induction, you can make two definitions and show their |
676 equivalence (as above) or make one definition and prove additional properties |
676 equivalence (as above) or make one definition and prove additional properties |
677 from it, for example rule induction from computation induction. |
677 from it, for example rule induction from computation induction. |
694 some of the semantics considered in the second part of the book. |
694 some of the semantics considered in the second part of the book. |
695 \fi |
695 \fi |
696 |
696 |
697 The reflexive transitive closure, called \<open>star\<close> below, is a function |
697 The reflexive transitive closure, called \<open>star\<close> below, is a function |
698 that maps a binary predicate to another binary predicate: if \<open>r\<close> is of |
698 that maps a binary predicate to another binary predicate: if \<open>r\<close> is of |
699 type \<open>\<tau> \<Rightarrow> \<tau> \<Rightarrow> bool\<close> then @{term "star r"} is again of type \<open>\<tau> \<Rightarrow> |
699 type \<open>\<tau> \<Rightarrow> \<tau> \<Rightarrow> bool\<close> then \<^term>\<open>star r\<close> is again of type \<open>\<tau> \<Rightarrow> |
700 \<tau> \<Rightarrow> bool\<close>, and @{prop"star r x y"} means that \<open>x\<close> and \<open>y\<close> are in |
700 \<tau> \<Rightarrow> bool\<close>, and \<^prop>\<open>star r x y\<close> means that \<open>x\<close> and \<open>y\<close> are in |
701 the relation @{term"star r"}. Think @{term"r\<^sup>*"} when you see @{term"star |
701 the relation \<^term>\<open>star r\<close>. Think \<^term>\<open>r\<^sup>*\<close> when you see \<^term>\<open>star |
702 r"}, because \<open>star r\<close> is meant to be the reflexive transitive closure. |
702 r\<close>, because \<open>star r\<close> is meant to be the reflexive transitive closure. |
703 That is, @{prop"star r x y"} is meant to be true if from \<open>x\<close> we can |
703 That is, \<^prop>\<open>star r x y\<close> is meant to be true if from \<open>x\<close> we can |
704 reach \<open>y\<close> in finitely many \<open>r\<close> steps. This concept is naturally |
704 reach \<open>y\<close> in finitely many \<open>r\<close> steps. This concept is naturally |
705 defined inductively:\<close> |
705 defined inductively:\<close> |
706 |
706 |
707 inductive star :: "('a \<Rightarrow> 'a \<Rightarrow> bool) \<Rightarrow> 'a \<Rightarrow> 'a \<Rightarrow> bool" for r where |
707 inductive star :: "('a \<Rightarrow> 'a \<Rightarrow> bool) \<Rightarrow> 'a \<Rightarrow> 'a \<Rightarrow> bool" for r where |
708 refl: "star r x x" | |
708 refl: "star r x x" | |
709 step: "r x y \<Longrightarrow> star r y z \<Longrightarrow> star r x z" |
709 step: "r x y \<Longrightarrow> star r y z \<Longrightarrow> star r x z" |
710 |
710 |
711 text\<open>The base case @{thm[source] refl} is reflexivity: @{term "x=y"}. The |
711 text\<open>The base case @{thm[source] refl} is reflexivity: \<^term>\<open>x=y\<close>. The |
712 step case @{thm[source]step} combines an \<open>r\<close> step (from \<open>x\<close> to |
712 step case @{thm[source]step} combines an \<open>r\<close> step (from \<open>x\<close> to |
713 \<open>y\<close>) and a @{term"star r"} step (from \<open>y\<close> to \<open>z\<close>) into a |
713 \<open>y\<close>) and a \<^term>\<open>star r\<close> step (from \<open>y\<close> to \<open>z\<close>) into a |
714 @{term"star r"} step (from \<open>x\<close> to \<open>z\<close>). |
714 \<^term>\<open>star r\<close> step (from \<open>x\<close> to \<open>z\<close>). |
715 The ``\isacom{for}~\<open>r\<close>'' in the header is merely a hint to Isabelle |
715 The ``\isacom{for}~\<open>r\<close>'' in the header is merely a hint to Isabelle |
716 that \<open>r\<close> is a fixed parameter of @{const star}, in contrast to the |
716 that \<open>r\<close> is a fixed parameter of \<^const>\<open>star\<close>, in contrast to the |
717 further parameters of @{const star}, which change. As a result, Isabelle |
717 further parameters of \<^const>\<open>star\<close>, which change. As a result, Isabelle |
718 generates a simpler induction rule. |
718 generates a simpler induction rule. |
719 |
719 |
720 By definition @{term"star r"} is reflexive. It is also transitive, but we |
720 By definition \<^term>\<open>star r\<close> is reflexive. It is also transitive, but we |
721 need rule induction to prove that:\<close> |
721 need rule induction to prove that:\<close> |
722 |
722 |
723 lemma star_trans: "star r x y \<Longrightarrow> star r y z \<Longrightarrow> star r x z" |
723 lemma star_trans: "star r x y \<Longrightarrow> star r y z \<Longrightarrow> star r x z" |
724 apply(induction rule: star.induct) |
724 apply(induction rule: star.induct) |
725 (*<*) |
725 (*<*) |
726 defer |
726 defer |
727 apply(rename_tac u x y) |
727 apply(rename_tac u x y) |
728 defer |
728 defer |
729 (*>*) |
729 (*>*) |
730 txt\<open>The induction is over @{prop"star r x y"} (the first matching assumption) |
730 txt\<open>The induction is over \<^prop>\<open>star r x y\<close> (the first matching assumption) |
731 and we try to prove \mbox{@{prop"star r y z \<Longrightarrow> star r x z"}}, |
731 and we try to prove \mbox{\<^prop>\<open>star r y z \<Longrightarrow> star r x z\<close>}, |
732 which we abbreviate by @{prop"P x y"}. These are our two subgoals: |
732 which we abbreviate by \<^prop>\<open>P x y\<close>. These are our two subgoals: |
733 @{subgoals[display,indent=0]} |
733 @{subgoals[display,indent=0]} |
734 The first one is @{prop"P x x"}, the result of case @{thm[source]refl}, |
734 The first one is \<^prop>\<open>P x x\<close>, the result of case @{thm[source]refl}, |
735 and it is trivial:\index{assumption@\<open>assumption\<close>} |
735 and it is trivial:\index{assumption@\<open>assumption\<close>} |
736 \<close> |
736 \<close> |
737 apply(assumption) |
737 apply(assumption) |
738 txt\<open>Let us examine subgoal \<open>2\<close>, case @{thm[source] step}. |
738 txt\<open>Let us examine subgoal \<open>2\<close>, case @{thm[source] step}. |
739 Assumptions @{prop"r u x"} and \mbox{@{prop"star r x y"}} |
739 Assumptions \<^prop>\<open>r u x\<close> and \mbox{\<^prop>\<open>star r x y\<close>} |
740 are the premises of rule @{thm[source]step}. |
740 are the premises of rule @{thm[source]step}. |
741 Assumption @{prop"star r y z \<Longrightarrow> star r x z"} is \mbox{@{prop"P x y"}}, |
741 Assumption \<^prop>\<open>star r y z \<Longrightarrow> star r x z\<close> is \mbox{\<^prop>\<open>P x y\<close>}, |
742 the IH coming from @{prop"star r x y"}. We have to prove @{prop"P u y"}, |
742 the IH coming from \<^prop>\<open>star r x y\<close>. We have to prove \<^prop>\<open>P u y\<close>, |
743 which we do by assuming @{prop"star r y z"} and proving @{prop"star r u z"}. |
743 which we do by assuming \<^prop>\<open>star r y z\<close> and proving \<^prop>\<open>star r u z\<close>. |
744 The proof itself is straightforward: from \mbox{@{prop"star r y z"}} the IH |
744 The proof itself is straightforward: from \mbox{\<^prop>\<open>star r y z\<close>} the IH |
745 leads to @{prop"star r x z"} which, together with @{prop"r u x"}, |
745 leads to \<^prop>\<open>star r x z\<close> which, together with \<^prop>\<open>r u x\<close>, |
746 leads to \mbox{@{prop"star r u z"}} via rule @{thm[source]step}: |
746 leads to \mbox{\<^prop>\<open>star r u z\<close>} via rule @{thm[source]step}: |
747 \<close> |
747 \<close> |
748 apply(metis step) |
748 apply(metis step) |
749 done |
749 done |
750 |
750 |
751 text\<open>\index{rule induction|)} |
751 text\<open>\index{rule induction|)} |
789 |
789 |
790 \begin{exercise} |
790 \begin{exercise} |
791 Formalize the following definition of palindromes |
791 Formalize the following definition of palindromes |
792 \begin{itemize} |
792 \begin{itemize} |
793 \item The empty list and a singleton list are palindromes. |
793 \item The empty list and a singleton list are palindromes. |
794 \item If \<open>xs\<close> is a palindrome, so is @{term "a # xs @ [a]"}. |
794 \item If \<open>xs\<close> is a palindrome, so is \<^term>\<open>a # xs @ [a]\<close>. |
795 \end{itemize} |
795 \end{itemize} |
796 as an inductive predicate \<open>palindrome ::\<close> @{typ "'a list \<Rightarrow> bool"} |
796 as an inductive predicate \<open>palindrome ::\<close> \<^typ>\<open>'a list \<Rightarrow> bool\<close> |
797 and prove that @{prop "rev xs = xs"} if \<open>xs\<close> is a palindrome. |
797 and prove that \<^prop>\<open>rev xs = xs\<close> if \<open>xs\<close> is a palindrome. |
798 \end{exercise} |
798 \end{exercise} |
799 |
799 |
800 \exercise |
800 \exercise |
801 We could also have defined @{const star} as follows: |
801 We could also have defined \<^const>\<open>star\<close> as follows: |
802 \<close> |
802 \<close> |
803 |
803 |
804 inductive star' :: "('a \<Rightarrow> 'a \<Rightarrow> bool) \<Rightarrow> 'a \<Rightarrow> 'a \<Rightarrow> bool" for r where |
804 inductive star' :: "('a \<Rightarrow> 'a \<Rightarrow> bool) \<Rightarrow> 'a \<Rightarrow> 'a \<Rightarrow> bool" for r where |
805 refl': "star' r x x" | |
805 refl': "star' r x x" | |
806 step': "star' r x y \<Longrightarrow> r y z \<Longrightarrow> star' r x z" |
806 step': "star' r x y \<Longrightarrow> r y z \<Longrightarrow> star' r x z" |
807 |
807 |
808 text\<open> |
808 text\<open> |
809 The single \<open>r\<close> step is performed after rather than before the \<open>star'\<close> |
809 The single \<open>r\<close> step is performed after rather than before the \<open>star'\<close> |
810 steps. Prove @{prop "star' r x y \<Longrightarrow> star r x y"} and |
810 steps. Prove \<^prop>\<open>star' r x y \<Longrightarrow> star r x y\<close> and |
811 @{prop "star r x y \<Longrightarrow> star' r x y"}. You may need lemmas. |
811 \<^prop>\<open>star r x y \<Longrightarrow> star' r x y\<close>. You may need lemmas. |
812 Note that rule induction fails |
812 Note that rule induction fails |
813 if the assumption about the inductive predicate is not the first assumption. |
813 if the assumption about the inductive predicate is not the first assumption. |
814 \endexercise |
814 \endexercise |
815 |
815 |
816 \begin{exercise}\label{exe:iter} |
816 \begin{exercise}\label{exe:iter} |
817 Analogous to @{const star}, give an inductive definition of the \<open>n\<close>-fold iteration |
817 Analogous to \<^const>\<open>star\<close>, give an inductive definition of the \<open>n\<close>-fold iteration |
818 of a relation \<open>r\<close>: @{term "iter r n x y"} should hold if there are \<open>x\<^sub>0\<close>, \dots, \<open>x\<^sub>n\<close> |
818 of a relation \<open>r\<close>: \<^term>\<open>iter r n x y\<close> should hold if there are \<open>x\<^sub>0\<close>, \dots, \<open>x\<^sub>n\<close> |
819 such that @{prop"x = x\<^sub>0"}, @{prop"x\<^sub>n = y"} and \<open>r x\<^bsub>i\<^esub> x\<^bsub>i+1\<^esub>\<close> for |
819 such that \<^prop>\<open>x = x\<^sub>0\<close>, \<^prop>\<open>x\<^sub>n = y\<close> and \<open>r x\<^bsub>i\<^esub> x\<^bsub>i+1\<^esub>\<close> for |
820 all @{prop"i < n"}. Correct and prove the following claim: |
820 all \<^prop>\<open>i < n\<close>. Correct and prove the following claim: |
821 @{prop"star r x y \<Longrightarrow> iter r n x y"}. |
821 \<^prop>\<open>star r x y \<Longrightarrow> iter r n x y\<close>. |
822 \end{exercise} |
822 \end{exercise} |
823 |
823 |
824 \begin{exercise}\label{exe:cfg} |
824 \begin{exercise}\label{exe:cfg} |
825 A context-free grammar can be seen as an inductive definition where each |
825 A context-free grammar can be seen as an inductive definition where each |
826 nonterminal $A$ is an inductively defined predicate on lists of terminal |
826 nonterminal $A$ is an inductively defined predicate on lists of terminal |
827 symbols: $A(w)$ means that $w$ is in the language generated by $A$. |
827 symbols: $A(w)$ means that $w$ is in the language generated by $A$. |
828 For example, the production $S \to a S b$ can be viewed as the implication |
828 For example, the production $S \to a S b$ can be viewed as the implication |
829 @{prop"S w \<Longrightarrow> S (a # w @ [b])"} where \<open>a\<close> and \<open>b\<close> are terminal symbols, |
829 \<^prop>\<open>S w \<Longrightarrow> S (a # w @ [b])\<close> where \<open>a\<close> and \<open>b\<close> are terminal symbols, |
830 i.e., elements of some alphabet. The alphabet can be defined like this: |
830 i.e., elements of some alphabet. The alphabet can be defined like this: |
831 \isacom{datatype} \<open>alpha = a | b | \<dots>\<close> |
831 \isacom{datatype} \<open>alpha = a | b | \<dots>\<close> |
832 |
832 |
833 Define the two grammars (where $\varepsilon$ is the empty word) |
833 Define the two grammars (where $\varepsilon$ is the empty word) |
834 \[ |
834 \[ |
838 \end{array} |
838 \end{array} |
839 \] |
839 \] |
840 as two inductive predicates. |
840 as two inductive predicates. |
841 If you think of \<open>a\<close> and \<open>b\<close> as ``\<open>(\<close>'' and ``\<open>)\<close>'', |
841 If you think of \<open>a\<close> and \<open>b\<close> as ``\<open>(\<close>'' and ``\<open>)\<close>'', |
842 the grammar defines strings of balanced parentheses. |
842 the grammar defines strings of balanced parentheses. |
843 Prove @{prop"T w \<Longrightarrow> S w"} and \mbox{@{prop "S w \<Longrightarrow> T w"}} separately and conclude |
843 Prove \<^prop>\<open>T w \<Longrightarrow> S w\<close> and \mbox{\<^prop>\<open>S w \<Longrightarrow> T w\<close>} separately and conclude |
844 @{prop "S w = T w"}. |
844 \<^prop>\<open>S w = T w\<close>. |
845 \end{exercise} |
845 \end{exercise} |
846 |
846 |
847 \ifsem |
847 \ifsem |
848 \begin{exercise} |
848 \begin{exercise} |
849 In \autoref{sec:AExp} we defined a recursive evaluation function |
849 In \autoref{sec:AExp} we defined a recursive evaluation function |
850 \<open>aval :: aexp \<Rightarrow> state \<Rightarrow> val\<close>. |
850 \<open>aval :: aexp \<Rightarrow> state \<Rightarrow> val\<close>. |
851 Define an inductive evaluation predicate |
851 Define an inductive evaluation predicate |
852 \<open>aval_rel :: aexp \<Rightarrow> state \<Rightarrow> val \<Rightarrow> bool\<close> |
852 \<open>aval_rel :: aexp \<Rightarrow> state \<Rightarrow> val \<Rightarrow> bool\<close> |
853 and prove that it agrees with the recursive function: |
853 and prove that it agrees with the recursive function: |
854 @{prop "aval_rel a s v \<Longrightarrow> aval a s = v"}, |
854 \<^prop>\<open>aval_rel a s v \<Longrightarrow> aval a s = v\<close>, |
855 @{prop "aval a s = v \<Longrightarrow> aval_rel a s v"} and thus |
855 \<^prop>\<open>aval a s = v \<Longrightarrow> aval_rel a s v\<close> and thus |
856 \noquotes{@{prop [source] "aval_rel a s v \<longleftrightarrow> aval a s = v"}}. |
856 \noquotes{@{prop [source] "aval_rel a s v \<longleftrightarrow> aval a s = v"}}. |
857 \end{exercise} |
857 \end{exercise} |
858 |
858 |
859 \begin{exercise} |
859 \begin{exercise} |
860 Consider the stack machine from Chapter~3 |
860 Consider the stack machine from Chapter~3 |