【问题标题】:How to shuffle dynamic facts in Prolog?如何在 Prolog 中打乱动态事实?
【发布时间】:2018-12-03 00:17:56
【问题描述】:

我在 Prolog 中有几个动态事实,我想打乱它们(以随机顺序重新排序)。 Prolog中有什么方法可以做到这一点吗?

:- dynamic max/3.
max(1,2,3).
max(1,5,6).
max(3,4,5).
max(2,2,5).

可能的随机顺序:

max(2,2,5).
max(1,2,3).
max(3,4,5).
max(1,5,6).

【问题讨论】:

  • 通常,如果您想对事实中的值重新排序,那么在 Prolog 中,您使用谓词在调用谓词时生成新值,而不是创建硬编码的事实。恕我直言,这比您寻求的更容易做到。如果允许使用谓词执行此操作,请在问题中注明,我相信您会很快得到答案。

标签: prolog swi-prolog


【解决方案1】:

正如您提到您正在使用 SWI-Prolog,一个可能的解决方案是使用其 nth_clause/3clause/3 内置谓词。这个想法是使用代理谓词访问谓词,在这种情况下是ramdom_max/3。我还假设您只有事实。

:- use_module(library(lists)).
:- use_module(library(random)).

ramdom_max(A, B, C) :-
    predicate_property(max(_,_,_), number_of_clauses(N)),
    numlist(1, N, List),
    random_permutation(List, Permutation),   
    member(Index, Permutation),
    nth_clause(max(_,_,_), Index, Ref),
    clause(max(A,B,C), _, Ref).

示例调用:

?- ramdom_max(A, B, C).
A = 1,
B = 2,
C = 3 ;
A = 3,
B = 4,
C = 5 ;
A = 1,
B = 5,
C = 6 ;
A = B, B = 2,
C = 5.

ramdom_max/3 谓词的每次调用都会为您提供不同的子句随机顺序,但仍会在回溯时枚举所有子句。

然而,这是一个计算成本相对较高的解决方案。但是由于max/3 是一个动态谓词,ramdom_max /3 子句主体中的第一个目标不能优化为只运行一次。让我们检查推理的数量:

% autoload the time/1 library predicate:
?- time(true).
% 3 inferences, 0.000 CPU in 0.000 seconds (60% CPU, 333333 Lips)
true.

?- time(ramdom_max(A, B, C)).
% 42 inferences, 0.000 CPU in 0.000 seconds (85% CPU, 913043 Lips)
A = 3,
B = 4,
C = 5 ;
% 6 inferences, 0.000 CPU in 0.000 seconds (69% CPU, 272727 Lips)
A = 1,
B = 2,
C = 3 ;
% 4 inferences, 0.000 CPU in 0.000 seconds (69% CPU, 222222 Lips)
A = 1,
B = 5,
C = 6 ;
% 6 inferences, 0.000 CPU in 0.000 seconds (70% CPU, 250000 Lips)
A = B, B = 2,
C = 5.

在使用findall/3 重新分级的 cmets 中,值得与 luker 的建议进行比较。一个可能的实现是:

ramdom_max(A, B, C) :-
    findall(max(A,B,C), max(A,B,C), Clauses),
    random_permutation(Clauses, Permutation),   
    member(max(A,B,C), Permutation).

定时通话:

?- time(ramdom_max(A, B, C)).
% 40 inferences, 0.000 CPU in 0.000 seconds (78% CPU, 930233 Lips)
A = 1,
B = 5,
C = 6 ;
% 2 inferences, 0.000 CPU in 0.000 seconds (50% CPU, 200000 Lips)
A = 1,
B = 2,
C = 3 ;
% 2 inferences, 0.000 CPU in 0.000 seconds (45% CPU, 250000 Lips)
A = B, B = 2,
C = 5 ;
% 4 inferences, 0.000 CPU in 0.000 seconds (62% CPU, 250000 Lips)
A = 3,
B = 4,
C = 5.

在这个非常有限测试中,性能大致相同。但它也是一种更简单、更便携的解决方案。然而,对您想要解决的问题多了解一些可能会获得更好的解决方案。

【讨论】:

    猜你喜欢
    • 2015-06-06
    • 2013-10-10
    • 1970-01-01
    • 2018-08-13
    • 1970-01-01
    • 2017-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多