swi-prolog:连接和切割



我正在尝试用java实现一个prolog解释器。我正试图弄清楚","运算符应该如何工作。我试图实现一个类似的规则:

and(A, B) :- A, B.

我正在使用测试用例c1、c2和c3基于下面的逻辑库测试我的实现。它们都应该输出"1"one_answers"false"。然而,我注意到最后一条规则(c3(打印的是"12"one_answers"false"。我在SWI-prolog中运行了相同的测试,最后一条规则也输出了"12"one_answers"false"。

那么,我的假设是否不正确,即逗号运算符可以编码为','(X, Y) :- X, Y.

n(1).
n(2).
and(X, Y) :- X, Y. % this is used to compare with the built in operator ','
c1 :-     n(X),     write(X),     =(1, X),     !, fail.
c2 :- ','(n(X), ','(write(X), ','(=(1, X), ','(!, fail)))).
c3 :- and(n(X), and(write(X), and(=(1, X), and(!, fail)))).

您对,作为二进制函数的性质是正确的,但对and的翻译还没有解释如何解释连词。让我们来看看Prolog的一个通用规则:

head :-  % we disregard variables at the moment
goal1,
goal2,
goal3.
fact. % a fact is a rule without a body

这可以理解为">目标意味着头部",或者"<em]为了推导头部,我们需要推导每个目标>。"。但goal1本身可能是一个规则,因此我们需要某种TODO列表(通常作为堆栈实现,但现在确切的行为无关紧要(。我们从TODO列表上的查询开始。如果列表中的某个元素是事实,我们可以将其删除。要删除规则,我们需要派生所有目标,以便用目标替换列表中的头。让我们以一个例子来看:

make(coffee).
make(tea).
make(orange_juice).
make(croissant).
make(scrambled_eggs).
prepare(beverage) :-
make(coffee).
prepare(beverage) :-
make(tea).
prepare(beverage) :-
make(orange_juice).
prepare(food) :-
make(croissant).
prepare(food) :-
make(scrambled_eggs).
breakfast :-
prepare(beverage),
prepare(food).

当我们查询早餐时,我们得到:

?- breakfast.
true ;
true ;
true ;
true ;
true ;
true.

不知道早餐吃什么有点无聊,但有六种吃法。那么我们是如何到达那里的呢?

我们从待办事项清单上的早餐开始:

  • 早餐

唯一适合的规则头是最后一个,所以我们将TODO更改为:

  • 准备(饮料(
  • 准备(食物(

我们现在有多条规则告诉我们要做什么饮料,让我们选择第一条:

  • 制作(咖啡(
  • 准备(食物(

幸运的是,make(coffee)是事实,所以我们可以将其从列表中划掉。

  • 准备(食物(

同样,我们可以准备食物:

  • 制作(羊角面包(

因为有一个相应的事实,我们已经做好了早餐(输出true(。但我们做了一些选择:我们可以准备茶或橙汁代替咖啡,也可以做炒鸡蛋代替羊角面包。这意味着我们可以回溯:

  • 制作(羊角面包(

好的,没有选择,让我们进一步回到

  • 准备(食物(

并将其扩展到

  • make(scrambled_eggs(

这再次是事实(true再次:((。当我们进一步回溯时,我们得到了制作饮料和食物的所有组合,并为所有6种组合打印true

剪切可防止回溯到放置之前的某个点。让我们修改规则如下:

breakfast :-
prepare(beverage),
!,
prepare(food).

现在我们无法取消饮料的选择,所以我们最终会选择咖啡和炒鸡蛋,或者咖啡和羊角面包:

?- breakfast.
true ;
true.

所以连合告诉我们下一步要衍生哪些东西,而切告诉我们停止回溯。在这两种情况下,我们都需要一个数据结构来记录我们已经做出的最后一系列选择。这一定是一个序列,因为我们需要记住我们还可以选择什么作为饮料和食物。在切割的情况下,我们可以忘记上一次切割后序列中的所有内容,即切割切割了选择点序列。因此,我们致力于这一特定的选择。

我希望这对实施有所帮助。

最新更新