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).
254 autobatch paramodulation.
255 unfold prime in H. elim H. assumption.
258 theorem fst_p_ord_times: \forall p,a,b. prime p
259 \to O \lt a \to O \lt b
260 \to fst ? ? (p_ord (a*b) p) = (fst ? ? (p_ord a p)) + (fst ? ? (p_ord b p)).
262 rewrite > (p_ord_times p a b (fst ? ? (p_ord a p)) (snd ? ? (p_ord a p))
263 (fst ? ? (p_ord b p)) (snd ? ? (p_ord b p)) H H1 H2).
264 simplify.reflexivity.
265 apply eq_pair_fst_snd.
266 apply eq_pair_fst_snd.
269 theorem p_ord_p : \forall p:nat. (S O) \lt p \to p_ord p p = pair ? ? (S O) (S O).
272 apply (trans_lt ? (S O)). unfold.apply le_n.assumption.
274 apply (absurd ? ? H).
276 apply divides_to_le.unfold.apply le_n.assumption.
277 rewrite < times_n_SO.
281 (* p_ord and divides *)
282 theorem divides_to_p_ord: \forall p,a,b,c,d,n,m:nat.
283 O < n \to O < m \to prime p
284 \to divides n m \to p_ord n p = pair ? ? a b \to
285 p_ord m p = pair ? ? c d \to divides b d \land a \le c.
288 [lapply (p_ord_to_exp1 ? ? ? ? Hcut H H4).
289 lapply (p_ord_to_exp1 ? ? ? ? Hcut H1 H5).
290 elim Hletin. clear Hletin.
291 elim Hletin1. clear Hletin1.
294 [apply (gcd_SO_to_divides_times_to_divides (exp p c))
295 [elim (le_to_or_lt_eq ? ? (le_O_n b))
298 apply (lt_to_not_eq O ? H).
307 apply eq_gcd_times_SO
308 [apply lt_to_le.assumption
309 |apply lt_O_exp.apply lt_to_le.assumption
311 (* hint non trova prime_to_gcd_SO e
312 autobatch non chiude il goal *)
313 apply prime_to_gcd_SO
314 [assumption|assumption]
318 |apply (trans_divides ? n)
319 [apply (witness ? ? (exp p a)).
325 |apply (le_exp_to_le p)
328 [apply lt_O_exp.apply lt_to_le.assumption
329 |apply (gcd_SO_to_divides_times_to_divides d)
330 [apply lt_O_exp.apply lt_to_le.assumption
333 |simplify.rewrite < sym_gcd.
334 apply eq_gcd_times_SO
335 [apply lt_to_le.assumption
336 |apply lt_O_exp.apply lt_to_le.assumption
338 (* hint non trova prime_to_gcd_SO e
339 autobatch non chiude il goal *)
340 apply prime_to_gcd_SO
341 [assumption|assumption]
342 |rewrite > sym_gcd. assumption
345 |apply (trans_divides ? n)
346 [apply (witness ? ? b).assumption
347 |rewrite > sym_times.assumption
357 (* p_ord and primes *)
358 theorem not_divides_to_p_ord_O: \forall n,i.
359 Not (divides (nth_prime i) n) \to p_ord n (nth_prime i) =
363 [apply lt_O_nth_prime_n
369 theorem p_ord_O_to_not_divides: \forall n,i,r.
371 p_ord n (nth_prime i) = pair nat nat O r
372 \to Not (divides (nth_prime i) n).
374 lapply (p_ord_to_exp1 ? ? ? ? ? ? H1)
375 [apply lt_SO_nth_prime_n
385 theorem p_ord_to_not_eq_O : \forall n,p,q,r.
387 p_ord n (nth_prime p) = pair nat nat q r \to
392 [lapply (p_ord_to_exp1 ? ? ? ? ? ? H1)
393 [apply lt_SO_nth_prime_n.
396 apply (lt_to_not_eq ? ? Hcut).
401 |apply (trans_lt ? (S O))[apply lt_O_S|assumption]
405 definition ord :nat \to nat \to nat \def
406 \lambda n,p. fst ? ? (p_ord n p).
408 definition ord_rem :nat \to nat \to nat \def
409 \lambda n,p. snd ? ? (p_ord n p).
411 theorem divides_to_ord: \forall p,n,m:nat.
412 O < n \to O < m \to prime p
414 \to divides (ord_rem n p) (ord_rem m p) \land (ord n p) \le (ord m p).
416 apply (divides_to_p_ord p ? ? ? ? n m H H1 H2 H3)
417 [unfold ord.unfold ord_rem.apply eq_pair_fst_snd
418 |unfold ord.unfold ord_rem.apply eq_pair_fst_snd
422 theorem divides_to_divides_ord_rem: \forall p,n,m:nat.
423 O < n \to O < m \to prime p \to divides n m \to
424 divides (ord_rem n p) (ord_rem m p).
426 elim (divides_to_ord p n m H H1 H2 H3).assumption.
429 theorem divides_to_le_ord: \forall p,n,m:nat.
430 O < n \to O < m \to prime p \to divides n m \to
431 (ord n p) \le (ord m p).
433 elim (divides_to_ord p n m H H1 H2 H3).assumption.
436 theorem exp_ord: \forall p,n. (S O) \lt p
437 \to O \lt n \to n = p \sup (ord n p) * (ord_rem n p).
439 elim (p_ord_to_exp1 p n (ord n p) (ord_rem n p))
443 |unfold ord.unfold ord_rem.
444 apply eq_pair_fst_snd
448 theorem divides_ord_rem: \forall p,n. (S O) < p \to O < n
449 \to divides (ord_rem n p) n.
451 apply (witness ? ? (p \sup (ord n p))).
453 apply exp_ord[assumption|assumption]
456 theorem lt_O_ord_rem: \forall p,n. (S O) < p \to O < n \to O < ord_rem n p.
458 elim (le_to_or_lt_eq O (ord_rem n p))
461 apply (lt_to_not_eq ? ? H1).
462 lapply (divides_ord_rem ? ? H H1).
463 rewrite < H2 in Hletin.
471 (* properties of ord e ord_rem *)
473 theorem ord_times: \forall p,m,n.O<m \to O<n \to prime p \to
474 ord (m*n) p = ord m p+ord n p.
476 rewrite > (p_ord_times ? ? ? (ord m p) (ord_rem m p) (ord n p) (ord_rem n p))
481 |unfold ord.unfold ord_rem.apply eq_pair_fst_snd
482 |unfold ord.unfold ord_rem.apply eq_pair_fst_snd
486 theorem ord_exp: \forall p,m.S O < p \to
490 rewrite > (p_ord_exp1 p (exp p m) m (S O))
492 |apply lt_to_le.assumption
493 |intro.apply (lt_to_not_le ? ? H).
502 theorem not_divides_to_ord_O:
503 \forall p,m. prime p \to \lnot (divides p m) \to
506 rewrite > (p_ord_exp1 p m O m)
508 |apply prime_to_lt_O.assumption
510 |simplify.apply plus_n_O
514 theorem ord_O_to_not_divides:
515 \forall p,m. O < m \to prime p \to ord m p = O \to
518 lapply (p_ord_to_exp1 p m (ord m p) (ord_rem m p))
523 rewrite < times_n_SO.
525 |apply prime_to_lt_SO.assumption
527 |unfold ord.unfold ord_rem.apply eq_pair_fst_snd
531 theorem divides_to_not_ord_O:
532 \forall p,m. O < m \to prime p \to divides p m \to
535 apply (ord_O_to_not_divides ? ? H H1 H3).
539 theorem not_ord_O_to_divides:
540 \forall p,m. O < m \to prime p \to \lnot (ord m p = O) \to
543 rewrite > (exp_ord p) in ⊢ (? ? %)
544 [apply (trans_divides ? (exp p (ord m p)))
545 [generalize in match H2.
546 cases (ord m p);intro
547 [apply False_ind.apply H3.reflexivity
552 |apply prime_to_lt_SO.
558 theorem not_divides_ord_rem: \forall m,p.O< m \to S O < p \to
559 \lnot (divides p (ord_rem m p)).
561 elim (p_ord_to_exp1 p m (ord m p) (ord_rem m p))
565 |unfold ord.unfold ord_rem.apply eq_pair_fst_snd
569 theorem ord_ord_rem: \forall p,q,m. O < m \to
570 prime p \to prime q \to
571 q < p \to ord (ord_rem m p) q = ord m q.
573 rewrite > (exp_ord p) in ⊢ (? ? ? (? % ?))
575 [rewrite > not_divides_to_ord_O in ⊢ (? ? ? (? % ?))
579 apply (lt_to_not_eq ? ? H3).
580 apply (divides_exp_to_eq ? ? ? H2 H1 H4)
583 apply (ltn_to_ltO ? ? H3)
596 theorem lt_ord_rem: \forall n,m. prime n \to O < m \to
597 divides n m \to ord_rem m n < m.
599 elim (le_to_or_lt_eq (ord_rem m n) m)
602 apply (ord_O_to_not_divides ? ? H1 H ? H2).
604 [apply prime_to_lt_SO.assumption
605 |apply (inj_times_l1 m)
607 |rewrite > sym_times in ⊢ (? ? ? %).
608 rewrite < times_n_SO.
609 rewrite < H3 in ⊢ (? ? (? ? %) ?).
612 [apply prime_to_lt_SO.assumption
619 |apply divides_ord_rem
620 [apply prime_to_lt_SO.assumption
627 (* p_ord_inv is used to encode the pair ord and rem into
628 a single natural number. *)
630 definition p_ord_inv \def
633 [pair q r \Rightarrow r*m+q].
635 theorem eq_p_ord_inv: \forall p,m,x.
636 p_ord_inv p m x = (ord_rem x p)*m+(ord x p).
637 intros.unfold p_ord_inv. unfold ord_rem.
643 theorem div_p_ord_inv:
644 \forall p,m,x. ord x p < m \to p_ord_inv p m x / m = ord_rem x p.
645 intros.rewrite > eq_p_ord_inv.
646 apply div_plus_times.
650 theorem mod_p_ord_inv:
651 \forall p,m,x. ord x p < m \to p_ord_inv p m x \mod m = ord x p.
652 intros.rewrite > eq_p_ord_inv.
653 apply mod_plus_times.