1 % |
1 % |
2 \begin{isabellebody}% |
2 \begin{isabellebody}% |
3 \def\isabellecontext{simplification}% |
3 \def\isabellecontext{simplification}% |
4 % |
4 % |
5 \begin{isamarkuptext}% |
5 \begin{isamarkuptext}% |
6 Once we have succeeded in proving all termination conditions, the recursion |
6 Once we have proved all the termination conditions, the \isacommand{recdef} |
7 equations become simplification rules, just as with |
7 recursion equations become simplification rules, just as with |
8 \isacommand{primrec}. In most cases this works fine, but there is a subtle |
8 \isacommand{primrec}. In most cases this works fine, but there is a subtle |
9 problem that must be mentioned: simplification may not |
9 problem that must be mentioned: simplification may not |
10 terminate because of automatic splitting of \isa{if}. |
10 terminate because of automatic splitting of \isa{if}. |
|
11 \index{*if expressions!splitting of} |
11 Let us look at an example:% |
12 Let us look at an example:% |
12 \end{isamarkuptext}% |
13 \end{isamarkuptext}% |
13 \isacommand{consts}\ gcd\ {\isacharcolon}{\isacharcolon}\ {\isachardoublequote}nat{\isasymtimes}nat\ {\isasymRightarrow}\ nat{\isachardoublequote}\isanewline |
14 \isacommand{consts}\ gcd\ {\isacharcolon}{\isacharcolon}\ {\isachardoublequote}nat{\isasymtimes}nat\ {\isasymRightarrow}\ nat{\isachardoublequote}\isanewline |
14 \isacommand{recdef}\ gcd\ {\isachardoublequote}measure\ {\isacharparenleft}{\isasymlambda}{\isacharparenleft}m{\isacharcomma}n{\isacharparenright}{\isachardot}n{\isacharparenright}{\isachardoublequote}\isanewline |
15 \isacommand{recdef}\ gcd\ {\isachardoublequote}measure\ {\isacharparenleft}{\isasymlambda}{\isacharparenleft}m{\isacharcomma}n{\isacharparenright}{\isachardot}n{\isacharparenright}{\isachardoublequote}\isanewline |
15 \ \ {\isachardoublequote}gcd\ {\isacharparenleft}m{\isacharcomma}\ n{\isacharparenright}\ {\isacharequal}\ {\isacharparenleft}if\ n{\isacharequal}{\isadigit{0}}\ then\ m\ else\ gcd{\isacharparenleft}n{\isacharcomma}\ m\ mod\ n{\isacharparenright}{\isacharparenright}{\isachardoublequote}% |
16 \ \ {\isachardoublequote}gcd\ {\isacharparenleft}m{\isacharcomma}\ n{\isacharparenright}\ {\isacharequal}\ {\isacharparenleft}if\ n{\isacharequal}{\isadigit{0}}\ then\ m\ else\ gcd{\isacharparenleft}n{\isacharcomma}\ m\ mod\ n{\isacharparenright}{\isacharparenright}{\isachardoublequote}% |
23 is proved automatically because it is already present as a lemma in |
24 is proved automatically because it is already present as a lemma in |
24 HOL\@. Thus the recursion equation becomes a simplification |
25 HOL\@. Thus the recursion equation becomes a simplification |
25 rule. Of course the equation is nonterminating if we are allowed to unfold |
26 rule. Of course the equation is nonterminating if we are allowed to unfold |
26 the recursive call inside the \isa{else} branch, which is why programming |
27 the recursive call inside the \isa{else} branch, which is why programming |
27 languages and our simplifier don't do that. Unfortunately the simplifier does |
28 languages and our simplifier don't do that. Unfortunately the simplifier does |
28 something else which leads to the same problem: it splits \isa{if}s if the |
29 something else that leads to the same problem: it splits |
29 condition simplifies to neither \isa{True} nor \isa{False}. For |
30 each \isa{if}-expression unless its |
|
31 condition simplifies to \isa{True} or \isa{False}. For |
30 example, simplification reduces |
32 example, simplification reduces |
31 \begin{isabelle}% |
33 \begin{isabelle}% |
32 \ \ \ \ \ gcd\ {\isacharparenleft}m{\isacharcomma}\ n{\isacharparenright}\ {\isacharequal}\ k% |
34 \ \ \ \ \ gcd\ {\isacharparenleft}m{\isacharcomma}\ n{\isacharparenright}\ {\isacharequal}\ k% |
33 \end{isabelle} |
35 \end{isabelle} |
34 in one step to |
36 in one step to |
42 Since the recursive call \isa{gcd\ {\isacharparenleft}n{\isacharcomma}\ m\ mod\ n{\isacharparenright}} is no longer protected by |
44 Since the recursive call \isa{gcd\ {\isacharparenleft}n{\isacharcomma}\ m\ mod\ n{\isacharparenright}} is no longer protected by |
43 an \isa{if}, it is unfolded again, which leads to an infinite chain of |
45 an \isa{if}, it is unfolded again, which leads to an infinite chain of |
44 simplification steps. Fortunately, this problem can be avoided in many |
46 simplification steps. Fortunately, this problem can be avoided in many |
45 different ways. |
47 different ways. |
46 |
48 |
47 The most radical solution is to disable the offending \isa{split{\isacharunderscore}if} |
49 The most radical solution is to disable the offending theorem |
|
50 \isa{split{\isacharunderscore}if}, |
48 as shown in \S\ref{sec:AutoCaseSplits}. However, we do not recommend this |
51 as shown in \S\ref{sec:AutoCaseSplits}. However, we do not recommend this |
49 because it means you will often have to invoke the rule explicitly when |
52 approach: you will often have to invoke the rule explicitly when |
50 \isa{if} is involved. |
53 \isa{if} is involved. |
51 |
54 |
52 If possible, the definition should be given by pattern matching on the left |
55 If possible, the definition should be given by pattern matching on the left |
53 rather than \isa{if} on the right. In the case of \isa{gcd} the |
56 rather than \isa{if} on the right. In the case of \isa{gcd} the |
54 following alternative definition suggests itself:% |
57 following alternative definition suggests itself:% |
57 \isacommand{recdef}\ gcd{\isadigit{1}}\ {\isachardoublequote}measure\ {\isacharparenleft}{\isasymlambda}{\isacharparenleft}m{\isacharcomma}n{\isacharparenright}{\isachardot}n{\isacharparenright}{\isachardoublequote}\isanewline |
60 \isacommand{recdef}\ gcd{\isadigit{1}}\ {\isachardoublequote}measure\ {\isacharparenleft}{\isasymlambda}{\isacharparenleft}m{\isacharcomma}n{\isacharparenright}{\isachardot}n{\isacharparenright}{\isachardoublequote}\isanewline |
58 \ \ {\isachardoublequote}gcd{\isadigit{1}}\ {\isacharparenleft}m{\isacharcomma}\ {\isadigit{0}}{\isacharparenright}\ {\isacharequal}\ m{\isachardoublequote}\isanewline |
61 \ \ {\isachardoublequote}gcd{\isadigit{1}}\ {\isacharparenleft}m{\isacharcomma}\ {\isadigit{0}}{\isacharparenright}\ {\isacharequal}\ m{\isachardoublequote}\isanewline |
59 \ \ {\isachardoublequote}gcd{\isadigit{1}}\ {\isacharparenleft}m{\isacharcomma}\ n{\isacharparenright}\ {\isacharequal}\ gcd{\isadigit{1}}{\isacharparenleft}n{\isacharcomma}\ m\ mod\ n{\isacharparenright}{\isachardoublequote}% |
62 \ \ {\isachardoublequote}gcd{\isadigit{1}}\ {\isacharparenleft}m{\isacharcomma}\ n{\isacharparenright}\ {\isacharequal}\ gcd{\isadigit{1}}{\isacharparenleft}n{\isacharcomma}\ m\ mod\ n{\isacharparenright}{\isachardoublequote}% |
60 \begin{isamarkuptext}% |
63 \begin{isamarkuptext}% |
61 \noindent |
64 \noindent |
62 Note that the order of equations is important and hides the side condition |
65 The order of equations is important: it hides the side condition |
63 \isa{n\ {\isasymnoteq}\ {\isadigit{0}}}. Unfortunately, in general the case distinction |
66 \isa{n\ {\isasymnoteq}\ {\isadigit{0}}}. Unfortunately, in general the case distinction |
64 may not be expressible by pattern matching. |
67 may not be expressible by pattern matching. |
65 |
68 |
66 A very simple alternative is to replace \isa{if} by \isa{case}, which |
69 A simple alternative is to replace \isa{if} by \isa{case}, |
67 is also available for \isa{bool} but is not split automatically:% |
70 which is also available for \isa{bool} and is not split automatically:% |
68 \end{isamarkuptext}% |
71 \end{isamarkuptext}% |
69 \isacommand{consts}\ gcd{\isadigit{2}}\ {\isacharcolon}{\isacharcolon}\ {\isachardoublequote}nat{\isasymtimes}nat\ {\isasymRightarrow}\ nat{\isachardoublequote}\isanewline |
72 \isacommand{consts}\ gcd{\isadigit{2}}\ {\isacharcolon}{\isacharcolon}\ {\isachardoublequote}nat{\isasymtimes}nat\ {\isasymRightarrow}\ nat{\isachardoublequote}\isanewline |
70 \isacommand{recdef}\ gcd{\isadigit{2}}\ {\isachardoublequote}measure\ {\isacharparenleft}{\isasymlambda}{\isacharparenleft}m{\isacharcomma}n{\isacharparenright}{\isachardot}n{\isacharparenright}{\isachardoublequote}\isanewline |
73 \isacommand{recdef}\ gcd{\isadigit{2}}\ {\isachardoublequote}measure\ {\isacharparenleft}{\isasymlambda}{\isacharparenleft}m{\isacharcomma}n{\isacharparenright}{\isachardot}n{\isacharparenright}{\isachardoublequote}\isanewline |
71 \ \ {\isachardoublequote}gcd{\isadigit{2}}{\isacharparenleft}m{\isacharcomma}n{\isacharparenright}\ {\isacharequal}\ {\isacharparenleft}case\ n{\isacharequal}{\isadigit{0}}\ of\ True\ {\isasymRightarrow}\ m\ {\isacharbar}\ False\ {\isasymRightarrow}\ gcd{\isadigit{2}}{\isacharparenleft}n{\isacharcomma}m\ mod\ n{\isacharparenright}{\isacharparenright}{\isachardoublequote}% |
74 \ \ {\isachardoublequote}gcd{\isadigit{2}}{\isacharparenleft}m{\isacharcomma}n{\isacharparenright}\ {\isacharequal}\ {\isacharparenleft}case\ n{\isacharequal}{\isadigit{0}}\ of\ True\ {\isasymRightarrow}\ m\ {\isacharbar}\ False\ {\isasymRightarrow}\ gcd{\isadigit{2}}{\isacharparenleft}n{\isacharcomma}m\ mod\ n{\isacharparenright}{\isacharparenright}{\isachardoublequote}% |
72 \begin{isamarkuptext}% |
75 \begin{isamarkuptext}% |
73 \noindent |
76 \noindent |
74 In fact, this is probably the neatest solution next to pattern matching. |
77 This is probably the neatest solution next to pattern matching, and it is |
|
78 always available. |
75 |
79 |
76 A final alternative is to replace the offending simplification rules by |
80 A final alternative is to replace the offending simplification rules by |
77 derived conditional ones. For \isa{gcd} it means we have to prove |
81 derived conditional ones. For \isa{gcd} it means we have to prove |
78 these lemmas:% |
82 these lemmas:% |
79 \end{isamarkuptext}% |
83 \end{isamarkuptext}% |
80 \isacommand{lemma}\ {\isacharbrackleft}simp{\isacharbrackright}{\isacharcolon}\ {\isachardoublequote}gcd\ {\isacharparenleft}m{\isacharcomma}\ {\isadigit{0}}{\isacharparenright}\ {\isacharequal}\ m{\isachardoublequote}\isanewline |
84 \isacommand{lemma}\ {\isacharbrackleft}simp{\isacharbrackright}{\isacharcolon}\ {\isachardoublequote}gcd\ {\isacharparenleft}m{\isacharcomma}\ {\isadigit{0}}{\isacharparenright}\ {\isacharequal}\ m{\isachardoublequote}\isanewline |
81 \isacommand{apply}{\isacharparenleft}simp{\isacharparenright}\isanewline |
85 \isacommand{apply}{\isacharparenleft}simp{\isacharparenright}\isanewline |
82 \isacommand{done}\isanewline |
86 \isacommand{done}\isanewline |
|
87 \isanewline |
83 \isacommand{lemma}\ {\isacharbrackleft}simp{\isacharbrackright}{\isacharcolon}\ {\isachardoublequote}n\ {\isasymnoteq}\ {\isadigit{0}}\ {\isasymLongrightarrow}\ gcd{\isacharparenleft}m{\isacharcomma}\ n{\isacharparenright}\ {\isacharequal}\ gcd{\isacharparenleft}n{\isacharcomma}\ m\ mod\ n{\isacharparenright}{\isachardoublequote}\isanewline |
88 \isacommand{lemma}\ {\isacharbrackleft}simp{\isacharbrackright}{\isacharcolon}\ {\isachardoublequote}n\ {\isasymnoteq}\ {\isadigit{0}}\ {\isasymLongrightarrow}\ gcd{\isacharparenleft}m{\isacharcomma}\ n{\isacharparenright}\ {\isacharequal}\ gcd{\isacharparenleft}n{\isacharcomma}\ m\ mod\ n{\isacharparenright}{\isachardoublequote}\isanewline |
84 \isacommand{apply}{\isacharparenleft}simp{\isacharparenright}\isanewline |
89 \isacommand{apply}{\isacharparenleft}simp{\isacharparenright}\isanewline |
85 \isacommand{done}% |
90 \isacommand{done}% |
86 \begin{isamarkuptext}% |
91 \begin{isamarkuptext}% |
87 \noindent |
92 \noindent |
|
93 Simplification terminates for these proofs because the condition of the \isa{if} simplifies to \isa{True} or \isa{False}. |
88 Now we can disable the original simplification rule:% |
94 Now we can disable the original simplification rule:% |
89 \end{isamarkuptext}% |
95 \end{isamarkuptext}% |
90 \isacommand{declare}\ gcd{\isachardot}simps\ {\isacharbrackleft}simp\ del{\isacharbrackright}\isanewline |
96 \isacommand{declare}\ gcd{\isachardot}simps\ {\isacharbrackleft}simp\ del{\isacharbrackright}\isanewline |
91 \end{isabellebody}% |
97 \end{isabellebody}% |
92 %%% Local Variables: |
98 %%% Local Variables: |