2

私はPrologで非常に簡単な演習を行っていますが、トレースには理解できないことがあります。プログラムは、>後続として表される整数の「大なり記号」()です。

greater_than(succ(_), 0).
greater_than(succ(A), succ(B)) :-
  greater_than(A, B).

私の問題:リクエストが次のトレースでをgreater_than(succ(succ(succ(0))),succ(0))生成する理由がわかりません:redo

[trace] ?- greater_than(succ(succ(succ(0))),succ(0)).
Call: (6) greater_than(succ(succ(succ(0))), succ(0)) ? creep
Call: (7) greater_than(succ(succ(0)), 0) ? creep
Exit: (7) greater_than(succ(succ(0)), 0) ? creep
Exit: (6) greater_than(succ(succ(succ(0))), succ(0)) ? creep
true ;
Redo: (7) greater_than(succ(succ(0)), 0) ? creep
Fail: (7) greater_than(succ(succ(0)), 0) ? creep
Fail: (6) greater_than(succ(succ(succ(0))), succ(0)) ? creep
false. 

なぜredoここにあるのですか?どうすればそれを回避できますか(もちろん、カットなしで)?

ところで、あなたが尋ねる前に:いいえ、それはある種の宿題ではありません...

4

2 に答える 2

2

OK、それで、与えられたコンパイラー/バージョンの組み合わせが持っているかもしれないし、持っていないかもしれないのはコンパイラーの最適化です。

それ以降のバージョンのSWIにはこの問題はありません。おそらく句の索引付けに関連しています。この動作は、インデックスを作成しない実装、または最初の引数でのみインデックスを作成する実装で見られます。

しかし、どうやら、「SWI-Prologは、複数の引数に対して「ジャストインタイム」のインデックスを提供します」。SWI 5.6.56マニュアルに、「最大4つの引数にインデックスを付けることができる」と記載されています。したがって、おそらく複数のインデックスを作成します。

于 2012-08-30T09:30:00.173 に答える
0

やり直しがある理由は、次の節に従うことによって代替の解決策があるかどうかをプロローグが(それを調べずに)推測できないことです。確かに、この場合、それは1つのヘッド統合チェックです(これは常に些細なことではありません)が、多くの時間がかかる可能性があります(または決して終了しない可能性があります)。

さて、これはまさにあなたがカットを使うべき場所です:あなたは余分な選択ポイントが解決策を生み出さないことを知っています(それであなたはセマンティクスを変えていません-グリーンカット)。または(ただし、ほとんどの場合、カットをカバーする構文糖衣です)、if-then-elseを使用できます。

greater_than(succ(A), B):-
    B = succ(BI) ->
    greater_than(A,BI)
    ; B = 0.

これでも、カットで回避される余分な計算が行われるわけではありません。

PS:誰もが宿題XDだと思うだろうとは思わない

于 2012-08-30T08:53:52.787 に答える