1

私はプロローグにかなり慣れていません。とにかく、指定された文字コードのリストで単語あたりの平均文字数を返す一連の再帰的なルールを作成しようとしています。私のコードは以下です。

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)" をやり直すことを決定し、失敗します。 . なぜこれが起こるのですか?

4

1 に答える 1

1

述語は正常に機能しています。解決策を見つけるために、プロローグはあらゆる方法を試します。したがって、AvgLen=2 という回答を与えた後、より多くの可能な解決策を探します。Prolog が解決策を見つけようとしているとき、Prolog は証明ツリーを構築します。そこでは、ゴールを証明するすべての可能な方法を保持し、すべての正しい答えが見つかり、ゴールを証明する他の方法がなくなるまで、それらすべてを 1 つずつ試します。これが、より多くの可能な解決策を試すために redo を呼び出す理由です。述語を決定論的にしたい場合は、cut(!) を次のように追加できます。

medellangd(Text,AvgLen) :-
    medellangd(Text,T,1,0,0),
    AvgLen = T,!.

これらは、最初の正しい答えが見つかると停止し、それ以上検索しません。

プロローグがどのように機能するかを理解するための簡単な例は次のとおりです。

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

simple_example(L) をクエリすると、上記の述語は成功します。ここで、L は空であるか、1 つの要素を持ちます。ここで、simple_example([]) をクエリしようとするとします。または simple_example([1])。トレースでは、次のように表示されます。

[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([]) をクエリするとします。トレースでは、[] が simple_example2 の両方の 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.
于 2016-09-17T18:45:20.383 に答える