Twins in family database - prolog

Here is my family database. But I am unable to find out twin babies from this database. I am given this question: Define the relation twins(Child1, Child2) to find twins in the family database.
family(
person(tom,right,date(17,may,1950),works(mathematician)),
person(ann,right,date(29,may,1951),unemployed),
[
person(pat,right,date(5,may,1983),unemployed),
person(max,right,date(5,may,1983),unemployed)
]).
family(
person(nick,wellbard,date(15,september,1954),works(electrician)),
person(cathrine,wellbard,date(11,march,1970),unemployed),
[
person(john,wellbard,date(15,may,1983),works(musician)),
person(mike,wellbard,date(25,may,1989),unemployed),
person(chloe,wellbard,date(15,may,1983),unemployed)
]).
family(
person(john,brock,date(17,january,1978),unemployed),
person(mary,brock,date(19,march,1951),works(teacher)),
[
person(tony,brock,date(20,may,1975),unemployed),
person(sasha,brock,date(1,april,1979),unemployed),
person(josh,brock,date(29,april,1983),unemployed)
]).
family(
person(abc,xyz,date(17,may,1950),works(mathematician)),
person(def,xyz,date(29,may,1951),unemployed),
[]).
Any help will be appreciated.

Well,it's simple to control that you have same family name and also same date of birth.
in_list(person(Name,F,date(D,M,Y),W),[person(Name,F,date(D,M,Y),W)|_T]):-
!.
in_list(X,[_|T]):-
in_list(X,T).
twins(person(Nam,F,Date,W),person(Name,F,Date,We)):-
family(person(_,F,_,_),person(_,F,_,_),T),
in_list(person(Nam,F,Date,W),T),
in_list(person(Name,F,Date,We),T).

Related

Visual Prolog 5.2 The variable is not bound in this clause

I have "in" predicate that goes through "people". But the X doesnt get a "person" and returns false, as i understood. Test goal and Run throw the same error
domains
person = c(name, nationality)
people = person*
name, nationality = symbol
predicates
name(person, name)
nationality (person, nationality)
in(person, people)
solve
clauses
name(c(N,_), N).
nationality (c(_,T), T).
in(X,[X,_,_,_]). %Error here
in(X,[_,X,_,_]).
in(X,[_,_,X,_]).
in(X,[_,_,_,X]).
solve :- in(C1, People), name(C1, brown),
in(C2, People), name(C2, clemens),
in(C3, People), name(C3, grifit),
in(C4, People), name(C4, grin),
in(C5, People), nationality(C5, canadian),
in(C6, People), nationality(C6, american),
in(C7, People), nationality(C7, australian),
in(C8, People), nationality(C8, british),
not(nationality(C1, british)),
not(nationality(C2, british)),
not(nationality(C3, american)),
not(nationality(C3, australian)),
not(nationality(C1, australian)),
not(nationality(C4, australian)),
write(People), nl.
goal
solve.
I expect X to be bound to the person (people item). What am I doing wrong?

Prolog book database (how to get results grouped by author?)

I have a the following database of facts like:
...
book(title1, author1),
book(title2, author2),
book(title3, author3),
book(title4, author1),
book(title5, author2),
...
I need to write a prolog query or rule to get titles grouped by the author (author1, author2...). I can't change order of facts in database.
For now I have only query looking like this:
book(T1, A), book(T2, A), T1 \= T2.
but it returns same thing few times
thanks in advance

How to findall for universal facts in prolog?

