How can I make this code asks each question once? - prolog

I'm trying this code on SWI-Prolog:
go :-
write('What is the patient''s name? '),
read(Patient),
hypothesis(Patient,Disease),
write_list([Patient,'probably has ',Disease,'.']),nl.
go :-
write('Sorry, I don''t seem to be able to'),nl,
write('diagnose the disease.'),nl.
symptom(Patient,fever) :-
write_list(['Does ',Patient,' have a fever (y/n) ?']),
response(Reply),
Reply='y'.
symptom(Patient,rash) :-
write_list(['Does ',Patient,' have a rash (y/n) ?']),
response(Reply),
Reply='y'.
symptom(Patient,headache) :-
write_list(['Does ',Patient,' have a headache (y/n) ?']),
response(Reply),
Reply='y'.
symptom(Patient,runny_nose) :-
write_list(['Does ',Patient,' have a runny_nose (y/n) ?']),
response(Reply),
Reply='y'.
symptom(Patient,conjunctivitis) :-
write_list(['Does ',Patient,' have a conjunctivitis (y/n) ?']),
response(Reply),
Reply='y'.
symptom(Patient,cough) :-
write_list(['Does ',Patient,' have a cough (y/n) ?']),
response(Reply),
Reply='y'.
symptom(Patient,body_ache) :-
write_list(['Does ',Patient,' have a body_ache (y/n) ?']),
response(Reply),
Reply='y'.
symptom(Patient,chills) :-
write_list(['Does ',Patient,' have a chills (y/n) ?']),
response(Reply),
Reply='y'.
symptom(Patient,sore_throat) :-
write_list(['Does ',Patient,' have a sore_throat (y/n) ?']),
response(Reply),
Reply='y'.
symptom(Patient,sneezing) :-
write_list(['Does ',Patient,' have a sneezing (y/n) ?']),
response(Reply),
Reply='y'.
symptom(Patient,swollen_glands) :-
write_list(['Does ',Patient,' have a swollen_glands (y/n) ?']),
response(Reply),
Reply='y'.
hypothesis(Patient,measles) :-
symptom(Patient,fever),
symptom(Patient,cough),
symptom(Patient,conjunctivitis),
symptom(Patient,runny_nose),
symptom(Patient,rash).
hypothesis(Patient,german_measles) :-
symptom(Patient,fever),
symptom(Patient,headache),
symptom(Patient,runny_nose),
symptom(Patient,rash).
hypothesis(Patient,flu) :-
symptom(Patient,fever),
symptom(Patient,headache),
symptom(Patient,body_ache),
symptom(Patient,conjunctivitis),
symptom(Patient,chills),
symptom(Patient,sore_throat),
symptom(Patient,runny_nose),
symptom(Patient,cough).
hypothesis(Patient,common_cold) :-
symptom(Patient,headache),
symptom(Patient,sneezing),
symptom(Patient,sore_throat),
symptom(Patient,runny_nose),
symptom(Patient,chills).
hypothesis(Patient,mumps) :-
symptom(Patient,fever),
symptom(Patient,swollen_glands).
hypothesis(Patient,chicken_pox) :-
symptom(Patient,fever),
symptom(Patient,chills),
symptom(Patient,body_ache),
symptom(Patient,rash).
hypothesis(Patient,measles) :-
symptom(Patient,cough),
symptom(Patient,sneezing),
symptom(Patient,runny_nose).
write_list([]).
write_list([Term| Terms]) :-
write(Term),
write_list(Terms).
response(Reply) :-
read_line_to_codes(user_input, Codes),
nth0(0, Codes, FirstCode),
char_code(Reply, FirstCode).
**And sometimes and randomly it asks the same question multiple times when it was already answered. Help please.**

