したがって、ここでの目的は、特定のプログラムの正確な終了プロパティを理解することです。Prolog は、比較的複雑な実行メカニズムを備えているため、他のプログラミング言語とは大きく異なります。特に、バックトラッキングは「通常の解像度」と非常に絡み合っており、統合と組み合わされています。
元のプログラムの問題を理解する最も簡単な方法は、次の障害スライスを検討することです (他の例についてはリンクを参照してください)。
plus(0,B,B) :- false , nat(B) .
plus(s(A),B,C) :- plus(A,s(B),C), false .
この小さなプログラムが終了しない場合、元のプログラムも終了しません。したがって、最初に、このプログラムがいつ終了しないかという問題を考えることができます。
C
3 番目の引数を考えてみましょう。単に渡される変数があります。その値 (このフラグメント) には誰も興味がありません。したがって、3 番目の引数は終了にはまったく影響しません。
さらに悪いことに、2 番目の引数もヘッド内の自由変数B
にすぎないため、このフラグメントが終了するかどうかに引数が影響することはありません。
したがって、このフラグメントを終了させたい場合は、最初の引数を知る必要があります。そうしないと、プログラムがループします。終了インファーサーを使用して、この降伏を終了条件として確認することもできます。
plus(A,B,C)terminates_if b(A),b(B);b(A),b(C).
最良の方法は、プログラムを再構成することです。次の終了条件を提供します。
plus(A,B,C)terminates_if b(A),b(B);b(C).
Prolog では、通常、プログラムをさらに一般化して、予期しない解決策を受け入れながら、終了条件をより良い状態に改善することを好みます。
plus(A,B,C)terminates_if b(A);b(C).
ただし、この最後のバージョンでは、常に受け入れられるとは限らないソリューションが認められています。たとえばplus(0, nonnumber, nonnumnber)
、今は成功していますが、失敗したい場合があります。
もちろん、カットを使っていくつかの実験を行うこともできますが、カットを使用すると非常にエラーが発生しやすいことに注意してください。少なくとも、「効率の向上」を妨げることが多い適切なテストと組み合わせる必要があります。