From: Jan Rychter
Subject: Saving random state in CMUCL
Date: 
Message-ID: <m2d6ihmgfc.fsf@tnuctip.rychter.com>
I am having trouble saving the random number generator state to a file
in CMUCL. Here's what I'm doing:

(defun save-random-state-to-file (filename)
  (let (random-state-file)
    (with-open-file (random-state-file filename
				       :direction :output
				       :if-exists :supersede)
      (print *random-state* random-state-file))))

(defun read-random-state-from-file (filename)
  (let (random-state-file)
    (with-open-file (random-state-file filename
				       :direction :input)
      (setf *random-state* (read random-state-file)))))


Which fails when trying to read the state back:

  * (read-random-state-from-file "/tmp/random.state")
  
  Type-error in KERNEL::OBJECT-NOT-TYPE-ERROR-HANDLER:
     #(0 2567483615 538 1700500280 3739261991 2172795598 2566071632 1965163719
  
  [...lines clipped...]
  
       2438610757 2105462232 1310058620) is not of type (OR
                                                         (SIMPLE-ARRAY
                                                          (UNSIGNED-BYTE 32)
                                                          (627))
                                                         NULL)
    Restarts:
    0: [ABORT] Return to Top-Level.
  
  Debug  (type H for help)
  
  ("DEFSTRUCT RANDOM-STATE" 268434086 2)[:OPTIONAL]
  Source: Error finding source: 
  Error in function DEBUG::GET-FILE-TOP-LEVEL-FORM:  Source file no longer exists:
    target:code/rand-mt19937.lisp.
  0] 
  * 


Trying the same under AllegroCL 6.2 seems to work fine:

CL-USER(3): (save-random-state-to-file "/tmp/random.state")
#S(RANDOM-STATE :MTI 63
                :FIXSEED
                #(3960924350 2165561044 562617442 2270225120 1264129478
                  758582028 172407450 2782512936 595962478 1609675396 ...))
CL-USER(4): (read-random-state-from-file "/tmp/random.state")
#S(RANDOM-STATE :MTI 63
                :FIXSEED
                #(3960924350 2165561044 562617442 2270225120 1264129478
                  758582028 172407450 2782512936 595962478 1609675396 ...))
CL-USER(5): 

Any hints? What am I doing wrong?

thanks,
--J.

From: Jan Rychter
Subject: Re: Saving random state in CMUCL
Date: 
Message-ID: <m2n0hlkzhl.fsf@tnuctip.rychter.com>
>>>>> "Jan" == Jan Rychter <···@rychter.com> writes:
 Jan> I am having trouble saving the random number generator state to a
 Jan> file in CMUCL. Here's what I'm doing:

Actually, it seems to be even worse:

* (setq *saved-state* (make-random-state t))
Warning:  Declaring *SAVED-STATE* special.

#S(RANDOM-STATE
     :STATE #(0 2567483615 624 2266088218 1091686521 2279569242 2507156923
[...]
              696185074 4238644201))
* (let ((*random-state* *saved-state*)) (loop for i from 1 to 10 collect (random 100)))
(54 59 98 31 93 48 51 2 38 18)
* (let ((*random-state* *saved-state*)) (loop for i from 1 to 10 collect (random 100)))
(51 74 31 49 24 23 72 45 63 86)
* (let ((*random-state* *saved-state*)) (loop for i from 1 to 10 collect (random 100)))
(63 40 35 2 72 13 16 5 25 11)
* 

CLISP seems to do the same thing:

[1]> (setq *saved-state* (make-random-state t))
#S(RANDOM-STATE #*1110001001000100010001011000101110011101001011001100011010101111)
[2]> (let ((*random-state* *saved-state*)) (loop for i from 1 to 10 collect (random 100)))
(57 9 60 45 85 74 72 67 4 62)
[3]> (let ((*random-state* *saved-state*)) (loop for i from 1 to 10 collect (random 100)))
(70 38 25 37 40 4 50 19 23 37)
[4]> (let ((*random-state* *saved-state*)) (loop for i from 1 to 10 collect (random 100)))
(72 36 64 33 68 11 56 97 98 5)

Am I right in thinking that the three rows of generated numbers should
be identical? That's what the hyperspec seems to suggest.

--J.
From: Paul F. Dietz
Subject: Re: Saving random state in CMUCL
Date: 
Message-ID: <5aydnTyHTLRfK1ujXTWcrg@dls.net>
Jan Rychter wrote:

