Prolog find father_in_law - prolog

m([ himu, eric, shawn, wasim, steve,
korim, mark, romiz, yash, ben, mathew,protik,
labib, tim, sam, richard, sultan,liton,sazid]).
f([ soma, sarah, priti, anika, rokeya, marry,
lucy, rimi, kani, buni, sanjida, raidah, maria, hema,
cathrin, pauly,lili]).
%third generation
family([wasim, priti, [soma]]).
family([korim, anika, [eric, marry]]).
family([yash,lili,[protik]]).
%second generation
family([mark, lucy, [wasim, rimi]]).
family([ben, sanjida, [priti, mathew]]).
family([romiz, kani, [anika, yash]]).
family([sazid, raidah, [korim]]).
%first generation
family([tim, maria, [lucy]]).
family([sam, hema, [ben]]).
family([richard, cathrin, [romiz]]).
family([sultan, pauly, [sazid,liton]]).
parent(tim,lucy).
parent(maria,lucy).
parent(sam,ben).
parent(hema,ben).
parent(richard,romiz).
parent(cathrin,romiz).
parent(sultan,sazid).
parent(pauly,sazid).
parent(pauly,liton).
parent(sultan,liton).
parent(sam,korim).
parent(raidah,korim).
parent(romiz,anika).
parent(romiz,yash).
parent(kani,anika).
parent(kani,yash).
parent(ben,priti).
parent(ben,mathew).
parent(sanjida,priti).
parent(sanjida,mathew).
parent(mark,wasim).
parent(mark,rimi).
parent(lucy,wasim).
parent(lucy,rimi).
parent(korim,eric).
parent(korim,marry).
parent(anika,eric).
parent(anika,marry).
parent(wasim,soma).
parent( priti, soma).
parent(yash,protik).
parent(lili,protik).
father_in_law(X, Y) :-
male(X) ,family([Z,Y|[_]]),parent(X, Z).
Here for father_in_law I only get wife's father_in_law. But I want also husband's father_in_law in this. Unable to understand how. Is this possible?

You need to change to:
male([ himu, eric, shawn, wasim, steve,
korim, mark, romiz, yash, ben, mathew,protik,
labib, tim, sam, richard, sultan,liton,sazid]).
female([ soma, sarah, priti, anika, rokeya, marry,
lucy, rimi, kani, buni, sanjida, raidah, maria, hema,
cathrin, pauly,lili]).
father_in_law(X, Y) :-
male(XM) ,member(X,XM),family([Z,Y,[_|_]]),parent(X, Z).
father_in_law(X, Y) :-
male(XM) ,member(X,XM),family([Y,Z,[_|_]]),parent(X, Z).
This gets husband's father_in_law.

Related

How to delete entry from rdf file in prolog

