6 \isacommand{primrec}. In most cases this works fine, but there is a subtle |
6 \isacommand{primrec}. In most cases this works fine, but there is a subtle |
7 problem that must be mentioned: simplification may not |
7 problem that must be mentioned: simplification may not |
8 terminate because of automatic splitting of \isa{if}. |
8 terminate because of automatic splitting of \isa{if}. |
9 Let us look at an example:% |
9 Let us look at an example:% |
10 \end{isamarkuptext}% |
10 \end{isamarkuptext}% |
11 \isacommand{consts}\ gcd\ ::\ {"}nat*nat\ {\isasymRightarrow}\ nat{"}\isanewline |
11 \isacommand{consts}\ gcd\ {\isacharcolon}{\isacharcolon}\ {\isachardoublequote}nat{\isacharasterisk}nat\ {\isasymRightarrow}\ nat{\isachardoublequote}\isanewline |
12 \isacommand{recdef}\ gcd\ {"}measure\ ({\isasymlambda}(m,n).n){"}\isanewline |
12 \isacommand{recdef}\ gcd\ {\isachardoublequote}measure\ {\isacharparenleft}{\isasymlambda}{\isacharparenleft}m{\isacharcomma}n{\isacharparenright}{\isachardot}n{\isacharparenright}{\isachardoublequote}\isanewline |
13 \ \ {"}gcd\ (m,\ n)\ =\ (if\ n=0\ then\ m\ else\ gcd(n,\ m\ mod\ n)){"}% |
13 \ \ {\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}% |
14 \begin{isamarkuptext}% |
14 \begin{isamarkuptext}% |
15 \noindent |
15 \noindent |
16 According to the measure function, the second argument should decrease with |
16 According to the measure function, the second argument should decrease with |
17 each recursive call. The resulting termination condition |
17 each recursive call. The resulting termination condition |
18 \begin{quote} |
18 \begin{quote} |
19 |
19 |
20 \begin{isabelle}% |
20 \begin{isabelle}% |
21 \mbox{n}\ {\isasymnoteq}\ 0\ {\isasymLongrightarrow}\ \mbox{m}\ mod\ \mbox{n}\ <\ \mbox{n} |
21 \mbox{n}\ {\isasymnoteq}\ \isadigit{0}\ {\isasymLongrightarrow}\ \mbox{m}\ mod\ \mbox{n}\ {\isacharless}\ \mbox{n} |
22 \end{isabelle}% |
22 \end{isabelle}% |
23 |
23 |
24 \end{quote} |
24 \end{quote} |
25 is provded automatically because it is already present as a lemma in the |
25 is provded automatically because it is already present as a lemma in the |
26 arithmetic library. Thus the recursion equation becomes a simplification |
26 arithmetic library. Thus the recursion equation becomes a simplification |
31 condition simplifies to neither \isa{True} nor \isa{False}. For |
31 condition simplifies to neither \isa{True} nor \isa{False}. For |
32 example, simplification reduces |
32 example, simplification reduces |
33 \begin{quote} |
33 \begin{quote} |
34 |
34 |
35 \begin{isabelle}% |
35 \begin{isabelle}% |
36 gcd\ (\mbox{m},\ \mbox{n})\ =\ \mbox{k} |
36 gcd\ {\isacharparenleft}\mbox{m}{\isacharcomma}\ \mbox{n}{\isacharparenright}\ {\isacharequal}\ \mbox{k} |
37 \end{isabelle}% |
37 \end{isabelle}% |
38 |
38 |
39 \end{quote} |
39 \end{quote} |
40 in one step to |
40 in one step to |
41 \begin{quote} |
41 \begin{quote} |
42 |
42 |
43 \begin{isabelle}% |
43 \begin{isabelle}% |
44 (if\ \mbox{n}\ =\ 0\ then\ \mbox{m}\ else\ gcd\ (\mbox{n},\ \mbox{m}\ mod\ \mbox{n}))\ =\ \mbox{k} |
44 {\isacharparenleft}if\ \mbox{n}\ {\isacharequal}\ \isadigit{0}\ then\ \mbox{m}\ else\ gcd\ {\isacharparenleft}\mbox{n}{\isacharcomma}\ \mbox{m}\ mod\ \mbox{n}{\isacharparenright}{\isacharparenright}\ {\isacharequal}\ \mbox{k} |
45 \end{isabelle}% |
45 \end{isabelle}% |
46 |
46 |
47 \end{quote} |
47 \end{quote} |
48 where the condition cannot be reduced further, and splitting leads to |
48 where the condition cannot be reduced further, and splitting leads to |
49 \begin{quote} |
49 \begin{quote} |
50 |
50 |
51 \begin{isabelle}% |
51 \begin{isabelle}% |
52 (\mbox{n}\ =\ 0\ {\isasymlongrightarrow}\ \mbox{m}\ =\ \mbox{k})\ {\isasymand}\ (\mbox{n}\ {\isasymnoteq}\ 0\ {\isasymlongrightarrow}\ gcd\ (\mbox{n},\ \mbox{m}\ mod\ \mbox{n})\ =\ \mbox{k}) |
52 {\isacharparenleft}\mbox{n}\ {\isacharequal}\ \isadigit{0}\ {\isasymlongrightarrow}\ \mbox{m}\ {\isacharequal}\ \mbox{k}{\isacharparenright}\ {\isasymand}\ {\isacharparenleft}\mbox{n}\ {\isasymnoteq}\ \isadigit{0}\ {\isasymlongrightarrow}\ gcd\ {\isacharparenleft}\mbox{n}{\isacharcomma}\ \mbox{m}\ mod\ \mbox{n}{\isacharparenright}\ {\isacharequal}\ \mbox{k}{\isacharparenright} |
53 \end{isabelle}% |
53 \end{isabelle}% |
54 |
54 |
55 \end{quote} |
55 \end{quote} |
56 Since the recursive call \isa{gcd\ (\mbox{n},\ \mbox{m}\ mod\ \mbox{n})} is no longer protected by |
56 Since the recursive call \isa{gcd\ {\isacharparenleft}\mbox{n}{\isacharcomma}\ \mbox{m}\ mod\ \mbox{n}{\isacharparenright}} is no longer protected by |
57 an \isa{if}, it is unfolded again, which leads to an infinite chain of |
57 an \isa{if}, it is unfolded again, which leads to an infinite chain of |
58 simplification steps. Fortunately, this problem can be avoided in many |
58 simplification steps. Fortunately, this problem can be avoided in many |
59 different ways. |
59 different ways. |
60 |
60 |
61 The most radical solution is to disable the offending |
61 The most radical solution is to disable the offending |
66 |
66 |
67 If possible, the definition should be given by pattern matching on the left |
67 If possible, the definition should be given by pattern matching on the left |
68 rather than \isa{if} on the right. In the case of \isa{gcd} the |
68 rather than \isa{if} on the right. In the case of \isa{gcd} the |
69 following alternative definition suggests itself:% |
69 following alternative definition suggests itself:% |
70 \end{isamarkuptext}% |
70 \end{isamarkuptext}% |
71 \isacommand{consts}\ gcd1\ ::\ {"}nat*nat\ {\isasymRightarrow}\ nat{"}\isanewline |
71 \isacommand{consts}\ gcd\isadigit{1}\ {\isacharcolon}{\isacharcolon}\ {\isachardoublequote}nat{\isacharasterisk}nat\ {\isasymRightarrow}\ nat{\isachardoublequote}\isanewline |
72 \isacommand{recdef}\ gcd1\ {"}measure\ ({\isasymlambda}(m,n).n){"}\isanewline |
72 \isacommand{recdef}\ gcd\isadigit{1}\ {\isachardoublequote}measure\ {\isacharparenleft}{\isasymlambda}{\isacharparenleft}m{\isacharcomma}n{\isacharparenright}{\isachardot}n{\isacharparenright}{\isachardoublequote}\isanewline |
73 \ \ {"}gcd1\ (m,\ 0)\ =\ m{"}\isanewline |
73 \ \ {\isachardoublequote}gcd\isadigit{1}\ {\isacharparenleft}m{\isacharcomma}\ \isadigit{0}{\isacharparenright}\ {\isacharequal}\ m{\isachardoublequote}\isanewline |
74 \ \ {"}gcd1\ (m,\ n)\ =\ gcd1(n,\ m\ mod\ n){"}% |
74 \ \ {\isachardoublequote}gcd\isadigit{1}\ {\isacharparenleft}m{\isacharcomma}\ n{\isacharparenright}\ {\isacharequal}\ gcd\isadigit{1}{\isacharparenleft}n{\isacharcomma}\ m\ mod\ n{\isacharparenright}{\isachardoublequote}% |
75 \begin{isamarkuptext}% |
75 \begin{isamarkuptext}% |
76 \noindent |
76 \noindent |
77 Note that the order of equations is important and hides the side condition |
77 Note that the order of equations is important and hides the side condition |
78 \isa{n \isasymnoteq\ 0}. Unfortunately, in general the case distinction |
78 \isa{n \isasymnoteq\ 0}. Unfortunately, in general the case distinction |
79 may not be expressible by pattern matching. |
79 may not be expressible by pattern matching. |
80 |
80 |
81 A very simple alternative is to replace \isa{if} by \isa{case}, which |
81 A very simple alternative is to replace \isa{if} by \isa{case}, which |
82 is also available for \isa{bool} but is not split automatically:% |
82 is also available for \isa{bool} but is not split automatically:% |
83 \end{isamarkuptext}% |
83 \end{isamarkuptext}% |
84 \isacommand{consts}\ gcd2\ ::\ {"}nat*nat\ {\isasymRightarrow}\ nat{"}\isanewline |
84 \isacommand{consts}\ gcd\isadigit{2}\ {\isacharcolon}{\isacharcolon}\ {\isachardoublequote}nat{\isacharasterisk}nat\ {\isasymRightarrow}\ nat{\isachardoublequote}\isanewline |
85 \isacommand{recdef}\ gcd2\ {"}measure\ ({\isasymlambda}(m,n).n){"}\isanewline |
85 \isacommand{recdef}\ gcd\isadigit{2}\ {\isachardoublequote}measure\ {\isacharparenleft}{\isasymlambda}{\isacharparenleft}m{\isacharcomma}n{\isacharparenright}{\isachardot}n{\isacharparenright}{\isachardoublequote}\isanewline |
86 \ \ {"}gcd2(m,n)\ =\ (case\ n=0\ of\ True\ {\isasymRightarrow}\ m\ |\ False\ {\isasymRightarrow}\ gcd2(n,m\ mod\ n)){"}% |
86 \ \ {\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}% |
87 \begin{isamarkuptext}% |
87 \begin{isamarkuptext}% |
88 \noindent |
88 \noindent |
89 In fact, this is probably the neatest solution next to pattern matching. |
89 In fact, this is probably the neatest solution next to pattern matching. |
90 |
90 |
91 A final alternative is to replace the offending simplification rules by |
91 A final alternative is to replace the offending simplification rules by |
92 derived conditional ones. For \isa{gcd} it means we have to prove% |
92 derived conditional ones. For \isa{gcd} it means we have to prove% |
93 \end{isamarkuptext}% |
93 \end{isamarkuptext}% |
94 \isacommand{lemma}\ [simp]:\ {"}gcd\ (m,\ 0)\ =\ m{"}\isanewline |
94 \isacommand{lemma}\ {\isacharbrackleft}simp{\isacharbrackright}{\isacharcolon}\ {\isachardoublequote}gcd\ {\isacharparenleft}m{\isacharcomma}\ \isadigit{0}{\isacharparenright}\ {\isacharequal}\ m{\isachardoublequote}\isanewline |
95 \isacommand{by}(simp)\isanewline |
95 \isacommand{by}{\isacharparenleft}simp{\isacharparenright}\isanewline |
96 \isacommand{lemma}\ [simp]:\ {"}n\ {\isasymnoteq}\ 0\ {\isasymLongrightarrow}\ gcd(m,\ n)\ =\ gcd(n,\ m\ mod\ n){"}\isanewline |
96 \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 |
97 \isacommand{by}(simp)% |
97 \isacommand{by}{\isacharparenleft}simp{\isacharparenright}% |
98 \begin{isamarkuptext}% |
98 \begin{isamarkuptext}% |
99 \noindent |
99 \noindent |
100 after which we can disable the original simplification rule:% |
100 after which we can disable the original simplification rule:% |
101 \end{isamarkuptext}% |
101 \end{isamarkuptext}% |
102 \isacommand{lemmas}\ [simp\ del]\ =\ gcd.simps\isanewline |
102 \isacommand{lemmas}\ {\isacharbrackleft}simp\ del{\isacharbrackright}\ {\isacharequal}\ gcd{\isachardot}simps\isanewline |
103 \end{isabelle}% |
103 \end{isabelle}% |
104 %%% Local Variables: |
104 %%% Local Variables: |
105 %%% mode: latex |
105 %%% mode: latex |
106 %%% TeX-master: "root" |
106 %%% TeX-master: "root" |
107 %%% End: |
107 %%% End: |