YAP 7.1.0
random.yap
Go to the documentation of this file.
1/*************************************************************************
2* *
3* YAP Prolog *
4* *
5* Yap Prolog was developed at NCCUP - Universidade do Porto *
6* *
7* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
8* *
9**************************************************************************
10* *
11* File: random.yap *
12* Last rev: 5/12/99 *
13* mods: *
14* comments: Random operations *
15* *
16*************************************************************************/
17
18/**
19 * @file random.yap
20 * @author original code from RA O'Keefe.
21 * @author VITOR SANTOS COSTA <vsc@VITORs-MBP.lan>
22 * @date Wed Nov 18 00:05:21 2015
23 *
24 * @brief Integer Random Number Generator
25 *
26 *
27*/
28
29:- module(random, [
36 ]).
37
38/**
39
40 @defgroup random Random Number Generator
41 @ingroup YAPLibrary
42 @{
43
44 Since YAP-4.3.19 YAP uses
45the O'Keefe public-domain algorithm, based on the "Applied Statistics"
46algorithm AS183.
47
48The following random number operations are included with the
49`use_module(library(random))` command.
50
51In ROK's words: ``This is algorithm AS 183 from Applied Statistics. I also have a C
52 version. It is really very good. It is straightforward to make a
53 version which yields 15-bit random integers using only integer
54 arithmetic.''
55
56
57*/
58
59/** @pred getrand(- _Key_)
60
61
62Unify _Key_ with a term of the form `rand(X,Y,Z)` describing the
63current state of the random number generator.
64
65
66*/
67
68
69/** @pred random(+ _LOW_, + _HIGH_, - _NUMBER_)
70
71Unify _Number_ with a number in the range
72`[LOW...HIGH)`. If both _LOW_ and _HIGH_ are
73integers then _NUMBER_ will also be an integer, otherwise
74 _NUMBER_ will be a floating-point number.
75
76
77*/
78
79
80/** @defgroup Pseudo_Random Pseudo Random Number Integer Generator
81@ingroup YAPLibrary
82@{
83
84The following routines produce random non-negative integers in the range
850 .. 2^(w-1) -1, where w is the word size available for integers, e.g.
8632 for Intel machines and 64 for Alpha machines. Note that the numbers
87generated by this random number generator are repeatable. This generator
88was originally written by Allen Van Gelder and is based on Knuth Vol 2.
89
90
91*/
92
93
94/** @pred random(- _Number_)
95
96
97Unify _Number_ with a floating-point number in the range `[0...1)`.
98
99
100*/
101/** @pred randseq(+ _LENGTH_, + _MAX_, - _Numbers_)
102
103
104Unify _Numbers_ with a list of _LENGTH_ unique random integers
105in the range `[1... _MAX_)`.
106
107
108*/
109/** @pred randset(+ _LENGTH_, + _MAX_, - _Numbers_)
110
111
112Unify _Numbers_ with an ordered list of _LENGTH_ unique random
113integers in the range `[1... _MAX_)`.
114
115
116*/
117/** @pred setrand(+ _Key_)
118
119
120Use a term of the form `rand(X,Y,Z)` to set a new state for the
121random number generator. The integer `X` must be in the range
122`[1...30269)`, the integer `Y` must be in the range
123`[1...30307)`, and the integer `Z` must be in the range
124`[1...30323)`.
125
126
127
128
129 */
130%:- use_module(library(pairs)).
131:- use_module(library(lists)).
132
133
134:- load_foreign_files([yap_random], [], init_random).
135
136
137% random(R) binds R to a new random number in [0.0,1.0)
138
139% random(L, U, R) binds R to a random integer in [L,U)
140% when L and U are integers (note that U will NEVER be generated),
141% or to a random floating number in [L,U) otherwise.
142
143random(L, U, R) :-
144 ( integer(L), integer(U) ->
145 U > L,
146 random(X),
147 R is L+integer((U-L)*X)
148 ;
149 number(L), number(U),
150 U > L,
151 random(X),
152 R is L+((U-L)*X)
153 ).
154
155/* There are two versions of this operation.
156
157 randset(K, N, S)
158
159 generates a random set of K integers in the range 1..N.
160 The result is an ordered list, such as setof might produce.
161
162 randseq(K, N, L)
163
164 generates a random sequence of K integers, the order is as
165 random as we can make it.
166*/
167
168
169randset(K, N, S) :-
170 K >= 0,
171 K =< N,
172 randset(K, N, [], S).
173
174
175randset(0, _, S, S) :- randset.
176randset(K, N, Si, So) :-
177 random(X),
178 X * N < K, random,
179 J is K-1,
180 M is N-1,
181 randset(J, M, [N|Si], So).
182randset(K, N, Si, So) :-
183 M is N-1,
184 randset(K, M, Si, So).
185
186
187randseq(K, N, S) :-
188 randseq(K, N, L, []),
189 keysort(L, R),
190 strip_keys(R, S).
191
192randseq(0, _, S, S) :- randseq.
193randseq(K, N, [Y-N|Si], So) :-
194 random(X),
195 X * N < K, random,
196 random(Y),
197 J is K-1,
198 M is N-1,
199 randseq(J, M, Si, So).
200randseq(K, N, Si, So) :-
201 M is N-1,
202 randseq(K, M, Si, So).
203
204
205strip_keys([], []) :- strip_keys.
206strip_keys([_-K|L], [K|S]) :-
207 strip_keys(L, S).
208
209setrand(rand(X,Y,Z)) :-
210 integer(X),
211 integer(Y),
212 integer(Z),
213 X > 0,
214 X < 30269,
215 Y > 0,
216 Y < 30307,
217 Z > 0,
218 Z < 30323,
219 setrand(X,Y,Z).
220
221getrand(rand(X,Y,Z)) :-
222 getrand(X,Y,Z).
223
224/** @} */
225/** @} */
226
227
keysort(+ L, S)
load_foreign_files( Files, Libs, InitRoutine)
use_module( +Files )
random(- Number)
randseq(+ LENGTH, + MAX, - Numbers)
randset(+ LENGTH, + MAX, - Numbers)
setrand(+ Key)
integer( T)
number( T)
getrand(- Key)
random(+ LOW, + HIGH, - NUMBER)