sicp-ex-3.82



<< Previous exercise (3.81) | Index | Next exercise (4.1) >>


meteorgan

  
  
 (define (random-in-range low high) 
   (let ((range (- high low))) 
     (+ low (* (random) range)))) 
 (define (random-number-pairs low1 high1 low2 high2) 
   (cons-stream (cons (random-in-range low1 high1) (random-in-range low2 high2)) 
                (random-number-pairs low1 high1 low2 high2))) 
  
 (define (monte-carlo experiment-stream passed failed) 
   (define (next passed failed) 
     (cons-stream (/ passed (+ passed failed)) 
                  (monte-carlo (stream-cdr experiment-stream) 
                               passed 
                               failed))) 
   (if (stream-car experiment-stream) 
       (next (+ passed 1) failed) 
       (next passed (+ failed 1)))) 
  
 (define (estimate-integral p x1 x2 y1 y2) 
   (let ((area (* (- x2 x1) (- y2 y1))) 
         (randoms (random-number-pairs x1 x2 y1 y2))) 
     (scale-stream (monte-carlo (stream-map p randoms) 0 0) area))) 
  
 ;; test. get the value of pi 
 (define (sum-of-square x y) (+ (* x x) (* y y))) 
 (define f 
   (lambda (x) 
     (not (> (sum-of-square (- (car x) 1) (- (cdr x) 1)) 
             1)))) 
 (define pi-stream (estimate-integral f 0 2 0 2)) 
  

If we use sicp-ex-3.5 as the lib, then the above can be simplified although sharing the same basic ideas.

Assume to use x3v's implementation:

 (define (estimate-integral p x1 x2 y1 y2)  
   (let ((area (* (- x2 x1) (- y2 y1)))  
         (randoms (stream-map (lambda (ignore) (p x1 x2 y1 y2 1)) ones))) 
     (scale-stream (monte-carlo (stream-map p randoms) 0 0) area))) 


tango

Meteorgan's solution uses the monte-carlo method with variables passed and failed. Following solution doesn't uses these and relies solely on streams.

 (define (add-streams s1 s2) (stream-map + s1 s2)) 
 (define ones (cons-stream 1.0 ones)) 
 (define integers (cons-stream 1.0 (add-streams ones integers))) 
  
 (define (random-stream lo hi) 
   (define (random-in-range low high) 
     (let ((range (- high low))) 
       (+ low (random range)))) 
   (cons-stream (random-in-range lo hi) 
                (random-stream lo hi))) 
  
 (define (estimate-integral p x1 x2 y1 y2) 
   (define throw-results 
     (stream-map (lambda (x) (if (eq? x true) 1.0 0)) 
                 (stream-map p 
                             (random-stream x1 x2) 
                             (random-stream y1 y2)))) 
   (define successful-throws 
     (cons-stream (stream-car throw-results) 
                  (add-streams (stream-cdr throw-results) 
                               successful-throws))) 
   (define (get-area probability) 
     (* probability (abs (* (- y2 y1) (- x2 x1))))) 
   (stream-map get-area 
               (stream-map / successful-throws integers))) 

master

Isn't producing random numbers the predicate's job? Doesn't the following simple definition of estimate-integral suffice?

 (define (estimate-integral P x1 x2 y1 y2) 
   (let ((width (- x2 x1)) 
         (height (- y2 y1))) 
     (let ((area (* width height))) 
       (scale-stream (monte-carlo P 0 0) area)))) 

x3v

Uses the random-in-range procedure previously defined in the book.

  
  
 (define (random-in-range low high) 
   (let ((range (- high low))) 
     (+ low (random range)))) 
  
 (define (rand-range-stream low high) 
   (cons-stream 
    (random-in-range low high) 
    (rand-range-stream low high))) 
  
 (define (experiment-stream x1 x2 y1 y2 radius) 
   (stream-map 
    (lambda (x) (> radius x)) 
    (add-streams 
     (stream-map square (rand-range-stream x1 x2)) 
     (stream-map square (rand-range-stream y1 y2))))) 
  
 (define pi-est-stream 
   (scale-stream (monte-carlo (experiment-stream -1.0 1.0 -1.0 1.0 1.0) 0 0) 4.0)) 
  
 (exact->inexact (stream-ref pi-est-stream 50000)) ;; ~3.1429 

krubar

Similar solution to meteorgan's. Requires random-in-range from Excercise 3.5 and monte-carlo from the beginning of section 3.5.5.

 (define (randoms-ranged low high) 
   (cons-stream (random-in-range low high) 
                (randoms-ranged low high))) 
  
 (define (integral-estimates P x1 x2 y1 y2) 
   (define point-in-integral-stream 
     (stream-map P (randoms-ranged x1 x2) (randoms-ranged y1 y2))) 
   (monte-carlo point-in-integral-stream 0 0)) 
  
 (define (in-unit-circle? x y) 
   (<= (+ (expt (- x 0.5) 2) 
          (expt (- y 0.5) 2)) 
       (expt 0.5 2))) 
  
 (define pi-integral-estimates 
   (stream-map (lambda (area) (/ area (* 0.5 0.5))) 
               (integral-estimates in-unit-circle? 0.0 1.0 0.0 1.0)))