I want to write a program in Prolog where a menu is given to the users. They choose to either add data, see existing data based on surname or age, or/and delete data based on surname or age. I don't know how to delete an entry based on age or surname. Here is what I've written. Can anyone tell me what I do wrong? Thank you.
:- use_module(library(semweb/rdf_db)).
:- use_module(library(semweb/rdf_http_plugin)).
:- use_module(library(semweb/turtle)).
:- dynamic id/1.
id(1).
run :- nl,
write('Option 1: Load new path'),nl,
write('Option 2: Create new user'),nl,
write('Option 3: Display data based on Surname'),nl,
write('Option 4: Display data based on Age'),nl,
write('Option 5: Delete data based on Surname'),nl,
write('Option 6: Delete data based on Age'),nl,
write('Option 7: Exit'),nl, %It saves the program before exiting
write('Option(1-7): '), read(X), nl,
( shouldExit(X)
; (option(X), run)
; (nl, write('Invalid option.'), nl, run)
).
shouldExit(7) :- save.
option(1) :- write('Give path for rdf file'), read(Path), doOpen(Path).
option(2) :- doRead.
option(3) :- write('Surname: '), read(Surname), findS(Surname).
option(4) :- write('Age: '), read(Age), findA(Age).
option(5) :- write('Surname: '), read(Surname), delS(Surname).
option(6) :- write('Age: '), read(Age), delA(Age).
/*Enter new user*/
doRead :- rdf_register_prefix(foaf,'http://xmlns.com/foaf/0.1/'),
write('Surname:'), read(Surname),
write('First Name:'), read(FirstName),
write('Age:'), read(Age),
id(N),
New is N+1,
retract(id(N)),
asserta(id(New)),
atom_concat('foaf:person', N, Person),
rdf_assert(Person, rdf:type, foaf:'Person'),
rdf_assert(Person, foaf:surname, literal(Surname)),
rdf_assert(Person, foaf:firstName, literal(FirstName)),
rdf_assert(Person, foaf:age, literal(Age)).
/*Display data based on Surname*/
findS(Surname) :- rdf(X, foaf:surname, literal(Surname)),
rdf(X, foaf:firstName, literal(FirstName)),
rdf(X, foaf:age, literal(Age)),
write('Found '), write(FirstName), write(' '),
write(Surname), write(', '), write(Age), nl, fail.
/*Display data based on Age*/
findA(Age) :- rdf(X, foaf:surname, literal(Surname)),
rdf(X, foaf:firstName, literal(FirstName)),
rdf(X, foaf:age, literal(Age)),
write('Found '), write(FirstName), write(' '),
write(Surname), write(', '), write(Age), nl, fail.
/*Loads the file from the path the user asks ''*/
doOpen(Path) :- rdf_load(Path).
/*Saves the changes before exiting*/
save :- rdf_save(Path, [foaf]).
/*Deletes user based on their surname*/
/*delS(Surname) :- .*/
/*Deletes user based on their age*/
delA(Age) :- rdf(X, foaf:surname, literal(Surname)),
rdf(X, foaf:firstName, literal(FirstName)),
rdf(X, foaf:age, literal(Age)),
retract(rdf(Surname, FirstName, Age)).
I don't know it, so this is a guess, but you are using:
retract(rdf(Surname, FirstName, Age)).
and that is Prolog retract/1, I think you need rdf_retractall instead.

I wrote a prolog code for my family tree. What's the problem with this code?

/*facts*/
female(Sufia).
female(Bilkis).
female(Nasima).
female(Rabeya).
female(NWife).
female(Eva).
female(Rekha).
female(Shammi).
female(Shanta).
female(TWife).
female(NSWife).
female(Jui).
female(SHWife).
female(TSWife).
male(Anowar).
male(Shahidul).
male(Khazal).
male(Shafik).
male(Nahid).
male(Jahorul).
male(Naim).
male(Tanim).
male(Raiyan).
male(NSon).
male(JHusband).
male(Jubayer).
male(Shoddo).
male(TSon).
male(NSSon).
male(JSon).
male(SHSon).
male(TSSon).
parent(Anowar,Shahidul).
parent(Anowar,Nasima).
parent(Anowar,Shafik).
parent(Shahidul,Nahid).
parent(Shahidul,Eva).
parent(Nasima,Rekha).
parent(Nasima,Shammi).
parent(Nasima,Shanta).
parent(Shafik,Tanim).
parent(Shafik,Raiyan).
parent(Nahid,NSon).
parent(Rekha,Jui).
parent(Rekha,Jubayer).
parent(Shammi,Shoddo).
parent(Tanim,TSon).
parent(NSon,NSSon).
parent(Jui,JSon).
parent(Shoddo,SHSon).
parent(TSon,TSSon).
/*rules*/
mother(X,Y):-parent(X,Y),female(X).
father(X,Y):-parent(X,Y),male(X).
son(X,Y):-parent(X,Y),male(X).
daughter(X,Y) :- female(X),parent(X,Y).
sister(X,Y) :- female(Y),parent(Par,X),parent(Par,Y), X \= Y.
child(X, Y) :-parent(Y, X).
sibling(X,Y):-parent(Z,X),parent(Z,Y),X\=Y.
grandparent(X,Z):-parent(X,Y),parent(Y,Z).
firstCousin(X,Y):-grandparent(Z,X),grandparent(Z,Y),X\=Y.
secondCousin(X,Y):-grandparent(A,X),grandparent(B,Y),sibling(A,B),A\=B.
firstcousinOnceRemoved(X,Y):-child(X,Z),cousin(Z,Y).
firstcousinTwiceRemoved(X,Y):-grandparent(X,Z),cousin(Z,Y).
You need to quote every name, otherwise these symbols are variables, not atoms.
Otherwise, just lowercase the first letter. To illustrate this last option, using my pet project, here is the graph:
as obtained from this source
:- module(answer_so, [answer_so/0]).
:- use_module(genealogy).
answer_so :- genealogy(answer_so, 'Answer SO').
parent_child(P,C) :- parent(P,C).
female(sufia).
female(bilkis).
female(nasima).
female(rabeya).
female(nwife).
female(eva).
female(rekha).
female(shammi).
female(shanta).
female(twife).
female(nswife).
female(jui).
female(shwife).
female(tswife).
male(anowar).
male(shahidul).
male(khazal).
male(shafik).
male(nahid).
male(jahorul).
male(naim).
male(tanim).
male(raiyan).
male(nson).
male(jhusband).
male(jubayer).
male(shoddo).
male(tson).
male(nsson).
male(json).
male(shson).
male(tsson).
parent(anowar,shahidul).
parent(anowar,nasima).
parent(anowar,shafik).
parent(shahidul,nahid).
parent(shahidul,eva).
parent(nasima,rekha).
parent(nasima,shammi).
parent(nasima,shanta).
parent(shafik,tanim).
parent(shafik,raiyan).
parent(nahid,nson).
parent(rekha,jui).
parent(rekha,jubayer).
parent(shammi,shoddo).
parent(tanim,tson).
parent(nson,nsson).
parent(jui,json).
parent(shoddo,shson).
parent(tson,tsson).
Seems there are no marriages...

