8

我有一个使用约束用 Sicstus Prolog 编写的程序。我的目标是使用 labeling/2 和其他一些方法来获得我的变量的随机实例化。

例子:

X #> 2, Y #= 2*X, Z #<10

如果我使用

List = [X,Y,Z],
labeling([], List)

获得的第一个结果将是 X = Y = Z = 0。您认为返回 X、Y 和 Z 的随机值集的最佳方法是什么?

4

4 回答 4

6

我对最近 SICStus 版本中的标签选项了解不多,但是使用 SWI-Prolog 的 library(clpfd),有选项 random_variable(Seed) 和 random_value(Seed),例如,您可以将它们与 labeling([random_variable (10),random_value(10)], 列表)。也许您可以让 SICStus 的作者整合类似的选项?

于 2012-01-01T17:17:17.610 回答
3

在 sicstus 中,这是通过自定义选择变量/值来完成的。

在您的情况下,只需执行以下操作:

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).

请参阅https://sicstus.sics.se/sicstus/docs/4.0.4/html/sicstus/Enumeration-Predicates.html中的值(枚举)。

希望能帮助到你 ;)

于 2016-12-18T18:45:36.647 回答
0

您可以使用 all_different([X,Y,Z]) 来获得不同的值,但是,在 Sicstus 中使用随机种子可能会很棘手,您可能需要定义一个函数来更改种子或再次启动随机函数。检查以下 www.sics.se/sicstus/docs/3.7.1/html/sicstus_23.html

于 2012-07-06T14:14:07.393 回答
0

我选择了 Jekejeke Prolog,用于与 CLP(FD) 相关的新谓词 random_labeling/1,它隐含地从知识库中获取随机数生成器,可以通过 sys_random Prolog 标志访问和修改。

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

我正在计划进一步的谓词 random_labeling/2。但它不需要种子,而是 Java java.util.Random 实例。这比种子更通用。但我想将 API 更改为 labeling/2 和一些选项将是最好的方法。

编辑 29.12.2018:我现在做笔记,因为我想采用 indomain/2 是个好主意,目前我已经实现了 random_indomain/1,并从此实现了 random_label/1。另请参阅此处:

来自 ECLiPSe Prolog random 的indomain/2:以随机顺序尝试枚举。在回溯时,先前测试的值被删除。此方法使用 random/1 创建随机数,使用前使用 seed/1 以使结果可重现。 http://eclipseclp.org/doc/bips/lib/gfd_search/indomain-2.html

于 2018-12-29T17:22:11.390 回答