Prolog: Random Labeling
-
11-04-2021 - |
Question
I have a program written in Sicstus Prolog using constraints. My goal is to use labeling/2 and some other method to obtain a random instantiation of my variables.
Example:
X #> 2, Y #= 2*X, Z #<10
If I use
List = [X,Y,Z],
labeling([], List)
The first result obtained will be X = Y = Z = 0. How do you think is the best way to return a random set of values for X, Y and Z?
La solution
I do not know much about the labeling options in recent SICStus versions, but with library(clpfd) of SWI-Prolog, there are the options random_variable(Seed) and random_value(Seed), you can use them for example with labeling([random_variable(10),random_value(10)], List). Maybe you can get the authors of SICStus to integrate similar options?
Autres conseils
In sicstus, this is done with a custom selection of variables / values.
In your case, just do:
labeling([value(mySelValores)], List)
mySelValores(Var, _Rest, BB, BB1) :-
fd_set(Var, Set),
select_best_value(Set, Value),
(
first_bound(BB, BB1), Var #= Value
;
later_bound(BB, BB1), Var #\= Value
).
select_best_value(Set, BestValue):-
fdset_to_list(Set, Lista),
length(Lista, Len),
random(0, Len, RandomIndex),
nth0(RandomIndex, Lista, BestValue).
See value(Enum) in https://sicstus.sics.se/sicstus/docs/4.0.4/html/sicstus/Enumeration-Predicates.html.
Hope it helps ;)
I have opted in Jekejeke Prolog, for a new predicate random_labeling/1 in connection with CLP(FD) that takes implicitly the random number generator from the knowledge base that can be accessed and modified via the sys_random Prolog flag.
Jekejeke Prolog 3, Runtime Library 1.3.4
(c) 1985-2019, XLOG Technologies GmbH, Switzerland
?- use_module(library(finite/clpfd)).
% 20 consults and 0 unloads in 944 ms.
Yes
?- use_module(library(basic/random)).
% 0 consults and 0 unloads in 0 ms.
Yes
?- random_new(111,R), set_prolog_flag(sys_random,R),
X in 0..5, Y #= X*X, random_label([X,Y]),
write(X-Y), nl, fail; true.
4-16
3-9
5-25
1-1
2-4
0-0
Yes
?- random_new(111,R), set_prolog_flag(sys_random,R),
X in 0..5, Y #= X*X, random_label([X,Y]),
write(X-Y), nl, fail; true.
4-16
3-9
5-25
1-1
2-4
0-0
I am planning a further predicate random_labeling/2. But it would not take a seed, but instead a Java java.util.Random instance. This is more versatile than a seed. But I guess changing the API to labeling/2 and some options would be the best way to go.
Edit 29.12.2018: I will now take notes, since I guess its a good idea to adopt indomain/2, currently I have implemented random_indomain/1, and from this implemented random_label/1. See also here:
indomain/2 from ECLiPSe Prolog random: Try the enumeration in a random order. On backtracking, the previously tested value is removed. This method uses random/1 to create random numbers, use seed/1 before to make results reproducible. http://eclipseclp.org/doc/bips/lib/gfd_search/indomain-2.html
you can use all_different([X,Y,Z]) in order to get different values however, working with random seed in Sicstus could be tricky and you may need to define a function to change the seed or start the random function again. check below www.sics.se/sicstus/docs/3.7.1/html/sicstus_23.html