# 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ô.

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