164 lines
3.8 KiB
Perl
164 lines
3.8 KiB
Perl
|
/* $Id$
|
||
|
|
||
|
Part of SWI-Prolog
|
||
|
|
||
|
Author: R.A. O'Keefe, V.S. Costa, L. Damas, Jan Wielemaker
|
||
|
E-mail: wielemak@science.uva.nl
|
||
|
WWW: http://www.swi-prolog.org
|
||
|
Copyright (C): Universidade do Porto, University of Amsterdam
|
||
|
*/
|
||
|
|
||
|
/*************************************************************************
|
||
|
* *
|
||
|
* YAP Prolog *
|
||
|
* *
|
||
|
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
||
|
* *
|
||
|
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
||
|
* *
|
||
|
**************************************************************************
|
||
|
* *
|
||
|
* File: random.yap *
|
||
|
* Last rev: 5/12/99 *
|
||
|
* mods: *
|
||
|
* comments: Random operations *
|
||
|
* *
|
||
|
*************************************************************************/
|
||
|
|
||
|
% original code from RA O'Keefe.
|
||
|
|
||
|
% This is algorithm AS 183 from Applied Statistics. I also have a C
|
||
|
% version. It is really very good. It is straightforward to make a
|
||
|
% version which yields 15-bit random integers using only integer
|
||
|
% arithmetic.
|
||
|
|
||
|
:- module(random,
|
||
|
[ random/1, % -float
|
||
|
random/3, % +Low, +High, -Random
|
||
|
randseq/3, % +Size, +Max, -Set
|
||
|
randset/3, % +Size, +Max, -List
|
||
|
getrand/1, % -State
|
||
|
setrand/1 % +State
|
||
|
]).
|
||
|
:- use_module(library(pairs)).
|
||
|
|
||
|
:- use_foreign_library(foreign(random)).
|
||
|
|
||
|
/** <module> Random numbers
|
||
|
|
||
|
Random number generator developed as part of the DEC10 library. The
|
||
|
algorithm is based on AS 183 from Applied Statistics. Originally
|
||
|
implemented ib Prolog by Richard O'Keeke. The SWI-Prolog versions is a
|
||
|
translation of a C-version for YAP based on the orginal source.
|
||
|
|
||
|
@copyright DEC10 version: Public domain, YAP: Artistic
|
||
|
@author R.A. O'Keefe, V.S. Costa, L. Damas, Jan Wielemaker
|
||
|
@see Built-in function random/1: A is random(10)
|
||
|
*/
|
||
|
|
||
|
|
||
|
|
||
|
/*******************************
|
||
|
* C PRIMITIVES *
|
||
|
*******************************/
|
||
|
|
||
|
%% random(-R:float) is det.
|
||
|
%
|
||
|
% Binds R to a new random number in [0.0,1.0).
|
||
|
%
|
||
|
% @see setrand/1, getrand/1.
|
||
|
|
||
|
%% setrand(+State:rand(A,B,C)) is det.
|
||
|
%% getrand(+State:rand(A,B,C)) is det.
|
||
|
%
|
||
|
% Query/set the state of the random library. A, B and C are
|
||
|
% integers in the range 1..30,000. The initial state is predefined
|
||
|
% and can be extracted using getrand/1:
|
||
|
%
|
||
|
% ==
|
||
|
% ?- getrand(X).
|
||
|
% X = rand(27314, 9213, 17773).
|
||
|
% ==
|
||
|
%
|
||
|
% @see random/1.
|
||
|
|
||
|
|
||
|
/*******************************
|
||
|
* PROLOG *
|
||
|
*******************************/
|
||
|
|
||
|
|
||
|
%% random(+L:int, +U:int, -R:int) is det.
|
||
|
%% random(+L:float, +U:float, -R:float) is det.
|
||
|
%
|
||
|
% Binds R to a random number in [L,U). If L and U are both
|
||
|
% integers, R is an integer, Otherwise, R is a float. Note that U
|
||
|
% will *never* be generated.
|
||
|
%
|
||
|
% @bug The state is only 48-bits. This is insufficient for
|
||
|
% generating uniformely distributed integers in a very
|
||
|
% large domain.
|
||
|
|
||
|
random(L, U, R) :-
|
||
|
integer(L), integer(U), !,
|
||
|
random(X),
|
||
|
R is L+floor((U-L)*X).
|
||
|
random(L, U, R) :-
|
||
|
number(L), number(U), !,
|
||
|
random(X),
|
||
|
R is L+((U-L)*X).
|
||
|
|
||
|
%% randset(+K:int, +N:int, -S:list(int)) is det.
|
||
|
%
|
||
|
% S is a sorted list of K integers in the range 1..N.
|
||
|
%
|
||
|
% @see randseq/3.
|
||
|
|
||
|
|
||
|
randset(K, N, S) :-
|
||
|
K >= 0,
|
||
|
K =< N,
|
||
|
randset(K, N, [], S).
|
||
|
|
||
|
|
||
|
randset(0, _, S, S) :- !.
|
||
|
randset(K, N, Si, So) :-
|
||
|
random(X),
|
||
|
X * N < K, !,
|
||
|
J is K-1,
|
||
|
M is N-1,
|
||
|
randset(J, M, [N|Si], So).
|
||
|
randset(K, N, Si, So) :-
|
||
|
M is N-1,
|
||
|
randset(K, M, Si, So).
|
||
|
|
||
|
|
||
|
%% randseq(+K:int, +N:int, -S:list(int)) is det.
|
||
|
%
|
||
|
% S is a list of K integers in the range 1..N. The order is
|
||
|
% random.
|
||
|
%
|
||
|
% @see randset/3.
|
||
|
|
||
|
|
||
|
randseq(K, N, S) :-
|
||
|
randseq(K, N, L, []),
|
||
|
keysort(L, R),
|
||
|
pairs_values(R, S).
|
||
|
|
||
|
randseq(0, _, S, S) :- !.
|
||
|
randseq(K, N, [Y-N|Si], So) :-
|
||
|
random(X),
|
||
|
X * N < K, !,
|
||
|
random(Y),
|
||
|
J is K-1,
|
||
|
M is N-1,
|
||
|
randseq(J, M, Si, So).
|
||
|
randseq(K, N, Si, So) :-
|
||
|
M is N-1,
|
||
|
randseq(K, M, Si, So).
|
||
|
|
||
|
|
||
|
|
||
|
|