I am using ancient Turbo Prolog since it is included in our curriculum. Why is this program not working?
domains
disease, indication = symbol
Patient = string
Fe,Ra,He,Ch,Vo,Ru = char
predicates
hypothesis(Patient,disease)
symptom(Patient,indication,char)
response(char)
go
clauses
go:-
write("What is patient's name?"),
readln(Patient),
symptom(Patient,fever,Fe),
symptom(Patient,rash,Ra),
symptom(Patient,head_ache,He),
symptom(Patient,chills,Ch),
symptom(Patient,runny_nose,Ru),
symptom(Patient,head_ache,He),
symptom(Patient,vomit,Vo),
hypothesis(Patient,Disease),
write(Patient," probably has ", Disease , "."),nl.
go:-
write("Sorry unable to seem to be diagnose disease"),nl.
symptom(Patient,Fever,Feedback) :-
Write("Does " , Patient , " have " , Fever , "(y/n) ?"),
response(Reply),
Feedback = Reply.
hypothesis(Patient, chicken_pox) :-
Fe = Ra = He = Ch = 'y'.
hypothesis(Patient, caner) :-
Ru = Ra = He = Vo = 'y'.
hypothesis(Patient, measles) :-
Vo = Ra = Ch = Fe = He = 'y'.
response(Reply):-
readchar(Reply),
write(Reply),nl.
I get the warning variable is only used at all lines which contains symtoms. Isn't the parameter passing call by reference? When i pass Fe to symptoms the value should be copied to Fe and when i compare it in hypothesis it should work accordingly. = operator in Turbo Prolog works very strangely. When it is not bound to any variable, the statement a = 3 will assign 3 to a and when a already contains a value a = 5 will check whether a's value is 5 or not.
Kindly help me why is the program not working?
Thanks in advance :)
The trouble is not with your symptoms/3 predicate, they will bind (unify) their 3rd argument to what response/1 gives. The problem is that these values are never passed into your hypothesis/2 procedure in go/0 so they are never used to try and generate a hypothesis. Prolog doesn't have global variables so you have to explicitly pass all values, though you can keep things in the database which can easily cause problems if you are not careful.
This means that in hypothesis/2 you are not testing the values of Fe, Ra, He, etc but binding local variables with the same names. This is also why you get warnings of the variables only being referenced once, you bind them but never use them. Remember they are local, all variables are local to the clause in which they occur.
All this applies to standard prolog, I have never used Turbo Prolog.
Related
I am learning Prolog, and do not understand why ?- [] = _. returns true in SWI-Prolog.
[] means an empty list, and _ means it is not empty, right?
Could someone explain the above logic?
_ is a logical variable, just like X or anything else that starts with an underscore or a capital letter. Free variables (i.e., variables that are not already bound to some term) can be unified with anything. A goal like [] = X says "unify X with []", with the effect that, if this succeeds, every use of X will refer to the term [].
With _ as the variable this is the same as for X, with the exception that _ is the anonymous variable: It cannot be reused, its name does not matter, and different occurrences of _ refer to different variables. So _ can never be bound before encountering the goal [] = _. Thus this unification succeeds, which is why you get the answer true.
_ does not by itself mean "not empty". But you may be confused by its use as a placeholder: L = [_,_,_] means that L is a list of three elements (that we know nothing about). In this sense _ means "there is something here". But it has to be inside the list for this meaning.
Trying to create a predicate (timePeriod/2) that calculates the time period between two dates for a specific fact. I've managed to do this by myself, but face issues when 'other answers' exist in the same list (i.e. easier to explain with examples).
I have the following knowledge-base facts;
popStar('Jackson',1987,1991).
popStar('Jackson',1992,1996).
popStar('Michaels',1996,2000).
popStar('Newcastle',2000,2007).
popStar('Bowie',2008,2010).
And the following function, calculates the time between dates for a specific fact (as per below).
Predicate (timePeriod/2) -
timePeriod(PS,X) :-
bagof((Name,Start,End),popStar(Name,Start,End),PSs),X is End-Start+1)
Using Bowie as an example; it returns X=3 (which is correct).
However, when there is repetition in the list, with more than one answer available, the predicate just states 'false'. Using the facts 'Jackson' as an example, I want to be able to calculate both of the time periods for both facts; at the same time.
So, if the predicate would work for both of the Jackson facts, the predicate timePeriod would state X=10.
Would really appreciate if anyone could suggest what to change in order for this to work correctly.
Thanks.
You probably don't quite understand what foreach/3 does. I don't think I fully understand foreach/3 either. I know for sure that it is not the same as say:
for each x in xs:
do foo(x)
Another thing: "tuples" in Prolog are not what you might expect, coming from a language like Python or Haskell. This: (a,b,c) is actually this: ','(a,','(b,c)). Much better is to use a flat term, the generic form would be triple(a,b,c). For a pair, the idiom is First-Second.
So, you can simplify your call to bagof/3 to this:
?- bagof(From-To, pop_star(Name, Start, End), Ts).
Name = 'Bowie',
Ts = [2008-2010] ;
Name = 'Jackson',
Ts = [1987-1991, 1992-1996] ;
Name = 'Michaels',
Ts = [1996-2000] ;
Name = 'Newcastle',
Ts = [2000-2007].
Once you have a list as above, you need to sum the differences, which would be maybe something like:
periods_total(Ps, T) :-
maplist(period_length, Ps, Ls),
sum_list(Ls, T).
period_length(From-To, Length) :-
Length is To - From + 1.
And then you can query like this:
?- bagof(From-To, pop_star('Jackson', From, To), Ps), periods_total(Ps, T).
Ps = [1987-1991, 1992-1996],
T = 10.
?- bagof(From-To, pop_star(Name, From, To), Ps), periods_total(Ps, T).
Name = 'Bowie',
Ps = [2008-2010],
T = 3 ;
Name = 'Jackson',
Ps = [1987-1991, 1992-1996],
T = 10 ;
Name = 'Michaels',
Ps = [1996-2000],
T = 5 ;
Name = 'Newcastle',
Ps = [2000-2007],
T = 8.
SWI-Prolog has a nice library to handle aggregation: it builds upon standard 'all solutions' predicates like findall/3,setof/3,bagof/3, so you should first grasp the basic of these (as Boris explained in his answer). With the library, a single query solves your problem:
timePeriod(PS,X) :-
aggregate(sum(P), B^E^(popStar(PS,B,E),P is E-B+1), X).
Trying to create a predicate (timePeriod/2) that calculates the time period between two dates for a specific fact. I've managed to do this by myself, but face issues when 'other answers' exist in the same list (i.e. easier to explain with examples).
I have the following knowledge-base facts;
popStar('Jackson',1987,1991).
popStar('Jackson',1992,1996).
popStar('Michaels',1996,2000).
popStar('Newcastle',2000,2007).
popStar('Bowie',2008,2010).
And the following function, calculates the time between dates for a specific fact (as per below).
Predicate (timePeriod/2) -
timePeriod(PS,X) :-
bagof((Name,Start,End),popStar(Name,Start,End),PSs),X is End-Start+1)
Using Bowie as an example; it returns X=3 (which is correct).
However, when there is repetition in the list, with more than one answer available, the predicate just states 'false'. Using the facts 'Jackson' as an example, I want to be able to calculate both of the time periods for both facts; at the same time.
So, if the predicate would work for both of the Jackson facts, the predicate timePeriod would state X=10.
Would really appreciate if anyone could suggest what to change in order for this to work correctly.
Thanks.
You probably don't quite understand what foreach/3 does. I don't think I fully understand foreach/3 either. I know for sure that it is not the same as say:
for each x in xs:
do foo(x)
Another thing: "tuples" in Prolog are not what you might expect, coming from a language like Python or Haskell. This: (a,b,c) is actually this: ','(a,','(b,c)). Much better is to use a flat term, the generic form would be triple(a,b,c). For a pair, the idiom is First-Second.
So, you can simplify your call to bagof/3 to this:
?- bagof(From-To, pop_star(Name, Start, End), Ts).
Name = 'Bowie',
Ts = [2008-2010] ;
Name = 'Jackson',
Ts = [1987-1991, 1992-1996] ;
Name = 'Michaels',
Ts = [1996-2000] ;
Name = 'Newcastle',
Ts = [2000-2007].
Once you have a list as above, you need to sum the differences, which would be maybe something like:
periods_total(Ps, T) :-
maplist(period_length, Ps, Ls),
sum_list(Ls, T).
period_length(From-To, Length) :-
Length is To - From + 1.
And then you can query like this:
?- bagof(From-To, pop_star('Jackson', From, To), Ps), periods_total(Ps, T).
Ps = [1987-1991, 1992-1996],
T = 10.
?- bagof(From-To, pop_star(Name, From, To), Ps), periods_total(Ps, T).
Name = 'Bowie',
Ps = [2008-2010],
T = 3 ;
Name = 'Jackson',
Ps = [1987-1991, 1992-1996],
T = 10 ;
Name = 'Michaels',
Ps = [1996-2000],
T = 5 ;
Name = 'Newcastle',
Ps = [2000-2007],
T = 8.
SWI-Prolog has a nice library to handle aggregation: it builds upon standard 'all solutions' predicates like findall/3,setof/3,bagof/3, so you should first grasp the basic of these (as Boris explained in his answer). With the library, a single query solves your problem:
timePeriod(PS,X) :-
aggregate(sum(P), B^E^(popStar(PS,B,E),P is E-B+1), X).
I know that the Title ,does not mean anything , however , how to get 'calculas1' word and put it in list from this fact using prolog :
hasMark(calculas1 , 78 , 110).
In Prolog, you can query a fact this way:
hasMark(Subject, X, Y).
Which, in the case of your example, would yield:
Subject = calculus1
X = 78
Y = 110
The easiest way to collect them would be using the builtin, findall:
findall(Subject, hasMark(Subject, _, _), Subjects).
This will yield:
Subjects = [calculus1, ...]
The ... are other subjects, if you have them. Notice that I used _ for two of the parameters. That means I don't care what those values are. Any variable that starts with a _, including that character by itself, means "don't care".
You can also use a predicate like this:
add_subject( MyList, [Subject | MyList] ) :-
hasMark(Subject, _, _).
So you can query:
add_subject( [], List ).
And get:
List = [calculus1].
Note that a naming convention with underscores and lower case is more commonly used in Prolog than "camelCase". So it would be preferred to name your facts has_mark.
I would need help about Prolog.
I posted my code, the problem is that i do not obtain the expected result.
I want planning actions for moving on table all blocks until is possible. To do this I prompt :
?- do(while(some(x, block(x) & -onTable(x)),pi(x,putOnTable(x))),s0,S).
I expect to see a response like :
S = do(putOnTable(e), do(putOnTable(b), do(putOnTable(c), s0)))
but Prolog returns "false" only. Someone can help me??
% Golog interpreter
%:- [golog_swi].
:- discontiguous clear/2, on/3, onTable/2.
:- op(800,xfy,[&]).
do(E,S,do(E,S)):- primitive_action(E),poss(a,S).
% Primitive Action Declarations.
primitive_action(putOn(_,_)).
primitive_action(putOnTable(_)).
poss(putOn(X,Y),S) :- clear(X,S), clear(Y,S), \+ on(X,Y,S), \+ X=Y.
poss(putOnTable(X),S):- clear(X,S), \+(onTable(X,S)).
% Successor State Axioms.
on(X,Y,do(A,S)):- A = putOn(X,Y); on(X,Y,S), \+ (A = putOnTable(X); A = putOn(X,_)).
onTable(X,do(A,S)) :- A = putOnTable(X); onTable(X,S), \+ A= putOn(X,_).
clear(X,do(A,S)) :- on(Y,X,S), (A = putOn(Y,_) ; A = putOnTable(Y)); clear(X,S), \+ A = putOn(_,X).
% Restore suppressed situation arguments
restoreSitArg(onTable(X),S,onTable(X,S)).
restoreSitArg(on(X,Y),S,on(X,Y,S)).
restoreSitArg(clear(X),S,clear(X,S)).
block(X):- member(X,[a,b,c,d,e]).
% iniTial COndition
onTable(a,s0).
on(b,a,s0).
on(c,b,s0).
clear(c,s0).
onTable(d,s0).
on(e,d,s0).
clear(3,s0).
thank you!!!
Your predicate do/3 cannot succeed because the goal primitive_action/1 will fail with your query.
Currently, while/2 is not described in primitive_action/1 and it seems it is missing also from your program. So you need to extend primitive_action/1 by further facts, or add a new rule to do/3. And in addition to that you need to describe what while/2 means.
This question is actually about Golog. Your mistake is pretty mundane: you didn't copy the Golog interpreter code into your source file/directory.
Golog defines a number of high-level programming constructs, including while-loops and non-deterministic picks (pi), used here. I'm sure you don't want to reinvent Golog, so just go and get it. I'm assuming that your question is part of an assignment of sorts, and your teacher probably pointed you to the Golog interpreter. Otherwise, you can always find it on the pages of the cognitive robotics group at the Univ. of Toronto: http://www.cs.toronto.edu/cogrobo/main/systems/index.html