(in-package :GECO)
#|
Genetic Evolution through Combination of Objects (GECO)
Copyright (C) 1993 George P. W. Williams, Jr.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|#
#+:GECO-STANDARD-CL-RANDOM
(let ((state *random-state*))
(defun GECO-RANDOM-FLOAT (number)
"Accept a positive floating-point number and returns a number of the same kind between zero (inclusive)
and the number (exclusive)."
(declare (float number))
(random number state))
(defun GECO-RANDOM-INTEGER (number)
"Accept a positive integer and returns a number of the same kind between zero (inclusive) and
the number (exclusive)."
(declare (integer number))
(random number state))
;; The following two functions allow external access to GECO's random state.
;; This makes it possible for the random state to be recorded/initialized to reproduce runs.
(defun SET-GECO-RANDOM-STATE (new-state)
(setq state new-state))
(defun GECO-RANDOM-STATE ()
state)
)
;;; The following implementation of the Park-Miller multiplicative congruential randomizer
;;; is adapted with permission from John Koza's simple genetic programming example.
;;; Copyright (c) John Koza, All rights reserved.
#+:GECO-PARK-MILLER-RANDOM
(let ((seed (coerce (random 1.0) 'double-float)))
;; The seed for the Park-Miller congruential randomizer.
(defun park-miller-randomizer ()
"The Park-Miller multiplicative congruential randomizer
(CACM, October 88, Page 1195). Creates pseudo random floating
point numbers in the range 0.0 < x <= 1.0. The seed value
for this randomizer is called seed, so you should
record/set this if you want to make your runs reproducible."
(let ((multiplier 16807.0d0);16807 is (expt 7 5)
(modulus 2147483647.0d0))
;2147483647 is (- (expt 2 31) 1)
(let ((temp (* multiplier seed)))
(setf seed (mod temp modulus))
;;Produces floating-point number in the range
;; 0.0 < x <= 1.0
(/ seed modulus))))
(defun park-miller-random-floating-point-number (n)
"Returns a pseudo random floating-point number
in range 0.0 <= number < n"
(let ((random-number (park-miller-randomizer)))
;; We subtract the randomly generated number from 1.0
;; before scaling so that we end up in the range
;; 0.0 <= x < 1.0, not 0.0 < x <= 1.0
(* n (- 1.0d0 random-number))))
(defun park-miller-random-integer (n)
"Returns a pseudo-random integer in the range 0 ---> n-1."
(let ((random-number (park-miller-random-floating-point-number 1.0)))
(floor (* n random-number))))
(defun GECO-RANDOM-FLOAT (number)
"Accept a positive floating-point number and returns a number of the same kind between zero (inclusive)
and the number (exclusive)."
(declare (float number))
(park-miller-random-floating-point-number number))
(defun GECO-RANDOM-INTEGER (number)
"Accept a positive integer and returns a number of the same kind between zero (inclusive) and
the number (exclusive)."
(declare (integer number))
(park-miller-random-integer number))
;; The following two functions allow external access to GECO's random state.
;; This makes it possible for the random state to be recorded/initialized to reproduce runs.
(defun SET-GECO-RANDOM-SEED (new-seed)
(setq seed new-seed))
(defun GECO-RANDOM-SEED ()
seed)
)