Prolog重新调用,没有明显的原因失败



我是Prolog的新手。无论如何,我试图编写一组递归规则,返回给定字符代码列表中每个单词的平均字符数。我的代码如下:

medellangd(Text,AvgLen) :-
    medellangd(Text,T,1,0,0),
    AvgLen = T.
medellangd([],AvgLen,Space,Words,Chars) :-
    T is (Chars/Words),
    AvgLen = T.
medellangd([A|B],AvgLen,Space,Words,Chars) :-
    succ(Chars,C),
    updatewords(A,Space,Words,W),
    updatespace(A,S),
    medellangd(B,T,S,W,C),
    AvgLen = T.
updatewords(A,1,Words,W) :-
    member(A, [65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122])
    -> succ(Words,S),
       W = S
    ;  W = Words.
updatewords(A,0,Words,W) :-
        W = Words.
updatespace(A,S) :-
    member(A,[65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122])
    -> S = 0
    ;  S = 1.

由于我不知道的原因,虽然AvgLen得到了正确的值,但当我调用medellangd([68,69],AvgLen)时,Prolog返回false。当我跟踪这个调用时,虽然每个调用在AvgLen获得它的值之前都退出了,但如果我在AvgLen值赋值后输入分号,Prolog决定重做"(9)updatewords(68, 1, 0, _G2574)",并且失败。为什么会发生这种情况?

您的谓词工作良好,为了找到解决方案prolog尝试了所有可能的方法,因此在给出答案AvgLen=2后,它搜索更多可能的解决方案。当Prolog试图找到一个解决方案时,它会构建一个证明树,在那里它保留了所有证明目标的可能方法,并逐一尝试,直到找到所有正确的答案,并且没有其他方法可以证明目标已经离开。这就是调用重做的原因,以尝试更多可能的解决方案。如果你想让谓词是确定性的您可以在:

中添加cut(!)
medellangd(Text,AvgLen) :-
    medellangd(Text,T,1,0,0),
    AvgLen = T,!.

,当找到第一个正确答案时,这些将停止,并且不会继续搜索。

一个简单的例子是理解prolog的工作原理:

simple_example([]).
simple_example([_]).

如果查询simple_example(L),则上述谓词成功。其中L是空的,或者只有一个元素。现在,如果您尝试查询simple_example([])。或simple_example([1])。在trace中,您将看到:

[trace]  ?- simple_example([1]).
   Call: (7) simple_example([1]) ? creep
   Exit: (7) simple_example([1]) ? creep
true.

另一方面,如果你用不同的方式写同一个例子:

  simple_example2(L):- L=[].
  simple_example2(L):- L=[_].

谓词simple_example2显然等同于simple_example,但是如果您查询simple_example2([])。在trace中,您将看到,因为我们有[]匹配simple_example2中的两个L,它将同时尝试两个L,当然只有第一个是正确的:

[trace]  ?- simple_example2([1]).
   Call: (7) simple_example2([1]) ? Unknown option (h for help)
   Call: (7) simple_example2([1]) ? Unknown option (h for help)
   Call: (7) simple_example2([1]) ? Unknown option (h for help)
   Call: (7) simple_example2([1]) ? creep
   Call: (8) [1]=[] ? creep
   Fail: (8) [1]=[] ? creep
   Redo: (7) simple_example2([1]) ? creep
   Call: (8) [1]=[_G3328] ? creep
   Exit: (8) [1]=[1] ? creep
   Exit: (7) simple_example2([1]) ? creep
true.

相关内容

  • 没有找到相关文章

最新更新