Find people who have children in common and form couples - prolog

I am learning prolog and I have the following facts:
parent(joseph,thiago).
parent(camilla,thiago).
parent(joseph,wanda).
parent(camilla,wanda).
parent(lucas,flora).
parent(joana,flora).
parent(thiago,davi).
parent(flora,davi).
I'm trying to find couples based on this rule: "A couple is made up of two people who have children in common."
couple(X,Y) :-
parent(X,Z),
parent(Y,Z),
write(X), write(' and '), write(Y), write(' are a couple.'), nl, false.
The problem is that some results are returning repeated parents, such as:
"joseph and joseph are a couple!"

Related

A Prolog rule that returns the subgoals in a proof search

I am looking for a simple/straightforward way to write a rule that outputs the antecedents in a proof search (successes of subgoals). Suppose i have the code
winsLottery(john).
healthy(john).
rich(X):-winsLottery(X).
happy(X):-rich(X), healthy(X).
I would like a rule antecedents(L, happy(john)), which returns
L = [
[rich(john), healthy(john)],
[winsLottery(john), healthy(john)]
]
I know about trace/0 but i am looking for a rule. I also tried clause/2 but this just gets the clause where the target event occurs and not any previous antecedents.
My motive is that I am interested in constructing a system that provides explanations for events. I know that i could do causes([rich(X), healthy(X)], happy(X)) in the knowledge base, but i am looking for clean and simple Prolog code that i can translate to classic first order logic (where lists are a bit problematic).
Thanks!
Looking at the suggestions of Guy, here is the solution:
main:-explain(happy(john)).
winsLottery(john).
healthy(john).
rich(X):-winsLottery(X).
happy(X):-rich(X), healthy(X).
explain(X):-
clause(X, B),
B == true.
explain((X1, X2)):-
explain(X1),
explain(X2).
explain(X):-
X \= true,
X \= (_, _),
clause(X, B),
write('An explanation for '), write(X), write(' is: '), nl, write(B), nl, nl,
explain(B).

Prolog If statement fact

I want to state a unique fact in my Prolog data base to change the outcome of my if statement.
My code is as follows:
suspect(Killer, mrBoddy) :-
affair(mrBoddy, Y),
married(X,Y),
write('Killer= '),
write(X), nl;
greedy(X),
write('Killer= '),
write(X), nl.
The output is
?- suspect(Killer, mrBoddy).
Killer= profPlum
true ? ;
Killer= colMustard
yes
My Facts
affair(mrBoddy, msGreen).
affair(mrBoddy,missScarlet).
married(profPlum, msGreen).
rich(mrBoddy).
greedy(colMustard).
motive_to_kill_affair(profPlum).
motive_to_kill_greed(colMustard).
I want to add a fact that will change the output to only one "Killer". Doesn't matter who it is. How could I achieve this?

Execution tree meta interpreting

I have tracing meta-interpreter made from my previous questions here and I would like to make similar meta-interpreter but this time for making execution trees.
I've made something like this below using similar to same code found on the web and techniques from my previous questions.
clause_tree(true,_,true) :- !, true.
clause_tree((G,R),Trail,(TG,TR)) :-
!,
clause_tree(G,Trail,TG),
clause_tree(R,Trail,TR).
clause_tree(G,_,prolog(G)) :-
(predicate_property(G,built_in) ;
predicate_property(G,compiled) ),
call(G).
clause_tree(G,Trail,tree(G,T)) :-
clause(G,Body),
clause_tree(Body,[G|Trail],T).
why(G) :-
call_with_depth_limit(
catch(
clause_tree(G,[],T),
cut,
fail),
30,
_Message),
nl,
draw_tree(T,0).
draw_tree(tree(Root,Branches),Tab) :- !,
tab(Tab),
write(Tab),
write(': '),
write(Root),
nl,
Tab1 is Tab + 1,
draw_tree(Branches,Tab1).
draw_tree((B,Bs),Tab) :- !,
draw_tree(B,Tab),
draw_tree(Bs,Tab).
draw_tree(Node,Tab) :-
tab(Tab),
write(Tab),
write(': '),
write(Node),
nl.
%example program for testing
%?-p(X).
p(X) :- a(X).
p(X) :- b(X),c(X), d(X),e(X).
p(X) :- f(X).
b(Y) :- g(Y), h(Y).
b(1).
b(2).
a(1).
c(1).
c(2).
d(1).
d(2).
e(2).
f(3).
g(2).
g(1).
h(2).
How can I alter this interpreter that it displays branches that fails and that tree is only one with all solutions? Consider that trees are done only for similar programs like example program written in code if that matters.
I am using swi-prolog.
Edit : I am trying to achieve something like this but in textual form.

creating a menu in prolog?

