grandfather predicate in Prolog - prolog

I have written the following program in SWI-Prolog:
male(reza).
male(aliakbar).
male(behrooz).
male(said).
male(aliasghar).
male(taghi).
male(gholamreza).
male(hadi).
female(fatema).
female(tahere).
female(olya).
female(fatema).
mother(fateme,reza).
mother(olya,hasan).
mother(x,y) :-
wife(x,z),
father(z,y).
brother(said,reza).
brother(x,y) :-
father(z,x),
father(z,y),
x\==y,
male(x).
sister(tahere,fateme).
sister(x,y) :-
father(z,x),
father(z,y),
x\==y,
female(x).
sister(olya,aliakbar).
wife(tahere,gholamreza).
father(gholamreza,hadi).
father(gholamreza, nastaran).
father(abdollah,hasan).
father(aliakbar,reza).
father(taghi,olya).
father(taghi,aliakbar).
father(taghi,aliasghar).
father(aliakbar,said).
grandfather(x,z) :-
father(x,y),
father(y,z).
grandfather(x,z) :-
father(x,y),
mother(y,z).
uncle(y,x) :-
father(z,x),
brother(z,y),
male(y).
aunt(y,x) :-
mother(z,x),
sister(z,y),
female(y).
cousin(y,x) :-
aunt(z,x),
mother(z,y),
female(y).
cousin(y,x) :-
aunt(z,x),
mother(z,y),
male(y).
When I consult "father(X,Y),father(Y,Z)." it returns the correct answer (names are in persian), i.e. it returns
X = taghi,
Y = aliakbar,
Z = reza ;
X = taghi,
Y = aliakbar,
Z = said ;
false.
But I could not find the correct answer of grandfather(X,Y). Please help me why.
Thanks.

Be careful: case is crucial in Prolog. Your rules cannot be interpreted right because you didn't use capitals for variables.

Related

IF-THEN in canonical form?

defining IF like this :
dynamic(if/1).
op(200, fx, if).
op(150, xfx, then).
op(100, xfy, and).
op(100, xfy, or).
generates the following canonical form :
?- write_canonical(if x then y).
if(then(x,y))
?- write_canonical(if x and z then y).
if(then(and(x,z),y))
?- write_canonical(if x and z or t then y).
if(then(and(x,or(z,t)),y))
Is there a way to generate :
if( conds, then(actions) ).
OR even better :
if( conds, (actions) ).
like this :
if(x,y)
if(x, then(y))
if( and(x,or(z,t)), then(y))
if( and(x,or(z,t)), (y))
one possible alternative I can see :)
?- op(200, xfy, ==>).
?- write_canonical(x ==> y).
==>(x,y)
?- write_canonical(x and z ==> y).
==>(and(x,z),y)
I found better solution to generate normal clauses. Instead of "then" I can just use ":-"
?- write_canonical(if x and z :- y ).
:-(if(and(x,z)),y)
?- assert(if x and z :- write(axz) ).
?- if x and z.
axz

My Prolog family tree program outputs/returns duplicated names

I am working on a family tree(Royal) implementation in prolog, and I am fairly new to prolog. So whenever I run:
| ?- brother_in_law(Who, diana).
Who = andrew ? ;
Who = andrew ? ;
Who = edward ? ;
Who = edward ? ;
no
As you can see, I'm getting these duplicates answers, and I was wondering if this is normal in prolog, or am I doing something wrong? How do I fix it? Any help would be appreciated.
This is my predicate for brother_in_law:
brother_in_law(B, X) :- male(B), brother(B, M), spouse(X, M).
Predicate for brother:
brother(X, Y) :- male(X), sibling(X, Y).
And final predicate siblings:
sibling(X, Y) :- child(X, P), child(Y, P), X \= Y.
Then I also have other facts such as male(edward), female(diana), and spouse(diana, charles), etc.

Given values x and y return rule name if it is true

