使用している用語はわかりませんが、Lloyd (論理プログラミングの基礎) で使用されている一般的な用語は、 success、infinite、およびfailure ブランチを含む可能性があるSLD-treeです。また、標準の Prolog 計算規則 (= 一番左の原子を選択) を使用していると仮定します。
あなたの例の SLD ツリーは無限であり、3 つの回答置換に対応する有限数の成功分岐が含まれていますX = b ; X = c ; X = d
。注意すべき重要なことは、このツリーには無限の障害ブランチがありますが、それでもすべてのソリューションが含まれているということです!
計算規則の選択そのものが、SLD ツリーのサイズと構造に影響を与える可能性があります。しかし、良い点は次のとおりです。計算ルールが何であれ、成功の分岐が得られます! 保証します!ええと、無限の SLD ツリーを巧妙な方法で描画し、使用方法を知っている人に保証されています...賢明に。しかし、無限のリソースと賢明さを備えた人々にとっては問題ありません。
もう 1 つの観察結果は、この SLD ツリーの形状が節の順序とはまったく無関係であることです。したがって、非再帰ルールが最後に記述されているかどうか (あなたの場合のように) または最初に記述されているかどうかは、ツリーの形状に大きな違いはありません: 同じサイズ (両方とも無限または両方とも有限) になり、含まれますノードの数は同じですが、一部のブランチは異なる順序で表示されます。
Prolog はその SLD ツリーを段階的に作成しようとしますが、最も原始的な方法を使用して作成します。ブランチの探索を開始し、他のブランチを展開する前に完全に探索します。つまり、Prolog は SLD ツリー (または正確には SLD ツリーの一部のみ) の非常にスペース効率の高い表現を使用できることを意味します。実際、これは本質的にスタックですが、支払う代償は無限分岐に出くわすと、スタックします - 実際、無限のリソースがない限り。そして、節の順序は、成功分岐 (= 答え) が見つかるかどうか、またはそれらが何らかの無限分岐によって埋められるかどうかに影響します。
実際には、これらすべての無限の木を視覚化することは非常に困難です。私たちはそれらに慣れていません。
しかし、Prolog がその証明をどのように実行するかをよりよく理解する方法は他にもあります。
ここでの中心的な概念は、SLD ツリーで言えば、すべてのブランチの有限性を意味するクエリ/ゴールの普遍的な終了です。
目標の普遍的な終了を観察するのは非常に簡単Goal,
false
です。代わりに実行するだけです。
では、これfalse
は私たちの SLD ツリーで何をしたのでしょうか? 基本的に、無限または有限の障害分岐のみが存在するようになりました。すべての答えはなくなりました。
今、事態はさらに良くなっています: 私たちはfalse
あなたのプログラムに導入することさえあります. 結果のプログラムは、失敗スライスと呼ばれます。このプログラムはもはや元のプログラムと同じではありませんが、次のプロパティが保持されます: 失敗スライスが終了しない (= 無限分岐がある) 場合、元のプログラムも終了しません (= 無限分岐がある)。
多くの場合、障害スライスははるかに短いため、理解がはるかに高速です。あなたのプログラムを見てください:
?- パス(a,X), false .
エッジ (a、b) :- false。
エッジ (b、c) :- false。
エッジ (a、d) :- false。
path(N,M):- path(N,New), false , edge(New,M) .
path(N,M):- false、 edge(N,M)。
経験豊富な Prolog プログラマーは、プログラムのこの小さな断片を見るだけで、はるかに理解しやすくなります。彼らは、無限の分岐を想像することに時間を費やしたり、実際の Prolog の実行を想像したりしません。
ある意味では、 はfalse
すでに計算規則を示していますfalse
。
これも「見る」ことを学ぶことができます。このリンクをたどってください。