1/* Part of SWI-Prolog 2 3 Author: R.A. O'Keefe, V.S. Costa, L. Damas, Jan Wielemaker 4 E-mail: J.Wielemaker@vu.nl 5 WWW: http://www.swi-prolog.org 6 Copyright (c) 2011-2016, Universidade do Porto, University of Amsterdam, 7 VU University Amsterdam. 8 All rights reserved. 9 10 Redistribution and use in source and binary forms, with or without 11 modification, are permitted provided that the following conditions 12 are met: 13 14 1. Redistributions of source code must retain the above copyright 15 notice, this list of conditions and the following disclaimer. 16 17 2. Redistributions in binary form must reproduce the above copyright 18 notice, this list of conditions and the following disclaimer in 19 the documentation and/or other materials provided with the 20 distribution. 21 22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 28 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 30 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 32 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33 POSSIBILITY OF SUCH DAMAGE. 34*/ 35 36:- module(random, 37 [ random/1, % -Float (0,1) 38 random_between/3, % +Low, +High, -Random 39 40 getrand/1, % -State 41 setrand/1, % +State 42 43 maybe/0, 44 maybe/1, % +P 45 maybe/2, % +K, +N 46 47 random_perm2/4, % A,B, X,Y 48 49 random_member/2, % -Element, +List 50 random_select/3, % ?Element, +List, -Rest 51 52 randseq/3, % +Size, +Max, -Set 53 randset/3, % +Size, +Max, -List 54 random_permutation/2, % ?List, ?Permutation 55 56 % deprecated interface 57 random/3 % +Low, +High, -Random 58 ]). 59:- use_module(library(pairs)). 60:- use_module(library(error)). 61:- use_module(library(lists)).
74check_gmp :- 75 current_arithmetic_function(random_float), 76 !. 77check_gmp :- 78 print_message(warning, random(no_gmp)). 79 80:- initialization check_gmp. 81 82 83 /******************************* 84 * PRIMITIVES * 85 *******************************/
95random(R) :-
96 R is random_float.
103random_between(L, U, R) :- 104 integer(L), integer(U), 105 !, 106 U >= L, 107 R is L+random((U+1)-L). 108random_between(L, U, _) :- 109 must_be(integer, L), 110 must_be(integer, U).
126random(L, U, R) :- 127 integer(L), integer(U), 128 !, 129 R is L+random(U-L). 130random(L, U, R) :- 131 number(L), number(U), 132 !, 133 R is L+((U-L)*random_float). 134random(L, U, _) :- 135 must_be(number, L), 136 must_be(number, U). 137 138 139 /******************************* 140 * STATE * 141 *******************************/
For compatibility reasons with older versions of this library,
setrand/1 also accepts a term rand(A,B,C)
, where A, B and C are
integers in the range 1..30,000. This argument is used to seed
the random generator. Deprecated.
164setrand(rand(A,B,C)) :- 165 !, 166 Seed is A<<30+B<<15+C, 167 set_random(seed(Seed)). 168setrand(State) :- 169 set_random(state(State)). 170 171:- if(current_predicate(random_property/1)). 172getrand(State) :- 173 random_property(state(State)). 174:- else. 175getrand(State) :- 176 existence_error(random_state, State). 177:- endif. 178 179 180 /******************************* 181 * MAYBE * 182 *******************************/
188maybe :-
189 random(2) =:= 0.
195maybe(P) :-
196 must_be(between(0.0,1.0), P),
197 random_float < P.
203maybe(K, N) :- 204 integer(K), integer(N), 205 between(0, N, K), 206 !, 207 random(N) < K. 208maybe(K, N) :- 209 must_be(nonneg, K), 210 must_be(nonneg, N), 211 domain_error(not_less_than_zero,N-K). 212 213 214 /******************************* 215 * PERMUTATION * 216 *******************************/
222random_perm2(A,B, X,Y) :- 223 ( maybe 224 -> X = A, Y = B 225 ; X = B, Y = A 226 ). 227 228 229 /******************************* 230 * SET AND LIST OPERATIONS * 231 *******************************/
240random_member(X, List) :-
241 must_be(list, List),
242 length(List, Len),
243 Len > 0,
244 N is random(Len),
245 nth0(N, List, X).
255random_select(X, List, Rest) :- 256 ( '$skip_list'(Len, List, Tail), 257 Tail == [] 258 -> true 259 ; '$skip_list'(RLen, Rest, Tail), 260 Tail == [] 261 -> Len is RLen+1 262 ), 263 !, 264 Len > 0, 265 N is random(Len), 266 nth0(N, List, X, Rest). 267random_select(_, List, Rest) :- 268 partial_list(List), partial_list(Rest), 269 instantiation_error(List+Rest). 270random_select(_, List, Rest) :- 271 must_be(list, List), 272 must_be(list, Rest).
?- randset(5, 5, S). S = [1, 2, 3, 4, 5]. (always) ?- randset(5, 20, S). S = [2, 7, 10, 19, 20].
290randset(K, N, S) :- 291 must_be(nonneg, K), 292 K =< N, 293 randset(K, N, [], S). 294 295randset(0, _, S, S) :- !. 296randset(K, N, Si, So) :- 297 random(N) < K, 298 !, 299 J is K-1, 300 M is N-1, 301 randset(J, M, [N|Si], So). 302randset(K, N, Si, So) :- 303 M is N-1, 304 randset(K, M, Si, So).
randseq(K, N, List) :- randset(K, N, Set), random_permutation(Set, List).
321randseq(K, N, S) :- 322 randseq(K, N, L, []), 323 keysort(L, R), 324 pairs_values(R, S). 325 326randseq(0, _, S, S) :- !. 327randseq(K, N, [Y-N|Si], So) :- 328 random(N) < K, 329 !, 330 random(Y), 331 J is K-1, 332 M is N-1, 333 randseq(J, M, Si, So). 334randseq(K, N, Si, So) :- 335 M is N-1, 336 randseq(K, M, Si, So).
347random_permutation(List1, List2) :- 348 is_list(List1), 349 !, 350 random_permutation_(List1, List2). 351random_permutation(List1, List2) :- 352 is_list(List2), 353 !, 354 random_permutation_(List2, List1). 355random_permutation(List1, List2) :- 356 partial_list(List1), partial_list(List2), 357 !, 358 instantiation_error(List1+List2). 359random_permutation(List1, List2) :- 360 must_be(list, List1), 361 must_be(list, List2). 362 363random_permutation_(List, RandomPermutation) :- 364 key_random(List, Keyed), 365 keysort(Keyed, Sorted), 366 pairs_values(Sorted, RandomPermutation). 367 368key_random([], []). 369key_random([H|T0], [K-H|T]) :- 370 random(K), 371 key_random(T0, T).
377partial_list(List) :- 378 '$skip_list'(_, List, Tail), 379 var(Tail). 380 381:- multifile 382 prolog:message//1. 383 384prologmessage(random(no_gmp)) --> 385 [ 'This version of SWI-Prolog is not compiled with GMP support.'-[], nl, 386 'Floating point random operations are not supported.'-[] 387 ]
Random numbers
This library is derived from the DEC10 library random. Later, the core random generator was moved to C. The current version uses the SWI-Prolog arithmetic functions to realise this library. These functions are based on the GMP library.
random(10)
*/