This is my prolog file.
male(bob).
male(john).
female(betty).
female(dana).
father(bob, john).
father(bob, dana).
mother(betty, john).
mother(betty, dana).
husband(X, Y) :- male(X), mother(Y, Z), father(X, Z).
wife(X, Y) :- female(X), father(Y, Z), mother(X, Z).
son(X, Y) :- male(X), mother(Y, X);female(X), father(Y, X).
daughter(X, Y) :- female(X), mother(Y, X);female(X), father(Y, X).
sister(X, Y) :- female(X), mother(Z, X), mother(Z, Y), X \= Y.
brother(X, Y) :- male(X), mother(Z, X), mother(Z, Y), X \= Y.
I want a name of rule if it returns true for any value x or y.
Let's say x = betty and y = john.
mother(betty, john). <- this will meet so my rule should return 'mother'.
Similarly if any other rule or fact meets true for some value x, y it should return that rule name.
How can I achieve something like that?
could be easy as
query_family(P1, P2, P) :-
% current_predicate(P/2),
member(P, [father, mother, husband, wife, son, daughter, sister, brother]),
call(P, P1, P2).
that gives
?- query_family(betty, john, R).
R = mother ;
false.
?- query_family(betty, X, R).
X = john,
R = mother ;
X = dana,
R = mother ;
X = bob,
R = wife ;
X = bob,
R = wife ;
false.
the semicolon after the answer means 'gimme next'
$ swipl
?- ['facts'].
?- setof( Functor,
Term^(member(Functor, [father, mother, husband, wife, son, daughter, sister, brother]),
Term =.. [Functor, betty, john],
once(Term)),
Answer).
Answer = [mother].
?-
If you want to avoid having to specify the list of functors of interest, you could use current_predicate(F/2).

Prolog ancestor clause using lists

I am struggling to get my head around this basic Prolog concept.
I understand that the basic clause for determining the ancestor of a person is as follows:
ancestor(X, Y) :- parent(X, Y).
ancestor(X, Y) :- parent(X, Z), ancestor(Z, Y).
However, I am trying to get my head around how this works for a prolog program that implements lists to determine children of a parent, i.e:
parent_of(simon, [matthew, andrea, joanne]).
To determine wether or not somebody is the father of somebody, I am using this which works perfectly:
father_of(X, Y) :- parent_of(X, List), my_member(Y, List), male(X).
However, I cant seem to figure out how to get this to work for the ancestor clause above.
member/2 it's the simpler relation between an element and a list:
ancestor_of(X, Y) :- parent_of(X, Ys), member(Y, Ys).
ancestor_of(X, Y) :- parent_of(X, Zs), member(Z, Zs), ancestor_of(Z, Y).
I've added a relation to test the transitive rule
parent_of(simon, [matthew, andrea, joanne]).
parent_of(andrea, [bill, joan]).
yields
?- ancestor_of(andrea,A).
A = bill ;
A = joan ;
false.
?- ancestor_of(simon,A).
A = matthew ;
A = andrea ;
A = joanne ;
A = bill ;
A = joan ;
false.
?- ancestor_of(X,bill).
X = andrea ;
X = simon ;
false.

Prolog grandfather(i,i)

A (very) strange story:
I married a widow(W) who has a daughter(D). My father(F) married my stepdaughter (D). My wife gave birth to a son(s1). The wife of my father (the stepdaughter) also had a son (s2).
The goal of this project is to input:
grandfather(i,i).
and return yes in prolog.
Here is what I have so far:
%facts
father(f,i).
husband(i,w).
husband(f,d).
mother(w,d).
mother(w,s1).
father(i,s1).
mother(d,s2).
father(f,s2).
%rules
father(X,Y) :- f_in_law(X,Y).
father(X,Y) :- husband(X,Z),mother(Z,Y).
f_in_law(X,Y) :- husband(Z,Y),father(X,Z).
b_in_law(X,Y) :- husband(Z,Y),brother(X,Z).
%brother(X,Y) :- b_in_law(X,Y).
uncle(X,Y) :- father(Z,Y),brother(X,Z).
grandfather(X,Y) :- father(Z,Y),father(X,Z).
I traced through it to see what went wrong. father(f,i) is true so that's good! But father(i,f) is thought of as false. Any suggestions/ideas on how to correct this? I appreciate any input as I am rather new to prolog.
Should the predicate be
f_in_law(X,Y) :- husband(Y,Z),father(X,Z).
instead of
f_in_law(X,Y) :- husband(Z,Y),father(X,Z).
I have reformulated the riddle
father(i, s1).
father(f, i).
father(f, s2).
fatlaw(X, Y) :- husband(X, Z), mother(Z, Y).
mother(w, d).
mother(w, s1).
mother(d, s2).
motlaw(X, Y) :- husband(Z, X), father(Z, Y).
husband(i, w).
husband(f, d).
grandfather(X, Y) :-
( father(X, Z) ; fatlaw(X, Z) )
, ( father(Z, Y) ; fatlaw(Z, Y) ; mother(Z, Y) ; motlaw(Z, Y) )
.
the point seems to be that grandfather must accept fake biological offsprings (I hope this is reasonable English).
with that
?- grandfather(X,X).
X = i ;
false.

Resources