You can use a dynamic predicate to store the answers to questions that have been asked before. Thus, when the system is verifying a hypothesis, it will not repeat the questions that were already asked during the verification of hypotheses that have already been verified previously.
:- dynamic symptom/3.
go :-
retractall(symptom(_, _, _)), % clear the database
write('What is the patient''s name? '),
read_atom(Patient),
hypothesis(Patient,Disease),
write_list([Patient,' probably has ', Disease, '.']),
nl.
go :-
write('Sorry, I don''t seem to be able to'),nl,
write('diagnose the disease.'),nl.
read_atom(Atom) :-
read_line_to_string(user_input, String), % <== EDIT: user_input instead of user
atom_string(Atom, String).
symptom(Patient, Symptom) :-
( symptom(Patient, Symptom, Answer) % If the answer is already known
-> true % then don't ask it again
; write_list(['Does ',Patient,' have a ', Symptom, ' (y/n)? ']), % else ask the question
read_atom(Answer), % read the answer and
assertz(symptom(Patient, Symptom, Answer)) % store it into the database
),
Answer = y.
hypothesis(Patient, measles) :-
symptom(Patient, fever),
symptom(Patient, cough),
symptom(Patient, conjunctivitis),
symptom(Patient, runny_nose),
symptom(Patient, rash).
hypothesis(Patient, german_measles) :-
symptom(Patient, fever),
symptom(Patient, headache),
symptom(Patient, runny_nose),
symptom(Patient, rash).
hypothesis(Patient, flu) :-
symptom(Patient, fever),
symptom(Patient, headache),
symptom(Patient, body_ache),
symptom(Patient, conjunctivitis),
symptom(Patient, chills),
symptom(Patient, sore_throat),
symptom(Patient, runny_nose),
symptom(Patient, cough).
hypothesis(Patient, common_cold) :-
symptom(Patient, headache),
symptom(Patient, sneezing),
symptom(Patient, sore_throat),
symptom(Patient, runny_nose),
symptom(Patient, chills).
hypothesis(Patient, mumps) :-
symptom(Patient, fever),
symptom(Patient, swollen_glands).
hypothesis(Patient, chicken_pox) :-
symptom(Patient, fever),
symptom(Patient, chills),
symptom(Patient, body_ache),
symptom(Patient, rash).
hypothesis(Patient, measles) :-
symptom(Patient, cough),
symptom(Patient, sneezing),
symptom(Patient, runny_nose).
write_list([]).
write_list([Term| Terms]) :-
write(Term),
write_list(Terms).

Related

SWI prolog return true instead of variable

here is my code
/*facts*/
male(James).
male(Charles).
male(William).
female(Megan).
male(George).
female(Catherine).
female(Diana).
female(Elizabith).
parent(James,Charles).
parent(James,Elizabeth).
parent(Charles,Catherine).
parent(Charles,William).
parent(Charles,Megan).
parent(Elizabeth,Diana).
parent(Diana,George).
/*rules*/
different(X,Y):- X\=Y.
father(X, Y) :- parent(X,Y), male(X).
mother(X, Y) :- parent(X,Y), female(X).
grandparent(X,Y):- parent(X,F), parent(F,Y).
grandma(X,Y):- parent(X,F), parent(F,Y),female(X).
sister(X,Y):-female(X), parent(F,X), parent(F,Y),different(X,Y) .
brother(X,Y):-male(X), parent(F,X), parent(F,Y),different(X,Y).
aunt(X,Y):-parent(F,Y), sister(X,F), female(X).
uncle(X,Y):-parent(F,Y), brother(X,F), male(X).
i write mother(X,Y). expecting return name not true or false .
same with all statements
Your facts use variables and not constants. Constants and functors start with a lowercase, so james, charles, megan and diana, not James, Charles, Megan and Diana:
male(james).
male(charles).
male(william).
female(megan).
male(george).
female(catherine).
female(diana).
female(elizabith).
parent(james, charles).
parent(james, elizabeth).
parent(charles, catherine).
parent(charles, william).
parent(charles, megan).
parent(elizabeth, diana).
parent(diana, george).

Do not know how to say male(X) not equal to female(X)

I have the following code in prolog.
male(X).
female(X).
child(X,Y).
mother(X,Y) :- female(X), child(Y,X).
this code outputs yes even when I test it as
male(X), mother(X,Y).
I don't how should I code male(X) is not equal to female(X) in this?
I have tried mother(X,Y) :- female(X), !, +male(X), child(Y,X). But this doesn't work.

How do I run a program like this in GNU-Prolog?

