neuper@48813
|
1 |
header {* GCD for polynomials, implemented using the function package (_FP) *}
|
neuper@48813
|
2 |
theory GCD_Poly_FP
|
neuper@48813
|
3 |
imports "~~/src/HOL/Library/Polynomial" "~~/src/HOL/Number_Theory/Primes"
|
neuper@48813
|
4 |
begin
|
neuper@48813
|
5 |
|
neuper@48813
|
6 |
text {*
|
neuper@48813
|
7 |
This code has been translated from GCD_Poly.thy by Diana Meindl,
|
neuper@48813
|
8 |
who follows Franz Winkler, Polynomial algorithyms in computer algebra, Springer 1996.
|
neuper@48830
|
9 |
Winkler's original identifiers are in test/./gcd_poly_winkler.sml;
|
neuper@48813
|
10 |
test/../gcd_poly.sml documents the changes towards GCD_Poly.thy;
|
neuper@48813
|
11 |
the style of GCD_Poly.thy has been adapted to the function package.
|
neuper@48813
|
12 |
*}
|
neuper@48813
|
13 |
|
neuper@48842
|
14 |
(* WN130304.TODO see Algebra/poly/LongDiv.thy: lcoeff_def*)
|
neuper@48837
|
15 |
(*---------------------------------------------------------------------------------------------
|
neuper@48837
|
16 |
declare [[simp_trace_depth_limit = 99]]
|
neuper@48837
|
17 |
declare [[simp_trace = true]]
|
neuper@48837
|
18 |
---------------------------------------------------------------------------------------------*)
|
neuper@48837
|
19 |
|
neuper@48813
|
20 |
section {* gcd for univariate polynomials *}
|
neuper@48813
|
21 |
|
neuper@48823
|
22 |
type_synonym unipoly = "int list"
|
neuper@48823
|
23 |
value "[0, 1, 2, 3, 4, 5] :: unipoly"
|
neuper@48823
|
24 |
|
neuper@48813
|
25 |
subsection {* a variant for div *}
|
neuper@48817
|
26 |
(* 5 div 2 = 2; ~5 div 2 = ~3; but ~5 div2 2 = ~2; *)
|
neuper@48831
|
27 |
definition div2 :: "int \<Rightarrow> int \<Rightarrow> int" (infixl "div2" 70) where
|
neuper@48815
|
28 |
"a div2 b = (if a div b < 0 then (\<bar>a\<bar> div \<bar>b\<bar>) * -1 else a div b)"
|
neuper@48813
|
29 |
|
neuper@48823
|
30 |
value " 5 div2 2 = 2"
|
neuper@48823
|
31 |
value "-5 div2 2 = -2"
|
neuper@48823
|
32 |
value "-5 div2 -2 = 2"
|
neuper@48823
|
33 |
value " 5 div2 -2 = -2"
|
neuper@48813
|
34 |
|
neuper@48823
|
35 |
value "gcd (15::int) (6::int) = 3"
|
neuper@48823
|
36 |
value "gcd (10::int) (3::int) = 1"
|
neuper@48823
|
37 |
value "gcd (6::int) (24::int) = 6"
|
neuper@48813
|
38 |
|
neuper@48831
|
39 |
(*---------------------------------------------------------------------------------------------*)
|
neuper@48813
|
40 |
subsection {* modulo calculations for integers *}
|
neuper@48817
|
41 |
(* modi is just local for mod_inv *)
|
neuper@48831
|
42 |
function modi :: "int \<Rightarrow> int \<Rightarrow> int \<Rightarrow> int \<Rightarrow> int" where
|
neuper@48815
|
43 |
"modi r rold m rinv =
|
neuper@48836
|
44 |
(if m \<le> rinv
|
neuper@48836
|
45 |
then 0 else
|
neuper@48815
|
46 |
if r mod m = 1
|
neuper@48815
|
47 |
then rinv
|
neuper@48836
|
48 |
else modi (rold * (rinv + 1)) rold m (rinv + 1))"
|
neuper@48813
|
49 |
by auto
|
neuper@48813
|
50 |
termination sorry
|
neuper@48831
|
51 |
(* mod_inv :: int \<Rightarrow> nat
|
neuper@48817
|
52 |
mod_inv r m = s
|
neuper@48836
|
53 |
assumes True
|
neuper@48836
|
54 |
yields r * s mod m = 1 *)
|
neuper@48831
|
55 |
fun mod_inv :: "int \<Rightarrow> int \<Rightarrow> int" where
|
neuper@48815
|
56 |
"mod_inv r m = modi r r m 1"
|
neuper@48813
|
57 |
|
neuper@48823
|
58 |
value "modi 5 5 7 1 = 3"
|
neuper@48823
|
59 |
value "modi 3 3 7 1 = 5"
|
neuper@48823
|
60 |
value "modi 4 4 339 1 = 85"
|
neuper@48813
|
61 |
|
neuper@48823
|
62 |
value "mod_inv 5 7 = 3"
|
neuper@48823
|
63 |
value "mod_inv 3 7 = 5"
|
neuper@48823
|
64 |
value "mod_inv 4 339 = 85"
|
neuper@48813
|
65 |
|
neuper@48831
|
66 |
(* mod_div :: int \<Rightarrow> int \<Rightarrow> nat \<Rightarrow> nat
|
neuper@48825
|
67 |
mod_div a b m = c
|
neuper@48836
|
68 |
assumes True
|
neuper@48836
|
69 |
yields a * b ^(-1) mod m = c <\<Longrightarrow> a mod m = *)
|
neuper@48831
|
70 |
definition mod_div :: "int \<Rightarrow> int \<Rightarrow> int \<Rightarrow> int" where
|
neuper@48815
|
71 |
"mod_div a b m = a * (mod_inv b m) mod m"
|
neuper@48813
|
72 |
|
neuper@48817
|
73 |
(* root1 is just local to approx_root *)
|
neuper@48831
|
74 |
function root1 :: "int \<Rightarrow> int \<Rightarrow> int" where
|
neuper@48815
|
75 |
"root1 a n = (if n * n < a then root1 a (n + 1) else n)"
|
neuper@48815
|
76 |
by auto
|
neuper@48815
|
77 |
termination sorry
|
neuper@48831
|
78 |
|
neuper@48825
|
79 |
(* required just for one approximation:
|
neuper@48836
|
80 |
approx_root :: nat \<Rightarrow> nat
|
neuper@48817
|
81 |
approx_root a = r
|
neuper@48836
|
82 |
assumes True
|
neuper@48836
|
83 |
yields r * r \<ge> a *)
|
neuper@48831
|
84 |
definition approx_root :: "int \<Rightarrow> int" where
|
neuper@48815
|
85 |
"approx_root a = root1 a 1"
|
neuper@48813
|
86 |
|
neuper@48836
|
87 |
(* chinese_remainder :: int \<Rightarrow> int \<Rightarrow> int \<Rightarrow> int \<Rightarrow> int
|
neuper@48836
|
88 |
chinese_remainder r1 m1 r2 m2 = r
|
neuper@48836
|
89 |
assumes True
|
neuper@48836
|
90 |
yields r = r1 mod m1 \<and> r = r2 mod m2 *)
|
neuper@48831
|
91 |
definition chinese_remainder :: "int \<Rightarrow> int \<Rightarrow> int \<Rightarrow> int \<Rightarrow> int" where
|
neuper@48815
|
92 |
"chinese_remainder r1 m1 r2 m2 =
|
neuper@48813
|
93 |
(r1 mod m1) + ((r2 - (r1 mod m1)) * (mod_inv m1 m2) mod m2) * m1"
|
neuper@48813
|
94 |
|
neuper@48823
|
95 |
value "chinese_remainder 17 9 3 4 = 35"
|
neuper@48823
|
96 |
value "chinese_remainder 7 2 6 11 = 17"
|
neuper@48813
|
97 |
|
neuper@48813
|
98 |
subsection {* operations with primes *}
|
neuper@48813
|
99 |
|
neuper@48830
|
100 |
(* is_prime :: int list \<Rightarrow> int \<Rightarrow> bool
|
neuper@48830
|
101 |
is_prime ps n = b
|
neuper@48830
|
102 |
assumes max ps < n \<and> n \<le> (max ps)^2 \<and>
|
neuper@48830
|
103 |
(* FIXME: really ^^^^^^^^^^^^^^^? *)
|
neuper@48831
|
104 |
(\<forall>p. List.member ps p \<longrightarrow> Primes.prime p) \<and> (\<forall>p. p < n \<and> Primes.prime p \<longrightarrow> List.member ps p)
|
neuper@48830
|
105 |
yields Primes.prime n *)
|
neuper@48830
|
106 |
fun is_prime :: "nat list \<Rightarrow> nat \<Rightarrow> bool" where
|
neuper@48830
|
107 |
"is_prime ps n =
|
neuper@48830
|
108 |
(if List.length ps > 0
|
neuper@48813
|
109 |
then
|
neuper@48830
|
110 |
if (n mod (List.hd ps)) = 0
|
neuper@48813
|
111 |
then False
|
neuper@48830
|
112 |
else is_prime (List.tl ps) n
|
neuper@48813
|
113 |
else True)"
|
neuper@48837
|
114 |
declare is_prime.simps [simp del] -- "make_primes, next_prime_not_dvd"
|
neuper@48813
|
115 |
|
neuper@48830
|
116 |
value "is_prime [2, 3] 2 = False" --"... precondition!"
|
neuper@48830
|
117 |
value "is_prime [2, 3] 3 = False" --"... precondition!"
|
neuper@48823
|
118 |
value "is_prime [2, 3] 4 = False"
|
neuper@48823
|
119 |
value "is_prime [2, 3] 5 = True"
|
neuper@48830
|
120 |
value "is_prime [2, 3, 5] 5 = False" --"... precondition!"
|
neuper@48823
|
121 |
value "is_prime [2, 3] 6 = False"
|
neuper@48830
|
122 |
value "is_prime [2, 3] 7 = True"
|
neuper@48832
|
123 |
value "is_prime [2, 3] 25 = True" -- "... because 5 not in list"
|
neuper@48813
|
124 |
|
neuper@48830
|
125 |
(* make_primes is just local to primes_upto only:
|
neuper@48830
|
126 |
make_primes :: int list \<Rightarrow> int \<Rightarrow> int \<Rightarrow> int list
|
neuper@48830
|
127 |
make_primes ps last_p n = pps
|
neuper@48831
|
128 |
assumes last_p = maxs ps \<and> (\<forall>p. List.member ps p \<longrightarrow> Primes.prime p) \<and>
|
neuper@48831
|
129 |
(\<forall>p. p < last_p \<and> Primes.prime p \<longrightarrow> List.member ps p)
|
neuper@48836
|
130 |
yields n \<le> maxs pps \<and> (\<forall>p. List.member pps p \<longrightarrow> Primes.prime p) \<and>
|
neuper@48831
|
131 |
(\<forall>p. (p < maxs pps \<and> Primes.prime p) \<longrightarrow> List.member pps p)*)
|
neuper@48830
|
132 |
function make_primes :: "nat list \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> nat list" where
|
neuper@48825
|
133 |
"make_primes ps last_p n =
|
neuper@48825
|
134 |
(if (List.nth ps (List.length ps - 1)) < n
|
neuper@48813
|
135 |
then
|
neuper@48830
|
136 |
if is_prime ps (last_p + 2)
|
neuper@48825
|
137 |
then make_primes (ps @ [(last_p + 2)]) (last_p + 2) n
|
neuper@48825
|
138 |
else make_primes ps (last_p + 2) n
|
neuper@48825
|
139 |
else ps)"
|
neuper@48837
|
140 |
by pat_completeness simp
|
neuper@48815
|
141 |
termination sorry
|
neuper@48837
|
142 |
declare make_primes.simps [simp del] -- "next_prime_not_dvd"
|
neuper@48825
|
143 |
|
neuper@48837
|
144 |
value "make_primes [2, 3] 3 4 = [2, 3, 5]"
|
neuper@48837
|
145 |
value "make_primes [2, 3] 3 5 = [2, 3, 5]"
|
neuper@48837
|
146 |
value "make_primes [2, 3] 3 6 = [2, 3, 5, 7]"
|
neuper@48837
|
147 |
value "make_primes [2, 3] 3 7 = [2, 3, 5, 7]"
|
neuper@48837
|
148 |
value "make_primes [2, 3] 3 8 = [2, 3, 5, 7, 11]"
|
neuper@48837
|
149 |
value "make_primes [2, 3] 3 9 = [2, 3, 5, 7, 11]"
|
neuper@48837
|
150 |
value "make_primes [2, 3] 3 10 = [2, 3, 5, 7, 11]"
|
neuper@48837
|
151 |
value "make_primes [2, 3] 3 11 = [2, 3, 5, 7, 11]"
|
neuper@48837
|
152 |
value "make_primes [2, 3] 3 12 = [2, 3, 5, 7, 11, 13]"
|
neuper@48837
|
153 |
value "make_primes [2, 3] 3 13 = [2, 3, 5, 7, 11, 13]"
|
neuper@48837
|
154 |
value "make_primes [2, 3] 3 14 = [2, 3, 5, 7, 11, 13, 17]"
|
neuper@48837
|
155 |
value "make_primes [2, 3] 3 15 = [2, 3, 5, 7, 11, 13, 17]"
|
neuper@48837
|
156 |
value "make_primes [2, 3] 3 16 = [2, 3, 5, 7, 11, 13, 17]"
|
neuper@48837
|
157 |
value "make_primes [2, 3] 3 17 = [2, 3, 5, 7, 11, 13, 17]"
|
neuper@48837
|
158 |
value "make_primes [2, 3] 3 18 = [2, 3, 5, 7, 11, 13, 17, 19]"
|
neuper@48837
|
159 |
value "make_primes [2, 3] 3 19 = [2, 3, 5, 7, 11, 13, 17, 19]"
|
neuper@48837
|
160 |
value "make_primes [2, 3, 5, 7] 7 4 = [2, 3, 5, 7]"
|
neuper@48831
|
161 |
|
neuper@48831
|
162 |
(* primes_upto :: nat \<Rightarrow> nat list
|
neuper@48830
|
163 |
primes_upto n = ps
|
neuper@48831
|
164 |
assumes True
|
neuper@48836
|
165 |
yields (\<forall>p. List.member ps p \<longrightarrow> Primes.prime p) \<and>
|
neuper@48831
|
166 |
n \<le> maxs ps \<and> maxs ps \<le> Fact.fact n + 1 \<and>
|
neuper@48831
|
167 |
(\<forall>p. p \<le> maxs ps \<and> Primes.prime p \<longrightarrow> List.member ps p) *)
|
neuper@48830
|
168 |
fun primes_upto :: "nat \<Rightarrow> nat list" where
|
neuper@48815
|
169 |
"primes_upto n = (if n < 3 then [2] else make_primes [2, 3] 3 n)"
|
neuper@48837
|
170 |
declare primes_upto.simps [simp del] -- "next_prime_not_dvd"
|
neuper@48813
|
171 |
|
neuper@48825
|
172 |
value "primes_upto 2 = [2]"
|
neuper@48825
|
173 |
value "primes_upto 3 = [2, 3]"
|
neuper@48825
|
174 |
value "primes_upto 4 = [2, 3, 5]"
|
neuper@48825
|
175 |
value "primes_upto 5 = [2, 3, 5]"
|
neuper@48825
|
176 |
value "primes_upto 6 = [2, 3, 5, 7]"
|
neuper@48825
|
177 |
value "primes_upto 7 = [2, 3, 5, 7]"
|
neuper@48825
|
178 |
value "primes_upto 8 = [2, 3, 5, 7, 11]"
|
neuper@48825
|
179 |
value "primes_upto 9 = [2, 3, 5, 7, 11]"
|
neuper@48825
|
180 |
value "primes_upto 10 = [2, 3, 5, 7, 11]"
|
neuper@48825
|
181 |
value "primes_upto 11 = [2, 3, 5, 7, 11]"
|
neuper@48813
|
182 |
|
neuper@48831
|
183 |
(* max's' is analogous to Integer.gcds *)
|
neuper@48830
|
184 |
fun maxs :: "nat list \<Rightarrow> nat" where
|
neuper@48831
|
185 |
"maxs ns = List.fold max ns (List.hd ns)"
|
neuper@48830
|
186 |
value "maxs [5, 3, 7, 1, 2, 4] = 7"
|
neuper@48830
|
187 |
|
neuper@48830
|
188 |
(* find the next prime greater p not dividing the number n:
|
neuper@48827
|
189 |
next_prime_not_dvd :: int \<Rightarrow> int \<Rightarrow> int (infix)
|
neuper@48827
|
190 |
n1 next_prime_not_dvd n2 = p
|
neuper@48827
|
191 |
assumes True
|
neuper@48837
|
192 |
yields p is_prime \<and> n1 < p \<and> \<not> p dvd n2 \<and> (* smallest with these properties... *)
|
neuper@48837
|
193 |
(\<forall> p'. (p' is_prime \<and> n1 < p' \<and> \<not> p' dvd n2) \<longrightarrow> p \<le> p') *)
|
neuper@48830
|
194 |
function next_prime_not_dvd :: "nat \<Rightarrow> nat \<Rightarrow> nat" (infixl "next'_prime'_not'_dvd" 70) where
|
neuper@48827
|
195 |
"n1 next_prime_not_dvd n2 =
|
neuper@48827
|
196 |
(let
|
neuper@48827
|
197 |
ps = primes_upto (n1 + 1);
|
neuper@48831
|
198 |
nxt = List.nth ps (List.length ps - 1) (* take_last *)
|
neuper@48827
|
199 |
in
|
neuper@48827
|
200 |
if n2 mod nxt \<noteq> 0
|
neuper@48827
|
201 |
then nxt
|
neuper@48827
|
202 |
else nxt next_prime_not_dvd n2)"
|
neuper@48837
|
203 |
by auto
|
neuper@48825
|
204 |
termination sorry
|
neuper@48830
|
205 |
|
neuper@48814
|
206 |
subsection {* auxiliary functions for univariate polynomials *}
|
neuper@48814
|
207 |
|
neuper@48815
|
208 |
(* not in List.thy, copy from library.ML *)
|
neuper@48815
|
209 |
fun nth_drop :: "nat \<Rightarrow> 'a list \<Rightarrow> 'a list" where
|
neuper@48815
|
210 |
"nth_drop n xs = List.take n xs @ List.drop (n + 1) xs"
|
neuper@48823
|
211 |
value "nth_drop 0 [] = []"
|
neuper@48823
|
212 |
value "nth_drop 0 [1, 2, 3::int] = [2, 3]"
|
neuper@48823
|
213 |
value "nth_drop 2 [1, 2, 3::int] = [1, 2]"
|
neuper@48823
|
214 |
value "nth_drop 77 [1, 2, 3::int] = [1, 2, 3]"
|
neuper@48814
|
215 |
|
neuper@48815
|
216 |
(* leading coefficient *)
|
neuper@48830
|
217 |
function lcoeff :: "unipoly \<Rightarrow> int" where
|
neuper@48830
|
218 |
"lcoeff uvp =
|
neuper@48815
|
219 |
(if List.nth uvp (List.length uvp - 1) \<noteq> 0
|
neuper@48815
|
220 |
then List.nth uvp (List.length uvp - 1)
|
neuper@48830
|
221 |
else lcoeff (nth_drop (List.length uvp - 1) uvp))"
|
neuper@48815
|
222 |
by auto
|
neuper@48815
|
223 |
termination sorry
|
neuper@48814
|
224 |
|
neuper@48830
|
225 |
value "lcoeff [3, 4, 5, 6] = 6"
|
neuper@48830
|
226 |
value "lcoeff [3, 4, 5, 6, 0] = 6"
|
neuper@48814
|
227 |
|
neuper@48815
|
228 |
(* degree *)
|
neuper@48815
|
229 |
function deg :: "unipoly \<Rightarrow> nat" where
|
neuper@48815
|
230 |
"deg uvp =
|
neuper@48837
|
231 |
(let len = List.length uvp - 1
|
neuper@48837
|
232 |
in
|
neuper@48837
|
233 |
if nth uvp len \<noteq> 0 then len else deg (nth_drop len uvp))"
|
neuper@48815
|
234 |
by auto
|
neuper@48815
|
235 |
termination sorry
|
neuper@48814
|
236 |
|
neuper@48823
|
237 |
value "deg [3, 4, 5, 6] = 3"
|
neuper@48823
|
238 |
value "deg [3, 4, 5, 6, 0] = 3"
|
neuper@48814
|
239 |
|
neuper@48815
|
240 |
(* drop leading coefficients equal 0 *)
|
neuper@48815
|
241 |
fun drop_lc0 :: "unipoly \<Rightarrow> unipoly" where
|
neuper@48815
|
242 |
"drop_lc0 [] = []"
|
neuper@48815
|
243 |
| "drop_lc0 uvp =
|
neuper@48815
|
244 |
(let l = List.length uvp - 1
|
neuper@48815
|
245 |
in
|
neuper@48815
|
246 |
if nth uvp l = 0
|
neuper@48815
|
247 |
then drop_lc0 (nth_drop l uvp)
|
neuper@48815
|
248 |
else uvp)"
|
neuper@48815
|
249 |
|
neuper@48823
|
250 |
value "drop_lc0 [0, 1, 2, 3, 4, 5, 0, 0] = [0, 1, 2, 3, 4, 5]"
|
neuper@48823
|
251 |
value "drop_lc0 [0, 1, 2, 3, 4, 5] = [0, 1, 2, 3, 4, 5]"
|
neuper@48815
|
252 |
|
neuper@48823
|
253 |
(* norm is just local to normalise *)
|
neuper@48815
|
254 |
fun norm :: "unipoly \<Rightarrow> unipoly \<Rightarrow> int (*nat?*) \<Rightarrow> int \<Rightarrow> nat \<Rightarrow> unipoly" where
|
neuper@48815
|
255 |
"norm pol nrm m lcp i =
|
neuper@48815
|
256 |
(if i = 0
|
neuper@48815
|
257 |
then [mod_div (nth pol i) lcp m] @ nrm
|
neuper@48815
|
258 |
else norm pol ([mod_div (nth pol i) lcp m] @ nrm) m lcp (i - 1))"
|
neuper@48836
|
259 |
(* normalise a unipoly such that lcoeff mod m = 1.
|
neuper@48817
|
260 |
normalise :: unipoly \<Rightarrow> nat \<Rightarrow> unipoly
|
neuper@48817
|
261 |
normalise [p_0, .., p_k] m = [q_0, .., q_k]
|
neuper@48817
|
262 |
assumes
|
neuper@48817
|
263 |
yields \<exists> t. 0 \<le> i \<le> k \<Rightarrow> (p_i * t) mod m = q_i \<and> (p_k * t) mod m = 1 *)
|
neuper@48815
|
264 |
fun normalise :: "unipoly \<Rightarrow> int (*nat?*) \<Rightarrow> unipoly" where
|
neuper@48815
|
265 |
"normalise p m =
|
neuper@48815
|
266 |
(let
|
neuper@48815
|
267 |
p = drop_lc0 p;
|
neuper@48830
|
268 |
lcp = lcoeff p
|
neuper@48815
|
269 |
in
|
neuper@48815
|
270 |
if List.length p = 0 then p else norm p [] m lcp (List.length p - 1))"
|
neuper@48815
|
271 |
|
neuper@48823
|
272 |
value "normalise [-18, -15, -20, 12, 20, -13, 2] 5 = [1, 0, 0, 1, 0, 1, 1]"
|
neuper@48823
|
273 |
value "normalise [9, 6, 3] 10 = [3, 2, 1]"
|
neuper@48815
|
274 |
|
neuper@48823
|
275 |
(* scalar multiplication, %* in GCD_Poly.thy *)
|
neuper@48817
|
276 |
fun mult_ups :: "unipoly \<Rightarrow> int \<Rightarrow> unipoly" (infixl "mult'_ups" 70) where
|
neuper@48831
|
277 |
"p mult_ups m = List.map (op * m) p"
|
neuper@48815
|
278 |
|
neuper@48823
|
279 |
value "[5, 4, 7, 8, 1] mult_ups 5 = [25, 20, 35, 40, 5]"
|
neuper@48823
|
280 |
value "[5, 4, -7, 8, -1] mult_ups 5 = [25, 20, -35, 40, -5]"
|
neuper@48815
|
281 |
|
neuper@48823
|
282 |
(* scalar divison, %/ in GCD_Poly.thy *)
|
neuper@48823
|
283 |
definition swapf :: "('a \<Rightarrow> 'b \<Rightarrow> 'c) \<Rightarrow> 'b \<Rightarrow> 'a \<Rightarrow> 'c" where
|
neuper@48815
|
284 |
"swapf f a b = f b a"
|
neuper@48823
|
285 |
definition div_ups :: "unipoly \<Rightarrow> int \<Rightarrow> unipoly" (infixl "div'_ups" 70) where
|
neuper@48817
|
286 |
"p div_ups m = map (swapf op div2 m) p"
|
neuper@48815
|
287 |
|
neuper@48823
|
288 |
value "[4, 3, 2, 5, 6] div_ups 3 = [1, 1, 0, 1, 2]"
|
neuper@48823
|
289 |
value "[4, 3, 2, 0] div_ups 3 = [1, 1, 0, 0]"
|
neuper@48815
|
290 |
|
neuper@48815
|
291 |
(* not in List.thy, copy from library.ML *)
|
neuper@48815
|
292 |
fun map2 :: "('a \<Rightarrow> 'b \<Rightarrow> 'c) \<Rightarrow> 'a list \<Rightarrow> 'b list \<Rightarrow> 'c list" where
|
neuper@48815
|
293 |
"map2 _ [] [] = []"
|
neuper@48815
|
294 |
| "map2 f (x # xs) (y # ys) = f x y # map2 f xs ys"
|
neuper@48815
|
295 |
| "map2 _ _ _ = []" (*raise ListPair.UnequalLengths*)
|
neuper@48815
|
296 |
|
neuper@48823
|
297 |
(* minus of polys, %-% in GCD_Poly.thy *)
|
neuper@48823
|
298 |
definition minus_up :: "unipoly \<Rightarrow> unipoly \<Rightarrow> unipoly" (infixl "minus'_up" 70) where
|
neuper@48817
|
299 |
"p1 minus_up p2 = map2 (op -) p1 p2"
|
neuper@48815
|
300 |
|
neuper@48823
|
301 |
value "[8, -7, 0, 1] minus_up [-2, 2, 3, 0] = [10, -9, -3, 1]"
|
neuper@48823
|
302 |
value "[8, 7, 6, 5, 4] minus_up [2, 2, 3, 1, 1] = [6, 5, 3, 4, 3]"
|
neuper@48815
|
303 |
|
neuper@48839
|
304 |
ML {*1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1*}
|
neuper@48839
|
305 |
|
neuper@48823
|
306 |
(* dvd for univariate polynomials *)
|
neuper@48837
|
307 |
(*---------------------------------------------------------------------------------------------
|
neuper@48837
|
308 |
declare [[simp_trace_depth_limit = 99]]
|
neuper@48837
|
309 |
declare [[simp_trace = true]]
|
neuper@48837
|
310 |
//===========================================================================================
|
neuper@48837
|
311 |
THIS IS THE GOAL as 'function'
|
neuper@48837
|
312 |
===========================================================================================
|
neuper@48837
|
313 |
function (sequential) dvd_up :: "unipoly \<Rightarrow> unipoly \<Rightarrow> bool" (infixl "dvd'_up" 70) where
|
neuper@48817
|
314 |
"[d] dvd_up [i] =
|
neuper@48817
|
315 |
(if (\<bar>d\<bar> \<le> \<bar>i\<bar>) & (i mod d = 0) then True else False)"
|
neuper@48837
|
316 |
| "d dvd_up p =
|
neuper@48817
|
317 |
(let
|
neuper@48817
|
318 |
d = drop_lc0 d;
|
neuper@48817
|
319 |
p = drop_lc0 p;
|
neuper@48817
|
320 |
d000 = (List.replicate (List.length p - List.length d) 0) @ d;
|
neuper@48830
|
321 |
quot = (lcoeff p) div2 (lcoeff d000);
|
neuper@48817
|
322 |
rest = drop_lc0 (p minus_up (d000 div_ups quot))
|
neuper@48817
|
323 |
in
|
neuper@48837
|
324 |
if rest = [] then True else
|
neuper@48837
|
325 |
if quot \<noteq> 0 & List.length d \<le> List.length rest
|
neuper@48817
|
326 |
then d dvd_up rest
|
neuper@48837
|
327 |
else False)"
|
neuper@48820
|
328 |
by pat_completeness auto
|
neuper@48817
|
329 |
termination sorry
|
neuper@48837
|
330 |
===========================================================================================//
|
neuper@48820
|
331 |
|
neuper@48837
|
332 |
//===========================================================================================
|
neuper@48837
|
333 |
futile trials
|
neuper@48837
|
334 |
===========================================================================================
|
neuper@48837
|
335 |
THIS PART WORKS:
|
neuper@48837
|
336 |
-------------------------------------------------------------------------------------------
|
neuper@48837
|
337 |
function dvd_up :: "unipoly \<Rightarrow> unipoly \<Rightarrow> bool" (infixl "dvd'_up" 70) where
|
neuper@48837
|
338 |
"d dvd_up p =
|
neuper@48837
|
339 |
(let
|
neuper@48837
|
340 |
d = drop_lc0 d;
|
neuper@48837
|
341 |
p = drop_lc0 p;
|
neuper@48837
|
342 |
d000 = (List.replicate (List.length p - List.length d) 0) @ d;
|
neuper@48837
|
343 |
quot = (lcoeff p) div2 (lcoeff d000);
|
neuper@48837
|
344 |
rest = drop_lc0 (p minus_up (d000 div_ups quot))
|
neuper@48837
|
345 |
in
|
neuper@48837
|
346 |
if rest = [] then True else
|
neuper@48837
|
347 |
if quot \<noteq> 0 & List.length d \<le> List.length rest
|
neuper@48837
|
348 |
then d dvd_up rest
|
neuper@48837
|
349 |
else False)"
|
neuper@48837
|
350 |
by pat_completeness auto
|
neuper@48837
|
351 |
termination sorry
|
neuper@48837
|
352 |
---------------------------------------------------------------------------------------------
|
neuper@48837
|
353 |
THIS PART ONLY WORKS AS 'fun' (because_vvv 'fun' completes the sequence of equations)
|
neuper@48837
|
354 |
---------------------------------------------------------------------------------------------
|
neuper@48837
|
355 |
function dvd_up :: "unipoly \<Rightarrow> unipoly \<Rightarrow> bool" (infixl "dvd'_up" 70) where
|
neuper@48837
|
356 |
"[d] dvd_up [i] =
|
neuper@48837
|
357 |
(if (\<bar>d\<bar> \<le> \<bar>i\<bar>) & (i mod d = 0) then True else False)"
|
neuper@48837
|
358 |
by pat_completeness auto
|
neuper@48837
|
359 |
termination sorry
|
neuper@48837
|
360 |
---------------------------------------------------------------------------------------------
|
neuper@48837
|
361 |
THIS IS THE GOAL as fun
|
neuper@48837
|
362 |
---------------------------------------------------------------------------------------------
|
neuper@48837
|
363 |
fun dvd_up :: "unipoly \<Rightarrow> unipoly \<Rightarrow> bool" (infixl "dvd'_up" 70) where
|
neuper@48837
|
364 |
"[d] dvd_up [i] =
|
neuper@48837
|
365 |
(if (\<bar>d\<bar> \<le> \<bar>i\<bar>) & (i mod d = 0) then True else False)"
|
neuper@48837
|
366 |
| "d dvd_up p =
|
neuper@48837
|
367 |
(let
|
neuper@48837
|
368 |
d = drop_lc0 d;
|
neuper@48837
|
369 |
p = drop_lc0 p;
|
neuper@48837
|
370 |
d000 = (List.replicate (List.length p - List.length d) 0) @ d;
|
neuper@48837
|
371 |
quot = (lcoeff p) div2 (lcoeff d000);
|
neuper@48837
|
372 |
rest = drop_lc0 (p minus_up (d000 div_ups quot))
|
neuper@48837
|
373 |
in
|
neuper@48837
|
374 |
if rest = [] then True else
|
neuper@48837
|
375 |
if quot \<noteq> 0 & List.length d \<le> List.length rest
|
neuper@48837
|
376 |
then d dvd_up rest
|
neuper@48837
|
377 |
else False)"
|
neuper@48837
|
378 |
---------------------------------------------------------------------------------------------
|
neuper@48837
|
379 |
THIS WORKS
|
neuper@48837
|
380 |
---------------------------------------------------------------------------------------------
|
neuper@48837
|
381 |
fun dvd_up :: "unipoly \<Rightarrow> unipoly \<Rightarrow> bool" (infixl "dvd'_up" 70) where
|
neuper@48837
|
382 |
"[d] dvd_up [i] =
|
neuper@48837
|
383 |
(if (\<bar>d\<bar> \<le> \<bar>i\<bar>) & (i mod d = 0) then True else False)"
|
neuper@48837
|
384 |
| "d dvd_up p = True" (*<<<######################################*)
|
neuper@48837
|
385 |
---------------------------------------------------------------------------------------------
|
neuper@48837
|
386 |
THIS WORKS
|
neuper@48837
|
387 |
---------------------------------------------------------------------------------------------
|
neuper@48837
|
388 |
fun dvd_up :: "unipoly \<Rightarrow> unipoly \<Rightarrow> bool" (infixl "dvd'_up" 70) where
|
neuper@48837
|
389 |
"[d] dvd_up [i] =
|
neuper@48837
|
390 |
(if (\<bar>d\<bar> \<le> \<bar>i\<bar>) & (i mod d = 0) then True else False)"
|
neuper@48837
|
391 |
| "d dvd_up p =
|
neuper@48837
|
392 |
(let
|
neuper@48837
|
393 |
d = drop_lc0 d;
|
neuper@48837
|
394 |
p = drop_lc0 p;
|
neuper@48837
|
395 |
d000 = (List.replicate (List.length p - List.length d) 0) @ d;
|
neuper@48837
|
396 |
quot = (lcoeff p) div2 (lcoeff d000);
|
neuper@48837
|
397 |
rest = drop_lc0 (p minus_up (d000 div_ups quot))
|
neuper@48837
|
398 |
in True)" (*<<<######################################*)
|
neuper@48837
|
399 |
---------------------------------------------------------------------------------------------
|
neuper@48837
|
400 |
THIS LOOPS
|
neuper@48837
|
401 |
---------------------------------------------------------------------------------------------
|
neuper@48837
|
402 |
function dvd_up :: "unipoly \<Rightarrow> unipoly \<Rightarrow> bool" (infixl "dvd'_up" 70) where
|
neuper@48837
|
403 |
"[d] dvd_up [i] =
|
neuper@48837
|
404 |
(if (\<bar>d\<bar> \<le> \<bar>i\<bar>) & (i mod d = 0) then True else False)"
|
neuper@48837
|
405 |
| "d dvd_up p =
|
neuper@48837
|
406 |
(let
|
neuper@48837
|
407 |
d = drop_lc0 d;
|
neuper@48837
|
408 |
p = drop_lc0 p;
|
neuper@48837
|
409 |
d000 = (List.replicate (List.length p - List.length d) 0) @ d;
|
neuper@48837
|
410 |
quot = (lcoeff p) div2 (lcoeff d000);
|
neuper@48837
|
411 |
rest = drop_lc0 (p minus_up (d000 div_ups quot))
|
neuper@48837
|
412 |
in
|
neuper@48837
|
413 |
if rest = [] then True else
|
neuper@48837
|
414 |
False)" (*<<<######################################*)
|
neuper@48837
|
415 |
apply pat_completeness
|
neuper@48837
|
416 |
---------------------------------------------------------------------------------------------
|
neuper@48837
|
417 |
(sequential) blows up the number of equations; proving compatibility of patterns not simpler:
|
neuper@48837
|
418 |
---------------------------------------------------------------------------------------------
|
neuper@48837
|
419 |
function (sequential) dvd_up :: "unipoly \<Rightarrow> unipoly \<Rightarrow> bool" (infixl "dvd'_up" 70) where
|
neuper@48837
|
420 |
"[d] dvd_up [i] =
|
neuper@48837
|
421 |
(if (\<bar>d\<bar> \<le> \<bar>i\<bar>) & (i mod d = 0) then True else False)"
|
neuper@48837
|
422 |
| "d dvd_up p =
|
neuper@48837
|
423 |
(let
|
neuper@48837
|
424 |
d = drop_lc0 d;
|
neuper@48837
|
425 |
p = drop_lc0 p;
|
neuper@48837
|
426 |
d000 = (List.replicate (List.length p - List.length d) 0) @ d;
|
neuper@48837
|
427 |
quot = (lcoeff p) div2 (lcoeff d000);
|
neuper@48837
|
428 |
rest = drop_lc0 (p minus_up (d000 div_ups quot))
|
neuper@48837
|
429 |
in
|
neuper@48837
|
430 |
if rest = [] then True else
|
neuper@48837
|
431 |
if quot \<noteq> 0 & List.length d \<le> List.length rest
|
neuper@48837
|
432 |
then d dvd_up rest
|
neuper@48837
|
433 |
else False)"
|
neuper@48837
|
434 |
using [[simp_trace_depth_limit = 99]]
|
neuper@48837
|
435 |
using [[simp_trace = true]]
|
neuper@48837
|
436 |
(*separating provers like that: functions.pdf p.10, with (sequential), see functions.pdf p.10*)
|
neuper@48837
|
437 |
apply pat_completeness (*resolves subgoal 1. (out of 16) on 'completeness of patterns',
|
neuper@48837
|
438 |
see \<section>3.2 Completeness and Compatibility in Alexander Krauss, Partial Recursive Functions in Higher-Order Logic
|
neuper@48837
|
439 |
leaves 15 subgoals on 'compatibility of patterns':
|
neuper@48837
|
440 |
goal (15 subgoals):
|
neuper@48837
|
441 |
1. \<And>d i da ia. ([d], [i]) = ([da], [ia]) \<Longrightarrow> (if \<bar>d\<bar> \<le> \<bar>i\<bar> \<and> i mod d = 0 then True else False) = (if \<bar>da\<bar> \<le> \<bar>ia\<bar> \<and> ia mod da = 0 then True else False)
|
neuper@48837
|
442 |
2. \<And>d i p. ([d], [i]) = ([], p) \<Longrightarrow> (if \<bar>d\<bar> \<le> \<bar>i\<bar> \<and> i mod d = 0 then True else False) = (let d = drop_lc0 []; p = drop_lc0 p; d000 = replicate (length p - length d) 0 @ d; quot = lcoeff p div2 lcoeff d000; rest = drop_lc0 (p minus_up (d000 div_ups quot)) in if rest = [] then True else if quot \<noteq> 0 \<and> length d \<le> length rest then dvd_up_sumC (d, rest) else False)
|
neuper@48837
|
443 |
3. \<And>d i v vb vc p. ([d], [i]) = (v # vb # vc, p) \<Longrightarrow> (if \<bar>d\<bar> \<le> \<bar>i\<bar> \<and> i mod d = 0 then True else False) = (let d = drop_lc0 (v # vb # vc); p = drop_lc0 p; d000 = replicate (length p - length d) 0 @ d; quot = lcoeff p div2 lcoeff d000; rest = drop_lc0 (p minus_up (d000 div_ups quot)) in if rest = [] then True else if quot \<noteq> 0 \<and> length d \<le> length rest then dvd_up_sumC (d, rest) else False)
|
neuper@48837
|
444 |
4. \<And>d i da. ([d], [i]) = (da, []) \<Longrightarrow> (if \<bar>d\<bar> \<le> \<bar>i\<bar> \<and> i mod d = 0 then True else False) = (let d = drop_lc0 da; p = drop_lc0 []; d000 = replicate (length p - length d) 0 @ d; quot = lcoeff p div2 lcoeff d000; rest = drop_lc0 (p minus_up (d000 div_ups quot)) in if rest = [] then True else if quot \<noteq> 0 \<and> length d \<le> length rest then dvd_up_sumC (d, rest) else False)
|
neuper@48837
|
445 |
5. \<And>d i da v vb vc. ([d], [i]) = (da, v # vb # vc) \<Longrightarrow> (if \<bar>d\<bar> \<le> \<bar>i\<bar> \<and> i mod d = 0 then True else False) = (let d = drop_lc0 da; p = drop_lc0 (v # vb # vc); d000 = replicate (length p - length d) 0 @ d; quot = lcoeff p div2 lcoeff d000; rest = drop_lc0 (p minus_up (d000 div_ups quot)) in if rest = [] then True else if quot \<noteq> 0 \<and> length d \<le> length rest then dvd_up_sumC (d, rest) else False)
|
neuper@48837
|
446 |
6. \<And>p pa. ([], p) = ([], pa) \<Longrightarrow> (let d = drop_lc0 []; p = drop_lc0 p; d000 = replicate (length p - length d) 0 @ d; quot = lcoeff p div2 lcoeff d000; rest = drop_lc0 (p minus_up (d000 div_ups quot)) in if rest = [] then True else if quot \<noteq> 0 \<and> length d \<le> length rest then dvd_up_sumC (d, rest) else False) = (let d = drop_lc0 []; p = drop_lc0 pa; d000 = replicate (length p - length d) 0 @ d; quot = lcoeff p div2 lcoeff d000; rest = drop_lc0 (p minus_up (d000 div_ups quot)) in if rest = [] then True else if quot \<noteq> 0 \<and> length d \<le> length rest then dvd_up_sumC (d, rest) else False)
|
neuper@48837
|
447 |
7. \<And>p v vb vc pa. ([], p) = (v # vb # vc, pa) \<Longrightarrow> (let d = drop_lc0 []; p = drop_lc0 p; d000 = replicate (length p - length d) 0 @ d; quot = lcoeff p div2 lcoeff d000; rest = drop_lc0 (p minus_up (d000 div_ups quot)) in if rest = [] then True else if quot \<noteq> 0 \<and> length d \<le> length rest then dvd_up_sumC (d, rest) else False) = (let d = drop_lc0 (v # vb # vc); p = drop_lc0 pa; d000 = replicate (length p - length d) 0 @ d; quot = lcoeff p div2 lcoeff d000; rest = drop_lc0 (p minus_up (d000 div_ups quot)) in if rest = [] then True else if quot \<noteq> 0 \<and> length d \<le> length rest then dvd_up_sumC (d, rest) else False)
|
neuper@48837
|
448 |
8. \<And>p d. ([], p) = (d, []) \<Longrightarrow> (let d = drop_lc0 []; p = drop_lc0 p; d000 = replicate (length p - length d) 0 @ d; quot = lcoeff p div2 lcoeff d000; rest = drop_lc0 (p minus_up (d000 div_ups quot)) in if rest = [] then True else if quot \<noteq> 0 \<and> length d \<le> length rest then dvd_up_sumC (d, rest) else False) = (let d = drop_lc0 d; p = drop_lc0 []; d000 = replicate (length p - length d) 0 @ d; quot = lcoeff p div2 lcoeff d000; rest = drop_lc0 (p minus_up (d000 div_ups quot)) in if rest = [] then True else if quot \<noteq> 0 \<and> length d \<le> length rest then dvd_up_sumC (d, rest) else False)
|
neuper@48837
|
449 |
9. \<And>p d v vb vc. ([], p) = (d, v # vb # vc) \<Longrightarrow> (let d = drop_lc0 []; p = drop_lc0 p; d000 = replicate (length p - length d) 0 @ d; quot = lcoeff p div2 lcoeff d000; rest = drop_lc0 (p minus_up (d000 div_ups quot)) in if rest = [] then True else if quot \<noteq> 0 \<and> length d \<le> length rest then dvd_up_sumC (d, rest) else False) = (let d = drop_lc0 d; p = drop_lc0 (v # vb # vc); d000 = replicate (length p - length d) 0 @ d; quot = lcoeff p div2 lcoeff d000; rest = drop_lc0 (p minus_up (d000 div_ups quot)) in if rest = [] then True else if quot \<noteq> 0 \<and> length d \<le> length rest then dvd_up_sumC (d, rest) else False)
|
neuper@48837
|
450 |
10. \<And>v vb vc p va vba vca pa. (v # vb # vc, p) = (va # vba # vca, pa) \<Longrightarrow> (let d = drop_lc0 (v # vb # vc); p = drop_lc0 p; d000 = replicate (length p - length d) 0 @ d; quot = lcoeff p div2 lcoeff d000; rest = drop_lc0 (p minus_up (d000 div_ups quot)) in if rest = [] then True else if quot \<noteq> 0 \<and> length d \<le> length rest then dvd_up_sumC (d, rest) else False) = (let d = drop_lc0 (va # vba # vca); p = drop_lc0 pa; d000 = replicate (length p - length d) 0 @ d; quot = lcoeff p div2 lcoeff d000; rest = drop_lc0 (p minus_up (d000 div_ups quot)) in if rest = [] then True else if quot \<noteq> 0 \<and> length d \<le> length rest then dvd_up_sumC (d, rest) else False)
|
neuper@48837
|
451 |
A total of 15 subgoals... *)
|
neuper@48827
|
452 |
|
neuper@48837
|
453 |
(*by auto ..LOOPS*)
|
neuper@48837
|
454 |
apply simp (*goal (14 subgoals): ^2. = 1. \<And>d i p. ([d], [i]) = ([], p) \<Longrightarrow> *)
|
neuper@48837
|
455 |
apply simp (*goal (13 subgoals): ^3. = 1. \<And>d i v vb vc p. ([d], [i]) = (v # vb # vc, p) \<Longrightarrow> *)
|
neuper@48837
|
456 |
(*apply simp LOOPS: ^4. \<And>d i da. ([d], [i]) = (da, []) \<Longrightarrow>*)
|
neuper@48837
|
457 |
defer (*goal (13 subgoals): ^4 = 1. \<And>d i da. ([d], [i]) = (da, []) \<Longrightarrow> *)
|
neuper@48837
|
458 |
apply simp (*goal (12 subgoals): ^5 = 1. \<And>d i da v vb vc. ([d], [i]) = (da, v # vb # vc) \<Longrightarrow> *)
|
neuper@48837
|
459 |
(*apply simp LOOPS*)
|
neuper@48837
|
460 |
defer (*goal (12 subgoals): ^6 = 1. \<And>p pa. ([], p) = ([], pa) \<Longrightarrow> *)
|
neuper@48837
|
461 |
apply simp (*goal (11 subgoals): 1. \<And>p v vb vc pa. ([], p) = (v # vb # vc, pa) \<Longrightarrow> *)
|
neuper@48837
|
462 |
(*apply simp LOOPS*)
|
neuper@48837
|
463 |
defer
|
neuper@48837
|
464 |
apply simp (*goal (10 subgoals): 1. \<And>p d v vb vc. ([], p) = (d, v # vb # vc) \<Longrightarrow> *)
|
neuper@48837
|
465 |
apply simp (*goal (9 subgoals): 1. \<And>v vb vc p va vba vca pa. (v # vb # vc, p) = (va ..*)
|
neuper@48837
|
466 |
apply simp (*goal (8 subgoals): 1. \<And>v vb vc p d. (v # vb # vc, p) = (d, []) \<Longrightarrow> *)
|
neuper@48837
|
467 |
apply simp (*goal (7 subgoals): 1. \<And>v vb vc p d va vba vca. (v # vb # vc, p) = (d, va ..*)
|
neuper@48837
|
468 |
apply simp (*goal (6 subgoals): 1. \<And>d da. (d, []) = (da, []) \<Longrightarrow> *)
|
neuper@48837
|
469 |
apply simp (*goal (5 subgoals): 1. \<And>d da v vb vc. (d, []) = (da, v # vb # vc) \<Longrightarrow> *)
|
neuper@48837
|
470 |
(*apply simp LOOPS*)
|
neuper@48837
|
471 |
defer
|
neuper@48837
|
472 |
apply simp (*goal (4 subgoals): 1. \<And>d i v vb vc p. ([d], [i]) = (v # vb # vc, p) \<Longrightarrow> *)
|
neuper@48837
|
473 |
(*apply simp LOOPS --- these are the 4 looping subgoals cp from above
|
neuper@48837
|
474 |
*)
|
neuper@48837
|
475 |
sorry
|
neuper@48837
|
476 |
===========================================================================================//
|
neuper@48827
|
477 |
|
neuper@48837
|
478 |
//===========================================================================================
|
neuper@48837
|
479 |
looking at proof obligations from pattern completeness and pattern compatibility.
|
neuper@48837
|
480 |
===========================================================================================
|
neuper@48837
|
481 |
separate provers by 'apply'
|
neuper@48837
|
482 |
---------------------------------------------------------------------------------------------
|
neuper@48837
|
483 |
function dvd_up :: "unipoly \<Rightarrow> unipoly \<Rightarrow> bool" (infixl "dvd'_up" 70) where
|
neuper@48837
|
484 |
"[d] dvd_up [i] =
|
neuper@48837
|
485 |
(if (\<bar>d\<bar> \<le> \<bar>i\<bar>) & (i mod d = 0) then True else False)"
|
neuper@48837
|
486 |
| "d dvd_up p =
|
neuper@48837
|
487 |
(let
|
neuper@48837
|
488 |
d = drop_lc0 d;
|
neuper@48837
|
489 |
p = drop_lc0 p;
|
neuper@48837
|
490 |
d000 = (List.replicate (List.length p - List.length d) 0) @ d;
|
neuper@48837
|
491 |
quot = (lcoeff p) div2 (lcoeff d000);
|
neuper@48837
|
492 |
rest = drop_lc0 (p minus_up (d000 div_ups quot))
|
neuper@48837
|
493 |
in
|
neuper@48837
|
494 |
if rest = [] then True else
|
neuper@48837
|
495 |
if quot \<noteq> 0 & List.length d \<le> List.length rest
|
neuper@48837
|
496 |
then d dvd_up rest
|
neuper@48837
|
497 |
else False)"
|
neuper@48837
|
498 |
using [[simp_trace_depth_limit = 99]]
|
neuper@48837
|
499 |
using [[simp_trace = true]]
|
neuper@48837
|
500 |
(*goal (4 subgoals): #1 is completeness of patterns
|
neuper@48837
|
501 |
1. \<And>P x. (\<And>d i. x = ([d], [i]) \<Longrightarrow> P) \<Longrightarrow> (\<And>d p. x = (d, p) \<Longrightarrow> P) \<Longrightarrow> P
|
neuper@48837
|
502 |
2. \<And>d i da ia. ([d], [i]) = ([da], [ia]) \<Longrightarrow> (if \<bar>d\<bar> \<le> \<bar>i\<bar> \<and> i mod d = 0 then True else False) = (if \<bar>da\<bar> \<le> \<bar>ia\<bar> \<and> ia mod da = 0 then True else False)
|
neuper@48837
|
503 |
3. \<And>d i da p. ([d], [i]) = (da, p) \<Longrightarrow> (if \<bar>d\<bar> \<le> \<bar>i\<bar> \<and> i mod d = 0 then True else False) = (let d = drop_lc0 da; p = drop_lc0 p; d000 = replicate (length p - length d) 0 @ d; quot = lcoeff p div2 lcoeff d000; rest = drop_lc0 (p minus_up (d000 div_ups quot)) in if rest = [] then True else if quot \<noteq> 0 \<and> length d \<le> length rest then dvd_up_sumC (d, rest) else False)
|
neuper@48837
|
504 |
4. \<And>d p da pa. (d, p) = (da, pa) \<Longrightarrow> (let d = drop_lc0 d; p = drop_lc0 p; d000 = replicate (length p - length d) 0 @ d; quot = lcoeff p div2 lcoeff d000; rest = drop_lc0 (p minus_up (d000 div_ups quot)) in if rest = [] then True else if quot \<noteq> 0 \<and> length d \<le> length rest then dvd_up_sumC (d, rest) else False) = (let d = drop_lc0 da; p = drop_lc0 pa; d000 = replicate (length p - length d) 0 @ d; quot = lcoeff p div2 lcoeff d000; rest = drop_lc0 (p minus_up (d000 div_ups quot)) in if rest = [] then True else if quot \<noteq> 0 \<and> length d \<le> length rest then dvd_up_sumC (d, rest) else False) *)
|
neuper@48837
|
505 |
apply pat_completeness
|
neuper@48837
|
506 |
(*goal (3 subgoals): #1-3 compatibility of patterns
|
neuper@48837
|
507 |
1. \<And>d i da ia. ([d], [i]) = ([da], [ia]) \<Longrightarrow> (if \<bar>d\<bar> \<le> \<bar>i\<bar> \<and> i mod d = 0 then True else False) = (if \<bar>da\<bar> \<le> \<bar>ia\<bar> \<and> ia mod da = 0 then True else False)
|
neuper@48837
|
508 |
2. \<And>d i da p. ([d], [i]) = (da, p) \<Longrightarrow> (if \<bar>d\<bar> \<le> \<bar>i\<bar> \<and> i mod d = 0 then True else False) = (let d = drop_lc0 da; p = drop_lc0 p; d000 = replicate (length p - length d) 0 @ d; quot = lcoeff p div2 lcoeff d000; rest = drop_lc0 (p minus_up (d000 div_ups quot)) in if rest = [] then True else if quot \<noteq> 0 \<and> length d \<le> length rest then dvd_up_sumC (d, rest) else False)
|
neuper@48837
|
509 |
3. \<And>d p da pa. (d, p) = (da, pa) \<Longrightarrow> (let d = drop_lc0 d; p = drop_lc0 p; d000 = replicate (length p - length d) 0 @ d; quot = lcoeff p div2 lcoeff d000; rest = drop_lc0 (p minus_up (d000 div_ups quot)) in if rest = [] then True else if quot \<noteq> 0 \<and> length d \<le> length rest then dvd_up_sumC (d, rest) else False) = (let d = drop_lc0 da; p = drop_lc0 pa; d000 = replicate (length p - length d) 0 @ d; quot = lcoeff p div2 lcoeff d000; rest = drop_lc0 (p minus_up (d000 div_ups quot)) in if rest = [] then True else if quot \<noteq> 0 \<and> length d \<le> length rest then dvd_up_sumC (d, rest) else False) *)
|
neuper@48837
|
510 |
apply simp (*goal (2 subgoals):
|
neuper@48837
|
511 |
1. \<And>d i da p. ([d], [i]) = (da, p) \<Longrightarrow> (if \<bar>d\<bar> \<le> \<bar>i\<bar> \<and> i mod d = 0 then True else False) = (let d = drop_lc0 da; p = drop_lc0 p; d000 = replicate (length p - length d) 0 @ d; quot = lcoeff p div2 lcoeff d000; rest = drop_lc0 (p minus_up (d000 div_ups quot)) in if rest = [] then True else if quot \<noteq> 0 \<and> length d \<le> length rest then dvd_up_sumC (d, rest) else False)
|
neuper@48837
|
512 |
2. \<And>d p da pa. (d, p) = (da, pa) \<Longrightarrow> (let d = drop_lc0 d; p = drop_lc0 p; d000 = replicate (length p - length d) 0 @ d; quot = lcoeff p div2 lcoeff d000; rest = drop_lc0 (p minus_up (d000 div_ups quot)) in if rest = [] then True else if quot \<noteq> 0 \<and> length d \<le> length rest then dvd_up_sumC (d, rest) else False) = (let d = drop_lc0 da; p = drop_lc0 pa; d000 = replicate (length p - length d) 0 @ d; quot = lcoeff p div2 lcoeff d000; rest = drop_lc0 (p minus_up (d000 div_ups quot)) in if rest = [] then True else if quot \<noteq> 0 \<and> length d \<le> length rest then dvd_up_sumC (d, rest) else False) *)
|
neuper@48837
|
513 |
(*apply simp ...LOOPS*)
|
neuper@48837
|
514 |
defer
|
neuper@48837
|
515 |
apply simp (*goal (1 subgoal): <<<################ this took very long, on the largest subgoa)
|
neuper@48837
|
516 |
goal (1 subgoal):
|
neuper@48837
|
517 |
1. \<And>d i da p. ([d], [i]) = (da, p) \<Longrightarrow>
|
neuper@48837
|
518 |
(if \<bar>d\<bar> \<le> \<bar>i\<bar> \<and> i mod d = 0 then True else False) =
|
neuper@48837
|
519 |
(let d = drop_lc0 da; p = drop_lc0 p; d000 = replicate (length p - length d) 0 @ d; quot = lcoeff p div2 lcoeff d000; rest = drop_lc0 (p minus_up (d000 div_ups quot))
|
neuper@48837
|
520 |
in if rest = [] then True else if quot \<noteq> 0 \<and> length d \<le> length rest then dvd_up_sumC (d, rest) else False)
|
neuper@48837
|
521 |
... this subgoal relates equation 1 and 2, and appears provable only with deep math knowledge.*)
|
neuper@48837
|
522 |
sorry
|
neuper@48837
|
523 |
===========================================================================================//
|
neuper@48837
|
524 |
|
neuper@48837
|
525 |
//===========================================================================================
|
neuper@48837
|
526 |
The above conclusion about 'not provable' originated from trials in Try_Funktions.thy.
|
neuper@48837
|
527 |
These trials provided hints on how to complete equations wrt. patterns on the lhs.
|
neuper@48837
|
528 |
===========================================================================================//
|
neuper@48837
|
529 |
|
neuper@48837
|
530 |
//===========================================================================================
|
neuper@48837
|
531 |
complete sequence of equations wrt. patterns on the lhs.
|
neuper@48837
|
532 |
===========================================================================================
|
neuper@48837
|
533 |
1st trial --> 4 unsolvable subgoals
|
neuper@48837
|
534 |
-------------------------------------------------------------------------------------------
|
neuper@48837
|
535 |
function dvd_up :: "unipoly \<Rightarrow> unipoly \<Rightarrow> bool" (infixl "dvd'_up" 70) where
|
neuper@48837
|
536 |
"[] dvd_up [] = False"
|
neuper@48837
|
537 |
| "[] dvd_up p = False"
|
neuper@48837
|
538 |
| "d dvd_up [] = False"
|
neuper@48837
|
539 |
| "[d] dvd_up [i] =
|
neuper@48837
|
540 |
(if (\<bar>d\<bar> \<le> \<bar>i\<bar>) & (i mod d = 0) then True else False)"
|
neuper@48837
|
541 |
| "d dvd_up p =
|
neuper@48837
|
542 |
(let
|
neuper@48837
|
543 |
d = drop_lc0 d;
|
neuper@48837
|
544 |
p = drop_lc0 p;
|
neuper@48837
|
545 |
d000 = (List.replicate (List.length p - List.length d) 0) @ d;
|
neuper@48837
|
546 |
quot = (lcoeff p) div2 (lcoeff d000);
|
neuper@48837
|
547 |
rest = drop_lc0 (p minus_up (d000 div_ups quot))
|
neuper@48837
|
548 |
in
|
neuper@48837
|
549 |
if rest = [] then True else
|
neuper@48837
|
550 |
if quot \<noteq> 0 & List.length d \<le> List.length rest
|
neuper@48837
|
551 |
then d dvd_up rest
|
neuper@48837
|
552 |
else False)"
|
neuper@48837
|
553 |
apply pat_completeness
|
neuper@48837
|
554 |
apply simp
|
neuper@48837
|
555 |
apply simp
|
neuper@48837
|
556 |
apply simp
|
neuper@48837
|
557 |
apply simp
|
neuper@48837
|
558 |
(*apply simp*)
|
neuper@48837
|
559 |
defer
|
neuper@48837
|
560 |
apply simp
|
neuper@48837
|
561 |
apply simp
|
neuper@48837
|
562 |
apply simp
|
neuper@48837
|
563 |
(*apply simp*)
|
neuper@48837
|
564 |
defer
|
neuper@48837
|
565 |
apply simp
|
neuper@48837
|
566 |
apply simp
|
neuper@48837
|
567 |
(*apply simp*)
|
neuper@48837
|
568 |
defer
|
neuper@48837
|
569 |
apply simp
|
neuper@48837
|
570 |
(*apply simp*)
|
neuper@48837
|
571 |
defer
|
neuper@48837
|
572 |
apply simp (*this was the last successful apply*)
|
neuper@48837
|
573 |
(*goal (4 subgoals):
|
neuper@48837
|
574 |
1. \<And>d p. ([], []) = (d, p) \<Longrightarrow>
|
neuper@48837
|
575 |
False = (let d = drop_lc0 d; p = drop_lc0 p; d000 = replicate (length p - length d) 0 @ d; quot = lcoeff p div2 lcoeff d000; rest = drop_lc0 (p minus_up (d000 div_ups quot))
|
neuper@48837
|
576 |
in if rest = [] then True else if quot \<noteq> 0 \<and> length d \<le> length rest then dvd_up_sumC (d, rest) else False)
|
neuper@48837
|
577 |
2. \<And>p d pa. ([], p) = (d, pa) \<Longrightarrow>
|
neuper@48837
|
578 |
False = (let d = drop_lc0 d; p = drop_lc0 pa; d000 = replicate (length p - length d) 0 @ d; quot = lcoeff p div2 lcoeff d000; rest = drop_lc0 (p minus_up (d000 div_ups quot))
|
neuper@48837
|
579 |
in if rest = [] then True else if quot \<noteq> 0 \<and> length d \<le> length rest then dvd_up_sumC (d, rest) else False)
|
neuper@48837
|
580 |
3. \<And>d da p. (d, []) = (da, p) \<Longrightarrow>
|
neuper@48837
|
581 |
False = (let d = drop_lc0 da; p = drop_lc0 p; d000 = replicate (length p - length d) 0 @ d; quot = lcoeff p div2 lcoeff d000; rest = drop_lc0 (p minus_up (d000 div_ups quot))
|
neuper@48837
|
582 |
in if rest = [] then True else if quot \<noteq> 0 \<and> length d \<le> length rest then dvd_up_sumC (d, rest) else False)
|
neuper@48837
|
583 |
4. \<And>d i da p. ([d], [i]) = (da, p) \<Longrightarrow>
|
neuper@48837
|
584 |
(if \<bar>d\<bar> \<le> \<bar>i\<bar> \<and> i mod d = 0 then True else False) =
|
neuper@48837
|
585 |
(let d = drop_lc0 da; p = drop_lc0 p; d000 = replicate (length p - length d) 0 @ d; quot = lcoeff p div2 lcoeff d000; rest = drop_lc0 (p minus_up (d000 div_ups quot))
|
neuper@48837
|
586 |
in if rest = [] then True else if quot \<noteq> 0 \<and> length d \<le> length rest then dvd_up_sumC (d, rest) else False) *)
|
neuper@48837
|
587 |
-------------------------------------------------------------------------------------------
|
neuper@48839
|
588 |
2nd trial --> 3 unsolvable subgoals on compatiblity of patterns
|
neuper@48837
|
589 |
-------------------------------------------------------------------------------------------
|
neuper@48837
|
590 |
function dvd_up :: "unipoly \<Rightarrow> unipoly \<Rightarrow> bool" (infixl "dvd'_up" 70) where
|
neuper@48837
|
591 |
"[] dvd_up p = False"
|
neuper@48837
|
592 |
| "d dvd_up [] = False"
|
neuper@48837
|
593 |
| "[d] dvd_up [i] =
|
neuper@48837
|
594 |
(if (\<bar>d\<bar> \<le> \<bar>i\<bar>) & (i mod d = 0) then True else False)"
|
neuper@48837
|
595 |
| "d dvd_up p =
|
neuper@48837
|
596 |
(let
|
neuper@48837
|
597 |
d = drop_lc0 d;
|
neuper@48837
|
598 |
p = drop_lc0 p;
|
neuper@48837
|
599 |
d000 = (List.replicate (List.length p - List.length d) 0) @ d;
|
neuper@48837
|
600 |
quot = (lcoeff p) div2 (lcoeff d000);
|
neuper@48837
|
601 |
rest = drop_lc0 (p minus_up (d000 div_ups quot))
|
neuper@48837
|
602 |
in
|
neuper@48837
|
603 |
if rest = [] then True else
|
neuper@48837
|
604 |
if quot \<noteq> 0 & List.length d \<le> List.length rest
|
neuper@48837
|
605 |
then d dvd_up rest
|
neuper@48837
|
606 |
else False)"
|
neuper@48837
|
607 |
apply pat_completeness
|
neuper@48837
|
608 |
apply simp
|
neuper@48837
|
609 |
apply simp
|
neuper@48837
|
610 |
apply simp
|
neuper@48837
|
611 |
defer
|
neuper@48837
|
612 |
apply simp
|
neuper@48837
|
613 |
apply simp
|
neuper@48837
|
614 |
defer
|
neuper@48837
|
615 |
apply simp
|
neuper@48837
|
616 |
defer
|
neuper@48837
|
617 |
apply simp
|
neuper@48837
|
618 |
(*goal (3 subgoals): ### the 1st subgoals disappears, the others are the same
|
neuper@48837
|
619 |
1. \<And>p d pa. ([], p) = (d, pa) \<Longrightarrow>
|
neuper@48837
|
620 |
False = (let d = drop_lc0 d; p = drop_lc0 pa; d000 = replicate (length p - length d) 0 @ d; quot = lcoeff p div2 lcoeff d000; rest = drop_lc0 (p minus_up (d000 div_ups quot))
|
neuper@48839
|
621 |
in if rest = [] then True else if quot \<noteq> 0 \<and> replicate length d \<le> length rest then dvd_up_sumC (d, rest) else False)
|
neuper@48837
|
622 |
2. \<And>d da p. (d, []) = (da, p) \<Longrightarrow>
|
neuper@48837
|
623 |
False = (let d = drop_lc0 da; p = drop_lc0 p; d000 = replicate (length p - length d) 0 @ d; quot = lcoeff p div2 lcoeff d000; rest = drop_lc0 (p minus_up (d000 div_ups quot))
|
neuper@48837
|
624 |
in if rest = [] then True else if quot \<noteq> 0 \<and> length d \<le> length rest then dvd_up_sumC (d, rest) else False)
|
neuper@48837
|
625 |
3. \<And>d i da p. ([d], [i]) = (da, p) \<Longrightarrow>
|
neuper@48837
|
626 |
(if \<bar>d\<bar> \<le> \<bar>i\<bar> \<and> i mod d = 0 then True else False) =
|
neuper@48837
|
627 |
(let d = drop_lc0 da; p = drop_lc0 p; d000 = replicate (length p - length d) 0 @ d; quot = lcoeff p div2 lcoeff d000; rest = drop_lc0 (p minus_up (d000 div_ups quot))
|
neuper@48839
|
628 |
in if rest = [] then True else if quot \<noteq> 0 \<and> length d \<le> length rest then dvd_up_sumC (d, rest) else False)
|
neuper@48839
|
629 |
---------------------------------------------------------------------------------------------
|
neuper@48839
|
630 |
but completing the sequence of equations doesn't help,
|
neuper@48839
|
631 |
because the most difficult subgoal (3. above, 4. above above) remains the same.
|
neuper@48839
|
632 |
---------------------------------------------------------------------------------------------
|
neuper@48839
|
633 |
*)
|
neuper@48839
|
634 |
------------------------------GCD_Poly ML-->Isabelle:-------------------------------------------*)
|
neuper@48839
|
635 |
function dvd_up :: "unipoly \<Rightarrow> unipoly \<Rightarrow> bool" (infixl "dvd'_up" 70) where
|
neuper@48839
|
636 |
"[d] dvd_up [p] =
|
neuper@48839
|
637 |
(if (\<bar>d\<bar> \<le> \<bar>p\<bar>) & (p mod d = 0) then True else False)"
|
neuper@48839
|
638 |
| "ds dvd_up ps =
|
neuper@48839
|
639 |
(let
|
neuper@48839
|
640 |
ds = drop_lc0 ds; ps = drop_lc0 ps;
|
neuper@48839
|
641 |
d000 = (List.replicate (List.length ps - List.length ds) 0) @ ds;
|
neuper@48839
|
642 |
quot = (lcoeff ps) div2 (lcoeff d000);
|
neuper@48839
|
643 |
rest = drop_lc0 (ps minus_up (d000 mult_ups quot))
|
neuper@48839
|
644 |
in
|
neuper@48839
|
645 |
if rest = [] then True else
|
neuper@48839
|
646 |
if quot \<noteq> 0 & List.length ds \<le> List.length rest then ds dvd_up rest else False)"
|
neuper@48839
|
647 |
apply pat_completeness
|
neuper@48839
|
648 |
apply simp
|
neuper@48839
|
649 |
defer
|
neuper@48839
|
650 |
apply simp
|
neuper@48839
|
651 |
(*---------------------------------------------------------------------------------------------
|
neuper@48842
|
652 |
FINALLY WE HAVE TO SHOW THE COMPATIBILITY OF THE TWO EQUATIONS
|
neuper@48839
|
653 |
1. \<And>(d\<Colon>int) (p\<Colon>int) (ds\<Colon>int list) ps\<Colon>int list.
|
neuper@48839
|
654 |
([d], [p]) = (ds, ps) \<Longrightarrow>
|
neuper@48839
|
655 |
(if \<bar>d\<bar> \<le> \<bar>p\<bar> \<and> p mod d = (0\<Colon>int) then True else False) =
|
neuper@48839
|
656 |
(let ds\<Colon>int list = drop_lc0 ds; ps\<Colon>int list = drop_lc0 ps;
|
neuper@48839
|
657 |
d000\<Colon>int list = replicate (length ps - length ds) (0\<Colon>int) @ ds;
|
neuper@48839
|
658 |
quot\<Colon>int = (lcoeff ps) div2 (lcoeff d000);
|
neuper@48839
|
659 |
rest\<Colon>int list = drop_lc0 (ps minus_up (d000 mult_ups quot))
|
neuper@48839
|
660 |
in if rest = [] then True
|
neuper@48839
|
661 |
else if quot \<noteq> (0\<Colon>int) \<and> length ds \<le> length rest then dvd_up_sumC (ds, rest) else False)
|
neuper@48839
|
662 |
---------------------------------------------------------------------------------------------*)
|
neuper@48839
|
663 |
sorry
|
neuper@48837
|
664 |
|
neuper@48842
|
665 |
(*FINALLY WE HAVE TO SHOW THE COMPATIBILITY OF THE TWO EQUATIONS*)
|
neuper@48842
|
666 |
lemma pat_compatibility:
|
neuper@48842
|
667 |
fixes d p :: int and ds ps rest :: "unipoly"
|
neuper@48839
|
668 |
assumes args_equal: "([d], [p]) = (ds, ps)" and not_zero: "d \<noteq> 0 \<and> p \<noteq> 0"
|
neuper@48842
|
669 |
assumes DELETE: "foo_sumC = body1"
|
neuper@48842
|
670 |
shows
|
neuper@48842
|
671 |
"(if \<bar>d\<bar> \<le> \<bar>p\<bar> \<and> p mod d = 0 then True else False) =
|
neuper@48839
|
672 |
(let ds = drop_lc0 ds; ps = drop_lc0 ps;
|
neuper@48839
|
673 |
d000 = replicate (length ps - length ds) (0\<Colon>int) @ ds;
|
neuper@48839
|
674 |
quot = lcoeff ps div2 lcoeff d000;
|
neuper@48839
|
675 |
rest = drop_lc0 (ps minus_up (d000 div_ups quot))
|
neuper@48839
|
676 |
in if rest = [] then True else
|
neuper@48842
|
677 |
if quot \<noteq> 0 \<and> length ds \<le> length rest then dvd_up_sumC (ds, rest) else False)"
|
neuper@48842
|
678 |
(* using the assumptions reachable is only ^^^^^^^^^^^^^^^^^^^^^^^ *)
|
neuper@48842
|
679 |
(is "?body\<^isub>1 = ?body\<^isub>2")
|
neuper@48839
|
680 |
proof -
|
neuper@48842
|
681 |
have "ds = [d]" and "ps = [p]" using args_equal by auto
|
neuper@48842
|
682 |
-- "required by hypsubst: assume 'ds = [d] \<Longrightarrow> ps = [p]' creates ((ds = [d] \<Longrightarrow> ps = [p])) \<Longrightarrow>"
|
neuper@48842
|
683 |
have simp1_ds: "drop_lc0 [d] = [d]" using not_zero by auto
|
neuper@48842
|
684 |
have simp1_ps: "drop_lc0 [p] = [p]" using not_zero by auto
|
neuper@48842
|
685 |
have simp2_body2: "drop_lc0 ([p] minus_up ([d] div_ups quot)) \<noteq> []" sorry
|
neuper@48842
|
686 |
have simp_body2: "True" sorry
|
neuper@48842
|
687 |
from `ds = [d]` `ps = [p]` have simp_body2: "?body\<^isub>2 = dvd_up_sumC (ds, rest)"
|
neuper@48842
|
688 |
proof -
|
neuper@48842
|
689 |
have "?body\<^isub>2 =
|
neuper@48842
|
690 |
(let quot = lcoeff [p] div2 lcoeff [d];
|
neuper@48842
|
691 |
rest = drop_lc0 ([p] minus_up ([d] div_ups quot))
|
neuper@48842
|
692 |
in if rest = [] then True else
|
neuper@48842
|
693 |
if quot \<noteq> 0 \<and> length [d] \<le> length rest then dvd_up_sumC ([d], rest) else False)"
|
neuper@48842
|
694 |
using `ds = [d]` `ps = [p]`
|
neuper@48842
|
695 |
by (hypsubst, subst simp1_ds, subst simp1_ps, simp add: Let_def)
|
neuper@48842
|
696 |
also have "\<dots> = dvd_up_sumC (ds, rest)"
|
neuper@48842
|
697 |
using simp2_body2
|
neuper@48842
|
698 |
sorry
|
neuper@48842
|
699 |
finally show ?thesis .
|
neuper@48842
|
700 |
qed
|
neuper@48842
|
701 |
from simp_body2 DELETE show ?thesis sorry
|
neuper@48842
|
702 |
qed
|
neuper@48842
|
703 |
|
neuper@48842
|
704 |
ML {* 1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1*1 *}
|
neuper@48842
|
705 |
|
neuper@48842
|
706 |
(*---------------------------------------------------------------------------------------------
|
neuper@48842
|
707 |
declare [[simp_trace_depth_limit = 99]]
|
neuper@48842
|
708 |
declare [[simp_trace = true]]
|
neuper@48842
|
709 |
lemma trial:
|
neuper@48842
|
710 |
assumes "[d] = ds \<Longrightarrow> [p] = ps"
|
neuper@48842
|
711 |
and "(let d000 = replicate (length ps - length ds) (0\<Colon>int) @ ds;
|
neuper@48842
|
712 |
quot = lcoeff ps div2 lcoeff d000;
|
neuper@48842
|
713 |
rest = drop_lc0 (ps minus_up (d000 div_ups quot))
|
neuper@48842
|
714 |
in if rest = [] then True else
|
neuper@48842
|
715 |
if quot \<noteq> (0\<Colon>int) \<and> length ds \<le> length rest then dvd_up_sumC (ds, rest) else False)"
|
neuper@48842
|
716 |
shows "(let d000 = replicate (length [p] - length [d]) (0\<Colon>int) @ [d];
|
neuper@48842
|
717 |
quot = lcoeff [p] div2 lcoeff d000;
|
neuper@48842
|
718 |
rest = drop_lc0 ([p] minus_up (d000 div_ups quot))
|
neuper@48842
|
719 |
in if rest = [] then True else
|
neuper@48842
|
720 |
if quot \<noteq> (0\<Colon>int) \<and> length [d] \<le> length rest then dvd_up_sumC ([d], rest) else False)"
|
neuper@48842
|
721 |
|
neuper@48839
|
722 |
oops
|
neuper@48842
|
723 |
---------------------------------------------------------------------------------------------*)
|
neuper@48839
|
724 |
|
neuper@48837
|
725 |
|
neuper@48837
|
726 |
(*---------------------------------------------------------------------------------------------
|
neuper@48823
|
727 |
(*
|
neuper@48823
|
728 |
value "[2, 3] dvd_up [8, 22, 15] = True"
|
neuper@48823
|
729 |
... FIXME loops, incorrect: ALL SHOULD EVALUATE TO TRUE .......
|
neuper@48817
|
730 |
*)
|
neuper@48823
|
731 |
value "[4] dvd_up [6] = False"
|
neuper@48823
|
732 |
value "[8] dvd_up [16, 0] = True"
|
neuper@48823
|
733 |
value "[3, 2] dvd_up [0, 0, 9, 12, 4] = True"
|
neuper@48823
|
734 |
value "[8, 0] dvd_up [16] = True"
|
neuper@48814
|
735 |
|
neuper@48823
|
736 |
(* centr is just local to poly_centr *)
|
neuper@48823
|
737 |
definition centr :: "int \<Rightarrow> int \<Rightarrow> int \<Rightarrow> int" where
|
neuper@48823
|
738 |
"centr m mid p_i = (if mid < p_i then p_i - m else p_i)"
|
neuper@48836
|
739 |
|
neuper@48836
|
740 |
(* normalise :: poly_centr \<Rightarrow> unipoly => int \<Rightarrow> unipoly
|
neuper@48836
|
741 |
normalise [p_0, .., p_k] m = [q_0, .., q_k]
|
neuper@48836
|
742 |
assumes
|
neuper@48836
|
743 |
yields 0 \<le> i \<le> k \<Rightarrow> |^ ~m/2 ^| <= q_i <=|^ m/2 ^|
|
neuper@48836
|
744 |
(where |^ x ^| means round x up to the next greater integer) *)
|
neuper@48823
|
745 |
definition poly_centr :: "unipoly \<Rightarrow> int \<Rightarrow> unipoly" where
|
neuper@48823
|
746 |
"poly_centr p m =
|
neuper@48823
|
747 |
(let
|
neuper@48823
|
748 |
mi = m div2 2;
|
neuper@48823
|
749 |
mid = if m mod mi = 0 then mi else mi + 1
|
neuper@48823
|
750 |
in map (centr m mid) p)"
|
neuper@48814
|
751 |
|
neuper@48823
|
752 |
value "poly_centr [7, 3, 5, 8, 1, 3] 10 = [-3, 3, 5, -2, 1, 3]"
|
neuper@48823
|
753 |
value "poly_centr [1, 2, 3, 4, 5] 2 = [1, 0, 1, 2, 3]"
|
neuper@48823
|
754 |
value "poly_centr [1, 2, 3, 4, 5] 3 = [1, -1, 0, 1, 2]"
|
neuper@48823
|
755 |
value "poly_centr [1, 2, 3, 4, 5] 4 = [1, 2, -1, 0, 1]"
|
neuper@48823
|
756 |
value "poly_centr [1, 2, 3, 4, 5] 5 = [1, 2, 3, -1, 0]"
|
neuper@48823
|
757 |
value "poly_centr [1, 2, 3, 4, 5] 6 = [1, 2, 3, -2, -1]"
|
neuper@48823
|
758 |
value "poly_centr [1, 2, 3, 4, 5] 7 = [1, 2, 3, 4, -2]"
|
neuper@48823
|
759 |
value "poly_centr [1, 2, 3, 4, 5] 8 = [1, 2, 3, 4, -3]"
|
neuper@48823
|
760 |
value "poly_centr [1, 2, 3, 4, 5] 9 = [1, 2, 3, 4, 5]"
|
neuper@48823
|
761 |
value "poly_centr [1, 2, 3, 4, 5] 10 = [1, 2, 3, 4, 5]"
|
neuper@48823
|
762 |
value "poly_centr [1, 2, 3, 4, 5] 11 = [1, 2, 3, 4, 5]"
|
neuper@48823
|
763 |
|
neuper@48836
|
764 |
(* sum_lmb :: poly_centr \<Rightarrow> unipoly \<Rightarrow> int \<Rightarrow> int
|
neuper@48827
|
765 |
sum_lmb [p_0, .., p_k] e = s
|
neuper@48827
|
766 |
assumes exp >= 0
|
neuper@48836
|
767 |
yields. p_0^e + p_1^e + ... + p_k^e *)
|
neuper@48823
|
768 |
definition sum_lmb :: "unipoly \<Rightarrow> nat \<Rightarrow> int" where
|
neuper@48831
|
769 |
"sum_lmb p exp = List.fold ((op +) o (swapf power exp)) p 0"
|
neuper@48823
|
770 |
|
neuper@48823
|
771 |
value "sum_lmb [-1, 2, -3, 4, -5] 1 = -3"
|
neuper@48823
|
772 |
value "sum_lmb [-1, 2, -3, 4, -5] 2 = 55"
|
neuper@48823
|
773 |
value "sum_lmb [-1, 2, -3, 4, -5] 3 = -81"
|
neuper@48823
|
774 |
value "sum_lmb [-1, 2, -3, 4, -5] 4 = 979"
|
neuper@48823
|
775 |
value "sum_lmb [-1, 2, -3, 4, -5] 5 = -2313"
|
neuper@48823
|
776 |
value "sum_lmb [-1, 2, -3, 4, -5] 6 = 20515"
|
neuper@48823
|
777 |
|
neuper@48830
|
778 |
(* LANDAU_MIGNOTTE_bound :: poly_centr \<Rightarrow> unipoly => unipoly \<Rightarrow> int
|
neuper@48830
|
779 |
LANDAU_MIGNOTTE_bound [a_0, ..., a_m] [b_0, .., b_n] = lmb
|
neuper@48827
|
780 |
assumes True
|
neuper@48836
|
781 |
yields lmb = 2^min(m,n) * gcd(a_m,b_n) *
|
neuper@48827
|
782 |
min( 1/|a_m| * root(sum_lmb [a_0,...a_m] 2 , 1/|b_n| * root(sum_lmb [b_0,...b_n] 2)*)
|
neuper@48830
|
783 |
definition LANDAU_MIGNOTTE_bound :: "unipoly \<Rightarrow> unipoly \<Rightarrow> nat" where
|
neuper@48831
|
784 |
"LANDAU_MIGNOTTE_bound p1 p2 =
|
neuper@48830
|
785 |
((power 2 (min (deg p1) (deg p2))) * (nat (gcd (lcoeff p1) (lcoeff p2))) *
|
neuper@48830
|
786 |
(nat (min (abs ((approx_root (sum_lmb p1 2)) div2 -(lcoeff p1)))
|
neuper@48830
|
787 |
(abs ((approx_root (sum_lmb p2 2)) div2 -(lcoeff p2))))))"
|
neuper@48823
|
788 |
|
neuper@48830
|
789 |
value "LANDAU_MIGNOTTE_bound [1] [4, 5] = 1"
|
neuper@48830
|
790 |
value "LANDAU_MIGNOTTE_bound [1, 2] [4, 5] = 2"
|
neuper@48830
|
791 |
value "LANDAU_MIGNOTTE_bound [1, 2, 3] [4, 5] = 2"
|
neuper@48830
|
792 |
value "LANDAU_MIGNOTTE_bound [1, 2, 3] [4] = 1"
|
neuper@48830
|
793 |
value "LANDAU_MIGNOTTE_bound [1, 2, 3] [4, 5] = 2"
|
neuper@48830
|
794 |
value "LANDAU_MIGNOTTE_bound [1, 2, 3] [4, 5, 6] = 12"
|
neuper@48823
|
795 |
|
neuper@48830
|
796 |
value "LANDAU_MIGNOTTE_bound [-1] [4, 5] = 1"
|
neuper@48830
|
797 |
value "LANDAU_MIGNOTTE_bound [-1, 2] [4, 5] = 2"
|
neuper@48830
|
798 |
value "LANDAU_MIGNOTTE_bound [-1, 2, -3] [4, -5] = 2"
|
neuper@48830
|
799 |
value "LANDAU_MIGNOTTE_bound [-1, 2, -3] [4] = 1"
|
neuper@48830
|
800 |
value "LANDAU_MIGNOTTE_bound [-1, 2, -3] [4, -5] = 2"
|
neuper@48830
|
801 |
value "LANDAU_MIGNOTTE_bound [-1, 2, -3] [4, -5, 6] = 12"
|
neuper@48823
|
802 |
|
neuper@48823
|
803 |
subsection {* modulo calculations for polynomials *}
|
neuper@48823
|
804 |
|
neuper@48827
|
805 |
(* pair is just local to chinese_remainder_poly, is "op ~~" in library.ML *)
|
neuper@48823
|
806 |
fun pair :: "unipoly \<Rightarrow> unipoly \<Rightarrow> ((int * int) list)" (infix "pair" 4) where
|
neuper@48823
|
807 |
"([] pair []) = []"
|
neuper@48823
|
808 |
| "([] pair ys) = []" (*raise ListPair.UnequalLengths*)
|
neuper@48823
|
809 |
| "(xs pair []) = []" (*raise ListPair.UnequalLengths*)
|
neuper@48823
|
810 |
| "((x#xs) pair (y#ys)) = (x, y) # (xs pair ys)"
|
neuper@48823
|
811 |
fun chinese_rem :: "int * int \<Rightarrow> int * int \<Rightarrow> int" where
|
neuper@48823
|
812 |
"chinese_rem (m1, m2) (p1, p2) = (chinese_remainder p1 m1 p2 m2)"
|
neuper@48823
|
813 |
|
neuper@48823
|
814 |
(* TODO *)
|
neuper@48823
|
815 |
fun chinese_remainder_poly :: "int * int \<Rightarrow> unipoly * unipoly \<Rightarrow> unipoly" where
|
neuper@48823
|
816 |
"chinese_remainder_poly (m1, m2) (p1, p2) = map (chinese_rem (m1, m2)) (p1 pair p2)"
|
neuper@48823
|
817 |
|
neuper@48823
|
818 |
value "chinese_remainder_poly (5, 7) ([2, 2, 4, 3], [3, 2, 3, 5]) = [17, 2, 24, 33]"
|
neuper@48823
|
819 |
|
neuper@48823
|
820 |
(* mod_pol is just local to mod_poly *)
|
neuper@48823
|
821 |
function mod_pol :: "unipoly \<Rightarrow> int \<Rightarrow> nat \<Rightarrow> unipoly" where
|
neuper@48823
|
822 |
"mod_pol p m n = (if n < List.length p
|
neuper@48823
|
823 |
then mod_pol ((List.tl p) @ [(List.hd p) mod m]) m (n + 1)
|
neuper@48823
|
824 |
else p)"
|
neuper@48831
|
825 |
by auto
|
neuper@48823
|
826 |
termination sorry
|
neuper@48823
|
827 |
(* TODO *)
|
neuper@48823
|
828 |
definition mod_poly :: "unipoly \<Rightarrow> int \<Rightarrow> unipoly" (infixl "mod'_poly" 70) where
|
neuper@48823
|
829 |
"p mod_poly m = mod_pol p m 0"
|
neuper@48823
|
830 |
|
neuper@48823
|
831 |
value "[5, 4, 7, 8, 1] mod_poly 5 = [0, 4, 2, 3, 1]"
|
neuper@48823
|
832 |
value "[5, 4, -7, 8, -1] mod_poly 5 = [0, 4, 3, 3, 4]"
|
neuper@48823
|
833 |
|
neuper@48823
|
834 |
(* euclidean algoritm in Z_p[x].
|
neuper@48831
|
835 |
mod_poly_gcd :: unipoly \<Rightarrow> unipoly \<Rightarrow> int \<Rightarrow> unipoly
|
neuper@48823
|
836 |
mod_poly_gcd p1 p2 m = g
|
neuper@48823
|
837 |
assumes
|
neuper@48836
|
838 |
yields gcd (p1 mod m) (p2 mod m) = g *)
|
neuper@48823
|
839 |
function mod_poly_gcd :: "unipoly \<Rightarrow> unipoly \<Rightarrow> int \<Rightarrow> unipoly" where
|
neuper@48823
|
840 |
"mod_poly_gcd p1 p2 m =
|
neuper@48823
|
841 |
(let
|
neuper@48823
|
842 |
p1m = p1 mod_poly m;
|
neuper@48823
|
843 |
p2m = drop_lc0 (p2 mod_poly m);
|
neuper@48823
|
844 |
p2n = (replicate (List.length p1 - List.length p2m) 0) @ p2m;
|
neuper@48830
|
845 |
quot = mod_div (lcoeff p1m) (lcoeff p2n) m;
|
neuper@48823
|
846 |
rest = drop_lc0 ((p1m minus_up (p2n mult_ups quot)) mod_poly m)
|
neuper@48823
|
847 |
in
|
neuper@48831
|
848 |
if rest = []
|
neuper@48831
|
849 |
then p2
|
neuper@48831
|
850 |
else
|
neuper@48831
|
851 |
if List.length rest < List.length p2
|
neuper@48831
|
852 |
then mod_poly_gcd p2 rest m
|
neuper@48831
|
853 |
else mod_poly_gcd rest p2 m)"
|
neuper@48831
|
854 |
by auto
|
neuper@48820
|
855 |
termination sorry
|
neuper@48820
|
856 |
|
neuper@48823
|
857 |
value "mod_poly_gcd [-18, -15, -20, 12, 20, -13, 2] [8, 28, 22, -11, -14, 1, 2] 7 = [2, 6, 0, 2, 6]"
|
neuper@48823
|
858 |
value "mod_poly_gcd [8, 28, 22, -11, -14, 1, 2] [2, 6, 0, 2, 6] 7 = [2, 6, 0, 2, 6]"
|
neuper@48823
|
859 |
value "mod_poly_gcd [20, 15, 8, 6] [8, -2, -2, 3] 2 = [0, 1]"
|
neuper@48820
|
860 |
|
neuper@48831
|
861 |
(* analogous to Integer.gcds
|
neuper@48831
|
862 |
gcds :: int list \<Rightarrow> int
|
neuper@48831
|
863 |
gcds ns = d
|
neuper@48831
|
864 |
assumes True
|
neuper@48831
|
865 |
yields THE d. ((\<forall>n. List.member ns n \<longrightarrow> d dvd n) \<and>
|
neuper@48836
|
866 |
(\<forall>d'. (\<forall>n. List.member ns n \<and> d' dvd n) \<longrightarrow> d' \<le> d)) *)
|
neuper@48831
|
867 |
fun gcds :: "int list \<Rightarrow> int" where
|
neuper@48831
|
868 |
"gcds ns = List.fold gcd ns (List.hd ns)"
|
neuper@48836
|
869 |
|
neuper@48831
|
870 |
value "gcds [6, 9, 12] = 3"
|
neuper@48831
|
871 |
value "gcds [6, -9, 12] = 3"
|
neuper@48831
|
872 |
value "gcds [8, 12, 16] = 4"
|
neuper@48831
|
873 |
value "gcds [-8, 12, -16] = 4"
|
neuper@48831
|
874 |
|
neuper@48831
|
875 |
(* prim_poly :: unipoly \<Rightarrow> unipoly
|
neuper@48831
|
876 |
prim_poly p = pp
|
neuper@48831
|
877 |
assumes True
|
neuper@48836
|
878 |
yields \<forall>p1, p2. (List.member pp p1 \<and> List.member pp p2 \<and> p1 \<noteq> p2) \<longrightarrow> gcd p1 p2 = 1 *)
|
neuper@48831
|
879 |
fun prim_poly :: "unipoly \<Rightarrow> unipoly" where
|
neuper@48831
|
880 |
"prim_poly [c] = (if c = 0 then [0] else [1])"
|
neuper@48831
|
881 |
| "prim_poly p =
|
neuper@48831
|
882 |
(let d = gcds p
|
neuper@48831
|
883 |
in
|
neuper@48831
|
884 |
if d = 1 then p else p div_ups d)"
|
neuper@48831
|
885 |
|
neuper@48831
|
886 |
value "prim_poly [12, 16, 32, 44] = [3, 4, 8, 11]"
|
neuper@48831
|
887 |
value "prim_poly [4, 5, 12] = [4, 5, 12]"
|
neuper@48831
|
888 |
value "prim_poly [0] = [0]"
|
neuper@48831
|
889 |
value "prim_poly [6] = [1]"
|
neuper@48829
|
890 |
|
neuper@48829
|
891 |
(*
|
neuper@48823
|
892 |
print_configs
|
neuper@48837
|
893 |
declare [[simp_trace_depth_limit = 99]]
|
neuper@48837
|
894 |
declare [[simp_trace = true]]
|
neuper@48831
|
895 |
|
neuper@48837
|
896 |
using [[simp_trace_depth_limit = 99]]
|
neuper@48837
|
897 |
using [[simp_trace = true]]
|
neuper@48829
|
898 |
*)
|
neuper@48837
|
899 |
---------------------------------------------------------------------------------------------*)
|
neuper@48827
|
900 |
|
neuper@48831
|
901 |
(*---------------------------------------------------------------------------------------------
|
neuper@48827
|
902 |
locale gcd_poly =
|
neuper@48827
|
903 |
fixes gcd_poly :: int poly -> int poly -> int poly
|
neuper@48831
|
904 |
assumes gcd_poly p1 p2 = d
|
neuper@48831
|
905 |
and p1 \<noteq> [:0:] and p2 \<noteq> [:0:]
|
neuper@48837
|
906 |
==> d dvd_poly p1 \<and> d dvd_poly p2 \<and>
|
neuper@48837
|
907 |
(\<forall>d'. (d' dvd_poly p1 \<and> d' dvd_poly p2) \<longrightarrow> d' \<le> d)
|
neuper@48831
|
908 |
---------------------------------------------------------------------------------------------*)
|
neuper@48813
|
909 |
end
|