从您在评论中所说的内容来看,我的印象是,对于您的用例来说,一个更重要的问题是:
解决方案可以是created以随机顺序?
(这是因为你说你不能把它们全部创造出来,然后choose随机的。)
To create鲍里斯暗示了一个好方法:简单地重新排序析取!
例如,在您显示的情况下:
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.
请注意,这种将随机性融入代码的方法是impure:现在您的程序中存在隐式全局状态,并且您无法再轻松地重现在描述此类程序的测试用例等时所需的结果。保存溶液逻辑纯粹性 /questions/tagged/logical-purity必须进入这种状态explicit,例如通过携带随机seed作为参数之一,以便每次运行都是完全可重现的。
请注意,像这样的连词和/或目标的重新排序仅适用于pure and 单调的Prolog 的子集,因此请确保使用声明性功能,例如限制条件安全地交换目标,并增加代码的通用性!