基本から始めましょう。カット演算子は!
常に成功します。カットを過去にさかのぼることはできません。これは、一方通行のゲートのようなものです。別の見方をすれば、これまでに行った決定にコミットするということです。
カットの使用法は、いくつかのカテゴリにグループ化されています。グリーンカットは、定義上、プログラムの実行時セマンティクスをまったく変更しないカットです。グリーンカットは、プログラマーがPrologに、ソリューションが不足していることをすでに知っていることを伝えるための単なる方法です。Prologがこれ以上解決策がないことを知らない場合、別の解決策が必要かどうかを尋ねられ、毎回失敗します。たとえば、この実装を見てくださいmin/3
:
min1(X, Y, X) :- X < Y.
min1(X, Y, Y) :- Y <= X.
?- min1(3, 4, X).
X = 3 ;
false.
Prologが私に別の解決策が必要かどうか尋ねた後、失敗した方法をご覧ください。これは、スタックに追加の選択ポイントがあったことの証拠です。カットでそれを排除することができます:
min2(X, Y, X) :- X < Y, !.
min2(X, Y, Y) :- Y =< X.
さて、Prologに質問すると、min2/3
答えは1つだけになります。
?- min2(3, 4, X).
X = 3.
プロンプトなし、ただ1つの解決策を参照してください。
さて、これを赤のカットではなく緑のカットにしているのは、行動や推論に実際の変化がないということです。Prologにはそれを知る方法がなく、相互に排他的であるというだけですX < Y
。Y =< X
緑色のカットはPrologに伝える方法です。一度、XがYより小さいと判断したら、YがXより小さいかどうかを確認する意味はありません。これにより、技術的になるために、スタックから選択ポイントが削除されます。Prologはバックトラックに多くの時間を費やし、不可能なケースの試行に費やす時間が無駄になるため、これは重要な最適化である場合があります。
赤いカットは少し違う動物です。赤いカットは、特別な方法で動作を変更するカットです。赤いカットの例を示すために、2番目のテストをmin/3
完全に削除しようとする場合があります。
min3(X, Y, X) :- X < Y, !.
min3(_, Y, Y).
「2番目の節に到達するまでに、XがY以上であることがわかっているので、YがX以下であるかどうかを確認する必要はありません」と自分で考えてみてください。一見合理的であるように思われmin2/3
、以前のような1つの解決策があることを知っていると、と同じ動作をしているように見えます。
?- min3(3, 4, X).
X = 3.
?- min3(4, 3, X).
X = 3.
ただし、ロジックの一部を削除したため、バックトラックに関連する微妙なバグに直面することになりました。min/3
3つのエンティティ間の関係として見ると、次のようなmin3/3
虚偽を生成するためにmin1/3
使用できますmin2/3
。
?- min1(3, 100, 100).
false.
?- min2(3, 100, 100).
false.
?- min3(3, 100, 100).
true.
100は3と100の最小値ではありませんがmin3/3
、3番目の値が変数でない場合は、同じ2番目の2つの値を持つものをすべて確認します。つまり、赤いカットを使用min3/3
する場合、3番目の位置に値が表示されることはないと想定しました。3番目のパラメーターを「out」パラメーターとして使用すると想定しました。
この知識を取り入れて、宿題を見てみましょう。私に最初に飛び出すのは、最初の2つのルールにこれと同じ種類の重複する条件付きロジックがあるということです。
calculateCarInsurance(PS,Insurance) :-
PS < 60, ...
calculateCarInsurance(PS,Insurance) :-
PS >= 60, ...
少なくとも、PS < 60
そこにコミットするためにグリーンカットを追加することができます。PSが60未満の場合、実際には60を超えることはできないため、グリーンカットはまったく無害です。
赤いカットを追加したくないということには注意が必要です。あなたがそれをあなたが望むように機能させるためにPrologの推論をいじくり回す必要があるとき、それらは時々必要です。この場合、calculateCarInsurance
複数のソリューションが返される可能性があることに注意してください。この動作は望ましくない場合があります。代わりに、最初に取得した動作にコミットすることをお勧めします。その場合、calculateCarInsurance
ルールのすべての本文の最後にカットを追加できます。そうすれば、Prologがいくつのソリューションを見つけても、単一のソリューションを得ることができます。これにより、プログラムの論理的な動作が変わりますが、要件によっては望ましい場合があります。これには同じマイナスの副作用もある可能性がありますがmin3/3
、保険の結果を検証したい場合は、calculateCarInsurance
おそらくそれが生成しない計算を肯定するでしょう。
私はそれがあなたを正しい軌道に乗せるのに十分であることを願っています。