Natural language interpreter in Prolog does not work - prolog

I'm having a problem in Prolog. I'm trying to write a converter that converts simple english sentences into commands in Prolog.
Im trying to create a text adventure game using the tutorial here.
My problem is this: After starting the main command loop, when entering a sentence and hitting the "enter" button, Prolog will simply jump into the next line, seemingly not executing the command at all. It does not matter how often I enter a full-stop. Before using this language converter, everything worked just fine and the game was playable using commands. The problem must be within this part of the code. More precisely, I think the part for reading lines or the get_command(X) function are most likely not working.
I'm using SWI-Polog by the way, in case that is of importance (some people add this info to their questions).
Since I can't spot the mistake myself, I will try to post the relevant code.
First the main command loop:
command_loop:-
write('Welcome to Nani Search'), nl,
look,nl,
repeat,
write('>nani> '),
get_command(X),
do(X), nl,
end_condition(X).
And now the converter (the get_command(X) function is at the very bottom):
% Natural language converter
command([V], InList):- verb(V, InList-[]).
verb(look, [look|X]-X).
verb(look, [look,around|X]-X).
verb(look, [glotz,ma,alde|X]-X).
verb(list_possessions, [inventory|X]-X).
verb(end, [end|X]-X).
verb(end, [quit|X]-X).
verb(end, [good,bye|X]-X).
command([V,O], InList) :-
verb(Object_Type, V, InList-S1),
object(Object_Type, O, S1-[]).
verb(place, goto, [go,to|X]-X).
verb(place, goto, [go|X]-X).
verb(place, goto, [move,to|X]-X).
% Exceptions for rooms with two words
verb(place, goto, [X|Y]-[X|Y]):- room(X).
verb(place, goto, [dining,room|Y]-[dining,room|Y]).
verb(thing, take, [take|X]-X).
verb(thing, drop, [drop|X]-X).
verb(thing, drop, [put|X]-X).
verb(thing, turn_on, [turn,on|X]-X).
verb(thing, turn_off, [turn,off|X]-X).
object(Type, N, S1-S3) :-
det(S1-S2),
noun(Type, N, S2-S3).
object(Type, N, S1-S2) :-
noun(Type, N, S1-S2).
det([the|X]- X).
det([a|X]-X).
det([an|X]-X).
% Exceptions for rooms with two words
noun(place, R, [R|X]-X):- room(R).
noun(place, 'dining room', [dining,room|X]-X).
% Exceptions for things with two words
noun(thing, T, [T|X]-X):- location(object(T,_),_).
noun(thing, T, [T|X]-X):- have(object(T,_)).
noun(thing, 'washing machine', [washing,machine|X]-X).
noun(thing, flashlight, [light|X]-X):- have(object(flashlight,_)).
noun(thing, light, [light|X]-X).
% read a line of words from the user
read_list(L) :-
write('> '),
read_line(CL),
wordlist(L,CL,[]), !.
read_line(L) :-
get0(C),
buildlist(C,L).
buildlist(13,[]) :- !.
buildlist(C,[C|X]) :-
get0(C2),
buildlist(C2,X).
wordlist([X|Y]) --> word(X), whitespace, wordlist(Y).
wordlist([X]) --> whitespace, wordlist(X).
wordlist([X]) --> word(X).
wordlist([X]) --> word(X), whitespace.
word(W) --> charlist(X), {name(W,X)}.
charlist([X|Y]) --> chr(X), charlist(Y).
charlist([X]) --> chr(X).
chr(X) --> [X],{X>=48}.
whitespace --> whsp, whitespace.
whitespace --> whsp.
whsp --> [X], {X<48}.
% Return a command
get_command(C) :-
read_list(L),
command(CL,L),
C =.. CL, !.
get_command(_) :-
write('I don''t understand'), nl, fail.
And finally, the do-function from the command loop:
do(goto(X)):-goto(X),!.
do(go(X)):-goto(X),!.
do(take(X)):-take(X),!.
do(put(X,Y)):-put(X),!.
do(turn_on(X)):-turn_on(X),!.
do(turn_off(X)):-turn_off(X),!.
do(inventory):-inventory,!.
do(list_things(X)):-list_things(X),!.
do(look):-look,!.
do(end).
do(_) :-
write('Invalid command').
By converting the natural language sentences into these commands, the program is supposed to start the respective function. It is supposed to work like this: When you enter go to the office. the converter is supposed to transform the frase into the command goto(office). When one writes take the flashlight it is supposed to convert it to take(flashlight) . When one writes look around. it should be converted to look. The converted command should then be send to the command loop and be executed via do(X) (As seen in the do-function, X must be command like goto(office).
I hope it is clear what my question is.
I also made a trace. The command loop is being started normally. This is what happens after the end of the command loop (the write('>nani> ') still being part of it).
Call: (7) write('>nani> ') ? creep
>nani>
Exit: (7) write('>nani> ') ? creep
Call: (7) get_command(_G3903) ? creep
Call: (8) read_list(_G3903) ? creep
Call: (9) write('> ') ? creep
>
Exit: (9) write('> ') ? creep
Call: (9) read_line(_G3903) ? creep
Call: (10) get0(_G3903) ? creep
|:
Then I'm able to enter a new command. By simply pressing the Enter button without giving any input, it will always do the following:
Exit: (10) get0(10) ? creep
Call: (10) buildlist(10, _G3904) ? creep
Call: (11) get0(_G3906) ? creep
|:
This is being repeated whenever I hit enter. When I enter a random letter or multiple letters before pressing enter, the value of the first get0 will change, but nothing else.
Depending on which letters I write there sometimes is a different result though. Here are two examples:
For example when I try writing dsf, this will happen:
|: dsf
Exit: (10) get0(100) ? skip
Call: (10) buildlist(100, _G3904) ? fail
Fail: (9) read_line(_G3903) ? creep
Fail: (8) read_list(_G3903) ? creep
Redo: (7) get_command(_G3903) ? creep
Call: (8) write('I don\'t understand') ? creep
I don't understand
Exit: (8) write('I don\'t understand') ? creep
Call: (8) nl ? creep
Exit: (8) nl ? creep
᠀ Call: (8) fail ? creep
Fail: (8) fail ? creep
Fail: (7) get_command(_G3903) ? creep
Redo: (7) repeat ? creep
Exit: (7) repeat ? creep
Call: (7) write('>nani> ') ? creep
>nani>
Exit: (7) write('>nani> ') ? creep
Call: (7) get_command(_G3903) ? creep
Call: (8) read_list(_G3903) ? creep
Call: (9) write('> ') ? creep
>
Exit: (9) write('> ') ? creep
Call: (9) read_line(_G3903) ? creep
Call: (10) get0(_G3903) ? creep
|:
Other input like apg will have the following result:
|: apg
Exit: (17) get0(97) ? print
Exit: (17) get0(97) ? goals
[17] get0(97)
[16] buildlist(10, [10|_G3915])
[15] buildlist(10, [10, 10|_G3915])
[14] buildlist(10, [10, 10, 10|_G3915])
[13] buildlist(10, [10, 10, 10, 10|_G3915])
Exit: (17) get0(97) ? creep
Call: (17) buildlist(97, _G3915) ? creep
Call: (18) get0(_G3927) ? creep
And when entering longer commands, random or also something like go to the office., the program will shut down completely, without a comment. This shutdown only happens while the trace is activated. When it is not, commands like go to the office. will, again, simply make the program jump to the next line, seemingly not doing anything.
What might also be interesting is the fact that, after starting the command loop, the program takes a long time to shut down. The following message is being displayed:
Waiting for Prolog. Close again to force termination ..
Since I'm really new to Prolog, I'm not quite sure how to interpret this. To me the reaction to the random letters as input is competely random. Maybe someone else has a clue.
I would apreciate it a lot, if someone could help me out. I hope it's not too big of a mistake.
Regards :)