> [1]> (setq *saved-state* (make-random-state t))
> #S(RANDOM-STATE #*1110001001000100010001011000101110011101001011001100011010101111)
> [2]> (let ((*random-state* *saved-state*)) (loop for i from 1 to 10 collect (random 100)))
> (57 9 60 45 85 74 72 67 4 62)
> [3]> (let ((*random-state* *saved-state*)) (loop for i from 1 to 10 collect (random 100)))
> (70 38 25 37 40 4 50 19 23 37)
> [4]> (let ((*random-state* *saved-state*)) (loop for i from 1 to 10 collect (random 100)))
> (72 36 64 33 68 11 56 97 98 5)
> 
> Am I right in thinking that the three rows of generated numbers should
> be identical? That's what the hyperspec seems to suggest.

No.  You are not copying the random state, you are just refering to the same
random state object.  (RANDOM ...) destructively modifies this object.

To copy a random state object, call MAKE-RANDOM-STATE with the random
state object to be copied as the argument.  Your let forms should be

   (let ((*random-state* (make-random-state *saved-state*))) ...)

	Paul
From: Jan Rychter
Subject: Re: Saving random state in CMUCL
Date: 
Message-ID: <m2k7cpjiv9.fsf@tnuctip.rychter.com>
Paul F. Dietz:
> Jan Rychter wrote:
> > [1]> (setq *saved-state* (make-random-state t))
> > #S(RANDOM-STATE #*1110001001000100010001011000101110011101001011001100011010101111)
> > [2]> (let ((*random-state* *saved-state*)) (loop for i from 1 to 10 collect (random 100)))
> > (57 9 60 45 85 74 72 67 4 62)
> > [3]> (let ((*random-state* *saved-state*)) (loop for i from 1 to 10 collect (random 100)))
> > (70 38 25 37 40 4 50 19 23 37)
> > [4]> (let ((*random-state* *saved-state*)) (loop for i from 1 to 10 collect (random 100)))
> > (72 36 64 33 68 11 56 97 98 5)
> > Am I right in thinking that the three rows of generated numbers should
> > be identical? That's what the hyperspec seems to suggest.
> 
> No.  You are not copying the random state, you are just refering to the same
> random state object.  (RANDOM ...) destructively modifies this object.
> 
> To copy a random state object, call MAKE-RANDOM-STATE with the random
> state object to be copied as the argument.  Your let forms should be
> 
>    (let ((*random-state* (make-random-state *saved-state*))) ...)

Thank you. This works very well indeed.

Either I don't understand the example in the HyperSpec, or the example
taken from
http://www.lisp.org/HyperSpec/Body/var_strandom-statest.html#STrandom-stateST
is wrong:

(setq snap-shot (make-random-state))
 ;; The series from any given point is random,
 ;; but if you backtrack to that point, you get the same series.
 (list (loop for i from 1 to 10 collect (random))
       (let ((*random-state* snap-shot))
         (loop for i from 1 to 10 collect (random)))
       (loop for i from 1 to 10 collect (random))
       (let ((*random-state* snap-shot))
         (loop for i from 1 to 10 collect (random))))
=>  ((19 16 44 19 96 15 76 96 13 61)
    (19 16 44 19 96 15 76 96 13 61)
    (16 67 0 43 70 79 58 5 63 50)
    (16 67 0 43 70 79 58 5 63 50))

(besides, random takes one non-optional argument, so this example won't
work out of the box anyway)

--J.
From: Paul F. Dietz
Subject: Re: Saving random state in CMUCL
Date: 
Message-ID: <AVWdne0e66-qIVujXTWcpw@dls.net>
Jan Rychter wrote:

> Either I don't understand the example in the HyperSpec, or the example
> taken from
> http://www.lisp.org/HyperSpec/Body/var_strandom-statest.html#STrandom-stateST
> is wrong:

