I am my own Grandpa!

The following is a (probably buggy) solution for the problem "I am my own grandfather" presented in many Prolog courses. I know it is buggy because some queries produces infinite loops, and some ended up crashing SWI-Prolog – after all, I’ve started learning Prolog today. But at least it answers the ultimate question correctly:

?- grandfather_in_law(i,i).
true .

 

erm.. Does the term "grandfather-in-law" even exist?

 

The Problem

The problem is stated as it follows (in english):

I married a widow (let’s call her w) who has grow-up daughter (call her d). My father (f), who visited us quite often, fell in love with my step-daughter and married her. Hence my father became my son-in-law and my step-daughter became my mother. Some months later, my wife gave birth to a son (s1), who became the brother-in-law of my father, as well as my uncle. The wife of my father, that is my step-daughter, also had a son (s2). Now I am my own grandfather. (aus N. Wirth, "Algorithms + data structures = programs"

In portuguese:

Eu me casei com uma viúva (W) que tem uma filha adulta (D). Meu pai (F), que nos visitava
freqüentemente, apaixonou-se por minha enteada e casou-se com ela. Logo, meu pai se tornou meu enteado e minha enteada tornou-se minha madrasta. Alguns meses depois, minha mulher teve um filho (S1), que se tornou cunhado do meu pai, assim como meu tio. A mulher do meu pai, isto é, minha enteada, também teve um filho (S2). Agora eu sou meu próprio avô.

And as a Youtube video:

 

The Proof

(Feel free to correct me if you wish)

    male(i).
    male(f).
    male(s1).
    male(s2).
    married(i,w).
    parent(w,d).
    parent(f,i).
    married(f,d).
    parent(w,s1).
    parent(i,s1).
    parent(f,s2).
    parent(d,s2).

    married(X,Y) :- tmarried(X,Y).
    tmarried(X, Y) :- married(Y,X).

    female(X) :- not(male(X)).

    %% Normal relationships
    father(Parent, Child) :-
        parent(Parent, Child),
        male(Parent).

    mother(Parent, Child) :-
        parent(Parent, Child),
        female(Parent).

    sibling(X,Y) :-
        parent(F, X),
        parent(F, Y), X = Y.

    uncle(Uncle, Nephew) :-
        parent(Parent, Nephew),
        sibling(Parent, Uncle),
        male(Uncle).

    grandparent(Grandfather, Grandchild) :-
        parent(X,Grandchild), parent(Grandfather,X).

    %% In-law relationships
    sibling_in_law(X,Y) :-
        parent(P,X),
        parent_in_law(P,Y),
        X = Y.

    sibling_in_law(X,Y) :-
        parent(P,Y),
        parent_in_law(P,X),
        X = Y.

    parent_in_law(Parent, Child) :-
        parent(Partner, Child),
        married(Parent, Partner).

    uncle_in_law(Uncle, Nephew) :-
        parent_in_law(Parent, Nephew),
        sibling(Parent, Uncle),
        male(Uncle).

    grandparent_in_law(Grandparent, Grandchild) :-
       ( parent_in_law(X, Grandchild), parent_in_law(Grandparent, X) );
       ( parent(X, Grandchild), parent_in_law(Grandparent, X) );
       ( parent_in_law(X, Grandchild), parent(Grandparent, X) ).

    grandfather_in_law(Grandfather, Grandchild) :-
        grandparent_in_law(Grandfather, Grandchild),
        male(Grandfather).

 

Now lets try and query grandfather_in_law(i,i). to see what if gives back.

And the answer is…

42 .

 

Now I know why everybody loves this language so much 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *