1. ホーム
  2. prolog

[解決済み] Prologにおけるエクスクラメーションマーク

2022-02-12 17:43:34

質問

次の事実と述語がある。

sound(time1).
sound(time2).
sun(time3).
relax(X):-sound(X),!,sun(X).
relax(_):-sun(_).

を実行する場合 relax(S). 期待するのは S=time1 により ! これは、(間違っていたら訂正してください)「X」が満たされたら、バックトラックを停止する、というものです。

以下はそのトレースです。

3 ?- trace.
true.

[trace] 3 ?- relax(S).
   Call: (6) relax(_G1831) ? creep
   Call: (7) sound(_G1831) ? creep
   Exit: (7) sound(time1) ? creep
   Call: (7) sun(time1) ? creep
   Fail: (7) sun(time1) ? creep
   Fail: (6) relax(_G1831) ? creep
false.

では、なぜPrologもチェックするかというと sun(time1) によって満たされた後にエクスクラメーションマークを満たしたにも関わらず sound(X) (なぜなら sound(time1) はファクトです)。

解決方法は?

その ! 記号は、その右側の節を左側に後退させないように、一方通行のゲートのようなもので、切り口を越えて後退することがないようにします。

いつ sound(time1) が真であれば、次の節 sun(time1) が評価され、その時初めてPrologは sun(time1)false (ナレッジベースを検索することで、実際には 知っている 事実であること)。

それから、カットのために、prologは値を試さない。 time2time3 を最初の節に追加しました。

カットの詳細

Prologは述語の節を左から右へ評価します。そして、一番左の節にある変数に値を束縛します。もし、節が true であれば、次のものに移る。もし、それが false Prologは他の値も試します。

もし、どの値でも満たすことができない節があれば、それは false となり、述語全体がそうなります(節がANDで結合されているため)。

全体は、節がノード、辺がその変数の異なる値を表す木の深さ優先探索として動作します。もし探索がある節が false であれば、その前の節に戻り、別の値を試すことになる。

ここで、カットが入ります。もし、カット( ! ) の間にある場合、その節が になります。 false 新しい値を試すのは、カットの後に評価が実行される場合のみです。つまり、カットの前に使われた変数の値は ロック そのため、評価結果がカットをまたぐと、変更することができません。