Related

Message:1031 Arithmetic overflow in prolog

predicates
nondeterm s(integer,integer)
nondeterm p(integer,integer,integer)
clauses
s(V,R) :-
p(0,V,R).
%,write(R),nl.
p(R,0,R).
p(Inc,V,R) :-
I2=Inc+V,
N1=V-1,
p(I2,N1,R).
goal
s(9,O).
gives an arithmetic overflow,,,why??
In Prolog mathematical expressions are not done with assignment, e.g. =. Prolog does not use assignment like many common programming languages, Prolog uses unification. If you want to do math expressions in Prolog and unify the result with a variable then you need to use the is/2 operator
I2 is Inc+V
N1 is V-1
You also need a guard statement to keep the second clause from being executed if the second parameter is 0.
s(V,O) :-
p(0,V,O).
p(R,0,R).
p(Inc,V,R) :-
V \= 0,
I2 is Inc+V,
N1 is V-1,
p(I2,N1,R).
Now your query returns
?- s(9,O).
O = 45 ;
false.
Complementing Guy's answer, it is instructive to run your query in the Prolog tracer as it clearly shows that, because you used unification (=/2) instead of arithmetic expression evaluation (is/2), your query build an increasingly bigger compound term at each recursive call until the global stack space is exhausted:
[trace] ?- s(9,O).
Call: (8) s(9, _3176) ? creep
Call: (9) p(0, 9, _3176) ? creep
Call: (10) _3396=0+9 ? creep
Exit: (10) 0+9=0+9 ? creep
Call: (10) _3402=9-1 ? creep
Exit: (10) 9-1=9-1 ? creep
Call: (10) p(0+9, 9-1, _3176) ? creep
Call: (11) _3408=0+9+(9-1) ? creep
Exit: (11) 0+9+(9-1)=0+9+(9-1) ? creep
Call: (11) _3414=9-1-1 ? creep
Exit: (11) 9-1-1=9-1-1 ? creep
Call: (11) p(0+9+(9-1), 9-1-1, _3176) ? creep
Call: (12) _3420=0+9+(9-1)+(9-1-1) ? creep
Exit: (12) 0+9+(9-1)+(9-1-1)=0+9+(9-1)+(9-1-1) ? creep
Call: (12) _3426=9-1-1-1 ?
...

