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)
,引擎采取了以下步骤:
在
talkswith(Person1,Person2):- 说话(Person1,L), 说话(Person2,L), Person1 \ = Person2。
将每次出现的Person1
替换为bob
,将Person2
替换为allen
以获得
talkswith(bob,allen) :-
speaks(bob,L),
speaks(allen,L),
bob \= allen.
让我们看看是否可以找到使右侧为真的L值。以speaks(bob,L).
开头L可以是什么?这是我们的事实:
实际上,第一个插槽不是鲍勃,因此无法使用。实际上,第2个插槽是bob,因此我们在L = english
中尝试speaks(allen,L), bob \= allen.
,现在我们要询问speaks(allen,english), bob\= allen.
speaks(allen,english)
是否符合事实?不是事实1,不是事实2,不是事实3,不是事实4。这会失败。答案 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的子句/事实,它将检查查询和该子句或事实的头部是否可以统一。
mike
与Person1
统一。现在Person1
已绑定到mike
。
alice
与Person2
统一。现在Person2
已绑定到alice
。
drew
与Person3
统一。 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的子句/事实,它将检查查询和子句的头部是否可以统一。
plays
与plays
统一
mike
与mike
统一
_7040
与leadguitar
统一。 _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
绑定到leadguitar
且Y
绑定到leadguitar
Fail: (9) leadguitar\=leadguitar
由于leadguitar
与leadguitar
相同,因此此查询失败。失败后,Prolog会回到最后一个选择点(Redo),并尝试寻找其他解决方案。
Redo: (9) plays(drew, _7040)
记住创建的最后一个选择点plays(drew,X) - cp1
。由于失败,将尝试使用其他可能的解决方案查询。由于plays(drew,X)
的第一个选择点因X
为leadguitar
而失败,因此使用了第二个事实,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 .
说的是正确的,但是alice
,noah
和mike
没有演奏主音,鼓和基音。