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\ ::\ {"}nat*nat\ {\isasymRightarrow}\ nat{"}\isanewline |
12 \isacommand{recdef}~gcd~{"}measure~({\isasymlambda}(m,n).n){"}\isanewline |
12 \isacommand{recdef}\ gcd\ {"}measure\ ({\isasymlambda}(m,n).n){"}\isanewline |
13 ~~{"}gcd~(m,~n)~=~(if~n=0~then~m~else~gcd(n,~m~mod~n)){"}% |
13 \ \ {"}gcd\ (m,\ n)\ =\ (if\ n=0\ then\ m\ else\ gcd(n,\ m\ mod\ n)){"}% |
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 \end{isamarkuptext}% |
18 \begin{quote} |
19 ~{"}n~{\isasymnoteq}~0~{\isasymLongrightarrow}~m~mod~n~<~n{"}% |
19 |
20 \begin{isamarkuptext}% |
20 \begin{isabelle}% |
21 \noindent |
21 n\ {\isasymnoteq}\ 0\ {\isasymLongrightarrow}\ m\ mod\ n\ <\ n |
|
22 \end{isabelle}% |
|
23 |
|
24 \end{quote} |
22 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 |
23 arithmetic library. Thus the recursion equation becomes a simplification |
26 arithmetic library. Thus the recursion equation becomes a simplification |
24 rule. Of course the equation is nonterminating if we are allowed to unfold |
27 rule. Of course the equation is nonterminating if we are allowed to unfold |
25 the recursive call inside the \isa{else} branch, which is why programming |
28 the recursive call inside the \isa{else} branch, which is why programming |
26 languages and our simplifier don't do that. Unfortunately the simplifier does |
29 languages and our simplifier don't do that. Unfortunately the simplifier does |
27 something else which leads to the same problem: it splits \isa{if}s if the |
30 something else which leads to the same problem: it splits \isa{if}s if the |
28 condition simplifies to neither \isa{True} nor \isa{False}. For |
31 condition simplifies to neither \isa{True} nor \isa{False}. For |
29 example, simplification reduces% |
32 example, simplification reduces |
30 \end{isamarkuptext}% |
33 \begin{quote} |
31 ~{"}gcd(m,n)~=~k{"}% |
34 |
32 \begin{isamarkuptext}% |
35 \begin{isabelle}% |
33 \noindent |
36 gcd\ (m,\ n)\ =\ k |
34 in one step to% |
37 \end{isabelle}% |
35 \end{isamarkuptext}% |
38 |
36 ~{"}(if~n=0~then~m~else~gcd(n,~m~mod~n))~=~k{"}% |
39 \end{quote} |
37 \begin{isamarkuptext}% |
40 in one step to |
38 \noindent |
41 \begin{quote} |
39 where the condition cannot be reduced further, and splitting leads to% |
42 |
40 \end{isamarkuptext}% |
43 \begin{isabelle}% |
41 ~{"}(n=0~{\isasymlongrightarrow}~m=k)~{\isasymand}~(n{\isasymnoteq}0~{\isasymlongrightarrow}~gcd(n,~m~mod~n)=k){"}% |
44 (if\ n\ =\ 0\ then\ m\ else\ gcd\ (n,\ m\ mod\ n))\ =\ k |
42 \begin{isamarkuptext}% |
45 \end{isabelle}% |
43 \noindent |
46 |
44 Since the recursive call \isa{gcd(n, m mod n)} is no longer protected by |
47 \end{quote} |
45 an \isa{if}, it is unfolded again, which leads to an infinite chain of simplification steps. |
48 where the condition cannot be reduced further, and splitting leads to |
46 Fortunately, this problem can be avoided in many different ways. |
49 \begin{quote} |
|
50 |
|
51 \begin{isabelle}% |
|
52 (n\ =\ 0\ {\isasymlongrightarrow}\ m\ =\ k)\ {\isasymand}\ (n\ {\isasymnoteq}\ 0\ {\isasymlongrightarrow}\ gcd\ (n,\ m\ mod\ n)\ =\ k) |
|
53 \end{isabelle}% |
|
54 |
|
55 \end{quote} |
|
56 Since the recursive call \isa{gcd\ (n,\ m\ mod\ n)} is no longer protected by |
|
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 |
|
59 different ways. |
47 |
60 |
48 The most radical solution is to disable the offending |
61 The most radical solution is to disable the offending |
49 \isa{split_if} as shown in the section on case splits in |
62 \isa{split_if} as shown in the section on case splits in |
50 \S\ref{sec:SimpFeatures}. |
63 \S\ref{sec:SimpFeatures}. |
51 However, we do not recommend this because it means you will often have to |
64 However, we do not recommend this because it means you will often have to |
53 |
66 |
54 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 |
55 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 |
56 following alternative definition suggests itself:% |
69 following alternative definition suggests itself:% |
57 \end{isamarkuptext}% |
70 \end{isamarkuptext}% |
58 \isacommand{consts}~gcd1~::~{"}nat*nat~{\isasymRightarrow}~nat{"}\isanewline |
71 \isacommand{consts}\ gcd1\ ::\ {"}nat*nat\ {\isasymRightarrow}\ nat{"}\isanewline |
59 \isacommand{recdef}~gcd1~{"}measure~({\isasymlambda}(m,n).n){"}\isanewline |
72 \isacommand{recdef}\ gcd1\ {"}measure\ ({\isasymlambda}(m,n).n){"}\isanewline |
60 ~~{"}gcd1~(m,~0)~=~m{"}\isanewline |
73 \ \ {"}gcd1\ (m,\ 0)\ =\ m{"}\isanewline |
61 ~~{"}gcd1~(m,~n)~=~gcd1(n,~m~mod~n){"}% |
74 \ \ {"}gcd1\ (m,\ n)\ =\ gcd1(n,\ m\ mod\ n){"}% |
62 \begin{isamarkuptext}% |
75 \begin{isamarkuptext}% |
63 \noindent |
76 \noindent |
64 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 |
65 \isa{n \isasymnoteq\ 0}. Unfortunately, in general the case distinction |
78 \isa{n \isasymnoteq\ 0}. Unfortunately, in general the case distinction |
66 may not be expressible by pattern matching. |
79 may not be expressible by pattern matching. |
67 |
80 |
68 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 |
69 is also available for \isa{bool} but is not split automatically:% |
82 is also available for \isa{bool} but is not split automatically:% |
70 \end{isamarkuptext}% |
83 \end{isamarkuptext}% |
71 \isacommand{consts}~gcd2~::~{"}nat*nat~{\isasymRightarrow}~nat{"}\isanewline |
84 \isacommand{consts}\ gcd2\ ::\ {"}nat*nat\ {\isasymRightarrow}\ nat{"}\isanewline |
72 \isacommand{recdef}~gcd2~{"}measure~({\isasymlambda}(m,n).n){"}\isanewline |
85 \isacommand{recdef}\ gcd2\ {"}measure\ ({\isasymlambda}(m,n).n){"}\isanewline |
73 ~~{"}gcd2(m,n)~=~(case~n=0~of~True~{\isasymRightarrow}~m~|~False~{\isasymRightarrow}~gcd2(n,m~mod~n)){"}% |
86 \ \ {"}gcd2(m,n)\ =\ (case\ n=0\ of\ True\ {\isasymRightarrow}\ m\ |\ False\ {\isasymRightarrow}\ gcd2(n,m\ mod\ n)){"}% |
74 \begin{isamarkuptext}% |
87 \begin{isamarkuptext}% |
75 \noindent |
88 \noindent |
76 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. |
77 |
90 |
78 A final alternative is to replace the offending simplification rules by |
91 A final alternative is to replace the offending simplification rules by |
79 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% |
80 \end{isamarkuptext}% |
93 \end{isamarkuptext}% |
81 \isacommand{lemma}~[simp]:~{"}gcd~(m,~0)~=~m{"}\isanewline |
94 \isacommand{lemma}\ [simp]:\ {"}gcd\ (m,\ 0)\ =\ m{"}\isanewline |
82 \isacommand{by}(simp)\isanewline |
95 \isacommand{by}(simp)\isanewline |
83 \isacommand{lemma}~[simp]:~{"}n~{\isasymnoteq}~0~{\isasymLongrightarrow}~gcd(m,~n)~=~gcd(n,~m~mod~n){"}\isanewline |
96 \isacommand{lemma}\ [simp]:\ {"}n\ {\isasymnoteq}\ 0\ {\isasymLongrightarrow}\ gcd(m,\ n)\ =\ gcd(n,\ m\ mod\ n){"}\isanewline |
84 \isacommand{by}(simp)% |
97 \isacommand{by}(simp)% |
85 \begin{isamarkuptext}% |
98 \begin{isamarkuptext}% |
86 \noindent |
99 \noindent |
87 after which we can disable the original simplification rule:% |
100 after which we can disable the original simplification rule:% |
88 \end{isamarkuptext}% |
101 \end{isamarkuptext}% |
89 \isacommand{lemmas}~[simp~del]~=~gcd.simps\isanewline |
102 \isacommand{lemmas}\ [simp\ del]\ =\ gcd.simps\isanewline |
90 \end{isabelle}% |
103 \end{isabelle}% |
91 %%% Local Variables: |
104 %%% Local Variables: |
92 %%% mode: latex |
105 %%% mode: latex |
93 %%% TeX-master: "root" |
106 %%% TeX-master: "root" |
94 %%% End: |
107 %%% End: |