Difference between two Implementation of even and odd in Prolog

i have two implementation of Prolog , the Function is to decide if the given number is odd or even
the first one works correctly
even1(0).
even1(X) :- X>0 ,X1 is X-1, odd1(X1).
odd1(1).
odd1(X) :- X>1 , X1 is X-1, even1(X1).
even1(2) returns true
but the second one doesnt work correctly
even2(0).
even2(X) :- X>0 , odd2(X-1).
odd2(1).
odd2(X) :- X>1 , even2(X-1).
even2(2) returns false
can anyone explain to me whats is the difference between the two of them ?
Prolog is a relational language, not a functional language. Thus, when you call odd2(X-1), the predicate argument, X-1, is not evaluated as an expression but interpreted as a compound term:
?- functor(X-1, Name, Arity).
Name = (-),
Arity = 2.
You can check what happens when Prolog proves a query by using your system trace functionality:
?- trace.
true.
[trace] ?- even2(2).
Call: (8) even2(2) ? creep
Call: (9) 2>0 ? creep
Exit: (9) 2>0 ? creep
Call: (9) odd2(2-1) ? creep
Call: (10) 2-1>0 ? creep
Exit: (10) 2-1>0 ? creep
Call: (10) even2(2-1-1) ? creep
Call: (11) 2-1-1>0 ? creep
Fail: (11) 2-1-1>0 ? creep
Fail: (10) even2(2-1-1) ? creep
Fail: (9) odd2(2-1) ? creep
Fail: (8) even2(2) ? creep
false.
Note that the expression 2-1-1 evaluates to zero but, being a compound term, the call even2(2-1-1) doesn't unify with your base case for the predicate, even2(0):
?- even2(2-1-1) = even2(0).
false.
?- 2-1-1 = 0.
false.
Therefore, Prolog tries the second clause and the call eventually fails the X>0 check. Note that >/2, by being an arithmetic comparison predicate, it does evaluate its arguments prior to the actual comparison.

