How to get both drive predicates working in prolog? - prolog

begin:-
go,
initialise. % drive predicate
begin:-
write('Sorry cannot help'),nl,nl.
go:-
write('Below is the list of the current toys available within the
store.'),nl,nl,nl,nl,
loop_through_list([car, football, action_men, train_tracks, lego, football, bikes, control_car, drees_up, doll, bear, furbies, craft, doll_house]).
loop_through_list([Head|Tail]) :-
write(Head),
write(' '),
loop_through_list(Tail).
initialise:-
nl,nl,nl,nl,
tab(40),write('******************************************'),nl,
tab(40),write('*** TOY GENERATING SYSTEM ***'),nl,
tab(40),write('******************************************'),nl,nl,
write('Please answer the following questions'),
write(' y (yes) or n (no).'),nl,nl, nl, nl.
The problem here is that the go:- and the initialise:- work separately when on their own, but not when put together. Is there a problem with all the nls?

The problem is that go/0 doesn't work corrently. While it prints the list, it fails at the end, meaning that the execution will stop afterwards. Therefore, when you run begin/0, initialize/0 will never run.
To fix it you need to add a base case for loop_through_list/0:
loop_through_list([]).
loop_through_list([Head|Tail]) :-
write(Head),
write(' '),
loop_through_list(Tail).
As a side note, "print_list" would be a more descriptive name for loop_through_list/0

Related

Prolog predicate with multiple lists

I'm using swipl but working the adventure tuorial from Amzi!. The syntax difference is causing me a headache. After setting up the facts, I have these statements
list_things(Place) :-
location(X, Place),
tab(2),
write(X), nl,
false.
list_connections(Place) :-
connect(Place, X),
tab(2),
write(X), nl,
false.
look :-
here(Place),
write('You are in the '), write(Place), nl,
write("You can go to: "), nl,
list_connections(Place), nl,
write('You can see: '), nl,
list_things(Place).
When I run look., it only outputs the first list from list_connections. That is
?- look.
You are in the kitchen
You can go to:
office
cellar
dining room
false.
Now, I understand the false at the end of the function is terminating the look, but I don't know the correct syntax in swipl.
Now, I understand the false at the end of the function is terminating the look
The false at the end of list_connections(Place) forces it to backtrack and retry, writing all the connected places as it does so. Once it has got through them all and failed for the last time, I think there is supposed to be another rule for it:
list_connections(_).
I see it here in Amzi! chapter 5:
That rule is a "succeed for anything" rule which will allow look to carry on and then list_things can run. And there is a similar one for list_things.

Prolog Beginner - macbook

Current college student here and have to learn Prolog this semester. Wanted to mess around and get ahead and learn it before we actually get into any assignments and I am lost lol.
I am creating a project for a program where it is dedicated to movies
I have my movie.pl file with things such as:
%acted_in(person,movie).
acted_in(brad_pitt,babel).
acted_in(cate_blanchette,babel).
acted_in(sharlto_copley,district_9).
acted_in(david_james,district_9).
%directed(person,movie).
directed(alejandro_inarritu,babel).
directed(neill_blomkamp,district_9).
%released(movie,year).
released(babel,2006).
released(district_9,2009).
Those are just some of the ones I have in there. Now my teacher does have stuff up already since he recommended we went ahead and tried our own programs. He went ahead and gave us a makefile that is supposed to work with everything just needed to change the EXE=movie.
The part where I am lost is on the main.pl. Say I have multiple different questions to put in, how would I add them? Do I just add a writeln with a new question under the previous print_query_false?
%main.pl
:- [movie].
print_query_true(Q) :-
forall(Q, writeln(true:Q)).
print_query_false(Q) :-
forall(\+ Q, writeln(false:Q)).
main :-
nl
writeln( "1. Did Leonardo DiCaprio act in Babel?" ),
print_query_true(acted_in(leonardo_dicaprio,babel)),
print_query_false(acted_in(leonardo_dicaprio,babel)),
nl,
halt.
The last problem I have is when i try to run swipl it goes through and turns on the program. but when i type in [movie]. it just says true and doesn't show that is says compiled or anything of the sort.
The part where I am lost is on the main.pl. Say I have multiple different questions to put in, how would I add them? Do I just add a writeln with a new question under the previous print_query_false?
Yes, for example:
main :-
nl,
format( "1. Did Leonardo DiCaprio act in Babel?" ),
nl,
print_query_true(acted_in(leonardo_dicaprio,babel)),
print_query_false(acted_in(leonardo_dicaprio,babel)),
nl,
format( "2. Was babel released in 2006?" ),
nl,
print_query_true(released(babel, 2006)),
print_query_false(released(babel, 2006)),
nl,
format( "3. Did anyone act in both Click and The Aviator?" ),
nl,
print_query_true((acted_in(X, click), acted_in(X, the_aviator))),
print_query_false((acted_in(X, click), acted_in(X, the_aviator))),
nl,
format("4. Did sharlto_copley and david_james both act in district_9?"),
nl,
print_query_true((acted_in(sharlto_copley, district_9), acted_in(david_james, district_9))),
print_query_false((acted_in(sharlto_copley, district_9), acted_in(david_james, district_9))),
nl,
format("5. Was there any two movies released in 2006 and 2009?"),
nl,
print_query_true((released(X, 2006), released(Y, 2009))),
print_query_false((released(X, 2006), released(Y, 2009))),
nl,
format("6. What actors acted in babel or district 9?"),
nl,
print_query_true((acted_in(X, babel) ; acted_in(X, district_9))),
print_query_false((acted_in(X, babel) ; acted_in(X, district_9))),
nl,
format("6. What actors played in babel but not in district 9?"),
nl,
print_query_true((acted_in(X, babel), \+ acted_in(X, district_9))),
print_query_false((acted_in(X, babel), \+ acted_in(X, district_9))),
nl,
halt.
I changed writeln to format to get proper formatted strings in the output. Test run:
?- [main].
% movie compiled 0.00 sec, 9 clauses
% main compiled 0.00 sec, 15 clauses
true.
?- main.
1. Did Leonardo DiCaprio act in Babel?
false:acted_in(leonardo_dicaprio,babel)
2. Was babel released in 2006?
true:released(babel,2006)
3. Did anyone act in both Click and The Aviator?
false: (acted_in(_G1551,click),acted_in(_G1551,the_aviator))
4. Did sharlto_copley and david_james both act in district_9?
true: (acted_in(sharlto_copley,district_9),acted_in(david_james,district_9))
5. Was there any two movies released in 2006 and 2009?
true: (released(babel,2006),released(district_9,2009))
6. What actors acted in babel or district 9?
true: (acted_in(brad_pitt,babel);acted_in(brad_pitt,district_9))
true: (acted_in(cate_blanchette,babel);acted_in(cate_blanchette,district_9))
true: (acted_in(sharlto_copley,babel);acted_in(sharlto_copley,district_9))
true: (acted_in(david_james,babel);acted_in(david_james,district_9))
6. What actors played in babel but not in district 9?
true: (acted_in(brad_pitt,babel),\+acted_in(brad_pitt,district_9))
true: (acted_in(cate_blanchette,babel),\+acted_in(cate_blanchette,district_9))
SWI-Prolog have an awesome documentation so I advise you to check up the predicates used to understand them fully:
forall: forall/2.
nl: nl/0
writeln: writeln/1
halt halt/0
format format/1
Compilation: SWI-prolog compilation
The last problem I have is when i try to run swipl it goes through and turns on the program. but when i type in [movie]. it just says true and doesn't show that is says compiled or anything of the sort.
Make sure you are in the right directory where you have your source-files.
SWI-Prolog v6.6.4 output:
?- [movie].
% movie compiled 0.00 sec, 9 clauses
true.

how to get user input prolog and store it

I'm trying to have the user input their birthday so I can tell them their zodiac sign. However, I'm having trouble getting their actual birthday and month. Could someone please help me? I've tried separating the reads into different functors, but I keep getting errors. The error I get when I combine both reads is "Syntax error: Operator priority clash." The error I get when I separate both reads is "ERROR: =:=/2: Arguments are not sufficiently instantiated."
Code when I combine the reads:
start :-
read_month,
read_month :-
write('Enter your birth month (month followed by a .): '),
nl,
read(X),
write('Enter your day of birth (followed by a .): '),
nl,
read(Y),
horoscope(X,Y).
Code when I separate the reads:
start :-
read_month,
read_day.
read_month :-
write('Enter your birth month (month followed by a .): '),
nl,
read(X).
read_day :-
write('Enter your day of birth (followed by a .): '),
nl,
read(Y),
horoscope(X,Y).
As a beginner, do not start like that. (And your first program is syntactically incorrect ; the first rule does not end with a period).
Instead, write a relation month_day_sign/3 which you can use directly at the toplevel, like so:
?- month_day_sign(7,24,Sign).
Sign = leo.
That's the way how you normally interact with Prolog. So you are exploiting the functionality of the toplevel shell.
Once you have mastered this, you may make some extra interface around. But don't go the other way!
By separating both "actions", the X is now disconnected from horoscope(X,Y)...

Undefined procedure in SWI-Prolog

Ok i got these two predicated hangman and graphics
fail([]).
hangman:-
getPhrase(Ans),
!,
write('Welcome to hangman.'),
nl,
fail(FailedList),
graphics(FailedList), %<--- The call is made here.
name(Ans,AnsList),
makeBlanks(AnsList, BlankList),
getGuess(AnsList,BlankList, FailedList).
graphics(FailedList):-
length(FailedList, L),
L == 0,
write('-----------'), nl,
write('|'), nl,
write('|'), nl,
write('|'), nl,
write('|'), nl,
write('|'), nl,
write('|'), nl,
write('|'), nl,
write('|'), nl,
write('/\'), nl.
Why do i get the error: ERROR: hangman/0: Undefined procedure: graphics/1?
Note that if i put the predicate graphics inside hangman in comments my program works fine.
(this answer is not really about the question asked so please let the answer to #SeçkinSavaşçı who did a great job answering the question, it's more of a code review)
Here, you visibly want to test if a list is empty and react accordingly by displaying some things. For the test if a list is empty part, you're doing it wrong:
graphics(FailedList):-
length(FailedList, L),
L == 0,
% some IO stuff
In prolog, you can use unification in a more straightforward manner:
graphics(FailedList):-
length(FailedList, 0),
% some IO stuff
or, better, where you directly test for the empty list in the head as a condition to execute the body of the predicate:
graphics([]):-
% some IO stuff
For the IO part, you're doing it kinda wrong again. SWI-Prolog, for example, has a writeln/1 predicate, that would make your code lighter:
graphics([]):-
writeln('-----------'),
writeln('|'),
writeln('|'),
writeln('|'),
writeln('|'),
writeln('|'),
writeln('|'),
writeln('|'),
writeln('|'),
writeln('/\\').
Still better, the format/1 predicate could be used:
graphics([]):-
format('-----------~n|~18~n|~n|~n|~n|~n|~n|~n|~n/\\').
The main predicate seems to have some problems too, but I'll let you look into it and ask questions if you're stuck somewhere :)
write('/\'), nl.
In the last line, you are escaping the ending quotation mark with \'. Change it to:
write('/\\'), nl.
BTW: #Mog has written the answer before I had a look at the comments, I tested it and now it finds graphics/1.

User input in prolog

I want to write a program that sets cold to true if the user enters winter and sets warm to true if the user enters summer. This is what I have so far:
start :- write('What season is it?: '), read(X), season(X).
cold :- season(winter).
warm :- season(summer).
However when I query start and enter winter for the season I get an error that season/1 is undefined. To fix this I tried changing my code to the following:
start :- season(X).
season(X) :- write('What season is it?: '), read(X).
cold :- season(winter).
warm :- season(summer).
Now when I query start it asks for the season as expected and I entered winter. I queried cold expecting a return of true since I figured season(winter) would be true, but instead I was again prompted to answer "what season is it?". How can I make this simple program work?
It looks that what you want to do is kind of "forward chaining". So you
want to be able to add a fact to the knowledge base, and then see
additional facts pop up.
Such things were very fashionable in the 80's when expert systems emerged
and can also be done with Prolog. Here is an article roughly describing the
difference between "backward chaining" and "forward chaining":
Logic Programming Associates Ltd.
ProWeb: Expert System
I have tried to remodel something similar to the above forward chaining
via the clause expansion mechanism that is available in many Prolog
systems and via an agenda that is held in the knowledge base as ordinary
facts. The expansion mechanism changes a rule of the following form:
P :- A
Into a rule where X is a fresh variable not occuring in P or A:
delta(X, P) :- A_new(X)
Where A_new is a condition that says that P is new when a new fact
X has arrived. Lets consider your example:
?- ['delta.p'].
?- [user].
:- forward season/1.
:- forward cold/0.
:- forward warm/0.
cold :- season(winter).
warm :- season(summer).
^D
These two Prolog rules would be turned into the following delta/2 rules
via the rewriting. Since the rules are very simple, the delta/2 rules
are also very simple:
?- listing(delta/2).
delta(X, cold) :-
X = season(winter).
delta(X, warm) :-
X = season(summer).
Here is an example session:
?- list.
Yes
?- volunteer(season(winter)).
Yes
?- list.
season(winter).
cold.
Yes
The rewriting in delta.p is very primitive. The rewriting can be enhanced
to support rigid predicates and to support the dynamic removal of facts.
Possible additional application areas of the "forward chaining" are then:
Natural Language Processing
Constraint Solving
Best Regards
The current delta/2 rewriting after a few more years development:
http://www.jekejeke.ch/idatab/doclet/blog/en/docs/15_min/02_reference/minimal/delta.html
An Article showing that a Constraint Store can be modelled:
https://plus.google.com/+JekejekeCh/posts/8oHErwopKxK
P.S.: The predicate name volunteer/1 stems form Nexpert Object,
an expert system shell in use in the 80's and 90's.
NEXPERT OBJECT version 3.0, Jean-Marie Chauvet, Neuron Data, Inc.
P.P.S.: But you might want to lookup newer things, such as Rete-NT, or OWL:
http://answers.semanticweb.com/questions/3304/forward-vs-backward-chaining
Because "cold/0" and "warm/0" take no arguments, it is impossible to change the result at runtime without altering their definition at runtime. The simplest way to do this is just to add or remove the facts "cold." and "warm." depending on user input, using assert/1 and retractall/1.
start :- write('What season is it?: '), read(X), season(X).
season(summer) :- retractall(cold), assert(warm).
season(winter) :- retractall(warm), assert(cold).
While defining the facts, you need to change the syntax a little bit.
start(Y) :- write('What season is it?: '), read(X), nl, season(X,Y).
season(winter,cold).
season(summer,warm).
Note that the user needs to end the input with a full stop. (eg. winter.)
season(winter,cold).
season(summer,warm).
start:-write('What season is it?'),write(' '),read(X),season(X,Y),write(Y).
The output will be look like this:
?- start.
What season is it? winter.
cold
true.

Resources