Prolog-用英语解释跟踪步骤

时间:2018-11-25 18:18:27

标签: prolog trace unification

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. talkswith(Person1,Person2):-     说话(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. 说(allen,俄语)。
    2. 说(鲍勃,英语)。
    3. 说(玛丽,俄语)。
    4. 说(玛丽,英语)。
  2. 实际上,第一个插槽不是鲍勃,因此无法使用。实际上,第2个插槽是bob,因此我们在L = english中尝试speaks(allen,L), bob \= allen.,现在我们要询问speaks(allen,english), bob\= allen.

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

1 个答案:

答案 0 :(得分:1)

  

用bob替换Person1的每次出现

Prolog使用syntactic unification,它永远不会替代。 free variable只能与一个值绑定一次。如果看起来变量多次被更改,则不会。可以有许多stack frames,并且对于每个堆栈帧,可以创建一组新的变量。


  

跟踪对您有所帮助,但是我需要将其翻译成上面示例的形式,并用简单的英语写出并解释步骤。

对于这些事实

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)和arity(在这种情况下为3)中进行搜索,并且仅找到带有一个子句的一个谓词。 Prolog还按照谓词在源代码中出现的顺序搜索谓词。 (索引)还有更多功能,但是不需要此级别的详细信息来解释此简单查询。


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

一旦Prolog找到了基于谓词名称和Arity的子句/事实,它将检查查询和该子句或事实的头部是否可以统一。

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发现了基于谓词名称和Arity的子句/事实,它将检查查询和子句的头部是否可以统一。

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 \= YX绑定到leadguitarY绑定到leadguitar


Fail: (9) leadguitar\=leadguitar

由于leadguitarleadguitar相同,因此此查询失败。失败后,Prolog会回到最后一个选择点(Redo),并尝试寻找其他解决方案。


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)的结果。


其余的只是复制/粘贴已完成的操作,并更改语句,变量,绑定值等。


answer类似,但有更多细节。


值得注意的是这个问题

  

我写了一条称为“组合”的新规则,该规则确定三个人是否可以用鼓手,基础吉他和主音吉他进行组合。

此查询未回答

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没有演奏主音,鼓和基音。