在swi-prolog中汇总/ 3

ДМИ*_*КОВ 10 prolog swi-prolog

我需要统计所有这些X,some_predicate(X)而且真的有很多这样的X.最好的方法是什么?

第一个线索是找到所有,累积到列表并返回它的长度.

countAllStuff( X ) :-
    findall( Y
           , permutation( [1,2,3,4,5,6,7,8,9,10], Y )
           , List
           ),
    length( List, X ).
Run Code Online (Sandbox Code Playgroud)

(permutation/2仅显示存在许多变体的示例,并且收集所有变量的方法很糟糕)

显然,我有堆栈溢出.

?- countAllStuff( X ).
ERROR: Out of global stack
Run Code Online (Sandbox Code Playgroud)

不是,我试图取代findallsetof并没有什么变化.

最后,我创建了aggregate(可点击的)谓词并尝试使用它.

?- aggregate(count, permutation([1,2,3,4], X), Y ).
X = [1, 2, 3, 4],
Y = 1 .

?- aggregate(count, [1,2,3,4], permutation([1,2,3,4], X), Y ).
X = [1, 2, 3, 4],
Y = 1 ;
X = [1, 2, 4, 3],
Y = 1 ;
Run Code Online (Sandbox Code Playgroud)

我想,这都是错的.我更喜欢这样的东西

?- aggregate(count, permutation([1,2,3,4], X), Y ).
Y = 24 .
Run Code Online (Sandbox Code Playgroud)

1)我做错了什么?

2)如何声明谓词以获得正确的答案?

Fre*_*Foo 10

使用存在量化变量,就像使用setof:

?- aggregate(count, X^permutation([1,2,3,4], X), N).
N = 24.
Run Code Online (Sandbox Code Playgroud)

  • @ garm0nboz1a:`X ^`的意思是"存在`X`",所以整个公式意味着"计算"排列([1,2,3,4],X)`成功的方式的数量**`X`并将该号码称为'N`." (5认同)
  • 在这种情况下 X^permutation 是什么? (2认同)

Cap*_*liC 7

在 SWI-Prolog 中有一个更高效的版本,它也避免锁定全局存储。因此,只需使用 nb_setval 和 nb_getval 即可获得至少 3 倍的性能(更多关于多线程)。就在不久前,另一个问题是关于计算解的问题。作为聚合的基础,它是学习 Prolog 时明显的停止点。为了评估我们使用这些语义等效的单线程调用获得的效率增益:

count_solutions(Goal, N) :-
assert(count_solutions_store(0)),
repeat,
(   call(Goal),
    retract(count_solutions_store(SoFar)),
    Updated is SoFar + 1,
    assert(count_solutions_store(Updated)),
    fail
;   retract(count_solutions_store(N))
), !.
:- dynamic count_solutions_store/1.

% no declaration required here
count_solutions_nb(Goal, N) :-
    nb_setval(count_solutions_store, 0),
    repeat,
    (   call(Goal),
        nb_getval(count_solutions_store, SoFar),
        Updated is SoFar + 1,
        nb_setval(count_solutions_store, Updated),
        fail
    ;   nb_getval(count_solutions_store, N)
    ), !.

parent(jane,dick).
parent(michael,dick).
parent(michael,asd).

numberofchildren(Parent, N) :-
    count_solutions_nb(parent(Parent, _), N).

many_solutions :-
    between(1, 500000, _).

time_iso :-
    time(count_solutions(many_solutions, N)),
    write(N), nl.

time_swi :-
    time(count_solutions_nb(many_solutions, N)),
    writeln(N).
Run Code Online (Sandbox Code Playgroud)

在我的系统上,我得到

?- [count_sol].
% count_sol compiled 0,00 sec, 244 bytes
true.

?- time_iso.
tim% 1,000,006 inferences, 2,805 CPU in 2,805 seconds (100% CPU, 356510 Lips)
500000
true.

?- time_swi.
% 2,000,010 inferences, 0,768 CPU in 0,768 seconds (100% CPU, 2603693 Lips)
500000
true.
Run Code Online (Sandbox Code Playgroud)

  • @j4nbur53:是的,count、sum、min、max 的 *aggregate_all* 变体使用 nb_setval (2认同)

Kaa*_*rel 5

还有aggregate_all/3

?- aggregate_all(count, permutation([1, 2, 3, 4], _), Total).
Total = 24.
Run Code Online (Sandbox Code Playgroud)

但是,就运行时和堆栈溢出而言,它似乎与您的findall+length解决方案同样好:

?- N is 10^7, time(aggregate_all(count, between(1, N, _), Total)).
% 10,000,022 inferences, 5.075 CPU in 5.089 seconds (100% CPU, 1970306 Lips)
N = Total, Total = 10000000.

?- N is 10^7, time((findall(X, between(1, N, _), L), length(L, Total))).
% 10,000,013 inferences, 4.489 CPU in 4.501 seconds (100% CPU, 2227879 Lips)
N = 10000000,
L = [_G30000569, _G30000566, _G30000545|...],
Total = 10000000.

?- N is 10^8, aggregate_all(count, between(1, N, _), Total).
ERROR: Out of global stack

?- N is 10^8, findall(X, between(1, N, _), L), length(L, Total).
ERROR: Out of global stack
Run Code Online (Sandbox Code Playgroud)

您可以使用assert/计算解决方案retract,这很慢,但确实避免了“堆栈外”问题:

?- assert(counter(0)), N is 10^8, between(1, N, _),
   retract(counter(C)), C1 is C + 1, assert(counter(C1)), fail
   ; retract(counter(C)).
C = 100000000.
Run Code Online (Sandbox Code Playgroud)