Prolog - recursing down family tree

后端 未结 3 1195
孤城傲影
孤城傲影 2021-02-10 20:19

I am trying to write a Prolog program that will print out the male successors of British Royalty in order. My attempt so far:

son(elizabeth, charles).
son(charle         


        
3条回答
  •  粉色の甜心
    2021-02-10 21:07

    You said:

    The first rule makes all three immediate children print out, then the second rule prints out all the descendants.

    For any given predicate (such as successor/2), PROLOG will generally evaluate all the possible solutions for the 1st clause, then the next, etc. up to the last clause, in that order. Therefore, PROLOG will behave exactly as you've suggested above - solutions to immediate children will be found first, as the first clause of successor/2 does just that, and the second clause finds the descendants. If you were after a different order, try re-ordering the clauses (i.e.);

    successor(X, Y) :- son(X, C), successor(C, Y).
    successor(X, Y) :- son(X, Y).
    

    This will cause PROLOG to evaluate to:

    ?- successor(elizabeth, Y).
    Y = william ;
    Y = henry ;
    Y = severn ;
    Y = charles ;
    Y = andrew ;
    Y = edward.
    

    i.e., all descentants before immediate children.

    The ordering you've suggested as wanting, however, can't be achieved through a simple reordering of these subgoals. Instead, consider the various tree traversal methods; i.e., in-order, pre-order and post-order. You could write a (simple) program which is capable of walking the tree structure in various different ways, instead of the default evaluation order for PROLOG. For example, consider the following new definition of successor/2:

    successor(Parent, [Son|SonDescendents]) :-
        son(Parent, Son),
        successor(Son, SonDescendents).
    

    This clause seeks to depth-first populate a list of children under a son, and will backtrack to find all solutions.

    successor(NonParent, []) :-
        \+ son(NonParent, _).
    

    This next clause takes care of the base-case whereby the given individual does not have any sons, therefore no descendants enter the result list (empty).

    Evaluating this gives:

    ?- successor(elizabeth, S).
    S = [charles, william] ;
    S = [charles, henry] ;
    S = [andrew] ;
    S = [edward, severn] ;
    false.
    

    ps. I highly recommend the following texts for learning PROLOG:

    The Art of Prolog, by Leon Sterling and Ehud Shapiro

    The Craft of Prolog, by Richard O'Keefe

    Programming in Prolog, by Clocksin and Mellish

提交回复
热议问题