1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5
;;;; Load with (ld "Exercise1.2.lisp")
7
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
13
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
15
;; The proof is structured in two main phases:
17
;; 1 - Prove that, given a set of coprimes m and a value m,
18
;; if each element of m divides v, then the product of the elements of m
20
;; 2 - Prove that, given a set of coprimes m, and given two values v1 and v2 which are
21
;; congruent modulo m with two sets of values l1 and l2, then l1 and l2
22
;; are congruent w.r.t. m iff v1 and v2 differ by a multiple of the
23
;; product of the elements of m. The ``if'' direction of this proof
24
;; exploits the statement obtained in phase 1.
26
;; Once the statement of phase 2 is proved, the theorem requested in the exercise
29
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
34
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
38
;; The key facts that are proved are the following (we omit the
39
;; statement of some hypothesis here):
41
;; (1) gcd(x,y) = 1 ^ y|v ^ x|v ==> xy|v (divides-both)
42
;; (2) gcd(x,y) = 1 ^ z|x ^ z|y ==> z = 1 (only-divisor-of-coprimes-is-1)
43
;; (3) gcd(x,y)|x ^ gcd(x,y)|y (gcd-divides-both)
44
;; (4) gcd(m,n) = 1 ^ gcd(n,k) = 1 ==> gcd(m,nk) =1 (prime-of-product)
45
;; (5) ForAll i: gcd(e,m_i) = 1 ==> gcd(m,Product(m_i)) = 1 (rel-prime-of-product)
46
;; (6) ForAll i,j with j<>j: gcd(m_i,m_j) = 1 ^
47
;; ForAll i: m_i|v ==> Product(m_i)|v
48
;; (if-every-coprime-divides-v-then-product-of-coprimes-divides-v)
51
;; The proof structure of this phase goes as follows:
70
(include-book "../../../../../arithmetic/mod-gcd")
72
(include-book "../../../../../rtl/rel1/lib1/basic")
74
(include-book "../../../../../rtl/rel1/support/fp")
76
;(local (include-book "../../../../../arithmetic/mod-gcd"))
78
;(local (include-book "../../../../../fp/lib/basic"))
80
;(local (include-book "../../../../../fp/fp"))
83
(defun g-c-d (x y) (nonneg-int-gcd x y))
86
(defun rel-prime (x y)
89
(defun rel-prime-all (x l)
92
(and (rel-prime x (car l))
93
(rel-prime-all x (cdr l)))))
95
(defun rel-prime-moduli (l)
98
(and (integerp (car l))
100
(rel-prime-all (car l) (cdr l))
101
(rel-prime-moduli (cdr l)))))
103
(defun divided-by-all (k m)
107
(integerp (/ k (car m)))
108
(divided-by-all k (cdr m)))))
114
(natp-all (cdr l)))))
120
(posp-all (cdr l)))))
125
(* (car l) (prod (cdr l)))))
128
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
130
;; First we prove that, if x and y are positive coprimes, and they both divide v,
131
;; then x * y divides v. We exploit the fact that the g-c-d can be expressed as
132
;; a linear combination of two multiplier functions, defined into the mod-gcd book.
134
;; The final lemma is stated by theorem divides-both.
136
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
138
(defun a (x y) (nonneg-int-gcd-multiplier1 x y))
140
(defun b (x y) (nonneg-int-gcd-multiplier2 x y))
144
(implies (and (integerp x) (integerp y))
145
(integerp (g-c-d x y)))
146
:rule-classes (:type-prescription))
149
(implies (and (integerp x) (>= x 0)
150
(integerp y) (>= y 0))
154
:hints (("Goal" :use Linear-combination-for-nonneg-int-gcd))
158
(in-theory (disable g-c-d))
161
(implies (and (integerp v) (= gcd 1)) (= (* v gcd) v))
171
(= (* v (+ (* (A X Y) X) (* (B X Y) Y))) v))
172
:hints (("Goal" :in-theory '((:definition natp))
174
(:instance hack-1 (gcd (+ (* (A X Y) X) (* (B X Y) Y)))))))
188
(= (* v (+ (* A X) (* B Y)) (/ (* x y)))
189
(+ (* (/ v y) a) (* (/ v x) b))))
201
(= (* v (+ (* (A X Y) X) (* (B X Y) Y)) (/ (* x y)))
202
(+ (* (/ v y) (a x y)) (* (/ v x) (b x y)))))
203
:hints (("Goal" :use ((:instance hack-3 (a (a x y)) (b (b x y)))
204
(:type-prescription a)
205
(:type-prescription b))))
216
(integerp (+ (* v1 v2) (* v3 v4))))
225
(integerp (+ (* (/ v y) (a x y)) (* (/ v x) (b x y)))))
226
:hints (("Goal" :use ( (:instance hack-5 (v1 (/ v y)) (v2 (a x y)) (v3 (/ v x)) (v4 (b x y)))
227
(:type-prescription a)
228
(:type-prescription b))))
240
(INTEGERP (* V div)))
241
:hints (("Goal" :in-theory nil))
257
(integerp (/ v (* x y))))
258
:hints (("Goal" :in-theory (current-theory 'ground-zero)
263
(:instance hack-7 (div (/ (* X Y)))
264
(res (+ (* (* V (/ Y)) (A X Y)) (* (* V (/ X)) (B X Y))))
265
(decomp-a-b (* V (+ (* (A X Y) X) (* (B X Y) Y)))))))))
270
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
272
;; Now we prove that the only common divisor of two coprimes is 1.
274
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
284
(equal (integerp (/ n d)) (equal (nonneg-int-mod n d) 0)))
285
:hints (("Goal" :use (:instance Left-nonneg-int-mod-* (n d) (j (/ n d))))))
289
(defthm only-divisor-of-coprimes-is-1
299
:hints (("Goal" :use (rel-prime g-c-d
300
(:instance Nonneg-int-gcd-is-LARGEST-common-divisor-<= (d z)))))
304
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
306
;; We now prove that (g-c-d x y) divides both x and y.
307
;; This is stated by theorem gcd-divides-both.
309
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
311
(defthm integer-div-of-factor
318
(integerp (/ (* b c) a)))
321
((:instance rel-prime (x a) (y b))
322
(:instance g-c-d (x a) (y b))
323
(:instance hack-8 (n c) (d a))
324
(:instance hack-8 (n (* b c)) (d a))
325
(:instance Divisor-of-product-divides-factor (y b) (z a) (x c))))))
341
(= (+ (* a x) (* b y)) 1))
342
(= (* c (+ (* a x) (* b y))) c))
349
(= (+ (* c a x) (* c b y))
350
(* c (+ (* a x) (* b y)))))
357
(= (+ (* a x) (* b y)) 1))
358
(= (+ (* c a x) (* c b y)) c))
359
:hints (("Goal" :use (hack-10 hack-11)))
372
(= k (+ (* k (a m n) m) (* k (b m n) n))))
373
:hints (("Goal" :use (
374
(:instance hack-12 (a (a m n)) (b (b m n)) (x m) (y n) (c k))
375
(:instance a-b-thm (x m) (y n))
376
(:instance rel-prime (x m) (y n)))))
387
(integerp (/ (* n k) cd))
389
(= k (+ (* k (a m n) (/ m cd) cd) (* (b m n) (/ (* n k) cd) cd))))
390
:hints (("Goal" :use (
392
(:instance hack-9 (x m) (y cd))
393
(:instance hack-9 (x (* n k)) (y cd)))))
404
(integerp (/ (* n k) cd))
406
(= k (* cd (+ (* k (a m n) (/ m cd) ) (* (b m n) (/ (* n k) cd))))))
407
:hints (("Goal" :use hack-14))
418
(integerp (/ (* n k) cd))
420
(integerp (+ (* k (a m n) (/ m cd) ) (* (b m n) (/ (* n k) cd)))))
431
(integerp (/ (* n k) cd))
433
(= (/ k cd) (+ (* k (a m n) (/ m cd) ) (* (b m n) (/ (* n k) cd)))))
434
:hints (("Goal" :use ( hack-16 hack-15)))
446
(integerp (/ (* n k) cd))
449
:hints (("Goal" :in-theory nil :use ( hack-16 hack-17)))
454
(defthm gcd-divides-both
460
(integerp (/ x (g-c-d x y)))
461
(integerp (/ y (g-c-d x y)))))
462
:hints (("Goal" :in-theory (enable g-c-d))))
466
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
468
;; Frome the fact that (g-c-d x y) divides both x and y, we easily
469
;; derive that, if m and n are coprimes, and m and k are coprimes,
470
;; then m and (n * k) are coprimes.
471
;; This is stated by prime-of-product.
473
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
485
(integerp (/ v (g-c-d v (* x y))))
486
(integerp (/ (* x y) (g-c-d v (* x y))))))
487
:hints (("Goal" :use ((:instance gcd-divides-both (x v) (y (* x y)))))))
499
(integerp (/ m (g-c-d m (* n k))))
500
(integerp (/ k (g-c-d m (* n k))))))
501
:hints (("Goal" :use (
502
(:instance g-c-d (x m) (y (* n k)))
503
(:instance Nonneg-int-gcd->-0 (n m) (d (* n k)))
504
(:instance hack-19 (v m) (x n) (y k))
505
(:instance hack-18 (cd (g-c-d m (* n k))))))))
508
(defthm prime-of-product
516
(rel-prime m (* n k)))
517
:hints (("Goal" :in-theory (enable rel-prime)
519
(:instance g-c-d (x m) (y (* n k)))
520
(:instance Nonneg-int-gcd->-0 (n m) (d (* n k)))
521
(:instance only-divisor-of-coprimes-is-1
522
(z (g-c-d m (* n k)))
528
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
530
;; We now prove that, if el is coprime with every element of a list
531
;; l, then it is coprime with their product (prod l).
532
;; This is stated by rel-prime-of-product.
534
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
537
(in-theory (enable prod rel-prime rel-prime-moduli))
548
(posp (prod (cdr m)))))
555
(rel-prime-all el m))
557
(rel-prime el (car m))
558
(rel-prime-all el (cdr m))))
559
:hints (("Goal" :use (:instance rel-prime-all (x el) (l m))))
563
(defthm rel-prime-of-product
568
(rel-prime-all el m))
569
(rel-prime el (prod m)))
570
:hints ( ("Goal" :in-theory (disable rel-prime natp) :induct (len m))
571
("Subgoal *1/2''" :use ( (:instance rel-prime (x el) (y 1))
572
(:instance g-c-d (x el) (y 1))
573
(:instance Nonneg-int-gcd-1-right (x el))))
574
("Subgoal *1/1'" :use
577
(:instance prod (l m))
578
(:instance prime-of-product (n (car m)) (k (prod (cdr m))) (m el))))))
581
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
583
;; We prove the main lemma of the first part of the proof,
584
;; namely that if m is a list of positive coprimes, and
585
;; every element of m divides v, then the product of the elements
586
;; of m, (prod m), divides v.
587
;; This is stated by if-every-coprime-divides-v-then-product-of-coprimes-divides-v.
589
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
595
(rel-prime-moduli m))
597
(rel-prime-moduli (cdr m))
605
(defthm if-every-coprime-divides-v-then-product-of-coprimes-divides-v
610
(divided-by-all v m))
611
(integerp (/ v (prod m))))
612
:hints (("Goal" :induct (len m))
614
:in-theory '((:definition posp) (:definition natp))
619
(:instance natp-all (l m))
620
(:instance posp-all (l m))
621
(:instance prod (l m))
622
(:instance rel-prime-moduli (l m))
623
(:instance divided-by-all (k v))
624
(:instance rel-prime-of-product (el (car m)) (m (cdr m)))
625
(:instance divides-both (x (car m)) (y (prod (cdr m))))))))
631
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
633
;; Second part of the proof.
635
;; We start by introducing the notion of congruence of a pair of lists
636
;; of numbers w.r.t. a third list of numbers.
637
;; Then we prove the following facts (where some hypothesis are omitted,
638
;; ``congruent'' indicates the definition congruent-all-mod, and
639
;; ``congruent-lists'' indicates the definition in
640
;; congruant-all-mod-list):
642
;; (7) ForAll i: m_i|k ==> congruent (x,y,m) ,==> congruent((x mod k),y,m)
643
;; (8) ForAll i,j with j<>j: gcd(m_i,m_j) = 1 ^
644
;; congruent(v1,l1,m) ^ congruent (v2,l2,m) ^
645
;; Product(m_i)|(v1-v2) ==> congruent-lists(l1,l2,m)
646
;; (9) ForAll i,j with j<>j: gcd(m_i,m_j) = 1 ^
647
;; congruent(v1,l1,m) ^ congruent (v2,l2,m) ^
648
;; congruent-lists(l1,l2,m) ==> Product(m_i)|(v1-v2)
649
;; (10) ForAll i,j with j<>j: gcd(m_i,m_j) = 1 ^
650
;; congruent(v1,l1,m) ^ congruent (v2,l2,m) ==>
651
;; (congruent-lists(l1,l2,m) <==> Product(m_i)|(v1-v2))
652
;; (11) (0<=v1<p) ^ (0<=v2<p) ^ p|(v1-v2) ==> v1 = v2
653
;; (12) ForAll i,j with j<>j: gcd(m_i,m_j) = 1 ^
654
;; (0<=v1<p) ^ (0<=v2<p) ^
655
;; congruent(v1,l,m) ^ congruent(v2,l,m) ==> v1 = v2
658
;; The proof scheme is the following (where (6) refers to the main statement derived
674
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
677
(union-theories (current-theory 'ground-zero)
680
(:definition natp-all)
682
(:executable-counterpart prod)
683
(:type-prescription prod)
685
(:executable-counterpart posp)
686
(:type-prescription posp)
687
(:definition posp-all)
688
(:executable-counterpart posp-all)
689
(:type-prescription posp-all)
690
(:induction posp-all)
691
(:definition divided-by-all)
692
(:executable-counterpart divided-by-all)
693
(:type-prescription divided-by-all)
694
(:induction divided-by-all) )))
698
(defun congruent-mod (x y m)
699
(= (mod x m) (mod y m)))
703
(defun congruent-all-mod (x a m)
704
(declare (xargs :measure (len m)))
707
(and (congruent-mod x (car a) (car m))
708
(congruent-all-mod x (cdr a) (cdr m)))))
711
(defun congruent-all-mod-list (l1 l2 m)
712
(declare (xargs :measure (len m)))
716
(congruent-mod (car l1) (car l2) (car m))
717
(congruent-all-mod-list (cdr l1) (cdr l2) (cdr m)))))
720
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
722
;; We load some books, importing only some key lemmas about
723
;; the combination of mod and arithmetic functions.
724
;; We prove some additional basic lemmas.
726
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
728
(include-book "../../../../../arithmetic/top-with-meta")
730
(include-book "Minimal-Mod-Lemmas")
732
(in-theory (disable mod-x-y-=-x-exp))
734
(in-theory (disable mod))
744
(equal (mod (mod x (* i z)) z)
746
:hints (("Goal" :use (:instance rewrite-mod-mod-exp (y (* i z))))))
748
(defthm r-mod-mod-cancel
754
(equal (mod (mod x z) z) (mod x z))))
758
(defthm product-divided-by-all
761
(divided-by-all (prod m) m))
762
:hints (("Subgoal *1/1.2''"
765
:in-theory (disable commutativity-of-*)
778
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
780
;; Here we prove that, if two values v1 and v2 differ by the product
781
;; of a list of coprimes m, then lists congruent to them are congruent w.r.t. m.
782
;; This is stated by if-values-differ-by-product-of-m-then-cong-lists-are-congruent-wrt-m.
784
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
786
(defthm if-k-is-divided-by-all-then-x-and-x-mod-k-have-same-congruence
789
(equal (len y) (len m))
793
(divided-by-all k m))
795
(congruent-all-mod (mod x k) y m)
796
(congruent-all-mod x y m))))
799
(defthm modulo-prod-has-same-congruence
802
(equal (len y) (len m))
806
(congruent-all-mod (mod x (prod m)) y m)
807
(congruent-all-mod x y m))))
812
(defthm express-mod-changing-arg-sign
817
(not (integerp (/ x y))))
818
(equal (mod (- x) y) (- y (mod x y))))
819
:hints (("Goal" :in-theory (enable mod)))
822
(defthm mod-0-allows-changing-arg-sign
831
(equal (mod (- x) y) 0)))
843
(not (integerp (/ y z)))
845
(equal (mod (- x y) z)
846
(mod (- (mod x z) (mod y z)) z)))
849
(:instance mod-+-exp (y (- y)))
850
(:instance express-mod-changing-arg-sign (x y) (y z))
851
(:instance cancel-mod-+-exp
854
(y (- (mod x z) (mod y z))))
855
(:instance integerp-mod-exp (i x) (j z))
856
(:instance integerp-mod-exp (i y) (j z)) )
858
(:rewrite inverse-of-*)
859
(:rewrite associativity-of-+)
860
(:rewrite commutativity-of-+))))
871
(equal (mod (- x y) z)
872
(mod (- (mod x z) (mod y z)) z)))
873
:hints (("Goal" :in-theory (enable mod)))
878
(and (force (integerp x))
881
(force (not (equal z 0))))
882
(equal (mod (- x y) z)
883
(mod (- (mod x z) (mod y z)) z)))
884
:hints (("Goal" :use (hack-24 hack-25))))
888
(defthm cong-all-mod-implies-cong-all-mod-list
891
(congruent-all-mod v1 l1 m)
892
(congruent-all-mod v1 l2 m))
893
(congruent-all-mod-list l1 l2 m)))
902
:hints (("Goal" :in-theory (enable rel-prime-moduli)))
903
:rule-classes :forward-chaining)
909
(integerp (/ (- a) b)))
919
(integerp (/ (- v1 v2) (prod m))))
921
(integerp (/ (- v2 v1) (prod m)))
922
(equal v2 (+ v1 (* (/ (- v2 v1) (prod m)) (prod m))))))
923
:hints (("Goal" :use (:instance hack-27 (a (- v1 v2)) (b (prod m)))))
927
(defthm if-values-differ-by-product-of-m-then-cong-lists-are-congruent-wrt-m
935
(equal (len l1) (len m))
936
(equal (len l2) (len m))
937
(congruent-all-mod v1 l1 m)
938
(congruent-all-mod v2 l2 m)
939
(integerp (/ (- v1 v2) (prod m))))
940
(congruent-all-mod-list l1 l2 m))
942
:in-theory '((:definition posp)
943
(:rewrite unicity-of-1))
947
cong-all-mod-implies-cong-all-mod-list
948
(:instance mod-x+i*y-y-exp (i (/ (- v2 v1) (prod m))) (x v1) (y (prod m)))
949
(:instance r-mod-mod (x v1) (i 1) (z (prod m)))
950
(:instance modulo-prod-has-same-congruence (x v1) (y l2))
951
(:instance modulo-prod-has-same-congruence (x v2) (y l2))))))
956
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
958
;; Now we prove that, given two values v1 and v2, if lists congruent to
959
;; them are congruent w.r.t. m, then v1 and v2 differ by the product
960
;; of the elements of m.
963
;; if-values-are-congruent-wrt-m-via-cong-lists-then-they-differ-by-a-multiple-of-prod-m.
965
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
969
(defthm same-congruence-over-conglist
971
(congruent-all-mod-list l1 l2 m)
973
(congruent-all-mod v l1 m)
974
(congruent-all-mod v l2 m)))
977
(defun cong-sg-val (v1 v2 m)
982
(congruent-mod v1 v2 (car m))
983
(cong-sg-val v1 v2 (cdr m)))))
986
(defthm same-cong-lists-means-same-mods
989
(equal (len l) (len m))
990
(congruent-all-mod v1 l m)
991
(congruent-all-mod v2 l m))
992
(cong-sg-val v1 v2 m)))
995
(implies (posp carm) (equal (mod 0 carm) 0))
999
(defthm same-cong-vals-implies-diff-has-cong-to-zero
1006
(cong-sg-val v1 v2 m)
1007
(cong-sg-val (- v1 v2) 0 m)))
1009
:in-theory (disable mod-=-0-exp
1017
("Subgoal *1/1" :use (
1018
(:instance mod-of-0 (carm (car m)))
1019
(:instance mod-- (x v1) (y v2) (z (car m)))))))
1022
(defthm cong-0-is-divided-by-all
1027
(equal (cong-sg-val v 0 m) (divided-by-all v m)))
1028
:hints (("Goal" :induct (len m))
1029
("Subgoal *1/1" :use ((:instance mod-of-0 (carm (car m)))
1030
(:instance mod-=-0-exp (x v) (y (car m))))
1031
:in-theory (disable MOD-=-0-EXP)))
1037
(in-theory (enable if-every-coprime-divides-v-then-product-of-coprimes-divides-v))
1042
(defthm if-values-are-congruent-wrt-m-via-cong-lists-then-they-differ-by-a-multiple-of-prod-m
1045
(rel-prime-moduli m)
1050
(equal (len l1) (len m))
1051
(equal (len l2) (len m))
1052
(congruent-all-mod v1 l1 m)
1053
(congruent-all-mod v2 l2 m)
1054
(congruent-all-mod-list l1 l2 m))
1055
(integerp (/ (- v1 v2) (prod m))))
1056
:hints (("Goal" :use ( hack-26
1057
(:instance cong-0-is-divided-by-all (v (- v1 v2)))
1058
(:instance same-congruence-over-conglist (v v2))
1059
(:instance same-cong-vals-implies-diff-has-cong-to-zero (v1 v1) (v2 v2))
1060
(:instance if-every-coprime-divides-v-then-product-of-coprimes-divides-v
1066
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1068
;; We prove that congruence w.r.t. m is equivalent to checking that the difference
1069
;; of two values is a multiple of the product of the elements of l.
1070
;; This follows easily from the ``if'' and ``only if'' lemmas proved above.
1072
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1075
(defthm congruence-of-cong-lists-is-equivalent-to-dividabilty-by-prod-m
1078
(rel-prime-moduli m)
1083
(equal (len l1) (len m))
1084
(equal (len l2) (len m))
1085
(congruent-all-mod v1 l1 m)
1086
(congruent-all-mod v2 l2 m))
1088
(congruent-all-mod-list l1 l2 m)
1089
(integerp (/ (- v1 v2) (prod m)))))
1091
:use (if-values-differ-by-product-of-m-then-cong-lists-are-congruent-wrt-m
1092
if-values-are-congruent-wrt-m-via-cong-lists-then-they-differ-by-a-multiple-of-prod-m))))
1097
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1099
;; Here we prove a basic lemma: if two numbers differ by a multiple of a fixed number prod,
1100
;; and they both are in the range [0,prod), then they are equal.
1102
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1110
(implies (equal resdiv 0) (equal (* resdiv prod) 0))
1111
(implies (< resdiv 0) (< (* resdiv prod) 0))
1112
(implies (> resdiv 0) (>= (* resdiv prod) prod)))))
1121
(integerp (/ v prod)))
1123
:hints (("Goal''" :use (:instance hack-29 (resdiv (/ v prod)))))
1135
(integerp (/ (abs (- v1 v2)) prod)))
1137
:hints (("Goal" :use (:instance hack-30 (v (abs (- v1 v2))))))
1142
(iff (integerp (/ (abs a) b)) (integerp (/ a b)))
1145
(defthm equality-in-range
1153
(integerp (/ (- v1 v2) prod)))
1155
:hints (("Goal" :use (hack-31
1156
(:instance hack-32 (a (- v1 v2)) (b prod)))))
1163
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1165
;; Required statement
1167
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1171
(defthm unique-inversion
1174
(rel-prime-moduli m)
1180
(equal (len l) (len m))
1181
(congruent-all-mod v1 l m)
1182
(congruent-all-mod v2 l m))
1184
:hints (("Goal" :use
1185
( (:instance congruence-of-cong-lists-is-equivalent-to-dividabilty-by-prod-m (l1 l) (l2 l))
1186
(:instance equality-in-range (prod (prod m))))))