In Prolog I can write
child(martha,charlotte).
child(charlotte,caroline).
child(caroline,laura).
child(laura,rose).
descend(X,Y) :-
child(X,Y).
descend(X,Y) :-
child(X,Z),
descend(Z,Y).
And then write
?- findall(X,descend(martha,X),Z).
and get four solutions
Z = [charlotte,caroline,laura,rose]
But if I then add an universal fact
likes(X,pomegranate).
and try
?- findall(X,likes(X, pomegranate),Z).
I get:
Z = [_G17].
What is that _G17?
What do I need to change to get essentially all variables? ( since likes(X,pomegranate) should mean everything likes pomegranate... right?) :
Z = [martha,charlotte,caroline,laura,rose]
Two solutions. The clean solution is to have a table that lists all "things" in the universe you describe:
person(martha).
person(charlotte).
% etc
And then your "likes" would be rather:
person_likes(P, pomegranate) :-
person(P).
You can also try to hack around it:
person(P) :- child(P, _).
person(P) :- child(_, P).
But this is... unsatisfactory? Think about a relational database: you would have two tables:
CREATE TABLE person (
id INTEGER PRIMARY KEY, -- usually autogenerated
name TEXT NOT NULL
);
CREATE TABLE parent_child (
parent_id INTEGER NOT NULL,
child_id INTEGER NOT NULL,
FOREIGN KEY parent_id REFERENCES person(id),
FOREIGN KEY child_id REFERENCES person(id)
);
The only reason, as far as I am aware, why you don't do the exact same thing in Prolog, is that most introductory tutorials are trying to seduce you and avoid going into such details. And of course the Prolog "database" is not a true relational database (for example, argument position does matter!).
TL;DR You can't avoid thinking about Prolog's resolution strategy when using Prolog.

Prolog queries beginner

Given the predicates
hasAccount(Person,Bank,Amount) – the Person has an account at the Bank with the balance Amount
lives(Person,City) – the Person lives in the City
created(Person,Bank,Month,Year) – the Person opened an account at the Bank in Month of the Year
how would you find someone who has the oldest account at the same bank using only the following "- , < =< > >= not" operators? I'm deeply lost!
Based on your comment, \+ is used for not (not proveable):
created(Who,Somebank,Month1,Year1),
\+ ( created(_,Somebank,Month2,Year2), older(Month2,Year2,Month1,Year1) )
with older/4 defined as:
older(_Month2,Year2,_Month1,Year1) :- Year2 < Year1.
older(Month2,Year,Month1,Year) :- Month2 < Month1.

A prolog assignment which uses lists

I have an assignment that's driving me crazy.... Here's the assignment:
The following contacts for people in a company are kept as facts as the followings:
phones(joao, [home/217777777, mobile91/917777777]).
phones(maria, [work/218888888, mobile93/938888888, mobile91/918888888]).
phones(jose, [home/213333333, mobile91/914444444]).
Define predicates in Prolog that allow to answer the following question:
1) Which are the possible contacts availiable if you want to phone to any person in a group?
For example:
?- all_contacts([joao,jose],ListOfContacts).
ListOfContactss = [home/217777777, mobile91/917777777, home/213333333,mobile91/914444444]
What I've done is this:
all_contacts([],_):-[].
all_contactos([X|T],LIST):-phones(X,LIST),all_contacts(T,Y).
However if I do:
?- all_contactos([jose,maria],LIST_CONTACTS).
LIST_CONTACTS = [casa/213333333, movel91/914444444].
That is, I only get the contacts for the first person on the list.
Thanks for any help.
You can use the meta predicate findall to collect the phones for all contacts of an input list:
all_contacts(People, Contacts):-
findall(Contact,
( member(Person, People), % For each person
phones(Person, LContact), % get the list of contacts of person
member(Contact, LContact) % collect each contact from that list
), Contacts). % Finally gather all contacts in one list
For your example this yields:
all_contacts([jose,maria],LIST_CONTACTS).
LIST_CONTACTS = [home/213333333, mobile91/914444444, work/218888888, mobile93/938888888, mobile91/918888888].
If you don't want to use builtin predicate you can achieve the same thing using recursive predicates by iterating over all the people and then over every phone for each person, and building a list of contacts along the recursion:
all_contacts(People, Contacts):-
all_contacts(People, [], Contacts).
all_contacts([], Contacts, Contacts).
all_contacts([Person|People], Contacts, NContacts):-
phones(Person, LContacts),
all_contacts_person(LContacts, Contacts, MContacts),
all_contacts(People, MContacts, NContacts).
all_contacts_person([], Contacts, Contacts).
all_contacts_person([Contact|LContacts], Contacts, MContacts):-
all_contacts_person(LContacts, [Contact|Contacts], MContacts).

Resources