在实现Prolog中的冒险游戏期间,我想知道在回溯过程中何时用新变量调用重做端口,以及何时用相同的变量调用重做端口?
例如,我有以下知识库:
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)).时,我得到以下内容:
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 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中尝试过的那样)
提前感谢您提供任何清晰的信息。
发布于 2017-07-29 19:36:22
这个答案使用。
当第一次使用跟踪时,第一件可以提供帮助的事情是使所有的端口都是可见。默认情况下,统一端口不可见,但可以用
?- visible(+unify).现在,由于这是一个很短的运行查询,所以不必为每个端口按空格键,我们可以使用
?- leash(-call).
?- leash(-exit).
?- leash(-redo).
?- leash(-fail).现在,如果打开跟踪并运行查询
?- trace.
[trace] ?- (location(X,Y),door(kitchen,Y)).您将不必按空格键期望得到答案。
这样做会回来的
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.现在,统一端口是可见的。
由于这是一个如此简短的查询,我将评论跟踪的重要行,然后回答您的问题。
% 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扩展。

https://stackoverflow.com/questions/45391973
复制相似问题