0

ある事実を別の事実に関連付け、指定された停止点まで継続するための述語を取得しようとしています。

たとえば、誰が誰から荷物を受け取り、どこから荷物を受け取ったのかを最後まで知りたい物流記録を作成しているとします。

プロローグ コード

    mailRoom(m).

    gotFrom(annie,brock).
    gotFrom(brock,cara).
    gotFrom(cara,daniel).
    gotFrom(daniel,m).


    gotFrom(X,Y) :- gotFrom(Y,_).

だから私が述語 gotFrom でやろうとしているのは、あなたが開始した時点からリストを再帰的に下に移動し (例: gotFrom(brock,Who))、m で指定された最後に到達することです。メールルーム。

残念ながら、この述語を実行すると、次のように表示されます。

    Who = annie.
    Who = brock.
    Who = cara.
    etc.etc....

私はすべてを踏み出そうとしましたが、ブロックからアニー、カーラ、そして無限の真を循環するまでどこに行くのかわかりません. 関数のワイルドカード (_) と関係があるような気がしますが、述語がプログラム内の次の事実を検索するために、関数のその部分を他にどのように表現できるかわかりません。最後までスキップ。

プログラムでバックカット (!) を使用しようとしましたが、同じエラーが発生します。

どんな助けでも大歓迎です。コードは必要ありません。何が間違っているのかを知りたいだけなので、正しい方法を学ぶことができます。

ありがとう。

4

1 に答える 1

1

残念ながら、この規則は無意味です。

gotFrom(X,Y) :- gotFrom(Y,_).

ここでは、X または Y を特定の値に制限するものは何もありません。また、シングルトン変数Xと匿名変数の存在は_、基本的に何でも機能することを意味します。それを試してみてください:

?- gotFrom([1,2,3], dogbert).
true ;
true ;

ここで確立しようとしているのは、ある種の推移的なプロパティです。その場合、あなたが望むのはおそらく次のようなものです:

gotFrom(X,Z) :- gotFrom(X, Y), gotFrom(Y, Z).

これにより、興味深い結果が得られます。

?- gotFrom(brock, Who).
Who = cara ;
Who = daniel ;
Who = m ;
ERROR: Out of local stack

問題の原因は、すぐにはわからない場合があります。そのルールでは、チェックされていない再帰が 2 回発生しています。再帰的に統合gotFrom/2してから、再帰的に再統合します。これを 2 つの述語に分割して、そのうちの 1 つを非再帰的に使用できるようにすることをお勧めします。

got_directly_from(annie,brock).
got_directly_from(brock,cara).
got_directly_from(cara,daniel).
got_directly_from(daniel,m).

gotFrom(X,Y) :- got_directly_from(X, Y).
gotFrom(X,Z) :- got_directly_from(X, Y), gotFrom(Y, Z).

これにより、望ましい動作が得られます。

?- gotFrom(brock, Who).
Who = cara ;
Who = daniel ;
Who = m ;
false.

これは、無意味なデータの攻撃に対して回復力があることに注意してください。

?- gotFrom([1,2,3], dogbert).
false.

一般的なアドバイス:

  1. シングルトン変数の警告を無視しないでください。ほとんどの場合、それらはバグです。
  2. 何が起こっているのか理解できないときは、決してカットを導入しないでください。カットは、最初に動作を理解し、カットがどのように影響するかを理解している場合にのみ使用する必要があります。理想的には、グリーン カット (パフォーマンスにのみ影響し、目に見える影響がないカット) に制限するようにしてください。Prolog が何をしようとしているのかを理解していない場合、レッド カットを追加すると、問題がより複雑になります。
于 2013-04-22T03:45:49.770 に答える