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