How to check if the name is in a list that is recognized by its similar term in a predicate?

Suppose, I have a prolog predicate such as:
name(music,[jazz,blues,classical]).
and what I want is to check membership of say jazz and return me true if in music?
So far, I did this:
ismember(X,Y):-imember(X,name(Y,Z)),write(Z).
imember(X,[_|Tail]):-imember(X,Tail).
imember(X,[X|_]).
But it isn't working.
?- ismember(jazz,music).
false.
And it isn't writing the write(Z) part.
In the visible part of the following fragment there is an error. Not only does your program fail, also the following generalization fails:
:- op(950, fy, *).
*(_).
ismember(X,Y):-
imember(_/*X*/,name(_/*Y*/,Z)).
imember(X,[_|Tail]):-
* imember(X,Tail).
imember(X,[_/*X*/|_]).
?- ismember(X, Y).
The generalization has been obtained by replacing some variables by _, and by removing one goal with *. It generalizes as much as possible. That is, any further generalization would make the goal succeed. And there is this nice property that holds in (pure, monotonic) Prolog:
If a generalization fails (for a specific query), then also the original program fails (for that same query).
That's the nice property that somehow establishes causality between a generalized fragment and the original program. If you want to remove the error, something in the generalized program has to be changed. Or conversely: If you make changes that still permit to get the generalization, then you have not fixed the error.
With this in mind,when searching for such a fragment, there is no need to "understand" the actual program. It suffices to guess and generalize mindlessly as long as this is possible.
Now, if we look at that generalization note that
the arguments of ismember/2 are completely ignored!
The problem is that the name(Y,Z) that you pass in imember/2 predicate isn't a list. You could simply write:
ismember(X,Y):-name(Y,Z),imember(X,Z),write(Z).
imember(X,[_|Tail]):-imember(X,Tail).
imember(X,[X|_]).
Example:
?- ismember(jazz,music).
[jazz,blues,classical]
true.
the ismember/2 predicate second parameter is a list , and you are not passing a list
here is a trace
[trace] ?- ismember(jazz,music).
Call: (8) ismember(jazz, music) ? creep
Call: (9) imember(jazz, name(music, _6828)) ? creep
Fail: (9) imember(jazz, name(music, _6828)) ? creep
Fail: (8) ismember(jazz, music) ? creep
false.
#coder answer is a correct way
or you can simply use the member/2 predicate as follows:
first define your list in the database:
music([jazz,blues,classical]).
now we have our music types list , next we write the rule
ismusicmember(X) :- music(L) , member(X,L),write(L).
music(L) to assign the variable L to our music list
member(X,L) the member/2 predicate check whether X is in the list or not
and running a query
?- ismusicmember(jazz).
[jazz,blues,classical]
true .
a trace:
[trace] ?- ismusicmember(jazz).
Call: (8) ismusicmember(jazz) ? creep
Call: (9) music(_7376) ? creep
Exit: (9) music([jazz, blues, classical]) ? creep
Call: (9) lists:member(jazz, [jazz, blues, classical]) ? creep
Exit: (9) lists:member(jazz, [jazz, blues, classical]) ? creep
Call: (9) write([jazz, blues, classical]) ? creep
[jazz,blues,classical]
Exit: (9) write([jazz, blues, classical]) ? creep
Exit: (8) ismusicmember(jazz) ? creep
true .

Prolog - Confusion With Order of Printing in Recursion

