swi prolog:连词和剪切

时间:2018-08-01 23:59:47

标签: prolog prolog-cut

我正在尝试在Java中实现序言解释器。我试图弄清楚','运算符应该如何工作。我试图实现这样的等效规则:

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

我正在使用以下用例c1,c2和c3来测试我基于逻辑的实现。它们都应该输出“ 1”和“ false”。但是,我注意到最后一个规则(c3)会显示“ 12”和“ false”。我在SWI序言中也进行了相同的测试,在那里,最后一条规则输出了“ 12”和“假”。

那么我的假设是否正确,即逗号运算符可以被编码为','(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)))).

1 个答案:

答案 0 :(得分:2)

您对,作为二元函数的性质是正确的,但是对and的转换尚未解释如何解释连接词。让我们看一下一般的Prolog规则:

head :-  % we disregard variables at the moment
  goal1,
  goal2,
  goal3.

fact. % a fact is a rule without a body

这可以理解为“ 目标隐含着目标”或“ 要获得目标,我们就需要推导每个目标”。但是目标1本身可能就是一条规则,因此我们需要某种类型的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(咖啡)
  • 准备(食物)

幸运的是,make(coffee)是事实,因此我们可以将其从清单中删除。

  • 准备(食物)

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

  • 制作(牛角包)

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

  • 制作(牛角包)

好的,那里没有其他选择,让我们再回头看

  • 准备(食物)

并将其扩展到

  • make(scrambled_eggs)。

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

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

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

现在我们无法撤消饮料的选择,因此我们最终将获得咖啡,炒鸡蛋或咖啡和羊角面包:

?- breakfast.
true ;
true.

因此,合取词告诉我们接下来要导出哪些内容,剪切告诉我们停止回溯。在这两种情况下,我们都需要一个数据结构,该数据结构记录我们已经做出和已经做出的选择的最后顺序。这必须是一个序列,因为我们需要记住作为饮料和食物可以选择的其他东西。在剪切的情况下,我们可以忘记上一次剪切之后序列中的所有内容,即剪切会切断选择点序列。因此,我们致力于这一特定选择。

我希望对实施有所帮助。