Write a predicate same_name(Person1,Person2) that returns true if Person 1 and Person 2 have same family name

parent(albert, jim).
parent(albert, peter).
parent(jim, brian).
parent(john, darren).
parent(peter, lee).
parent(peter, sandra).
parent(peter, james).
parent(peter, kate).
parent(peter, kyle).
parent(brian, jenny).
parent(irene, jim).
parent(irene, peter).
parent(pat, brian).
parent(pat, darren).
parent(amanda, jenny).
female(irene).
female(pat).
female(lee).
female(sandra).
female(jenny).
female(amanda).
female(kate).
male(albert).
male(jim).
male(peter).
male(brian).
male(john).
male(darren).
male(james).
male(kyle).
We assume that each person will have the same family name as their father, but that married women retain their original birth name.
Example :
?- same_name(pat, brian).
false.
?- same_name(jenny, jim).
true
I wrote conditions to check if they have same father or one of them is grandfather :
check_grandfather(A,B) :-
parent(A,X),
parent(X,B).
check_siblings(A,b) :-
parent(X,A),
parent(X,B),
A \== B.
but I can not understand how can I use conditions to check same_name.
I am thinking something like,
same_name(P1,P2) :-
check_siblings(P1,P2),
check_grandfather(P1,P2).
But it doesn't seem to work. I am very new to prolog so any help would be appreciated.

Fact appears only once in the Knowledge Base

