Prolog - 用英语解释跟踪步骤

Prolog - Explain trace steps in English

plays(alice, leadguitar).
plays(noah, drums).
plays(mike, leadguitar).
plays(mike, drums).
plays(katie, baseguitar).
plays(drew, leadguitar).
plays(drew, baseguitar).

duetwith(Person1,Person2):- 
    plays(Person1,L),
    plays(Person2,L), 
    Person1 \= Person2.

我编写了一个名为组合的新规则,用于确定三个人是否可以使用鼓手、基础吉他和主音吉他进行组合。

combo(Person1,Person2,Person3):- 
    plays(Person1,X), 
    plays(Person2,Y), 
    plays(Person3,Z), 
    X \= Y, 
    Y \= Z, 
    X\=Z.

德鲁、爱丽丝和迈克可以组合吗?

combo(mike,alice,drew).

是的,所以答案是肯定的,他们可以组合。

我需要帮助来理解程序在序言中回答上述查询所采取的步骤。非常感谢任何有关步骤列表的帮助,这样我可以更深入地了解 Prolog 采取的每个步骤。

这是 Prolog 针对不同示例所采取的步骤列表的示例,只是为了让您了解我在寻找什么。

talkswith(bob,allen) 的情况下,引擎采取了以下步骤:

  1. 与(人 1,人 2)交谈:- 说话(Person1,L), 说话(Person2,L), Person1 \= Person2.

将每个出现的 Person1 替换为 bob 并将 Person2 替换为 allen 以获得

talkswith(bob,allen) :- 
    speaks(bob,L),
    speaks(allen,L),
    bob \= allen.
  1. 让我们看看是否可以找到使右侧为真的 L 值。从 speaks(bob,L). 开始 L 可以是什么?这是我们的事实:

    1. 会说(艾伦,俄语)。
    2. 会说(鲍勃,英语)。
    3. 会说(玛丽,俄语)。
    4. 会说(玛丽,英语)。
  2. 事实上1,第一个slot不是bob,所以不行。事实上 2,第一个槽位是 bob,所以让我们尝试 L = englishin speaks(allen,L), bob \= allen. Now we are asking speaks(allen,english), bob\= allen.

  3. 返回知识库。 speaks(allen,english) 是否符合事实?不是事实 1,不是事实 2,不是事实 3,不是事实 4。这失败了。
  4. 现在我们回到第 2 步。事实 2 没有解决,所以让我们试试事实 3。不,那不是鲍勃。事实 4 也不是鲍勃。我们找不到适用的 L 值,因此搜索失败。

replace every occurrence of Person1 with bob

Prolog 使用 syntactic unification which never does replacement. A free variable can only be bound once to a value. If it looks like a variable is being changed more than once, it is not. There can be many stack frames 并且可以为每个堆栈帧创建一组新变量。


Trace is somewhat helpful but I need to translate that into the form of the example above with the steps written out and explained in plain English.

对于这些事实

plays(alice, leadguitar).
plays(noah, drums).
plays(mike, leadguitar).
plays(mike, drums).
plays(katie, baseguitar).
plays(drew, leadguitar).
plays(drew, baseguitar).

和这个谓词

combo(Person1,Person2,Person3):- 
    plays(Person1,X), 
    plays(Person2,Y), 
    plays(Person3,Z), 
    X \= Y, 
    Y \= Z, 
    X\=Z.

和这个查询

combo(mike,alice,drew).

首先阅读 SWI-Prolog Debugging and Tracing Programs

运行 带跟踪的查询,启用统一端口并关闭。

?- visible(+unify).
true.

?- leash(-all).
true.

?- trace.
true.

[trace] ?- combo(mike,alice,drew).
   Call: (8) combo(mike, alice, drew)
   Unify: (8) combo(mike, alice, drew)
   Call: (9) plays(mike, _7040)
   Unify: (9) plays(mike, leadguitar)
   Exit: (9) plays(mike, leadguitar)
   Call: (9) plays(alice, _7040)
   Unify: (9) plays(alice, leadguitar)
   Exit: (9) plays(alice, leadguitar)
   Call: (9) plays(drew, _7040)
   Unify: (9) plays(drew, leadguitar)
   Exit: (9) plays(drew, leadguitar)
   Call: (9) leadguitar\=leadguitar
   Fail: (9) leadguitar\=leadguitar
   Redo: (9) plays(drew, _7040)
   Unify: (9) plays(drew, baseguitar)
   Exit: (9) plays(drew, baseguitar)
   Call: (9) leadguitar\=leadguitar
   Fail: (9) leadguitar\=leadguitar
   Redo: (9) plays(mike, _7040)
   Unify: (9) plays(mike, drums)
   Exit: (9) plays(mike, drums)
   Call: (9) plays(alice, _7040)
   Unify: (9) plays(alice, leadguitar)
   Exit: (9) plays(alice, leadguitar)
   Call: (9) plays(drew, _7040)
   Unify: (9) plays(drew, leadguitar)
   Exit: (9) plays(drew, leadguitar)
   Call: (9) drums\=leadguitar
   Exit: (9) drums\=leadguitar
   Call: (9) leadguitar\=leadguitar
   Fail: (9) leadguitar\=leadguitar
   Redo: (9) plays(drew, _7040)
   Unify: (9) plays(drew, baseguitar)
   Exit: (9) plays(drew, baseguitar)
   Call: (9) drums\=leadguitar
   Exit: (9) drums\=leadguitar
   Call: (9) leadguitar\=baseguitar
   Exit: (9) leadguitar\=baseguitar
   Call: (9) drums\=baseguitar
   Exit: (9) drums\=baseguitar
   Exit: (8) combo(mike, alice, drew)
