我可以使用整数作为参数吗?

时间:2019-02-13 18:34:10

标签: prolog

在给定后裔程度的情况下,如何知道人X是人Y的后代?

我已经尝试过了:

descendant(X, Y, 1) :- son(X, Y).
descendant(X, Y, Degree) :- son(X, Z) , descendant(Z, Y, Degree-1).

如果X是Y的儿子,则son(X, Y)返回yes的位置。如果Degree == 1返回正确的答案,但是对于descendant(X, Y, 2),应返回{{1} },如果X是Y的孙子,但返回yes

2 个答案:

答案 0 :(得分:5)

1)命名son(X,Y)的意思是“ XY的儿子”吗?反之亦然? son_of(X,Y)更好。

2)利用:我们在这里不需要做一般的算术……我们只需要计数。


所以我们开始in the beginning ...

child_of(abel, adam).           % from source
child_of(abel, eve).
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).              %   If Z is  a    child of Y ...
                                % then Y is an ancestor of Z.
ancestor_of(X, Z) :-
   child_of(Z, Y),              %   If Z is  a    child of Y ...
   ancestor_of(X, Y).           %  and X is an ancestor of Y ...
                                % then X is an ancestor of Z.

接下来,我们添加一个指示距离的附加参数。

我们使用s/1项来表示自然数,并向ancestor_of/2添加新参数:

ancestor_of_dist(Y, Z, s(0)) :-      
   child_of(Z, Y).              %   If Z is  a    child of Y ... 
                                % then Y is an ancestor of Z with distance = 1."
ancestor_of_dist(X, Z, s(N)) :-      
   child_of(Z, Y),              %   If Z is  a    child of Y ... 
   ancestor_of_dist(X, Y, N).   %  and X is an ancestor of Y with distance N ...
                                % then X is an ancestor of Z with distance N+1.

那...谁是谁的祖父母?

?- 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.

答案 1 :(得分:3)

Prolog不是一种功能语言。因此,Degree-1项不会被解释为表达式。对于Prolog,Degree-1只是一个带有两个参数的复合术语。使用标准write_canonical/1谓词就可以清楚地看出这一点,该谓词无需使用运算符就可以写出一个术语:

?- write_canonical(Degree-1).
-(_,1)
true.

改为:

descendant(X, Y, 1) :-
    son(X, Y).
descendant(X, Y, Degree) :-
    son(X, Z) ,
    descendant(Z, Y, Degree0),
    Degree is Degree0 + 1.

is/2标准内置谓词将左参数与右参数中的算术表达式的值统一起来。

P.S。请注意,我建议的替代descendant/3谓词定义将解决您所描述的问题,但它不是有效的定义,因为它不是 tail-recursive 定义。即第二个子句中的递归调用不是子句主体中的最后一个调用。但是,使用累加器即可轻松解决此问题。