質問
プロローグで家系図をシミュレーションする必要があります。そして、私は対称述語の問題を抱えています。事実:
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, joh):yes
blood_relation(john,johns_father): no
それで...これを修正する方法はありますか。そして、クエリが必要です:blood_relation にないすべてのペア。
アップデート:
最初のステートメントはどのような種類の関係を満たすことになるでしょうか?blood_relation(X,Y):-blood_relation(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
新しいルールです。そして、クエリが必要です。これは本当に頭が痛くなります。おそらく関係がクソのように書かれているからでしょう。
そしてそれ以上の事実はありません。それだけです。すべてのルールとすべての事実。
クエリ.. not(blood_relation(X,Y))
機能しません、そしてその理由が本当にわかりません。たとえばクエリ:
age(X,Y), Y>18,
not(parent(X,Z)),write(X),nl,fail.
問題なく動作します
解決
ちょっと宿題っぽいですね…。
prolog の初心者のほとんどが思いつかないトリックの 1 つは、リストのパターン マッチングです。次のような [a1,[[a2],[b2,[[e3],[f3]]],[c2]]] のようなツリーを考えてみましょう。 <tree
>=[ルート,[<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]).
ルートとしてペアを使用したり、性別を追加したり、ツリーのメンバーの特定の関係に名前を付けたりするなど、これを改善できると思います...
他のヒント
特定の述語を対称にする素朴な解決策は、まともな解決策からそれほど遠くありません。一般論として、おじさんなどにつまづかないよう、友人関係を見てみましょう。
ここでは、友情関係の詳細を示すいくつかの事実を示します (たとえば、数字はユーザー ID であり、引数の特定の順序は友情を開始した人によるものです)。
friends(1,2).
friends(5,2).
friends(7,4).
最初は「」のようなルールを考えるでしょう。friends(A,B) :- friends(B,A).
" とすると問題は解決しますが、引数をもう一度交換するだけでうまくいくかもしれないとプロローグに指示するため、無限再帰につながります。「」という述語があります。@</2
これは、ある項 (変数であっても) が「標準的な項の順序」で他の項より前に来るかどうかを示します。ここでは技術的な意味はそれほど重要ではありませんが、重要なのは、2 つの異なる用語について、それらの 1 つの順序にのみ当てはまるということです。これを使って無限再帰を打ち破ることができます。
この 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).
最初のステートメントはどのような種類の関係を満たすことになるでしょうか?
blood_relation(X,Y):-blood_relation(X,Y).
それはあなたがまだ「知らない」ことを何も教えていないので、再発の頭痛を引き起こすでしょう。「いいえ」の答えについては、取得しようとしているクエリからすべての答えをすでに取得しているように見えますが、インタープリターは、これ以上はないと伝えているだけです。
もっと多くの事実と、叔父/2の定義を投稿するべきです。母親の兄弟と一致せず、母親の妹だけを一致させている理由はありますか?他にも取り組むべき問題がたくさんあります:-)。
血のつながりがないものについては、次のことを試してください。
not_blood_relation(X, Y) :- blood_relation(X, Y), !, fail.
not_blood_relation(X, Y).
そして、なぜそれが機能するのかを自問してください。