3

私はPrologを初めて使用し、この割り当てを与えられました。

私のコードは次のとおりです。

relatives(cindy,tanya).
relatives(tanya,alan).
relatives(alan,mike).
relatives(kerry,jay).
relatives(jay,alan).

isRelated(X,Y):-
    relatives(X,Y).
isRelated(X,Y):-
    relatives(X,Z),
    isRelated(Z,Y).

十分に単純です。これは、次の場合を示しています。

?- isRelated(cindy,mike).

Prologはtrueを返します。今、私はそれを真に戻す方法に固執しています:

?- isRelated(mike,cindy).

isRelated(Z、Y)がfalseを返し、XとYを切り替えて、isRelatedを再度実行するなどのアイデアを考え出そうとしてきました。しかし、Prologがそのようなアイデアを許可するかどうかはわかりません。ヒントやアドバイスをいただければ幸いです。ありがとう!

更新:* ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * **

だから私は追加しました:

isRelated(X,Y):-
    relatives(X,Y);
    relatives(Y,X).

それは「直接的な」関係を満足させるでしょう、しかし単に私はそれが間接的な関係を満たさないことを知りました。

最初のクエリの場合、私は本当に次のようなことをしたいと思います。

isRelated(mike,cindy)

失敗した場合は、XとYを切り替えて、その逆が当てはまるかどうかを確認してください。

isRelated(cindy,mike)

それは間違いなく真になります。Prologでこれを構文的に行う方法がわかりません。

4

3 に答える 3

1

まだコメントを残すことができないので、コメントにある人たちへのさらなるヒント:あなたの元のルールと事実のセットで isRelated(cindy,tanya)は、真実ですが、そうではないので、対称isRelated(tanya,cindy)にする必要があります。それを達成するためisRelated(X,Y)の簡単な追加は何ですか?isRelated

また、すべての基本事実に対して X から Y への矢印を使用して関係のグラフを描画してみて、relatives(X,Y)それが Prolog インタープリターがクエリをどのように満たそうとするかを考えるのに役立つかどうかを確認することもできます。

于 2012-02-23T06:48:53.337 に答える
1

したがって、最後の質問に答えるために、C で呼び出すように、Prologでとのを切り替えません。論理変数が保持する値は、明示的に変更することはできず、バックトラックするだけです。ただし、 を使用する場所で簡単に使用でき、その逆も可能です。XYswap(x,y)YX

somePred(X,Y):- is_it(X,Y).
somePred(X,Y):- is_it(Y,X).

これはsomePred述語を論理和、「OR」として定義します。のように明示的に書くこともできます。

somePred(X,Y):- is_it(X,Y) ; is_it(Y,X).

そこのセミコロンに注意してください。,述語 OTOH 間のコンマは、接続詞「AND」を定義します (複合用語内のコンマは、用語の「引数」を区切る役割を果たします)。

于 2012-02-23T07:26:44.923 に答える
1

あなたはもうすぐそこにいます。1 つの述語にあまりにも多くのものを詰め込もうとしているだけだと思います。

問題文を英語で書き、それを基に作業します。

XとYの2人の間に関係がある

  • X と Y が直接関連している場合、または
  • X の直接の親戚である P が Y に関連している場合。

その後、簡単になります。私は次のようにアプローチします:

まず、親戚に関する一連の事実があります。

related( cindy, tanya ).
...
related( james, alan ).

次に、直接的な関係を記述する述語は、これらの事実の用語です。

directly_related( X , Y ) :- % a direct relationship exists 
  related(X,Y)               %   if X is related to Y
  .                          % ... OR ...
directly_related( X , Y ) :- % a direct relationship exists
  related(Y,X)               %   if Y is related to X
  .                          %

最後に、関係を記述する述語:

is_related(X,Y) :-        % a relationship exists between X and Y
  directly_related(X,Y)   %   if a direct relationship exists between them
  .                       % ... OR ...
is_related(X,Y) :-        % a relationship exists between X and Y
  directly_related(X,P) , %   if a direct relationship exists between X and some other person P
  is_related(P,Y)         %   and [recursively] a relationship exists between P and Y.
  .                       %

解決策は、実際にはこれよりも複雑です。

  1. 関係に関する事実は、1 つ以上のグラフを表します。グラフの詳細については、http: //web.cecs.pdx.edu/~shard/course/Cs163/Doc/Graphs.html を参照してください。あなたがしているのは、グラフ内のノード X からノード Y へのパスを見つけることです。

  2. リレーションシップに関する事実によって記述されたグラフが、X と Y の間に 1 つ以上のパスを持っている場合、上記のソリューションは、そのようなパスごとに 1 回、(バックトラックで) 複数回成功する可能性があります。ソリューションは決定論的である必要があります。通常、2 人が血縁関係にあることを確認したら、これで完了です。いとこが 2 人いるからといって、叔母と 2 度血縁関係があるとは限りません。

  3. 関係のグラフに「循環」パスが存在するような循環A → B → C → A …が含まれている場合 (ほぼ確実に正しい) 、解は無制限の再帰の影響を受けやすくなります。つまり、ソリューションはサイクルを検出して処理する必要があります。それはどのように達成できるでしょうか。

于 2012-02-23T18:58:00.407 に答える