Given the following program:
postIt([]).
postIt([c|R]) :- postIt(R), !, nl.
postIt([X|R]) :- postIt(R), write(X).
Query:
?- postIt([a,b,c,d,e]).
Trace:
[trace] ?-
| postIt([a,b,c,d,e]).
Call: (8) postIt([a, b, c, d, e]) ? creep
Call: (9) postIt([b, c, d, e]) ? creep
Call: (10) postIt([c, d, e]) ? creep
Call: (11) postIt([d, e]) ? creep
Call: (12) postIt([e]) ? creep
Call: (13) postIt([]) ? creep
Exit: (13) postIt([]) ? creep
Call: (13) write(e) ? creep
e
Exit: (13) write(e) ? creep
Exit: (12) postIt([e]) ? creep
Call: (12) write(d) ? creep
d
Exit: (12) write(d) ? creep
Exit: (11) postIt([d, e]) ? creep
Call: (11) nl ? creep
Exit: (11) nl ? creep
Exit: (10) postIt([c, d, e]) ? creep
Call: (10) write(b) ? creep
b
Exit: (10) write(b) ? creep
Exit: (9) postIt([b, c, d, e]) ? creep
Call: (9) write(a) ? creep
a
Exit: (9) write(a) ? creep
Exit: (8) postIt([a, b, c, d, e]) ? creep
true.
I don't quite understand why the output is 'ed' 'ba'. I figured that the program would print 'ab' skip 'c' then print 'de'. I am hoping someone may be able to clarify this for me.
Before I address the actual question, one additional point: Please consider using more_readable_names_with_underscores insteadOfStickingItAllTogetherLikeThis. Thus, I suggest for example the name post_it/1.
Next, to make our life simpler, I will only consider the following fragment of your code:
post_it([]).
post_it([X|R]) :- post_it(R), write(X).
That is, I have simply omitted the second clause entirely.
What do you expect now from the query ?- post_it([a,b,c,d]).? Is it abcd?
No, obviously it isn't:
?- post_it([a,b,c,d]).
dcba
Why? In your case, since you are using the impure predicate write/1, the reason for this can only be understood procedurally, that is taking into account the actual execution strategy of Prolog.
The execution strategy of Prolog is called, among other names, depth first search with chronological backtracking. When you have a clause like:
a :- b, c.
then, when a/0 is executed, b/0 is invoked first, and only if b/0 succeeds, c/0 is invoked.
Thus, consider for example the simpler query:
?- post_it([a,b]).
First, post_it([b]) is invoked, and it emits b (Exercise: Why?). Only then, a is emitted, because write(a) occurs as the second goal in post_it/1.
Obviously, in such simple cases, we can still somehow grasp the procedural definition. The major deficit of this is that this quickly becomes way too complex to understand, and so I can only recommend to avoid side-effects: They will invariably make your code too hard to understand, and you are already seeing the first signs of this.
Recommendation: Work in the pure subset of Prolog. In your case, consider the following relation between lists:
without_c(Ls0, Ls) :-
tfilter(dif(c), Ls0, Ls).
This uses tfilter/3 from Ulrich Neumerkel's library(reif) to declaratively describe the relation between two lists, where the second list is the same as the first, but without any occurrence of the atom c.
Example query:
?- without_c([a,b,c,d], Ls).
Ls = [a, b, d].
Much more general cases work too, for example:
?- length(Ls0, _), without_c(Ls0, Ls).
Ls0 = Ls, Ls = [] ;
Ls0 = [c],
Ls = [] ;
Ls0 = Ls, Ls = [_7366],
dif(_7366, c) ;
Ls0 = [c, c],
Ls = [] .
Note that such relations can be easily tested, because the arguments can be reasoned about explicitly, much in contrast to output that only occurs on the terminal. In addition, this program admits a declarative reading, freeing you from many operational considerations.
Note also an additional problem of your original definition: Due to the usage of !/0, it has become extremely hard to predict the effect of removing the second clause. The resulting program is not more specific (as would be expected otherwise), but actually emits solutions that were previously not emitted!

Some doubts about declarative meaning of a program that prints a list of lists in Prolog

