首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >什么时候用跟踪/0中的新变量调用重做端口?

什么时候用跟踪/0中的新变量调用重做端口?
EN

Stack Overflow用户
提问于 2017-07-29 17:16:48
回答 2查看 294关注 0票数 1

在实现Prolog中的冒险游戏期间,我想知道在回溯过程中何时用新变量调用重做端口,以及何时用相同的变量调用重做端口?

例如,我有以下知识库:

代码语言:javascript
运行
复制
location(desk,office).
location(apple,kitchen).
location(flashlight,desk).
location('washing machine',cellar).
location(nani,'washing machine').
location(broccoli,kitchen).
location(crackers,kitchen).
location(computer,office).

door(office,hall).
door(kitchen,office).
door(hall,'dining room').
door(kitchen,cellar).
door('dining room',kitchen).

在跟踪查询?-(location(X,Y),door(kitchen,Y)).时,我得到以下内容:

代码语言:javascript
运行
复制
   Call: (9) location(_7998, _8000) ? creep
   Exit: (9) location(desk, office) ? creep
   Call: (9) door(kitchen, office) ? creep
   Exit: (9) door(kitchen, office) ? creep
X = desk,
Y = office ;
   Redo: (9) door(kitchen, office) ? creep      <==== 1
   Fail: (9) door(kitchen, office) ? creep
   Redo: (9) location(_7998, _8000) ? creep
   Exit: (9) location(apple, kitchen) ? creep
   Call: (9) door(kitchen, kitchen) ? creep
   Fail: (9) door(kitchen, kitchen) ? creep
   Redo: (9) location(_7998, _8000) ? creep
   Exit: (9) location(flashlight, desk) ? creep
   Call: (9) door(kitchen, desk) ? creep
   Fail: (9) door(kitchen, desk) ? creep
   Redo: (9) location(_7998, _8000) ? creep
   Exit: (9) location('washing machine', cellar) ? creep
   Call: (9) door(kitchen, cellar) ? creep
   Exit: (9) door(kitchen, cellar) ? creep
X = 'washing machine',
Y = cellar ;
   Redo: (9) location(_7998, _8000) ? creep    <==== 2
   Exit: (9) location(nani, 'washing machine') ? creep
   Call: (9) door(kitchen, 'washing machine') ? creep
   Fail: (9) door(kitchen, 'washing machine') ? creep
   Redo: (9) location(_7998, _8000) ? creep
   Exit: (9) location(broccoli, kitchen) ? creep
代码语言:javascript
运行
复制
   Call: (9) door(kitchen, kitchen) ? creep
   Fail: (9) door(kitchen, kitchen) ? creep
   Redo: (9) location(_7998, _8000) ? creep
   Exit: (9) location(crackers, kitchen) ? creep
   Call: (9) door(kitchen, kitchen) ? creep
   Fail: (9) door(kitchen, kitchen) ? creep
   Redo: (9) location(_7998, _8000) ? creep
   Exit: (9) location(computer, office) ? creep
   Call: (9) door(kitchen, office) ? creep
   Exit: (9) door(kitchen, office) ? creep
X = computer,
Y = office ;
   Redo: (9) door(kitchen, office) ? creep    <==== 3
   Fail: (9) door(kitchen, office) ? creep
false.

我理解变量的绑定是如何工作的,但我不明白为什么Prolog返回。

Redo: (9) door(kitchen, office) ? creep <==== 1

Redo: (9) door(kitchen, office) ? creep <==== 3

在找到第一个解决方案(最后一个解决方案相同)之后,

在第二个解决方案之后,它立即寻找X和Y的新绑定。

Redo: (9) location(_7998, _8000) ? creep <==== 2

为什么它不立即在第一个也是最后一个解决方案之后继续寻找X和Y的新绑定,而不是诉诸于

Redo: (9) door(kitchen, office) ? creep <==== 3

(但还是失败了)?

