SICP exercise 1.28: false negatives in the Miller-Rabin test - algorithm

Exercise 1.28. One variant of the Fermat test that cannot be fooled is called the Miller-Rabin test (Miller 1976; Rabin 1980). This
starts from an alternate form of Fermat's Little Theorem, which states
that if n is a prime number and a is any positive integer less than n,
then a raised to the (n - 1)st power is congruent to 1 modulo n. To
test the primality of a number n by the Miller-Rabin test, we pick a
random number a < n and raise a to the (n - 1)st power modulo n using
the expmod procedure. However, whenever we perform the squaring step
in expmod, we check to see if we have discovered a ''nontrivial square
root of 1 modulo n,'' that is, a number not equal to 1 or n - 1 whose
square is equal to 1 modulo n. It is possible to prove that if such a
nontrivial square root of 1 exists, then n is not prime. It is also
possible to prove that if n is an odd number that is not prime, then,
for at least half the numbers a < n, computing a^(n-1) in this way will
reveal a nontrivial square root of 1 modulo n. (This is why the
Miller-Rabin test cannot be fooled.) Modify the expmod procedure to
signal if it discovers a nontrivial square root of 1, and use this to
implement the Miller-Rabin test with a procedure analogous to
fermat-test. Check your procedure by testing various known primes and
non-primes. Hint: One convenient way to make expmod signal is to have
it return 0.
(define (fast-prime? n)
(define (fast-prime-iter n counter)
(cond ((= counter 1) #t) ; There is no need to check 1
((miller-rabin-test n counter)
(fast-prime-iter n (- counter 1)))
(else
(newline)
(display counter)
#f)))
(fast-prime-iter n (- n 2)))
(define (miller-rabin-test n a)
(define (expmod base exp m)
(cond ((= exp 0) 1)
((even? exp)
(nontrivial-square-root?
(remainder (square (expmod base (/ exp 2) m))
m)))
(else
(remainder (* base (expmod base (- exp 1) m))
m))))
(= (expmod a (- n 1) n) 1))
(define (nontrivial-square-root? val)
(if (= val 1)
0
val))
My idea is to filter out those so-called "nontrivial square roots of 1 modulo n" with the procedure nontrivial-square-root?. A 0 is returned if (remainder (square (expmod base (/ exp 2) m)) m) is 1, in which case the square of (expmod base (/ exp 2) m) must be equal to 1 modulo n (this is because m always equals n), making it a nontrivial square root.
While nontrivial-square-root? does filter out carmichael numbers such as 561, 1105, 1729, 2465, 2821 and 6601, prime numbers such as 7 and 13 are also reported to be composite.
What causes these false negatives?

The important part of the quote marked with bold text:
However, whenever we perform the squaring step in expmod, we check to see if we have discovered a ''nontrivial square root of 1 modulo n,'' that is, a number not equal to 1 or n - 1 whose square is equal to 1 modulo n
So before you square and take the remainder you have to check that the argument is not 1 or n - 1. This occurs, e.g., if you call (miller-rabin-test 5 3). Working the recursion out you notice that there is a call (nontrivial-square-root? (remainder (square 4) 5)) which evaluates to (nontrivial-square-root? 1). However, 5 can still be prime because 4 is 5 - 1.
So in the squaring part you can, e.g., call a following function:
(define (sqrmod-with-check val n)
(let ((sqrmod (remainder (square val) n)))
(cond ((or (= val (- n 1)) (= val 1)) sqrmod)
((= sqrmod 1) 0)
(else sqrmod))))
where the arguments are the expmod call and m. This does the square and remainder for you except in the case we have found a nontrivial square root of 1 modulo n, when it returns 0. I divided it to three conditions, instead of two, just because of readability.

Related

calculate the sum of proper divisors of a given number in Racket BSL

Design a Racket function named findProperDivisor that takes a natural number and calculates the sum of all its proper divisors. A proper divisor of a natural number is the divisor that is strictly less than the number.
Examples:
Input: 20
Output: 22
//Proper divisors: 1 + 2 + 4 + 5 + 10 = 22
(define (sum-of-proper-divisors n i)
(cond [(= i 1) 1]
[(= (remainder n i) 0)
(+ i (sum-of-proper-divisors n (sub1 i)))]
[else (sum-of-proper-divisors n (sub1 i))]))
I found this code on this page but it gives me 1+2+4+5+10+20=42 I need 22.
I would like to write this code with one parameter by using recursion and cond. I am using Beginning Student Language (BSL), which does not have things like let defined.
Step 1: understand what the code is doing. Why is there an additional parameter? What is happening with it?
Step 2: How do you call this? What does this mean for i?
Step 3: What would you have to do differently so that the remainder is not checked against the number itself?
To fulfill the condition strictly smaller than itself, call it with (sum-of-proper-divisors 20 (sub1 20)) then you get 22, since then, 20 is not counted as divisor.
Since you should define that function with just one number as argument, - due to the constrains of this beginner-language, I would define the desired function as a second function:
(define (sum-of-proper-divisors n i)
(cond ((= 1 i) 1)
((= (remainder n i) 0)
(+ i (sum-of-proper-divisors n (sub1 i))))
(else (sum-of-proper-divisors n (sub1 i)))))
(define (findProperDivisors n)
(sum-of-proper-divisors n (sub1 n)))
(findProperDivisors 20) ;; => 22

Racket conditional sum of series by recursion

I am new to Racket. I need to sum all the natural numbers less than 1000 (or any nth value) and the numbers will be divisible by 3 or 5. I have a code which can do that but using iteration. But I have to do same thing by recursion. The code is as follows:
(define (sum-divisibles limit)
(for/sum ([i (in-range 1 limit)]
#:when (or (divides? i 3)
(divides? i 5)))
i))
(define (divides? m n)
(= 0 (remainder m n)))
I need to do same thing but with recursion but not with loop or iteration.
This is straightforward, as long as you visualize each iteration in the loop as a function call. Think about it: the original for loop goes from 1 up to and including limit-1. That's the same as starting from limit-1, decreasing the limit by 1 at each function call, and stopping when we reach 0.
There are two important things to remember wen writing recursive procedure:
We have to make sure that we stop at some point - this is called the base case; for this example, that happens when we reach 0 (because the original loop includes 1).
We have to combine the partial results that we obtain along when calling the recursion: if the current number happens to be divisible by 3 or 5 then we add it to the rest of the recursive calls, otherwise we ignore it but keep advancing the recursion anyway, until we reach the base case.
This is what I mean:
(define (sum-divisibles limit)
(cond ((= limit 0) 0) ; base case, stop recursion
((or (divides? limit 3) (divides? limit 5)) ; does the condition hold?
(+ limit ; then we add current value
(sum-divisibles (- limit 1)))) ; and advance the recursion
(else ; otherwise skip it
(sum-divisibles (- limit 1))))) ; and advance the recursion
Be careful with the initial limit value, remember that in your original code the limit is not added to the sum (the iteration stops right before reaching it), hence the equivalent way to call the recursive version is this:
(sum-divisibles (- n 1))
For example, to obtain the same value as (sum-divisibles 50) with your code, we have to call it like this in the recursive version:
(sum-divisibles 49)
=> 543
Alternatively you could write a helper procedure that takes care of decreasing the input limit by one before calling the actual recursive procedure, but that's left as an exercise for the reader.
Let have n be some positive number and m is predecessor, m = n - 1.
Now, suppose you know that (sum-divisibles m) equals some value s. How would you do to compute (sum-divisible n)?
Try writing a function which takes a value n and the value s, and computes the sum for n.
(define (recur n s) ...)
Then you will be able to define sum-divisibles in terms of limit and the recursive application of sum-divisibles for limit - 1. You also need to take care of the base case of the recursion, when limit is zero.
One can use 'named let' for recursion:
(define limit 1000)
(let loop ((n 1) ; starting values
(sum 0))
(cond
[(> n limit) sum] ; print out sum if limit reached;
[(or (= 0 (modulo n 3)) ; if n is divisible by 3 or 5
(= 0 (modulo n 5)))
(loop (add1 n) (+ sum n))] ; add this number to sum and loop again with next number
[else ; if not divisible
(loop (add1 n) sum)] ; loop with next number without adding to sum
))

Get the Sum of given number in scheme

Hi i want my function to sum digits such that the result is less than 10 (77 = 14=5). dont know why it's passing the base case
(define (reduct n)
(if(< n 10) n
(+(modulo n 10)(reduct (truncate(/ n 10))))))
You forgot to call reduct again after adding. Here's the fixed version:
(define (reduct n)
(if (< n 10)
n
(reduct (+ (modulo n 10) (reduct (quotient n 10))))))
Note that the inner reduct recursion is actually redundant and can be removed, leaving:
(define (reduct n)
(if (< n 10)
n
(reduct (+ (modulo n 10) (quotient n 10)))))
or, if you want to only divide once (and get the modulo too), you can use the R7RS floor/ procedure:
(define (reduct n)
(if (< n 10)
n
(reduct (call-with-values (lambda () (floor/ n 10)) +))))
(This is, by the way, a pure loop. A Ruby version could look like:
def reduct(n)
n = n % 10 + n / 10 while n >= 10
n
end
or (for the one-division-only approach)
def reduct(n)
n = n.divmod(10).reduce(:+) while n >= 10
n
end
except that it uses mutation unlike the Scheme version.)
However, as my comment already says, the result will always be the same as doing (modulo n 9) (except that 0 should become 9, so (+ (modulo (- n 1) 9) 1) is probably more correct), so if you're doing this for numerological purposes or otherwise not a homework which requires you to do it the "hard way", just use that.

Find the Hardy–Ramanujan number using R5RS scheme. Please suggest improvements in idiom and calculations.

I remember once going to see
[Srinivasa Ramanujan] when he was ill
at Putney. I had ridden in taxi cab
number 1729 and remarked that the
number seemed to me rather a dull one,
and that I hoped it was not an
unfavorable omen. "No," he replied,
"it is a very interesting number; it
is the smallest number expressible as
the sum of two cubes in two different
ways." [G. H. Hardy as told in "1729
(number)"]
In "Math Wrath" Joseph Tartakovsky says about this feat, "So what?
Give me two minutes and my calculator watch, and I'll do the same
without exerting any little gray cells." I don't know how
Mr. Tartakovsky would accomplish that proof on a calculator watch, but
the following is my scheme function that enumerates numbers starting
at 1 and stops when it finds a number that is expressable in two
seperate ways by summing the cubes of two positive numbers. And it
indeeds returns 1729.
There are two areas where I would appreciate suggestions for
improvement. One area is, being new to scheme, style and idiom. The other area is around the calculations. Sisc
does not return exact numbers for roots, even when they could be. For
example (expt 27 1/3) yields 2.9999999999999996. But I do get exact
retults when cubing an exact number, (expt 3 3) yields 27. My
solution was to get the exact floor of a cube root and then test
against the cube of the floor and the cube of the floor plus one,
counting as a match if either match. This solution seems messy and hard to reason about. Is there a more straightforward way?
; Find the Hardy-Ramanujan number, which is the smallest positive
; integer that is the sum of the cubes of two positivie integers in
; two seperate ways.
(define (hardy-ramanujan-number)
(let ((how-many-sum-of-2-positive-cubes
; while i^3 + 1 < n/1
; tmp := exact_floor(cube-root(n - i^3))
; if n = i^3 + tmp^3 or n = i^3 + (tmp + 1) ^3 then count := count + 1
; return count
(lambda (n)
(let ((cube (lambda (n) (expt n 3)))
(cube-root (lambda (n) (inexact->exact (expt n 1/3)))))
(let iter ((i 1) (count 0))
(if (> (+ (expt i 3) 1) (/ n 2))
count
(let* ((cube-i (cube i))
(tmp (floor (cube-root (- n cube-i)))))
(iter (+ i 1)
(+ count
(if (or (= n (+ cube-i (cube tmp)))
(= n (+ cube-i (cube (+ tmp 1)))))
1
0))))))))))
(let iter ((n 1))
(if (= (how-many-sum-of-2-positive-cubes n) 2)
n
(iter (+ 1 n))))))
Your code looks mostly fine, I see a few very minor things to comment on:
There's no need to define cube and cube-root at the innermost scope,
Using define for internal functions makes it look a little clearer,
This is related to the second part of your question: you're using inexact->exact on a floating point number which can lead to large rationals (in the sense that you allocate a pair of two big integers) -- it would be better to avoid this,
Doing that still doesn't solve the extra test that you do -- but that's only because you're not certain if you have the right number of if you missed by 1. Given that it should be close to an integer, you can just use round and then do one check, saving you one test.
Fixing the above, and doing it in one function that returns the number when it's found, and using some more "obvious" identifier names, I get this:
(define (hardy-ramanujan-number n)
(define (cube n) (expt n 3))
(define (cube-root n) (inexact->exact (round (expt n 1/3))))
(let iter ([i 1] [count 0])
(if (> (+ (cube i) 1) (/ n 2))
(hardy-ramanujan-number (+ n 1))
(let* ([i^3 (cube i)]
[j^3 (cube (cube-root (- n i^3)))]
[count (if (= n (+ i^3 j^3)) (+ count 1) count)])
(if (= count 2) n (iter (+ i 1) count))))))
I'm running this on Racket, and it looks like it's about 10 times faster (50ms vs 5ms).
Different Schemes behave differently when it comes to exact exponentiation: some return an exact result when possible, some an inexact result in all cases. You can look at ExactExpt, one of my set of implementation contrasts pages, to see which Schemes do what.

weirdness in scheme

I was trying to implement Fermat's primality test in Scheme.
I wrote a procedure fermat2(initially called fermat1) which returns true
when a^p-1 congruent 1(mod p) (please read it correctly guys!!)
a
every prime p number should satisfy the procedure (And hence Fermat's little theorem .. )
for any a
But when I tried to count the number of times this procedure yields true for a fixed number of trials ... ( using countt procedure, described in code) I got shocking results ans
So I changed the procedure slightly (I don't see any logical change .. may be I'm blind) and named it fermat1(replacing older fermat1 , now old fermat1 ->fermat2) and it worked .. the prime numbers passed the test all the times ...
why on earth the procedure fermat2 called less number of times ... what is actually wrong??
if it is wrong why don't I get error ... instead that computation is skipped!!(I think so!)
all you have to do , to understand what I'm trying to tell is
(countt fermat2 19 100)
(countt fermat1 19 100)
and see for yourself.
Code:
;;Guys this is really weird
;;I might not be able to explain this
;;just try out
;;(countt fermat2 19 100)
;;(countt fermat1 19 100)
;;compare both values ...
;;did you get any error using countt with fermat2,if yes please specify why u got error
;;if it was because of reminder procedure .. please tell your scheme version
;;created on 6 mar 2011 by fedvasu
;;using mit-scheme 9.0 (compiled from source/microcode)
;; i cant use a quote it mis idents (unfriendly stack overflow!)
;;fermat-test based on fermat(s) little theorem a^p-1 congruent to 1 (mod p) p is prime
;;see MIT-SICP,or Algorithms by Vazirani or anyother number theory book
;;this is the correct logic of fermat-test (the way it handles 0)
(define (fermat1 n)
(define (tryout a x)
;; (display "I've been called\n")
(= (remainder (fast-exp a (- x 1)) x) 1))
;;this exercises the algorithm
;;1+ to avoid 0
(define temp (random n))
(if (= temp 0)
(tryout (1+ temp) n)
(tryout temp n)))
;;old fermat-test
;;which is wrong
;;it doesnt produce any error!!
;;the inner procedure is called only selective times.. i dont know when exactly
;;uncomment the display line to see how many times tryout is called (using countt)
;;i didnt put any condition when it should be called
;;rather it should be every time fermat2 is called
;;how is it so??(is it to avoid error?)
(define (fermat2 n)
(define (tryout a x)
;; (display "I've been called\n")
(= (remainder (fast-exp a (- x 1)) x) 1))
;;this exercises the algorithm
;;1+ to avoid 0
(tryout (1+ (random n)) n))
;;this is the dependency procedure for fermat1 and fermat2
;;this procedure calculates base^exp (exp=nexp bcoz exp is a keyword,a primitive)
;;And it is correct :)
(define (fast-exp base nexp)
;;this is iterative procedure where a*b^n = base^exp is constant always
;;A bit tricky though
(define (logexp a b n)
(cond ((= n 0) a);;only at the last stage a*b^n is not same as base^exp
((even? n) (logexp a (square b) (/ n 2)))
(else (logexp (* a b) b (- n 1)))))
(logexp 1 base nexp))
;;utility procedure which takes a procedure and its argument and an extra
;; argument times which tells number of times to call
;;returns the number of times result of applying proc on input num yielded true
;;counting the number times it yielded true
;;procedure yields true for fixed input,
;;by calling it fixed times)
;;uncommenting display line will help
(define (countt proc num times)
(define (pcount p n t c)
(cond ((= t 0)c)
((p n );; (display "I'm passed by fermat1\n")
(pcount p n (- t 1) (+ c 1)));;increasing the count
(else c)))
(pcount proc num times 0))
I had real pain .. figuring out what it actually does .. please follow the code and tell why this dicrepieancies?
Even (countt fermat2 19 100) called twice returns different results.
Let's fix your fermat2 since it's shorter. Definition is: "If n is a prime number and a is any positive integer less than n, then a raised to the nth power is congruent to a modulo n.". That means f(a, n) = a^n mod n == a mod n. Your code tells f(a, n) = a^(n-1) mod n == 1 which is different. If we rewrite this according to definition:
(define (fermat2 n)
(define (tryout a x)
(= (remainder (fast-exp a x) x)
(remainder a x)))
(tryout (1+ (random n)) n))
This is not correct yet. (1+ (random n)) returns numbers from 1 to n inclusive, while we need [1..n):
(define (fermat2 n)
(define (tryout a x)
(= (remainder (fast-exp a x) x)
(remainder a x)))
(tryout (+ 1 (random (- n 1))) n))
This is correct version but we can improve it's readability. Since you're using tryout only in scope of fermat2 there is no need in parameter x to pass n - latter is already bound in scope of tryout, so final version is
(define (fermat n)
(define (tryout a)
(= (remainder (fast-exp a n) n)
(remainder a n)))
(tryout (+ 1 (random (- n 1)))))
Update:
I said that formula used in fermat2 is incorrect. This is wrong because if a*k = b*k (mod n) then a = b (mod n). Error as Vasu pointed was in generating random number for test.

Resources