Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
434 views
in Technique[技术] by (71.8m points)

aggregating predicates in SWI-Prolog

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

First clue is to findall, accumulate to a list and return the length of the list.

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

(permutation/2 is only a dummy placeholder demonstrating that there are many results and that it's bad way to compute the count)

Obviously, with real data, there will be a stack overflow.

?- countAllStuff( X ).
ERROR: Out of global stack

Then, I'm trying to replace findall with setof, to no avail.

At last, I've found the [aggregate][1] (clickable) family of predicates, and trying to use aggregate/3 and aggregate/4:

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

It's all wrong, I think. I need to get something like this:

?- aggregate(count, permutation([1,2,3,4], X), Y ).
Y = 24 .
  1. What am I doing wrong?

  2. How can I declare a predicate to conpute the right answer? [1]: http://www.swi-prolog.org/pldoc/doc/home/vnc/prolog/lib/swipl/library/aggregate.pl

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Use an existentially quantified variable, as you would with setof:

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...