如果返回两个或多个结果,则谓词成功

时间:2012-11-15 02:58:27

标签: prolog

如果成功rule1 iff rule2返回两个或更多结果

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

如何计算结果,然后设置何时成功的最小值?

2 个答案:

答案 0 :(得分:5)

  

如何计算结果,然后设置最小值?

目前尚不清楚结果的含义。所以我会做一些猜测。结果可能是:

解决方案。例如,目标member(X,[1,2,1])有两个解决方案。不是三个。在这种情况下,请考虑使用setof/3或类似的谓词。无论如何,在解决您遇到的问题之前,您应首先了解setof/3

答案。目标member(X,[1,2,1])有三个答案。目标member(X,[Y,Z])有两个答案,但无数的解决方案。

因此,如果您想确保至少有一定数量的答案,请定义:

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

call_nth/2 defined in another SO-answer

请注意,其他SO-answers不正确:它们要么不终止,要么产生意外的实例化。

答案 1 :(得分:2)

您可以使用库(aggregate)来计算解决方案

:- use_module(library(aggregate)).

% it's useful to declare this for modularization
:- meta_predicate at_least(0, +).

at_least(Predicate, Minimum) :-
      aggregate_all(count, Predicate, N),
      N >= Minimum.

示例:

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

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

编辑这是一种更有效的方法,使用global variables

的SWI-Prolog工具
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 ).

根据这个定义,P被称为只是 N次。 (我引入了一个显示它返回的服务谓词m / 2)

m(X, L) :- member(X, L), writeln(x:X).

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

编辑会计@false评论,我试过

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

来自here的call_nth。

从实际的角度来看,我认为nb_setval(vs nb_setarg)在全局变量和局部变量之间经常进行权衡。即对于某些任务可以轻易地知道接受条件的限制是什么。如果不需要,nb_setarg会更干净。

底线:更好的方法是使用call_nth,双重否定的'技巧'解决了过度的变量实例化。