Every time I would try to compile it, the compilation would always seem to fail. I am very new to the language and have discovered this program while looking for examples of programs that use Prolog but I am at a loss on how to run it. The reason for using this program fragment as an example is that I would like to make a program of my own that will be able to let the user know what sickness they have based on the symptoms that the user entered.
domains
disease,indication = symbol.
Patient,name = string.
predicates
hypothesis(string,disease).
symptom(name,indication).
response(char).
go.
clauses
the program would detect an error at very first lines and I'm not sure why.
go :-
write("What is the patient's name? "),
readln(Patient),
hypothesis(Patient,Disease),
write(Patient,"probably has ",Disease,"."),nl.
go :-
write("Sorry, I don't seem to be able to"),nl,
write("diagnose the disease."),nl.
symptom(Patient,fever) :-
write("Does ",Patient," have a fever (y/n) ?"),
response(Reply),
Reply='y'.
symptom(Patient,rash) :-
write("Does ",Patient," have a rash (y/n) ?"),
response(Reply),
Reply='y'.
symptom(Patient,headache) :-
write("Does ",Patient," have a headache (y/n) ?"),
response(Reply),
Reply='y'.
symptom(Patient,runny_nose) :-
write("Does ",Patient," have a runny_nose (y/n) ?"),
response(Reply),
Reply='y'.
symptom(Patient,conjunctivitis) :-
write("Does ",Patient," have a conjunctivitis (y/n) ?"),
response(Reply),
Reply='y'.
symptom(Patient,cough) :-
write("Does ",Patient," have a cough (y/n) ?"),
response(Reply),
Reply='y'.
symptom(Patient,body_ache) :-
write("Does ",Patient," have a body_ache (y/n) ?"),
response(Reply),
Reply='y'.
symptom(Patient,chills) :-
write("Does ",Patient," have a chills (y/n) ?"),
response(Reply),
Reply='y'.
symptom(Patient,sore_throat) :-
write("Does ",Patient," have a sore_throat (y/n) ?"),
response(Reply),
Reply='y'.
symptom(Patient,sneezing) :-
write("Does ",Patient," have a sneezing (y/n) ?"),
response(Reply),
Reply='y'.
symptom(Patient,swollen_glands) :-
write("Does ",Patient," have a swollen_glands (y/n) ?"),
response(Reply),
Reply='y'.
hypothesis(Patient,measles) :-
symptom(Patient,fever),
symptom(Patient,cough),
symptom(Patient,conjunctivitis),
symptom(Patient,runny_nose),
symptom(Patient,rash).
hypothesis(Patient,german_measles) :-
symptom(Patient,fever),
symptom(Patient,headache),
symptom(Patient,runny_nose),
symptom(Patient,rash).
hypothesis(Patient,flu) :-
symptom(Patient,fever),
symptom(Patient,headache),
symptom(Patient,body_ache),
symptom(Patient,conjunctivitis),
symptom(Patient,chills),
symptom(Patient,sore_throat),
symptom(Patient,runny_nose),
symptom(Patient,cough).
hypothesis(Patient,common_cold) :-
symptom(Patient,headache),
symptom(Patient,sneezing),
symptom(Patient,sore_throat),
symptom(Patient,runny_nose),
symptom(Patient,chills).
hypothesis(Patient,mumps) :-
symptom(Patient,fever),
symptom(Patient,swollen_glands).
hypothesis(Patient,chicken_pox) :-
symptom(Patient,fever),
symptom(Patient,chills),
symptom(Patient,body_ache),
symptom(Patient,rash).
hypothesis(Patient,measles) :-
symptom(Patient,cough),
symptom(Patient,sneezing),
symptom(Patient,runny_nose).
response(Reply) :-
readchar(Reply),
write(Reply),nl.
Your code seems to be TurboProlog or Visual Prolog code. Start by deleting the code starting with domains up to clauses. You will also need to replace the calls to readchar/1 and readln/1 predicates with calls to standard Prolog predicates such as read/1 or read_term/3. In the particular case, of readchar/1, and only for running under GNU Prolog, you can define it as:
readchar(Char) :-
get_key(Code), char_code(Char, Code), nl.
Some other Prolog systems provide a readchar functionality but there's no standard. The main difference of these predicates compared with the standard get_char/1 predicate is not requiring a return/enter when used at the top-level.
Also, replace all calls to write with arity greater then 1 with a sequence of calls to the standard write/1 predicate and replace in those calls the double quotes with single quotes.

