1 | % (c) 2009-2021 Lehrstuhl fuer Softwaretechnik und Programmiersprachen, | |
2 | % Heinrich Heine Universitaet Duesseldorf | |
3 | % This software is licenced under EPL 1.0 (http://www.eclipse.org/org/documents/epl-v10.html) | |
4 | ||
5 | :- module(random_permutations, [get_num_bits/3, | |
6 | get_masks/3, | |
7 | random_permutation_element/10, | |
8 | init_random_permutations/0, | |
9 | ||
10 | enum_fd_random/3 % high-level predicate | |
11 | ]). | |
12 | ||
13 | :- use_module(probsrc(module_information),[module_info/2]). | |
14 | :- module_info(group,cbc). | |
15 | :- module_info(description,'This module provides on-the-fly construction of random permutations of intervals.'). | |
16 | ||
17 | foreign_resource(random_permutations,[get_num_bits,draw_index]). | |
18 | foreign(get_num_bits, c, get_num_bits(+integer,-integer,-integer)). | |
19 | foreign(draw_index, c, draw_index(+integer,+integer,+integer,+integer,+integer,+integer,+integer,+integer,-integer,-integer)). | |
20 | ||
21 | :- dynamic is_initialised/0. | |
22 | ||
23 | :- use_module(probsrc(pathes_lib),[safe_load_foreign_resource/2]). | |
24 | ||
25 | init_random_permutations :- is_initialised,!. | |
26 | init_random_permutations :- | |
27 | safe_load_foreign_resource(random_permutations,random_permutations), | |
28 | assertz(is_initialised). | |
29 | ||
30 | ||
31 | get_masks(HalfNumBits,LeftMask,RightMask) :- | |
32 | RightMask is (1 << HalfNumBits) - 1, | |
33 | LeftMask is RightMask << HalfNumBits. | |
34 | ||
35 | random_permutation_element(Index,MaxIndex,From,To,Seed,NumBits,LeftMask,RightMask,RandomElement,NextIndex) :- | |
36 | draw_index(Index,MaxIndex,Seed,NumBits,LeftMask,RightMask,From,To,DrawnElement,NextIndex), | |
37 | % working on a 4^x long interval. thus, we might pick a number that is too large | |
38 | % if this happens, we just pick a new one | |
39 | % to avoid context switching overhead, this is now done inside the C code | |
40 | RandomElement is DrawnElement + From. | |
41 | ||
42 | ||
43 | :- use_module(library(random),[random/1]). | |
44 | % enumerate Prolog/FD variable between low and up in random order | |
45 | enum_fd_random(Var,Low,Up) :- | |
46 | init_random_permutations, | |
47 | IntervalLength is Up - Low + 1, | |
48 | get_num_bits(IntervalLength,MaxIdx,NumBits), | |
49 | get_masks(NumBits,LeftMask,RightMask), | |
50 | % the seed relies on the random predicate, not on now/1, thus prob can be made deterministic by setting a central random seed | |
51 | random(TempSeed), | |
52 | Seed is floor(TempSeed * 10000), | |
53 | enum_fd_random_aux(Var,0,MaxIdx,Low,Up,Seed,NumBits,LeftMask,RightMask). | |
54 | ||
55 | enum_fd_random_aux(Var,CurIdx,MaxIdx,From,To,Seed,NumBits,LeftMask,RightMask) :- | |
56 | random_permutation_element(CurIdx,MaxIdx,From,To,Seed,NumBits,LeftMask,RightMask,Drawn,NextIdx), | |
57 | (Var=Drawn ; enum_fd_random_aux(Var,NextIdx,MaxIdx,From,To,Seed,NumBits,LeftMask,RightMask)). | |
58 | ||
59 | ||
60 | % ------------------- | |
61 | % Testing predicates | |
62 | % ------------------- | |
63 | % unused at the moment: | |
64 | %:- public shuffle/2. | |
65 | %:- use_module(library(system)). | |
66 | %shuffle(From,To) :- | |
67 | % init_random_permutations, | |
68 | % IntervalLength is To - From + 1, | |
69 | % get_num_bits(IntervalLength,MaxIndex,NumBits), | |
70 | % get_masks(NumBits,LeftMask,RightMask), | |
71 | % now(Seed), | |
72 | % shuffle(From,0,To,MaxIndex,Seed,NumBits,LeftMask,RightMask). | |
73 | %shuffle(From,CurIdx,To,MaxIndex,Seed,NumBits,LeftMask,RightMask) :- | |
74 | % random_permutation_element(CurIdx,MaxIndex,From,To,Seed,NumBits,LeftMask,RightMask,Drawn,NextIdx), | |
75 | % format('Drawing index ~w resulted in ~w~n',[CurIdx,Drawn]), | |
76 | % shuffle(From,NextIdx,To,MaxIndex,Seed,NumBits,LeftMask,RightMask). | |
77 | %shuffle(_,_,_,_,_,_,_,_). |