true.

Call: (8) combo(mike, alice, drew)

Prolog 查找匹配查询的谓词。当 Prolog 查找谓词时,它按谓词名称搜索,在本例中为 combo,在本例中为元数,在本例中为 3,并且只找到一个带有一个子句的谓词。 Prolog 还按照谓词在源代码中出现的顺序搜索谓词。它还有更多内容(索引),但解释这个简单的查询不需要那么详细。


Unify: (8) combo(mike, alice, drew)

一旦 Prolog 根据谓词名称和元数找到 clause/fact,它就会检查子句或事实的查询和头部是否可以统一。

mikePerson1统一。 Person1 现在绑定到 mike
alicePerson2 统一。 Person2 现在绑定到 alice
drewPerson3 统一。 Person3 现在绑定到 drew


Call: (9) plays(mike, _7040)

如果前一条语句统一,则调用下一条语句。每个语句本身就是一个查询。因此 运行 查询 plays(mike,X). 作为独立查询与子句中的此语句相同。 plays/2 有很多事实,其中两个匹配 plays(mike,X). Prolog 使用它找到的第一个,但是因为有多个事实,所以做出了选择点。我们将调用这个特定的选择点plays(mike,X) - cp1,并在遇到相应的REDO时返回一个特定的选择点。


Unify: (9) plays(mike, leadguitar)

一旦 Prolog 根据谓词名称和元数找到 clause/fact,它就会检查子句的查询和头部是否可以统一。

playsplays
统一 mikemike
统一 _7040leadguitar 统一。 _7040 绑定到 leadguitar.


Exit: (9) plays(mike, leadguitar)

这只是完成 Prolog 的端口 box model。它显示了 Call: (9) plays(mike, _7040) 的结果。此声明没有统一。


Call: (9) plays(alice, _7040)
Unify: (9) plays(alice, leadguitar)
Exit: (9) plays(alice, leadguitar)

alice 的模式相同。爱丽丝只有一个事实,所以没有为她生成选择点。


Call: (9) plays(drew, _7040)
Unify: (9) plays(drew, leadguitar)
Exit: (9) plays(drew, leadguitar)

drew 的模式相同。由于 drew 有两个关于 plays(drew,X). 的事实,因此生成了一个选择点。 plays(drew,X) - cp1


Call: (9) leadguitar\=leadguitar

这是第四条语句 X \= Y,其中 X 绑定到 leadguitarY 绑定到 leadguitar


Fail: (9) leadguitar\=leadguitar

由于 leadguitarleadguitar 没有区别,此查询失败。失败后 Prolog 返回到最后一个选择点(重做)并尝试找到另一个解决方案。


Redo: (9) plays(drew, _7040)

记住最后创建的选择点,plays(drew,X) - cp1。由于某些事情失败了,因此尝试使用另一种可能的解决方案进行查询。由于 plays(drew,X) 的第一个选择点因 Xleadguitar 而失败,因此使用了第二个事实,plays(drew,baseguitar).


Unify: (9) plays(drew, baseguitar)

只是表明正在使用 plays(drew,X) 的第二个事实。


Exit: (9) plays(drew, baseguitar)

显示Redo: (9) plays(drew, _7040)的结果。


剩下的只是 copy/paste 已经完成的工作,以及更改语句、变量、绑定值等


这个 类似,但有更多细节。


值得注意的是这个问题

I write a new rule called combo that determines whether or not three people can make a combo with a drummer, a base guitar, and a lead guitar.

此查询未回答

combo(Person1,Person2,Person3):- 
    plays(Person1,X), 
    plays(Person2,Y), 
    plays(Person3,Z), 
    X \= Y, 
    Y \= Z, 
    X\=Z.

因为如果加上这些事实

plays(alice, flute).
plays(noah, cello).
plays(mike, trumpet).

这个查询

?- combo(alice,noah,mike).
true ;
true .

说正确,但 alicenoahmike 没有演奏主音吉他、鼓和底吉他。