paulson@10341
|
1 |
(* ID: $Id$ *)
|
paulson@10295
|
2 |
(* EXTRACT from HOL/ex/Primes.thy*)
|
paulson@10295
|
3 |
|
paulson@11080
|
4 |
(*Euclid's algorithm
|
paulson@11080
|
5 |
This material now appears AFTER that of Forward.thy *)
|
haftmann@16417
|
6 |
theory Primes imports Main begin
|
paulson@10295
|
7 |
|
nipkow@25261
|
8 |
fun gcd :: "nat \<Rightarrow> nat \<Rightarrow> nat" where
|
nipkow@25261
|
9 |
"gcd m n = (if n=0 then m else gcd n (m mod n))"
|
paulson@10295
|
10 |
|
paulson@10295
|
11 |
|
paulson@10295
|
12 |
ML "Pretty.setmargin 64"
|
wenzelm@22097
|
13 |
ML "ThyOutput.indent := 5" (*that is, Doc/TutorialI/settings.ML*)
|
paulson@10295
|
14 |
|
paulson@10295
|
15 |
|
paulson@11234
|
16 |
text {*Now in Basic.thy!
|
paulson@10295
|
17 |
@{thm[display]"dvd_def"}
|
paulson@10295
|
18 |
\rulename{dvd_def}
|
paulson@10295
|
19 |
*};
|
paulson@10295
|
20 |
|
paulson@10295
|
21 |
|
paulson@10295
|
22 |
(*** Euclid's Algorithm ***)
|
paulson@10295
|
23 |
|
nipkow@25261
|
24 |
lemma gcd_0 [simp]: "gcd m 0 = m"
|
paulson@10846
|
25 |
apply (simp);
|
paulson@10846
|
26 |
done
|
paulson@10295
|
27 |
|
nipkow@25261
|
28 |
lemma gcd_non_0 [simp]: "0<n \<Longrightarrow> gcd m n = gcd n (m mod n)"
|
paulson@10846
|
29 |
apply (simp)
|
paulson@10846
|
30 |
done;
|
paulson@10295
|
31 |
|
paulson@10295
|
32 |
declare gcd.simps [simp del];
|
paulson@10295
|
33 |
|
paulson@10295
|
34 |
(*gcd(m,n) divides m and n. The conjunctions don't seem provable separately*)
|
nipkow@25261
|
35 |
lemma gcd_dvd_both: "(gcd m n dvd m) \<and> (gcd m n dvd n)"
|
paulson@10846
|
36 |
apply (induct_tac m n rule: gcd.induct)
|
paulson@11080
|
37 |
--{* @{subgoals[display,indent=0,margin=65]} *}
|
paulson@10846
|
38 |
apply (case_tac "n=0")
|
paulson@11080
|
39 |
txt{*subgoals after the case tac
|
paulson@11080
|
40 |
@{subgoals[display,indent=0,margin=65]}
|
paulson@11080
|
41 |
*};
|
paulson@11080
|
42 |
apply (simp_all)
|
paulson@11080
|
43 |
--{* @{subgoals[display,indent=0,margin=65]} *}
|
paulson@10846
|
44 |
by (blast dest: dvd_mod_imp_dvd)
|
paulson@10846
|
45 |
|
paulson@10295
|
46 |
|
paulson@10295
|
47 |
|
paulson@10295
|
48 |
text {*
|
paulson@10295
|
49 |
@{thm[display] dvd_mod_imp_dvd}
|
paulson@10295
|
50 |
\rulename{dvd_mod_imp_dvd}
|
paulson@10295
|
51 |
|
paulson@10295
|
52 |
@{thm[display] dvd_trans}
|
paulson@10295
|
53 |
\rulename{dvd_trans}
|
paulson@11080
|
54 |
*}
|
paulson@10295
|
55 |
|
paulson@10295
|
56 |
lemmas gcd_dvd1 [iff] = gcd_dvd_both [THEN conjunct1]
|
paulson@10295
|
57 |
lemmas gcd_dvd2 [iff] = gcd_dvd_both [THEN conjunct2];
|
paulson@10295
|
58 |
|
paulson@10295
|
59 |
|
paulson@10295
|
60 |
text {*
|
paulson@10295
|
61 |
\begin{quote}
|
paulson@10295
|
62 |
@{thm[display] gcd_dvd1}
|
paulson@10295
|
63 |
\rulename{gcd_dvd1}
|
paulson@10295
|
64 |
|
paulson@10295
|
65 |
@{thm[display] gcd_dvd2}
|
paulson@10295
|
66 |
\rulename{gcd_dvd2}
|
paulson@10295
|
67 |
\end{quote}
|
paulson@10295
|
68 |
*};
|
paulson@10295
|
69 |
|
paulson@10295
|
70 |
(*Maximality: for all m,n,k naturals,
|
paulson@10295
|
71 |
if k divides m and k divides n then k divides gcd(m,n)*)
|
paulson@10295
|
72 |
lemma gcd_greatest [rule_format]:
|
nipkow@25261
|
73 |
"k dvd m \<longrightarrow> k dvd n \<longrightarrow> k dvd gcd m n"
|
paulson@10846
|
74 |
apply (induct_tac m n rule: gcd.induct)
|
paulson@10846
|
75 |
apply (case_tac "n=0")
|
paulson@10853
|
76 |
txt{*subgoals after the case tac
|
paulson@10853
|
77 |
@{subgoals[display,indent=0,margin=65]}
|
paulson@10853
|
78 |
*};
|
paulson@10846
|
79 |
apply (simp_all add: dvd_mod)
|
paulson@10846
|
80 |
done
|
paulson@10295
|
81 |
|
paulson@11080
|
82 |
text {*
|
paulson@11080
|
83 |
@{thm[display] dvd_mod}
|
paulson@11080
|
84 |
\rulename{dvd_mod}
|
paulson@11080
|
85 |
*}
|
paulson@11080
|
86 |
|
paulson@10853
|
87 |
(*just checking the claim that case_tac "n" works too*)
|
nipkow@25261
|
88 |
lemma "k dvd m \<longrightarrow> k dvd n \<longrightarrow> k dvd gcd m n"
|
paulson@10853
|
89 |
apply (induct_tac m n rule: gcd.induct)
|
paulson@10853
|
90 |
apply (case_tac "n")
|
paulson@11080
|
91 |
apply (simp_all add: dvd_mod)
|
paulson@11080
|
92 |
done
|
paulson@11080
|
93 |
|
paulson@10853
|
94 |
|
paulson@10295
|
95 |
theorem gcd_greatest_iff [iff]:
|
nipkow@25261
|
96 |
"(k dvd gcd m n) = (k dvd m \<and> k dvd n)"
|
paulson@10846
|
97 |
by (blast intro!: gcd_greatest intro: dvd_trans)
|
paulson@10295
|
98 |
|
paulson@10295
|
99 |
|
paulson@10846
|
100 |
(**** The material below was omitted from the book ****)
|
paulson@10846
|
101 |
|
paulson@10295
|
102 |
constdefs
|
paulson@10300
|
103 |
is_gcd :: "[nat,nat,nat] \<Rightarrow> bool" (*gcd as a relation*)
|
paulson@10295
|
104 |
"is_gcd p m n == p dvd m \<and> p dvd n \<and>
|
paulson@10295
|
105 |
(ALL d. d dvd m \<and> d dvd n \<longrightarrow> d dvd p)"
|
paulson@10295
|
106 |
|
paulson@10295
|
107 |
(*Function gcd yields the Greatest Common Divisor*)
|
nipkow@25261
|
108 |
lemma is_gcd: "is_gcd (gcd m n) m n"
|
paulson@10846
|
109 |
apply (simp add: is_gcd_def gcd_greatest);
|
paulson@10846
|
110 |
done
|
paulson@10295
|
111 |
|
paulson@10295
|
112 |
(*uniqueness of GCDs*)
|
paulson@10295
|
113 |
lemma is_gcd_unique: "\<lbrakk> is_gcd m a b; is_gcd n a b \<rbrakk> \<Longrightarrow> m=n"
|
paulson@10846
|
114 |
apply (simp add: is_gcd_def);
|
paulson@10846
|
115 |
apply (blast intro: dvd_anti_sym)
|
paulson@10846
|
116 |
done
|
paulson@10295
|
117 |
|
paulson@10295
|
118 |
|
paulson@10295
|
119 |
text {*
|
paulson@10295
|
120 |
@{thm[display] dvd_anti_sym}
|
paulson@10295
|
121 |
\rulename{dvd_anti_sym}
|
paulson@10295
|
122 |
|
paulson@10295
|
123 |
\begin{isabelle}
|
paulson@10295
|
124 |
proof\ (prove):\ step\ 1\isanewline
|
paulson@10295
|
125 |
\isanewline
|
paulson@10295
|
126 |
goal\ (lemma\ is_gcd_unique):\isanewline
|
paulson@10295
|
127 |
\isasymlbrakk is_gcd\ m\ a\ b;\ is_gcd\ n\ a\ b\isasymrbrakk \ \isasymLongrightarrow \ m\ =\ n\isanewline
|
paulson@10295
|
128 |
\ 1.\ \isasymlbrakk m\ dvd\ a\ \isasymand \ m\ dvd\ b\ \isasymand \ (\isasymforall d.\ d\ dvd\ a\ \isasymand \ d\ dvd\ b\ \isasymlongrightarrow \ d\ dvd\ m);\isanewline
|
paulson@10295
|
129 |
\ \ \ \ \ \ \ n\ dvd\ a\ \isasymand \ n\ dvd\ b\ \isasymand \ (\isasymforall d.\ d\ dvd\ a\ \isasymand \ d\ dvd\ b\ \isasymlongrightarrow \ d\ dvd\ n)\isasymrbrakk \isanewline
|
paulson@10295
|
130 |
\ \ \ \ \isasymLongrightarrow \ m\ =\ n
|
paulson@10295
|
131 |
\end{isabelle}
|
paulson@10295
|
132 |
*};
|
paulson@10295
|
133 |
|
nipkow@25261
|
134 |
lemma gcd_assoc: "gcd (gcd k m) n = gcd k (gcd m n)"
|
paulson@10295
|
135 |
apply (rule is_gcd_unique)
|
paulson@10295
|
136 |
apply (rule is_gcd)
|
paulson@10295
|
137 |
apply (simp add: is_gcd_def);
|
paulson@10295
|
138 |
apply (blast intro: dvd_trans);
|
nipkow@25261
|
139 |
done
|
paulson@10295
|
140 |
|
paulson@10295
|
141 |
text{*
|
paulson@10295
|
142 |
\begin{isabelle}
|
paulson@10295
|
143 |
proof\ (prove):\ step\ 3\isanewline
|
paulson@10295
|
144 |
\isanewline
|
paulson@10295
|
145 |
goal\ (lemma\ gcd_assoc):\isanewline
|
paulson@10295
|
146 |
gcd\ (gcd\ (k,\ m),\ n)\ =\ gcd\ (k,\ gcd\ (m,\ n))\isanewline
|
paulson@10295
|
147 |
\ 1.\ gcd\ (k,\ gcd\ (m,\ n))\ dvd\ k\ \isasymand \isanewline
|
paulson@10295
|
148 |
\ \ \ \ gcd\ (k,\ gcd\ (m,\ n))\ dvd\ m\ \isasymand \ gcd\ (k,\ gcd\ (m,\ n))\ dvd\ n
|
paulson@10295
|
149 |
\end{isabelle}
|
paulson@10295
|
150 |
*}
|
paulson@10295
|
151 |
|
paulson@10295
|
152 |
|
nipkow@25261
|
153 |
lemma gcd_dvd_gcd_mult: "gcd m n dvd gcd (k*m) n"
|
haftmann@27657
|
154 |
apply (auto intro: dvd_trans [of _ m])
|
paulson@10295
|
155 |
done
|
paulson@10295
|
156 |
|
paulson@10295
|
157 |
(*This is half of the proof (by dvd_anti_sym) of*)
|
nipkow@25261
|
158 |
lemma gcd_mult_cancel: "gcd k n = 1 \<Longrightarrow> gcd (k*m) n = gcd m n"
|
paulson@10295
|
159 |
oops
|
paulson@10295
|
160 |
|
paulson@10295
|
161 |
end
|