2012-11-15 70 views
4

如何执行rule1成功iff rule2返回两个或更多结果如果返回两个或多个结果,则判断成功

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

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

+1

应该很容易使用[findall/3]进行编码(http://stackoverflow.com/questions/1468150/how-do-i-find-all-solutions-to-a-goal-in-prolog)。 – ShiDoiSi

回答

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. 

编辑这里是一个更有效的方式,使用SWI-Prolog的设施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). 

用这个定义,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. 

与call_nth从here

从实际角度来看,我认为nb_setval(vs nb_setarg)遭受了全局和局部变量之间的通常折衷。即对于某些任务可能会很轻易地知道接受条件的限制。如果这不是必需的,nb_setarg它更干净。

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

+1

您对全局变量的使用不正确。你在查询中产生意外的替换('X = 2')。 – false

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/2defined in another SO-answer

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

+2

感谢您解释解决方案和答案的区别。 – CapelliC

+2

@chac:这个区别是[tag:clpfd]的关键! – false