3

プロローグで家系図をシミュレートする必要があります。そして、対称述語の問題があります。 事実:

parent(x,y).
male(x).
female(y).
age(x, number).

ルール:

blood_relation頭が痛いです。これは私がやったことです:

blood_relation(X,Y) :- ancestor(X,Y).
blood_relation(X,Y) :- uncle(X,Y)
                    ; brother(X,Y)
                    ; sister(X,Y)
                    ; (mother(Z,Y),sister(X,Z))
                    ; (father(Z,Y),sister(X,Z))
                    ; (father(Z,Y),brother(X,Z)).
blood_relation(X,Y) :- uncle(X,Z)
                    , blood_relation(Z,Y).

そして、満足のいく結果が得られていると思います(二重印刷があります-これを修正できますか)、問題は、この関係を対称にしたいということです。今ではありません。

blood_relation(johns_father, john):yes 
blood_relation(john,johns_father): no

だから..これを修正する方法はありますか。そして、クエリが必要です: Blood_relation にないすべてのペア..

アップデート:

最初のステートメントは、どのような関係を満たす必要がありますか? 血の関係(X,Y):-血の関係(X,Y)。

申し訳ありません..それは悪いコピー/貼り付けです..それ

blood_relation(X,Y):-ancestor(X,Y).

以上で修正されました。

その他のルールは次のとおりです。

father(X,Y) :-
  parent(X,Y),male(X).  
mother(X,Y) :-
  parent(X,Y),female(X).  
brother(X,Y) :-
  parent(Z,X),parent(Z,Y),
  male(X).  
sister(X,Y) :-
  parent(Z,X),parent(Z,Y),
  female(X).  
grandFather(X,Y) :-
  parent(Z,Y),parent(X,Z),
  male(X).  
grandMother(X,Y) :-
  parent(Z,Y),
  parent(X,Z),female(X).  
uncle(X,Y) :-
  mother(Z,Y),brother(X,Z).  
ancestor(X,Y) :-
  ancestor(X,Y).  
ancestor(X,Y) :-
  parent(X,Z),ancestor(Z,Y).

母の弟は叔父の定義です。ちょっと変です。実装する必要があるルールがありますが、それ以外のルールを実装する方法がわかりません。私はただ混乱しています。

blood_relation対称にする方法はありますか?そしてnot_blood_relation新ルールです。そして、クエリが必要です。これは本当に頭が痛いです。多分関係ががらくたのように書かれているからです。

そして、これ以上の事実はありません。それで全部です。すべてのルール、すべての事実。

query..not(blood_relation(X,Y))は機能しません。その理由は本当にわかりません。クエリの例:

age(X,Y), Y>18,  
not(parent(X,Z)),write(X),nl,fail.

うまく動作します

4

3 に答える 3

12

特定の述語を対称にするための素朴な解決策は、まともなものからそれほど遠くありません。一般論として、おじさんなどにつまずかないように友人関係を見てみましょう。

以下は、友情関係の詳細を示すいくつかの事実です (たとえば、数字はユーザー ID であり、引数の特定の順序は、友情を開始した人に由来します)。

friends(1,2).
friends(5,2).
friends(7,4).

最初は " " のようなルールでfriends(A,B) :- friends(B,A).問題が解決すると思うかもしれませんが、これは prolog に引数をもう一度交換するだけでうまくいく可能性があることを伝えるため、無限再帰につながります。" " と呼ばれる述語があります。これは、@</2ある用語 (変数であっても) が「用語の標準的な順序」で別の用語の前に来るかどうかを示します。技術的な意味はここではそれほど重要ではありませんが、重要なのは、2 つの異なる用語の場合、それらの 1 つの順序にのみ当てはまるということです。これを使用して、無限再帰を破ることができます!

この単一のルールは、" friend/2" を対称にすることを処理します。

friends(A,B) :- A @< B, friends(B,A).

これは素晴らしいことですが、大規模なプロジェクトで採用すべきアプローチ方法があります。私の事実のリストの引数の順序には、実際の意味があったことを思い出してください (誰が友情を始めたのか)。最後のルールを追加すると、この情報への将来のアクセスが破壊され、コードを読む他の人にとっては、対称プロパティがコードの 1 行に隠され、ハードコードされたデータのブロックに直面すると無視しやすくなります。

産業用強度のソリューションを検討してください。

friended(1,2).
friended(5,2).
friended(7,4).

friends(A,B) :- friended(A,B).
friends(A,B) :- friended(B,A).

かさばりますが、あいまいな述語を使用せずにきれいに読み取り、元の情報を保持します (実際のアプリケーションでいつか再び必要になるかもしれません)。

--

特定のプロパティを持たないペアを見つけることに関しては、否定を使用して実際の個人を探すときに、ルールにコンテキストを提供する述語を常に含めるようにしてください。

potential_enemies(A,B) :- user(A), user(B), \+ friends(A,B).
于 2009-04-30T02:50:27.980 に答える
1

ちょっと宿題みたいですね…

Prolog の初心者のほとんどが考えない 1 つのトリックは、リスト パターン マッチングです。[a1,[[a2],[b2,[[e3],[f3]]],[c2]]] のようなツリーを<tree>=[root,[ <tree1>, <tree2>,...]] と考えてください:

%Y is immediate child of X?
child(X,Y,[X|S]) :- member([Y|_],S).

%pick one tree in S and check
child(X,Y,[X|S]) :- member([Z|SS],S),child(Z,Y,[Z|SS]).

%X and Y end up with same root?
sib(X,Y,[R|T]) :- child(R,X,[R|T]), child(R,Y,[R|T]).

ペアをルートとして使用したり、性別を追加したり、ツリーのメンバーの特定の関係に名前を付けたりするなど、これを改善できると思います...

于 2009-04-27T00:29:36.597 に答える
0

最初のステートメントは、どのような関係を満たす必要がありますか?

blood_relation(X,Y):-blood_relation(X,Y).

それは、あなたがまだ「知らない」ことを教えてくれるわけではなく、再帰的な頭痛の種になります。「いいえ」の答えについては、取得しようとしているクエリからすべての回答を既に取得しているように見え、インタープリターはそれ以上ないことを伝えているだけです。

あなたは本当にもっと多くの事実と uncle/2 の定義を投稿する必要があります。また、母親の兄弟とは一致せず、妹だけと一致する理由はありますか? 他にも取り組むべき問題がたくさんあります:-)。

血縁以外のすべての場合は、これを試してください。

not_blood_relation(X, Y) :- blood_relation(X, Y), !, fail.
not_blood_relation(X, Y).

そして、なぜそれが機能するのかを自問してください!

于 2009-04-27T00:33:50.767 に答える