web-dev-qa-db-ja.com

Prologの感嘆符

次の事実と述語を考えると:

_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)は事実であるため)。

15
JAN

_!_記号は、右側の句が左側に戻るのを防ぎます。これは一方向のゲートのようなもので、カットを超えて戻ることはありません。

sound(time1)がtrueの場合、次の句Sun(time1)が評価され、プロローグはSun(time1)falseであることを検出します(ナレッジベースを検索することにより、実際にはそれが事実であることを知っているわけではありません)。

次に、カットのため、プロローグは最初の節の値_time2_および_time3_を試行しません。

カットの詳細:

Prologは、述語の節を左から右に評価します。左端の句の変数に値をバインドします。句がtrueの場合、次の句に移動します。 falseの場合、prologは他の値も試行します。

いずれかの句がどの値でも満たすことができない場合、それはfalseになり、述語全体になります(句がANDで結合されているため)。

全体がツリーの深さ優先走査として機能します。ここで、句はノードであり、エッジはその変数のさまざまな値を表します。トラバーサルが句をfalseであると検出した場合、前の句に戻り、別の値を試します。

これがカットです。 2つの句の間にカット(_!_)を置くと、afterの句がfalseになり、新しい値を試すことを意味しますカット後に評価が実行された場合にのみ続行されます。これは、カットの前に使用された変数の値がlockedであり、評価がカットを超えたときに変更できないことを意味します。

26
0605002

これをさらに明確にするために、誰かが感嘆符演算子の動作にまだ苦労している場合(私がしたように)、ここに例があります:

_sound(time3).
sound(time1).
Sun(time1).
relax(X):-sound(X),!,Sun(X).
_

この特定の例では、Prologに?-relax(S).を要求すると、結果はfalseになります。 Prologは次のように機能していると説明できます。

  1. Prologは、要求された述語(relax(SOMEVARIABLE unizable with S))を検索します。
  2. Prologは述語relax(X)を見つけます。これで、変数XとSがバインドされました。
  3. Prologは節の評価を開始します:
    • sound(X)
      • Prologは、sound(X)を満たすファクトをファイルで検索します。
      • ファクトを見つけますsound(time3)。そしてそれを変数X = S = time3と統合します。
      • Prologは演算子である次の節に続きます!したがって、彼はこのオペレーターの後ろに戻ることはありません。
    • Sun(X)
      • Prologは、Sun(X)を満たすファクトをファイルで検索します。 Xはすでにバインドされているため、存在しないSun(time3)を検索します。
  4. 結論
    • この時点で、なかった場合!演算子Prologは(backtrack)をsound(X)に返し、変数X = SをX = S = time1として再割り当てします。事実Sun(time1)が存在するため、最終的にはtrueになります。
    • Prologは、どのルールでもrelax(S)に一致しなかったため、falseを返します。

私が4で言ったように反対に!演算子それは結果として成功

_sound(time3).
sound(time1).
Sun(time1).
relax(X):-sound(X),Sun(X).
_

ある時点で私が間違っている場合は、遠慮なく訂正してください。

22
Smarty77

それでもルールの残りの部分を満たそうとしますが、感嘆符の前に戻ることはありません。つまり、Sun(X)が失敗した場合、バックトレースせずにdifferentオブジェクトをsound(X)に一致させようとしますが、そのルールに完全には一致しません。

4
Junuxx