1 (**************************************************************************)
4 (* ||A|| A project by Andrea Asperti *)
6 (* ||I|| Developers: *)
7 (* ||T|| A.Asperti, C.Sacerdoti Coen, *)
8 (* ||A|| E.Tassi, S.Zacchiroli *)
10 (* \ / Matita is distributed under the terms of the *)
11 (* v GNU Lesser General Public License Version 2.1 *)
13 (**************************************************************************)
15 include "datatypes/constructors.ma".
17 include "nat/nth_prime.ma".
18 include "nat/gcd.ma". (* for some properties of divides *)
19 include "nat/relevant_equations.ma". (* required by autobatch paramod *)
21 let rec p_ord_aux p n m \def
25 [ O \Rightarrow pair nat nat O n
27 match (p_ord_aux p (n / m) m) with
28 [ (pair q r) \Rightarrow pair nat nat (S q) r] ]
29 | (S a) \Rightarrow pair nat nat O n].
31 (* p_ord n m = <q,r> if m divides n q times, with remainder r *)
32 definition p_ord \def \lambda n,m:nat.p_ord_aux n n m.
34 theorem p_ord_aux_to_Prop: \forall p,n,m. O < m \to
35 match p_ord_aux p n m with
36 [ (pair q r) \Rightarrow n = m \sup q *r ].
39 apply (nat_case (n \mod m)).
40 simplify.apply plus_n_O.
42 simplify.apply plus_n_O.
44 apply (nat_case1 (n1 \mod m)).intro.
46 generalize in match (H (n1 / m) m).
47 elim (p_ord_aux n (n1 / m) m).
49 rewrite > assoc_times.
50 rewrite < H3.rewrite > (plus_n_O (m*(n1 / m))).
53 rewrite < div_mod.reflexivity.
54 assumption.assumption.
55 intros.simplify.apply plus_n_O.
58 theorem p_ord_aux_to_exp: \forall p,n,m,q,r. O < m \to
59 (pair nat nat q r) = p_ord_aux p n m \to n = m \sup q * r.
62 match (pair nat nat q r) with
63 [ (pair q r) \Rightarrow n = m \sup q * r ].
65 apply p_ord_aux_to_Prop.
69 (* questo va spostato in primes1.ma *)
70 theorem p_ord_exp: \forall n,m,i. O < m \to n \mod m \neq O \to
71 \forall p. i \le p \to p_ord_aux p (m \sup i * n) m = pair nat nat i n.
78 elim (n \mod m).simplify.reflexivity.simplify.reflexivity.
81 cut (O < n \mod m \lor O = n \mod m).
82 elim Hcut.apply (lt_O_n_elim (n \mod m) H3).
83 intros. simplify.reflexivity.
85 apply H1.apply sym_eq.assumption.
86 apply le_to_or_lt_eq.apply le_O_n.
87 generalize in match H3.
88 apply (nat_case p).intro.apply False_ind.apply (not_le_Sn_O n1 H4).
90 simplify. fold simplify (m \sup (S n1)).
91 cut (((m \sup (S n1)*n) \mod m) = O).
93 simplify.fold simplify (m \sup (S n1)).
94 cut ((m \sup (S n1) *n) / m = m \sup n1 *n).
96 rewrite > (H2 m1). simplify.reflexivity.
97 apply le_S_S_to_le.assumption.
100 rewrite > assoc_times.
101 apply (lt_O_n_elim m H).
102 intro.apply div_times.
104 apply divides_to_mod_O.
106 simplify.rewrite > assoc_times.
107 apply (witness ? ? (m \sup n1 *n)).reflexivity.
110 theorem p_ord_aux_to_Prop1: \forall p,n,m. (S O) < m \to O < n \to n \le p \to
111 match p_ord_aux p n m with
112 [ (pair q r) \Rightarrow r \mod m \neq O].
113 intro.elim p.absurd (O < n).assumption.
114 apply le_to_not_lt.assumption.
116 apply (nat_case1 (n1 \mod m)).intro.
117 generalize in match (H (n1 / m) m).
118 elim (p_ord_aux n (n1 / m) m).
120 apply eq_mod_O_to_lt_O_div.
121 apply (trans_lt ? (S O)).unfold lt.apply le_n.
122 assumption.assumption.assumption.
124 apply (trans_le ? n1).change with (n1 / m < n1).
125 apply lt_div_n_m_n.assumption.assumption.assumption.
129 apply (not_eq_O_S m1).
130 rewrite > H5.reflexivity.
133 theorem p_ord_aux_to_not_mod_O: \forall p,n,m,q,r. (S O) < m \to O < n \to n \le p \to
134 pair nat nat q r = p_ord_aux p n m \to r \mod m \neq O.
137 match (pair nat nat q r) with
138 [ (pair q r) \Rightarrow r \mod m \neq O].
140 apply p_ord_aux_to_Prop1.
141 assumption.assumption.assumption.
144 theorem p_ord_exp1: \forall p,n,q,r. O < p \to \lnot p \divides r \to
145 n = p \sup q * r \to p_ord n p = pair nat nat q r.
150 |unfold.intro.apply H1.
151 apply mod_O_to_divides[assumption|assumption]
152 |apply (trans_le ? (p \sup q)).
154 elim q.simplify.apply le_n_Sn.
156 generalize in match H3.
157 apply (nat_case n1).simplify.
158 rewrite < times_n_SO.intro.assumption.
160 apply (trans_le ? (p*(S m))).
161 apply (trans_le ? ((S (S O))*(S m))).
162 simplify.rewrite > plus_n_Sm.
167 apply le_times_r.assumption.
168 apply not_eq_to_le_to_lt.
169 unfold.intro.apply H1.
171 apply (witness ? r r ?).simplify.apply plus_n_O.
173 rewrite > times_n_SO in \vdash (? % ?).
175 change with (O \lt r).
176 apply not_eq_to_le_to_lt.
178 apply H1.rewrite < H3.
179 apply (witness ? ? O ?).rewrite < times_n_O.reflexivity.
184 theorem p_ord_to_exp1: \forall p,n,q,r. (S O) \lt p \to O \lt n \to p_ord n p = pair nat nat q r\to
185 \lnot p \divides r \land n = p \sup q * r.
189 apply (p_ord_aux_to_not_mod_O n n p q r).assumption.assumption.
190 apply le_n.symmetry.assumption.
191 apply divides_to_mod_O.apply (trans_lt ? (S O)).
192 unfold.apply le_n.assumption.assumption.
193 apply (p_ord_aux_to_exp n).apply (trans_lt ? (S O)).
194 unfold.apply le_n.assumption.symmetry.assumption.
197 theorem eq_p_ord_q_O: ∀p,n,q. p_ord n p = pair ? ? q O → n=O ∧ q=O.
200 [ cases p; simplify; intros; destruct H; split; reflexivity;
208 rewrite < minus_n_O in H;
210 change in H:(? ? match % return ? with [_⇒?|_⇒?] ?) with (mod n1 (S O));
211 rewrite > mod_SO in H;
213 change in H:(? ? match ? ? (? %) ? return ? with [_⇒?] ?) with (div n1 (S O));
214 rewrite > div_SO in H;
217 letin H1 ≝ (p_ord_aux_to_exp n1 (S n1) 1); clearbody H1;
218 elim (p_ord_aux n1 (S n1) 1) in H H1 (q' r'); simplify in H H1;
220 lapply (H1 q' O (le_n ?) (refl_eq ? ?));
221 rewrite < times_n_O in Hletin;
224 lapply (p_ord_to_exp1 ? ? ? ? ? ? H);
232 apply (witness ? O O);
237 theorem p_ord_times: \forall p,a,b,qa,ra,qb,rb. prime p
238 \to O \lt a \to O \lt b
239 \to p_ord a p = pair nat nat qa ra
240 \to p_ord b p = pair nat nat qb rb
241 \to p_ord (a*b) p = pair nat nat (qa + qb) (ra*rb).
244 elim (p_ord_to_exp1 ? ? ? ? Hcut H1 H3).
245 elim (p_ord_to_exp1 ? ? ? ? Hcut H2 H4).
247 apply (trans_lt ? (S O)).unfold.apply le_n.assumption.
249 elim (divides_times_to_divides ? ? ? H H9).
250 apply (absurd ? ? H10 H5).
251 apply (absurd ? ? H10 H7).
255 autobatch paramodulation.
256 unfold prime in H. elim H. assumption.
259 theorem fst_p_ord_times: \forall p,a,b. prime p
260 \to O \lt a \to O \lt b
261 \to fst ? ? (p_ord (a*b) p) = (fst ? ? (p_ord a p)) + (fst ? ? (p_ord b p)).
263 rewrite > (p_ord_times p a b (fst ? ? (p_ord a p)) (snd ? ? (p_ord a p))
264 (fst ? ? (p_ord b p)) (snd ? ? (p_ord b p)) H H1 H2).
265 simplify.reflexivity.
266 apply eq_pair_fst_snd.
267 apply eq_pair_fst_snd.
270 theorem p_ord_p : \forall p:nat. (S O) \lt p \to p_ord p p = pair ? ? (S O) (S O).
273 apply (trans_lt ? (S O)). unfold.apply le_n.assumption.
275 apply (absurd ? ? H).
277 apply divides_to_le.unfold.apply le_n.assumption.
278 rewrite < times_n_SO.
282 (* p_ord and divides *)
283 theorem divides_to_p_ord: \forall p,a,b,c,d,n,m:nat.
284 O < n \to O < m \to prime p
285 \to divides n m \to p_ord n p = pair ? ? a b \to
286 p_ord m p = pair ? ? c d \to divides b d \land a \le c.
289 [lapply (p_ord_to_exp1 ? ? ? ? Hcut H H4).
290 lapply (p_ord_to_exp1 ? ? ? ? Hcut H1 H5).
291 elim Hletin. clear Hletin.
292 elim Hletin1. clear Hletin1.
295 [apply (gcd_SO_to_divides_times_to_divides (exp p c))
296 [elim (le_to_or_lt_eq ? ? (le_O_n b))
299 apply (lt_to_not_eq O ? H).
302 autobatch;assumption;
308 apply eq_gcd_times_SO
309 [apply lt_to_le.assumption
310 |apply lt_O_exp.apply lt_to_le.assumption
312 (* hint non trova prime_to_gcd_SO e
313 autobatch non chiude il goal *)
314 apply prime_to_gcd_SO
315 [assumption|assumption]
319 |apply (trans_divides ? n)
320 [apply (witness ? ? (exp p a)).
326 |apply (le_exp_to_le p)
329 [apply lt_O_exp.apply lt_to_le.assumption
330 |apply (gcd_SO_to_divides_times_to_divides d)
331 [apply lt_O_exp.apply lt_to_le.assumption
334 |simplify.rewrite < sym_gcd.
335 apply eq_gcd_times_SO
336 [apply lt_to_le.assumption
337 |apply lt_O_exp.apply lt_to_le.assumption
339 (* hint non trova prime_to_gcd_SO e
340 autobatch non chiude il goal *)
341 apply prime_to_gcd_SO
342 [assumption|assumption]
343 |rewrite > sym_gcd. assumption
346 |apply (trans_divides ? n)
347 [apply (witness ? ? b).assumption
348 |rewrite > sym_times.assumption
358 (* p_ord and primes *)
359 theorem not_divides_to_p_ord_O: \forall n,i.
360 Not (divides (nth_prime i) n) \to p_ord n (nth_prime i) =
364 [apply lt_O_nth_prime_n
370 theorem p_ord_O_to_not_divides: \forall n,i,r.
372 p_ord n (nth_prime i) = pair nat nat O r
373 \to Not (divides (nth_prime i) n).
375 lapply (p_ord_to_exp1 ? ? ? ? ? ? H1)
376 [apply lt_SO_nth_prime_n
386 theorem p_ord_to_not_eq_O : \forall n,p,q,r.
388 p_ord n (nth_prime p) = pair nat nat q r \to
393 [lapply (p_ord_to_exp1 ? ? ? ? ? ? H1)
394 [apply lt_SO_nth_prime_n.
397 apply (lt_to_not_eq ? ? Hcut).
402 |apply (trans_lt ? (S O))[apply lt_O_S|assumption]
406 definition ord :nat \to nat \to nat \def
407 \lambda n,p. fst ? ? (p_ord n p).
409 definition ord_rem :nat \to nat \to nat \def
410 \lambda n,p. snd ? ? (p_ord n p).
412 theorem divides_to_ord: \forall p,n,m:nat.
413 O < n \to O < m \to prime p
415 \to divides (ord_rem n p) (ord_rem m p) \land (ord n p) \le (ord m p).
417 apply (divides_to_p_ord p ? ? ? ? n m H H1 H2 H3)
418 [unfold ord.unfold ord_rem.apply eq_pair_fst_snd
419 |unfold ord.unfold ord_rem.apply eq_pair_fst_snd
423 theorem divides_to_divides_ord_rem: \forall p,n,m:nat.
424 O < n \to O < m \to prime p \to divides n m \to
425 divides (ord_rem n p) (ord_rem m p).
427 elim (divides_to_ord p n m H H1 H2 H3).assumption.
430 theorem divides_to_le_ord: \forall p,n,m:nat.
431 O < n \to O < m \to prime p \to divides n m \to
432 (ord n p) \le (ord m p).
434 elim (divides_to_ord p n m H H1 H2 H3).assumption.
437 theorem exp_ord: \forall p,n. (S O) \lt p
438 \to O \lt n \to n = p \sup (ord n p) * (ord_rem n p).
440 elim (p_ord_to_exp1 p n (ord n p) (ord_rem n p))
444 |unfold ord.unfold ord_rem.
445 apply eq_pair_fst_snd
449 theorem divides_ord_rem: \forall p,n. (S O) < p \to O < n
450 \to divides (ord_rem n p) n.
452 apply (witness ? ? (p \sup (ord n p))).
454 apply exp_ord[assumption|assumption]
457 theorem lt_O_ord_rem: \forall p,n. (S O) < p \to O < n \to O < ord_rem n p.
459 elim (le_to_or_lt_eq O (ord_rem n p))
462 apply (lt_to_not_eq ? ? H1).
463 lapply (divides_ord_rem ? ? H H1).
464 rewrite < H2 in Hletin.
472 (* properties of ord e ord_rem *)
474 theorem ord_times: \forall p,m,n.O<m \to O<n \to prime p \to
475 ord (m*n) p = ord m p+ord n p.
477 rewrite > (p_ord_times ? ? ? (ord m p) (ord_rem m p) (ord n p) (ord_rem n p))
482 |unfold ord.unfold ord_rem.apply eq_pair_fst_snd
483 |unfold ord.unfold ord_rem.apply eq_pair_fst_snd
487 theorem ord_exp: \forall p,m.S O < p \to
491 rewrite > (p_ord_exp1 p (exp p m) m (S O))
493 |apply lt_to_le.assumption
494 |intro.apply (lt_to_not_le ? ? H).
503 theorem not_divides_to_ord_O:
504 \forall p,m. prime p \to \lnot (divides p m) \to
507 rewrite > (p_ord_exp1 p m O m)
509 |apply prime_to_lt_O.assumption
511 |simplify.apply plus_n_O
515 theorem ord_O_to_not_divides:
516 \forall p,m. O < m \to prime p \to ord m p = O \to
519 lapply (p_ord_to_exp1 p m (ord m p) (ord_rem m p))
524 rewrite < times_n_SO.
526 |apply prime_to_lt_SO.assumption
528 |unfold ord.unfold ord_rem.apply eq_pair_fst_snd
532 theorem divides_to_not_ord_O:
533 \forall p,m. O < m \to prime p \to divides p m \to
536 apply (ord_O_to_not_divides ? ? H H1 H3).
540 theorem not_ord_O_to_divides:
541 \forall p,m. O < m \to prime p \to \lnot (ord m p = O) \to
544 rewrite > (exp_ord p) in ⊢ (? ? %)
545 [apply (trans_divides ? (exp p (ord m p)))
546 [generalize in match H2.
547 cases (ord m p);intro
548 [apply False_ind.apply H3.reflexivity
553 |apply prime_to_lt_SO.
559 theorem not_divides_ord_rem: \forall m,p.O< m \to S O < p \to
560 \lnot (divides p (ord_rem m p)).
562 elim (p_ord_to_exp1 p m (ord m p) (ord_rem m p))
566 |unfold ord.unfold ord_rem.apply eq_pair_fst_snd
570 theorem ord_ord_rem: \forall p,q,m. O < m \to
571 prime p \to prime q \to
572 q < p \to ord (ord_rem m p) q = ord m q.
574 rewrite > (exp_ord p) in ⊢ (? ? ? (? % ?))
576 [rewrite > not_divides_to_ord_O in ⊢ (? ? ? (? % ?))
580 apply (lt_to_not_eq ? ? H3).
581 apply (divides_exp_to_eq ? ? ? H2 H1 H4)
584 apply (ltn_to_ltO ? ? H3)
597 theorem lt_ord_rem: \forall n,m. prime n \to O < m \to
598 divides n m \to ord_rem m n < m.
600 elim (le_to_or_lt_eq (ord_rem m n) m)
603 apply (ord_O_to_not_divides ? ? H1 H ? H2).
605 [apply prime_to_lt_SO.assumption
606 |apply (inj_times_l1 m)
608 |rewrite > sym_times in ⊢ (? ? ? %).
609 rewrite < times_n_SO.
610 rewrite < H3 in ⊢ (? ? (? ? %) ?).
613 [apply prime_to_lt_SO.assumption
620 |apply divides_ord_rem
621 [apply prime_to_lt_SO.assumption
628 (* p_ord_inv is used to encode the pair ord and rem into
629 a single natural number. *)
631 definition p_ord_inv \def
634 [pair q r \Rightarrow r*m+q].
636 theorem eq_p_ord_inv: \forall p,m,x.
637 p_ord_inv p m x = (ord_rem x p)*m+(ord x p).
638 intros.unfold p_ord_inv. unfold ord_rem.
644 theorem div_p_ord_inv:
645 \forall p,m,x. ord x p < m \to p_ord_inv p m x / m = ord_rem x p.
646 intros.rewrite > eq_p_ord_inv.
647 apply div_plus_times.
651 theorem mod_p_ord_inv:
652 \forall p,m,x. ord x p < m \to p_ord_inv p m x \mod m = ord x p.
653 intros.rewrite > eq_p_ord_inv.
654 apply mod_plus_times.