aggregate/3 in swi-prolog

前端 未结 4 634
滥情空心
滥情空心 2021-01-11 16:05

I need to count all X, that some_predicate(X) and there really a lot of such X. What is the best way to do that?

First clue is

4条回答
  •  太阳男子
    2021-01-11 16:41

    There is also aggregate_all/3:

    ?- aggregate_all(count, permutation([1, 2, 3, 4], _), Total).
    Total = 24.
    

    However, as far as runtime and stack overflows are concerned it seems to perform equally well to your findall+length solution:

    ?- 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
    

    You can count the solutions using assert/retract, this is quite slow but does avoid the "out of stack" problem:

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

提交回复
热议问题