Update from HH
[hl193./.git] / 100 / e_is_transcendental.ml
1 (*
2  *  HOL Light proof that e is transcendental.
3  *
4  *  This HOL Light proof and its relationship to the informal proof is
5  *  described in :
6  *
7  *  "Formalizing a Proof that e is Transcendental", Journal of Formal
8  *  Reasoning, Vol 4, No 1. 2011.
9  *
10  *  It follows the informal proof provided by the good folks at the
11  *  planetmath website:
12  *
13  *  http://planetmath.org/encyclopedia/EIsTranscendental2.html
14  *
15  *  Note: the original proof script linked to in the above paper
16  *  partitioned the proofs amongst several files, each encapsulated
17  *  in an Ocaml module.  This file has simply concatenated those files
18  *  and hence the module structure persists.
19  *
20  *  Jesse Bingham, Jan 2012
21  *  jesse.d.bingham@intel.com
22  *  jesse.bingham@gmail.com
23  *)
24
25 (* this is needed since the sum from the HOL core (iter.ml, i think)
26  * which is used below, gets overwritten when Library/analysis.ml is loaded.
27  *)
28 let OLD_SUM = sum;;
29
30 (* required stuff from HOL Light library... *)
31 needs "Library/binomial.ml";;
32 needs "Library/analysis.ml";;
33 needs "Library/transc.ml";;
34 needs "Library/prime.ml";;
35 needs "Library/iter.ml";;
36 needs "Library/integer.ml";;
37 needs "Library/floor.ml";;
38 (* get def of transcendental from Harrison's Liouville proof  *)
39 needs "100/liouville.ml";;
40
41 prioritize_real();;
42
43 (*
44  *  A few misculaneous proof utility functions
45  *)
46
47 (* A listified version of ADD_ASSUM *)
48 let ADD_ASSUMS lst thm =
49     let f x y = ADD_ASSUM y x in
50     List.fold_left f thm lst
51 ;;
52 (* A tactic that takes a goal with an assumption A /\ B and replaces
53  * it with a goal with the two assumptions A and B
54  *)
55 let SPLIT_CONJOINED_ASSUMPT_TAC t =
56     (UNDISCH_TAC t) THEN
57     (ONCE_REWRITE_TAC [TAUT `(X /\ Y ==> Z) <=> (X ==> Y ==> Z)`]) THEN
58     (DISCH_TAC THEN DISCH_TAC)
59 ;;
60 (* Adds an assumption and discharges it in one fell swoop *)
61 let ADD_ASSUM_DISCH ass thm = DISCH ass (ADD_ASSUM ass thm);;
62 (* BRW = Bolean ReWrite *)
63 let BRW t f = ONCE_REWRITE_RULE [TAUT t] f;;
64 (* Those two boolean rewrites come in handy *)
65 let BRW0 f = BRW `(X ==> Y ==> Z) <=> (X /\ Y ==> Z)` f;;
66 let BRW1 f = BRW `(X /\ Y ==> Z) <=> (X ==> Y ==> Z)` f;;
67 (* a bunch of trivial real theorems that are useful for
68  * rewriting/simplifying/mesoning
69  *)
70 let rewrites0 = map REAL_ARITH [`&0 + (y:real) = y`;`(x:real) * &0 = &0`;`(&1:real) + &0 = &1`;`(x:real) * &1 = x`];;
71
72 module Pm_lemma1 = struct
73
74 let PDI_DEF = new_recursive_definition num_RECURSION
75     `    (poly_diff_iter p 0 = p)
76       /\ (poly_diff_iter p (SUC n) = poly_diff (poly_diff_iter p n))
77     `
78 let PDI_POLY_DIFF_COMM = prove(
79     `! p n.(poly_diff_iter (poly_diff p) n) = (poly_diff (poly_diff_iter p n))`,
80     STRIP_TAC THEN INDUCT_TAC THEN (ASM_SIMP_TAC [PDI_DEF])
81 )
82
83 let SODN = new_definition
84     `SODN p n = iterate poly_add (0..n) (\i.poly_diff_iter p i)`
85 ;;
86 let SOD = new_definition `!p. SOD p = SODN p (LENGTH p)`;;
87
88 let PHI = new_definition `Phi f x = (exp (-- x)) * (poly (SOD f) x)`
89
90 let PLANETMATH_EQN_1_1_1 = prove(
91     `! x f.((Phi f) diffl ((exp (--x)) * ((poly (poly_diff (SOD f)) x) - (poly (SOD f) x))) )(x)`,
92     let lem1 = SPECL [`\x.exp (--x)`;
93                       `\x.poly (SOD f) x`;
94                       `--(exp (--x))`;
95                       `poly (poly_diff (SOD f)) x`;
96                       `x:real`]  DIFF_MUL in
97     let EXP_NEG_X_DIFF = prove(
98           `!x. ((\x.exp (--x)) diffl (-- (exp (--x))))(x)`,
99           STRIP_TAC THEN DIFF_TAC THEN REAL_ARITH_TAC) in
100     let lem2 = SPEC `x:real` EXP_NEG_X_DIFF in
101     let lem3 = SPECL [`SOD f`;`x:real`] POLY_DIFF in
102     let lem4 = CONJ lem2 lem3 in
103     let lem5 = BETA_RULE (MP lem1 lem4) in
104     let lem6 = REAL_ARITH `(a*(b - c)) = (-- a*c) + (b*a)` in
105     let PHI_abs = prove(
106           `Phi f  = \x.((exp (-- x)) * (poly (SOD f) x))`,
107           (PURE_REWRITE_TAC [SYM (ABS `x:real` (SPEC_ALL PHI))])
108           THEN (ACCEPT_TAC (SYM (ETA_CONV `\x.(Phi f x)`))))
109     in
110     (REPEAT STRIP_TAC) THEN
111     (REWRITE_TAC [PHI_abs]) THEN
112     (REWRITE_TAC [lem6]) THEN
113     (ACCEPT_TAC lem5)
114 )
115
116 let POLY_SUB = prove(
117         `!p1 p2 x. poly (p1 ++ (neg p2)) x = poly p1 x - poly p2 x`,
118         (REWRITE_TAC [POLY_ADD;poly_neg;POLY_CMUL]) THEN REAL_ARITH_TAC
119 )
120 let ZERO_INSERT_NUMSEG = prove(
121     `!n. (0..n) = (0 INSERT (1..n))`,
122     let lem01 = SIMP_RULE [ARITH_RULE `0 <= n`] (SPECL [`0`;`n:num`] NUMSEG_LREC) in
123     let lem02 = SIMP_RULE [ARITH_RULE `0 + 1 = 1`] lem01 in
124     (ACCEPT_TAC (GEN_ALL (GSYM lem02)))
125 )
126 let PDI_POLYDIFF_SUC_LEMMA = prove(
127     `!f n .(poly_diff_iter (poly_diff f) n) = poly_diff_iter f (SUC n)`,
128     STRIP_TAC THEN INDUCT_TAC THENL
129     [ (SIMP_TAC [PDI_DEF]);
130       (ONCE_REWRITE_TAC [PDI_DEF]) THEN
131       (ONCE_REWRITE_TAC [PDI_DEF]) THEN
132       (SIMP_TAC [PDI_POLY_DIFF_COMM])
133     ]
134 )
135 let SOD_POLY_DIFF_ITERATE = prove(
136     `!f .(SOD (poly_diff f)) = iterate (++) (1..(LENGTH f)) (\i.poly_diff_iter f i)`,
137     let lemA1 = SPECL [`1`;`0`] NUMSEG_EMPTY in
138     let lemA2 = SIMP_RULE [ARITH_RULE `0 < 1`] lemA1 in
139     let lem1 =  MATCH_MP ITERATE_IMAGE_NONZERO MONOIDAL_POLY_ADD in
140     let lem2 = ISPECL [`poly_diff_iter f`;`SUC`;`0..(LENGTH (poly_diff f))`] lem1 in
141     let lem3 = SIMP_RULE [FINITE_NUMSEG] lem2 in
142     let lem4 = ONCE_REWRITE_RULE [ARITH_RULE `~(~(x=y) /\ (SUC x) = (SUC y))`] lem3 in
143     let lem5 = SIMP_RULE [] lem4 in
144     let lem6 = ISPECL [`0`;`n:num`;`1`] NUMSEG_OFFSET_IMAGE in
145     let lem7 = SIMP_RULE [ARITH_RULE `!m.m+1 = SUC m`] lem6 in
146     let lem8 = SIMP_RULE [ARITH_RULE `SUC 0 = 1`] lem7 in
147     let lem9 = ONCE_REWRITE_RULE [ETA_CONV `(\i. SUC i)`] lem8 in
148     let lem10 = ONCE_REWRITE_RULE [GSYM lem9] lem5 in
149     let lem11 = ONCE_REWRITE_RULE [GSYM (ETA_CONV `(\i. poly_diff_iter f i)`)] lem10 in
150     let lem12 = SIMP_RULE [o_DEF] lem11 in
151     let lemma0 = prove(
152         `! h t.SUC (LENGTH (poly_diff (CONS h t))) = LENGTH (CONS h t)`,
153         (SIMP_TAC [LENGTH_POLY_DIFF;LENGTH;PRE])
154     ) in
155     (ONCE_REWRITE_TAC [SOD]) THEN (ONCE_REWRITE_TAC [SODN]) THEN
156     (ONCE_REWRITE_TAC [PDI_POLYDIFF_SUC_LEMMA ]) THEN LIST_INDUCT_TAC THENL
157     [ (SIMP_TAC [poly_diff;LENGTH]) THEN
158       (SIMP_TAC [GSYM lemma0;lem12]) THEN
159       (SIMP_TAC [NUMSEG_SING;MONOIDAL_POLY_ADD;ITERATE_SING]) THEN
160       (SIMP_TAC [lemA2;MATCH_MP ITERATE_CLAUSES_GEN MONOIDAL_POLY_ADD]) THEN
161       (ONCE_REWRITE_TAC [POLY_ADD_IDENT]) THEN
162       (SIMP_TAC [PDI_DEF;POLY_DIFF_CLAUSES]);
163       (SIMP_TAC [lem12;GSYM lemma0])
164     ]
165 )
166 let ZERO_ITERATE_POLYADD_LEMMA = prove(
167     `!n f .iterate (++) (0 INSERT (1..n)) f
168            = (f 0) ++ iterate (++) (1..n) f`,
169     let lem0 = prove(`!n. ~(0 IN (1..n))`,
170                       STRIP_TAC THEN (ONCE_REWRITE_TAC [IN_NUMSEG]) THEN
171                       ARITH_TAC) in
172     let lem1 = ISPEC `poly_add` ITERATE_CLAUSES_GEN in
173     let lem2 = SIMP_RULE [MONOIDAL_POLY_ADD] lem1  in
174     let lem3 = CONJUNCT2 lem2  in
175     let lem4 = ISPECL [`f:(num -> (real)list)`;`0`;`1..n`] lem3  in
176     let lem5 = ISPECL [`poly_add`;`f:(num -> (real)list)`;`1..n` ] FINITE_SUPPORT  in
177     let lem6 = SIMP_RULE [FINITE_NUMSEG] lem5 in
178     let lem7 = MP lem4 lem6  in
179     let lem9 = SIMP_RULE [lem0] lem7  in
180     (ACCEPT_TAC (GEN_ALL lem9))
181 )
182 let SOD_SOD_POLYDIFF = prove(
183     `!f .(SOD f) = f ++ (SOD (poly_diff f))`,
184     (ONCE_REWRITE_TAC [SOD_POLY_DIFF_ITERATE]) THEN (ONCE_REWRITE_TAC [SOD]) THEN
185     (ONCE_REWRITE_TAC [SODN]) THEN
186     (ONCE_REWRITE_TAC [ZERO_INSERT_NUMSEG]) THEN
187     (ONCE_REWRITE_TAC [ZERO_ITERATE_POLYADD_LEMMA]) THEN
188     (BETA_TAC) THEN (SIMP_TAC [PDI_DEF])
189 )
190 let SUC_INSERT_NUMSEG = prove(
191     `!n. (0..(SUC n)) = (SUC n) INSERT (0..n)`,
192     let lem01 = SIMP_RULE [ARITH_RULE `0 <= SUC n`]
193                           (SPECL [`0`;`n:num`] NUMSEG_REC) in
194     ACCEPT_TAC (GEN_ALL lem01)
195 )
196 let SUC_NOT_IN_NUMSEG = prove(
197     `!m n. ~((SUC n) IN (m..n))`,
198     STRIP_TAC THEN (ONCE_REWRITE_TAC [IN_NUMSEG]) THEN ARITH_TAC
199 )
200 let SUC_ITERATE_PDI_POLYDIFF_LEMMA = prove(
201     `iterate (++) ((SUC n) INSERT (0..n)) (\i.poly_diff_iter (poly_diff p) i) =
202      (poly_diff_iter (poly_diff p) (SUC n)) ++
203      iterate (++) (0..n) (\i.poly_diff_iter (poly_diff p) i)`,
204     let lem1 = ISPEC `poly_add` ITERATE_CLAUSES_GEN in
205     let lem2 = SIMP_RULE [MONOIDAL_POLY_ADD] lem1 in
206     let lem3 = CONJUNCT2 lem2 in
207     let lem4 = ISPECL [`(\i.poly_diff_iter (poly_diff p) i)`;`SUC n`;`0..n`] lem3 in
208     let lem5 = ISPECL [`poly_add`;`\i.poly_diff_iter (poly_diff p) i`;`0..n` ] FINITE_SUPPORT in
209     let lem6 = SIMP_RULE [FINITE_NUMSEG] lem5 in
210     let lem7 = MP lem4 lem6 in
211     let lem9 = SIMP_RULE [SPEC `0` SUC_NOT_IN_NUMSEG] lem7 in
212     ACCEPT_TAC lem9
213 )
214 let SODN_POLY_DIFF_COMM = prove(
215     `!n p.(SODN (poly_diff p) n) = poly_diff (SODN p n)`,
216     let lem = MP (ISPEC `poly_add` ITERATE_SING) MONOIDAL_POLY_ADD in
217     let lem1 = ISPEC `poly_add` ITERATE_CLAUSES_GEN in
218     let lem2 = SIMP_RULE [MONOIDAL_POLY_ADD] lem1 in
219     let lem3 = CONJUNCT2 lem2 in
220     let lem10 = SIMP_RULE [GSYM SUC_INSERT_NUMSEG] SUC_ITERATE_PDI_POLYDIFF_LEMMA in
221     let lema00 = ISPECL [`(\i.poly_diff_iter (p) i)`;`SUC n`;`0..n`] lem3 in
222     let lema0 = SIMP_RULE [GSYM SUC_INSERT_NUMSEG] lema00 in
223     let lem15 = ISPECL [`poly_add`;`\i.poly_diff_iter (p) i`;`0..n` ] FINITE_SUPPORT in
224     let lem16 = SIMP_RULE [FINITE_NUMSEG] lem15 in
225     let lema1 = MP lema0 lem16 in
226     let lema2 = SIMP_RULE [SPEC `0` SUC_NOT_IN_NUMSEG] lema1 in
227     let lema3 = ONCE_REWRITE_RULE [GSYM SODN] lema2 in
228     INDUCT_TAC THENL
229     [ (ONCE_REWRITE_TAC [SODN]) THEN
230       (SIMP_TAC [NUMSEG_SING;ITERATE_SING]) THEN
231       (ONCE_REWRITE_TAC [lem]) THEN
232       (BETA_TAC) THEN
233       (SIMP_TAC [PDI_POLY_DIFF_COMM])
234       ;
235       (ONCE_REWRITE_TAC [SODN]) THEN (ONCE_REWRITE_TAC [lem10]) THEN
236       (ONCE_REWRITE_TAC [GSYM SODN]) THEN (ASM_SIMP_TAC []) THEN
237       (ONCE_REWRITE_TAC [PDI_DEF ]) THEN
238       (ONCE_REWRITE_TAC [PDI_POLY_DIFF_COMM]) THEN
239       (ONCE_REWRITE_TAC [GSYM POLYDIFF_ADD]) THEN
240       STRIP_TAC THEN AP_TERM_TAC THEN
241       (ONCE_REWRITE_TAC [lema3]) THEN (SIMP_TAC [PDI_DEF])
242     ]
243 )
244 let SUC_ITERATE_POLYADD_LEMMA = prove(
245     `!n f .iterate (++) ((SUC n) INSERT (0..n)) f
246            = (f (SUC n)) ++ iterate (++) (0..n) f`,
247     let lem1 = ISPEC `poly_add` ITERATE_CLAUSES_GEN in
248     let lem2 = SIMP_RULE [MONOIDAL_POLY_ADD] lem1  in
249     let lem3 = CONJUNCT2 lem2  in
250     let lem4 = ISPECL [`f:(num -> (real)list)`;`SUC n`;`0..n`] lem3  in
251     let lem5 = ISPECL [`poly_add`;`f:(num -> (real)list)`;`0..n` ] FINITE_SUPPORT  in
252     let lem6 = SIMP_RULE [FINITE_NUMSEG] lem5 in
253     let lem7 = MP lem4 lem6  in
254     let lem9 = SIMP_RULE [SPEC `0` SUC_NOT_IN_NUMSEG] lem7  in
255     ACCEPT_TAC (GEN_ALL lem9)
256 )
257 let NUMSEG_LENGTH_POLYDIFF_LEMMA = prove(
258     `!f. (0..(LENGTH f)) = ((LENGTH f) INSERT (0..(LENGTH (poly_diff f))))`,
259     (SIMP_TAC [LENGTH_POLY_DIFF]) THEN (LIST_INDUCT_TAC) THENL
260     [ (SIMP_TAC [LENGTH;PRE]) THEN (SIMP_TAC [NUMSEG_CLAUSES]) THEN
261       (SIMP_TAC [INSERT_DEF;NOT_IN_EMPTY;IN]);
262       (SIMP_TAC [LENGTH;PRE]) THEN
263       (SIMP_TAC [ARITH_RULE `0 <= SUC n`;NUMSEG_REC])
264     ]
265 )
266 let POLY_DIFF_LENGTH_LT = prove(
267     `!p. (~(p=[])) ==> (LENGTH (poly_diff p)) < (LENGTH p)`,
268     SIMP_TAC [LENGTH_POLY_DIFF;LENGTH_EQ_NIL;
269                ARITH_RULE `!n.(~(n=0)) ==> (PRE n) < n`]
270 );;
271 let POLY_DIFF_LENGTH_LE_SUC = prove(
272     `! p n . (LENGTH p <= SUC n)  ==> (LENGTH (poly_diff p) <= n)`,
273     (REPEAT STRIP_TAC) THEN (ASM_CASES_TAC `p:(real)list =[]`) THENL
274     [ (ASM_SIMP_TAC [poly_diff;LENGTH]) THEN (ARITH_TAC);
275       (ASM_MESON_TAC [POLY_DIFF_LENGTH_LT;LT_SUC_LE;LTE_TRANS])
276     ]
277 )
278 let PDI_LENGTH_AUX = prove(
279     `! n p. (LENGTH p <= n) ==> poly_diff_iter p n = []`,
280     INDUCT_TAC THENL
281     [ MESON_TAC [PDI_DEF;LENGTH_EQ_NIL;ARITH_RULE `n <= 0 <=> n = 0`];
282       ASM_MESON_TAC [PDI_DEF;PDI_POLY_DIFF_COMM;POLY_DIFF_LENGTH_LE_SUC] ]
283 )
284 let PDI_LENGTH_NIL =  prove(
285     `! p . poly_diff_iter p (LENGTH p) = []`,
286     SIMP_TAC [PDI_LENGTH_AUX;LE_REFL]
287 )
288 let SOD_POLYDIFF_THEOREM = prove(
289     `!f .(SOD (poly_diff f)) = (poly_diff (SOD f))`,
290     let lemmmag = prove(
291         `0 INSERT (0..0) = (0..0)`,
292         (SIMP_TAC [NUMSEG_SING]) THEN
293         (SIMP_TAC [INSERT_DEF;NOT_IN_EMPTY;IN])) in
294     let SUC_LENGTH_CONS = prove(
295         `SUC (LENGTH (t:(real)list)) = (LENGTH (CONS h t))`,
296         (SIMP_TAC [LENGTH])) in
297     (ONCE_REWRITE_TAC [SOD]) THEN
298     (ONCE_REWRITE_TAC [SODN_POLY_DIFF_COMM]) THEN
299     (ONCE_REWRITE_TAC [SODN]) THEN
300     (STRIP_TAC) THEN
301     (CONV_TAC (RAND_CONV (ONCE_REWRITE_CONV [NUMSEG_LENGTH_POLYDIFF_LEMMA]))) THEN
302     (SPEC_TAC (`f:(real)list`,`f:(real)list`)) THEN
303     (LIST_INDUCT_TAC) THENL
304     [ (SIMP_TAC [poly_diff]) THEN
305       (SIMP_TAC [LENGTH]) THEN
306       (SIMP_TAC [SUM_SING_NUMSEG ]) THEN
307       (SIMP_TAC [lemmmag])
308       ;
309        (SIMP_TAC [LENGTH_POLY_DIFF]) THEN
310        (SIMP_TAC [LENGTH;PRE]) THEN
311        (CONV_TAC (RAND_CONV (ONCE_REWRITE_CONV [SUC_ITERATE_POLYADD_LEMMA]))) THEN
312        (SIMP_TAC [LENGTH;PRE]) THEN
313        (SIMP_TAC [GSYM SODN]) THEN
314        (ONCE_REWRITE_TAC [GSYM SODN]) THEN
315        (ONCE_REWRITE_TAC [SUC_LENGTH_CONS]) THEN
316        (ONCE_REWRITE_TAC [PDI_LENGTH_NIL]) THEN
317        (SIMP_TAC [POLY_ADD_CLAUSES ]);
318     ]
319 )
320 let SOD_SOD_DIFF_LEMMA = prove(
321     `!f x.(poly (SOD f) x) - (poly (poly_diff (SOD f)) x) = poly f x`,
322     MESON_TAC [SOD_SOD_POLYDIFF; POLY_ADD ; POLY_SUB;SOD_POLYDIFF_THEOREM;
323                REAL_ARITH `((x:real) + y) -y = x`]
324 )
325
326 let PLANETMATH_EQN_1_1_2 = prove(
327     `!f x.
328         ((exp (--x)) * ((poly (poly_diff (SOD f)) x) - (poly (SOD f) x)))
329         = (-- (exp (--x))) * (poly f x)`,
330     let lem17 = prove(`!x y.(x - y) = (-- (y - x))`,REAL_ARITH_TAC) in
331     (REPEAT STRIP_TAC) THEN
332     (ONCE_REWRITE_TAC [lem17]) THEN (ONCE_REWRITE_TAC [SOD_SOD_DIFF_LEMMA])
333     THEN REAL_ARITH_TAC
334 )
335
336 let PLANETMATH_EQN_1_1_3 = prove(
337     `! x f.((Phi f) diffl (-- (exp (--x)) * (poly f x)))(x)`,
338     (ONCE_REWRITE_TAC [GSYM PLANETMATH_EQN_1_1_2]) THEN (ACCEPT_TAC PLANETMATH_EQN_1_1_1)
339 )
340 let PHI_CONTL =
341    let lem0 = SPECL [`Phi f`;`-- (exp (--x)) * (poly f x)`;`x:real`] DIFF_CONT in
342    GEN_ALL (MP lem0 (SPEC_ALL PLANETMATH_EQN_1_1_3))
343
344 let PHI_DIFFERENTIABLE = prove(
345     `!f x.(Phi f) differentiable x`,
346     (SIMP_TAC [differentiable]) THEN (REPEAT STRIP_TAC) THEN
347     (EXISTS_TAC `((exp (--x)) * ((poly (poly_diff (SOD f)) x) - (poly (SOD f) x)))`)
348     THEN (SIMP_TAC [PLANETMATH_EQN_1_1_1])
349 )
350 let PLANETMATH_EQN_1_2 =
351    (* this one's a bit nasty *)
352    let FO_LEMMA2 = GEN_ALL (prove(
353          `((! l z. (C (l:real) (z:real)) ==> l = (l' z))) ==> ((? (l:real) (z:real) .(A z) /\ (B  z) /\ (C l z) /\ (D l) ) ==> (? (z:real).((A z) /\ (B z) /\ (D (l' z)))))`,
354        let lem0 = prove(`(! (l:real) z.(C l (z:real)) ==> l = (l' z)) ==> ((C l z) = ((C l z) /\ l = (l' z)))`, MESON_TAC[]) in
355        let lem1 = UNDISCH lem0 in
356         (STRIP_TAC THEN (ONCE_REWRITE_TAC [lem1]) THEN (MESON_TAC[]))
357    )) in
358     let PROP_LEMMA = TAUT `! a b c d.((a /\ b /\ c) ==> d) = (b ==> c ==> a ==> d)` in
359     let MVT_SPEC = SPECL [`Phi f`;`&0`;`x:real`] MVT in
360     let MVT_SPEC2 = ONCE_REWRITE_RULE [PROP_LEMMA] MVT_SPEC in
361     let MVT_SPEC3 = UNDISCH MVT_SPEC2 in
362     let MVT_SPEC4 = UNDISCH MVT_SPEC3 in
363     let MVT_SPEC5 = UNDISCH MVT_SPEC4 in
364     let lem0 = prove(`! x. x - &0 = x`,REAL_ARITH_TAC) in
365     let MVT_SPEC6 = ONCE_REWRITE_RULE [lem0] MVT_SPEC5 in
366     let DIFF_UNIQ_SPEC1 = SPEC `Phi f` DIFF_UNIQ in
367     let DIFF_UNIQ_SPEC2 = SPEC `l:real` DIFF_UNIQ_SPEC1 in
368     let DIFF_UNIQ_SPEC3 = SPEC ` (-- (exp (--x)) * (poly f x)) ` DIFF_UNIQ_SPEC2 in
369     let DIFF_UNIQ_SPEC4 = SPEC `x:real` DIFF_UNIQ_SPEC3 in
370     let lem8 = SIMP_RULE [PLANETMATH_EQN_1_1_3] DIFF_UNIQ_SPEC4 in
371     let lem9 = GENL [`l:real`;`x:real`] lem8 in
372     let lem10 = SPECL [`\l x.((Phi f diffl l) x)`;`\z.(&0)<z`;`\z.z < (x:real)`;`\l. (Phi f x) - (Phi f (&0)) = x * l`] FO_LEMMA2  in
373     let lem12 = SPEC `\x.(--(exp (--x))) * (poly f x)` lem10 in
374     let lem13 = BETA_RULE lem12 in
375     let lem14 = MP lem13 lem9 in
376     let lem15 = MP lem14 MVT_SPEC6  in
377     let lem70 = SPECL [`f:(real)list`;`x':real`] PHI_DIFFERENTIABLE  in
378     let lem71 = ADD_ASSUM `(&0) < x' /\ x' < x` lem70 in
379     let lem72 = GEN `x':real` (DISCH_ALL lem71) in
380     let lem73 = MP (DISCH (concl lem72) lem15) lem72 in
381     let lem80 = SPECL [`f:(real)list`;`x':real`] PHI_CONTL  in
382     let lem81 = ADD_ASSUM `(&0) <= x' /\ x' <= x` lem80 in
383     let lem82 = GEN `x':real` (DISCH_ALL lem81) in
384     let lem83 = MP (DISCH (concl lem82) lem73) lem82 in
385     lem83
386
387 let xi_DEF  = new_specification ["xi"]
388     (let FO_LEM = prove(
389          `  (! x f.(P x) ==> ? z. (Q z x f))
390           = (! (x:real) (f:(real)list). ? (z:real). (P x) ==> (Q z x f))`,
391          MESON_TAC []) in
392     ((CONV_RULE SKOLEM_CONV)
393       (ONCE_REWRITE_RULE [FO_LEM]
394         (GEN_ALL (DISCH_ALL PLANETMATH_EQN_1_2)))))
395
396 let PLANETMATH_LEMMA_1 = prove(
397     `!x f.  &0 < x
398             ==> poly (SOD f) (&0) * exp x =
399                 poly (SOD f) x + x * exp (x - xi x f) * poly f (xi x f)`,
400     let lemA = CONJUNCT2 (CONJUNCT2 (UNDISCH (SPEC_ALL xi_DEF))) in
401     let lemB = ONCE_REWRITE_RULE [PHI] lemA in
402     let lemC = ONCE_REWRITE_RULE [REAL_ARITH `((A:real) - B = C) = (B = A - C)`] lemB in
403     let lemD = SIMP_RULE [REAL_NEG_0;REAL_EXP_0;REAL_MUL_LID] lemC in
404     let lem01 =  ASSUME `A = ((exp (-- x))*B - (C *( -- (exp (-- y))) * D))` in
405     let lem02 = DISJ2 `exp x = &0` lem01 in
406     let lem03 = REWRITE_RULE [GSYM (SPEC `exp x` REAL_EQ_MUL_LCANCEL)] lem02 in
407     let lem04 = SIMP_RULE [REAL_EXP_NEG_MUL;REAL_EXP_ADD_MUL] lem03 in
408     let lem05 = SIMP_RULE [REAL_SUB_LDISTRIB] lem04 in
409     let lem07 = SIMP_RULE [REAL_MUL_ASSOC;REAL_EXP_NEG_MUL;REAL_MUL_LID] lem05 in
410     let fact00 = REAL_ARITH `(B:real) - ((expx * C) * (--expy))  * D = B + C * (expx * expy) * D` in
411     let lem08 = ONCE_REWRITE_RULE [fact00] lem07 in
412     let lem09 = SIMP_RULE [GSYM REAL_EXP_ADD] lem08 in
413     let lem10 = SIMP_RULE [prove(`(x:real) + -- y =  x - y`, REAL_ARITH_TAC)] lem09 in
414     let lem11 = GEN_ALL (DISCH_ALL lem10) in
415     let lem12 = SPECL [`poly (SOD f) (&0)`;
416                        `poly (SOD f) x`;
417                        `x:real`;
418                        `x:real`;
419                        `xi x f`;
420                        `poly f (xi x f)`] lem11 in
421     let lem13 = MP lem12 lemD  in
422     let lem14 = SPECL [`exp x`;`poly (SOD f) (&0)`] REAL_MUL_SYM in
423     ACCEPT_TAC (GEN_ALL (DISCH_ALL (ONCE_REWRITE_RULE [lem14] lem13)))
424 )
425
426 end;;
427
428 module Pm_lemma2 = struct
429
430 let POLY_MCLAURIN =  prove(
431     `! p x. poly p x =
432             psum (0, LENGTH p) (\m.poly (poly_diff_iter p m) (&0) / &(FACT m) * x pow m)`,
433     let lem002 = SPECL [`poly p`;`\n.poly (poly_diff_iter p n)`] MCLAURIN_ALL_LE in
434     let lem003 = SIMP_RULE [Pm_lemma1.PDI_DEF;POLY_DIFF] lem002 in
435     let lem004 = REWRITE_RULE [ETA_CONV `(\x.poly l x)`] POLY_DIFF in
436     let lem005 = MATCH_MP lem003 (GEN `m:num` (SPECL [`poly_diff_iter p m`] lem004)) in
437     let lem007 = SPECL [`x:real`;`LENGTH (p:(real)list)`] lem005 in
438     let lem008 = ONCE_REWRITE_RULE [Pm_lemma1.PDI_LENGTH_NIL] lem007 in
439     let lem009 = ONCE_REWRITE_RULE [poly] lem008 in
440     let lem010 = SIMP_RULE [REAL_ARITH `!x. ((&0)/x) = &0`] lem009 in
441     let lem011 = SIMP_RULE [REAL_MUL_LZERO;REAL_ADD_RID] lem010 in
442     let lem012 = prove(`(? t . (A t) /\ B) ==> B`, MESON_TAC []) in
443     ACCEPT_TAC (GEN_ALL (MATCH_MP lem012 lem011))
444 )
445 let DIFF_ADD_CONST_COMMUTE = prove(
446     `!f a l x . (f diffl l) (x + a) ==> ((\x. f (x + a)) diffl l) x`,
447     let lem01 = CONJ (SPEC_ALL DIFF_X) (SPECL [`a:real`;`x:real`] DIFF_CONST) in
448     let lem02 = BETA_RULE (MATCH_MP DIFF_ADD lem01) in
449     let lem03 = ONCE_REWRITE_RULE [REAL_ARITH `&1 + &0 = &1`] lem02 in
450     let lem04 = SPECL [`f:real->real`;`\(x:real).((x + a)):real`;`l:real`;`&1`] DIFF_CHAIN  in
451     let MUL_ONE = REAL_ARITH `! x.(&1) * x = x /\ x * (&1) = x` in
452     let lem05 = ONCE_REWRITE_RULE [MUL_ONE] (BETA_RULE lem04) in
453     let lem06 = GEN_ALL (SIMP_RULE [lem03] lem05) in
454     ACCEPT_TAC lem06
455 )
456 let POLY_DIFF_ADD_CONST_COMMUTE = prove(
457     `! p1 p2 a.(!x.(poly p2 x) = (poly p1 (x-a)))
458             ==> (!x . ((poly (poly_diff p2) x) = (poly (poly_diff p1) (x-a))))`,
459     let lem01 = SPECL
460                   [`\x.poly p1 x`;`-- a:real`;`l:real`;`x:real`]
461                   DIFF_ADD_CONST_COMMUTE in
462     let lem02 = ONCE_REWRITE_RULE [REAL_ARITH `w + --v = w - v`] (BETA_RULE lem01) in
463     let lem03 = SPECL [`p1:(real)list`;`(x:real) -a`] POLY_DIFF in
464     let lem04 = MATCH_MP lem02 lem03 in
465     let lem05 = ASSUME `!x.poly p2 x = poly p1 (x - a)` in
466     let lem06 = ONCE_REWRITE_RULE [GSYM lem05] lem04 in
467     let lem07 = SPECL [`p2:(real)list`;`x:real`] POLY_DIFF in
468     let lem08 = MATCH_MP DIFF_UNIQ (CONJ lem07 lem06)  in
469     (REPEAT STRIP_TAC) THEN (ACCEPT_TAC lem08)
470 )
471
472 let HARD_WON = prove(
473     `! p1 p2 a n.(!x.(poly p2 x) = (poly p1 (x-a)))
474             ==> ((\x.poly (poly_diff_iter p2 n) x) = (\x.(poly (poly_diff_iter p1 n) (x - a)))) `,
475     let lem = SPECL [`poly_diff_iter p1 n`;`poly_diff_iter p2 n`;`a:real`] POLY_DIFF_ADD_CONST_COMMUTE in
476     let tm = `(!x . poly p2 x = poly p1 (x -a )) ==>
477                    (\x.poly (poly_diff_iter p2 n) x) = (\x. poly (poly_diff_iter p1 n) (x - a))` in
478     (STRIP_TAC THEN STRIP_TAC THEN STRIP_TAC ) THEN
479     (INDUCT_TAC) THENL
480     [ SIMP_TAC [Pm_lemma1.PDI_DEF] ;
481       STRIP_TAC THEN (ONCE_REWRITE_TAC [Pm_lemma1.PDI_DEF]) THEN (UNDISCH_TAC tm) THEN
482       (ASM_REWRITE_TAC[FUN_EQ_THM]) THEN (ACCEPT_TAC lem)
483     ]
484 )
485 (* if f:real->real is a function, let us call the function g x = f (x+a),
486  * where a is a constant, a "shifting" of f by a.  if f is defined by a poly,
487  * i.e. a (real)list, then (poly_shift f a) is the (real)list defining
488  * the shifting of f by a.
489  *)
490 let POLY_SHIFT_DEF = new_recursive_definition list_RECURSION
491                `   (poly_shift [] a = [])
492                 /\ (poly_shift (CONS c t) a =
493                    (CONS c (poly_shift t a)) ++ (a ## (poly_shift t a)))`
494
495 (* POLY_SHIFT simply says that poly_shift does what is supposed to do
496  *)
497 let POLY_SHIFT = prove(
498     `! p a x .(poly p (x + a)) = (poly (poly_shift p a) x)`,
499     let lem01 = ASSUME `! a x . poly  t (x + a) = poly (poly_shift t a ) x` in
500     LIST_INDUCT_TAC THENL
501     [
502      (ONCE_REWRITE_TAC [POLY_SHIFT_DEF;poly]) THEN (SIMP_TAC [poly]);
503      (REPEAT STRIP_TAC) THEN (ONCE_REWRITE_TAC [POLY_SHIFT_DEF]) THEN
504      (ONCE_REWRITE_TAC [POLY_ADD]) THEN (ONCE_REWRITE_TAC [POLY_CMUL]) THEN
505      (ONCE_REWRITE_TAC [poly;GSYM lem01]) THEN
506      (ONCE_REWRITE_TAC [GSYM lem01]) THEN (REAL_ARITH_TAC)
507     ]
508 )
509 let POLY_SHIFT_LENGTH = prove(
510     `! p a . (LENGTH (poly_shift p a)) = (LENGTH p)`,
511
512     (LIST_INDUCT_TAC) THENL
513     [ (SIMP_TAC [POLY_SHIFT_DEF]);
514       (SIMP_TAC [POLY_SHIFT_DEF]) THEN
515       (ASM_SIMP_TAC
516         [LENGTH;POLY_CMUL_LENGTH;POLY_ADD_LENGTH;
517          ARITH_RULE `MAX (x:num) y = if (x > y) then x else y`;
518          ARITH_RULE `! n. SUC n >n`])
519     ]
520 )
521 let POLY_TAYLOR = prove(
522     `! p x a. poly p x =
523               psum (0,LENGTH p) (\m.poly (poly_diff_iter p m) a/ &(FACT m) * (x - a) pow m)`,
524     let lem01 = SPEC `poly_shift p a` POLY_MCLAURIN in
525     let lem02 = SPECL [`p:(real)list`;`poly_shift p a`;`-- a:real`;`n:num`] HARD_WON in
526     let lem03 = GSYM ( SPECL [`p:(real)list`;`a:real`] POLY_SHIFT) in
527     let lem04 = SIMP_RULE [REAL_ARITH `a - --b = a + b`] lem02 in
528     let lem05 = ONCE_REWRITE_RULE [ETA_AX] (MP lem04 lem03) in
529     let lem06 = BETA_RULE (ONCE_REWRITE_RULE [lem05] lem01) in
530     let lem07 = ONCE_REWRITE_RULE [REAL_ARITH `&0 + a = a`] lem06 in
531     let lem08 = ONCE_REWRITE_RULE [GSYM POLY_SHIFT] lem07 in
532     let lem09 = ONCE_REWRITE_RULE [POLY_SHIFT_LENGTH] lem08 in
533     let lem10 = RATOR_CONV (ONCE_REWRITE_CONV [REAL_ARITH `(x:real) = (x + a) - a`]) `x pow m` in
534     let lem11 = ONCE_REWRITE_RULE [lem10] lem09 in
535     let lem12 = SPEC `(x - a):real` lem11 in
536     let lem13 = ONCE_REWRITE_RULE [REAL_ARITH `(x:real) - a + a = x`] lem12 in
537     ACCEPT_TAC (GEN_ALL lem13 )
538 )
539 let PLANETMATH_LEMMA_2_A = prove(
540     `! p a x . poly p x =
541        ((\s .psum (0,LENGTH p) ((\m.poly (poly_diff_iter p m) a/ &(FACT m) * (s m))))
542          (\m.(x - a) pow m))`,
543     BETA_TAC THEN (MATCH_ACCEPT_TAC POLY_TAYLOR)
544 )
545 let ITERATE_SUC_REC = prove(
546     `!(op:D -> D -> D) m n (f:num -> D) .
547               monoidal op ==>
548               (m <= SUC n) ==>
549               iterate op (m..(SUC n)) f
550                = op (f (SUC n)) (iterate op (m..n) f)`,
551     let lem0 = UNDISCH_ALL (SPEC_ALL (GSYM NUMSEG_REC)) in
552     let lem1 = ISPEC `op:D -> D -> D` ITERATE_CLAUSES_GEN in
553     let lem2 = CONJUNCT2 (UNDISCH lem1) in
554     let lem3 = ISPECL [`f:(num -> D)`;`SUC n`;`m..n`] lem2 in
555     let lem4 = SIMP_RULE [] (DISCH_ALL lem3) in
556     let lem50 = prove(
557         `!m n. ~((SUC n) IN (m..n))`,
558         STRIP_TAC THEN (ONCE_REWRITE_TAC [IN_NUMSEG]) THEN ARITH_TAC) in
559     let lem5 = SIMP_RULE [lem50;FINITE_SUPPORT;FINITE_NUMSEG] lem4 in
560     let lem6 = ADD_ASSUM `m <= SUC n` lem5 in
561     let lem7 = ONCE_REWRITE_RULE [lem0] lem6 in
562     SIMP_TAC [lem7]
563 );;
564 let ITERATE_POLY_ADD_PRE_REC = prove(
565     `!f n . n > 0
566         ==> iterate (++) (0..n) f = (f n) ++ (iterate (++) (0..n-1) f)`,
567     MESON_TAC [ITERATE_CLAUSES_NUMSEG; MONOIDAL_POLY_ADD; POLY_ADD_SYM;
568                ARITH_RULE `0 <= x`; ARITH_RULE `n > 0 ==> n = SUC (n - 1)`]
569 );;
570 let PSUM_ITERATE = prove(
571     `! n m f. psum (m,n) f
572               = if (n > 0) then (iterate (+) (m..((n+m)-1)) f) else &0`,
573     let lem01 = ARITH_RULE `~(n+m=0) ==> (SUC n + m) -1 = SUC ((n + m) -1)` in
574     let lem02 = MP (ISPEC `(+)` ITERATE_SING) MONOIDAL_REAL_ADD in
575     let lem03 = prove(
576           `iterate (+) (m..SUC ((n + m) - 1)) f
577            = f (SUC ((n+m)-1)) + iterate (+) (m..(n+m)-1) f`,
578            MESON_TAC [ARITH_RULE `m <= SUC ((n+m)-1)`;ITERATE_CLAUSES_NUMSEG;
579                       MONOIDAL_REAL_ADD;REAL_ADD_SYM]) in
580     let lem04 = UNDISCH (UNDISCH (ARITH_RULE `~(n+m=0) ==> n=0 ==> m-1 < m`)) in
581     let lem05 = SIMP_RULE [lem04] (SPECL [`m:num`;`m-1`] NUMSEG_EMPTY) in
582     INDUCT_TAC THENL
583     [ SIMP_TAC [ARITH_RULE `~(0 > 0)`;sum_DEF];
584       (SIMP_TAC [ARITH_RULE `(SUC n) > 0`]) THEN (REPEAT STRIP_TAC) THEN
585       (ASM_CASES_TAC `n + m =0`) THENL
586       [ (REWRITE_TAC [UNDISCH (ARITH_RULE `n + m = 0 ==> n = 0`)]) THEN
587         (REWRITE_TAC [lem02;NUMSEG_SING;ARITH_RULE `(SUC 0 +m) -1 = m`]) THEN
588         (MESON_TAC [sum_DEF; ADD_CLAUSES;REAL_ARITH `&0 + x = x`]) ;
589         (ONCE_REWRITE_TAC [sum_DEF;UNDISCH lem01]) THEN
590         (REWRITE_TAC [lem03]) THEN (ASM_CASES_TAC `n = 0`) THEN
591         (ASM_SIMP_TAC
592           [ARITH_RULE `~(0 > 0)`;ADD_CLAUSES;REAL_ADD_LID;REAL_ADD_RID;
593            lem05;ITERATE_CLAUSES_GEN; MONOIDAL_REAL_ADD;NEUTRAL_REAL_ADD;
594            REAL_ADD_SYM;ADD_SYM;ARITH_RULE `~(n=0) ==> n>0 /\ SUC (n-1) = n`])
595       ]
596     ]
597 );;
598 let FACT_DIV_RCANCELS = prove(
599     `!n x. x / &(FACT n) * &(FACT n) = x`,
600     MESON_TAC [REAL_ARITH `!x. &0 < x ==> ~(x = &0)`;
601                REAL_DIV_RMUL;FACT_LT;REAL_OF_NUM_LT]
602 )
603 let PLANETMATH_LEMMA_2_B = prove(
604     `! p (x:real) a . poly (SOD p) a =
605        ((\s .psum (0,LENGTH p) ((\m.poly (poly_diff_iter p m) a/ &(FACT m) * (s m))))
606          (\m. &(FACT m)))`,
607     let lem6 = ISPECL [`(\i.poly_diff_iter p i)`;`LENGTH (p:(real)list)`]
608                 ITERATE_POLY_ADD_PRE_REC in
609     let lem7 = UNDISCH lem6 in
610     let lem8 = UNDISCH (ARITH_RULE `~(LENGTH (p:(real)list) > 0) ==> (LENGTH p = 0)`) in
611     let lem9 = ONCE_REWRITE_RULE [LENGTH_EQ_NIL] lem8 in
612     BETA_TAC THEN (REPEAT STRIP_TAC) THEN (ONCE_REWRITE_TAC [FACT_DIV_RCANCELS]) THEN
613     (ONCE_REWRITE_TAC [PSUM_ITERATE]) THEN (ASM_CASES_TAC `LENGTH (p:(real)list) > 0`) THENL
614     [ (ASM_SIMP_TAC [Pm_lemma1.SOD;Pm_lemma1.SODN;ITERATE_RADD_POLYADD;ARITH_RULE `x + 0 = x`]) THEN
615       (AP_THM_TAC) THEN (AP_TERM_TAC) THEN (SIMP_TAC [lem7;Pm_lemma1.PDI_LENGTH_NIL;POLY_ADD_CLAUSES]);
616       (ASM_SIMP_TAC []) THEN
617       (SIMP_TAC
618       [lem9;poly;Pm_lemma1.SOD;Pm_lemma1.SODN;NUMSEG_SING;MONOIDAL_POLY_ADD;ITERATE_SING;LENGTH;Pm_lemma1.PDI_DEF])
619     ]
620 )
621 end;;
622
623
624 module Pm_eqn4 = struct
625
626 let N_IS_INT = prove(
627     `!n . integer (&n)`,
628     MESON_TAC [is_int]
629 )
630 let NEG_N_IS_INT = prove(
631     `!n . integer (--(&n))`,
632     MESON_TAC [is_int]
633 );;
634 let PLANETMATH_EQN_3 = prove(
635     `!f. 0 < nu
636           ==> poly (SOD f) (&0) * exp (&nu) =
637               poly (SOD f) (&nu) +
638               &nu * exp (&nu - xi (&nu) f) * poly f (xi (&nu) f)`,
639     let RW = SPECL [`0`;`nu:num`] REAL_OF_NUM_LT in
640     ACCEPT_TAC (ONCE_REWRITE_RULE [RW] (SPEC `(&nu):real` Pm_lemma1.PLANETMATH_LEMMA_1))
641 )
642 (* the RHS of PLANETMATH_EQN_4
643  *  TBD: mentioned in paper
644  *)
645 let LHS = new_definition
646         `LHS c f = sum (0..(PRE (LENGTH c))) (\i.(EL i c)*(poly (SOD f) (&i)))`
647
648 (* the LHS of PLANETMATH_EQN_4
649  *  TBD: mentioned in paper
650  *)
651 let RHS = new_definition
652         `RHS  c f = -- sum (1..(PRE (LENGTH c)) )
653                           (\i.  (&i)
654                               * (EL i c)
655                               * (exp ((&i) - (xi (&i) f)))
656                               * (poly f (xi (&i) f))
657                           )`
658
659 let E_POW_N = prove(
660     `!n.(exp (real_of_num 1)) pow n = exp(&n)`,
661     SIMP_TAC [GSYM REAL_EXP_N;REAL_MUL_RID])
662
663
664 (*  The proof was originally done with a slightly different transcendental
665  *  predicate than found in Harrison's 100/liouville.ml it turns out the difference
666  *  is that &0 satisfies my transcendental!  Thankfully, it is easy to show that
667  *  e != 0, and hence the two notions of transcendence are equivalent for e.
668  *  So that I could eliminate even brining my muddled definition of
669  *  transcendental into the proof, this file ultimately proves
670  *  E_TRANSCENDENTAL_EQUIV, which allows the main proof to only mention
671  *  Harrison's transcendental predicate.
672  *)
673
674 let NO_CONST_TERM_POLY_ROOT = prove(
675     `!p . (~(x = &0) /\ ((HD p) = &0) /\ (poly p x = &0) /\ ~(p = []))
676            ==> ((poly (TL p) x) = &0)`,
677     LIST_INDUCT_TAC THEN
678     (ASM_SIMP_TAC [HD;TL;NOT_CONS_NIL;poly]) THEN
679     (MESON_TAC [REAL_ARITH `((&0):real) + x = x`;REAL_ENTIRE])
680 )
681
682 let NEGATED_POLY_ROOT = prove(
683     `!p . (poly p x = &0) ==> (poly ((-- &1) ## p) x = &0)`,
684     MESON_TAC [POLY_CMUL;REAL_ARITH `(-- &1) * ((&0):real) = &0`]
685 )
686
687 (*  changes a polynomial p to p/x^k, where k is the lowest power
688  *  of x where p has a non-zero coefficient.  This amounts to
689  *  just stripping off all leading zeros from the head of the list p.
690  *)
691 let POLY_NUKE = new_recursive_definition list_RECURSION
692                `   (poly_nuk [] = [])
693                 /\ (poly_nuk (CONS (c:real) t) =
694                    (if (c = &0) then (poly_nuk t) else (CONS c t)))`
695
696 let POLY_NUKE_ROOT = prove(
697     `!p . ((~(x = &0)) /\ (poly p x = &0)) ==> (poly (poly_nuk p) x = &0)`,
698     LIST_INDUCT_TAC THENL
699     [ SIMP_TAC[POLY_NUKE];
700       (ASM_CASES_TAC `(h:real) = &0`) THEN
701       (ASM_MESON_TAC [HD;TL;POLY_NUKE;NOT_CONS_NIL;NO_CONST_TERM_POLY_ROOT])
702     ]
703 )
704 let POLY_NUKE_ZERO = prove(
705     `!p . (poly p = poly []) <=> (poly (poly_nuk p) = poly [])`,
706     LIST_INDUCT_TAC THEN (ASM_MESON_TAC [POLY_ZERO;ALL;POLY_NUKE])
707 )
708 let POLY_CONST_NO_ROOTS = prove(
709     `! c.  ~(poly [c] = poly []) ==> ~(poly [c] x = &0)`,
710     (MESON_TAC [poly;REAL_ENTIRE;POLY_ZERO;ALL;
711                 REAL_ARITH `(x:real) + &0 = x`;
712                 REAL_ARITH `(x:real) * &0 = &0`])
713 )
714 let LENGTH_1 = prove(
715     `! lst . (LENGTH lst = 1) <=> (? x. lst = [x])`,
716     LIST_INDUCT_TAC THEN
717     (MESON_TAC [LENGTH;ARITH_RULE `SUC x = 1 <=> x = 0`;NOT_CONS_NIL;LENGTH_EQ_NIL])
718 )
719 let SOUP_LEMMA = prove(
720     `!p . ~(x = &0) /\ ~(poly p = poly []) /\ (poly p x = &0)
721             ==> LENGTH (poly_nuk p) > 1`,
722     let l0 = ARITH_RULE `(~(n = 0) /\ ~(n = 1)) <=> n > 1` in
723     let l1 = UNDISCH (UNDISCH (BRW1 (SPEC_ALL POLY_NUKE_ROOT))) in
724     (ONCE_REWRITE_TAC [GSYM l0]) THEN (REPEAT STRIP_TAC) THENL
725     [ (ASM_MESON_TAC [LENGTH;LENGTH_EQ_NIL;POLY_NUKE_ZERO]);
726       (ASM_MESON_TAC [l1;POLY_CONST_NO_ROOTS;LENGTH_1;LENGTH;POLY_NUKE_ZERO]) ]
727 )
728
729 let POLY_NUKE_HD_NONZERO = prove(
730     `!p . ~(poly p = poly []) ==> ~((HD (poly_nuk p)) = &0)`,
731     LIST_INDUCT_TAC THEN (ASM_CASES_TAC `(h:real) = &0`) THEN
732     (ASM_SIMP_TAC [HD;POLY_ZERO;ALL;POLY_NUKE])
733 )
734
735 let IS_INT_POLY_NUKE = prove(
736     `!p . (ALL integer p) ==> (ALL integer (poly_nuk p))`,
737     LIST_INDUCT_TAC THEN (ASM_MESON_TAC [ALL;POLY_NUKE;N_IS_INT])
738 )
739
740 let POLY_X_NOT_POLY_NIL = prove(
741     `~(poly [&0;&1] = poly [])`,
742     (SIMP_TAC [FUN_EQ_THM;POLY_X;poly;prove(`(~ ! x .P x) <=> (? x. ~ P x)`,MESON_TAC[])] )
743     THEN (EXISTS_TAC `real_of_num 1`) THEN (REAL_ARITH_TAC)
744 )
745
746 let NOT_TRANSCENDENTAL_ZERO = prove(
747       `~ (transcendental (&0))`,
748       (REWRITE_TAC [transcendental;algebraic]) THEN
749       (EXISTS_TAC `[&0 ; &1]:(real)list`) THEN
750       (MESON_TAC [POLY_X;POLY_X_NOT_POLY_NIL;ALL;N_IS_INT])
751 )
752
753 let ALL_IS_INT_POLY_CMUL = prove(
754     `! p c. (integer c) /\ (ALL integer p) ==> (ALL integer (c ## p))`,
755     (LIST_INDUCT_TAC) THEN (ASM_SIMP_TAC [poly_cmul;ALL;INTEGER_MUL])
756 )
757
758 (*
759  * Harrison's transcendental predicate from 100/liouville.ml is equivalent
760  * to my predicate conjoined with x != 0.
761  *)
762 let TRANSCENDENTAL_MY_TRANSCENDENTAL = prove(
763     `!x. transcendental x <=>
764          (~(x = &0) /\
765              ~ ? c.     (ALL integer c)
766                      /\ ((LENGTH c) > 1)
767                      /\ ((poly c x) = &0)
768                      /\ (HD c) > &0 )`,
769     let contra_pos = TAUT `(~X ==> ~Y /\ ~Z) <=> ((Y \/ Z) ==> X)` in
770     let contra_pos2 = TAUT `((~X /\ ~Y) ==> ~Z) <=> (Z ==> ~X ==> Y)` in
771     let l0 = prove(`!c . LENGTH c > 1 ==> HD c > &0 ==> ~(poly c = poly [])`,
772                    LIST_INDUCT_TAC THEN
773                    (ASM_MESON_TAC [LENGTH_EQ_NIL;ARITH_RULE `n > 1 ==> ~(n = 0)`;
774                                    REAL_ARITH `(x:real) > &0 ==> ~(x = &0)`;
775                                    HD;ALL;POLY_ZERO])) in
776     let witness = `if ((&0) <= (HD (poly_nuk p)))
777                    then (poly_nuk p)
778                    else ((-- &1) ## (poly_nuk p))` in
779     let l2 = REAL_ARITH `!(x:real). (&0 <= x) /\ ~(x = &0) ==> x > &0` in
780     let l3 = prove( `! c p. LENGTH (c ## p) =  LENGTH p`,
781                     STRIP_TAC THEN LIST_INDUCT_TAC THEN
782                     (ASM_SIMP_TAC [poly_cmul;LENGTH])) in
783     let POLY_CMUL_HD = prove(
784         `! x p . (~(p = [])) ==> HD (x ## p) = x * (HD p)`,
785         STRIP_TAC THEN LIST_INDUCT_TAC THEN (SIMP_TAC [NOT_CONS_NIL;poly_cmul;HD])
786     ) in
787     (REWRITE_TAC [transcendental;algebraic]) THEN
788     (STRIP_TAC THEN EQ_TAC) THENL
789     [ (ONCE_REWRITE_TAC [contra_pos]) THEN STRIP_TAC THENL
790       [ASM_MESON_TAC [transcendental;algebraic; NOT_TRANSCENDENTAL_ZERO];
791       (EXISTS_TAC `c:(real)list`) THEN
792       (ASM_MESON_TAC [l0; NOT_TRANSCENDENTAL_ZERO  ])];
793       (REWRITE_TAC [contra_pos2]) THEN
794       (STRIP_TAC THEN STRIP_TAC) THEN (ASM_SIMP_TAC [IS_INT_POLY_NUKE]) THEN
795       (EXISTS_TAC witness) THEN
796       (ASM_CASES_TAC `((&0) <= (HD (poly_nuk p)))`) THEN
797       (ASM_MESON_TAC [ IS_INT_POLY_NUKE;ALL_IS_INT_POLY_CMUL;NEG_N_IS_INT;
798                        l2;POLY_NUKE_HD_NONZERO;NEGATED_POLY_ROOT;SOUP_LEMMA;
799                        l3;POLY_NUKE_ROOT;POLY_NUKE_ZERO;POLY_CMUL_HD;
800                        REAL_ARITH `~(&0 <= (x:real)) <=> ((-- &1) * x) > &0`])
801     ]
802 )
803
804 let E_TRANSCENDENTAL_EQUIV = prove(
805     `(transcendental (exp (&1))) <=>
806      (~ ? c.  (ALL integer c)
807            /\ ((LENGTH c) > 1)
808            /\ ((poly c (exp (&1))) = &0)
809            /\ (HD c) > &0 )`,
810     MESON_TAC[TRANSCENDENTAL_MY_TRANSCENDENTAL;
811               REAL_EXP_POS_LT; REAL_ARITH `&0 < (x:real) ==> ~(&0 = x)`]
812 )
813
814 (* TBD mentionedin paper *)
815 let PLANETMATH_EQN_4 =  prove(
816     `(~ (transcendental (exp (&1)))) ==> ? c .
817           ((ALL integer c) /\ ((LENGTH c) > 1) /\ ((EL 0 c) > &0) /\ (! f .((LHS c f) = (RHS c f))))`,
818      let foo2 = prove( `(HD c) > (real_of_num 0) ==> EL 0 c > &0`,SIMP_TAC [EL]) in
819      let lem01 = SPECL [`f:num->real`;`0`;`0`;`PRE (LENGTH (c:(real)list))`] SUM_COMBINE_R in
820      let lem02 = ARITH_RULE `(0 <= 0 + 1 /\ 0 <= (PRE (LENGTH (c:(real)list))))` in
821      let lem03 = GSYM (MP lem01 (lem02) ) in
822      let lem06 = ISPECL [`f1:num->real`;
823                          `f2:num->real`;
824                          `1`;`(PRE (LENGTH (c:(real)list)))`] SUM_ADD in
825      let new0 = SPECL [`f:num->real`;`1`;`PRE (LENGTH (c:(real)list))`] PSUM_SUM_NUMSEG in
826      let new1 = SIMP_RULE [ARITH_RULE `~(1 = 0)`;ARITH_RULE `(1 + x) -1 = x`] new0 in
827      let new2 = ONCE_REWRITE_RULE [new1] lem06 in
828      let lem001 = REAL_ARITH `((A:real) * B * C * D + B * E) = (B * (A * C * D + E))` in
829      let lem0 = REAL_ARITH `(x:real) =  x * (&1) - (&0) * y` in
830      let lem1 = GEN_ALL (ONCE_REWRITE_RULE [GSYM REAL_EXP_0] lem0) in
831      let lem2 = SPECL [`poly (SOD f) (&0)`;
832                        ` exp (&0 - xi (&0) f) * poly f (xi (&0) f)`] lem1 in
833      let PLANETMATH_EQN_3_TWEAKED =
834          REWRITE_RULE
835            [REAL_ARITH `((A:real) = B+C) <=> (B = A -C)`]
836            PLANETMATH_EQN_3
837      in
838      let lem21 = GEN `nu:num` (SPEC_ALL PLANETMATH_EQN_3_TWEAKED) in
839      let lem3 = CONJ lem21 lem2 in
840      let NUM_CASES_LEMMA = prove(
841          ` !P .((! n .(0 < n) ==> (P n)) /\ (P 0) ==> ! n . P n)`,
842          (REPEAT STRIP_TAC) THEN (SPEC_TAC (`n:num`,`n:num`)) THEN
843          INDUCT_TAC THEN (ASM_SIMP_TAC[]) THEN
844          (ASM_SIMP_TAC [ARITH_RULE `0 < (SUC n)`])) in
845      let lem4 = SPEC `(\nu.poly (SOD f) (&nu) = poly (SOD f) (&0) * exp (&nu) - &nu * (exp ((&nu) - xi (&nu) f)) * poly f (xi (&nu) f))` NUM_CASES_LEMMA in
846      let lem5 = BETA_RULE lem4 in
847      let lem6 = MP lem5 lem3 in
848      let lem100 =
849          SIMP_RULE
850            [ARITH_RULE `!n.0 <= n`;ARITH_RULE `(0:num) + 1 = 1`]
851            (ISPECL [`f:num->real`;`0`;`0`;`PRE (LENGTH (c:(real)list))`] SUM_COMBINE_R) in
852      let lem0001 = ASSUME `LENGTH (c:(real)list) > 1` in
853      let lem0002 = MATCH_MP (ARITH_RULE `(x:num) > 1 ==> ~(x=0)`) lem0001 in
854      let lem0003 =  REWRITE_RULE [LENGTH_EQ_NIL] lem0002 in
855      let lem0004 = MATCH_MP  POLY_SUM_EQUIV lem0003 in
856      let SUM_LMUL_NUMSEG = GEN_ALL (ISPECL [`f:num->real`;`c:real`;`n..m`] SUM_LMUL) in
857      (ONCE_REWRITE_TAC [E_TRANSCENDENTAL_EQUIV]) THEN
858      (ONCE_REWRITE_TAC [LHS;RHS]) THEN
859      (REPEAT STRIP_TAC) THEN
860      (EXISTS_TAC `c:(real)list`) THEN
861      (ONCE_REWRITE_TAC [GSYM REAL_RNEG_UNIQ]) THEN
862      (ONCE_REWRITE_TAC [lem03]) THEN
863      (ONCE_REWRITE_TAC [NUMSEG_CONV `0..0`]) THEN
864      (ONCE_REWRITE_TAC [SUM_SING] ) THEN
865      (ASM_SIMP_TAC[foo2]) THEN
866      (BETA_TAC) THEN
867      (ONCE_REWRITE_TAC [ARITH_RULE `0 + 1 = 1`] ) THEN
868      (ONCE_REWRITE_TAC [REAL_ARITH `(A:real) + B + C = (A + C) + B`] ) THEN
869      (ONCE_REWRITE_TAC [GSYM new2]) THEN
870      (BETA_TAC) THEN
871      (ONCE_REWRITE_TAC [lem001]) THEN
872      (CONV_TAC ((RAND_CONV o ABS_CONV o RATOR_CONV o RAND_CONV o RATOR_CONV) (PURE_ONCE_REWRITE_CONV [lem6]))) THEN
873      (ONCE_REWRITE_TAC [REAL_ARITH `(A:real) + B - A = B`]) THEN
874      (ONCE_REWRITE_TAC [REAL_ARITH `(EL 0 c) * (poly (SOD f) (&0))  = (EL 0 c) * (poly (SOD f) (&0)) * (&1)`]) THEN
875      (ONCE_REWRITE_TAC [GSYM REAL_EXP_0]) THEN
876      (ONCE_REWRITE_TAC [GSYM (BETA_CONV `(\x.(EL x c) * (poly (SOD f) (&0)) * exp (&x)) (0)`)]) THEN
877      (ONCE_REWRITE_TAC [GSYM (ISPEC `\x.(EL x c) * (poly (SOD f) (&0)) * exp (&x)` SUM_SING)]) THEN
878      (ONCE_REWRITE_TAC [GSYM (NUMSEG_CONV `0..0`)]) THEN
879      (ONCE_REWRITE_TAC [REAL_ADD_AC]) THEN
880      (ONCE_REWRITE_TAC [lem100]) THEN
881      (ONCE_REWRITE_TAC [REAL_ARITH `(A:real) * B * C = B * A * C`]) THEN
882      (ONCE_REWRITE_TAC [ SUM_LMUL_NUMSEG ]) THEN
883      (ONCE_REWRITE_TAC [GSYM E_POW_N]) THEN
884      (ONCE_REWRITE_TAC [GSYM lem0004]) THEN
885      (ASM_SIMP_TAC[]) THEN
886      (REAL_ARITH_TAC)
887      )
888
889 end;;
890
891 module Pm_eqn5 = struct
892
893 let POLY_MUL_ITER = new_recursive_definition num_RECURSION
894     `(poly_mul_iter f 0 = [&1]) /\
895      (!n . poly_mul_iter f (SUC n) = (f (SUC n)) ** (poly_mul_iter f n))`
896
897 let PLANETMATH_EQN_5 =
898     new_definition
899       `g n p  = (&1/(&(FACT (p  -1)))) ##
900                    ((poly_exp [&0;&1] (p-1)) **
901                        (poly_exp (poly_mul_iter (\i.[-- &i; &1]) n) p))`
902
903 end;;
904
905
906
907 module Pm_eqn4_rhs = struct
908
909 let ABS_LE_MUL2 = prove(
910   `!(w:real) x y z. abs(w) <= y /\ abs(x) <= z ==> abs(w * x) <= (y * z)`,
911   REPEAT GEN_TAC THEN DISCH_TAC THEN
912   REWRITE_TAC[ABS_MUL] THEN MATCH_MP_TAC REAL_LE_MUL2 THEN
913   ASM_REWRITE_TAC[ABS_POS])
914
915 let SEPTEMBER_2009_LEMMA = prove(
916     `!x f n n'.
917     (!i.(0 <= i /\ i <= n) ==> (abs (poly (f i) x)) <= &(n')) ==>
918     (abs (poly (poly_mul_iter f n) x)) <= (&(n') pow n)`,
919     let lem0 = ASSUME `!i. 0 <= i /\ i <= SUC n ==> abs (poly (f i) x) <= &n'` in
920     let lem1 = SPEC `SUC n` lem0 in
921     let lem2 = SIMP_RULE [ARITH_RULE `0 <= SUC n /\ SUC n <= SUC n`] lem1 in
922     let lem3 = prove(`(!i:num.(P0 i) ==> (P1 i)) ==> (!i:num.((P1 i) ==> (Q i))) ==> (!i:num.((P0 i) ==> (Q i)))`, MESON_TAC[]) in
923     let lem4 = ARITH_RULE `!i.(0 <= i /\ i <= n) ==> (0 <= i /\ i <= SUC n)` in
924     let lem5 = GEN `Q:num->bool` (MATCH_MP lem3 lem4) in
925     let lem6 = ASSUME `!n'. (!i. 0 <= i /\ i <= n ==> abs (poly (f i) x) <= &n') ==> abs (poly (poly_mul_iter f n) x) <= &n' pow n` in
926     let lem7 = SPEC `n':num` lem6 in
927     let lem9 = UNDISCH (BETA_RULE (SPEC `\i. abs (poly (f (i:num)) x) <= &n'` lem5)) in
928     let lem11 = MP (lem7) (lem9) in
929     STRIP_TAC THEN STRIP_TAC THEN INDUCT_TAC THENL
930     [ (REWRITE_TAC ([Pm_eqn5.POLY_MUL_ITER;poly;real_pow]@rewrites0))
931       THEN (REAL_ARITH_TAC);
932       (STRIP_TAC) THEN (STRIP_TAC) THEN
933       (REWRITE_TAC [Pm_eqn5.POLY_MUL_ITER;POLY_MUL;real_pow]) THEN
934       (MATCH_MP_TAC ABS_LE_MUL2) THEN
935       (SIMP_TAC [lem2;lem11])
936     ]
937 )
938 let SEPTEMBER_2009_LEMMA_2 = prove(
939     `&0 < x /\ x < &n
940       ==> (!i. 0 <= i /\ i <= n ==> abs(poly [-- &i; &1] x) <= &n)`,
941     (REWRITE_TAC [GSYM REAL_LE]) THEN (REPEAT STRIP_TAC) THEN
942     (REWRITE_TAC ([poly]@rewrites0)) THEN
943     (REWRITE_TAC [REAL_ARITH `&0 <= -- &i + (x:real) <=>  &i <= x`;real_abs]) THEN (ASM_CASES_TAC `&i <= (x:real)`) THENL
944     [ (ASM_SIMP_TAC []) THEN
945       (REWRITE_TAC [REAL_ARITH `-- &i + (x:real) =  x - &i `]) THEN
946       (ASM_REAL_ARITH_TAC);
947       (ASM_SIMP_TAC []) THEN
948       (REWRITE_TAC [REAL_ARITH `--(-- &i + (x:real)) =  &i - x `]) THEN
949       (ASM_REAL_ARITH_TAC)
950     ]
951 )
952
953 let FACT_DIV_LCANCELS = prove(
954     `!n x.  &(FACT n) * x / &(FACT n)  = x`,
955     let lem0 = SPECL [`0`;`FACT n`] REAL_OF_NUM_LT in
956     let lem1 = ONCE_REWRITE_RULE [GSYM lem0] FACT_LT in
957     let lem2 = SPECL [`x:real`;`(&(FACT n)):real`] REAL_DIV_LMUL in
958     let lem3 = REAL_ARITH `!x:real. &0 < x ==> ~(x = &0)` in
959     let lem4 = MATCH_MP lem3 (SPEC_ALL lem1) in
960     ACCEPT_TAC (GEN_ALL (MP lem2 lem4))
961 )
962 let NOVEMBER_LEMMA_1 = prove(
963     `p > 1 ==>
964       &0 < x /\ x < &n ==>
965        (abs(poly (g n p) x)) <=
966            (&1/(&(FACT (p  -1)))) * ((&n) pow (p - 1)) * ((&n pow n) pow p)`,
967    let l0 = SPECL [`0`;`FACT (p-1)`] REAL_OF_NUM_LT in
968    let l2 = snd (EQ_IMP_RULE l0) in
969    let l3 = MP l2 (SPEC `(p:num) - 1` FACT_LT)  in
970    let l4 = SPEC `(&(FACT (p - 1))):real` REAL_LE_LCANCEL_IMP in
971    let l5 = SIMP_RULE [l3] l4 in
972    let ll0 = snd (EQ_IMP_RULE (SPEC_ALL REAL_ABS_REFL)) in
973    let ll1 = IMP_TRANS (REAL_ARITH `(&0):real < x ==> &0 <= x`) ll0 in
974    let ll2 = UNDISCH ll1 in
975    let asses = [`(p:num) > 1`;`&0 < (x:real)`; `(x:real) < &n`] in
976    let j0 = SPECL [`p - 1`;`x:real`;`(&n):real`] REAL_POW_LE2 in
977    let j1 = REAL_ARITH `(&0) < (x:real) /\ x < (&n) ==> (&0 <=x /\ x <= (&n))` in
978    let j2 = UNDISCH_ALL (BRW1 (IMP_TRANS j1 j0)) in
979    let ll4 = SPECL [`(x:real) pow (p - 1)`;`((&n):real) pow (p - 1)`;`(abs (r:real)) pow p`] REAL_LE_MUL2 in
980    let ll5 = (SPECL [`x:real`;`(p:num) - 1`] REAL_POW_LE) in
981    let ll50 = UNDISCH (IMP_TRANS (REAL_ARITH `&0 < x ==> (&0) <= (x:real)`) ll5;) in
982    let ll6  = ADD_ASSUMS asses ll4 in
983    let ll7 = REAL_ARITH `(x:real) < y ==> x <= y` in
984    let ll8 = SIMP_RULE [j2;ll50;ll7;REAL_POW_LE;REAL_ABS_POS] ll6 in
985    let ll9 = ADD_ASSUM `p > 1` (SPEC `p:num` REAL_POW_LE2) in
986    let ll10 = UNDISCH (ARITH_RULE `p > 1 ==> ~(p = 0)`) in
987    let ll11 = SIMP_RULE [ll10] ll9 in
988    let ll12 = SPEC `abs (r:real)` ll11 in
989    let ll13 = SIMP_RULE [REAL_ABS_POS] ll12 in
990    let lem0 = UNDISCH (UNDISCH (BRW1 SEPTEMBER_2009_LEMMA_2)) in
991    let lem1 = MATCH_MP SEPTEMBER_2009_LEMMA lem0 in
992    let lem2 = DISCH_ALL (DISCH `(&0) < (x:real)` lem1) in
993    let lem3 = SPEC `SUC n` (GEN (`n:num`) lem2) in
994    (STRIP_TAC) THEN (STRIP_TAC) THEN
995    (ONCE_REWRITE_TAC [Pm_eqn5.PLANETMATH_EQN_5]) THEN
996    (ONCE_REWRITE_TAC [POLY_CMUL]) THEN
997    (ONCE_REWRITE_TAC [POLY_MUL]) THEN
998    (ONCE_REWRITE_TAC [POLY_EXP]) THEN
999    (ONCE_REWRITE_TAC [poly]) THEN
1000    (ONCE_REWRITE_TAC [poly]) THEN
1001    (ONCE_REWRITE_TAC [poly]) THEN
1002    (REWRITE_TAC rewrites0) THEN
1003    (ONCE_REWRITE_TAC [REAL_ABS_MUL]) THEN
1004    (ONCE_REWRITE_TAC [REAL_ABS_MUL]) THEN
1005    (ONCE_REWRITE_TAC [REAL_ABS_POW]) THEN
1006    (ONCE_REWRITE_TAC [REAL_ABS_DIV]) THEN
1007    (ONCE_REWRITE_TAC [ABS_N]) THEN
1008    (MATCH_MP_TAC l5) THEN
1009    (ONCE_REWRITE_TAC [REAL_MUL_ASSOC]) THEN
1010    (SIMP_TAC [FACT_DIV_LCANCELS;REAL_ARITH `&1 * (x:real) = x`]) THEN
1011    (SIMP_TAC [ll2]) THEN
1012    (MATCH_MP_TAC ll8) THEN
1013    (MATCH_MP_TAC ll13) THEN
1014    (UNDISCH_TAC `&0 < (x:real)`) THEN
1015    (UNDISCH_TAC `(x:real) < &n`) THEN
1016    (SPEC_TAC (`n:num`,`n:num`)) THEN
1017    INDUCT_TAC THENL [(REAL_ARITH_TAC); (ACCEPT_TAC lem3)]
1018 )
1019
1020 let NOVEMBER_LEMMA_2 = prove(
1021     ` 1 <= v /\ v <= n
1022        ==> ((&0) < ( xi (&v) f)  /\ (xi (&v) f) < (&n))`,
1023     let l0 = SPECL [`(&v):real`;`f:(real)list`] Pm_lemma1.xi_DEF in
1024     let l1 = UNDISCH (ONCE_REWRITE_RULE [REAL_OF_NUM_LT] l0) in
1025     let [l2;l3;_] = CONJUNCTS l1 in
1026     let l4 = GEN_ALL (REAL_ARITH `(&v) <= y ==> z < (&v) ==> (z:real) < y`) in
1027     let l6 = SPECL [`v:num`;`z:real`;`(&n):real`] l4 in
1028     let l7 = UNDISCH  l6 in
1029     (ONCE_REWRITE_TAC [ TAUT `(X /\ Y ==> Z) <=> (X ==> Y ==> Z)`;ARITH_RULE `1 <= v <=> 0 < v` ]) THEN
1030     (ONCE_REWRITE_TAC [GSYM REAL_OF_NUM_LE;GSYM REAL_OF_NUM_LT]) THEN
1031     (STRIP_TAC) THEN (STRIP_TAC) THEN (SIMP_TAC [l2]) THEN
1032     (MATCH_MP_TAC l7) THEN (ACCEPT_TAC  l3)
1033 )
1034
1035 let REAL_LE_MUL3 = prove(
1036     `! w0 x0 y0 w1 x1 (y1:real).
1037      (&0 <= w0) ==> (&0 <= x0) ==> (&0 <= y0) ==>
1038      (w0 <= w1) ==> (x0 <= x1) ==> (y0 <= y1) ==>
1039      (w0 * x0 * y0) <= (w1 * x1 * y1)`,
1040      let lst = [`w0:real`;`w1:real`;`(x0 * y0):real`;`(x1 * y1):real`] in
1041      let c0 = SPECL lst REAL_LE_MUL2 in
1042      MESON_TAC [c0;REAL_LE_MUL2;REAL_LE_MUL]
1043 )
1044
1045 let MAX_ABS_DEF =
1046     new_recursive_definition list_RECURSION
1047        `    (max_abs [] = &0)
1048         /\  (max_abs (CONS h t) = real_max (real_abs h) (max_abs t))`
1049
1050 let MAX_ABS_LE = prove(
1051     `! cs i.
1052      (0 <= i /\ i < (LENGTH cs) ==>
1053        (real_abs (EL i cs)) <= (max_abs cs))`,
1054     let l0 = UNDISCH (REAL_ARITH `~((abs h) <= max_abs t) ==> x <= (max_abs t) ==> x <= (abs h)`) in
1055     LIST_INDUCT_TAC THENL
1056     [ (SIMP_TAC [LENGTH]) THEN ARITH_TAC;
1057       INDUCT_TAC THENL
1058       [ (SIMP_TAC [HD;EL;MAX_ABS_DEF;REAL_MAX_MAX]);
1059         (SIMP_TAC [TL;EL;MAX_ABS_DEF;REAL_MAX_MAX;LENGTH;LT_SUC]) THEN
1060         (ASM_CASES_TAC `(real_abs h) <= (max_abs t)`) THEN
1061         (ASM_SIMP_TAC [real_max;ARITH_RULE `0 <= y`;l0])
1062       ]
1063     ]
1064 )
1065 let KEATS_PART_1 = prove(
1066     `1 <= i /\ i <= PRE (LENGTH c) ==> ( &i * abs (EL i c) <= &i * max_abs c)`,
1067     let keats12 = ARITH_RULE `1 <= i /\ i <= (PRE (LENGTH (c:(real)list))) ==> (0 <= i /\ i < LENGTH c)` in
1068     let keats13 = IMP_TRANS keats12 (SPECL [`c:(real)list`;`i:num`] MAX_ABS_LE) in
1069     let keats14 = SPECL [`real_of_num i`] REAL_LE_LMUL in
1070     let keats15 = ARITH_RULE `(&0) <= (real_of_num i)` in
1071     let keats16 = SIMP_RULE [keats15] keats14 in
1072     let keats17 = UNDISCH keats13 in
1073     let keats18 = MATCH_MP keats16 keats17 in
1074     ACCEPT_TAC (DISCH_ALL keats18)
1075 )
1076 let KEATS_PART_2 = prove(
1077     `(1 <= v /\ v <= PRE (LENGTH (c:(real)list))) ==>
1078        abs (exp ((&v) - xi (&v) (g (PRE (LENGTH c)) p))) <= abs (exp (&(PRE (LENGTH (c:(real)list)))))`,
1079     let j0 = ASSUME `1 <= v /\ (v:num) <= (PRE (LENGTH (c:(real)list)))` in
1080     let j00 = ONCE_REWRITE_RULE [GSYM REAL_OF_NUM_LE] (CONJUNCT2 j0) in
1081     let j1 = REAL_ARITH `!n .(real_of_num v <= &n) ==> (&0 > --xi (&v) (g n p)) ==> (&n) > (&v) - (xi (&v) (g n p))` in
1082 let j2 = MP (SPEC `PRE (LENGTH (c:(real)list))` j1) j00 in
1083     let g_term = `g (PRE (LENGTH (c:(real)list))) p` in
1084     let k33 = SPEC `PRE (LENGTH (c:(real)list))` (GEN `n:num` NOVEMBER_LEMMA_2) in
1085     let k34 = SPEC g_term (GEN `f:(real)list` k33) in
1086     let k35 = DISCH `1 <= v /\ v <= (PRE (LENGTH (c:(real)list)))` (CONJUNCT1 (UNDISCH k34)) in
1087     let k36 = UNDISCH (SPEC `PRE (LENGTH (c:(real)list))` (GEN `n:num` k35)) in
1088     let k37 = REAL_ARITH `!x. (real_of_num 0) < x ==> (real_of_num 0) > -- x` in
1089     let k38 = MATCH_MP k37 k36 in
1090     let k40 = MP j2 k38 in
1091     let k41 = REAL_ARITH `!x (y:real).x > y ==> y <= x` in
1092     let k42 = MATCH_MP k41 k40 in
1093     let k42 = ONCE_REWRITE_RULE [GSYM REAL_EXP_MONO_LE] k42 in
1094     let k43 = REAL_ARITH `!(x:real) . (&0) <= x ==> abs x = x` in
1095     let k44 = GEN `x:real` (MATCH_MP k43 (SPEC `x:real` REAL_EXP_POS_LE)) in
1096     let k45 = ONCE_REWRITE_RULE [GSYM k44] k42 in
1097     let k46 = DISCH_ALL k45 in
1098     let k47 = BRW0 (SIMP_RULE [ARITH_RULE `0 < v <=> 1 <= v`] k46) in
1099     ACCEPT_TAC k47
1100 )
1101 let KEATS_PART_3 =
1102     UNDISCH
1103     (prove(
1104     `p > 1 ==> (1 <= i /\ i <= PRE (LENGTH (c:(real)list)))
1105      ==> abs (poly (g (PRE (LENGTH c)) p) (xi (&i) (g (PRE (LENGTH c)) p))) <=
1106          &1 / &(FACT (p - 1)) *
1107          &(PRE (LENGTH c)) pow (p - 1) *
1108          &(PRE (LENGTH c)) pow PRE (LENGTH c) pow p`,
1109     let k0 = UNDISCH NOVEMBER_LEMMA_2 in
1110     let k1 = UNDISCH NOVEMBER_LEMMA_1 in
1111     let k2 = GEN `x:real` k1 in
1112     let k3 = SPEC `xi (real_of_num i) f` k2 in
1113     let k5 = MATCH_MP k3 k0 in
1114     let g_term = `g (PRE (LENGTH (c:(real)list))) p` in
1115     let k6 = SPEC g_term (GEN `f:(real)list` k5) in
1116     let k7 = SPEC `PRE (LENGTH (c:(real)list))` (GEN `n:num` (DISCH `1 <= v /\ v <= n` k6)) in
1117     let k8 = DISCH `0 < v` k7 in
1118     let k9 = BRW0 (SIMP_RULE [ARITH_RULE `0 < v <=> 1 <= v`] k8) in
1119     MATCH_ACCEPT_TAC (DISCH_ALL k9)
1120 ))
1121
1122 let RHS_4_F5_LE_SUM = prove(
1123     `abs (RHS c (g (PRE (LENGTH c)) p)) <=
1124      sum (1..PRE (LENGTH c))
1125      (\i. &i *
1126           abs (EL i c) *
1127           abs (exp (&i - xi (&i) (g (PRE (LENGTH c)) p))) *
1128           abs
1129           (poly (g (PRE (LENGTH c)) p) (xi (&i) (g (PRE (LENGTH c)) p))))`,
1130     let keats4 = REFL `abs (RHS c f)` in
1131     let keats5 = (CONV_RULE (RAND_CONV (REWRITE_CONV [Pm_eqn4.RHS]))) keats4 in
1132     let keats6 = REWRITE_RULE [REAL_ABS_NEG] keats5 in
1133     let keats7 =
1134         SPECL [`(\i.(&i) * (EL i c) * (exp (&i - (xi (&i) f))) * (poly f (xi
1135         (&i) f)))`;`1`;`PRE (LENGTH (c:(real)list))`] SUM_ABS_NUMSEG in
1136     let keats8 = ONCE_REWRITE_RULE  [GSYM keats6] keats7 in
1137     let keats9 = REWRITE_RULE  [REAL_ABS_NUM;REAL_ABS_MUL] keats8 in
1138     let g_term = `g (PRE (LENGTH (c:(real)list))) p` in
1139     let keats10 = SPEC g_term (GEN `f:(real)list` keats9) in
1140     ACCEPT_TAC  keats10
1141 )
1142
1143
1144 let RHS_4_BOUND_PRE = prove(
1145         `abs (RHS c (g (PRE (LENGTH c)) p)) <=
1146           (sum (1..PRE (LENGTH c)) &) *
1147                (max_abs c *
1148                abs (exp (&(PRE (LENGTH c)))) *
1149                &1 / &(FACT (p - 1)) *
1150                &(PRE (LENGTH c)) pow (p - 1) *
1151                &(PRE (LENGTH c)) pow PRE (LENGTH c) pow p)`,
1152       let w0 = `(real_of_num i) * (real_abs (EL i c))` in
1153       let w1 = `(real_of_num i) * (max_abs c)` in
1154       let x0 = `abs (exp (&v - xi (&v) (g (PRE (LENGTH (c:(real)list))) p)))`
1155       in
1156       let x1 = `abs (exp (&(PRE (LENGTH (c:(real)list)))))` in
1157       let y0 = `abs (poly (g (PRE (LENGTH (c:(real)list))) p) (xi (&i) (g (PRE
1158       (LENGTH c)) p)))` in
1159       let y1 = ` &1 / &(FACT (p - 1)) * &(PRE (LENGTH (c:(real)list))) pow (p -
1160       1) * &(PRE (LENGTH c)) pow PRE (LENGTH c) pow p` in
1161       let rename_free_var oo nn tt = SPEC nn (GEN oo tt) in
1162       let v2i tt = rename_free_var `v:num` `i:num` tt in
1163       let josh0  = SPECL [w0;x0;y0;w1;x1;y1] REAL_LE_MUL3 in
1164       let josh2 = SPECL [`real_of_num i`;`real_abs (EL i c)`] REAL_LE_MUL in
1165       let josh3 = SIMP_RULE [REAL_ABS_POS;REAL_ARITH `(real_of_num 0) <= &i`] josh2
1166       in
1167       let josh4 = v2i (SIMP_RULE [josh3;REAL_ABS_POS] josh0) in
1168       let josh5 = SIMP_RULE [UNDISCH KEATS_PART_1] josh4 in
1169       let josh6 = SIMP_RULE [UNDISCH (v2i KEATS_PART_2)] josh5 in
1170       let josh7 = SIMP_RULE [UNDISCH KEATS_PART_3] josh6 in
1171       let josh8 = DISCH `1 <= i /\ i <= (PRE (LENGTH (c:(real)list)))` josh7 in
1172       let f0 = `(\i.
1173              &i *
1174              abs (EL i c) *
1175              abs (exp (&i - xi (&i) (g (PRE (LENGTH c)) p))) *
1176              abs (poly (g (PRE (LENGTH c)) p) (xi (&i) (g (PRE (LENGTH c))
1177              p))))` in
1178       let f1 = `(\i.
1179                  (&i * max_abs c) *
1180                  abs (exp (&(PRE (LENGTH c)))) *
1181                  &1 / &(FACT (p - 1)) *
1182                  &(PRE (LENGTH c)) pow (p - 1) *
1183                  &(PRE (LENGTH c)) pow PRE (LENGTH c) pow p)` in
1184       let josh9 = SPECL [f0;f1;`1`;`PRE (LENGTH (c:(real)list))`] SUM_LE_NUMSEG
1185       in
1186       let josh10 = REWRITE_RULE [GSYM REAL_MUL_ASSOC] (BETA_RULE josh9) in
1187       let josh11 = REWRITE_RULE [GSYM REAL_MUL_ASSOC] (GEN `i:num` josh8) in
1188       let josh12 = MP josh10 josh11 in
1189       let josh13 = CONJ RHS_4_F5_LE_SUM josh12 in
1190       let josh14 = MATCH_MP REAL_LE_TRANS josh13 in
1191       let josh15 = ONCE_REWRITE_RULE [SUM_RMUL] josh14 in
1192       ACCEPT_TAC josh15
1193 )
1194
1195 (* A reviewer of the Journal of Formalized Reasoning paper for this proof
1196  * pointed out that the "abs" in "abs (exp (&(PRE (LENGTH c))))" of
1197  * RHS_4_BOUND_PRE is redundant.  So here that theorem is rewritten to
1198  * remove that abs.
1199  *)
1200 let RHS_4_BOUND =
1201     let l1 = MATCH_MP (SPEC `&0:real` REAL_LT_IMP_LE)
1202                       (SPEC `x:real` REAL_EXP_POS_LT) in
1203     let l2 = REWRITE_RULE [GSYM REAL_ABS_REFL] l1 in
1204     ONCE_REWRITE_RULE [l2] RHS_4_BOUND_PRE
1205 ;;
1206
1207 let JESSE_POW_LEMMA = prove(
1208      `(p:num) > 1 ==> !x.real_pow x p = x * (real_pow x (p-1))`,
1209      let c0 = UNDISCH (ARITH_RULE `(p:num) > 1 ==> p = SUC (p - 1) `) in
1210      STRIP_TAC THEN STRIP_TAC THEN
1211      (CONV_TAC (RATOR_CONV (ONCE_REWRITE_CONV [c0]))) THEN
1212      (SIMP_TAC [real_pow])
1213 )
1214 let JESSE_REAL_ABS_LE = prove(
1215     `!(x:real) y.(abs x) <= y ==> (abs x) <= (abs y)`,
1216     let int10 = UNDISCH (REAL_ARITH `(real_abs x) <= y ==>  y = real_abs y`) in
1217     (REPEAT STRIP_TAC) THEN (ASM_SIMP_TAC [GSYM int10])
1218 )
1219 let OLDGERMAN_LEMMA = prove(
1220   ` !C2 C e.
1221         &0 < e
1222         ==> (?N . !n. n >= N ==>
1223         abs (C2 * inv (&(FACT n)) * C pow n - &0) < e)`,
1224    let w0 = MATCH_MP SUM_SUMMABLE (SPEC `C:real` REAL_EXP_CONVERGES) in
1225    let w1 = MATCH_MP SER_ZERO w0 in
1226    let w2 = BETA_RULE w1 in
1227    let w3 = SPEC `C2:real` SEQ_CONST in
1228    let w4 = CONJ w3 w2 in
1229    let w5 = BETA_RULE (MATCH_MP SEQ_MUL w4) in
1230    let w6 = ONCE_REWRITE_RULE [REAL_ARITH `(C2:real) * (&0) = &0`] w5 in
1231    let w7 = ONCE_REWRITE_RULE [SEQ] w6 in
1232    let w8 = GEN_ALL (BETA_RULE w7) in
1233    (REPEAT STRIP_TAC) THEN
1234    (CHOOSE_TAC (UNDISCH (SPEC_ALL w8))) THEN
1235    (EXISTS_TAC `SUC N`) THEN
1236    (ASM_SIMP_TAC [ARITH_RULE `n' >= SUC n ==> n' >= n`])
1237 )
1238
1239 let RHS_4_LT_ONE_MESSY = prove(
1240    `?p0. !p. p > 1 ==> p> p0 ==> abs (RHS c (g (PRE (LENGTH c)) p)) < &1`,
1241    let c1 = ONCE_REWRITE_RULE [ UNDISCH JESSE_POW_LEMMA ] RHS_4_BOUND in
1242    let c2 = SPECL [`real_pow (&(PRE (LENGTH (c:(real)list)))) (p-1)`]
1243    REAL_MUL_SYM in
1244    let c3 = ONCE_REWRITE_RULE [ c2] c1 in
1245    let c4 = ONCE_REWRITE_RULE [ GSYM REAL_MUL_ASSOC ] c3 in
1246    let c5 = ONCE_REWRITE_RULE [ GSYM REAL_POW_MUL ] c4 in
1247    let c6 = ONCE_REWRITE_RULE [REAL_MUL_SYM] (CONJUNCT2 real_pow) in
1248    let c7 = ONCE_REWRITE_RULE [GSYM c6] c5 in
1249    let c8 = REAL_ARITH `!x. (real_of_num 1)/x = inv x` in
1250    let c9 = ONCE_REWRITE_RULE [c8] c7 in
1251    let c10 = REAL_ARITH `!x y z.(inv x) * y * z = y * inv x * z` in
1252    let c11 = ONCE_REWRITE_RULE [c10] c9 in
1253    let t0 =
1254     `sum (1..PRE (LENGTH c)) & *
1255      max_abs c *
1256      (exp (&(PRE (LENGTH c)))) *
1257      &(PRE (LENGTH c)) pow PRE (LENGTH c)` in
1258    let t1 = `real_of_num (PRE (LENGTH (c:(real)list))) pow SUC (PRE (LENGTH c))`
1259    in
1260    let int0 = SPECL [t0;t1;`real_of_num 1`]  OLDGERMAN_LEMMA in
1261    let int1 = SIMP_RULE [REAL_ARITH `(real_of_num 0) < &1`] int0 in
1262    let int2 = SIMP_RULE [REAL_ARITH `x - (real_of_num 0) = x`] int1 in
1263    let t8 = `!n. n >= N
1264         ==> abs
1265             ((sum (1..PRE (LENGTH c)) & *
1266               max_abs c *
1267               (exp (&(PRE (LENGTH c)))) *
1268               &(PRE (LENGTH c)) pow PRE (LENGTH c)) *
1269              inv (&(FACT n)) *
1270              &(PRE (LENGTH c)) pow SUC (PRE (LENGTH c)) pow n) <
1271             &1` in
1272    let int5 = ASSUME t8 in
1273    let int50 = REAL_ARITH `((x:real) * y * z * w) * (a * b) = x * y * z * w * a *
1274    b` in
1275    let int51 = ONCE_REWRITE_RULE [int50] int5 in
1276    let int6 = SPEC `p - 1` int51 in
1277    let int7 = ARITH_RULE ` (p > N ==> p - 1 >= N)` in
1278    let int8 = UNDISCH (IMP_TRANS int7 int6) in
1279    let int9 = ARITH_RULE `(x:real) <= y ==> y < (real_of_num 1) ==> x < (&1)` in
1280    let int10 = MATCH_MP JESSE_REAL_ABS_LE c11 in
1281    let int11 = MATCH_MP int9 int10 in
1282    let int12 = MP int11 int8 in
1283    (CHOOSE_TAC int2) THEN
1284    (EXISTS_TAC `N:num`) THEN
1285    (STRIP_TAC) THEN
1286    (STRIP_TAC) THEN
1287    (ONCE_REWRITE_TAC [ARITH_RULE `p > 0 ==> ((p:num)  > N <=> p - 1 >= N)`]) THEN
1288    (DISCH_TAC) THEN
1289    (MATCH_ACCEPT_TAC int12)
1290 )
1291 let LT_ONE = prove(
1292         `!c. ?p0. !p. p> p0 ==> abs (RHS c (g (PRE (LENGTH c)) p)) < &1`,
1293     STRIP_TAC THEN (CHOOSE_TAC RHS_4_LT_ONE_MESSY) THEN (EXISTS_TAC `SUC p0`) THEN
1294     (ASM_MESON_TAC [ARITH_RULE `p > SUC p0 ==> (p > p0 /\ p > 1)`])
1295 )
1296 end;;
1297
1298
1299
1300
1301 module Pm_eqn4_lhs = struct
1302
1303 let N_IS_INT = prove(
1304     `!n . integer (&n)`,
1305     MESON_TAC [is_int]
1306 )
1307 let NEG_N_IS_INT = prove(
1308     `!n . integer (--(&n))`,
1309     MESON_TAC [is_int]
1310 )
1311 let INT_OF_REAL_ADD = prove(
1312     `!x y.(integer x) /\ (integer y)
1313            ==> (int_of_real (x + y)) =
1314                (int_of_real x) + (int_of_real y)`,
1315     SIMP_TAC[integer;int_add;int_rep;N_IS_INT;NEG_N_IS_INT]
1316 )
1317 let INT_OF_REAL_MUL = prove(
1318     `!x y.(integer x) /\ (integer y)
1319            ==> (int_of_real (x * y)) =
1320                (int_of_real x) * (int_of_real y)`,
1321     SIMP_TAC[is_int;int_mul;int_rep;N_IS_INT;NEG_N_IS_INT]
1322 )
1323
1324 let rec INT_OF_REAL_CONV_helper t =
1325     let real_op_2_int_op t =
1326         if (t = `real_add`) then `int_add`
1327         else if (t = `real_sub`) then `int_sub`
1328         else if (t = `real_mul`) then `int_mul`
1329         else if (t = `real_pow`) then `int_pow`
1330         else if (t = `real_neg`) then `int_neg`
1331         else t
1332     in
1333     if (is_var t) then (mk_comb (`int_of_real`,t),[],[t])
1334     else if ((rator t) = `real_of_num`) then
1335       (mk_comb (`int_of_real`, t),[t],[])
1336     else if ((rator t) = `real_neg`) then
1337       let rand1 = rand t in
1338       let (expr1,lst1,lst2) = INT_OF_REAL_CONV_helper rand1 in
1339       let lst = lst1 @ [t] in
1340       let expr = mk_comb (`int_neg`, expr1) in
1341       (expr,lst,lst2)
1342     else if ((rator (rator t)) = `real_pow`) then
1343       let rand1 = rand (rator t) in
1344       let exponent = rand t in
1345       let (expr1,lst1,lst2) = INT_OF_REAL_CONV_helper rand1 in
1346       let lst = lst1 @ [t] in
1347       let expr = mk_comb (mk_comb (`int_pow`,expr1),exponent) in
1348       (expr,lst,lst2)
1349     else if (   ((rator (rator t)) = `real_add`)
1350              or ((rator (rator t)) = `real_mul`)
1351              or ((rator (rator t)) = `real_sub`)  ) then
1352       let int_op = real_op_2_int_op (rator (rator t)) in
1353       let rand1 = rand (rator t) in
1354       let rand2 = rand t in
1355       let (expr1,lst11,lst12) = INT_OF_REAL_CONV_helper rand1 in
1356       let (expr2,lst21,lst22) = INT_OF_REAL_CONV_helper rand2 in
1357       let lst1 = lst11 @ lst21 @ [t] in
1358       let lst2 = lst12 @ lst22 in
1359       let expr = mk_comb (mk_comb (int_op,expr1),expr2) in
1360       (expr,lst1,lst2)
1361     else (t,[],[t])
1362
1363
1364 (* ------------------------------------------------------------------------- *)
1365 (* I wrote an initial version of this, but John Harrison proposed this       *)
1366 (* version which is faster and also requires less theorems.                  *)
1367 (* ------------------------------------------------------------------------- *)
1368 let INT_OF_REAL_CONV =
1369   let final_tweak = MATCH_MP(MESON[int_tybij] `real_of_int x = y ==> int_of_real y = x`) in
1370   fun t ->
1371     let (exp,real_sub_terms,is_int_assumpts) = INT_OF_REAL_CONV_helper t in
1372     let is_int_assumpts = List.map (fun x -> mk_comb (`integer`,x)) is_int_assumpts in
1373     let fexp = rand(concl(PURE_REWRITE_CONV[GSYM int_of_num] exp)) in
1374     let rexp = mk_comb(`real_of_int`,fexp)
1375     and ths = map (GEN_REWRITE_RULE I [CONJUNCT2 int_tybij] o ASSUME) is_int_assumpts in
1376     let th3 = PURE_REWRITE_CONV(ths @ [int_pow_th; int_add_th; int_mul_th; int_sub_th; int_neg_th; int_of_num_th]) rexp in
1377     itlist DISCH is_int_assumpts (final_tweak th3)
1378
1379 let ALL_IS_INT = prove(
1380     `! h t . (ALL integer (CONS h t)) ==> (integer h)  /\ (ALL integer t)`,
1381     SIMP_TAC [ALL]
1382 )
1383
1384 let ALL_IS_INT_POLY_ADD = prove(
1385     `! p1 p2 . (ALL integer p1) /\ (ALL integer p2) ==> (ALL integer (p1 ++ p2))`,
1386     let lem01 = UNDISCH (SPECL [`h:real`;`t:(real)list`] ALL_IS_INT) in
1387     let [lem02;lem03] = CONJUNCTS lem01 in
1388     let lem04 = UNDISCH (SPECL [`h':real`;`t':(real)list`] ALL_IS_INT) in
1389     let [lem05;lem06] = CONJUNCTS lem04 in
1390     let lem07 = CONJ lem02 lem05 in
1391     let lem08 = MATCH_MP INTEGER_ADD lem07 in
1392     let lem09 = ASSUME `! p2. ALL integer t /\ ALL integer p2 ==> ALL integer (t ++ p2)` in
1393     let lem10 = SPEC `t':(real)list` lem09 in
1394     let lem11 = CONJ lem03 lem06 in
1395     let lem12 = MP lem10 lem11 in
1396     LIST_INDUCT_TAC THENL
1397     [ (SIMP_TAC [poly_add]);
1398       LIST_INDUCT_TAC THENL
1399       [ (SIMP_TAC [poly_add]);
1400         (SIMP_TAC [poly_add]) THEN (ONCE_REWRITE_TAC [NOT_CONS_NIL]) THEN
1401         (SIMP_TAC []) THEN (SIMP_TAC [HD;TL]) THEN (STRIP_TAC) THEN
1402         (SIMP_TAC [ALL]) THEN
1403         (CONJ_TAC) THENL [(ACCEPT_TAC lem08); (ACCEPT_TAC lem12)]
1404       ]
1405     ]
1406 )
1407 let ALL_IS_INT_POLY_CMUL = prove(
1408     `! p c. (integer c) /\ (ALL integer p) ==> (ALL integer (c ## p))`,
1409     (LIST_INDUCT_TAC) THEN (ASM_SIMP_TAC [poly_cmul;ALL;INTEGER_MUL])
1410 )
1411
1412 let ALL_IS_INT_POLY_MUL = prove(
1413     `! p1 p2 . (ALL integer p1) /\ (ALL integer p2) ==> (ALL integer (p1 ** p2))`,
1414     let lem01 = UNDISCH (SPECL [`h:real`;`t:(real)list`] ALL_IS_INT) in
1415     let lem02 = UNDISCH (SPECL [`h':real`;`t':(real)list`] ALL_IS_INT) in
1416     let [lem03;lem04] = CONJUNCTS lem01 in
1417     let [lem05;lem06] = CONJUNCTS lem02 in
1418     let lem07 = MATCH_MP INTEGER_MUL (CONJ lem03 lem05) in
1419     let lem08 = MATCH_MP ALL_IS_INT_POLY_CMUL (CONJ lem03 lem06) in
1420     let lem09 = ASSUME `! p2. ALL integer t /\ ALL integer p2 ==> ALL integer (t ** p2)` in
1421     let lem10 = SPEC `(CONS h' t'):(real)list` lem09 in
1422     LIST_INDUCT_TAC THENL
1423     [ (LIST_INDUCT_TAC THENL [(SIMP_TAC [ALL;poly_mul]);(SIMP_TAC [poly_mul])]);
1424       LIST_INDUCT_TAC THENL
1425       [ (SIMP_TAC [poly_mul]) THEN
1426         ((ASM_CASES_TAC `(t:(real)list) = []`) THENL
1427         [ (ASM_SIMP_TAC [ALL;poly_cmul]) THEN (SIMP_TAC [poly_cmul]);
1428           (ASM_SIMP_TAC [ALL;poly_cmul;poly_add]) THEN (SIMP_TAC [SPEC `0` N_IS_INT])
1429         ]);
1430         (STRIP_TAC) THEN (ONCE_REWRITE_TAC [poly_mul] ) THEN
1431         (ASM_CASES_TAC `(t:(real)list) = []`) THENL
1432         [ (ASM_SIMP_TAC [ALL;poly_cmul]) THEN STRIP_TAC THENL
1433           [(ACCEPT_TAC lem07) ;(ACCEPT_TAC lem08)];
1434           (ASM_SIMP_TAC []) THEN (MATCH_MP_TAC ALL_IS_INT_POLY_ADD) THEN
1435           (CONJ_TAC) THENL
1436           [ (MATCH_MP_TAC ALL_IS_INT_POLY_CMUL) THEN (CONJ_TAC) THENL
1437             [(ACCEPT_TAC lem03) ; (ASM_SIMP_TAC[])];
1438             (SIMP_TAC [ALL]) THEN (CONJ_TAC) THENL
1439             [(ACCEPT_TAC (SPEC `0` N_IS_INT)); (ASM_SIMP_TAC [lem04;lem10])]
1440           ]
1441         ]
1442       ]
1443     ]
1444 )
1445 let NOT_POLY_MUL_ITER_NIL = prove(
1446     `! n . ~((poly_mul_iter (\i.[ -- &i; &1]) n) = [])`,
1447     let lem02 = SIMP_RULE [NOT_CONS_NIL] (ISPEC `[ -- &(SUC n); &1]` NOT_POLY_MUL_NIL ) in
1448     let lem03 = ISPEC `(poly_mul_iter (\i.[ -- &i; &1]) n)` lem02 in
1449     let lem04 = UNDISCH  lem03 in
1450     INDUCT_TAC THENL
1451     [ (SIMP_TAC [Pm_eqn5.POLY_MUL_ITER;NOT_CONS_NIL]);
1452       (SIMP_TAC [Pm_eqn5.POLY_MUL_ITER;lem04])
1453     ]
1454 )
1455
1456 let ALL_IS_INT_POLY_MUL_ITER = prove(
1457     `! n. (ALL integer (poly_mul_iter (\i.[-- &i; &1]) n))`,
1458     let FOOBAR_LEMMA =  prove(
1459         `ALL integer [-- &(SUC n); &1]`,
1460         (SIMP_TAC [ALL]) THEN (SIMP_TAC [N_IS_INT;NEG_N_IS_INT])) in
1461     INDUCT_TAC THENL
1462     [ (ONCE_REWRITE_TAC [Pm_eqn5.POLY_MUL_ITER]) THEN
1463       (ONCE_REWRITE_TAC [ALL]) THEN (SIMP_TAC [ALL;N_IS_INT]);
1464       (ONCE_REWRITE_TAC [Pm_eqn5.POLY_MUL_ITER]) THEN (BETA_TAC) THEN
1465       (MATCH_MP_TAC ALL_IS_INT_POLY_MUL) THEN (CONJ_TAC) THENL
1466       [(ACCEPT_TAC (FOOBAR_LEMMA)); (ASM_SIMP_TAC [])]
1467     ]
1468 )
1469
1470 let ALL_IS_INT_POLY_EXP = prove(
1471     `!n p. (ALL integer p) ==> (ALL integer (poly_exp p n))`,
1472     let lem01 = ASSUME `! p. ALL integer p ==> ALL integer (poly_exp p n)` in
1473     let lem02 = ASSUME ` ALL integer p` in
1474     let lem03 = MP (SPEC_ALL lem01) lem02 in
1475     let lem04 = CONJ lem02 lem03 in
1476     let lem05 = MATCH_MP ALL_IS_INT_POLY_MUL lem04 in
1477     INDUCT_TAC THENL
1478     [ (ONCE_REWRITE_TAC [poly_exp]) THEN (ONCE_REWRITE_TAC [ALL]) THEN
1479       (ONCE_REWRITE_TAC [ALL]) THEN (SIMP_TAC [SPEC `1` N_IS_INT]);
1480       (ONCE_REWRITE_TAC [poly_exp]) THEN (REPEAT STRIP_TAC) THEN (ACCEPT_TAC lem05)
1481    ]
1482 )
1483
1484 let BLAHBLAH = prove(
1485     `! p1 p2. (LENGTH p1 <= LENGTH p2) ==> (&0 ## p1 ++ p2) = p2`,
1486      LIST_INDUCT_TAC THENL
1487      [ (SIMP_TAC [LENGTH;poly_cmul;poly_add]);
1488        LIST_INDUCT_TAC THENL
1489        [ (SIMP_TAC [LENGTH]) THEN ARITH_TAC;
1490          (ASM_SIMP_TAC [poly_cmul;poly_add;NOT_CONS_NIL;HD;TL;
1491                         REAL_ARITH `&0 * h + h' = h'`;LENGTH;
1492                         ARITH_RULE `(SUC x) <= (SUC y) <=> x <= y`]) ]
1493      ]
1494 )
1495
1496 let BLAHBLAH3 = prove(
1497     `! n h t. (LENGTH t) <= LENGTH (poly_exp [&0;&1] n ** CONS h t)`,
1498     let lem04 = ASSUME `! h t . LENGTH t <= LENGTH (poly_exp [&0;&1] n ** CONS h t)` in
1499     let lem05 = SPECL [`h:real`;`t:(real)list`] lem04  in
1500     let lem06 = ARITH_RULE `!(x:num) y . x <= y ==> x <= SUC y` in
1501     let lem07 = MATCH_MP lem06 lem05   in
1502     let lem08 = GEN_ALL lem07  in
1503      INDUCT_TAC THENL
1504      [ (SIMP_TAC [poly_exp;poly_mul;poly_cmul;POLY_CMUL_LID;LENGTH]) THEN ARITH_TAC;
1505        (SIMP_TAC [POLY_EXP_X_REC;poly_mul;NOT_POLY_EXP_X_NIL;poly_cmul;poly_add;NOT_CONS_NIL;LENGTH;TL]) THEN
1506        (ASM_SIMP_TAC [BLAHBLAH]) THEN (ACCEPT_TAC lem08)
1507     ]
1508 )
1509 let TELEVISION = prove (
1510     `!n p.(~ (p = [])) ==>  EL n (poly_exp [&0;&1] n ** p) = HD p`,
1511     let lem = MATCH_MP BLAHBLAH (SPEC_ALL BLAHBLAH3) in
1512     INDUCT_TAC THENL
1513     [ (SIMP_TAC [EL;poly_exp;POLY_MUL_CLAUSES]) THEN (LIST_INDUCT_TAC) THENL
1514       [ (SIMP_TAC[]); (SIMP_TAC [NOT_CONS_NIL;POLY_CMUL_LID])];
1515         (SIMP_TAC [EL;POLY_EXP_X_REC;poly_mul;NOT_POLY_EXP_X_NIL]) THEN
1516         LIST_INDUCT_TAC THENL
1517         [ (SIMP_TAC []);
1518           (SIMP_TAC [poly_cmul;poly_add;NOT_CONS_NIL;TL;HD]) THEN
1519           (ASM_SIMP_TAC [lem;NOT_CONS_NIL;HD])
1520         ]
1521     ]
1522 )
1523 let JOSHUA = prove(
1524     `!i n p.(~ (p = [])) /\ (i < n) ==>  EL i (poly_exp [&0;&1] n ** p) = &0`,
1525     let lem0000 = SPECL [`t:(real)list`;`poly_exp [&0;&1] n ** (CONS h t)`] BLAHBLAH in
1526     let lem0001 = MATCH_MP lem0000 (SPEC_ALL BLAHBLAH3)  in
1527     let lem0002 = ASSUME `! n p . ~(p = []) /\ i < n ==> EL i (poly_exp [&0;&1] n ** p) = &0` in
1528     let lem0003 = SIMP_RULE [NOT_CONS_NIL] (SPECL [`n:num`;`(CONS (h:real) t)`] lem0002) in
1529     INDUCT_TAC THENL
1530     [ INDUCT_TAC THENL
1531       [ ARITH_TAC ;
1532         LIST_INDUCT_TAC THENL
1533         [ (SIMP_TAC[]);
1534           (SIMP_TAC [POLY_EXP_X_REC;EL;HD;poly_mul;NOT_POLY_EXP_NIL;NOT_CONS_NIL;HD_POLY_ADD;poly_cmul]) THEN
1535            REAL_ARITH_TAC
1536         ]
1537       ];
1538       INDUCT_TAC THENL
1539       [ ARITH_TAC;
1540        (SIMP_TAC [EL;POLY_EXP_X_REC;poly_mul;NOT_POLY_EXP_NIL;NOT_CONS_NIL]) THEN
1541        LIST_INDUCT_TAC THENL
1542        [ (SIMP_TAC[]);
1543          (SIMP_TAC [poly_cmul;poly_add;NOT_CONS_NIL;TL;lem0001]) THEN
1544          (SIMP_TAC [ARITH_RULE `(SUC i) < (SUC n) <=> i < n`;lem0003])
1545        ]
1546       ]
1547     ]
1548 )
1549 let POLY_MUL_HD = prove(
1550     `! p1 p2. (~(p1 = []) /\ ~(p2 = [])) ==> (HD (p1 ** p2)) = (HD p1) * (HD p2)`,
1551     LIST_INDUCT_TAC THENL
1552     [ (SIMP_TAC[]);
1553       (LIST_INDUCT_TAC) THENL
1554       [ (SIMP_TAC[]);
1555         (SIMP_TAC [NOT_CONS_NIL]) THEN (ONCE_REWRITE_TAC [poly_mul]) THEN
1556         (ASM_CASES_TAC `(t:(real)list) = []`) THENL
1557         [ (ASM_SIMP_TAC [HD;poly_cmul]);
1558           (ASM_SIMP_TAC [HD;poly_cmul;poly_add]) THEN
1559           (SIMP_TAC [NOT_CONS_NIL;HD]) THEN (REAL_ARITH_TAC)
1560         ]
1561       ]
1562     ]
1563 )
1564 let POLY_MUL_ITER_HD_FACTORIAL = prove(
1565     `! n. (HD (poly_mul_iter (\i.[-- &i; &1]) n)) = ((-- &1) pow n) * (&(FACT n))`,
1566     let lem01 = prove(`~([-- &(SUC n); &1] = [])`,SIMP_TAC [NOT_CONS_NIL]) in
1567     let lem02 = ISPECL
1568                   [`[-- &(SUC n); &1]`;`poly_mul_iter (\i.[-- &i; &1]) n`]
1569                   POLY_MUL_HD in
1570     let lem03 = CONJ lem01 (SPEC_ALL NOT_POLY_MUL_ITER_NIL) in
1571     let lem04 = MP lem02 lem03 in
1572     let lem05 = prove(
1573         `!n. ((-- &1) pow n) = -- ((-- &1) pow (SUC n))`,
1574         STRIP_TAC THEN (ONCE_REWRITE_TAC [pow]) THEN REAL_ARITH_TAC
1575     ) in
1576     INDUCT_TAC THENL
1577     [ (ONCE_REWRITE_TAC [Pm_eqn5.POLY_MUL_ITER]) THEN (SIMP_TAC [HD;FACT]) THEN REAL_ARITH_TAC;
1578       (ONCE_REWRITE_TAC [Pm_eqn5.POLY_MUL_ITER]) THEN BETA_TAC THEN
1579       (ONCE_REWRITE_TAC [lem04]) THEN (ONCE_REWRITE_TAC [HD]) THEN
1580       (ASM_SIMP_TAC []) THEN (ONCE_REWRITE_TAC [FACT]) THEN
1581       (ONCE_REWRITE_TAC [GSYM REAL_OF_NUM_MUL]) THEN
1582       (CONV_TAC (RATOR_CONV (ONCE_REWRITE_CONV [lem05]))) THEN REAL_ARITH_TAC
1583     ]
1584 )
1585 let PLANETMATH_THM_5_1 =  prove(
1586     `! n p.
1587        p > 0 ==>
1588        n > 0 ==>
1589        ? As .
1590           ((g n p) = (&1/(&(FACT (p  - 1)))) ## As)
1591        /\ (! i. i< (p-1) ==> (EL i As) = &0)
1592        /\ ((EL (p-1) As) = ((-- &1) pow (n * p)) * ((&(FACT n)) pow p))
1593        /\ (ALL integer As)`,
1594     let lem01 = SPECL [`poly_exp [&0;&1] (p - 1)`;`poly_exp (poly_mul_iter (\i.[-- &i; &1]) n) p`] ALL_IS_INT_POLY_MUL in
1595     let lem02 = SPECL [`p-1`;`[&0;&1]`] ALL_IS_INT_POLY_EXP in
1596     let lem03 = prove(`ALL integer [&0;&1]`, (REWRITE_TAC [ALL]) THEN (SIMP_TAC [N_IS_INT])) in
1597     let lem04 = MP lem02 lem03 in
1598     let lem05 = SPECL [`p:num`;`poly_mul_iter (\i.[-- &i; &1]) n`] ALL_IS_INT_POLY_EXP in
1599     let lem06 = MP lem05 (SPEC_ALL ALL_IS_INT_POLY_MUL_ITER)  in
1600     let lem07 = MP lem01 (CONJ lem04 lem06)  in
1601     let lem08 = SPECL [`p-1`;`poly_exp (poly_mul_iter (\i.[-- &i; &1]) n) p`] TELEVISION in
1602     let lem09 = SIMP_RULE [ NOT_POLY_EXP_NIL;NOT_POLY_MUL_ITER_NIL] lem08 in
1603     let lem10 = SPECL [`i:num`;`p - 1`;`poly_exp (poly_mul_iter (\i. [ -- &i; &1]) n ) p`] JOSHUA in
1604     let lem11 = SIMP_RULE [NOT_POLY_MUL_ITER_NIL;NOT_POLY_EXP_NIL] lem10 in
1605     (REPEAT STRIP_TAC) THEN
1606     (EXISTS_TAC `((poly_exp [&0;&1] (p-1)) ** (poly_exp (poly_mul_iter (\i.[-- &i; &1]) n) p))`) THEN
1607     CONJ_TAC THENL
1608     [ (ONCE_REWRITE_TAC [Pm_eqn5.PLANETMATH_EQN_5]) THEN (SIMP_TAC[]);
1609       CONJ_TAC THENL
1610       [ (SIMP_TAC [lem11]);
1611         CONJ_TAC THENL
1612         [ (ONCE_REWRITE_TAC [lem09]) THEN
1613           (SPEC_TAC (`n:num`,`n:num`)) THEN
1614           (INDUCT_TAC) THENL
1615           [ (SIMP_TAC [NOT_CONS_NIL;HD_POLY_EXP;HD;Pm_eqn5.POLY_MUL_ITER;FACT;pow;
1616                        REAL_POW_ONE;ARITH_RULE `0 * p = 0`;REAL_ARITH `&1 * &1 = &1`]);
1617             (SIMP_TAC [HD_POLY_EXP; NOT_POLY_MUL_ITER_NIL; POLY_MUL_ITER_HD_FACTORIAL]) THEN
1618             (SIMP_TAC [REAL_POW_MUL;REAL_POW_POW;BLAHBLAH3]) ];
1619           ACCEPT_TAC lem07 ]
1620       ]
1621     ]
1622 )
1623 let as_def =
1624     let ll01 = SPEC_ALL PLANETMATH_THM_5_1 in
1625     let FO_LEMMA1 = prove(`((p > 0) ==> (n > 0) ==> (? z. C p n z))
1626                             <=> (? z. (p > 0) ==> (n > 0) ==> C p n z)`,MESON_TAC[]) in
1627     let ll02 = GEN_ALL (SIMP_RULE [FO_LEMMA1] ll01) in
1628     let ll03 = ONCE_REWRITE_RULE [SKOLEM_CONV (concl ll02)] ll02 in
1629     new_specification ["As"] ll03
1630 (* split up def of As into its four conjuncts *)
1631 let g_eq_As
1632     = (GEN_ALL o DISCH_ALL o CONJUNCT1 o  UNDISCH o UNDISCH o SPEC_ALL) as_def
1633 let prefix_As_zero
1634     = (GEN_ALL o DISCH_ALL o CONJUNCT1 o CONJUNCT2 o  UNDISCH o UNDISCH o SPEC_ALL) as_def
1635 let fact_As
1636     = (GEN_ALL o DISCH_ALL o CONJUNCT1 o CONJUNCT2 o CONJUNCT2 o  UNDISCH o UNDISCH o SPEC_ALL) as_def
1637 let ALL_integer_As
1638     = (GEN_ALL o DISCH_ALL o CONJUNCT2 o CONJUNCT2 o CONJUNCT2 o  UNDISCH o UNDISCH o SPEC_ALL) as_def
1639
1640 let POLY_DIFF_AUX_LEM1 = prove(
1641     `! i p k. i < (LENGTH p) ==> EL i (poly_diff_aux k p) = (EL i p) * &(i + k)`,
1642     let lem0001 = ASSUME `! p k . i < LENGTH p ==> EL i (poly_diff_aux k p ) = EL i p * &(i + k)` in
1643     let lem0002 = SPECL [` t:(real)list`;`SUC k`] lem0001 in
1644     let lem0003 = prove(`SUC i < LENGTH (CONS (h:real) t) <=> i < LENGTH t`,(SIMP_TAC [LENGTH]) THEN ARITH_TAC) in
1645     INDUCT_TAC THENL
1646     [ LIST_INDUCT_TAC THENL
1647       [ (SIMP_TAC [poly_diff_aux;LENGTH]) THEN ARITH_TAC;
1648         (SIMP_TAC [poly_diff_aux;ARITH_RULE `0 + k = k`;poly_diff;LENGTH;EL;HD;TL]) THEN REAL_ARITH_TAC ];
1649       LIST_INDUCT_TAC THENL
1650       [ (SIMP_TAC [LENGTH]) THEN ARITH_TAC;
1651         (SIMP_TAC [poly_diff_aux;EL;TL]) THEN STRIP_TAC THEN
1652         (SIMP_TAC [lem0003;lem0002;ARITH_RULE `i + SUC k = SUC i + k`]) ]
1653     ]
1654 )
1655 let EL_POLY_DIFF = prove(
1656     `! i p. i < (LENGTH (poly_diff p)) ==> EL i (poly_diff p) = (EL (SUC i) p) * &(SUC i)`,
1657     let lem01 =  SPECL [`SUC i`;`t:(real)list`;`1`] POLY_DIFF_AUX_LEM1  in
1658     INDUCT_TAC THENL
1659     [ LIST_INDUCT_TAC THENL
1660       [ ((SIMP_TAC [LENGTH;poly_diff]) THEN ARITH_TAC);
1661         (SIMP_TAC [LENGTH;PRE;EL;HD;TL;ARITH_RULE `SUC 0 = 1`;REAL_ARITH `x * &1 = x`;poly_diff;NOT_CONS_NIL]) THEN
1662         (SPEC_TAC (`t:(real)list`,`t:(real)list`)) THEN
1663         LIST_INDUCT_TAC THENL [(SIMP_TAC [LENGTH;poly_diff_aux]) THEN ARITH_TAC;
1664                                (SIMP_TAC [HD;poly_diff_aux;REAL_ARITH `&1 * h = h`])]
1665      ];
1666      LIST_INDUCT_TAC THENL
1667      [ ((SIMP_TAC [LENGTH;HD;poly_diff;REAL_ARITH `&1 * h = h`])) THEN ARITH_TAC;
1668         (SIMP_TAC [poly_diff;NOT_CONS_NIL;TL;LENGTH_POLY_DIFF_AUX ]) THEN (SIMP_TAC [lem01;EL;TL]) THEN ARITH_TAC ]
1669      ]
1670 )
1671 let POLY_AT_ZERO = prove(
1672     `!p .(~(p = [])) ==> poly p (&0) = HD p`,
1673     LIST_INDUCT_TAC THENL [ SIMP_TAC []; (SIMP_TAC [poly;HD]) THEN REAL_ARITH_TAC ]
1674 )
1675 let PDI_POLY_DIFF_COMM = prove(
1676     `! p n.(poly_diff_iter (poly_diff p) n) = (poly_diff (poly_diff_iter p n))`,
1677     STRIP_TAC THEN INDUCT_TAC THENL
1678     [(SIMP_TAC [Pm_lemma1.PDI_DEF]);
1679      (ONCE_REWRITE_TAC [Pm_lemma1.PDI_DEF]) THEN (ASM_SIMP_TAC [])]
1680 )
1681 let EL_PDI_AT_ZERO = prove(
1682      `!i p. (i < (LENGTH p))
1683          ==> ( poly (poly_diff_iter p i) (&0)) = ((EL i p) * (&(FACT i)))`,
1684     let lem03 = prove(`SUC i < LENGTH (CONS (h:real) t) <=> i < LENGTH t`,(SIMP_TAC [LENGTH]) THEN ARITH_TAC) in
1685     let lem04 = ASSUME `!p . i < LENGTH p ==> poly (poly_diff_iter p i) (&0) = EL i p * &(FACT i)` in
1686     let lem05 = SIMP_RULE [LENGTH_POLY_DIFF;LENGTH;PRE] (SPEC `poly_diff (CONS h t)` lem04) in
1687     let lem06 = prove(`i < LENGTH t ==> i < LENGTH (poly_diff (CONS h t))`,SIMP_TAC [LENGTH_POLY_DIFF;PRE;LENGTH]) in
1688     INDUCT_TAC THENL
1689     [ (LIST_INDUCT_TAC THENL
1690       [(SIMP_TAC [LENGTH]) THEN ARITH_TAC; (SIMP_TAC [Pm_lemma1.PDI_DEF;FACT;EL;NOT_CONS_NIL;POLY_AT_ZERO]) THEN REAL_ARITH_TAC]);
1691       LIST_INDUCT_TAC THENL
1692       [ (SIMP_TAC [LENGTH]) THEN ARITH_TAC;
1693         (SIMP_TAC [Pm_lemma1.PDI_DEF;GSYM PDI_POLY_DIFF_COMM;lem03;lem05]) THEN
1694         (SIMP_TAC [lem06;EL_POLY_DIFF;FACT;REAL_OF_NUM_MUL;GSYM REAL_MUL_ASSOC])
1695       ]
1696     ]
1697 )
1698 let EL_PDI_AT_ZERO2 = prove(
1699     `!i p. ((~ (p = [])) /\ (i <= (LENGTH p) - 1)) ==> ( poly (poly_diff_iter p i) (&0)) = ((EL i p) * (&(FACT i)))`,
1700     STRIP_TAC THEN LIST_INDUCT_TAC THEN
1701     (SIMP_TAC [NOT_CONS_NIL;LENGTH;ARITH_RULE `(i <= (SUC x) -1) <=> (i < (SUC x))`;EL_PDI_AT_ZERO])
1702 )
1703 let POLY_CMUL_PDI = prove(
1704     `!p c i. (poly_diff_iter (c ## p) i) = c ##(poly_diff_iter p i)`,
1705     STRIP_TAC THEN STRIP_TAC THEN INDUCT_TAC THEN (ASM_SIMP_TAC [Pm_lemma1.PDI_DEF;POLY_CMUL_POLY_DIFF])
1706 )
1707 let LENGTH_g = prove(
1708     `! n p . (LENGTH (g n p)) >= p `,
1709     let lem00 = ARITH_RULE `SUC ((SUC p ) - 1) = SUC p` in
1710     let lem01 = prove(`! n p. ~((poly_exp (poly_mul_iter (\i.[-- &i; &1]) n ) (SUC p)) = [])`,
1711                        SIMP_TAC [NOT_POLY_EXP_NIL; NOT_POLY_MUL_ITER_NIL]) in
1712     let lem02 = MATCH_MP POLY_MUL_LENGTH2 (SPEC_ALL lem01) in
1713     let lem03 = SPECL [`poly_exp [&0;&1] (SUC p - 1)`] lem02 in
1714     let lem04 = SIMP_RULE [POLY_EXP_X_LENGTH] lem03 in
1715     let lem05 = SIMP_RULE [lem00] lem04 in
1716      (SIMP_TAC [Pm_eqn5.PLANETMATH_EQN_5;POLY_CMUL_LENGTH]) THEN STRIP_TAC THEN INDUCT_TAC THENL
1717      [ ARITH_TAC; SIMP_TAC [lem05]]
1718 )
1719 let LENGTH_As = prove(
1720     `! n p . p > 0 ==> n > 0 ==> LENGTH (As n p) >= p`,
1721     let lem50 = ADD_ASSUM `p > 0` (ADD_ASSUM `n > 0` (SPEC_ALL LENGTH_g)) in
1722     let lem51 = ONCE_REWRITE_RULE [UNDISCH_ALL (SPEC_ALL g_eq_As)] lem50 in
1723     let lem52 = ONCE_REWRITE_RULE [POLY_CMUL_LENGTH] lem51 in
1724     SIMP_TAC [lem52]
1725 )
1726 let REAL_MUL_RDIV = prove(
1727     `!x y. ~(y = &0) ==> ((x * y) / y = x)`,
1728     SIMP_TAC[real_div; GSYM REAL_MUL_ASSOC; REAL_MUL_RINV; REAL_MUL_RID]
1729 )
1730 let REAL_MUL_DIV_ASSOC = prove(
1731     `!x y z.((x * z) / y = x * (z / y))`,
1732     SIMP_TAC [real_div;GSYM REAL_MUL_ASSOC]
1733 )
1734 let IS_INT_FACT_DIV = prove(
1735     `! n m. n >= m ==> integer ( (&(FACT n))/(&(FACT m)) )`,
1736     let lem0 = SPEC_ALL (ONCE_REWRITE_RULE [GSYM (SPECL [`FACT n`;`0`] REAL_OF_NUM_EQ)] FACT_NZ) in
1737     let lem1 = SPECL [`&(SUC n)`;`&(FACT n)`]  REAL_MUL_RDIV in
1738     let lem2 = MP lem1 lem0 in
1739     let lem4 = ASSUME `! m. n >= m ==> integer (&(FACT n)/ &(FACT m))` in
1740     let lem5 = UNDISCH (SPEC_ALL lem4) in
1741     let lem6 = prove(`integer(&(SUC n))`,SIMP_TAC [N_IS_INT]) in
1742     let lem7 = CONJ lem6 lem5 in
1743     let lem8 = MATCH_MP INTEGER_MUL lem7  in
1744     let lem9 = UNDISCH_ALL (ARITH_RULE `(~(n >= m)) ==> (SUC n >= m) ==>  m = SUC n`) in
1745     INDUCT_TAC THENL
1746     [ (SIMP_TAC [ARITH_RULE `0 >= m ==> m = 0`;FACT_NZ;REAL_OF_NUM_EQ;REAL_DIV_REFL;N_IS_INT]);
1747       (STRIP_TAC) THEN (ASM_CASES_TAC `(n:num) >= m`) THENL
1748       [ (ASM_SIMP_TAC [FACT;GSYM REAL_OF_NUM_MUL;lem2;N_IS_INT]) THEN
1749         (SIMP_TAC [FACT;GSYM REAL_OF_NUM_MUL;REAL_MUL_DIV_ASSOC;lem8]);
1750         (STRIP_TAC) THEN
1751         (SIMP_TAC [lem9;FACT_NZ;REAL_OF_NUM_EQ;REAL_DIV_REFL;N_IS_INT])
1752       ]
1753     ]
1754 )
1755 let SATURDAY_LEMMA = prove(
1756     `!x. p > 1 ==> m >= p ==> x * ((&(FACT m))/(&(FACT (p-1)))) = x * (&p) * ((&(FACT m))/(&(FACT p)))`,
1757     let lem01 = UNDISCH (ARITH_RULE `p > 1 ==> SUC (p -1) = p`) in
1758     let lem02 = ADD_ASSUM `p > 1` (SPEC `p - 1` (CONJUNCT2 FACT)) in
1759     let lem03 = GSYM (ONCE_REWRITE_RULE [lem01] lem02) in
1760     let lem04 =  SPEC `&p` REAL_DIV_REFL in
1761     let lem05 = ADD_ASSUM `p > 1` (SPECL [`p:num`;`0`] REAL_OF_NUM_EQ) in
1762     let lem06 = SIMP_RULE [UNDISCH (ARITH_RULE `p > 1 ==> ~(p = 0)`)] lem05 in
1763     let lem07 = GSYM (MP lem04 lem06) in
1764     (REPEAT STRIP_TAC) THEN
1765     (CONV_TAC (RATOR_CONV (ONCE_REWRITE_CONV [GSYM REAL_MUL_LID]))) THEN
1766     (ONCE_REWRITE_TAC [lem07]) THEN
1767     (ONCE_REWRITE_TAC [real_div]) THEN
1768     (ONCE_REWRITE_TAC [REAL_ARITH `((x1:real) * x2) * x * (x3 * x4) = x * x1 * (x3 * (x2 * x4))`]) THEN
1769     (ONCE_REWRITE_TAC [GSYM REAL_INV_MUL]) THEN
1770     (ONCE_REWRITE_TAC [REAL_OF_NUM_MUL]) THEN
1771     (SIMP_TAC [REAL_MUL_ASSOC;GSYM REAL_INV_MUL]) THEN
1772     (ONCE_REWRITE_TAC [lem03]) THEN
1773     (SIMP_TAC [REAL_MUL_ASSOC;GSYM REAL_OF_NUM_MUL])
1774 )
1775 let SHRIVER = prove(
1776     `!f0. (!i. m <= i /\ i <= SUC n ==> (f0 i))
1777        ==> (!i. m <= i /\ i <= n ==> (f0 i)) `,
1778     let lem01 = UNDISCH_ALL (ARITH_RULE `i <= n ==> i <= SUC n`) in
1779     let lem02 = CONJ (ASSUME `(m:num) <= (i:num)`) lem01  in
1780     let lem03 = ASSUME `!i. m <= i /\ i <= SUC n ==> (f0 i)` in
1781     let lem04 = SPEC_ALL lem03 in
1782     let lem05 = MP lem04 lem02 in
1783     (REPEAT STRIP_TAC) THEN (ACCEPT_TAC lem05)
1784 )
1785 let IS_INT_SUM = prove(
1786  `!f n m.(!i.m <= i /\  i <= n ==> integer (f i)) ==> integer (sum (m..n) f)`,
1787   let l0 = SPECL [`m:num`;`n:num`;`i:num`] IN_NUMSEG in
1788   let l1 = SPECL [`m:num`;`SUC n`] NUMSEG_EMPTY in
1789   let l2 = ADD_ASSUM `SUC n < m` l1 in
1790   let l3 = ASM_REWRITE_RULE [] l2 in
1791   let l4 = (UNDISCH o ARITH_RULE) `~(SUC n < m) ==> m <= SUC n` in
1792   let l5 = ONCE_REWRITE_RULE [GSYM IN_NUMSEG] SHRIVER in
1793   let l6 = SPEC `\(i:num).(integer (f i))` l5 in
1794   let l7 = BETA_RULE l6 in
1795   let l8 = ASSUME `! m. (!i. i IN m..n ==> integer (f i)) ==> integer (sum (m..n) f)` in
1796   let l9 = SPEC_ALL l8 in
1797   let l10 = UNDISCH (IMP_TRANS l7 l9) in
1798   let jj0 = ARITH_RULE `(~(SUC n < m)) ==> m <= SUC n /\ (SUC n) <= SUC n` in
1799   let jj1 = UNDISCH (ONCE_REWRITE_RULE [GSYM IN_NUMSEG] jj0) in
1800   let jj2 = SPEC `SUC n` (ASSUME `!i. i IN m.. SUC n ==> integer (f i)`) in
1801   let jj3 = (MP jj2 jj1) in
1802   let l18 = CONJ l10 jj3 in
1803   let l19 = MATCH_MP INTEGER_ADD l18 in
1804   let l20 = DISCH `!i. i IN m..SUC n ==> integer (f i)` l19 in
1805   let l21 = ASSUME `!i . i = 0 ==> integer (f 0)` in
1806   let l22 = SIMP_RULE [] (SPEC `0` l21) in
1807   (ONCE_REWRITE_TAC [GSYM l0]) THEN STRIP_TAC THEN
1808   INDUCT_TAC THENL
1809   [ STRIP_TAC THEN
1810     (ASM_CASES_TAC `m = 0`) THENL
1811     [ (ASM_SIMP_TAC []) THEN
1812       (ONCE_REWRITE_TAC [NUMSEG_CONV `0..0`]) THEN
1813       (ONCE_REWRITE_TAC [ SUM_SING]) THEN
1814       (SIMP_TAC [IN_SING]) THEN (DISCH_TAC) THEN (SIMP_TAC [l22]);
1815       (ASM_SIMP_TAC [NUMSEG_CLAUSES;SUM_CLAUSES;N_IS_INT])
1816     ];
1817     STRIP_TAC THEN (ASM_CASES_TAC `SUC n < m`) THENL
1818     [ (ASM_SIMP_TAC [l3;SUM_CLAUSES;N_IS_INT]);
1819       (ASM_SIMP_TAC [l4;SUM_CLAUSES_NUMSEG]) THEN
1820       (ACCEPT_TAC l20)
1821     ]
1822   ]
1823 )
1824 let ALL_IMP_EL = prove(
1825     `! (l:(a)list) i P. (ALL P l) ==> (i < LENGTH l) ==> P (EL i l)`,
1826     SIMP_TAC[GSYM ALL_EL]
1827 )
1828 let KEY_LEMMA = prove(
1829     `n > 0 ==>
1830      p > 0 ==>
1831     ! i . p <= i /\ i <= (LENGTH (As n p) - 1) ==> integer ((&(FACT i)/ &(FACT p)) * (EL i (As n p)))`,
1832     let jem0 = ISPECL [`(As n p)`;`i:num`;`integer`] ALL_IMP_EL in
1833     let jem1 = MP jem0 (UNDISCH (UNDISCH (SPEC_ALL ALL_integer_As)))  in
1834     let jem3 = ARITH_RULE `LENGTH (As n p) > 0 ==> ((i < LENGTH (As n p)) <=> i <= LENGTH (As n p) - 1)` in
1835     let jem4 = UNDISCH_ALL ((SPEC_ALL LENGTH_As)) in
1836     let jem5 = UNDISCH (ARITH_RULE `p > 0 ==> (LENGTH (As n p) >= p) ==> (LENGTH (As n p) > 0)`) in
1837     let jem6 = MP jem5 jem4 in
1838     let jem7 = MP jem3 jem6 in
1839     let jem8 = ONCE_REWRITE_RULE [jem7] jem1 in
1840     let kem0 = SPECL [`i:num`;`p:num`] IS_INT_FACT_DIV in
1841     let kem1 = ADD_ASSUM  `p <= (i:num)` (ADD_ASSUM `i <= (LENGTH (As n p) - 1)` kem0) in
1842     let kem2 = SIMP_RULE [UNDISCH_ALL (ARITH_RULE `p <= i ==> i <= LENGTH (As n p) -1 ==> i >= p`)] kem1 in
1843     (REPEAT STRIP_TAC) THEN (SIMP_TAC[UNDISCH jem8;kem2;INTEGER_MUL])
1844 )
1845
1846 let KEY_LEMMA2 = prove(
1847     `p > 1 ==>
1848      n > 0 ==>
1849      ? K0 .   integer K0
1850            /\ (&1 / &(FACT ( p - 1))) * (sum (p.. LENGTH (As n p) -1) (\m. EL m (As n p) * &(FACT m))) = (&p) * K0`,
1851     let lem0000 = SPEC `EL m (As n p)` SATURDAY_LEMMA in
1852     let lem1000 = DISCH `m <= LENGTH (As n p) -1` (ADD_ASSUM `m <= LENGTH (As n p) -1` (UNDISCH_ALL lem0000)) in
1853     let lem2000 = DISCH `(m:num) >= p` lem1000 in
1854     let lem3000 = ONCE_REWRITE_RULE [ARITH_RULE `(m:num) >= p <=> p <= m`] lem2000 in
1855     let lem4000 = ONCE_REWRITE_RULE [TAUT `(a ==> b ==> c) <=> ((a  /\ b) ==> c)`] (GEN `m:num` lem3000) in
1856     let lem5000 = MATCH_MP SUM_EQ_NUMSEG lem4000 in
1857     let nem2 = SPECL [`\x.(&(FACT x)/ &(FACT p)) * (EL x (As n p))`;`LENGTH (As n p) - 1`;`p:num`] IS_INT_SUM in
1858     let nem3 = BETA_RULE nem2 in
1859     let nem4 = SIMP_RULE [UNDISCH (UNDISCH KEY_LEMMA)] nem3 in
1860     let nem5 = ADD_ASSUM `p > 1` (DISCH `p > 0` nem4) in
1861     let nem6 = SIMP_RULE [(UNDISCH o ARITH_RULE) `(p:num) > 1 ==> p > 0`] nem5 in
1862     STRIP_TAC THEN STRIP_TAC THEN (ONCE_REWRITE_TAC [GSYM SUM_LMUL]) THEN
1863     (BETA_TAC) THEN (ONCE_REWRITE_TAC [real_div]) THEN (ONCE_REWRITE_TAC [REAL_MUL_LID]) THEN
1864     (ONCE_REWRITE_TAC [REAL_ARITH `(x1:real) * x2 * x3 = x2 * (x3 * x1)`]) THEN
1865     (ONCE_REWRITE_TAC [GSYM real_div]) THEN (ONCE_REWRITE_TAC [lem5000]) THEN
1866     (ONCE_REWRITE_TAC [REAL_ARITH `(x1:real) * x2 * x3 = x2 * (x3 * x1)`]) THEN
1867     (ONCE_REWRITE_TAC [SUM_LMUL]) THEN
1868     (EXISTS_TAC `sum (p .. LENGTH (As n p) -1) (\x. &(FACT x) / &(FACT p) * EL x (As n p))`) THEN
1869     (SIMP_TAC [nem6])
1870 )
1871 let NOT_g_NIL = prove(
1872     `!n p . ~ ((g n p ) = [])`,
1873      SIMP_TAC [Pm_eqn5.PLANETMATH_EQN_5; NOT_CONS_NIL; NOT_POLY_EXP_NIL; NOT_POLY_CMUL_NIL;
1874                NOT_POLY_MUL_NIL;NOT_POLY_MUL_ITER_NIL]
1875 )
1876 let FACT_DIV_RCANCELS = prove(
1877     `!n x. x / &(FACT n) * &(FACT n) = x`,
1878     MESON_TAC [REAL_ARITH `!x. &0 < x ==> ~(x = &0)`;
1879                REAL_DIV_RMUL;FACT_LT;REAL_OF_NUM_LT]
1880 )
1881
1882 let PSUM_ITERATE = prove(
1883     `! n m f. psum (m,n) f
1884               = if (n > 0) then (iterate (+) (m..((n+m)-1)) f) else &0`,
1885     let lem01 = ARITH_RULE `~(n+m=0) ==> (SUC n + m) -1 = SUC ((n + m) -1)` in
1886     let lem02 = MP (ISPEC `(+)` ITERATE_SING) MONOIDAL_REAL_ADD in
1887     let lem03 = prove(
1888           `iterate (+) (m..SUC ((n + m) - 1)) f
1889            = f (SUC ((n+m)-1)) + iterate (+) (m..(n+m)-1) f`,
1890            MESON_TAC [ARITH_RULE `m <= SUC ((n+m)-1)`;ITERATE_CLAUSES_NUMSEG;
1891                       MONOIDAL_REAL_ADD;REAL_ADD_SYM]) in
1892     let lem04 = UNDISCH (UNDISCH (ARITH_RULE `~(n+m=0) ==> n=0 ==> m-1 < m`)) in
1893     let lem05 = SIMP_RULE [lem04] (SPECL [`m:num`;`m-1`] NUMSEG_EMPTY) in
1894     INDUCT_TAC THENL
1895     [ SIMP_TAC [ARITH_RULE `~(0 > 0)`;sum_DEF];
1896       (SIMP_TAC [ARITH_RULE `(SUC n) > 0`]) THEN (REPEAT STRIP_TAC) THEN
1897       (ASM_CASES_TAC `n + m =0`) THENL
1898       [ (REWRITE_TAC [UNDISCH (ARITH_RULE `n + m = 0 ==> n = 0`)]) THEN
1899         (REWRITE_TAC [lem02;NUMSEG_SING;ARITH_RULE `(SUC 0 +m) -1 = m`]) THEN
1900         (MESON_TAC [sum_DEF; ADD_CLAUSES;REAL_ARITH `&0 + x = x`]) ;
1901         (ONCE_REWRITE_TAC [sum_DEF;UNDISCH lem01]) THEN
1902         (REWRITE_TAC [lem03]) THEN (ASM_CASES_TAC `n = 0`) THEN
1903         (ASM_SIMP_TAC
1904           [ARITH_RULE `~(0 > 0)`;ADD_CLAUSES;REAL_ADD_LID;REAL_ADD_RID;
1905            lem05;ITERATE_CLAUSES_GEN; MONOIDAL_REAL_ADD;NEUTRAL_REAL_ADD;
1906            REAL_ADD_SYM;ADD_SYM;ARITH_RULE `~(n=0) ==> n>0 /\ SUC (n-1) = n`])
1907       ]
1908     ]
1909 )
1910
1911
1912 let PLANETMATH_EQN_5_2 = prove(
1913     `p > 1 ==>
1914      n > 0 ==>
1915      (? K0.   integer K0
1916            /\ poly (SOD (g n p)) (&0) =
1917               &(FACT n) pow p * -- &1 pow (n * p) + &p * K0)`,
1918     let lem01 = SPECL [`g n p`;`x:real`;`(&0):real`] Pm_lemma2.PLANETMATH_LEMMA_2_B in
1919     let lem02 = GEN_ALL lem01 in
1920     let lem03 = SPEC_ALL (BETA_RULE lem02) in
1921     let lem04 = SIMP_RULE [FACT_DIV_RCANCELS] lem03 in
1922     let lem05 = SIMP_RULE [PSUM_ITERATE] lem04 in
1923     let lem06 = SIMP_RULE [ARITH_RULE `(n:num) + 0 = n`] lem05 in
1924     let lem07 = ADD_ASSUM `n > 0` (ADD_ASSUM `p > 0` lem06) in
1925     let lem08 = REWRITE_RULE [GSYM LENGTH_EQ_NIL;ARITH_RULE `~(x = 0) <=> x > 0`] NOT_g_NIL in
1926     let lem09 = SIMP_RULE [lem08] lem07 in
1927     let lem10 = CONV_RULE (RAND_CONV (REWRITE_CONV [UNDISCH_ALL (SPEC_ALL g_eq_As)])) lem09 in
1928     let lem11 = SIMP_RULE [POLY_CMUL_LENGTH] lem10 in
1929     let lem12 = SPECL [`m:num`;`(As n p)`] EL_PDI_AT_ZERO in
1930     let lem13 = SIMP_RULE [POLY_CMUL_PDI;POLY_CMUL;lem12] lem11 in
1931     let lem14 = GSYM (BETA `(\m. poly (poly_diff_iter (As n p) m) (&0)) m`) in
1932     let lem15 = ISPECL [`(\m. poly (poly_diff_iter (As n p) m) (&0))`;`&1/ &(FACT (p - 1))`;`0..LENGTH (As n p) -1`] SUM_LMUL in
1933     let lem16 = ONCE_REWRITE_RULE [lem14] lem13 in
1934     let lem17 = ONCE_REWRITE_RULE [GSYM sum] lem16 in
1935     let lem18 = SIMP_RULE [GSYM lem17] lem15 in
1936     let lem20 = SPECL [`(\m.  poly (poly_diff_iter (As n p) m) (&0))`;`(\m. EL m (As n p) * &(FACT m))`;`0`;`LENGTH (As n p) - 1`] SUM_EQ_NUMSEG in
1937     let lem21 = ONCE_REWRITE_RULE [ARITH_RULE `0 <= i`] (BETA_RULE lem20) in
1938     let lem22 = ADD_ASSUM `~(As n p = [])` (ONCE_REWRITE_RULE [EL_PDI_AT_ZERO2] lem21) in
1939     let lem30 = SPECL [`i:num`;`As n p`] EL_PDI_AT_ZERO2 in
1940     let lem31 = ASM_REWRITE_RULE [] (ADD_ASSUM `~(As n p = [])` lem30) in
1941     let lem23 = ONCE_REWRITE_RULE [lem31] lem22 in
1942     let lem24 = REWRITE_RULE [GSYM lem16] lem23 in
1943     let lem25 = ONCE_REWRITE_RULE [lem24] lem18 in
1944     let lem30 = ISPECL [`\m. EL m (As n p) * &(FACT m)`;`0`;`p-1`;`(LENGTH (As n p) - 1) - (p - 1)`] SUM_ADD_SPLIT in
1945     let lem31 = SIMP_RULE [ARITH_RULE `0 <= x`] lem30 in
1946     let lem32 = UNDISCH_ALL (ARITH_RULE `! x. x  >= p ==> (p - 1) + (x - 1) - (p -1)=  x - 1`) in
1947     let lem33 = UNDISCH_ALL (SPEC_ALL LENGTH_As) in
1948     let lem34 = SPEC `LENGTH (As n p)` lem32 in
1949     let lem35 = MP lem34 lem33 in
1950     let lem36 = ONCE_REWRITE_RULE [UNDISCH (ARITH_RULE `p > 1 ==> (p - 1) + 1 = p`);lem35] lem31 in
1951     let lem37 = ONCE_REWRITE_RULE [lem36] lem25 in
1952     let lem38 = SIMP_RULE [UNDISCH (ARITH_RULE `p > 1 ==> p > 0`)] (DISCH `p > 0` lem37) in
1953     let lem39 = ISPECL [`\m. EL m (As n p) * &(FACT m)`;`0`;`p-2`;`1`] SUM_ADD_SPLIT in
1954     let lem40 = ADD_ASSUM `n > 0` (ADD_ASSUM `p > 1` lem39) in
1955     let lem41 = SIMP_RULE (map (UNDISCH o ARITH_RULE) [`p > 1 ==> p - 2 + 1 = p-1`;`p > 1 ==> (p - 2) + 1 = p - 1`]) lem40 in
1956     let lem42 = SIMP_RULE [SUM_SING_NUMSEG;ARITH_RULE `0 <= x`] lem41 in
1957     let lem45 = ADD_ASSUM `p > 1` (SPEC_ALL prefix_As_zero) in
1958     let lem46 = SIMP_RULE [UNDISCH_ALL (ARITH_RULE `p > 1 ==> p > 0`)] lem45 in
1959     let lem47 = UNDISCH (ONCE_REWRITE_RULE [UNDISCH_ALL (ARITH_RULE `p > 1 ==> (i < p-1 <=> i <= p-2)`)] lem46) in
1960     let lem48 = SIMP_RULE [REAL_ARITH `((&0):real) + x = x`; SUM_EQ_0_NUMSEG;REAL_ARITH `((&0):real) * x = &0`;lem47] lem42 in
1961     let lem49 = SIMP_RULE [UNDISCH (ARITH_RULE `p > 1 ==> p > 0`)] (ADD_ASSUM `p > 1` (SPEC_ALL fact_As)) in
1962     let lem50 = SIMP_RULE [UNDISCH lem49] lem48 in
1963     let lem51 = ONCE_REWRITE_RULE [lem50] lem38 in
1964     let lem52 = SPECL [`p - 1`;`(&1):real`] FACT_DIV_RCANCELS in
1965     let lem53 = SIMP_RULE [REAL_ARITH `(x:real) * (y * z) = (x * z) * y`;lem52;REAL_ARITH `(x:real) * (y + z) = (x * y) + (x * z)`] lem51 in
1966     let lem54 = SIMP_RULE [REAL_ARITH `&1 * x = (x:real)`] lem53 in
1967     let josh0 = UNDISCH_ALL KEY_LEMMA2 in
1968     let josh1 = REAL_ARITH `!(y:real) x1 x2 . x1  = x2 <=> y + x1 = y + x2` in
1969     let josh2 = SPEC `(&(FACT n) pow p * -- &1 pow (n * p)):real` josh1 in
1970     let josh3 = ONCE_REWRITE_RULE [josh2] josh0 in
1971     let josh4 = ONCE_REWRITE_RULE [GSYM lem54] josh3 in
1972     let josh5 = DISCH `~ (As n p = [])` josh4 in
1973     let jem4 = ADD_ASSUM `p > 1` ((SPEC_ALL LENGTH_As)) in
1974     (* JOHN: the UNDISCH here is necessary... i don't think it should be *)
1975     let jem5 = UNDISCH (SIMP_RULE [UNDISCH (ARITH_RULE `(p:num) > 1 ==> p > 0`)] jem4) in
1976     let jem6 = UNDISCH (ARITH_RULE `p > 1 ==> (LENGTH (As n p) >= p) ==> ~((LENGTH (As n p) = 0))`)  in
1977     let jem7 = MP jem6 jem5  in
1978     let jem8 = SIMP_RULE [LENGTH_EQ_NIL] jem7 in
1979     let josh6 = MP josh5 jem8 in
1980     let josh7 = DISCH_ALL josh6 in
1981     let josh11 = ONCE_REWRITE_RULE [GSYM OLD_SUM] lem17 in
1982     let josh12 = REWRITE_RULE [GSYM josh11] josh7 in
1983     let josh13 =  SIMP_RULE [] (DISCH_ALL josh12) in
1984     let josh14 = BRW `(X ==> Y ==> Z ==> W) <=> ((X /\ Y /\ Z) ==> W)` josh13 in
1985     let josh15 = ONCE_REWRITE_RULE [ARITH_RULE `(p > 0 /\ n > 0 /\ p > 1) <=> (p > 1 /\ n > 0)`] (DISCH_ALL josh14) in
1986     let josh16 = BRW1 josh15 in
1987     let josh17 = SIMP_RULE [PSUM_ITERATE;ARITH_RULE `~(0 > 0)`] josh16 in
1988     ACCEPT_TAC josh17
1989 )
1990 let PLANETMATH_DIVIDES_FACT_PRIME_1 = prove (
1991     `!p n. (prime p) /\ p > n ==> ~(num_divides p (FACT n))`,
1992     (SIMP_TAC [DIVIDES_FACT_PRIME]) THEN ARITH_TAC
1993 )
1994 let INT_OF_REAL_NEG_NUM = prove(
1995     `!(n:num).int_of_real (-- (real_of_num n)) = -- (int_of_real (real_of_num n))`,
1996     SIMP_TAC [GSYM int_of_num;GSYM int_of_num_th;GSYM int_neg]
1997 )
1998 let ABS_EQ_ONE = prove(
1999     `!(x:real) .((abs x) = &1) ==> ((x = &1) \/ (x = -- &1))`,
2000     ARITH_TAC
2001 )
2002 let POW_NEG_1 = prove(
2003    `!(x:num). (((-- (&1 :real)) pow x) = -- &1) \/  (((-- (&1 : real)) pow x) = &1)`,
2004     let lem00 = ONCE_REWRITE_RULE [TAUT `x \/ y <=> y \/ x`] ABS_EQ_ONE in
2005     let lem01 = (SPEC `(-- (&1 :real)) pow x` lem00) in
2006     let lem02 = (SPEC `x:num` POW_M1) in
2007     let lem03 = MP lem01 lem02 in
2008     STRIP_TAC THEN (ACCEPT_TAC lem03)
2009 )
2010 let NUM_DIVIDES_INT_DIVIDES = prove(
2011     `!(x:num) (y:num).(x divides y) <=> ((&x):int divides ((&y):int))`,
2012     (ONCE_REWRITE_TAC [num_divides])  THEN (SIMP_TAC [])
2013 )
2014 let SON_OF_A_GUN = prove(
2015     `! (p:num) (n:num) .
2016      p > n
2017      ==> (prime p)
2018      ==> ~(int_divides (& p) (&(FACT n) pow p * -- &1 pow (n * p) ))`,
2019     let POW_INT_NEG_1 = INT_OF_REAL_THM POW_NEG_1 in
2020     let lem0000 = TAUT `(A /\ B ==> C) <=> (A ==> B ==> C)` in
2021     let lem0001 = ONCE_REWRITE_RULE [lem0000] PLANETMATH_DIVIDES_FACT_PRIME_1 in
2022     let lem0002 = UNDISCH_ALL (SPEC_ALL lem0001) in
2023     let lem0008 = ONCE_REWRITE_RULE [TAUT `(x /\ y ==> z) <=> (x ==> ~z ==> ~y)`]  PRIME_DIVEXP in
2024     let lem0009 = SPECL [`p:num`;`p:num`;`FACT n`] lem0008 in
2025     let lem0010 = UNDISCH lem0009 in
2026     let lem0011 = MP lem0010 lem0002 in
2027      STRIP_TAC THEN STRIP_TAC THEN STRIP_TAC THEN STRIP_TAC THEN
2028      (DISJ_CASES_TAC (SPEC `(n * p):num` POW_INT_NEG_1))  THENL
2029      [ (ASM_SIMP_TAC [INT_OF_NUM_POW; ARITH_RULE `x * (--(&1):int) = -- x`;ARITH_RULE `x * ((&1):int) = x`]) THEN
2030        (ONCE_REWRITE_TAC [GSYM INT_DIVIDES_RNEG]) THEN
2031        (ONCE_REWRITE_TAC [ARITH_RULE `-- -- (x:int) = x`]) THEN
2032        (ONCE_REWRITE_TAC [GSYM NUM_DIVIDES_INT_DIVIDES]) THEN
2033        (ACCEPT_TAC lem0011);
2034        (ASM_SIMP_TAC [INT_OF_NUM_POW; ARITH_RULE `x * (--(&1):int) = -- x`;ARITH_RULE `x * ((&1):int) = x`]) THEN
2035        (ONCE_REWRITE_TAC [GSYM NUM_DIVIDES_INT_DIVIDES]) THEN
2036        (ACCEPT_TAC lem0011)
2037      ]
2038 )
2039 let MAY_LEMMA = prove(
2040     `(p:num) > (n:num)
2041       ==> (prime p)
2042       ==> ~(int_divides (& p) ((int_of_num (FACT n)) pow p * -- &1 pow (n * p) + &p * K0))`,
2043       let lem00 = BRW `(x /\ y ==> z) <=> (x ==> ~z ==> ~y)` INT_DIVIDES_ADD_REVR in
2044       let lem0 = prove(`int_divides ((&p):int) (&p * K0)`,INTEGER_TAC) in
2045       let lem1 = (UNDISCH_ALL o SPEC_ALL) SON_OF_A_GUN in
2046       let lem2 = SPECL [`(&p):int`;`((&p):int) * K0`; `(&(FACT n) pow p):int *
2047       -- &1 pow (n * p)` ] lem00 in
2048       let lem3 = MP (MP lem2 lem0) lem1 in
2049       let lem4 = (DISCH_ALL lem3) in
2050       let lem5 = ONCE_REWRITE_RULE [ARITH_RULE `(x:int) + y = y + x`] lem4 in
2051       (ACCEPT_TAC lem5)
2052 )
2053 let PLANET_MATH_alpha_1 = prove(
2054     `n > 0 ==> p > n ==> prime p ==> (integer (poly (SOD (g n p )) (&0)))`,
2055     let a1 = UNDISCH (UNDISCH (ARITH_RULE `n > 0 ==> p > n ==> p > 1`)) in
2056     let a2 = UNDISCH (SIMP_RULE [] (DISCH `n > 0` (MP PLANETMATH_EQN_5_2 a1))) in
2057     let t1 = `integer K0 /\
2058               poly (SOD (g n p)) (&0) =
2059               &(FACT n) pow p * -- &1 pow (n * p) + &p * K0` in
2060     (STRIP_TAC THEN STRIP_TAC THEN STRIP_TAC) THEN (CHOOSE_TAC a2) THEN
2061     (SPLIT_CONJOINED_ASSUMPT_TAC t1) THEN (ASM_REWRITE_TAC[]) THEN
2062     (ASM_SIMP_TAC [N_IS_INT;INTEGER_ADD;NEG_N_IS_INT;INTEGER_POW;INTEGER_MUL])
2063 )
2064 let PLANET_MATH_alpha_2 = prove(
2065     `n > 0 ==> p > n ==> prime p ==>
2066      ( ~((&p) divides (int_of_real (poly (SOD (g n p )) (&0)))))`,
2067     let t1 = `integer K0 /\
2068               poly (SOD (g n p)) (&0) =
2069               &(FACT n) pow p * -- &1 pow (n * p) + &p * K0` in
2070     let t = `((real_of_num (FACT n)) pow p) * (-- &1 pow (n * p)) + (&p * K0)` in
2071     let arch0 = INT_OF_REAL_CONV t in
2072     let a1 = UNDISCH (UNDISCH (ARITH_RULE `n > 0 ==> p > n ==> p > 1`)) in
2073     let a2 = UNDISCH (SIMP_RULE [] (DISCH `n > 0` (MP PLANETMATH_EQN_5_2 a1))) in
2074     let a3 = SPEC `int_of_real K0` (GEN `K0:int` MAY_LEMMA) in
2075     let a4 = GSYM (UNDISCH arch0) in
2076     let a5 = ONCE_REWRITE_RULE [a4] a3 in
2077     STRIP_TAC THEN STRIP_TAC THEN STRIP_TAC THEN (CHOOSE_TAC a2) THEN
2078     (SPLIT_CONJOINED_ASSUMPT_TAC t1) THEN (ASM_SIMP_TAC [a5])
2079 )
2080 let INT_OF_REAL_NEG_INT_OF_NUM = prove(
2081     `!n. int_of_real(-- (real_of_num n)) = -- int_of_num n`,
2082     SIMP_TAC [int_of_num;INT_OF_REAL_NEG_NUM]
2083 )
2084 let PLANET_MATH_alpha_3 = prove(
2085      `n > 0 ==> p > n ==> prime p ==>
2086       (~((poly (SOD (g n p)) (&0)) = &0))`,
2087       let lem0 = prove(
2088             `!(x:num) (y:real).
2089                (x > 0) ==>
2090                (integer y) ==>
2091                (~(&x divides (int_of_real y))) ==>
2092                ~(y = &0)`,
2093               MESON_TAC [is_int;INT_OF_NUM_GT;INT_DIVIDES_RNEG;REAL_OF_NUM_EQ;int_of_num;INT_OF_REAL_NEG_INT_OF_NUM;INT_OF_NUM_EQ;INT_DIVIDES_0]) in
2094       let lem1 = ARITH_RULE `n > 0 ==> p > n ==> p > 0` in
2095       MESON_TAC [lem0;lem1; PLANET_MATH_alpha_1; PLANET_MATH_alpha_2]
2096 )
2097 let PLANET_MATH_alpha = prove(
2098     `n > 0 ==> p > n ==> prime p ==>
2099      (     (integer (poly (SOD (g n p )) (&0)))
2100        /\ ~((&p) divides (int_of_real (poly (SOD (g n p )) (&0))))
2101        /\ ~((poly (SOD (g n p)) (&0)) = &0))`,
2102      SIMP_TAC [PLANET_MATH_alpha_1; PLANET_MATH_alpha_2; PLANET_MATH_alpha_3]
2103 )
2104 let REAL_FACT_NZ = prove(
2105     `~((&(FACT n)) = (real_of_num 0))`,
2106     let l0 = GSYM (SPECL [`FACT n`;`0`] REAL_OF_NUM_EQ) in
2107     ACCEPT_TAC (SPEC_ALL (ONCE_REWRITE_RULE [l0] FACT_NZ))
2108 )
2109
2110 let IS_INT_FACT_DIV_FACT_DIV_FACT = prove(
2111     `! i k.integer ((&(FACT (i+k)))/(&(FACT i))/(&(FACT k)))`,
2112     let l0 = MATCH_MP (ARITH_RULE `(~(x=0)) ==> 0 < x`) (SPEC `k:num` FACT_NZ) in
2113     let l1 = ONCE_REWRITE_RULE [GSYM REAL_OF_NUM_LT] l0 in
2114     let l2 = MATCH_MP REAL_EQ_LDIV_EQ l1 in
2115     (REPEAT STRIP_TAC) THEN (REWRITE_TAC [is_int;l2]) THEN
2116     (EXISTS_TAC ` (binom(i+k,k))`) THEN DISJ1_TAC THEN
2117     (MESON_TAC [BINOM_FACT;MULT_SYM;MULT_ASSOC;REAL_OF_NUM_MUL;REAL_OF_NUM_EQ])
2118 )
2119
2120 (*  if you replace the second SIMP_TAC with MESON_TAC, it fails!!
2121  *  (i alwasy thought MESON_TAC was strictly stronger than SIMP_TAC
2122  *)
2123 let POLY_CMUL_EL = prove(
2124     `!p c i.(i < (LENGTH p)) ==> (EL i (c ## p)) = c * (EL i p)`,
2125     let l0 = ARITH_RULE `(SUC i) < (SUC j) <=> i < j` in
2126     LIST_INDUCT_TAC THENL
2127     [ (SIMP_TAC [LENGTH;ARITH_RULE `~(n < (0:num))`]);
2128       STRIP_TAC THEN INDUCT_TAC THENL
2129       [ (SIMP_TAC [poly_cmul;HD;EL]);
2130         (ASM_SIMP_TAC [LENGTH;poly_cmul;TL;EL;l0])
2131       ]
2132     ]
2133 )
2134 let PDI_COEFF_FACT = prove(
2135     `! k q i.(i < LENGTH (poly_diff_iter q k)) ==>
2136             (EL i (poly_diff_iter q k)) = ((&(FACT (i+k)))/(&(FACT i))) * (EL (i+k) q)`,
2137     let t0 = `!q i.  i < LENGTH (poly_diff_iter q k)
2138                   ==> EL i (poly_diff_iter q k) = &(FACT (i + k)) / &(FACT i) * EL (i + k) q` in
2139     let l0 = SPECL [`q:(real)list`;`SUC i`] ( ASSUME t0) in
2140     let l1 = ONCE_REWRITE_RULE [ARITH_RULE `(SUC i) < x <=> i < (PRE x)`] l0 in
2141     let l2 = ONCE_REWRITE_RULE [GSYM LENGTH_POLY_DIFF] l1 in
2142     let l3 = ONCE_REWRITE_RULE [FACT;GSYM REAL_OF_NUM_MUL] l2 in
2143     let l4 = ONCE_REWRITE_RULE [GSYM REAL_OF_NUM_MUL] l3 in
2144     let l5 =  REWRITE_RULE [real_div;REAL_INV_MUL] l4 in
2145     let l6 = REAL_ARITH `(w * (inv x) * y ) * z = (w * y * z) * (inv x)` in
2146     let l9 = ONCE_REWRITE_RULE [GSYM REAL_OF_NUM_LT] (ARITH_RULE `0 < SUC i`) in
2147     let l10 = MATCH_MP REAL_EQ_RDIV_EQ l9 in
2148     let l11 = ONCE_REWRITE_RULE [l6] l5 in
2149     let l12 = ONCE_REWRITE_RULE [real_div] l10 in
2150     let l13 = ONCE_REWRITE_RULE [l12] l11 in
2151     INDUCT_TAC THENL
2152     [ (REWRITE_TAC [Pm_lemma1.PDI_DEF;ARITH_RULE `i + 0 = i`]) THEN
2153       (MESON_TAC [REAL_DIV_REFL;FACT_NZ;REAL_OF_NUM_EQ;REAL_ARITH `(real_of_num 1) * x = x`]);
2154       (ONCE_REWRITE_TAC [Pm_lemma1.PDI_DEF]) THEN (SIMP_TAC [EL_POLY_DIFF]) THEN
2155       (ONCE_REWRITE_TAC [ARITH_RULE `i + (SUC k) = (SUC i) + k`]) THEN
2156       (ONCE_REWRITE_TAC [FACT]) THEN (ONCE_REWRITE_TAC [real_div]) THEN
2157       (SIMP_TAC [l13;real_div;REAL_MUL_ASSOC])
2158     ]
2159 )
2160 (* I think this should hold if we replace [--a;&1] with an arbitrary polynomial q,
2161  * however the existing ORDER* theorems would not be sufficient to prove it and
2162  * I don't feel like putting in the effort right now
2163  *)
2164 let POLY_DIVIDES_POLY_DIFF = prove(
2165     `!p n a.
2166          (poly_divides (poly_exp [--a;&1] (SUC n)) p)
2167          ==> (poly_divides (poly_exp [--a;&1] n) (poly_diff p))`,
2168     let l0 = ARITH_RULE `op = SUC odp ==> SUC n <= op ==> n <= odp` in
2169     let l1 = ARITH_RULE `(SUC n <= m ) ==> ~(m = 0)` in
2170     MESON_TAC [l0;l1;POLY_DIFF_ZERO;ORDER_DIVIDES;ORDER_DIFF]
2171 )
2172 let POLY_DIVIDES_MUL = prove(
2173     `!p1 p2 p3.poly_divides p1 p2 ==> poly_divides p1 (p2 ** p3)`,
2174     (ONCE_REWRITE_TAC [divides]) THEN (REPEAT STRIP_TAC) THEN
2175     (EXISTS_TAC `q ** p3`) THEN
2176     (ASM_MESON_TAC [FUN_EQ_THM;POLY_MUL;POLY_MUL_ASSOC])
2177 )
2178 let POLY_DIVIDES_MUL3 = prove(
2179     `!p1 p2 p3.(poly_divides p1 p2) ==> (poly_divides p1 (p3 ** p2))`,
2180     (ONCE_REWRITE_TAC [divides]) THEN (REPEAT STRIP_TAC) THEN
2181     (EXISTS_TAC `p3 ** q`) THEN (UNDISCH_TAC `poly (p2) = poly (p1 ** q)`) THEN
2182     (ONCE_REWRITE_TAC [FUN_EQ_THM]) THEN (REWRITE_TAC [POLY_MUL]) THEN
2183     (MESON_TAC [REAL_MUL_ASSOC;REAL_MUL_SYM])
2184 )
2185 let POLY_DIVIDES_POLY_MUL_ITER = prove(
2186     `!f n v. 1 <= v ==> v <= n ==> poly_divides (f v) (poly_mul_iter f n)`,
2187     let l1 = ARITH_RULE `~(v <= n) ==> (v <= SUC n) ==> v = SUC n` in
2188     let l2 = UNDISCH (UNDISCH l1) in
2189     STRIP_TAC THEN INDUCT_TAC THENL
2190     [ ARITH_TAC;
2191       (ONCE_REWRITE_TAC [Pm_eqn5.POLY_MUL_ITER]) THEN STRIP_TAC THEN
2192       (ASM_CASES_TAC `v <= (n:num)`) THENL
2193       [ ASM_MESON_TAC [POLY_DIVIDES_MUL3];
2194         STRIP_TAC THEN STRIP_TAC THEN
2195         (MESON_TAC [l2;POLY_DIVIDES_MUL;POLY_DIVIDES_REFL]) ]
2196     ]
2197 )
2198 (*
2199  *  This one was suprisingly tricky to prove...
2200  *)
2201 let POLY_DIVIDES_POLY_EXP2 = prove(
2202     `!n p1 p2.(poly_divides p1 p2) ==> poly_divides (poly_exp p1 n) (poly_exp p2 n)`,
2203     let t0 = `!p1 p2.
2204                 (?q. poly p2 = poly (p1 ** q))
2205                 ==> (?q. poly (poly_exp p2 n) = poly (poly_exp p1 n ** q))` in
2206     let l0 = ASSUME t0 in
2207     let l1 = UNDISCH (REWRITE_RULE [divides] (SPEC_ALL l0)) in
2208     let l3 = prove(
2209         `(x2 = x5 * x6 /\ x1 = x4 * x7) ==> (x1:real) * x2 = (x4 * x5) * x6 * x7`,
2210          MESON_TAC [REAL_MUL_SYM;REAL_MUL_ASSOC]) in
2211    (ONCE_REWRITE_TAC [divides]) THEN INDUCT_TAC THENL
2212    [ (MESON_TAC [divides;poly_exp;POLY_DIVIDES_REFL]);
2213      (STRIP_TAC THEN STRIP_TAC THEN DISCH_TAC) THEN (CHOOSE_TAC l1) THEN
2214      (UNDISCH_TAC `?q. poly p2 = poly (p1 ** q)`) THEN STRIP_TAC THEN
2215      (ONCE_REWRITE_TAC [poly_exp]) THEN (EXISTS_TAC `q ** q'`) THEN
2216      (REWRITE_TAC [poly_exp;FUN_EQ_THM;POLY_MUL]) THEN
2217      (ASM_MESON_TAC [l3;FUN_EQ_THM;POLY_MUL])
2218    ]
2219 )
2220 let POLY_EXP_ONE = prove(
2221     `!p .p = poly_exp p 1`,
2222     MESON_TAC [poly_exp;ARITH_RULE `1 = SUC 0`;POLY_MUL_RID]
2223 )
2224 let POLY_DIVIDES_ROOT = prove(
2225     `!p a.poly_divides [--a;&1] p ==> (poly p a) = &0`,
2226     MESON_TAC [ORDER_ROOT;ORDER_DIVIDES;POLY_EXP_ONE;
2227                ARITH_RULE `1 <= ord ==> ~(ord = 0)`]
2228 )
2229
2230 let POLY_DIVIDES_PDI = prove(
2231     `!n p a.
2232          (poly_divides (poly_exp [--a;&1] (SUC n)) p)
2233          ==> (poly_divides [--a;&1] (poly_diff_iter p n))`,
2234     let t0 = `!p a.  poly_divides (poly_exp [--a; &1] (SUC n)) p
2235                      ==> poly_divides [--a; &1] (poly_diff_iter p n)` in
2236     let l0 = ASSUME t0 in
2237     let l1 = SPEC `poly_diff p` l0 in
2238     let l2 = SPECL [`p:(real)list`;`SUC n`;`a:real`] POLY_DIVIDES_POLY_DIFF in
2239     let l3 = UNDISCH l2 in
2240     let l4 = MATCH_MP l1 l3 in
2241     INDUCT_TAC THENL
2242     [ (SIMP_TAC [poly_exp;POLY_MUL_RID;Pm_lemma1.PDI_DEF]);
2243       (REPEAT STRIP_TAC) THEN (ASM_MESON_TAC [l4;Pm_lemma1.PDI_DEF;PDI_POLY_DIFF_COMM])
2244     ]
2245 )
2246 let POLY_DIVIDES_PDI2 = prove(
2247      `!n m p a.
2248           m > n
2249           ==> (poly_divides (poly_exp [--a;&1] m) p)
2250           ==> (poly_divides [--a;&1] (poly_diff_iter p n))`,
2251      MESON_TAC [POLY_EXP_DIVIDES;POLY_DIVIDES_PDI;
2252                 ARITH_RULE `m > n <=> (SUC n) <= m`]
2253 )
2254 let TAIL_GUNNER = prove(
2255     ` x < p ==> 1 <= v ==> v <= n ==>
2256       poly (poly_diff_iter
2257            (poly_exp [&0; &1] (p - 1) **
2258             poly_exp (poly_mul_iter (\i. [-- &i; &1]) n) p)
2259           x)
2260           (&v)
2261        = &0 `,
2262      MESON_TAC [POLY_DIVIDES_ROOT; ARITH_RULE `x < p <=> (p:num) > x`;
2263                 POLY_DIVIDES_PDI2; POLY_DIVIDES_MUL3; POLY_DIVIDES_POLY_EXP2;
2264                 POLY_DIVIDES_POLY_MUL_ITER]
2265 )
2266
2267 let IS_INT_POLY = prove(
2268     `!p x.(integer x) ==> (ALL integer p) ==> integer (poly p x)`,
2269     LIST_INDUCT_TAC THEN
2270     (ASM_MESON_TAC [N_IS_INT;ALL;poly;INTEGER_ADD;INTEGER_MUL])
2271 )
2272 (*  surprising the MESON needs so much help with the rewrites here
2273  *  (i.e. i though i could just hit it with ASM_MESON_TAC with all four thms
2274  *)
2275 let INV_POLY_CMUL = prove(
2276     `!y x . (~(x = &0)) ==> (x) ## (inv x) ## y = y`,
2277     LIST_INDUCT_TAC THENL
2278     [ ASM_MESON_TAC [poly_cmul];
2279       (REPEAT STRIP_TAC) THEN
2280       (REWRITE_TAC [poly_cmul;REAL_MUL_ASSOC]) THEN
2281       (ASM_MESON_TAC [REAL_MUL_RINV;REAL_MUL_LID])
2282     ]
2283 )
2284 let INV_POLY_CMUL2 = prove(
2285     `!y x . (~(x = &0)) ==> (inv x) ## (x) ## y = y`,
2286     MESON_TAC [INV_POLY_CMUL;REAL_INV_INV;REAL_INV_EQ_0]
2287 )
2288 (* the final ASM_MESON_TAC fails if poly_cmul is rolled into the thm list *)
2289 let POLY_CMUL_EQUALS = prove(
2290     `!z x y. (~(z = &0)) ==> ((x = y) <=> (z ## x = z ## y))`,
2291     (REPEAT STRIP_TAC) THEN EQ_TAC THENL
2292     [ (SIMP_TAC[]);
2293       (SPEC_TAC (`x:(real)list`,`x:(real)list`)) THEN
2294       (SPEC_TAC (`y:(real)list`,`y:(real)list`)) THEN
2295       (LIST_INDUCT_TAC) THENL
2296       [ LIST_INDUCT_TAC THENL
2297         [ (SIMP_TAC [POLY_CMUL_CLAUSES]);
2298           (ASM_MESON_TAC [POLY_CMUL_CLAUSES;NOT_CONS_NIL])];
2299         LIST_INDUCT_TAC THENL [
2300           (ASM_MESON_TAC [POLY_CMUL_CLAUSES;NOT_CONS_NIL]);
2301           (ONCE_REWRITE_TAC [poly_cmul]) THEN
2302           (ASM_MESON_TAC [REAL_EQ_LCANCEL_IMP;CONS_11])]
2303       ]
2304     ]
2305 )
2306 let PDI_LENGTH_THM = prove(
2307     `!f n. LENGTH(poly_diff_iter f n) = (LENGTH f) - n`,
2308     STRIP_TAC THEN INDUCT_TAC THENL
2309     [ (SIMP_TAC [Pm_lemma1.PDI_DEF;ARITH_RULE `(x:num) - 0 = x`]);
2310       (ONCE_REWRITE_TAC [Pm_lemma1.PDI_DEF]) THEN
2311       (ONCE_REWRITE_TAC [LENGTH_POLY_DIFF]) THEN ASM_ARITH_TAC ]
2312 )
2313 let CAPTAINS_CLOTHES = prove(
2314     `! k q.
2315      (ALL integer q) ==>
2316      ? r .(ALL integer r) /\ r = (inv (&(FACT k))) ## (poly_diff_iter q k)`
2317     ,
2318     let e0 = `(inv (&(FACT k))) ## (poly_diff_iter q k)` in
2319     let l1 = ONCE_REWRITE_RULE [GSYM (SPEC `inv (&(FACT k))` POLY_CMUL_LENGTH)]
2320                                PDI_COEFF_FACT in
2321     let l2 = UNDISCH (SPEC_ALL l1) in
2322     let l3 = prove(`i < LENGTH( inv (&(FACT k)) ## poly_diff_iter q k)
2323                      ==> (i + k) < LENGTH q`,
2324                     MESON_TAC [PDI_LENGTH_THM;POLY_CMUL_LENGTH;
2325                                ARITH_RULE `(i:num) < f -k ==> (i+k) < f`]) in
2326     (REPEAT STRIP_TAC) THEN (EXISTS_TAC e0) THEN (SIMP_TAC []) THEN
2327     (ASM_SIMP_TAC [ONCE_REWRITE_RULE [GSYM POLY_CMUL_LENGTH] POLY_CMUL_EL]) THEN
2328     (ONCE_REWRITE_TAC [GSYM ALL_EL]) THEN (REPEAT STRIP_TAC) THEN
2329     (ASM_SIMP_TAC [ONCE_REWRITE_RULE [GSYM POLY_CMUL_LENGTH] POLY_CMUL_EL]) THEN
2330     (ONCE_REWRITE_TAC [l2]) THEN (ONCE_REWRITE_TAC [REAL_MUL_ASSOC]) THEN
2331     (MATCH_MP_TAC INTEGER_MUL) THEN STRIP_TAC THENL
2332     [ (MESON_TAC [IS_INT_FACT_DIV_FACT_DIV_FACT;REAL_MUL_SYM;real_div;REAL_MUL_ASSOC]);
2333       (ASM_MESON_TAC  [l3;ALL_IMP_EL]) ]
2334 )
2335 let MESSY_JESSE2 = prove(
2336   `n > 0 ==> p > n ==>
2337      (? (Bs:num->num->real). ! v .
2338          (1 <= v) ==> (v <= n) ==>
2339          (    (! i . (integer (Bs v i)))
2340            /\ (poly (SOD (g n p)) (&v)) =
2341                  ((real_of_num 1) / (&(FACT (p - 1)))) *
2342                    (psum (0,LENGTH (g n p))
2343                       (\i. (&(FACT i)) * (Bs v i)))
2344            /\ (! i. (i < p) ==> (Bs v i) = &0)  ))`,
2345     let root_canal = REAL_ARITH `(x:real) * (&0) = &0` in
2346     let bs = `\(v:num) . \(x:num).
2347                if (x <= (LENGTH (g n p)) ) then
2348                     (poly
2349                        ((inv (&(FACT x))) ##
2350                         (poly_diff_iter
2351                         (poly_exp [&0; &1] (p - 1) **
2352                          poly_exp (poly_mul_iter (\i. [-- &i; &1]) n) p)
2353                         x))
2354                        (&v))
2355                else (&0)` in
2356     let l0 = prove(`ALL integer [&0;&1]`,MESON_TAC [ALL;N_IS_INT]) in
2357     let t0 = `(poly_exp [&0; &1] (p - 1) **
2358               poly_exp (poly_mul_iter (\i. [-- &i; &1]) n) p)` in
2359     let l2 = SPECL [`i:num`;t0] CAPTAINS_CLOTHES in
2360     let l3 = prove(`ALL integer (poly_exp [&0; &1] (p - 1) ** poly_exp (poly_mul_iter (\i. [-- &i; &1]) n) p)`,MESON_TAC[l0;ALL_IS_INT_POLY_MUL;ALL_IS_INT_POLY_EXP;ALL_IS_INT_POLY_MUL_ITER]) in
2361     let l4 = MP l2 l3 in
2362     let l7 = ONCE_REWRITE_RULE [GSYM REAL_OF_NUM_EQ] FACT_NZ in
2363     let l8 = (SIMP_RULE [l7]) (SPEC `(&(FACT i)):real` POLY_CMUL_EQUALS) in
2364     (* these are not true for x =0, however we only use it for x= &(FACT i) *)
2365     let l10_0 = SPECL [`y:(real)list`;`(real_of_num (FACT i))`] INV_POLY_CMUL in
2366     let l12_0 = SPECL [`y:(real)list`;`(real_of_num (FACT i))`] INV_POLY_CMUL2 in
2367     let l10 = SIMP_RULE [REAL_FACT_NZ] l10_0 in
2368     let l12 = SIMP_RULE [REAL_FACT_NZ] l12_0 in
2369     let l9 = ONCE_REWRITE_RULE [l8] l4 in
2370     let l11 = GSYM (ONCE_REWRITE_RULE [l10] l9) in
2371     let l133 = prove(`
2372       (psum (0,m) (\i.(x i) * (if i <= m then (y i) else c))) =
2373       (psum (0,m) (\i.(x i) * (y i)))`,
2374       MESON_TAC [SUM_EQ;ARITH_RULE `(0 <= i /\ i < (m:num) + 0) ==> i <= m`]) in
2375     let l18 = MATCH_MP REAL_MUL_RINV (SPEC `i:num` l7) in
2376     let lass2 = SPECL [`g n p`;`x:real`;`v:real`] Pm_lemma2.PLANETMATH_LEMMA_2_B in
2377     let lass3 = BETA_RULE lass2 in
2378     let lass4 = CONV_RULE (RAND_CONV (RAND_CONV (REWRITE_CONV [Pm_eqn5.PLANETMATH_EQN_5]))) lass3 in
2379     let lass5 = REWRITE_RULE [POLY_CMUL;POLY_CMUL_PDI] lass4 in
2380     let lass6 = CONV_RULE (RAND_CONV (ONCE_REWRITE_CONV [GSYM (ISPEC `f:num->real` ETA_AX)])) (SPEC_ALL SUM_CMUL) in
2381     let lass7 = ONCE_REWRITE_RULE [GSYM REAL_MUL_ASSOC] lass5 in
2382     let lass8 = REWRITE_RULE [lass6] lass7 in
2383     let lass10 = ONCE_REWRITE_RULE [REAL_MUL_DIV_ASSOC] lass8 in
2384     let lass11 =  ONCE_REWRITE_RULE [real_div] lass10 in
2385     let lass12 = REAL_ARITH `((w:real) * x * y) * z = w * x * y * z` in
2386     let lass13 = ONCE_REWRITE_RULE [lass12] lass11 in
2387     let lass14 = REWRITE_RULE [lass6] lass13 in
2388     let MUL_ONE = REAL_ARITH `! x.(&1) * x = x /\ x * (&1) = x` in
2389     let lass15 = SIMP_RULE [REAL_MUL_LINV;REAL_FACT_NZ;MUL_ONE] lass14 in
2390     STRIP_TAC THEN STRIP_TAC THEN (EXISTS_TAC bs) THEN (REPEAT STRIP_TAC) THENL
2391     [
2392       (BETA_TAC THEN BETA_TAC) THEN (ASM_CASES_TAC `(i <= LENGTH (g n p))`) THENL
2393       [ (ASM_SIMP_TAC[]) THEN (ASM_CASES_TAC `((i:num) < p)`) THENL
2394         [ (ASM_MESON_TAC [POLY_CMUL;TAIL_GUNNER;
2395                           N_IS_INT;REAL_ARITH `(x:real) * (&0) = &0`]);
2396           (ASSUME_TAC (UNDISCH (ARITH_RULE `~(i < (p:num)) ==> (p <= i)`))) THEN
2397           (CHOOSE_TAC l11) THEN
2398           (SPLIT_CONJOINED_ASSUMPT_TAC (snd (dest_exists (concl l11)))) THEN
2399           (ASM_REWRITE_TAC[l12]) THEN
2400           (ASM_MESON_TAC [N_IS_INT;IS_INT_POLY])
2401         ];
2402         (ASM_MESON_TAC [N_IS_INT])
2403       ];
2404       (BETA_TAC) THEN (SIMP_TAC [l133]) THEN
2405       (SIMP_TAC [POLY_CMUL;l18;REAL_MUL_ASSOC;REAL_MUL_LID]) THEN
2406       (SIMP_TAC [lass15;REAL_INV_1OVER]);
2407       BETA_TAC THEN (ASM_MESON_TAC [TAIL_GUNNER;POLY_CMUL;root_canal])
2408     ]
2409 )
2410 let INTEGER_PSUM = prove(
2411     `!f m.(! i . i < m ==> integer (f i)) ==> (integer (psum (0,m) f))`,
2412     let l0 = ASSUME `!i. i < SUC m ==> integer (f i)` in
2413     let l1 = SPEC `m:num` l0 in
2414     let l2 = SIMP_RULE [ARITH_RULE `m < SUC m`] l1 in
2415     STRIP_TAC THEN INDUCT_TAC THENL
2416     [ (MESON_TAC [sum;int_of_num;int_of_num_th;N_IS_INT]);
2417       (SIMP_TAC [sum;ARITH_RULE `0 + (x:num) = x`]) THEN
2418       (STRIP_TAC) THEN (MATCH_MP_TAC INTEGER_ADD) THEN
2419       (ASM_MESON_TAC[l2;ARITH_RULE `(i:num) < m ==> i < SUC m`])
2420     ]
2421 )
2422 let INT_DIVIDES_PSUM = prove(
2423     `!f m p.(! i . i < m ==>
2424              ((integer (f i)) /\ (int_divides p (int_of_real (f i)))))
2425                 ==> (int_divides p (int_of_real (psum (0,m) f)))`,
2426     let l0 = ASSUME `!i. i < SUC m ==> integer (f i) /\ p divides int_of_real (f i)` in
2427     let l1 = SPEC `m:num` l0 in
2428     let l2 = SIMP_RULE [ARITH_RULE `m < SUC m`] l1 in
2429     let l3 = ASSUME `(!i. i < m ==> integer (f i)) ==> integer (psum (0,m) f)` in
2430     let l4 = SPEC `i:num` l0 in
2431     let l5 = DISCH `i < SUC m` ((CONJUNCT1 (UNDISCH l4))) in
2432     let l8 = prove(`(!i.i < SUC m
2433                          ==> (integer (f i))) ==> (!i.i < m ==> (integer (f i)))`,
2434                    MESON_TAC [ARITH_RULE `i < m ==> i < SUC m`]) in
2435     let ll1 = MP l8 (GEN_ALL l5) in
2436     let ll2 = MP l3 ll1 in
2437     let ll3 = MATCH_MP INT_OF_REAL_ADD (CONJ ll2 (CONJUNCT1 l2))  in
2438     STRIP_TAC THEN INDUCT_TAC THENL
2439     [ (MESON_TAC [sum;int_of_num;int_of_num_th;INT_DIVIDES_0]);
2440       (SIMP_TAC [sum;ARITH_RULE `0 + (x:num) = x`]) THEN
2441       (ASSUME_TAC (SPECL [`f:num->real`;`m:num`] INTEGER_PSUM)) THEN
2442       (STRIP_TAC) THEN
2443       (STRIP_TAC) THEN
2444       (ONCE_REWRITE_TAC [ll3]) THEN
2445       (MATCH_MP_TAC INT_DIVIDES_ADD) THEN
2446       (CONJ_TAC) THENL
2447       [ (ASM_MESON_TAC [ARITH_RULE `i < m ==> i < SUC m`]);
2448         (ASM_MESON_TAC [ARITH_RULE `m < SUC m`])
2449       ]
2450     ]
2451 )
2452 let PLANET_MATH_beta = prove(
2453     `p > n ==>
2454      n > 0 ==>
2455      (! v.
2456        (1 <= v /\ v <= n) ==>
2457        (   (integer (poly (SOD (g n p )) (&v)))
2458         /\ ((&p) divides (int_of_real (poly (SOD (g n p )) (&v))))
2459        )
2460      )`,
2461     let l2 = GSYM (ONCE_REWRITE_RULE [REAL_MUL_SYM] real_div) in
2462     let ll3 = ARITH_RULE `(int_of_num p) * &0 = &0` in
2463     let l7 = UNDISCH (SPECL [`i:num`;`p:num`] IS_INT_FACT_DIV) in
2464     let l11 = prove(`p > 0 ==> FACT p = p * (FACT (p-1))`,
2465                     MESON_TAC [FACT; ARITH_RULE `p > 0 ==> SUC (p -1) = p `]) in
2466     let l12 = UNDISCH (UNDISCH (ARITH_RULE `(p:num) > n ==> n > 0 ==> p > 0`)) in
2467     let l13 = MP l11 l12 in
2468     let t9 =
2469       `1 <= (v:num) ==>
2470        v <= (n:num) ==>
2471        (!v. 1 <= v
2472               ==> v <= n
2473               ==> (!i. integer (Bs v i)) /\
2474                   poly (SOD (g n p)) (&v) =
2475                   &1 / &(FACT (p - 1)) *
2476                   psum (0,LENGTH (g n p)) (\i. &(FACT i) * Bs v i) /\
2477                   (!i. i < p ==> Bs v i = &0)) ==>
2478         (integer (Bs v i))` in
2479     let lll0 = UNDISCH (UNDISCH (UNDISCH (prove(t9,MESON_TAC[])))) in
2480     let l8 = REWRITE_RULE [l13;real_div;REAL_INV_MUL] l7 in
2481     let l9 = REWRITE_RULE [N_IS_INT;GSYM REAL_OF_NUM_MUL] l8 in
2482     let l10 = REWRITE_RULE [REAL_INV_MUL] l9 in
2483     let l11 = MATCH_MP (INTEGER_MUL) (CONJ l10 lll0) in
2484     let l12 = MATCH_MP INT_OF_REAL_MUL (CONJ (SPEC `p:num` N_IS_INT) l11) in
2485     let l15 = GSYM l12 in
2486     let lll8 = ARITH_RULE `p > n ==> n > 0 ==> ~(p = 0)` in
2487     let lll9 = ONCE_REWRITE_RULE [GSYM REAL_OF_NUM_EQ] lll8 in
2488     let lll10 = UNDISCH (UNDISCH lll9) in
2489
2490     let sc1 = prove (`(~((x:real) = &0)) ==> (x * y * inv x) = y`,
2491                       MESON_TAC [REAL_MUL_RID;REAL_MUL_ASSOC;
2492                                  REAL_MUL_SYM;REAL_MUL_LINV;REAL_MUL_LID]) in
2493     let sc2 = prove (`(~((x:real) = &0)) ==> (x * y * (inv x) * z) = y * z`,
2494                       MESON_TAC [sc1;REAL_MUL_ASSOC]) in
2495     (REPEAT STRIP_TAC) THENL
2496       [ (CHOOSE_TAC (UNDISCH (UNDISCH MESSY_JESSE2))) THEN
2497         (ASM_SIMP_TAC []) THEN
2498         (ONCE_REWRITE_TAC [GSYM SUM_CMUL]) THEN
2499         (MATCH_MP_TAC INTEGER_PSUM) THEN
2500         (REPEAT STRIP_TAC) THEN
2501         BETA_TAC THEN
2502         (ASM_CASES_TAC `i < (p:num)`) THENL
2503         [ (ASM_SIMP_TAC [N_IS_INT;REAL_ARITH `(x:real) * (&0) = &0`]);
2504           (ASSUME_TAC (UNDISCH (ARITH_RULE `(~((i:num) < p)) ==> i >= p-1`))) THEN
2505           (ASM_MESON_TAC [REAL_INV_1OVER;REAL_MUL_ASSOC;
2506                           IS_INT_FACT_DIV; l2;INTEGER_MUL])
2507         ];
2508         (CHOOSE_TAC (UNDISCH (UNDISCH MESSY_JESSE2))) THEN
2509         (ASM_SIMP_TAC []) THEN
2510         (ONCE_REWRITE_TAC [GSYM SUM_CMUL]) THEN
2511         (MATCH_MP_TAC INT_DIVIDES_PSUM) THEN
2512         (REPEAT STRIP_TAC) THENL
2513         [ BETA_TAC THEN
2514           (ASM_CASES_TAC `i < (p:num)`) THENL
2515           [ (ASM_SIMP_TAC [N_IS_INT;REAL_ARITH `(x:real) * (&0) = &0`]);
2516             (ASSUME_TAC (UNDISCH (ARITH_RULE `(~((i:num) < p)) ==> i >= p-1`))) THEN
2517             (ASM_MESON_TAC [REAL_INV_1OVER;REAL_MUL_ASSOC;
2518                             IS_INT_FACT_DIV; l2;INTEGER_MUL])
2519           ];
2520           (ONCE_REWRITE_TAC [int_divides]) THEN BETA_TAC THEN
2521           (ASM_CASES_TAC `i < (p:num)`) THENL
2522           [ (ASM_SIMP_TAC [N_IS_INT;REAL_ARITH `(x:real) * (&0) = &0`]) THEN
2523             (EXISTS_TAC `int_of_num 0`) THEN
2524             (MESON_TAC [ll3;int_of_num_th;int_of_num]);
2525             (ASSUME_TAC (UNDISCH (ARITH_RULE `(~((i:num) < p)) ==> i >= p`))) THEN
2526             (EXISTS_TAC `int_of_real (((&(FACT i))/(&(FACT p))) * (Bs (v:num) i))`) THEN
2527             (ONCE_REWRITE_TAC [int_of_num]) THEN
2528             (ONCE_REWRITE_TAC [l13]) THEN
2529             (ONCE_REWRITE_TAC [N_IS_INT;GSYM REAL_OF_NUM_MUL]) THEN
2530             (SIMP_TAC [ real_div]) THEN
2531             (ONCE_REWRITE_TAC [ REAL_INV_MUL]) THEN
2532             (ONCE_REWRITE_TAC [ REAL_MUL_LID]) THEN
2533             (ONCE_REWRITE_TAC [l15]) THEN
2534             (ASSUME_TAC lll10) THEN
2535             (ONCE_REWRITE_TAC [REAL_MUL_ASSOC]) THEN
2536             (ASM_MESON_TAC [sc2;REAL_MUL_SYM])
2537           ]
2538         ]
2539       ]
2540 )
2541
2542 let JUNE_LEMMA = prove(
2543     `n > 0 ==> p > n ==> v <= n ==> integer (poly (SOD (g n p)) (&v))`,
2544     let lem0 = CONJUNCT1 (UNDISCH_ALL PLANET_MATH_alpha) in
2545     let lem1 = UNDISCH_ALL (SPEC_ALL (UNDISCH_ALL PLANET_MATH_beta)) in
2546     let lem2 = DISCH `1 <= v /\ v <= n` (CONJUNCT1 lem1) in
2547     let lem3 = SPEC `SUC v` (GEN `v:num` lem2) in
2548     let lem4 = SIMP_RULE [ARITH_RULE `1 <= SUC v`] lem3 in
2549     (STRIP_TAC THEN STRIP_TAC) THEN
2550     (SPEC_TAC (`v:num`,`v:num`)) THEN
2551     (INDUCT_TAC THENL [(SIMP_TAC [lem0]);(ACCEPT_TAC lem4)])
2552 )
2553 let DIVIDES_SUM_NOT_ZERO = prove(
2554     `!(x:int) (y:int) (z:int).
2555          (~(z divides x)) /\  (z divides y) ==> ~(x + y = &0)`,
2556     let l0 = ASSUME `(x:int) + y = &0` in
2557     let l1 = ONCE_REWRITE_RULE [ARITH_RULE `((x:int) + y = &0) <=> (x = --y)`] l0 in
2558     (REPEAT STRIP_TAC) THEN (UNDISCH_TAC `~((z:int) divides x)`) THEN
2559     (REWRITE_TAC [l1]) THEN (UNDISCH_TAC `((z:int) divides y)`) THEN
2560     (INTEGER_TAC)
2561 )
2562 let NUM_OF_INT_ABS = prove(
2563     `!(x:num) (y:int).num_of_int (abs y)  = x <=> abs y = &x`,
2564 (* stupid... *)
2565     let j0 = UNDISCH (prove(`(num_of_int (abs y) = x) ==> x = num_of_int (abs y)`,MESON_TAC [])) in
2566     let j1 = ARITH_RULE `&0 <= ((abs y):int)` in
2567     let j2 = MATCH_MP INT_OF_NUM_OF_INT j1 in
2568     (REPEAT STRIP_TAC) THEN EQ_TAC THENL
2569     [ (STRIP_TAC THEN SIMP_TAC [j0;j2]);
2570       (ASM_SIMP_TAC [NUM_OF_INT_OF_NUM])]
2571 )
2572 let INT_DIVIDES_IMP_ABS_NUM_DIVIDES = prove(
2573     `! (x:int) (y:num).
2574        (x divides (&y)) ==> ((num_of_int (abs x)) divides y)`,
2575     let w0 = ARITH_RULE `((&0):int) <= abs x` in
2576     let w1 = fst (EQ_IMP_RULE (SPEC `abs (x:int)` NUM_OF_INT)) in
2577     let w2 = MP w1 w0 in
2578     let w3 = ARITH_RULE `((&0):int) <= x ==> abs x = x` in
2579     let w4 = ARITH_RULE `(~(((&0):int) <= x)) ==> abs x = -- x` in
2580     (REWRITE_TAC [int_divides;num_divides]) THEN
2581     (REPEAT STRIP_TAC) THEN (ASM_REWRITE_TAC [w2]) THEN
2582     (ASM_CASES_TAC `((&0):int) <= x`) THENL
2583     [ (ONCE_REWRITE_TAC [UNDISCH w3]) THEN
2584       (EXISTS_TAC `x':int`) THEN (REFL_TAC);
2585       (ONCE_REWRITE_TAC [UNDISCH w4]) THEN
2586       (EXISTS_TAC `--x':int`) THEN (ARITH_TAC)
2587     ]
2588 )
2589 let INT_PRIME_NUM_PRIME = prove(
2590     `!p. int_prime (&p) <=> prime p`,
2591     (ONCE_REWRITE_TAC [int_prime;prime]) THEN
2592     (MESON_TAC [divides;num_divides;
2593                 INT_ABS;INT_POS;INT_OF_NUM_EQ;INT_LT_IMP_NE;INT_GT;
2594                 ARITH_RULE `2 <= p ==> abs((&p):int) > &1`;
2595                 INT_DIVIDES_IMP_ABS_NUM_DIVIDES;NUM_OF_INT_ABS;PRIME_GE_2;
2596                 prime;int_prime ])
2597 )
2598
2599 let DIVIDES_INT_OF_REAL_ADD = prove(
2600          `!x y p.integer x /\
2601                  integer y /\
2602                  p divides (int_of_real x) /\
2603                  p divides (int_of_real y)
2604                  ==> p divides (int_of_real (x + y))`,
2605          SIMP_TAC [INT_OF_REAL_ADD;INT_DIVIDES_ADD]
2606 )
2607 let ITCHY_LEMMA = prove(
2608     `! f p n.
2609        (!v.1<= v /\ v <=  n ==>
2610         integer (f v) /\
2611         &p divides int_of_real (f v)) ==>
2612         (&p divides int_of_real (sum (1..n) f))`,
2613     let l0 = fst (EQ_IMP_RULE (SPECL [`1`;`0`] (GSYM NUMSEG_EMPTY))) in
2614     let l1 = INTEGER_RULE `&p divides ((&0))` in
2615     let l2 = SPEC `0` (GEN_ALL int_of_num) in
2616     let l3 = ONCE_REWRITE_RULE [l2] l1 in
2617     let l4 = SPECL [`f:num->real`;`n:num`;`1`] IS_INT_SUM in
2618     let l5 = prove(`(!v. 1 <= v /\ v <= SUC n ==> integer (f v)) ==> (!i. 1 <= i /\ i <= n ==> integer (f i))`,MESON_TAC [ARITH_RULE `v <= n ==> v <= SUC n`]) in
2619     let l6 = IMP_TRANS l5 l4 in
2620     let l7 = prove(`(!v. 1 <= v /\ v <= SUC n ==> (integer (f v)) /\  (&p) divides int_of_real (f v)) ==> (&p) divides int_of_real (f (SUC n))`,MESON_TAC [ARITH_RULE `1 <= (SUC n) /\ SUC n <= SUC n`]) in
2621     let l9 = prove(`(!v. 1 <= v /\ v <= SUC n ==> integer (f v)) ==> integer (f (SUC n))`,MESON_TAC [ARITH_RULE `1 <= SUC n /\ SUC n <= SUC n`]) in
2622     let tm = `\(v:num).integer (f v) /\ (&p) divides int_of_real (f v)` in
2623     let l10 = BETA_RULE (SPEC tm SHRIVER) in
2624     let l11 = UNDISCH (SPEC `1` (GEN `m:num` l10)) in
2625      STRIP_TAC THEN STRIP_TAC THEN INDUCT_TAC THENL
2626      [ SIMP_TAC  [ARITH_RULE `0 < 1`;l0;SUM_CLAUSES;l3];
2627        DISCH_TAC THEN
2628        (SIMP_TAC [SUM_CLAUSES_NUMSEG;ARITH_RULE `1 <= SUC n`]) THEN
2629        (MATCH_MP_TAC DIVIDES_INT_OF_REAL_ADD) THEN (CONJ_TAC) THENL
2630        [ ASM_SIMP_TAC [l6];
2631          CONJ_TAC THENL
2632          [ ASM_SIMP_TAC [l9];
2633            CONJ_TAC THENL
2634            [ ASM_SIMP_TAC [l11];
2635              ASM_SIMP_TAC [l7] ]]]]
2636 )
2637 let GOTTA_DO_DISHES_LEMMA = prove(
2638     `!(x:real) (y:real).
2639        (integer x) /\ (integer y) ==>
2640        (?(z:int).(~(z divides (int_of_real x)))
2641            /\ (z divides (int_of_real y)))
2642        ==> ~(x + y = &0)`,
2643     let mk_lemma x y =
2644         let lem0 = SPECL [x;y;`z:int`] DIVIDES_SUM_NOT_ZERO in
2645         let lem1 = TAUT `(X /\ Y ==> Z) <=> (X ==> Y ==> Z)` in
2646         UNDISCH (UNDISCH (ONCE_REWRITE_RULE [lem1] lem0))
2647     in
2648     let mk_tac x y =
2649         (ASM_REWRITE_TAC [GSYM int_of_num;INT_OF_REAL_NEG_INT_OF_NUM]) THEN
2650         (STRIP_TAC) THEN
2651         (REWRITE_TAC [GSYM int_neg_th;GSYM int_eq; GSYM int_add_th;GSYM int_of_num_th]) THEN
2652         (ACCEPT_TAC (mk_lemma  x y))
2653     in
2654     (ONCE_REWRITE_TAC [is_int]) THEN
2655     (STRIP_TAC THEN STRIP_TAC THEN STRIP_TAC ) THENL
2656     [ mk_tac `(&n):int` `(&n'):int` ;
2657       mk_tac `(&n):int` `--(&n'):int` ;
2658       mk_tac `--(&n):int` `(&n'):int` ;
2659       mk_tac `--(&n):int` `--(&n'):int`
2660      ]
2661 )
2662
2663 let RAINY_DAY = prove(
2664     `! p x y.
2665        prime p ==>
2666        (&p) > x ==>
2667        integer x ==>
2668        x > (&0) ==>
2669        integer y ==>
2670        (((&p) divides (int_of_real (x * y)))
2671         <=> ((&p) divides int_of_real y))`,
2672     let ss3 = SPECL [`int_of_num n`;`(&p):int`] INT_PRIME_COPRIME_LT in
2673     let ss4 = ONCE_REWRITE_RULE [ARITH_RULE `abs ((&x):int) = &x`] ss3 in
2674     let ss40 = prove(`!(x:num) (y:num).  (int_of_num x) < (int_of_num y) <=> (real_of_num x) < (real_of_num y)`,SIMP_TAC [INT_OF_NUM_LT;REAL_OF_NUM_LT]) in
2675     let ss5 = ONCE_REWRITE_RULE [ss40;INT_COPRIME_SYM;INT_PRIME_NUM_PRIME] ss4 in
2676     let ss6 = SPECL [`(&p):int`;`(&n):int`;`int_of_real y`] INT_COPRIME_DIVPROD in
2677     let ss7 = ONCE_REWRITE_RULE [TAUT `(X /\ Y ==> Z) <=> (Y ==> X ==> Z)`] ss6 in
2678     let ss8 = IMP_TRANS ss5 ss7 in
2679     let ss9 = ONCE_REWRITE_RULE [TAUT `(A /\ B /\ C ==> D ==> E) <=> (A ==> B ==> C ==> D ==> E)`] ss8 in
2680     let ss10 = UNDISCH ss9 in
2681     (REPEAT STRIP_TAC) THEN (ASM_SIMP_TAC [INT_OF_REAL_MUL]) THEN
2682     (EQ_TAC) THENL
2683     [ (SIMP_TAC [INT_DIVIDES_LMUL]) THEN
2684       (UNDISCH_TAC `integer x`) THEN
2685       (ONCE_REWRITE_TAC [is_int]) THEN
2686       (STRIP_TAC) THENL
2687       [ (ASM_REWRITE_TAC[]) THEN
2688         (ONCE_REWRITE_TAC [GSYM int_of_num]) THEN
2689         (UNDISCH_TAC `(&(p:num)) > (x:real)`) THEN
2690         (UNDISCH_TAC `(x:real) > &0`) THEN
2691         (ASM_REWRITE_TAC []) THEN
2692         (ONCE_REWRITE_TAC [REAL_ARITH `(y:real) > z <=> z < y`]) THEN
2693         (ACCEPT_TAC ss10);
2694         (ASM_ARITH_TAC)
2695       ];
2696       (SIMP_TAC [INT_DIVIDES_LMUL])
2697     ]
2698 )
2699 let PLANET_MATH_gamma = prove(
2700     `n > 0 ==>
2701      p > n ==>
2702      prime p ==>
2703      &p > (EL 0 c) ==>
2704      (EL 0 c) > (&0) ==>
2705      n = PRE (LENGTH (c)) ==>
2706      (ALL integer c) ==>
2707      ( (integer (LHS c (g n p))) /\ ~((LHS c (g n p)) = &0))`,
2708      let lemma01 = SPECL [`\i. EL i c * poly (SOD (g n p)) (&i)`;`n:num`;`k:num` ] IS_INT_SUM in
2709      let lemma02 = BETA_RULE lemma01 in
2710      let lemma021 = UNDISCH JUNE_LEMMA in
2711      let lemma022 = UNDISCH_ALL (ARITH_RULE `n > 0 ==> p > n ==> p > 1`) in
2712      let lemma023 = DISCH_ALL (SIMP_RULE [lemma022] lemma021) in
2713      let lemma04 = UNDISCH (UNDISCH lemma023) in
2714      let lemma08 = ISPECL [`c:(real)list`;`v:num`;`integer`] ALL_IMP_EL in
2715      let lemma09 = ADD_ASSUM `n > 0` (UNDISCH lemma08) in
2716      let lemma10 = ADD_ASSUM `n = PRE (LENGTH (c:(real)list))` lemma09 in
2717      let lemma11 = ARITH_RULE `n > 0 ==> (n = PRE (LENGTH (c:(real)list))) ==> ((v < LENGTH c) <=> (v <= n))` in
2718      let lemma12 = UNDISCH (UNDISCH lemma11) in
2719      let lemma13 = ONCE_REWRITE_RULE [lemma12] lemma10 in
2720      let lemma15 = CONJ (UNDISCH (UNDISCH lemma04)) (UNDISCH lemma13) in
2721      let lemma16 = MATCH_MP INTEGER_MUL (ONCE_REWRITE_RULE [CONJ_SYM] lemma15) in
2722      let lemma17 = DISCH `v <= (n:num)` lemma16 in
2723      let lemma18 = ADD_ASSUM_DISCH `k <= (v:num)` lemma17 in
2724      let lemma19 = ONCE_REWRITE_RULE [TAUT `(X ==> Y ==> Z) <=> ((X /\ Y) ==> Z)`] lemma18 in
2725      let lemma20 = GEN `v:num` lemma19 in
2726      let lemma21 = GEN `k:num` (MATCH_MP lemma02 lemma20) in
2727      let lemma29 = SPEC `0` lemma21 in
2728      let lemma30 = GSYM (ASSUME `n = PRE (LENGTH (c:(real)list))`) in
2729      let lemma300 = SPECL [`f:(num -> real)`;`0`;`PRE (LENGTH (c:(real)list))`] SUM_CLAUSES_LEFT in
2730      let lemma31 = ADD_ASSUM `n > 0` (ADD_ASSUM `n = PRE (LENGTH (c:(real)list))` lemma300) in
2731      let lemma32 = MP lemma31 (ARITH_RULE `0 <= PRE (LENGTH (c:(real)list))`) in
2732      let lemma0000 = BRW `(X ==> Y ==> Z) <=> ((X /\ Y) ==> Z)` GOTTA_DO_DISHES_LEMMA in
2733      let lemmaa00 = UNDISCH PLANET_MATH_alpha in
2734      let lemmaa03 = ARITH_RULE `n >0 ==> ((n = PRE (LENGTH (c:(real)list))) ==> 0 < (LENGTH c))` in
2735      let lemmaa04 = ISPECL [`c:(real)list`;`0`;`integer`] ALL_IMP_EL in
2736      let lemmaa05 = MP (UNDISCH lemmaa04) (UNDISCH (UNDISCH lemmaa03))  in
2737      let c1 = ARITH_RULE `n > 0 ==> n = PRE (LENGTH (c:(real)list)) ==> 0 < (LENGTH (c:(real)list))` in
2738      let c2 = UNDISCH (UNDISCH c1) in
2739      let c3 = MP (UNDISCH lemmaa04) c2 in
2740      let c4 = CONJUNCT1 (UNDISCH (UNDISCH (UNDISCH PLANET_MATH_alpha))) in
2741      let c40 = CONJUNCT2 (UNDISCH (UNDISCH (UNDISCH PLANET_MATH_alpha))) in
2742      let c5 = SPECL [`p:num`;`(EL 0 c):real`;`poly (SOD (g n p)) (&0)`] RAINY_DAY in
2743      let c7 = ((UNDISCH (UNDISCH c5))) in
2744      let c8 = SIMP_RULE [c3] c7 in
2745      let c9 = UNDISCH c8 in
2746      let c10 = SIMP_RULE [c4] c9 in
2747      let d0 = UNDISCH PLANET_MATH_beta in
2748      let d1 = BRW `(X ==> Y ==> Z) <=> (Y ==> X ==> Z)` d0 in
2749      let d2 = SIMP_RULE [UNDISCH (ARITH_RULE `p > (n:num) ==> n > 0 ==> p > 1`)] d1 in
2750      let d3 = UNDISCH d2 in
2751      let d8 = CONJUNCT2 (UNDISCH (SPEC_ALL d3)) in
2752      let d9 = SPECL [`(&p):int`;`int_of_real (EL v c)`;`int_of_real (poly (SOD (g n p)) (&v))`] INT_DIVIDES_LMUL in
2753      let d10 = ADD_ASSUM `ALL integer c` d9 in
2754      let d11 = ADD_ASSUM `n = PRE (LENGTH (c:(real)list))` d10 in
2755      let d12 = ADD_ASSUM `1 <= v /\ v <= n` d11 in
2756      let d13 = CONJUNCT1 (UNDISCH (SPEC_ALL d3)) in
2757      let d14 = DISCH `1 <= v` (ADD_ASSUM `1 <= v` lemma13) in
2758      let d15 = BRW `(X ==> Y ==> Z) <=> (X /\ Y ==> Z)` d14 in
2759      let d16 = UNDISCH d15 in
2760      let d17 = CONJ d16 d13 in
2761      let d18 = GSYM (MATCH_MP INT_OF_REAL_MUL d17) in
2762      let d19 = ONCE_REWRITE_RULE [d18] d12 in
2763      let d20 = MP d19 d8 in
2764      let d21 = UNDISCH (SPECL [`1`;`v:num`] (GEN `k:num` lemma20)) in
2765      let d22 = CONJ d21 d20 in
2766      let d23 = DISCH `1 <=v /\ v <= n` d22 in
2767      let d24 = GEN `v:num` d23 in
2768      let d25 = MATCH_MP ITCHY_LEMMA d24 in
2769      ((REPEAT STRIP_TAC) THENL
2770       [ (ONCE_REWRITE_TAC [Pm_eqn4.LHS]) THEN (SIMP_TAC [lemma30;lemma29]);
2771         (UNDISCH_TAC `LHS c (g n p) = &0`) THEN
2772         (REWRITE_TAC [Pm_eqn4.LHS]) THEN
2773         (SIMP_TAC [lemma32;ARITH_RULE `0 + 1 = 1`]) THEN
2774         (ONCE_REWRITE_TAC [lemma30]) THEN
2775         (MATCH_MP_TAC lemma0000) THEN
2776         (CONJ_TAC) THENL
2777         [ (CONJ_TAC) THENL
2778           [ (MATCH_MP_TAC INTEGER_MUL) THEN (ASM_SIMP_TAC [lemmaa00;lemmaa05]);
2779             (ACCEPT_TAC (SPEC `1` lemma21))
2780           ];
2781           (EXISTS_TAC `(&p):int`) THEN (CONJ_TAC) THENL
2782           [(ONCE_REWRITE_TAC [c10]) THEN (ASM_SIMP_TAC [c40]);
2783            (ACCEPT_TAC d25)
2784           ]
2785         ]
2786       ] )
2787 )
2788 end;;
2789
2790
2791
2792 module Finale = struct
2793
2794 let IS_INT_NZ_ABS_GE_1 = prove (
2795     `!x. ((integer x) /\ ~(x = &0)) ==> ~(abs x < &1)`,
2796     let lemmy0 = REAL_ARITH `(x:real) < y <=> ~(y <= x)` in
2797     let lemmy1 = ONCE_REWRITE_RULE [lemmy0] REAL_NZ_IMP_LT in
2798     let lemmy2 = REAL_ARITH `(real_neg x) = &0 <=> x = &0` in
2799     let lemmy3 = REAL_ARITH `&0 <= (real_neg x) <=> x <= &0` in
2800     (ONCE_REWRITE_TAC [is_int]) THEN
2801     (ONCE_REWRITE_TAC [TAUT `(X /\ Y ==> Z) <=> (X ==> Y ==> Z)`]) THEN
2802     (STRIP_TAC) THEN (STRIP_TAC) THENL
2803     [ (ASM_REWRITE_TAC[]) THEN (SIMP_TAC [REAL_ABS_NUM] ) THEN
2804       (ONCE_REWRITE_TAC [REAL_OF_NUM_LT;REAL_OF_NUM_EQ]) THEN
2805       (ARITH_TAC);
2806       (ASM_REWRITE_TAC[]) THEN (ONCE_REWRITE_TAC [real_abs]) THEN
2807       (ONCE_REWRITE_TAC [lemmy2;lemmy3]) THEN
2808       (ONCE_REWRITE_TAC [REAL_OF_NUM_EQ]) THEN
2809       (SIMP_TAC [lemmy1;REAL_NEG_NEG]) THEN
2810       (ONCE_REWRITE_TAC [REAL_OF_NUM_LT]) THEN (ARITH_TAC)
2811     ]
2812 )
2813 let PBR_LEMMA = prove(
2814     `!n1 n2 n3 p. p > MAX n1 (MAX n2 n3) ==> (p > n1 /\ p > n2 /\ p > n3)`,
2815     (REWRITE_TAC [MAX]) THEN ARITH_TAC
2816
2817 )
2818 let BIGGER_PRIME_EXISTS = prove(
2819   `!(n:num). ?p. prime p /\ p > n`,
2820    let lem0 = prove(`{x | prime x} = prime`,SET_TAC[]) in
2821    let lem1 = ARITH_RULE `p > n <=> ~(p <= (n:num))` in
2822    MESON_TAC [PRIMES_INFINITE;lem0;lem1;IN_ELIM_THM;num_FINITE;INFINITE]
2823 )
2824 let BUD_LEMMA = prove(
2825     `!(f:num->bool) (n1:num) (n2:num).((?(N:num) . !(p:num).p > N ==> f p)
2826       ==> (? (p0:num).prime p0 /\ p0 > n1 /\ p0 > n2 /\ f p0))`,
2827     let amigo3 = SPECL [`N:num`;`n1:num`;`n2:num`;`p:num`] PBR_LEMMA in
2828     let amigo4 = UNDISCH amigo3  in
2829     (REPEAT STRIP_TAC) THEN
2830     (CHOOSE_TAC (SPEC  `MAX N (MAX n1 n2)` BIGGER_PRIME_EXISTS )) THEN
2831     (EXISTS_TAC `p:num`) THEN
2832     (UNDISCH_TAC `prime p /\ p > MAX N (MAX n1 n2)`) THEN
2833     (ONCE_REWRITE_TAC [TAUT `(X /\ Y ==> Z) <=> (X ==> Y ==> Z)`]) THEN
2834     (DISCH_TAC THEN DISCH_TAC) THEN
2835     (ASM_SIMP_TAC [amigo4])
2836 )
2837
2838 let ALL_IMP_EL = prove(
2839     `! (l:(a)list) i P. (ALL P l) ==> (i < LENGTH l) ==> P (EL i l)`,
2840     SIMP_TAC[GSYM ALL_EL]
2841 )
2842
2843 let HAMMS_LEMMA = prove(
2844      `~(?c. ALL integer c /\
2845             LENGTH c > 1 /\
2846             EL 0 c > &0 /\
2847             (!f. LHS c f = RHS c f))`,
2848      let erica0  = UNDISCH_ALL Pm_eqn4_lhs.PLANET_MATH_gamma in
2849      let erica1  = MATCH_MP IS_INT_NZ_ABS_GE_1 erica0  in
2850      let erica2  = ASM_REWRITE_RULE [] erica1 in
2851      let erica3 = SPEC_ALL Pm_eqn4_rhs.LT_ONE in
2852      let erica4 = MATCH_MP BUD_LEMMA erica3 in
2853      let erica5 = ADD_ASSUM `ALL integer c` erica4 in
2854      let erica8 = ARITH_RULE `(n = PRE (LENGTH (c:(real)list))) ==> n > 0 ==>
2855      0 < (LENGTH c) ` in
2856      let erica9 = UNDISCH (UNDISCH erica8) in
2857      let erica10 = UNDISCH (ISPECL [`c:(real)list`;`0`;`integer`] ALL_IMP_EL) in
2858      let erica11 = MP erica10 erica9 in
2859      let erica12 = ONCE_REWRITE_RULE [is_int] erica11 in
2860      let erica13 = ARITH_RULE `!n. ~(( -- (real_of_num n)) > &0)` in
2861      let erica14 = prove(
2862          `n = PRE (LENGTH c) ==>
2863           n > 0 ==>
2864           ALL integer c ==>
2865           (EL 0 c) > &0 ==>
2866           ?n. EL 0 c = &n`,
2867           MESON_TAC [DISCH_ALL erica12;erica13]
2868      ) in
2869      let erica15 = UNDISCH_ALL erica14 in
2870      let sim0 = SELECT_RULE (ASSUME (concl erica15)) in
2871      let sim1 = DISCH (concl erica15) sim0 in
2872      let sim2 = MP sim1 erica15 in
2873      let erica18 = SPECL [`n:num`;`@n. EL 0 c = (real_of_num n)`] erica5 in
2874      let erica19 = ONCE_REWRITE_RULE [GSYM REAL_OF_NUM_GT] erica18 in
2875      let erica20 =  ONCE_REWRITE_RULE [GSYM sim2] erica19 in
2876      let erica21 =  ONCE_REWRITE_RULE [REAL_OF_NUM_GT] erica20 in
2877      let erica22 = DISCH `(real_of_num p) > EL 0 c` erica2 in
2878      let erica23 = DISCH `(p:num) > n` erica22 in
2879      let erica24 = DISCH `prime (p:num)` erica23 in
2880      let erica25 = GEN `p:num` erica24 in
2881      let erica28 = UNDISCH (ARITH_RULE `n = PRE (LENGTH (c:(real)list)) ==> ((n > 0) <=> (LENGTH c) > 1)`) in
2882      let erica29 = UNDISCH (ONCE_REWRITE_RULE [erica28] (DISCH `n > 0` (erica25))) in
2883      let erica30 = UNDISCH (ONCE_REWRITE_RULE [erica28] (DISCH `n > 0` (erica21))) in
2884       (CONV_TAC NNF_CONV) THEN
2885       (REPEAT STRIP_TAC) THEN
2886       (ASM_MESON_TAC [DISCH_ALL erica29;DISCH_ALL erica30])
2887 )
2888
2889 let TRANSCENDENTAL_E = prove(
2890     `transcendental (exp (&1))`,
2891     MESON_TAC [HAMMS_LEMMA;Pm_eqn4.PLANETMATH_EQN_4]
2892 )
2893
2894 end;;
2895
2896 Finale.TRANSCENDENTAL_E;;