gpt4 book ai didi

prolog - swi 序言 : conjunction and cut

转载 作者:行者123 更新时间:2023-12-03 20:54:01 25 4
gpt4 key购买 nike

我正在尝试在 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)))).

最佳答案

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

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

fact. % a fact is a rule without a body

这可以被理解为“目标意味着头部”,或者“为了推导我们需要推导每个目标的头部”。但是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.

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

我们从待办事项 list 上的早餐开始:
  • 早餐

  • 唯一适合的规则头是最后一个,因此我们将 TODO 更改为:
  • 准备(饮料)
  • 准备(食物)

  • 我们现在有多个规则告诉我们要制作什么饮料,让我们选择第一个:
  • 制作(咖啡)
  • 准备(食物)

  • 幸运的是, make(coffee)是事实,因此我们可以将其从列表中划掉。
  • 准备(食物)

  • 同样,我们可以准备食物:
  • 制作(羊角面包)

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

  • 好的,那里没有选择,让我们更进一步:
  • 准备(食物)

  • 并将其扩展为
  • 制作(炒鸡蛋)。

  • 这又是一个事实( true 又是:))。当我们进一步回溯时,我们得到制作饮料和食物的所有组合并打印 true对于所有 6 个。

    切割可防止回溯到放置之前的点。让我们修改规则如下:
    breakfast :-
    prepare(beverage),
    !,
    prepare(food).

    现在我们无法撤消饮料选择,所以我们最终会得到咖啡和炒鸡蛋或咖啡和羊角面包:
    ?- breakfast.
    true ;
    true.

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

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

    关于prolog - swi 序言 : conjunction and cut,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51643790/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com