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 set "baseuri" "cic:/matita/library_auto/nat/factorization".
17 include "auto/nat/ord.ma".
18 include "auto/nat/gcd.ma".
19 include "auto/nat/nth_prime.ma".
21 (* the following factorization algorithm looks for the largest prime
23 definition max_prime_factor \def \lambda n:nat.
24 (max n (\lambda p:nat.eqb (n \mod (nth_prime p)) O)).
26 (* max_prime_factor is indeed a factor *)
27 theorem divides_max_prime_factor_n:
28 \forall n:nat. (S O) < n
29 \to nth_prime (max_prime_factor n) \divides n.
31 apply divides_b_true_to_divides
32 [ apply lt_O_nth_prime_n
33 | apply (f_max_true (\lambda p:nat.eqb (n \mod (nth_prime p)) O) n);
34 cut (\exists i. nth_prime i = smallest_factor n)
36 apply (ex_intro nat ? a).
38 [ apply (trans_le a (nth_prime a))
41 exact lt_nth_prime_n_nth_prime_Sn*)
43 apply le_smallest_factor_n
46 (*CSC: simplify here does something nasty! *)
47 change with (divides_b (smallest_factor n) n = true).
48 apply divides_to_divides_b_true
50 (*apply (trans_lt ? (S O))
53 | apply lt_SO_smallest_factor.
60 apply divides_smallest_factor_n;
61 apply (trans_lt ? (S O));
62 [ unfold lt; apply le_n;
68 apply prime_to_nth_prime;
69 apply prime_smallest_factor_n;
75 theorem divides_to_max_prime_factor : \forall n,m. (S O) < n \to O < m \to n \divides m \to
76 max_prime_factor n \le max_prime_factor m.
78 unfold max_prime_factor.
81 (*apply (trans_le ? n)
83 | apply divides_to_le;assumption
85 | change with (divides_b (nth_prime (max_prime_factor n)) m = true).
86 apply divides_to_divides_b_true
88 (*cut (prime (nth_prime (max_prime_factor n)))
89 [ apply lt_O_nth_prime_n
90 | apply prime_nth_prime
93 (*cut (nth_prime (max_prime_factor n) \divides n)
98 [ apply (transitive_divides ? n);
99 [ apply divides_max_prime_factor_n.
103 | apply divides_b_true_to_divides;
104 [ apply lt_O_nth_prime_n.
105 | apply divides_to_divides_b_true;
106 [ apply lt_O_nth_prime_n.
107 | apply divides_max_prime_factor_n.
117 theorem p_ord_to_lt_max_prime_factor: \forall n,p,q,r. O < n \to
118 p = max_prime_factor n \to
119 (pair nat nat q r) = p_ord n (nth_prime p) \to
120 (S O) < r \to max_prime_factor r < p.
123 cut (max_prime_factor r \lt max_prime_factor n \lor
124 max_prime_factor r = max_prime_factor n)
127 | absurd (nth_prime (max_prime_factor n) \divides r)
130 (*apply divides_max_prime_factor_n.
134 cut (r \mod (nth_prime (max_prime_factor n)) \neq O)
136 (*unfold Not in Hcut1.
139 apply Hcut1.apply divides_to_mod_O;
140 [ apply lt_O_nth_prime_n.
145 cut(pair nat nat q r=p_ord_aux n n (nth_prime (max_prime_factor n)));
151 (* CERCA COME MAI le_n non lo applica se lo trova come Const e non Rel *)
154 apply (p_ord_aux_to_not_mod_O n n ? q r);
155 [ apply lt_SO_nth_prime_n.
158 | rewrite < H1.assumption.
164 | apply (le_to_or_lt_eq (max_prime_factor r) (max_prime_factor n)).
165 apply divides_to_max_prime_factor
168 | apply (witness r n ((nth_prime p) \sup q)).
170 apply (p_ord_aux_to_exp n n ? q r)
171 [ apply lt_O_nth_prime_n
178 theorem p_ord_to_lt_max_prime_factor1: \forall n,p,q,r. O < n \to
179 max_prime_factor n \le p \to
180 (pair nat nat q r) = p_ord n (nth_prime p) \to
181 (S O) < r \to max_prime_factor r < p.
183 cut (max_prime_factor n < p \lor max_prime_factor n = p)
185 [ apply (le_to_lt_to_lt ? (max_prime_factor n))
186 [ apply divides_to_max_prime_factor
189 | apply (witness r n ((nth_prime p) \sup q)).
191 (*qui auto non chiude il goal*)
192 apply (p_ord_aux_to_exp n n)
193 [ apply lt_O_nth_prime_n.
199 | apply (p_ord_to_lt_max_prime_factor n ? q);auto
207 | apply (le_to_or_lt_eq ? p H1)
211 (* datatypes and functions *)
213 inductive nat_fact : Set \def
214 nf_last : nat \to nat_fact
215 | nf_cons : nat \to nat_fact \to nat_fact.
217 inductive nat_fact_all : Set \def
218 nfa_zero : nat_fact_all
219 | nfa_one : nat_fact_all
220 | nfa_proper : nat_fact \to nat_fact_all.
222 let rec factorize_aux p n acc \def
226 match p_ord n (nth_prime p1) with
227 [ (pair q r) \Rightarrow
228 factorize_aux p1 r (nf_cons q acc)]].
230 definition factorize : nat \to nat_fact_all \def \lambda n:nat.
232 [ O \Rightarrow nfa_zero
235 [ O \Rightarrow nfa_one
237 let p \def (max (S(S n2)) (\lambda p:nat.eqb ((S(S n2)) \mod (nth_prime p)) O)) in
238 match p_ord (S(S n2)) (nth_prime p) with
239 [ (pair q r) \Rightarrow
240 nfa_proper (factorize_aux p r (nf_last (pred q)))]]].
242 let rec defactorize_aux f i \def
244 [ (nf_last n) \Rightarrow (nth_prime i) \sup (S n)
245 | (nf_cons n g) \Rightarrow
246 (nth_prime i) \sup n *(defactorize_aux g (S i))].
248 definition defactorize : nat_fact_all \to nat \def
249 \lambda f : nat_fact_all.
251 [ nfa_zero \Rightarrow O
252 | nfa_one \Rightarrow (S O)
253 | (nfa_proper g) \Rightarrow defactorize_aux g O].
255 theorem lt_O_defactorize_aux:
258 O < defactorize_aux f i.
264 rewrite > times_n_SO;auto
266 [ change with (O < nth_prime i).
267 apply lt_O_nth_prime_n
269 change with (O < exp (nth_prime i) n);
271 apply lt_O_nth_prime_n
272 | change with (O < defactorize_aux n1 (S i)).
278 theorem lt_SO_defactorize_aux: \forall f:nat_fact.\forall i:nat.
279 S O < defactorize_aux f i.
284 rewrite > times_n_SO.
287 [ change with (S O < nth_prime i).
288 apply lt_SO_nth_prime_n
289 | change with (O < exp (nth_prime i) n).
291 apply lt_O_nth_prime_n
295 rewrite > times_n_SO.
299 [ change with (O < exp (nth_prime i) n).
301 apply lt_O_nth_prime_n
302 | change with (S O < defactorize_aux n1 (S i)).
308 theorem defactorize_aux_factorize_aux :
309 \forall p,n:nat.\forall acc:nat_fact.O < n \to
310 ((n=(S O) \land p=O) \lor max_prime_factor n < p) \to
311 defactorize_aux (factorize_aux p n acc) O = n*(defactorize_aux acc p).
322 apply (not_le_Sn_O (max_prime_factor n) H2)
325 (* generalizing the goal: I guess there exists a better way *)
326 cut (\forall q,r.(pair nat nat q r) = (p_ord_aux n1 n1 (nth_prime n)) \to
327 defactorize_aux match (p_ord_aux n1 n1 (nth_prime n)) with
328 [(pair q r) \Rightarrow (factorize_aux n r (nf_cons q acc))] O =
329 n1*defactorize_aux acc (S n))
330 [ (*invocando auto in questo punto, dopo circa 7 minuti l'esecuzione non era ancora terminata
331 ne' con un errore ne' chiudendo il goal
333 apply (Hcut (fst ? ? (p_ord_aux n1 n1 (nth_prime n)))
334 (snd ? ? (p_ord_aux n1 n1 (nth_prime n)))).
336 (*apply sym_eq.apply eq_pair_fst_snd*)
340 cut (n1 = r * (nth_prime n) \sup q)
344 (*rewrite < assoc_times.
348 (*cut (O < r \lor O = r)
357 apply (not_le_Sn_O O).
358 rewrite < H5 in \vdash (? ? %).
362 | apply le_to_or_lt_eq.
365 | cut ((S O) < r \lor (S O) \nlt r)
368 apply (p_ord_to_lt_max_prime_factor1 n1 ? q r)
373 apply (not_eq_O_S n).
378 (*apply le_S_S_to_le.
401 | cut (r < (S O) ∨ r=(S O))
405 (*apply le_n_O_to_eq.
412 [ apply (not_le_Sn_O O).
413 rewrite > Hcut3 in ⊢ (? ? %).
423 (*apply (le_to_or_lt_eq r (S O)).
429 | apply (decidable_lt (S O) r)
432 | rewrite > sym_times.
433 apply (p_ord_aux_to_exp n1 n1)
434 [ apply lt_O_nth_prime_n
442 theorem defactorize_factorize: \forall n:nat.defactorize (factorize n) = n.
449 | intro.(*CSC: simplify here does something really nasty *)
451 (let p \def (max (S(S m1)) (\lambda p:nat.eqb ((S(S m1)) \mod (nth_prime p)) O)) in
452 defactorize (match p_ord (S(S m1)) (nth_prime p) with
453 [ (pair q r) \Rightarrow
454 nfa_proper (factorize_aux p r (nf_last (pred q)))])=(S(S m1))).
456 (* generalizing the goal; find a better way *)
457 cut (\forall q,r.(pair nat nat q r) = (p_ord (S(S m1)) (nth_prime p)) \to
458 defactorize (match p_ord (S(S m1)) (nth_prime p) with
459 [ (pair q r) \Rightarrow
460 nfa_proper (factorize_aux p r (nf_last (pred q)))])=(S(S m1)))
461 [ (*invocando auto qui, dopo circa 300 secondi non si ottiene alcun risultato*)
462 apply (Hcut (fst ? ? (p_ord (S(S m1)) (nth_prime p)))
463 (snd ? ? (p_ord (S(S m1)) (nth_prime p)))).
466 apply eq_pair_fst_snd*)
470 cut ((S(S m1)) = (nth_prime p) \sup q *r)
472 [ rewrite > defactorize_aux_factorize_aux
473 [ (*CSC: simplify here does something really nasty *)
474 change with (r*(nth_prime p) \sup (S (pred q)) = (S(S m1))).
475 cut ((S (pred q)) = q)
476 [ (*invocando auto qui, dopo circa 300 secondi non si ottiene ancora alcun risultato*)
479 (*rewrite > sym_times.
481 apply (p_ord_aux_to_exp (S(S m1)))
482 [ apply lt_O_nth_prime_n
488 cut (O < q \lor O = q)
491 | absurd (nth_prime p \divides S (S m1))
492 [ apply (divides_max_prime_factor_n (S (S m1))).
498 | cut ((S(S m1)) = r)
499 [ rewrite > Hcut3 in \vdash (? (? ? %)).
500 (*CSC: simplify here does something really nasty *)
501 change with (nth_prime p \divides r \to False).
503 apply (p_ord_aux_to_not_mod_O (S(S m1)) (S(S m1)) (nth_prime p) q r) [ apply lt_SO_nth_prime_n
510 | (*invocando auto qui, dopo circa 300 secondi non si ottiene ancora alcun risultato*)
511 apply divides_to_mod_O
512 [ apply lt_O_nth_prime_n
516 | rewrite > times_n_SO in \vdash (? ? ? %).
518 rewrite > (exp_n_O (nth_prime p)).
519 rewrite > H1 in \vdash (? ? ? (? (? ? %) ?)).
525 (*apply le_to_or_lt_eq.
530 | (* e adesso l'ultimo goal. TASSI: che ora non e' piu' l'ultimo :P *)
531 cut ((S O) < r \lor S O \nlt r)
534 apply (p_ord_to_lt_max_prime_factor1 (S(S m1)) ? q r);auto
559 | cut (r \lt (S O) \or r=(S O))
562 (*[ apply le_n_O_to_eq.
567 apply (not_le_Sn_O O).
568 rewrite > H3 in \vdash (? ? %).
574 (*apply (le_to_or_lt_eq r (S O)).
580 | apply (decidable_lt (S O) r)
584 cut (O < r \lor O = r)
588 apply (not_eq_O_S (S m1)).
592 (*rewrite < times_n_O.
596 (*apply le_to_or_lt_eq.
600 | (* prova del cut *)
601 apply (p_ord_aux_to_exp (S(S m1)));auto
602 (*[ apply lt_O_nth_prime_n
614 [ (nf_last n) \Rightarrow O
615 | (nf_cons n g) \Rightarrow S (max_p g)].
617 let rec max_p_exponent f \def
619 [ (nf_last n) \Rightarrow n
620 | (nf_cons n g) \Rightarrow max_p_exponent g].
622 theorem divides_max_p_defactorize: \forall f:nat_fact.\forall i:nat.
623 nth_prime ((max_p f)+i) \divides defactorize_aux f i.
628 (*apply (witness ? ? ((nth_prime i) \sup n)).
631 (nth_prime (S(max_p n1)+i) \divides
632 (nth_prime i) \sup n *(defactorize_aux n1 (S i))).
636 rewrite > assoc_times.
638 (*rewrite < plus_n_Sm.
639 apply (witness ? ? (n2* (nth_prime i) \sup n)).
644 theorem divides_exp_to_divides:
645 \forall p,n,m:nat. prime p \to
646 p \divides n \sup m \to p \divides n.
651 (*apply (transitive_divides p (S O))
655 | cut (p \divides n \lor p \divides n \sup n1)
659 (*apply H;assumption*)
662 (*apply divides_times_to_divides
670 theorem divides_exp_to_eq:
671 \forall p,q,m:nat. prime p \to prime q \to
672 p \divides q \sup m \to p = q.
677 [ apply (divides_exp_to_divides p q m);assumption
678 | (*invocando auto in questo punto, dopo piu' di 8 minuti la computazione non
679 * era ancora terminata.
682 (*invocando auto anche in questo punto, dopo piu' di 10 minuti la computazione
683 * non era ancora terminata.
690 theorem not_divides_defactorize_aux: \forall f:nat_fact. \forall i,j:nat.
691 i < j \to nth_prime i \ndivides defactorize_aux f j.
695 (nth_prime i \divides (nth_prime j) \sup (S n) \to False).
697 absurd ((nth_prime i) = (nth_prime j))
698 [ apply (divides_exp_to_eq ? ? (S n));auto
699 (*[ apply prime_nth_prime
700 | apply prime_nth_prime
706 [ apply (not_le_Sn_n i).
707 rewrite > Hcut in \vdash (? ? %).
709 | apply (injective_nth_prime ? ? H2)
715 cut (nth_prime i \divides (nth_prime j) \sup n
716 \lor nth_prime i \divides defactorize_aux n1 (S j))
718 [ absurd ((nth_prime i) = (nth_prime j))
719 [ apply (divides_exp_to_eq ? ? n);auto
720 (*[ apply prime_nth_prime
721 | apply prime_nth_prime
727 [ apply (not_le_Sn_n i).
728 rewrite > Hcut1 in \vdash (? ? %).
730 | apply (injective_nth_prime ? ? H4)
735 (*apply (trans_lt ? j)
744 (*apply divides_times_to_divides.
745 apply prime_nth_prime.
751 lemma not_eq_nf_last_nf_cons: \forall g:nat_fact.\forall n,m,i:nat.
752 \lnot (defactorize_aux (nf_last n) i= defactorize_aux (nf_cons m g) i).
755 (exp (nth_prime i) (S n) = defactorize_aux (nf_cons m g) i \to False).
757 cut (S(max_p g)+i= i)
758 [ apply (not_le_Sn_n i).
759 rewrite < Hcut in \vdash (? ? %). (*chiamando auto qui da uno strano errore "di tipo"*)
764 | apply injective_nth_prime.
765 apply (divides_exp_to_eq ? ? (S n))
766 [ apply prime_nth_prime
767 | apply prime_nth_prime
769 change with (divides (nth_prime ((max_p (nf_cons m g))+i))
770 (defactorize_aux (nf_cons m g) i)).
771 apply divides_max_p_defactorize
776 lemma not_eq_nf_cons_O_nf_cons: \forall f,g:nat_fact.\forall n,i:nat.
777 \lnot (defactorize_aux (nf_cons O f) i= defactorize_aux (nf_cons (S n) g) i).
783 apply (not_divides_defactorize_aux f i (S i) ?)
789 rewrite > assoc_times.
790 apply (witness ? ? ((exp (nth_prime i) n)*(defactorize_aux g (S i)))).
795 theorem eq_defactorize_aux_to_eq: \forall f,g:nat_fact.\forall i:nat.
796 defactorize_aux f i = defactorize_aux g i \to f = g.
799 [ generalize in match H.
803 apply (inj_exp_r (nth_prime i))
804 [ apply lt_SO_nth_prime_n
805 | (*qui auto non conclude il goal attivo*)
809 (*auto chiamato qui NON conclude il goal attivo*)
810 apply (not_eq_nf_last_nf_cons n2 n n1 i H2)
812 | generalize in match H1.
815 apply (not_eq_nf_last_nf_cons n1 n2 n i).
820 generalize in match H3.
821 apply (nat_elim2 (\lambda n,n2.
822 ((nth_prime i) \sup n)*(defactorize_aux n1 (S i)) =
823 ((nth_prime i) \sup n2)*(defactorize_aux n3 (S i)) \to
824 nf_cons n n1 = nf_cons n2 n3))
832 rewrite > (plus_n_O (defactorize_aux n3 (S i))).
835 apply (not_eq_nf_cons_O_nf_cons n1 n3 n5 i).
836 (*auto chiamato qui NON chiude il goal attivo*)
841 apply (not_eq_nf_cons_O_nf_cons n3 n1 n4 i).
843 (*auto chiamato qui non chiude il goal*)
846 cut (nf_cons n4 n1 = nf_cons m n3)
854 (match nf_cons n4 n1 with
855 [ (nf_last m) \Rightarrow n1
856 | (nf_cons m g) \Rightarrow g ] = n3).
863 (match nf_cons n4 n1 with
864 [ (nf_last m) \Rightarrow m
865 | (nf_cons m g) \Rightarrow m ] = m).
866 (*invocando auto qui, dopo circa 8 minuti la computazione non era ancora terminata*)
874 apply (inj_times_r1 (nth_prime i))
875 [ apply lt_O_nth_prime_n
876 | rewrite < assoc_times.
877 rewrite < assoc_times.
886 theorem injective_defactorize_aux: \forall i:nat.
887 injective nat_fact nat (\lambda f.defactorize_aux f i).
890 apply (eq_defactorize_aux_to_eq x y i H).
893 theorem injective_defactorize:
894 injective nat_fact_all nat defactorize.
896 change with (\forall f,g.defactorize f = defactorize g \to f=g).
899 [ generalize in match H.
906 apply (not_eq_O_S O H1)
907 | (* zero - proper *)
910 apply (not_le_Sn_n O).
911 rewrite > H1 in \vdash (? ? %).
913 (*change with (O < defactorize_aux n O).
914 apply lt_O_defactorize_aux*)
916 | generalize in match H.
922 (*apply (not_eq_O_S O).
930 apply (not_le_Sn_n (S O)).
931 rewrite > H1 in \vdash (? ? %).
933 (*change with ((S O) < defactorize_aux n O).
934 apply lt_SO_defactorize_aux*)
936 | generalize in match H.
938 [ (* proper - zero *)
941 apply (not_le_Sn_n O).
942 rewrite < H1 in \vdash (? ? %).
944 (*change with (O < defactorize_aux n O).
945 apply lt_O_defactorize_aux.*)
949 apply (not_le_Sn_n (S O)).
950 rewrite < H1 in \vdash (? ? %).
952 (*change with ((S O) < defactorize_aux n O).
953 apply lt_SO_defactorize_aux.*)
954 | (* proper - proper *)
956 apply (injective_defactorize_aux O).
957 (*invocata qui la tattica auto NON chiude il goal, chiuso invece
965 theorem factorize_defactorize:
966 \forall f,g: nat_fact_all. factorize (defactorize f) = f.
969 (*apply injective_defactorize.
970 apply defactorize_factorize.