在Prolog中,可以按随机顺序选择解决方案吗?

时间:2017-01-01 05:15:03

标签: prolog

如果我有以下内容:

a(X) :- X = 1; X = 2; X = 3; X = 4.

我可以按确定的顺序生成解决方案:

?- a(X).
X = 1 ;
X = 2 ;
X = 3 ;
X = 4.

是否有任何方法要求系统以非确定性,随机顺序生成解决方案?例如:

?- a(X).
X = 4 ;
X = 1 ;
X = 3 ;
X = 2.

我知道我可以找到所有解决方案然后随机选择一个(findall(X, a(X), Y), random_member(Z, Y).),但在我的情况下这太贵了。

可能更清楚的例子:

p(X,Y,Z) :-
  (X = a; X = b; X = c; X = d),   % (D1)
  (Y = a; Y = b; Y = c),          % (D2)
  (Z = a; Z = b; Z = c; Z = d).   % (D3)

确定性时,使用X = d, Y = c, Z = d生成解决方案?- p(X,Y,Z).将始终通过之前的47个解决方案(4 * 3 * 4 = 48)。但是,如果以非确定性顺序选择析取,系统可能会选择D1处的X = d,D2处的Y = c,D3处的Z = d,将其生成为第一个解决方案。

这用于受约束的AI生成的内容,因此在现实世界的用例中还有更多的变量。

1 个答案:

答案 0 :(得分:0)

根据您在评论中的说法,我的印象是,对您的用例更重要的问题是:

  

可以随机顺序创建解决方案吗?

(这是因为你说你不能全部创建它们,然后选择一个随机的。)

要以不同的顺序创建它们,Boris已经暗示了一个好方法:只需重新排序析取

例如,在您显示的情况下:

p(X, Y, Z) :-
  (X = a; X = b; X = c; X = d),   % (D1)
  (Y = a; Y = b; Y = c),          % (D2)
  (Z = a; Z = b; Z = c; Z = d).   % (D3)

如果分离(例如:(X = c ; X = b ; etc.)和每个片段可能以不同的顺序产生解决方案),您可以(自动)通过交换订单来创建此片段的声明等效版本。

但是,首次将其重写为等效版本可能更容易:

p(X, Y, Z) :-
    member(X, [a,b,c,d]),
    member(Y, [a,b,c]),
    member(Z, [a,b,c,d]).

通过这种方式, shuffle 列表更容易,并使用随机列表生成解决方案。

例如,您可以将其更改为:

p(X, Y, Z) :-
    random_member(X, [a,b,c,d]),
    random_member(Y, [a,b,c]),
    random_member(Z, [a,b,c,d]).

random_member(X, Ls0) :-
    random_permutation(Ls0, Ls),
    member(X, Ls).

现在,您将得到如下答案:

?- p(X, Y, Z).
X = d,
Y = Z, Z = b ;
X = Z, Z = d,
Y = b ;
X = d,
Y = b,
Z = c ;
etc.

请注意,这种将随机性合并到代码中的方法是不纯:程序中现在存在隐式全局状态,并且在描述测试用例等时无法再轻松地再现所需的结果。对于这样的程序。保留 的解决方案必须使此状态显式,例如将随机种子作为参数之一,每次运行都是完全可重现的。

请注意,重新排序此类连词和/或目标仅适用于Prolog的单调子集,因此请确保使用等声明性功能约束以安全地交换目标,并增加代码的通用性!