[comp.lang.prolog] random number generator

dave@quintus.UUCP (David Bowen) (01/28/91)

In article <27A20DBF.15393@ics.uci.edu> cain@ics.uci.edu (Timothy Cain) writes:
>Does anyone have a random number generator written in Prolog, or know
>how I can get a random number using Quintus Prolog 2.4 (UNIX)? I'd
>rather not have to write a C routine just to produce a few different
>numbers for every run of my Prolog code.

Use library(random).  It defines a number of different routines for random
number generation.

ken@aiai.ed.ac.uk (Ken Johnson) (01/29/91)

In article <27A20DBF.15393@ics.uci.edu> cain@ics.uci.edu (Timothy Cain) writes:

>Does anyone have a random number generator written in Prolog, or know
>how I can get a random number using Quintus Prolog 2.4 (UNIX)? I'd
>rather not have to write a C routine just to produce a few different
>numbers for every run of my Prolog code.

The following is in the Prolog Library and (as far as I know!!) is
public domain.  Please aknowledge ROK's authorship.  The algorithm is
very clever. 

---------------------------------------- Cut Here 8< -------------------------
%   File   : RANDOM.PL
%   Author : R.A.O'Keefe
%   Updated: 1 October 1984
%   NIP version: 13 May 1987
%   Purpose: Random number generator.

%   given an integer N >= 1, random(N, I) unifies I with a random
%   integer between 0 and N - 1.

random(N, I) :-
	(	recorded(seed,[A0,A1,A2],Key)
		->	erase(Key)
	;
			A0 = 3172, A1 = 9814, A2 = 20125
	),
	B0 is (A0*171) mod 30269,
	B1 is (A1*172) mod 30307,
	B2 is (A2*170) mod 30323,
	record(seed,[B0,B1,B2],_),
	R is A0/30269 + A1/30307 + A2/30323,
	I is trunc((R - trunc(R)) * N).

%	The next bit: K R Johnson, 13-5-87
%	Restart the random sequence from the beginning

randomise :-
	(	recorded(seed,[_,_,_],Key)
		->	erase(Key)
		;	true
	),
	record(seed, [3172,9814,20125], _).

%	Instantiate the seeds to your own favourite value

randomise(Seed) :-
	integer(Seed),
	Seed > 0,
	(	recorded(seed,[_,_,_], Key)
		->	erase(Key)
		;	true
	),
	S0 is Seed mod 30269,
	S1 is Seed mod 30307,
	S2 is Seed mod 30323,
	record(seed,[S0,S1,S2],_).

%   given an non-empty List, random(List, Elem, Rest) unifies Elem with
%   a random element of List and Rest with the other elements.

random(List, Elem, Rest) :-
	length(List, N),
	N > 0,
	random(N, I),
	nth0(I, List, Elem, Rest).


%   rand_perm(List, Perm) unifies Perm with a random permutation
%   of List.  What good this may be I'm not sure, and there's bound
%   to be a more efficient way of doing it.  Oh well.

rand_perm([], []).
rand_perm([H1|T1], [H2|T2]) :-
	random([H1|T1], H2, T3),
	rand_perm(T3, T2).

-- 
  My father always wanted me                       %          Ken Johnson, AIAI
    To be a buccaneer;                             % 80 South Bridge, Edinburgh
  So when I fixed his lawnmower                    %   E-mail ken@aiai.ed.ac.uk
    He gave a hearty cheer.        -- me           %   031-650 2756 direct line

ken@aiai.ed.ac.uk (Ken Johnson) (01/30/91)

In article <4024@skye.ed.ac.uk> I gave a random number generator which I
attributed to Richard O'Keefe.  I have since received the following
letter about its authorship:

$ From baw@uk.co.npl.seg Wed Jan 30 12:01:01 1991
$ Received: from uk.ac.ukc by aiai.ed.ac.uk; Wed, 30 Jan 91 12:00:55 GMT
$ Received: from psg.npl.co.uk by kestrel.Ukc.AC.UK   with UUCP  id aa19671;
$           30 Jan 91 11:50 GMT
$ Received: from guava.seg.npl.co.uk by snow.psg.npl.co.uk; Wed, 30 Jan 91 10:53:1
$ 5 GMT
$ Date: Wed, 30 Jan 91 10:53:12 GMT
$ From: Brian A Wichmann <baw@uk.co.npl.seg>
$ Message-Id: <25478.9101301053@guava.seg.npl.co.uk>
$ To: ken@ed.aiai
$ Subject: Clever random numbers
$ Status: R
$ 
$ Dear Ken,
$ The `clever' random number generator you have in Prolog using
$ three primes is due to ID Hill (david) and myself. See
$ An efficient and portable pseudo-random number generator.
$ Applied Stats. AS183. 1982. Also Byte March 1987.
$ 
$ Please add this reference to the documentation, otherwise people
$ will be confused by the `cleverness' !!!
$ Brian Wichmann.


