src/Tools/isac/Knowledge/GCD_Poly_FP.thy
author Walther Neuper <neuper@ist.tugraz.at>
Mon, 18 Mar 2013 10:46:37 +0100
changeset 48842 525fa7d00969
parent 48839 01d86d244319
child 48844 286814b700a9
permissions -rw-r--r--
GCD_Poly ML-->Isabelle: intermediate
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