(我发现了一个类似的问题这里,但不幸的是,我的声誉不允许我在那里发表评论,我认为这个问题与我的Prolog版本无关(就像我在SWI和GNUProlog中尝试过的那样)

提前感谢您提供任何清晰的信息。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-07-29 19:36:22

这个答案使用。

当第一次使用跟踪时,第一件可以提供帮助的事情是使所有的端口都是可见。默认情况下,统一端口不可见,但可以用

代码语言:javascript
运行
复制
?- visible(+unify).

现在,由于这是一个很短的运行查询,所以不必为每个端口按空格键,我们可以使用

代码语言:javascript
运行
复制
?- leash(-call).
?- leash(-exit).
?- leash(-redo).
?- leash(-fail).

现在,如果打开跟踪并运行查询

代码语言:javascript
运行
复制
?- trace.
[trace] ?- (location(X,Y),door(kitchen,Y)).

您将不必按空格键期望得到答案。

这样做会回来的

代码语言:javascript
运行
复制
   Call: (9) location(_9632, _9634)
   Unify: (9) location(desk, office)
   Exit: (9) location(desk, office)
   Call: (9) door(kitchen, office)
   Unify: (9) door(kitchen, office)
   Exit: (9) door(kitchen, office)
X = desk,
Y = office ;
   Redo: (9) door(kitchen, office)
   Fail: (9) door(kitchen, office)
   Redo: (9) location(_9632, _9634)
   Unify: (9) location(apple, kitchen)
   Exit: (9) location(apple, kitchen)
   Call: (9) door(kitchen, kitchen)
   Fail: (9) door(kitchen, kitchen)
   Redo: (9) location(_9632, _9634)
   Unify: (9) location(flashlight, desk)
   Exit: (9) location(flashlight, desk)
   Call: (9) door(kitchen, desk)
   Fail: (9) door(kitchen, desk)
   Redo: (9) location(_9632, _9634)
   Unify: (9) location('washing machine', cellar)
   Exit: (9) location('washing machine', cellar)
   Call: (9) door(kitchen, cellar)
   Unify: (9) door(kitchen, cellar)
   Exit: (9) door(kitchen, cellar)
X = 'washing machine',
Y = cellar ;
   Redo: (9) location(_9632, _9634)
   Unify: (9) location(nani, 'washing machine')
   Exit: (9) location(nani, 'washing machine')
   Call: (9) door(kitchen, 'washing machine')
   Fail: (9) door(kitchen, 'washing machine')
   Redo: (9) location(_9632, _9634)
   Unify: (9) location(broccoli, kitchen)
   Exit: (9) location(broccoli, kitchen)
   Call: (9) door(kitchen, kitchen)
   Fail: (9) door(kitchen, kitchen)
   Redo: (9) location(_9632, _9634)
   Unify: (9) location(crackers, kitchen)
   Exit: (9) location(crackers, kitchen)
   Call: (9) door(kitchen, kitchen)
   Fail: (9) door(kitchen, kitchen)
   Redo: (9) location(_9632, _9634)
   Unify: (9) location(computer, office)
   Exit: (9) location(computer, office)
   Call: (9) door(kitchen, office)
   Unify: (9) door(kitchen, office)
   Exit: (9) door(kitchen, office)
X = computer,
Y = office ;
   Redo: (9) door(kitchen, office)
   Fail: (9) door(kitchen, office)
false.

现在,统一端口是可见的。

由于这是一个如此简短的查询,我将评论跟踪的重要行,然后回答您的问题。

代码语言:javascript
运行
复制
   % location fact 1: location(desk, office) -------------------------
   % First predicate of query - location(X,Y)

   % The location facts are matched in the order of the source code
   % Since the code is looking for location(X,Y)
   % it matches location fact 1: location(desk, office)
   % Since there are more location facts like location(X, Y),
   % e.g.
   %   location(apple,kitchen).
   %   location(flashlight,desk).
   %   location('washing machine',cellar).
   %   location(nani,'washing machine').
   %   location(broccoli,kitchen).
   %   location(crackers,kitchen).
   %   location(computer,office).
   % a choice point is generated
   % choice point: location 1
   Call: (9) location(_9632, _9634)

   % Unifies with first location fact.
   % X binds with desk
   % Y binds with office
   Unify: (9) location(desk, office)

   Exit: (9) location(desk, office)

   % Second predicate of query - door(kitchen,Y)).
   % Y is bound with office
   % The door facts are matched in the order of the source code
   % Since the code is only looking for door(kitchen,office)
   % it matches door fact 2: door(kitchen,office)
   % Since there are more door facts like door(kitchen,Y),
   % e.g.
   %    door(kitchen,cellar).
   % a choice point is generated
   % choice point: door 1
   Call: (9) door(kitchen, office)

   % Since there is a door(kitchen, office) fact
   % unify with second predicate
   Unify: (9) door(kitchen, office)
   Exit: (9) door(kitchen, office)
   % No more predicates in the query so return result.