-- 
  My father always wanted me                       %          Ken Johnson, AIAI
    To be a buccaneer;                             % 80 South Bridge, Edinburgh
  So when I fixed his lawnmower                    %   E-mail ken@aiai.ed.ac.uk
    He gave a hearty cheer.        -- me           %   031-650 2756 direct line

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (01/31/91)

In article <27A20DBF.15393@ics.uci.edu>, cain@ics.uci.edu (Timothy Cain) writes:
> Does anyone have a random number generator written in Prolog, or know
> how I can get a random number using Quintus Prolog 2.4 (UNIX)?

LOOK IN THE LIBRARY!  It's even mentioned in the manual.
	?- use_module(library(random))).
	?- random(X).	% uniform [0,1) random float
There are lots of other routines in that file.
-- 
The Marxists have merely _interpreted_ Marxism in various ways;
the point, however, is to _change_ it.		-- R. Hochhuth.

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (01/31/91)

In article <4024@skye.ed.ac.uk>, ken@aiai.ed.ac.uk (Ken Johnson) writes:
> The following is in the Prolog Library and (as far as I know!!) is
> public domain.  Please acknowledge ROK's authorship.  The algorithm is
> very clever. 

Oh dear.  Did the version of RANDOM.PL I left at Edinburgh *really* omit
the attribution?  The algorithm used there for generating uniform random
floats is algorithm AS 163 from the journal Applied Statistics.  (In
effect it is a 48-bit linear congruential method.)

> random(N, I) :-
> 	(	recorded(seed,[A0,A1,A2],Key)
> 		->	erase(Key)
> 	;
> 			A0 = 3172, A1 = 9814, A2 = 20125
> 	),
>	...
> 	record(seed,[B0,B1,B2],_),
> 	...

I'm quite sure *I* didn't leave it like that.  The third argument of
recorded/1 is NOT a "key".  It's a "data base reference", "dbref" or
"ref" for short.  The FIRST argument is the "key".

Further, the thing that is recorded is not a seed, it is a random state,
and it always contains precisely three numbers, so a list is not appropriate.
What's more, if you haven't modules, it's a good idea to choose key names
that are unlikely to picked by users.  Hence

	recorded('random state', 'random state'(A0,A1,A2), Ref)
	...
	recorda('random state', 'random state'(B1,B1,B3), _)

> %   rand_perm(List, Perm) unifies Perm with a random permutation
> %   of List.  What good this may be I'm not sure, and there's bound
> %   to be a more efficient way of doing it.  Oh well.

> rand_perm([], []).
> rand_perm([H1|T1], [H2|T2]) :-
> 	random([H1|T1], H2, T3),
> 	rand_perm(T3, T2).

I'm sure that comment can't be mine.  There are *much* more efficient
ways of doing it, and the Quintus library uses one of them.  What's more,
the operation is there because it is extremely useful; I found that most
of the time that I was generating random numbers was to shuffle lists
(generate random permuations), so it seemed as well to do it directly.
(Think about generating test data.)
-- 
The Marxists have merely _interpreted_ Marxism in various ways;
the point, however, is to _change_ it.		-- R. Hochhuth.

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (01/31/91)

In article <4682@goanna.cs.rmit.oz.au>, ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) writes:
> Oh dear.  Did the version of RANDOM.PL I left at Edinburgh *really* omit
> the attribution?  The algorithm used there for generating uniform random
> floats is algorithm AS 163 from the journal Applied Statistics.
                         ***
Oops.  That should have been "183".  I'm quite sure that the attribution
was included in at least one of the versions of random.pl that I wrote at
Edinburgh.  There's a hardcover book of algorithms from Applied Statistics
and I think the algorithm was reprinted in that.
-- 
The Marxists have merely _interpreted_ Marxism in various ways;
the point, however, is to _change_ it.		-- R. Hochhuth.