我在Prolog中跟踪函数时遇到问题。

我在Prolog中跟踪函数时遇到问题。,prolog,trace,Prolog,Trace,一般来说,我对Prolog和计算机编程都是新手。现在,我已经完成了学习Prolog的练习!我一直都过得很好,但偶尔,当我遇到困难时,我会尝试使用跟踪功能一行一行地跟踪程序,看看它是如何工作的,或者出了什么问题,但我无法理解跟踪列出的内容。我会举个例子 其中一个练习是用谓词纵横字谜/6填充纵横字谜网格。这些都是答案中的事实和规则: word(abalone,a,b,a,l,o,n,e). word(abandon,a,b,a,n,d,o,n). word(enhance,e,n,h,a,n,

一般来说,我对Prolog和计算机编程都是新手。现在,我已经完成了学习Prolog的练习!我一直都过得很好,但偶尔,当我遇到困难时,我会尝试使用跟踪功能一行一行地跟踪程序,看看它是如何工作的,或者出了什么问题,但我无法理解跟踪列出的内容。我会举个例子

其中一个练习是用谓词纵横字谜/6填充纵横字谜网格。这些都是答案中的事实和规则:

 word(abalone,a,b,a,l,o,n,e).
 word(abandon,a,b,a,n,d,o,n).
 word(enhance,e,n,h,a,n,c,e).
 word(anagram,a,n,a,g,r,a,m).
 word(connect,c,o,n,n,e,c,t).
 word(elegant,e,l,e,g,a,n,t).

crossword(V1,V2,V3,H1,H2,H3):-
word(H1,_,H12V12,_,H14V22,_,H16V32,_),
word(H2,_,H22V14,_,H24V24,_,H26V34,_),
word(H3,_,H32V16,_,H34V26,_,H36V36,_),

word(V1,_,H12V12,_,H22V14,_,H32V16,_),
word(V2,_,H14V22,_,H24V24,_,H34V26,_),
word(V3,_,H16V32,_,H26V34,_,H36V36,_).
这个很好用。但是我想知道它是如何工作的,我想看看计算机是如何一步一步地通过规则工作的。所以我在查询纵横字谜(V1、V2、V3、H1、H2、H3)上使用了跟踪。接下来的只是生产的前十行左右

[trace]  ?- crossword(V1,V2,V3,H1,H2,H3).
  Call: (8) crossword(_5238, _5240, _5242, _5244, _5246, _5248) ? creep
  Call: (9) word(_5244, _5658, _5660, _5662, _5664, _5666, _5668, _5670) ? creep
  Exit: (9) word(abalone, a, b, a, l, o, n, e) ? creep
  Call: (9) word(_5246, _5658, _5660, _5662, _5664, _5666, _5668, _5670) ? creep
  Exit: (9) word(abalone, a, b, a, l, o, n, e) ? creep
  Call: (9) word(_5248, _5658, _5660, _5662, _5664, _5666, _5668, _5670) ? creep
  Exit: (9) word(abalone, a, b, a, l, o, n, e) ? creep
  Call: (9) word(_5238, _5658, b, _5662, b, _5666, b, _5670) ? creep
  Fail: (9) word(_5238, _5658, b, _5662, b, _5666, b, _5670) ? creep
  Redo: (9) word(_5248, _5658, _5660, _5662, _5664, _5666, _5668, _5670) ? creep
  Exit: (9) word(abandon, a, b, a, n, d, o, n) ? creep
  Call: (9) word(_5238, _5658, b, _5662, b, _5666, b, _5670) ? creep
  Fail: (9) word(_5238, _5658, b, _5662, b, _5666, b, _5670) ? creep
我知道,第一行只是对查询的重述,但变量变成了任意数字。然后进入规则的第一个目标,再次,变量被简单地实例化为任意数。该目标将程序发送到数据库中的第一个事实,即word(鲍鱼、a、b、a、l、o、n、e)

现在我开始感到困惑。为什么之后的下一行又是第一个目标,但第一个变量从_5244变为_5246?然后我得到了一个Exit:word(鲍鱼,a,b,a,l,o,n,e)-顺便说一下,我不确定调用什么:Exit:means是完全相同的意思-后跟同一行,但第一个变量从_5246更改为_5248。这是怎么回事?为什么其他变量都是常量,而只有第一个变量在变化

再往下一点,我就更加困惑了。电话:(9)单词(_5238,_5658,b,_5662,b,_5666,b,_5670)?卑鄙小人,b来自哪里?为什么有三个?我想第一个在那里是因为它是鲍鱼的第二个字母,因此填补了填字游戏中的这个位置,但是为什么后面的两个b在那里呢?他们不应该是“l”和“n”吗


我意识到这对于理解Prolog的人来说可能非常简单,但我不知道发生了什么。这是一个问题,因为跟踪函数可能是学习Prolog最有用的工具。如果我不能使用它并理解它,那么我就无法在学习的过程中检查事物是如何工作的。如果有人能帮我澄清这一点,并为我提供一种更好地阅读和理解跟踪的方法,我将不胜感激。

如果您使用的是SWI Prolog,我建议使用gtrace(键入“gtrace.”并调用谓词)

_5238表示变量

当您调用word/6时,变量被模式匹配到第一个候选变量,并生成一个选择点。 在这种情况下,假设生成了6(单词数/8个定义)“或”句子

如果pattenmatch失败,prolog会选择下一个候选者。 如果pattenmatch成功,prolog将转到下一行(并生成下一个选择点) 如果所有选择都失败,prolog将返回到上一个选择点,并在此点尝试下一个候选项(回溯)

请注意,每个单词/8单独调用时都会生成选择点

在所有的选择点上,prolog都会记住正在测试的候选人

注意,当回溯发生时,选择点上的所有变量都变为自由变量(不允许更改prolog变量。值或自由变量)