1

特定の人に関係するすべての人のリストを返す方法に頭を悩ませています。したがって、親戚(A、B)と言うと、Aは人であり、Bはその人に関連するすべての人のリストです。これを支援するために必要な追加のルールを書くことができます。これが私がこれまでに持っているものです。

man(joe).
man(tim).
man(milan).
man(matt).
man(eugene).

woman(mary).
woman(emily).
woman(lily).
woman(rosie).
woman(chris).

parent(milan, mary).
parent(tim, milan).
parent(mary, lily).
parent(mary, joe).
parent(mary, matt).
parent(chris, rosie).
parent(eugene, mary).
parent(eugene, chris).

cousins(A, B) :- parent(C, A), parent(D, B), parent(E, C), parent(E, D), not(parent(C, B)), not(parent(D, A)), A \=B.

paternalgrandfather(A, C) :- man(A), man(B), parent(B, C), parent(A, B).

sibling(A, B) :- parent(C, A), parent(C, B), A \= B.

誰かが私がこれをどのように行うかについて私を導くことができますか?ありがとう。

4

2 に答える 2

0

重複を避けるために、組み込みの述語findall/3と多分sort/2を使用する必要があると思います

それはこれらの線に沿って進むでしょう:

relatives(Person, Relatives):-
  findall(Relative, is_relative(Person, Relative), LRelatives),
  sort(LRelatives, Relatives).

is_relative(Person, Relative):-
  (cousins(Person, Relative) ; paternalgrandfather(Person, Relative) ; sibling(Person, Relative)).

より多くの関係を取得するために、is_relativeにさらに句を追加することをお勧めします。

于 2012-05-09T04:05:51.173 に答える
0

「真の」関係に集中する必要があると思います。つまりparent(Old,Jung)、他の述語はここでは無関係です。parent/2で発生する原子は識別子である(つまり、名前は一意である)という明らかな仮定があります。この写真から、ここのすべての人は親戚であるようです:

ここに画像の説明を入力してください

次に、問題は、親関係にあるすべての接続された頂点を見つけることと同等である必要があります。深さ優先探索を実装して、訪問したノードのリストを渡してループを回避することができます(親に戻って子に戻る必要があることに注意してください)。

relatives(Person, Relatives) :-
    relatives([], Person, [Person|Relatives]).

relatives(Visited, Person, [Person|Relatives]) :-
    findall(Relative, immediate(Person, Visited, R), Immediates),
    ... find relatives of immediates and append all in relatives.

immediate(Person, Visited, R) :-
    (parent(Person, R) ; parent(R, Person)),
    \+ member(R, Visited).

このスニペットを完成できるかどうかを確認してください。親戚/3の引数の順序は、簡単なmaplist/3に選択されていることに注意してください。

より高度なコードを研究したい場合は、SWI-Prologライブラリ(ugraph)reachable(+Vertex, +Graph, -Vertices)がリストベースのグラフ表現でそれを行う述語を提供します。

ここに、画像(フィード先のファイルdot)を取得するためのSWI-Prologスニペットがあります。

graph(Fact2) :-
    format('digraph ~s {~n', [Fact2]),
    forall(call(Fact2, From, To), format(' ~s -> ~s;~n', [From, To])),
    format('}\n').

この方法で呼び出すことができます:

?- tell('/tmp/parent.gv'),graph(parent),told.

次に、コマンドラインで発行しますdot -Tjpg /tmp/parent.gv | display

于 2012-05-09T09:28:02.303 に答える