summaryrefslogtreecommitdiff
path: root/books/workshops/2006/cowles-gamboa-euclid/Euclid/prime-fac.lisp
diff options
context:
space:
mode:
Diffstat (limited to 'books/workshops/2006/cowles-gamboa-euclid/Euclid/prime-fac.lisp')
-rw-r--r--books/workshops/2006/cowles-gamboa-euclid/Euclid/prime-fac.lisp595
1 files changed, 595 insertions, 0 deletions
diff --git a/books/workshops/2006/cowles-gamboa-euclid/Euclid/prime-fac.lisp b/books/workshops/2006/cowles-gamboa-euclid/Euclid/prime-fac.lisp
new file mode 100644
index 0000000..d4b56d2
--- /dev/null
+++ b/books/workshops/2006/cowles-gamboa-euclid/Euclid/prime-fac.lisp
@@ -0,0 +1,595 @@
+; Unique Prime Factorization Theorem for Positive Integers.
+; Copyright (C) 2004 John R. Cowles, University of Wyoming
+
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License as
+; published by the Free Software Foundation; either version 2 of
+; the License, or (at your option) any later version.
+
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+; GNU General Public License for more details.
+
+; You should have received a copy of the GNU General Public
+; License along with this program; if not, write to the Free
+; Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+; USA.
+
+; Written by:
+; John Cowles
+; Department of Computer Science
+; University of Wyoming
+; Laramie, WY 82071 U.S.A.
+
+;; The outline of Bob and J's original proof, as developed in THM,
+;; is followed. Their proof is described in the book:
+
+;; R.S. Boyer and J S. Moore, A Computational Logic, Academic Press,
+;; 1979.
+
+;; For the formal statement of the theorem, search for
+;; PRIME-FACTORIZATION-EXISTENCE and
+;; PRIME-FACTORIZATION-UNIQUENESS.
+
+;; Modified Jan. 05
+;; Modified July 05
+;; Modified Nov. 05 (for ACL2 Version 2.9.3).
+;; Modified July 06 (for ACL2 Version 3.0).
+
+#|
+To certify this book, first, create a world with the following package:
+
+(defpkg "POS"
+ (set-difference-eq
+ (union-eq *acl2-exports*
+ *common-lisp-symbols-from-main-lisp-package*)
+; Subtracted 12/4/2012 by Matt K. for addition to *acl2-exports*:
+ '(nat-listp acl2-number-listp)))
+
+(certify-book "prime-fac"
+ 1
+ )
+|#
+(in-package "POS")
+
+(local
+ (include-book "arithmetic/top-with-meta" :dir :system
+; Matt K.: Commenting out use of :uncertified-okp after v4-3 in order to
+; support provisional certification:
+; :uncertified-okp nil
+ :defaxioms-okp nil
+ :skip-proofs-okp nil))
+
+(include-book "arithmetic/mod-gcd" :dir :system
+; Matt K.: Commenting out use of :uncertified-okp after v4-3 in order to
+; support provisional certification:
+; :uncertified-okp nil
+ :defaxioms-okp nil
+ :skip-proofs-okp nil)
+
+;; The definition of nonneg-int-gcd often interacts with the rewrite rule,
+;; commutativity-of-nonneg-int-gcd, to cause the rewriter to loop and stack
+;; overflow.
+(in-theory (disable ACL2::commutativity-of-nonneg-int-gcd))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Here are the definitions of nonnegative-integer-quotient,
+;; nonneg-int-mod, and
+;; nonneg-int-gcd.
+
+;; (defun
+;; nonnegative-integer-quotient (i j)
+;; (declare (xargs :guard (and (integerp i)
+;; (not (< i 0))
+;; (integerp j)
+;; (< 0 j))
+;; :mode :program))
+;; (if (or (= (nfix j) 0)
+;; (< (ifix i) j))
+;; 0
+;; (+ 1 (nonnegative-integer-quotient (- i j) j))))
+
+;; (verify-termination
+;; (nonnegative-integer-quotient (declare (xargs :mode :logic))))
+
+;; (defun
+;; nonneg-int-mod ( n d )
+;; (declare (xargs :guard (and (integerp n)
+;; (>= n 0)
+;; (integerp d)
+;; (< 0 d))))
+;; (if (zp d)
+;; (nfix n)
+;; (if (< (nfix n) d)
+;; (nfix n)
+;; (nonneg-int-mod (- n d) d))))
+
+;; (defun
+;; nonneg-int-gcd ( x y )
+;; (declare (xargs :guard (and (integerp x)
+;; (>= x 0)
+;; (integerp y)
+;; (>= y 0))))
+;; (if (zp y)
+;; (nfix x)
+;; (nonneg-int-gcd y (nonneg-int-mod x y))))
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun
+ dividesp (x y)
+ "Return T iff x|y iff there is an integer z
+ such that (equal (* x z) y)."
+ (declare (xargs :guard (and (integerp x)
+ (>= x 0)
+ (integerp y)
+ (>= y 0))))
+ (if (zp x)
+ (= y 0)
+ (= (ACL2::nonneg-int-mod y x) 0)))
+
+(defun
+ prime1p (x y)
+ "Return T iff x has no divisors z with
+ 1 < z <= y."
+ (declare (xargs :guard (and (integerp x)
+ (>= x 0)
+ (integerp y)
+ (>= y 0))))
+ (if (or (zp y)(= y 1))
+ t
+ (and (not (dividesp y x))
+ (prime1p x (- y 1)))))
+
+#| A positive integer is a prime iff
+ it has exactly two positive integer
+ divisors, namely 1 and the integer
+ itself. The integer 1 is NOT a prime
+ under this definition because 1 only
+ has one positive integer divisor.
+
+ The definition of primep given below
+ is equivalent to the one just stated.
+|#
+
+(defun
+ primep (x)
+ (declare (xargs :guard t))
+ (and (integerp x)
+ (> x 1)
+ (prime1p x (- x 1))))
+
+(defthm
+ not-prime1p-lemma
+ (implies (and (integerp y)
+
+; Matt K. mod 5/2016 (type-set bit for {1}): Originally the following
+; hypothesis was instead (dividesp z x), and was last. After our type-set
+; changes, where this lemma was applied to prove divisors-of-primep, the
+; free-variable match failed for the old version of this lemma. The problem
+; was that D was on the type-alist with type *ts-integer>1*; neither (< 1 D)
+; nor (< D 2) was on the type-alist. Since dividesp is enabled, here we place
+; what amounts to the expanded form of (dividesp z x).
+
+ (equal (acl2::nonneg-int-mod x z) 0)
+ (< 1 z)
+ (<= z y))
+ (not (prime1p x y))))
+
+(defun
+ greatest-factor (x y)
+ "Return the largest z such that z|x and
+ 1 < z <= y. If no such z exists return x."
+ (declare (xargs :guard (and (integerp x)
+ (>= x 0)
+ (integerp y)
+ (>= y 0))))
+ (cond ((or (zp y)(= y 1))
+ x)
+ ((dividesp y x) y)
+ (t (greatest-factor x (- y 1)))))
+
+(defthm
+ x>1-forward
+ (implies (and (not (equal x 1))
+ (not (zp x)))
+ (> x 1))
+ :rule-classes :forward-chaining)
+
+(defthm
+ greatest-factor=1
+ (equal (equal (greatest-factor x y) 1)
+ (equal x 1)))
+
+(defthm
+ natp-greatest-factor
+ (equal (and (integerp (greatest-factor x y))
+ (>= (greatest-factor x y) 0))
+ (or (and (integerp y)
+ (> y 1))
+ (and (integerp x)
+ (>= x 0))))
+ :rule-classes ((:type-prescription
+ :corollary
+ (implies (and (integerp x)
+ (>= x 0))
+ (and (integerp (greatest-factor x y))
+ (>= (greatest-factor x y) 0))))
+ (:type-prescription
+ :corollary
+ (implies (and (integerp y)
+ (> y 1))
+ (and (integerp (greatest-factor x y))
+ (>= (greatest-factor x y) 0))))
+ (:type-prescription
+ :corollary
+ (implies (and (not (zp y))
+ (not (equal y 1)))
+ (and (integerp (greatest-factor x y))
+ (>= (greatest-factor x y) 0))))))
+
+(defthm
+ dividesp-greatest-factor
+ (implies (and (integerp x)
+ (>= x 0))
+ (dividesp (greatest-factor x y) x))
+ :rule-classes ((:rewrite
+ :corollary
+ (implies (and (integerp x)
+ (>= x 0))
+ (equal
+ (ACL2::nonneg-int-mod x (greatest-factor x y)) 0)))))
+
+(defthm
+ <-greatest-factor
+ (implies (and (> x y)
+ (not (prime1p x y)))
+ (< (greatest-factor x y) x))
+ :rule-classes (:rewrite :linear))
+
+(defthm
+ greatest-factor->-1
+ (implies (> i 1)
+ (> (greatest-factor i j) 1))
+ :rule-classes :linear)
+
+(defthm
+ <-nonnegative-integer-quotient
+ (implies (and (> i 0)
+ (> j 1))
+ (< (nonnegative-integer-quotient i j) i))
+ :rule-classes :linear)
+
+(defthm
+ posp-nonnegative-integer-quotient
+ (implies (and (integerp i)
+ (integerp j)
+ (>= i j)
+ (> j 0))
+ (> (nonnegative-integer-quotient i j) 0))
+ :rule-classes :type-prescription)
+
+(defthm
+ *-nonnegative-integer-quotient
+ (implies (and (integerp y)
+ (>= y 0)
+ (dividesp x y))
+ (equal (* x (nonnegative-integer-quotient y x))
+ y)))
+
+(defun
+ prime-factors (x)
+ "Return a list, lst, of primes so that
+ x = product of the members of lst."
+ (declare (xargs :guard (and (integerp x)
+ (>= x 0))))
+ (cond ((or (zp x)(= x 1)) nil)
+ ((primep x)(list x))
+ (t (append (prime-factors (greatest-factor x (- x 1)))
+ (prime-factors (nonnegative-integer-quotient
+ x
+ (greatest-factor x (- x 1))))))))
+
+(defun
+ prime-listp (lst)
+ (declare (xargs :guard t))
+ (if (consp lst)
+ (and (primep (car lst))
+ (prime-listp (cdr lst)))
+ t))
+
+(defthm
+ prime-listp-append
+ (implies (and (prime-listp lst1)
+ (prime-listp lst2))
+ (prime-listp (append lst1 lst2))))
+
+(defun
+ acl2-number-listp (lst)
+ (declare (xargs :guard t))
+ (if (consp lst)
+ (and (acl2-numberp (car lst))
+ (acl2-number-listp (cdr lst)))
+ t))
+
+(defun
+ product-lst (lst)
+ (declare (xargs :guard (acl2-number-listp lst)))
+ (if (consp lst)
+ (* (car lst)(product-lst (cdr lst)))
+ 1))
+
+(defthm
+ product-lst-append
+ (equal (product-lst (append lst1 lst2))
+ (* (product-lst lst1)
+ (product-lst lst2))))
+
+(defthm
+ prime-listp-prime-factors
+ (prime-listp (prime-factors x)))
+
+(defthm
+ product-lst-prime-factors
+ (implies (and (integerp x)
+ (> x 0))
+ (equal (product-lst (prime-factors x)) x)))
+
+(defthm
+ PRIME-FACTORIZATION-EXISTENCE
+ (and (prime-listp (prime-factors x))
+ (implies (and (integerp x)
+ (> x 0))
+ (equal (product-lst (prime-factors x)) x)))
+ :rule-classes nil)
+
+(defun
+ nat-listp (lst)
+ (declare (xargs :guard t))
+ (if (consp lst)
+ (and (integerp (car lst))
+ (>= (car lst) 0)
+ (nat-listp (cdr lst)))
+ t))
+
+(defthm
+ natp-product-lst
+ (implies (nat-listp lst)
+ (and (integerp (product-lst lst))
+ (>= (product-lst lst) 0)))
+ :rule-classes :type-prescription)
+
+(defthm
+ prime-listp=>nat-listp
+ (implies (prime-listp lst)
+ (nat-listp lst))
+ :rule-classes :forward-chaining)
+
+(defthm
+ nonneg-int-mod-*-0-rt
+ (implies (and (integerp x)
+ (integerp y)
+ (>= y 0)
+ (equal (ACL2::nonneg-int-mod y c) 0))
+ (equal (ACL2::nonneg-int-mod (* x y) c) 0)))
+
+(defthm
+ nonneg-int-mod-product-lst
+ (implies (and (nat-listp lst)
+ (member-equal c lst))
+ (equal (ACL2::nonneg-int-mod (product-lst lst) c) 0)))
+
+(defthm
+ nonnegative-integer-quotient-*
+ (implies (and (integerp x)
+ (> x 0)
+ (integerp y)
+ (>= y 0))
+ (equal (nonnegative-integer-quotient (* x y) x) y))
+ :hints (("goal"
+ :in-theory (disable *-nonnegative-integer-quotient)
+ :use (:instance
+ *-nonnegative-integer-quotient
+ (y (* x y))))))
+
+(defthm
+ *-nonnegative-integer-quotient-*
+ (implies (and (integerp w)
+ (integerp c)
+ (>= c 0)
+ (dividesp a w))
+ (equal (* c (nonnegative-integer-quotient w a))
+ (nonnegative-integer-quotient (* c w) a))))
+
+(defthm
+ divisors-of-primep
+ (implies (and (primep p)
+ (dividesp d p))
+ (or (equal d p)
+ (equal d 1)))
+ :rule-classes nil
+ :hints (("Goal"
+ :use ((:instance
+ ACL2::divisor-<=
+ (ACL2::n p)
+ (ACL2::d d))))))
+
+(defthm
+ nonneg-int-gcd=>nonneg-int-mod
+ (implies (equal (ACL2::nonneg-int-gcd x y) y)
+ (equal (ACL2::nonneg-int-mod x y) 0)))
+
+(defthm
+ primep=>nonneg-int-gcd=1
+ (implies (and (not (dividesp p x))
+ (primep p))
+ (equal (ACL2::nonneg-int-gcd x p) 1))
+ :hints (("Goal"
+ :use (:instance
+ divisors-of-primep
+ (d (ACL2::nonneg-int-gcd x p))))))
+
+(defthm
+ Prime-divisor-of-product-divides-factor
+ (implies (and (primep p)
+ (dividesp p (* x y))
+ (not (dividesp p y)))
+ (dividesp p x))
+ :rule-classes ((:rewrite
+ :corollary
+ (implies (and (primep p)
+ (equal (ACL2::nonneg-int-mod (* x y) p) 0)
+ (not (dividesp p y)))
+ (equal (ACL2::nonneg-int-mod x p) 0))))
+ :hints (("Goal"
+ :use (:instance
+ ACL2::Divisor-of-product-divides-factor
+ (ACL2::z p)
+ (ACL2::y y)
+ (ACL2::x x)))))
+
+(defthm
+ divides-product-lst=>member-equal
+ (implies (and (primep p)
+ (prime-listp lst)
+ (not (member-equal p lst)))
+ (not (equal (ACL2::nonneg-int-mod (product-lst lst) p) 0)))
+ :hints (("Subgoal *1/5"
+ :use (:instance
+ divisors-of-primep
+ (d p)
+ (p (car lst))))))
+
+(defthm
+ *-prime-product-lst=>member-equal
+ (implies (and (equal (* p (product-lst lst1))
+ (product-lst lst2))
+ (nat-listp lst1)
+ (primep p)
+ (prime-listp lst2))
+ (member-equal p lst2))
+ :hints (("Goal"
+ :in-theory (disable divides-product-lst=>member-equal)
+ :use (:instance
+ divides-product-lst=>member-equal
+ (lst lst2)))))
+
+(defun
+ delete-one (x lst)
+ "Return the result of deleting
+ one occurrence of x from the list lst."
+ (declare (xargs :guard t))
+ (if (consp lst)
+ (if (equal x (car lst))
+ (cdr lst)
+ (cons (car lst)(delete-one x (cdr lst))))
+ lst))
+
+(defthm
+ prime-listp-delete-one
+ (implies (prime-listp lst)
+ (prime-listp (delete-one x lst))))
+
+(defthm
+ product-lst-delete-one
+ (implies (and (nat-listp lst)
+ (member-equal c lst)
+ (> c 0))
+ (equal (product-lst (delete-one c lst))
+ (nonnegative-integer-quotient (product-lst lst) c)))
+ :hints (("subgoal *1/4"
+ :in-theory (disable *-nonnegative-integer-quotient-*)
+ :use (:instance
+ *-nonnegative-integer-quotient-*
+ (c (car lst))
+ (w (product-lst (cdr lst)))
+ (a c)))))
+
+(defun
+ bag-equal (lst1 lst2)
+ "Return T iff lst1 and lst2 have the same
+ members with the same multiplicity (but
+ maybe in a different order)."
+ (declare (xargs :guard (true-listp lst2)))
+ (if (consp lst1)
+ (and (member-equal (car lst1) lst2)
+ (bag-equal (cdr lst1)
+ (delete-one (car lst1) lst2)))
+ (atom lst2)))
+
+(defthm
+ product-lst-of-prime-listp>1
+ (implies (and (prime-listp lst)
+ (consp lst))
+ (> (product-lst lst) 1))
+ :rule-classes :linear)
+
+(defthm
+ PRIME-FACTORIZATION-UNIQUENESS
+ (implies (and (prime-listp lst1)
+ (prime-listp lst2)
+ (equal (product-lst lst1)
+ (product-lst lst2)))
+ (bag-equal lst1 lst2)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Show that bag-equal has the expected properties:
+
+;; Lisp objects that are bag-equal have the same length.
+
+;; Lisp objects that are bag-equal have the same members.
+
+;; Elements in Lisp objects that are bag-equal occur
+;; in each object with the same multiplicity.
+
+(defthm
+ len-delete-one
+ (implies (member-equal x lst)
+ (equal (+ 1 (len (delete-one x lst)))
+ (len lst))))
+
+(defthm
+ bag-equal->equal-len
+ (implies (bag-equal lst1 lst2)
+ (equal (len lst1)
+ (len lst2)))
+ :rule-classes nil)
+
+(defthm
+ member-equal-delete-one
+ (implies (not (equal x y))
+ (iff (member-equal x (delete-one y lst))
+ (member-equal x lst))))
+
+(defthm
+ bag-equal->iff-member-equal
+ (implies (bag-equal lst1 lst2)
+ (iff (member-equal x lst1)
+ (member-equal x lst2))))
+
+(defun
+ multiplicity (x lst)
+ (if (consp lst)
+ (if (equal x (car lst))
+ (+ 1 (multiplicity x (cdr lst)))
+ (multiplicity x (cdr lst)))
+ 0))
+
+(defthm
+ multiplicity-delete-one-1
+ (implies (member-equal x lst)
+ (equal (+ 1 (multiplicity x (delete-one x lst)))
+ (multiplicity x lst))))
+
+(defthm
+ multiplicity-delete-one-2
+ (implies (not (equal x y))
+ (equal (multiplicity x (delete-one y lst))
+ (multiplicity x lst))))
+
+(defthm
+ bag-equal->equal-multiplicity
+ (implies (bag-equal lst1 lst2)
+ (equal (multiplicity x lst1)
+ (multiplicity x lst2)))
+ :rule-classes nil)