Prolog swi序言:连接和剪切

Prolog swi序言:连接和剪切,prolog,prolog-cut,Prolog,Prolog Cut,我试图用java实现一个prolog解释器。我正在试图弄清楚操作员应该如何工作。我尝试实施一个类似的规则,如下所示: and(A, B) :- A, B. 我正在使用测试用例c1、c2和c3,基于下面的逻辑基础测试我的实现。它们都应该输出“1”和“false”。然而,我注意到最后一条规则(c3)打印“12”和“false”。我在SWI prolog中运行了相同的测试,最后一条规则输出“12”和“false” 那么,我的假设是否不正确,逗号运算符可以编码为,'(X,Y):-X,Y. n(1).

我试图用java实现一个prolog解释器。我正在试图弄清楚操作员应该如何工作。我尝试实施一个类似的规则,如下所示:

and(A, B) :- A, B.
我正在使用测试用例c1、c2和c3,基于下面的逻辑基础测试我的实现。它们都应该输出“1”和“false”。然而,我注意到最后一条规则(c3)打印“12”和“false”。我在SWI prolog中运行了相同的测试,最后一条规则输出“12”和“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)))).

关于
作为二进制函数的性质,您是正确的,但是对
的翻译还没有解释如何解释连词。让我们看一看一般的序言规则:

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

fact. % a fact is a rule without a body
这可以理解为“目标意味着头部”,或者“为了获得头部,我们需要获得每个目标”。但目标1本身可能是一个规则,因此我们需要某种类型的待办事项列表(通常作为堆栈实现,但确切的行为现在并不重要)。我们从待办事项列表上的查询开始。如果列表中的某个元素是事实,我们可以将其删除。要删除一条规则,我们需要导出所有目标,以便用目标替换列表中的标题。让我们用一个例子来看一下:

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
)。但我们做了一些选择:我们可以准备茶或橙汁而不是咖啡,我们可以做炒蛋而不是牛角面包。这意味着我们可以回溯:

  • 制作(牛角面包)
好吧,这里没有选择,让我们进一步回顾:

  • 准备(食物)
并将此扩展到

  • 做(炒鸡蛋)
这也是一个事实(
true
再次:))。当我们进一步回溯时,我们得到了制作饮料和食品的所有组合,并打印出所有6种组合的
true

切口可防止在放置点之前回溯到该点。让我们修改规则如下:

breakfast :-
    prepare(beverage),
    !,
    prepare(food).
现在我们无法取消饮料选择,因此我们将以咖啡和炒蛋或咖啡和牛角面包结束:

?- breakfast.
true ;
true.
所以连词告诉我们下一步要导出哪些东西,切割告诉我们停止回溯。在这两种情况下,我们都需要一个数据结构来记录我们已经做出的最后一系列选择。它必须是一个序列,因为我们需要记住我们可以选择的饮料和食物。在切割的情况下,我们可以忘记最后一次切割之后的序列中的所有内容,即切割切割选择点序列。因此,我们致力于这一特殊选择


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

cut在调用它的谓词子句的上下文中应用prune回溯。因此,
和(!,fail)
将失败并在调用它的位置返回。鉴于,
,”(!,fail)
,与
!,相同!,失败
将不会回溯。因此,
和(!,fail)
的行为与
不同!,失败
。您必须编写
和(!,失败)
@Louger看这更多的是关于cut的语义,而不是and的?@DanielLyons是的,绝对是。@Louger,谢谢你的回答。我需要仔细考虑一下。我发现很难理解的是c1显然等同于c2,但c2并不等同于c3。“,”是一个运算符,而“和/2”是一个规则,这一事实似乎是不同的?在Prolog中,有一个称为
write\u canonical(X)
的谓词,它允许您按照Prolog在规范中看到的方式编写术语。尝试
编写规范((A,B))