/usr/share/acl2-6.3/books/quadratic-reciprocity/mersenne.lisp is in acl2-books-source 6.3-5.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 | (in-package "ACL2")
;; This book illustrates a simple application of the theory of quadratic
;; residues to the Mersenne prime problem. We show that certain Mersenne
;; numbers may be factored by applying a theorem of Euler, which combines
;; two results: (1) Euler's criterion for quadratic residues and (2) the
;; second supplement to the law of quadratic reciprocity, which computes
;; the quadratic character of 2 modulo an odd prime p.
;; The two theorems and the relevant definitions are contained in the
;; book "gauss":
(include-book "gauss")
(comp t)
; We skip some forms by default, because they take a long time to run.
(defmacro maybe-skip (x)
; Redefine to be x if you want to execute forms inside (maybe-skip ...).
(declare (ignore x))
'(value-triple nil))
;; For a prime p, the Mersenne number Mp is defined to be 2^p-1:
(defun m (p) (1- (expt 2 p)))
;; We would like to determine the primality of Mp. For small values of p,
;; this can be done simply by executing the function primep:
(defthm mersenne-19
(primep (m 19)))
;;[Time: .4 seconds]
(maybe-skip
(defthm mersenne-31
(primep (m 31)))
)
;;[Time: 65 minutes]
;; The timing of mersenne-31 suggests that the computation of mersenne-61
;; is intractable:
;;(defthm mersenne-61
;; (primep (m 61)))
;;[Time: a billion hours?]
;; Naturally, we can handle larger composites than primes:
(defthm mersenne-23
(not (primep (m 23))))
;;[Time: .02 seconds]
(maybe-skip
(defthm mersenne-67
(not (primep (m 67))))
)
;;[Time: 288 seconds]
(maybe-skip
(defthm mersenne-999671
(not (primep (m 999671))))
)
;;[Time: 165 minutes]
;;(defthm mersenne-19876271
;; (not (primep (m 19876271))))
;;[Error: Attempt to create an integer that is too large to represent.]
;; There is an obvious optimization of this procedure, based on
;; the observation that if n has a proper divisor, then it has one
;; that is at most sqrt(n). Thus, we define an alternative to
;; the function least-divisor that stops at sqrt(n), and
;; establish a rewrite rule:
(defun least-divisor-2 (k n)
(declare (xargs :measure (nfix (- n k))))
(if (and (integerp n)
(integerp k)
(< 1 k)
(<= k n))
(if (> (* k k) n)
n
(if (divides k n)
k
(least-divisor-2 (1+ k) n)))
nil))
(comp t)
(defthm least-divisor-rewrite-lemma-1
(implies (and (integerp n)
(integerp k)
(< 1 k)
(<= k n)
(<= (* (least-divisor k n) (least-divisor k n)) n))
(equal (least-divisor k n)
(least-divisor-2 k n)))
:rule-classes ()
:hints (("Subgoal *1/7" :use (least-divisor-divides))
("Subgoal *1/1" :use (least-divisor-divides))))
(defthm least-divisor-rewrite-lemma-2
(implies (and (integerp n)
(> n 1)
(not (= n (least-divisor 2 n))))
(<= (* (least-divisor 2 n) (least-divisor 2 n)) n))
:rule-classes ()
:hints (("Goal" :in-theory (enable divides)
:use ((:instance least-divisor-divides (k 2))
(:instance least-divisor-is-least (k 2) (d (/ n (least-divisor 2 n))))
(:instance *-weakly-monotonic (x (least-divisor 2 n)) (y 1) (y+ (/ n (least-divisor 2 n))))
(:instance *-weakly-monotonic (x (least-divisor 2 n)) (y+ 1) (y (/ n (least-divisor 2 n))))))))
(defthm least-divisor-rewrite-lemma-3
(implies (and (integerp n)
(integerp k)
(< 1 k)
(<= k n)
(= n (least-divisor k n)))
(= n (least-divisor-2 k n)))
:rule-classes ()
:hints (("Goal" :use (least-divisor-divides
(:instance least-divisor-is-least (d (least-divisor-2 2 n)))))))
(defthm least-divisor-rewrite
(equal (least-divisor 2 n)
(least-divisor-2 2 n))
:hints (("Goal" :use (least-divisor-rewrite-lemma-2
(:instance least-divisor-rewrite-lemma-3 (k 2))
(:instance least-divisor-rewrite-lemma-1 (k 2))))))
;; In order to arrange that the more efficient variant is executed, we must
;; disable the executable counterparts of primep and least-proper-divisor
;; and enable the logical function primep. This allows us to establish
;; primality somewhat more efficiently:
(in-theory (enable primep))
(in-theory (disable (primep) (least-divisor)))
(defthm mersenne-31-revisited
(primep (m 31)))
;;[Time: .05 seconds]
(maybe-skip
(defthm mersenne-61
(primep (m 61)))
)
;;[Time: 54 minutes]
;; However, the above optimization does not help at all in the composite case.
;; In the special case where mod(p,4) = 3 and 2*p+1 is prime, the following
;; theorem may be used. This theorem is attributed to Euler in Hardy and
;; Wright, where it appears as Theorem 103. It is an immediate comsequence
;; of Euler's Criterion and the Second Supplement.
(defthm theorem-103
(implies (and (primep p)
(= (mod p 4) 3)
(primep (1+ (* 2 p))))
(divides (1+ (* 2 p)) (m p)))
:rule-classes ()
:hints (("Goal" :use ((:instance second-supplement (p (1+ (* 2 p))))
(:instance euler-criterion (m 2) (p (1+ (* 2 p))))
(:instance mod-sum (a 1) (b (* 2 p)) (n 8))
(:instance mod-prod (k 2) (m p) (n 4))
(:instance divides-leq (x (1+ (* 2 p))) (y 2))
(:instance divides-mod-equal (a (expt 2 p)) (b 1) (n (1+ (* 2 p))))))))
;; With the exception of p = 3 (in which case Mp = 2*p+1), Mp is composite
;; for any p satisfying the hypothesis of theorem-103:
(defthm expt-2-p-bnd
(implies (and (integerp p)
(> p 3))
(> (expt 2 p) (* 2 (1+ p))))
:rule-classes ())
(defthm theorem-103-corollary
(implies (and (primep p)
(= (mod p 4) 3)
(> p 3)
(primep (1+ (* 2 p))))
(not (primep (m p))))
:hints (("Goal" :use (theorem-103
expt-2-p-bnd
(:instance primep-no-divisor (p (1- (expt 2 p))) (d (1+ (* 2 p))))))))
;; In order to arrange for theorem-103-corollary to be used as a
;; rewrite rule, we must disable the logical expansion of both
;; primep and m. We must also re-enable the executable counterpart
;; of primep to allow the computation of primep(p) and primep(2*p+1):
(in-theory (disable primep m (m)))
(in-theory (enable (primep)))
(defthm mersenne-23-revisited
(not (primep (m 23))))
;;[Time: .01 seconds]
(defthm mersenne-999671-revisited
(not (primep (m 999671))))
;;[Time: .01 seconds]
(maybe-skip
(defthm mersenne-19876271
(not (primep (m 19876271))))
)
;;[Time: 47 seconds]
|