4
likes(tom,jerry).
likes(mary,john).
likes(mary,mary).
likes(tom,mouse).
likes(jerry,jerry).
likes(jerry,cheese).
likes(mary,fruit).
likes(john,book).
likes(mary,book).
likes(tom,john).

likes(john,X):-likes(X,john), X\=john.

こんにちは、上記は非常に単純なプロローグ ファイルで、いくつかの事実と 1 つのルールのみが含まれています。しかし、このファイルをロードした後、Prolog に次のクエリを依頼します。

likes(john,X).

プログラムがクラッシュします。その理由はlikes(john,john)、ルールにX\=john.

何かアドバイス?

4

2 に答える 2

3

皮肉なことに、私たちがアクセスしているサイトを考えると、スタックオーバーフローが発生しています。

これは、prologが使用する実行順序のために行われ、ルール内で無限再帰になり、ルールが再びlikes(X,john)アクティブになります(事実ではありません) 。X\=john

これを修正する1つの方法は、次のようにルールの名前をファクトとは異なるものにすることです。

kindoflikes(tom,jerry).
kindoflikes(mary,john).
kindoflikes(mary,mary).
kindoflikes(tom,mouse).
kindoflikes(jerry,jerry).
kindoflikes(jerry,cheese).
kindoflikes(mary,fruit).
kindoflikes(john,book).
kindoflikes(mary,book).
kindoflikes(tom,john).

likes(Y,X):- kindoflikes(X,Y), X\=Y.
likex(Y,X):- kindoflikes(Y,X), X\=Y.

2つのルール定義のkindoflikesでXとYが逆になっていることに注意してください。だからあなたは得る:

?- likes(john,X).
X = mary ;
X = tom ;
X = book.

しかし、あなたはジョンが好きなものを見つけることに縛られていません、そしてあなたはすることができます:

?- likes(jerry,X).
X = tom ;
X = cheese.
于 2012-04-28T04:11:52.407 に答える
2

最初の質問は、プログラムがクラッシュする理由でした。使用している Prolog システムの種類はわかりませんが、多くのシステムでは、Prolog 内から処理できるクリーンな「リソース エラー」が生成されます。

実際の問題は、プログラムがクエリで終了しないことlikes(john, X)です。それはあなたに期待される答えを与え、それから初めてループします。

?- いいね(ジョン、X)。
X = 本。
X = メアリー;
X = トム;
エラー: ローカル スタックが不足しています

その問題を非常に迅速に検出できたことは、非常に幸運でした。より多くの答えを想像してみてください。すべての答えを調べる忍耐力があるかどうかは明らかではありませんでした。しかし、そのためのショートカットがあります。代わりに尋ねる:

?- likes(john, X), false .

このfalse目標は決して真実ではありません。したがって、それは簡単に答えを防ぎます。せいぜい、false末尾にあるクエリは終了します。現在、これは当てはまりません。この非終了の理由は、次のを検討するときに最もよくわかります(詳細については、他の回答を参照してください)。

?- likes(john,X), false .

いいね(トム、ジェリー) :- false .
likes(mary,john) :- false .
likes(mary,mary) :- false .
いいね(トム、マウス) :- false .
likes(jerry,jerry) :- false .
likes(ジェリー、チーズ) :- false .
likes(mary,fruit) :- false .
likes(john,book) :- false .
likes(mary,book) :- false .
いいね(トム、ジョン) :- false .
いいね(ジョン、X) :-
   likes(X,john), false ,
    X\=john .

したがって、スタック オーバーフローの原因はプログラムのこの小さな部分です。問題を解決するには、その小さな部分で何かをしなければなりません。dif(X, john)1 つ:ルールが次のようになるように目標を追加します。

いいね(ジョン、X) :-
   dif(X, ジョン),
   いいね(X、ジョン)。

dif/2SICStus、SWI、YAP、B、IF などの多くの Prolog システムで利用できます。

于 2012-11-14T21:01:43.607 に答える