1) Именование: Означает ли son(X,Y)
"X
сын Y
" - или наоборот?son_of(X,Y)
лучше.
2) Эксплойт арифметика-преемник : Здесь нам не нужна общая арифметика ... нам нужно только считать.
Итак, давайте начнем в начале ...
child_of(abel, <b>adam</b>). % <a href="https://en.wikipedia.org/wiki/Genealogies_in_the_Bible" rel="nofollow noreferrer">from source</a>
child_of(abel, <b>eve</b>).
child_of(cain, adam).
child_of(cain, eve).
child_of(enoch, cain).
child_of(irad, enoch).
child_of(mehujael, irad).
child_of(methushael, mehujael).
child_of(lamech, methushael).
child_of(jabal, lamech).
child_of(jabal, adah).
child_of(jubal, lamech).
child_of(jubal, adah).
child_of(tubal_cain, lamech).
child_of(tubal_cain, zillah).
child_of(naamah, lamech).
child_of(naamah, zillah).
child_of(seth, adam).
child_of(seth, eve).
child_of(enos, seth).
child_of(kenan, enos).
child_of(mahalalel, kenan).
child_of(jared, mahalalel).
child_of(enoch, jared).
child_of(methuselah, enoch).
child_of(lamech, methuselah).
child_of(noah, lamech).
child_of(shem, noah).
child_of(ham, noah).
child_of(japheth, noah).
На основании child_of/2
мы сначала определим ancestor_of/2
- это не должно быть для вас чем-то новым!
ancestor_of(Y, Z) :-
child_of(Z, Y). % <i>If</i> Z is a child of Y ...
% <i>then</i> Y is an ancestor of Z.
ancestor_of(X, Z) :-
child_of(Z, Y), % <i>If</i> Z is a child of Y ...
ancestor_of(X, Y). % <i>and</i> X is an ancestor of Y ...
% <i>then</i> X is an ancestor of Z.
Далее мы добавляем дополнительный параметр, указывающий расстояние.
Мы используем s/1
слагаемые для представления натуральных чисел и добавления нового аргументак ancestor_of/2
:
ancestor_of_dist(Y, Z, s(0)) :-
child_of(Z, Y). % <i>If</i> Z is a child of Y ...
% <i>then</i> Y is an ancestor of Z <b>with distance = 1</b>."
ancestor_of_dist(X, Z, s(N)) :-
child_of(Z, Y), % <i>If</i> Z is a child of Y ...
ancestor_of_dist(X, Y, N). % <i>and</i> X is an ancestor of Y <b>with distance N</b> ...
% <i>then</i> X is an ancestor of Z <b>with distance N+1</b>.
Итак ... кто из них дедушка?
?- ancestor_of_dist(X, Z, s(s(0))).
X = adam, Z = enoch
; X = eve, Z = enoch
; X = cain, Z = irad
; X = jared, Z = irad
; X = enoch, Z = mehujael
; ...
; X = lamech, Z = japheth
; false.