#prolog
Вопрос:
У меня есть приведенное определение потомка, как показано ниже:
«человек, который находится в прямой линии с предком. Например: ребенок, внук, правнук и навсегда»
а также другие правила, такие как:
...
childof(X, Y).
parent(X, Y).
grandchild(X, Y).
ancestor(X, Y).
...
Так могу ли я просто написать правило, как показано ниже,
descendant(X, Y):- ancestorof(Y, X).
или есть лучший способ сделать это?
Ответ №1:
Это проблема обхода дерева или графа.
Я бы обобщил ancestor_of/3
предикат:
ancestor(Ancestor,Generations,Descendant)
Предполагая, что у вас есть, скажем, набор фактов, таких как
parents( mother, father, child ).
Он может сказать, что родитель является либо матерью, либо отцом ребенка:
% P is a parent of C if P is either the mother or father of C.
parent(P,C) :- parents(P,_,C).
parent(P,C) :- parents(_,P,C).
И, учитывая вышесказанное, решение может выглядеть следующим образом:
ancestor(Ancestor, Generations, Descendant) :-
ancestor( Ancestor, 0, Generations, Descendant )
.
ancestor( A, N, G, D ) :- % A is an ancestor of D...
parent(A,D), % * if A is the immediate parent of D
G is N 1 % * in which case, tick the generation count
. % Easy!
ancestor( A, N, G, D ) :- % otherwise, A is an ancestor of D...
parent(A,X), % * if A is the immediate parent of somebody
X = D, % * other than D
N1 is N 1, % * [ tick the generation count]
ancestor( X, N1, G, D ) % and that somebody is the ancestor of D
. % Also easy!
Это позволяет нам говорить такие вещи, как:
grandparent(A,C) :- ancestor(A,2,C).
great-grandparent(A,C) :- ancestor(A,3,C).
и т.д.
Это будет работать для биологического происхождения, но если вы допускаете небиологическое происхождение (например, приемных родителей и т. П.), То «Я сам себе дедушка»-это возможность, и вам нужно будет иметь список посещенных узлов, чтобы вы могли обнаружить любые циклы на графике.
Попробуйте выяснить, как определить из этого различные степени родства (как выглядит троюродный брат, трижды удаленный?). Для начала вам нужно будет определить статус брата или сестры.