adrianwong programmer · retired coal miner

Proving "I'm My Own Grandpa" in Prolog

I’m My Own Grandpa” is a song about a man who, through a combination of perfectly legal marriages, becomes his own grandfather.

Let’s prove it (and all the other tangled relationships mentioned in the song) in Prolog, shall we?

Many, many years ago
when I was twenty-three,
I got married to a widow
who was as pretty as could be.

husband(me, pretty_widow).

wife(X, Y) :- husband(Y, X).

married(X, Y) :- husband(X, Y).
married(X, Y) :- wife(X, Y).

This widow had a grown-up daughter
who had hair of red.
My father fell in love with her,
and soon the two were wed.

diff --git a/grandpa.pl b/grandpa.pl
index 1cf8670..67c599b 100644
--- a/grandpa.pl
+++ b/grandpa.pl
@@ -1,6 +1,22 @@
 husband(me, pretty_widow).
+husband(my_dad, pretty_widow_daughter).

 wife(X, Y) :- husband(Y, X).

+father(my_dad, me).
+
+mother(pretty_widow, pretty_widow_daughter).
+
 married(X, Y) :- husband(X, Y).
 married(X, Y) :- wife(X, Y).
+
+parent(X, Y) :- parent0(X, Y).
+parent(X, Y) :- step_parent(X, Y).
+
+step_parent(X, Z) :-
+    married(X, Y),
+    parent0(Y, Z),
+    \+ parent0(X, Z).
+
+parent0(X, Y) :- father(X, Y).
+parent0(X, Y) :- mother(X, Y).

This made my dad my son-in-law
and changed my very life.
My daughter was my mother,
for she was my father’s wife.

diff --git a/grandpa.pl b/grandpa.pl
index 67c599b..3fb0516 100644
--- a/grandpa.pl
+++ b/grandpa.pl
@@ -18,5 +18,10 @@ step_parent(X, Z) :-
     parent0(Y, Z),
     \+ parent0(X, Z).

+parent_in_law(X, Z) :-
+    married(Y, Z),
+    parent(X, Y),
+    \+ parent(X, Z).
+
 parent0(X, Y) :- father(X, Y).
 parent0(X, Y) :- mother(X, Y).

Queries:

?- parent_in_law(me, my_dad), !.
true.

?- parent(pretty_widow_daughter, me), !.
true.

To complicate the matters worse,
although it brought me joy,
I soon became the father
of a bouncing baby boy.

diff --git a/grandpa.pl b/grandpa.pl
index 3fb0516..1ba9004 100644
--- a/grandpa.pl
+++ b/grandpa.pl
@@ -3,8 +3,10 @@ husband(my_dad, pretty_widow_daughter).

 wife(X, Y) :- husband(Y, X).

+father(me, bouncing_baby_boy).
 father(my_dad, me).

+mother(pretty_widow, bouncing_baby_boy).
 mother(pretty_widow, pretty_widow_daughter).

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

My little baby then became
a brother-in-law to dad.
And so became my uncle,
though it made me very sad.

diff --git a/grandpa.pl b/grandpa.pl
index 1ba9004..7af0858 100644
--- a/grandpa.pl
+++ b/grandpa.pl
@@ -27,3 +27,21 @@ parent_in_law(X, Z) :-

 parent0(X, Y) :- father(X, Y).
 parent0(X, Y) :- mother(X, Y).
+
+sibling(X, Y) :- distinct(sibling0(X, Y)).
+
+sibling_in_law(X, Y) :- sibling_in_law0(X, Y).
+sibling_in_law(X, Y) :- sibling_in_law0(Y, X).
+
+sibling_in_law0(X, Z) :-
+    married(X, Y),
+    sibling(Y, Z).
+
+sibling0(X, Y) :-
+    parent(Z, X),
+    parent(Z, Y),
+    X \= Y.
+
+uncle_aunt(X, Z) :-
+    sibling(X, Y),
+    parent(Y, Z).

Queries:

?- sibling_in_law(bouncing_baby_boy, my_dad), !.
true.

?- uncle_aunt(bouncing_baby_boy, me), !.
true.

For if he was my uncle,
then that also made him brother
To the widow’s grown up daughter who,
of course, was my step-mother

Queries:

?- sibling(bouncing_baby_boy, pretty_widow_daughter), !.
true.

?- step_parent(pretty_widow_daughter, me), !.
true.

Father’s wife then had a son,
who kept them on the run.
And he became my grandson,
for he was my daughter’s son.

diff --git a/grandpa.pl b/grandpa.pl
index 7af0858..c92b116 100644
--- a/grandpa.pl
+++ b/grandpa.pl
@@ -5,9 +5,11 @@ wife(X, Y) :- husband(Y, X).

 father(me, bouncing_baby_boy).
 father(my_dad, me).
+father(my_dad, my_dad_new_son).

 mother(pretty_widow, bouncing_baby_boy).
 mother(pretty_widow, pretty_widow_daughter).
+mother(pretty_widow_daughter, my_dad_new_son).

 married(X, Y) :- husband(X, Y).
 married(X, Y) :- wife(X, Y).
@@ -28,6 +30,10 @@ parent_in_law(X, Z) :-
 parent0(X, Y) :- father(X, Y).
 parent0(X, Y) :- mother(X, Y).

+grandparent(X, Z) :-
+    parent(X, Y),
+    parent(Y, Z).
+
 sibling(X, Y) :- distinct(sibling0(X, Y)).

 sibling_in_law(X, Y) :- sibling_in_law0(X, Y).

Query:

?- grandparent(me, my_dad_new_son), !.
true.

My wife is now my mother’s mother
and it makes me blue,
Because, although she is my wife,
she’s my grandma too.

Query:

?- grandparent(pretty_widow, me), !.
true.

If my wife is my grandmother,
then I am her grandchild
And every time I think of it,
it simply drives me wild.

For now I have become
the strangest case you ever saw,
As the husband of my grandmother,
I am my own grandpa!

And the most important query of them all:

?- grandparent(me, me), !.
true.

Q.E.D.

Source code can be found here.