X = desk,
Y = office ;

   % Remember choice point: door 1
   % Use the second predicate
   % on the remaining door facts like door(kitchen,Y)
   % e.g.
   %    door(kitchen,cellar).
   Redo: (9) door(kitchen, office)

   % There are no more door facts that unify with door(kitchen, office)
   % so fail.
   Fail: (9) door(kitchen, office)

   % Since the second predicate failed,
   % go back to the first predicate location(X,Y)
   % location fact 2: location(apple, kitchen) -----------------------

   % Remember choice point: location 1
   % Use the first predicate
   % on the remaining location facts like location(X,Y)
   % e.g.
   %   location(apple,kitchen).
   %   location(flashlight,desk).
   %   location('washing machine',cellar).
   %   location(nani,'washing machine').
   %   location(broccoli,kitchen).
   %   location(crackers,kitchen).
   %   location(computer,office).
   Redo: (9) location(_9632, _9634)

   % The second fact unifies with the first predicate location(X,Y)
   % X binds with apple
   % Y binds with kitchen
   Unify: (9) location(apple, kitchen)
   Exit: (9) location(apple, kitchen)

   % Second predicate of query - door(kitchen,Y)).
   % Y is bound with kitchen
   % The door facts are matched in the order of the source code
   % Since the code is only looking for door(kitchen,kitchen)
   % it matches none of the door facts
   % and since it checked all of the door facts
   % no choice point was generated.
   Call: (9) door(kitchen, kitchen)

   % There is no door(kitchen, kitchen) fact so fail.
   Fail: (9) door(kitchen, kitchen)

   % location fact 3: location(flashlight, desk) ---------------------
   % Remember choice point: location 1
   % Use the first predicate
   % on the remaining location facts like location(X,Y)
   % e.g.
   %   location(flashlight,desk).
   %   location('washing machine',cellar).
   %   location(nani,'washing machine').
   %   location(broccoli,kitchen).
   %   location(crackers,kitchen).
   %   location(computer,office).
   Redo: (9) location(_9632, _9634)
   Unify: (9) location(flashlight, desk)
   Exit: (9) location(flashlight, desk)
   Call: (9) door(kitchen, desk)
   Fail: (9) door(kitchen, desk)

   % Since the second predicate failed,
   % go back to the first predicate location(X,Y)
   % location fact 4: location('washing machine', cellar)  -----------
   % Remember choice point: location 1
   % Use the first predicate
   % on the remaining location facts like location(X,Y)
   % e.g.
   %   location('washing machine',cellar).
   %   location(nani,'washing machine').
   %   location(broccoli,kitchen).
   %   location(crackers,kitchen).
   %   location(computer,office).
   Redo: (9) location(_9632, _9634)

   % The forth fact unifies with the first predicate location(X,Y)
   % X binds with 'washing machine'
   % Y binds with cellar
   Unify: (9) location('washing machine', cellar)

   Exit: (9) location('washing machine', cellar)

   % Second predicate of query - door(kitchen,Y)).
   % Y is bound with cellar
   % The door facts are matched in the order of the source code
   % Since the code is only looking for door(kitchen,cellar)
   % it matches door fact 4: door(kitchen,cellar)
   % Since there are NO more door facts like door(kitchen,Y),
   % NO choice point is generated
   Call: (9) door(kitchen, cellar)

   % There is a door(kitchen, cellar) fact so unify.
   Unify: (9) door(kitchen, cellar)
   Exit: (9) door(kitchen, cellar)
   % No more predicates in the query so return result.