menu :-
repeat,
write(' '),nl,
write(' 1.the number of hello '),nl,
write(' '),nl,
write('enter your choice:'),nl,
read(Choice), Choice>0, Choice =<6,
doit(Choice),Choice=6.
doit(1):- numberofhello(N).
doit(6):- abort.
my_list([hello,hello,hello]).
counthowmany(_, [], 0) :- !.
counthowmany(X, [X|Q], N) :- !, counthowmany(X, Q, N1), N is N1+1.
counthowmany(X, [_|Q], N) :- counthowmany(X, Q, N).
numberofhello(N) :- my_list(L),counthowmany(hello,L,N).
now in the code above after compile buffer when I ask Prolog for a menu the menu appears
with one choice and when i enter 1 for number of hello in the list(my_list) i don't get any answer and i get a singleton variable warning while compiling .....
can anyone help me please........
A "singleton" variable is very similar, in other languages, to the warning, "Variable was assigned a value that is never used" or "A variable has been declared but never used". So your clause must do something with N in your first doit clause. You can also avoid the doit(6) :- abort. clause by allowing your menu to succeed without any choice points using a cut (!).
So, try:
menu :- repeat,
write(' '),nl,
write(' 1.the number of hello '),nl,
write(' '),nl,
write('enter your choice:'),nl,
read(Choice), Choice>0, Choice =<6,
doit(Choice), Choice=6, !.
doit(1):-
numberofhello(N),
write('Number of hello is = '), write(N), nl.
% Removed doit(6)...
...

swi prolog solve

I am using SWI Prolog for windows 7 and one of my assignments is a basic logic puzzle. We have been given a sample solution to a seperate problem - including its source code.
Its the "Its a tie" problem. However I do not know how to get results using the Solve:- predicate. After consulting the .pl file do I have to input a specific command to the console or anything like that?
Thanks for any help.
Source Code (I did not write this code) :
% Problem #1, "It's a tie", Dell Logic Puzzles, October 1999
% Each man (mr so-and-so) got a tie from a relative.
tie(cupids).
tie(happy_faces).
tie(leprechauns).
tie(reindeer).
mr(crow).
mr(evans).
mr(hurley).
mr(speigler).
relative(daughter).
relative(father_in_law).
relative(sister).
relative(uncle).
solve :-
tie(CrowTie), tie(EvansTie), tie(HurleyTie), tie(SpeiglerTie),
all_different([CrowTie, EvansTie, HurleyTie, SpeiglerTie]),
relative(CrowRelative), relative(EvansRelative),
relative(HurleyRelative), relative(SpeiglerRelative),
all_different([CrowRelative, EvansRelative, HurleyRelative, SpeiglerRelative]),
Triples = [ [crow, CrowTie, CrowRelative],
[evans, EvansTie, EvansRelative],
[hurley, HurleyTie, HurleyRelative],
[speigler, SpeiglerTie, SpeiglerRelative] ],
% 1. The tie with the grinning leprechauns wasn't a present from a daughter.
\+ member([_, leprechauns, daughter], Triples),
% 2. Mr. Crow's tie features neither the dancing reindeer nor the yellow happy faces.
\+ member([crow, reindeer, _], Triples),
\+ member([crow, happy_faces, _], Triples),
% 3. Mr. Speigler's tie wasn't a present from his uncle.
\+ member([speigler, _, uncle], Triples),
% 4. The tie with the yellow happy faces wasn't a gift from a sister.
\+ member([_, happy_faces, sister], Triples),
% 5. Mr Evans and Mr. Speigler own the tie with the grinning leprechauns
% and the tie that was a present from a father-in-law, in some order.
( (member([evans, leprechauns, _], Triples),
member([speigler, _, father_in_law], Triples)) ;
(member([speigler, leprechauns, _], Triples),
member([evans, _, father_in_law], Triples)) ),
% 6. Mr. Hurley received his flamboyant tie from his sister.
member([hurley, _, sister], Triples),
tell(crow, CrowTie, CrowRelative),
tell(evans, EvansTie, EvansRelative),
tell(hurley, HurleyTie, HurleyRelative),
tell(speigler, SpeiglerTie, SpeiglerRelative).
% Succeeds if all elements of the argument list are bound and different.
% Fails if any elements are unbound or equal to some other element.
all_different([H | T]) :- member(H, T), !, fail.
all_different([_ | T]) :- all_different(T).
all_different([_]).
tell(X, Y, Z) :-
write('Mr. '), write(X), write(' got the '), write(Y),
write(' tie from his '), write(Z), write('.'), nl.
After consulting the file, just type the name of the predicate, with the arguments in parentheses (if there are any), followed by a period. If you have more than one predicate in your query, separate them by commas. In your case (I called the file solve.pl):
?- [solve].
% solve compiled 0.00 sec, 18 clauses
true.
?- solve.
Mr. crow got the cupids tie from his daughter.
Mr. evans got the leprechauns tie from his uncle.
Mr. hurley got the reindeer tie from his sister.
Mr. speigler got the happy_faces tie from his father_in_law.
true ;
false.
?-

Resources