Write a rule that take a list whose elements are themselves lists and
print on each line the elements of internals list:
Example:
?- printList[[1,a],[2,b]]).
1 a
2 b
The solution it the following one:
/* BASE CASE: The list is empty, so there is nothing to print */
printList([]).
printList([P|R]):- printList(P),
!,
nl,
printList(R).
printList([X|R]):- write(X),
!,
printList(R).
I have the printList rule that reaches the base case when the list is empty and in this case there is nothing to print.
If I am not in the base case (the list is not empty) it calls the second rule printList([P|R]) and now I have my first doubt:
The element P is a list because Prolog automatically handles an internal list as an element?
So, If I have something like:
[[1,a],[2,b],[3,c],[4,d]] I have that Prolog automatically match in this way:
P = [1,a] (the first list as the head element)
R = [[2,b],[3,c],[4,d]] (the other 3 list are the element of a tail list)
And then the program calls the printList predicate on the head element (the first list) and this version of the rule writes all the elements in the current list.
Is this right this interpretation?
Now I have some doubts about about the trace of this program, for example if I execute this statement I obtain the following trace:
[trace] ?- printList([[1,a], [2,b]]).
Call: (6) printList([[1, a], [2, b]]) ? creep
Call: (7) printList([1, a]) ? creep
Call: (8) printList(1) ? creep
Fail: (8) printList(1) ? creep
Redo: (7) printList([1, a]) ? creep
Call: (8) write(1) ? creep
1
Exit: (8) write(1) ? creep
Call: (8) printList([a]) ? creep
Call: (9) printList(a) ? creep
Fail: (9) printList(a) ? creep
Redo: (8) printList([a]) ? creep
Call: (9) write(a) ? creep
a
Exit: (9) write(a) ? creep
Call: (9) printList([]) ? creep
Exit: (9) printList([]) ? creep
Exit: (8) printList([a]) ? creep
Exit: (7) printList([1, a]) ? creep
Call: (7) nl ? creep
Exit: (7) nl ? creep
Call: (7) printList([[2, b]]) ? creep
Call: (8) printList([2, b]) ? creep
Call: (9) printList(2) ? creep
Fail: (9) printList(2) ? creep
Redo: (8) printList([2, b]) ? creep
Call: (9) write(2) ? creep
2
Exit: (9) write(2) ? creep
Call: (9) printList([b]) ? creep
Call: (10) printList(b) ? creep
Fail: (10) printList(b) ? creep
Redo: (9) printList([b]) ? creep
Call: (10) write(b) ? creep
b
Exit: (10) write(b) ? creep
Call: (10) printList([]) ? creep
Exit: (10) printList([]) ? creep
Exit: (9) printList([b]) ? creep
Exit: (8) printList([2, b]) ? creep
Call: (8) nl ? creep
Exit: (8) nl ? creep
Call: (8) printList([]) ? creep
Exit: (8) printList([]) ? creep
Exit: (7) printList([[2, b]]) ? creep
Exit: (6) printList([[1, a], [2, b]]) ? creep
true.
This is quite clear for me (I think that my previous reasoning is right) but I am not understanding why whenever it reaches an element in an internal list it calls the printList relation on it (that is a simple element and not a list), for example here:
Call: (8) printList(1) ? creep
Fail: (8) printList(1) ? creep
the program had considered the first list of the original list and then, into it to have to print its first element, why call the printList relation on this simple element
Is it because this simple element may in turn be internal lists?
Something like:
[[[1.1,a1,a2],[1.2,b1,b2]], [2,b]] (in which I have a list that contains 2 lists and the first element it is a list that contains 2 lists. So the program checks if an element it is an element or an internal list?
I think you're over-thinking it. Look at the code:
printList([P|R]):- printList(P),
Right there you can see that printList/1 is being unified with the head of the list. The fact that all the rules of printList/1 match lists and only lists is a fact that you, the human, can immediately see. But Prolog does not "notice" this fact, so if you are to call, say,
printList([1])
the first matching rule is the one above, so it will immediately try to unify printList(1). This will fail, naturally, because 1 is not a list and so doesn't match any of the rules for printList/1. Prolog then backtracks and tries the next rule, which is the one that starts like this:
printList([X|R]):- write(X),
This is clearly going to unify [1] with X = 1, R = [], so it's clearly going to write the first element, the one, and then proceed as usual. There is no magic here involving "internal lists," which as far as I'm aware is not a concept in Prolog at all (if such a thing is treated in the compiler it is well hidden from the user of Prolog).
Prolog isn't psychic; it has to try the rules to see if they fail, even if that attempt is essentially a failing pattern-match in the head of the Horn clause.
I am unable to distinguish your first from your second question so I hope this answers both. :)

Resources