5

I am attempting to write a gprolog program that affirms that, given some "reasonable" background from this song (listen here :-) ), will answer yes when I query grandpa(me, me) (i.e., Am I indeed my own grandpa?). This was given as an assignment for my AI class, and we were left to decide for ourselves what facts and predicates to include. Though it's full of redundancy and some clauses that I don't use (some just for the sake of the song), here is what I threw together, with the necessary assumption that step-children are considered to be full/general children:

  3 male(me).
  4 male(mydad).
  5 male(mybaby).
  6 female(widow).
  7 female(redhead).
  8 grandma(Z, X) :- female(Z), child(Z, Y), child(Y, X).           
  9 grandpa(Z, X) :- male(Z), child(Z, Y), child(Y, X).         
 10 child(me, mydad). 
 11 child(redhead, widow). 
 12 child(mybaby, me).
 13 child(A, B) :- married(B, C), married(A, D), child(D, C).  
 14 child(C, A) :- married(A, B), child(C, B). %step children as children
 15 married(me, widow). 
 16 married(widow, me). 
 17 married(mydad, redhead).

It's sloppy, but I'd say the most important things are clauses 13 and 14. In particular, 14 attempts to ensure that, for example, my dad is my child since he married my stepchild and is thus my son-in-law.

Anyway, a trace shows that running the query seems to work--kind of:

{trace}
| ?- grandpa(me, me).
      1    1  Call: grandpa(me,me) ? 
      2    2  Call: male(me) ? 
      2    2  Exit: male(me) ? 
      3    2  Call: child(me,_366) ? 
      3    2  Exit: child(me,mydad) ? 
      4    2  Call: child(mydad,me) ? 
      5    3  Call: married(me,_415) ? 
      5    3  Exit: married(me,widow) ? 
      6    3  Call: married(mydad,_440) ? 
      6    3  Exit: married(mydad,redhead) ? 
      7    3  Call: child(redhead,widow) ? 
      7    3  Exit: child(redhead,widow) ? 
      4    2  Exit: child(mydad,me) ? 
      1    1  Exit: grandpa(me,me) ? 

true ? 

(2 ms) yes

My concern is with the true? statement. If I just press enter, the yes appears, but saying something like a leads to an infinite loop, with the call stack getting a little bigger and bigger each round before "true" appears again. What is going on here? I thought that a successful 'confirmation' of the query would mean the end of things. I don't see any more variables to check!

4

1 回答 1

1

true vs yes are used to distinguish where there could be more solutions. Prolog can inspect the proof stack, looking for choice points, i.e. where alternative computation still to be disproved are waiting.

Hitting a, you stress the main loop that leads to the paradox:

...
   Redo: (31) child(redhead, me)
   Call: (32) married(me, _G2289)
   Exit: (32) married(me, widow)
   Call: (32) child(redhead, widow)
   Exit: (32) child(redhead, widow)
   Exit: (31) child(redhead, me)
   Exit: (30) child(redhead, widow)
   Exit: (29) child(redhead, me)
   Exit: (28) child(redhead, widow)
...

(note: trace obtained with SWI-Prolog, please ignore small differences)

于 2013-07-02T05:27:38.073 回答