I have this KB (Knowledge Base):
%artist(ArtistId, ArtistName, YearofDebut).
%album(AlbumId, AlbumName, YearOfRelease, Artists).
%song(AlbumId, Songname, Duration).
%artist/3
artist(1, 'MIEIC', 2006).
artist(2, 'John Williams', 1951).
artist(3, 'LEIC', 1995).
artist(4, 'One Hit Wonder', 2013).
%album/4
album(a1, 'MIEIC Reloaded', 2006,[1]).
album(a2, 'Best Of', 2015, [2]).
album(a3, 'Legacy', 2014, [1,3]).
album(a4, 'Release', 2013, [4]).
%song/3
song(a1, 'Rap do MIEIC', 4.14).
song(a2, 'Indiana Jones', 5.25).
song(a1, 'Pop do MIEIC', 4.13).
song(a2, 'Harry Potter', 5.13).
song(a1, 'Rock do MIEIC', 3.14).
song(a2, 'Jaws', 3.04).
song(a2, 'Jurassic Park', 5.53).
song(a2, 'Back to the Future', 3.24).
song(a2, 'Star Wars', 5.20).
song(a2, 'E.T. the Extra-Terrestrial', 3.42).
song(a3, 'Legacy', 3.14).
song(a3, 'Inheritance', 4.13).
song(a4, 'How did I do it?', 4.05).
And I want a query that asks if an album is a single (Got only one song).
recentSingle(+AlbumId).
recentSingle(a1) ?
No
recentSingle(a4) ?
Yes
How do I search in the whole KB and check if it only appears once?
ANSWER:
recentSingle(AlbumId) :- album(AlbumId, _, Year, _),
Year > 2010,
\+ isNotSingle(AlbumId).
isNotSingle(AlbumId) :- song(AlbumId, Name1, _),
song(AlbumId, Name2, _),
Name1 \= Name2.
Regards
Try something like this
recentSingle(X) :- aggregate_all(count, song(X, _, _), Count), Count = 1.
This should work too
recentSingle(X) :- aggregate_all(count, song(X, _, _), 1).

Prolog Query Exercise - Beginner

I'm a begginer at Prolog and I need some help with this exercise, this is the knowledge base provided:
album(‘R. Stevie Moore’, ‘Manuscription’).
album(‘Lane Steinberg’, ‘Manuscription’).
album(‘R. Stevie Moore’, ‘The Yung & Moore Show’).
album(‘Yukio Yung’, ‘The Yung & Moore Show’).
album(‘Jessie Evans’, ‘Autonervous’).
album(‘Bettina Koster’, ‘Autonervous’).
album(‘Lucia Pamela’, ‘Walkin on the moon’).
album(‘Shooby Taylor’, ‘The Human Horn’).
album(‘Tiny Tim’, ‘God Bless Tiny Tim’).
album(‘The Legendary Stardust Cowboy’, ‘Rock-It to Stardom’).
vinil(‘Rock-It to Stardom’).
vinil(‘Walking on the Moon’).
cd( ‘God Bless Tiny Tim’).
cd(‘Walking on the Moon’).
cd(‘Autonervous’).
cd(‘Manuscription’).
cassette(‘The Human Horn’).
cassette(‘The Yung & Moore Show’).
mp3(‘Walkin on the Moon’).
I need to make a query that will return to me all the albums that were made by only one musician.
Thanks for your help :)
In the comments you have provided your code album(X,B),album(Y,C), B \= C. Actually, this is not too far away from a correct solution.
A correct solution could be:
one_musician_album(X) :-
album(A, X),
\+ (album(B, X), A \= B).
The meaning of the predicate is: an album X is a "one-musician album" if this album is authored by some musician A and it's not possible to find a different musician B authored the album X.
Test run:
?- one_musician_album(X).
X = 'Walkin on the moon' ;
X = 'The Human Horn' ;
X = 'God Bless Tiny Tim' ;
X = 'Rock-It to Stardom'.
To get all answers you have to type ';' after each answer.
Maybe this is not needed for you, but it's possible to get all answers in a list with findall:
?- findall(X, one_musician_album(X), Albums).
Albums = ['Walkin on the moon', 'The Human Horn', 'God Bless Tiny Tim', 'Rock-It to Stardom'].
Here is a generalization, based on 'all solutions' builtin bagof/3.
Note that
?- bagof(A, album(A,T), As).
T = 'Autonervous',
As = ['Jessie Evans', 'Bettina Koster'] ;
T = 'God Bless Tiny Tim',
As = ['Tiny Tim']
....
then, restricting the authors (As) to be a list of a single element, we get albums with a single author
?- bagof(A, album(A,T), [A]).
A = 'Tiny Tim',
T = 'God Bless Tiny Tim' ;
...
then, we could use findall/3, as in the good answer by Sergey, or, again, bagof/3, with explicit quantification:
?- bagof(T, A^bagof(A, album(A, T), [A]), Ts).
Ts = ['God Bless Tiny Tim', 'Rock-It to Stardom', 'The Human Horn', 'Walkin on the moon'].

Resources