Prolog Beginner - macbook - prolog

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.

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 - program skipping over read?

Title more or less says it all. I got the following code in SWI-PROLOG:
get_card(1):-
nb_getval(playerOneHand, Hand),
write("Select which cards you want to play:"), nl,
read(Input),
handle_input(Input).
get_card(2):-
nb_getval(playerTwoHand, Hand),
write("Select which cards you want to play:"), nl,
read(Input),
handle_input(Input).
Expected input-format right now is something like [ 0, 1 ]. to play your first two cards, [ 0 ]. to only play your first card, so on and so forth. While I know this is beyond horrible as far as input formats go, the priority right now is to atleast get it working, then move on to a better UI from there.
This is what happens:
I'm very new to Prolog so bear with me, but this is how I'm looking at it: It seems to be "skipping" over our read and is now expecting a new command to be entered instead (ENTER has been pressed in the above picture).
I feel like the solution should be very simple but unfortunately is nothing I can seem to wrap my head around. Thanks in advance!
EDIT: Example code that can be ran to reproduce the issue, unless it's only happening on my system for some reason:
% Initialize globals
?- nb_setval(playerOneHand, []).
?- nb_setval(playerTwoHand, []).
handle_input(Input, Hand):-
write("Input is "), write(Input), nl,
write("Hand is "), write(Hand), nl.
get_card(1):-
nb_getval(playerOneHand, Hand),
write("Select which cards you want to play: "), nl,
read(Input),
handle_input(Input, Hand).
get_card(2):-
nb_getval(playerTwoHand, Hand),
write("Select which cards you want to play: "), nl,
read(Input),
handle_input(Input, Hand).
?- write("Player 1: "), get_card(1), nl,
write("Player 2: "), get_card(2), nl.
Using SWI-Prolog and the given code in a test.pl file, it is simply consulted via the terminal interface (File -> Consult -> test.pl). Trying to give SWI-Prolog ANY kind of input then results in the issue at hand.
As mentioned by Isabelle Newbie in the comments, swipl.exe (that is started by default) has a long-running bug associated with proper input/output. Navigating to where Prolog is installed and instead using swipl-win.exe seems to have done the trick.

Prolog read predicate cant read user key in in initialization?

I want to have a prolog program which can auto run once I compile finish and it should read input from user keyboard. However when i use
:- write('Your name is: '), nl, read(X).
there is not any effect on read(X), which it means that there us not any prompt for users to key in. Is there any solution for this problem? My prolog compiler is WIN-Prolog 5.0, thanks for your helo :)
maybe you need something like
:- initialization(main). % changed to be ISO compliant, was :- initialization main.
main :- write('Your name is: '), nl, read(X).
at least, ISO Prologs do it in this way....
Since read/1 is meant to parse Prolog (it's a full fledged parser), you must supply a Prolog term, and don't forget, as Joel76 suggested, to complete input with a dot: for instance:
Your name is:
|: 'Carlo'.

How to get both drive predicates working in 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

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