A predicate that succeeds if two or more results are returned

How to implement rule1 , which succeeds if if rule2 returns two or more results?

 rule1(X) :- rule2(X, _). 

How can I count the results and then set the minimum value for successful completion?

+4
source share
2 answers

How can I count the results and then set the minimum value when it is true?

It is unclear what you mean by the results. Therefore, I will make some guesses. The result could be:

Decision. For example, the target member(X,[1,2,1]) has two solutions. Not three. In this case, consider using either setof/3 or a similar predicate. In any case, you must first understand setof/3 before solving the problem that you have.

Answer. The goal of member(X,[1,2,1]) consists of three answers. The target member(X,[Y,Z]) has two answers, but an infinite number of solutions.

So, if you want to make sure that there are at least a certain number of answers, define:

  at_least (Goal, N): -
    \ + \ + call_nth (Goal, N).

with call_nth/2 defined in another SO response .

Note that the other SO answers are incorrect: they either do not complete or do not create unexpected instances.

+5
source

you can use the library ( aggregate ) to count decisions

 :- use_module(library(aggregate)). % it useful to declare this for modularization :- meta_predicate at_least(0, +). at_least(Predicate, Minimum) :- aggregate_all(count, Predicate, N), N >= Minimum. 

Example:

 ?- at_least(member(_,[1,2,3]),3). true. ?- at_least(member(_,[1,2,3]),4). false. 

edit here is a more efficient way using SWI-Prolog tools for global variables

 at_least(P, N) :- nb_setval(at_least, 0), P, nb_getval(at_least, C), S is C + 1, ( S >= N, ! ; nb_setval(at_least, S), fail ). 

with this definition, P is called simply N times. (I present the m / 2 service predicate that displays what it returns)

 m(X, L) :- member(X, L), writeln(x:X). ?- at_least(m(X,[1,2,3]),2). x:1 x:2 X = 2. 

edit , given @false comment, I tried

  ?- call_nth(m(X,[1,2,3]),2). x:1 x:2 X = 2 ; x:3 false. 

with a call to nth from here .

From a practical point of view, I think nb_setval (vs nb_setarg ) suffers from the usual tradeoffs between global and local variables. That is, for some task, one could easily find out that the limit hit in order to accept the condition. If this is not required, nb_setarg will be cleaner.

Bottom line: the best way to do this, obviously, would be to use call_nth, with a "double negation" trick that decides non-standard instance creation.

+2
source

Source: https://habr.com/ru/post/1446122/


All Articles