Error in Family Tree using Prolog

I have some issues in my family tree. As required, I need to create predicates on father, mother, son, daughter, grandfather, sibling, aunt, uncle, cousin, spouse, parent_of based on the facts of Male, Female, parent_of.
male(jerry).
male(stuart).
male(warren).
male(peter).
female(kather).
female(maryalice).
female(ann).
brother(jerry,stuart).
brother(jerry,kather).
brother(peter, warren).
sister(ann, maryalice).
sister(kather,jerry).
parent_of(warren,jerry).
parent_of(maryalice,jerry).
father(X,Y) :- male(X), parent_of(X,Y).
mother(X,Y) :- female(X), parent_of(X,Y).
son(X,Y) :- male(X), parent_of(Y,X).
daughter(X,Y) :- female(X), parent_of(Y,X).
grandfather(X,Y) :- father(X,P), parent_of(P,Y).
sibling(X,Y):- parent_of(P,X), parent_of(P,Y), X\=Y.
aunt(X,Y) :- sister(X,P), parent_of(P,Y).
uncle(X,Y) :- brother(X,P), parent_of(P,Y).
cousin(X,Y):- sibling(P,Q), parent_of(P,X), parent_of(Q,Y).
spouse(X,Y) :- parent_of(X,P), parent_of(Y,P).
parent_of(X,Y) :- male(X), father(X,Y); female(X), mother(X,Y).
The parent_of predicate gives me an error. Clasues of parent_of/2 are not together in the source file. When I ignore the error and run a query ?- sibling(jerry, stuart), it gives me an error out of local stack. Anyone know how to solve this problem. Your help will be appreicated. Thanks.
Problem 1
The parent_of predicate gives me an error. Clasues of parent_of/2 are not together in the source file.
Simply place definitions of the predicate right next to eachother
Change
parent_of(warren,jerry).
parent_of(maryalice,jerry).
...
spouse(X,Y) :- parent_of(X,P), parent_of(Y,P).
parent_of(X,Y) :- male(X), father(X,Y); female(X), mother(X,Y).
to
parent_of(warren,jerry).
parent_of(maryalice,jerry).
parent_of(X,Y) :- male(X), father(X,Y); female(X), mother(X,Y).
...
spouse(X,Y) :- parent_of(X,P), parent_of(Y,P).
Problem 2
?- sibling(jerry, stuart), it gives me an error out of local stack.
You have a circular logic error. You define parent_of\2 in terms of father\2 and father\2 in terms of parent_of\2. This will cause each to circle off into Prolog never-never-land.

How can I refractor the display functions?

I have these display functions:
display_siblings(X,Y):-
setof(X-Y, (siblings(X,Y), ordered(X-Y)), Sibs),
write('The siblings of'),
write(X),
write('are'),nl,
foreach(member(Pair, Sibs),
writeln(Pair)),nl,
write('% end'), nl.
display_sisters(X,Y):-
setof(X-Y, (sisters(X,Y), ordered(X-Y)), Sibs),
write('The sisters of'),
write(X),
write('are'),nl,
foreach(member(Pair, Sibs),
writeln(Pair)),nl,
write('% end'), nl.
As you can see only the second argument of setof is changing.
Could I make one display function of both and if it can how can I do this?
Roelof
One way would be:
display_siblings(X, Y):-
setof(X-Y, (siblings(X, Y), ordered(X-Y)), Sibs),
write('The siblings of'),
write_sibs(X, Sibs).
display_sisters(X, Y) :=
setof(X-Y, (sisters(X, Y), ordered(X-Y)), Sibs),
write('The sisters of'),
write_sibs(X, Sibs).
write_sibs(X, Sibs):-
write(X),
write('are'), nl,
foreach(member(Pair, Sibs),
writeln(Pair)),nl,
write('% end'), nl.
Another way would be:
display_siblings(X, Y) :-
display('siblings', X, Y).
display_sisters(X, Y) :-
display('sisters', X, Y).
display(Type, X, Y) :-
setof(X-Y, (call(Type, X, Y), ordered(X-Y)), Sibs),
write('The '), write(Type), write(' of'),
write(X),
write('are'),nl,
foreach(member(Pair, Sibs),
writeln(Pair)),nl,
write('% end'), nl.

Resources