6

我是 prolog 的新手,正在尝试如何让它在找到一个答案后停止查询。我正在使用这段代码:

member1(L,[L|_]).                    
member1(L,[_|RS]) :- member1(L,RS),!.      

结果是:

| ?- member1(3,[3,2,3]).

true ? a

yes

我不知道如何让 Prolog 停止打印“true”?而是打印“是”。我试过使用 if/else 构造和格式函数,但它仍然打印“true?”。有任何想法吗?

4

2 回答 2

3

你剪错地方了。在基本条件之后进行切割,即“一旦满足基本条件,就不再回溯”:

member1(L,[L|_]) :- !.                   
member1(L,[_|RS]) :- member1(L,RS).    

If-then 对我有用,也许你实现它不同?(在 swi-prolog 上)

member1(X,[Y|RS]) :-
    ( X = Y         -> true
    ; member1(X,RS) -> true
    ; false
    ) .

Swi 也有谓词once/1

编辑以解决 false 指出的错误。

于 2013-11-24T22:01:32.757 回答
2

从您显示的输出中,我假设您使用的是 GNU Prolog。但是,首先要说一句重要的话:

您放置的切口没有按您的意愿切割!事实上,它甚至不阻止只有一个答案。这是证据:

| ?- member1(X,[1,2,3]).

X = 1 ? ;

X = 2

yes

所以你仍然有两个答案。根据经验:在递归目标之后进行切割经常会做一些意想不到的事情。

如果您坚持要确切地得到第一个答案,只需说once(member(X,[1,2,3])). 这once/1实际上也是一个削减,但完全是伪装的。它被驯服只做一件事。是的,您也可以将切入到递归规则中,但对于初学者来说,最好将其留到后面的课程中。

在这一切的背后还有另一点不太明显:如果 GNU Prolog 的顶层 shell 看到一个开放的替代方案(行话:choicepoint),它会要求您提供进一步的解决方案。因此,当 GNU 要求您提供更多信息时,它知道某些部分尚未探索,但不能保证实际上还有另一个答案:

?- member(1-X,[1-a,2-b,3-c]). 

X = a ? ;

no

在这里,顶层看到一个开放的选择点,因此询问您是否要进一步探索查询。唉,这个搜索是在脉络中......

于 2013-11-25T01:19:09.237 回答