X = 'washing machine',
Y = cellar ;

   % location fact 5: location(nani, 'washing machine') --------------
   % Remember choice point: location 1
   % Use the first predicate
   % on the remaining location facts like location(X,Y)
   % e.g.
   %   location(nani,'washing machine').
   %   location(broccoli,kitchen).
   %   location(crackers,kitchen).
   %   location(computer,office).
   Redo: (9) location(_9632, _9634)
   Unify: (9) location(nani, 'washing machine')
   Exit: (9) location(nani, 'washing machine')
   Call: (9) door(kitchen, 'washing machine')
   Fail: (9) door(kitchen, 'washing machine')

   % location fact 6: location(broccoli, kitchen) --------------------
   % Remember choice point: location 1
   % Use the first predicate
   % on the remaining location facts like location(X,Y)
   % e.g.
   %   location(broccoli,kitchen).
   %   location(crackers,kitchen).
   %   location(computer,office).
   Redo: (9) location(_9632, _9634)
   Unify: (9) location(broccoli, kitchen)
   Exit: (9) location(broccoli, kitchen)
   Call: (9) door(kitchen, kitchen)
   Fail: (9) door(kitchen, kitchen)

   % location fact 7: location(crackers, kitchen) --------------------
   % Remember choice point: location 1
   % Use the first predicate
   % on the remaining location facts like location(X,Y)
   % e.g.
   %   location(crackers,kitchen).
   %   location(computer,office).
   Redo: (9) location(_9632, _9634)
   Unify: (9) location(crackers, kitchen)
   Exit: (9) location(crackers, kitchen)
   Call: (9) door(kitchen, kitchen)
   Fail: (9) door(kitchen, kitchen)

   % Since the second predicate failed,
   % go back to the first predicate location(X,Y)
   % location fact 8: location(computer, office) ---------------------
   % Remember choice point: location 1
   % Use the first predicate
   % on the remaining location facts like location(X,Y)
   % e.g.
   %   location(computer,office).
   Redo: (9) location(_9632, _9634)

   % The last fact unifies with the first predicate location(X,Y)
   % X binds with computer
   % Y binds with office
   Unify: (9) location(computer, office)
   Exit: (9) location(computer, office)

   % Second predicate of query - door(kitchen,Y)).
   % Y is bound with office
   % The door facts are matched in the order of the source code
   % Since the code is only looking for door(kitchen,office)
   % it matches door fact 2: door(kitchen,office)
   % Since there are more door facts like door(kitchen,Y),
   % e.g.
   %    door(kitchen,cellar).
   % a choice point is generated
   % choice point: door 2
   Call: (9) door(kitchen, office)

   % Since there is a door(kitchen, office) fact
   % unify with second predicate
   Unify: (9) door(kitchen, office)
   Exit: (9) door(kitchen, office)
   % No more predicates in the query so return result.
X = computer,
Y = office ;
   % Remember choice point: door 2
   % Use the second predicate
   % on the remaining door facts like door(kitchen,Y)
   % e.g.
   %    door(kitchen,cellar).
   Redo: (9) door(kitchen, office)

   % There are no more door facts that unify with door(kitchen, office)
   % so fail.
   Fail: (9) door(kitchen, office)

   % There are no more location facts so end the query.
false.

补充

当我创建答案时,它是在一个文本编辑器中,它可以为Prolog代码做语法突出显示,并且为了帮助我保持正确,我打开了三个窗格进行比较。一个窗格有位置和门的规则。一个窗格有注释,第三个窗格有类似的注释。当我向下移动代码时,我继续更新第三个窗格中的注释,以匹配第二个窗格中的类似注释,同时根据第一个窗格中的事实进行检查。我注意到这一点,因为这可能是一个更好的方式来理解评论,而不是阅读他们从这个答案张贴。

编辑器是Visual Studio代码,为了突出显示Prolog,安装了Prolog扩展

票数 2
EN

Stack Overflow用户

发布于 2017-07-29 17:53:21

这只是一个评论张贴作为一个答复,因为它有一个图片。

如果使用图形调试器,您可以看到何时创建了选择点。

代码语言:javascript
运行
复制
?- gtrace.
true.

[trace] ?- (location(X,Y),door(kitchen,Y)).

在调试器的下面图像中,我用绿色矩形突出显示了选择点。

若要退出顶级跟踪模式,请输入nodebug

代码语言:javascript
运行
复制
[trace] ?- nodebug.
true.

?- 

注意:是选择点导致使用重做端口。

注意:调试prolog的另一种方法是通过使用失效切片。还可以阅读带有故障切片的问题加标

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45391973

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档