The example looks bogus.  Note that the examples are not considered to be
part of the standard (I think this means they didn't vote on them.)

	Paul
From: Barry Margolin
Subject: Re: Saving random state in CMUCL
Date: 
Message-ID: <iX5ya.3$sO4.948@paloalto-snr1.gtei.net>
In article <··············@tnuctip.rychter.com>,
Jan Rychter  <···@rychter.com> wrote:
>Either I don't understand the example in the HyperSpec, or the example
>taken from
>http://www.lisp.org/HyperSpec/Body/var_strandom-statest.html#STrandom-stateST
>is wrong:
>
>(setq snap-shot (make-random-state))
> ;; The series from any given point is random,
> ;; but if you backtrack to that point, you get the same series.
> (list (loop for i from 1 to 10 collect (random))
>       (let ((*random-state* snap-shot))
>         (loop for i from 1 to 10 collect (random)))
>       (loop for i from 1 to 10 collect (random))
>       (let ((*random-state* snap-shot))
>         (loop for i from 1 to 10 collect (random))))
>=>  ((19 16 44 19 96 15 76 96 13 61)
>    (19 16 44 19 96 15 76 96 13 61)
>    (16 67 0 43 70 79 58 5 63 50)
>    (16 67 0 43 70 79 58 5 63 50))
>
>(besides, random takes one non-optional argument, so this example won't
>work out of the box anyway)

Other than the missing argument, it looks right.

First it saves a copy of the current random state in SNAP-SHOT.

Then it produces 10 random numbers starting from that state, which updates
the state 10 times.

Then it produces 10 random numbers starting from the copy in SNAP-SHOT.
This is the same number sequence as the previous step.  It also updates the
snapshot 10 times.

Then it produces the next 10 random numbers from the updated versions of
both the original state and the snapshot, which again produce the same
sequences as each other.

-- 
Barry Margolin, ··············@level3.com
Genuity Managed Services, a Level(3) Company, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Raymond Toy
Subject: Re: Saving random state in CMUCL
Date: 
Message-ID: <4n7k8nnh5c.fsf@edgedsp4.rtp.ericsson.se>
>>>>> "Jan" == Jan Rychter <···@rychter.com> writes:

    Jan> I am having trouble saving the random number generator state to a file
    Jan> in CMUCL. Here's what I'm doing:

    Jan> (defun save-random-state-to-file (filename)
    Jan>   (let (random-state-file)
    Jan>     (with-open-file (random-state-file filename
    Jan> 				       :direction :output
    Jan> 				       :if-exists :supersede)
    Jan>       (print *random-state* random-state-file))))

[snip]
    Jan> Which fails when trying to read the state back:

    Jan>   * (read-random-state-from-file "/tmp/random.state")
  
    Jan>   Type-error in KERNEL::OBJECT-NOT-TYPE-ERROR-HANDLER:
    Jan>      #(0 2567483615 538 1700500280 3739261991 2172795598 2566071632 1965163719
  
    Jan>   [...lines clipped...]
  
This is because the state array is a specialized array so it can't be
read back in.

However, if you print the random state readably, CMUCL has an
extension that allows you to read the random state back correctly.

        (write *random-state* :readably t)
        =>
        #S(RANDOM-STATE
               :STATE #A((UNSIGNED-BYTE 32) (627)
                         (0 2567483615 348 4203766947 73816872 3641397606 3709929322
                          277738477 3663162349 901888981 1226828757 121400213
                          3991191241 3716604976 3700546593 4225279515
                          852147860
                          ...)))

And this can be read back in.

Ray
From: Peter Seibel
Subject: Re: Saving random state in CMUCL
Date: 
Message-ID: <m3znlirk63.fsf@javamonkey.com>
Raymond Toy <···@rtp.ericsson.se> writes:

> However, if you print the random state readably, CMUCL has an
> extension that allows you to read the random state back correctly.

I'm not sure that's an "extension"--the standard requires the
implementation to provide this facility:

  22.1.3.10 Printing Random States

  A specific syntax for printing objects of type random-state is not
  specified. However, every implementation must arrange to print a
  random state object in such a way that, within the same
  implementation, read can construct from the printed representation a
  copy of the random state object as if the copy had been made by
  make-random-state.

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Raymond Toy
Subject: Re: Saving random state in CMUCL
Date: 
Message-ID: <4niss6ucms.fsf@edgedsp4.rtp.ericsson.se>
>>>>> "Peter" == Peter Seibel <·····@javamonkey.com> writes:

    Peter> Raymond Toy <···@rtp.ericsson.se> writes:
    >> However, if you print the random state readably, CMUCL has an
    >> extension that allows you to read the random state back correctly.

    Peter> I'm not sure that's an "extension"--the standard requires the
    Peter> implementation to provide this facility:

    Peter>   22.1.3.10 Printing Random States

    Peter>   A specific syntax for printing objects of type random-state is not
    Peter>   specified. However, every implementation must arrange to print a
    Peter>   random state object in such a way that, within the same
    Peter>   implementation, read can construct from the printed representation a
    Peter>   copy of the random state object as if the copy had been made by
    Peter>   make-random-state.

Sorry, the extension I was referring to is the ability for CMUCL to
print and read specialized arrays, which isn't required, I think.

Ray