Datalog code not working in DrRacket - prolog

I am trying to run this prolog code in DrRacket: http://www.anselm.edu/homepage/mmalita/culpro/graf1.html
#lang datalog
arc(a,b).
arc(b,c).
arc(a,c).
arc(a,d).
arc(b,e).
arc(e,f).
arc(b,f).
arc(f,g).
pathall(X,X,[]).
pathall(X,Y,[X,Z|L]):- arc(X,Z),pathall(Z,Y,L). % error on this line;
pathall(a,g)?
However, it is giving following error:
read: expected a `]' to close `['
I suspect '|' symbol is not being read as head-tail separator of the list. Additionally, [] is also giving error (if subsequent line is removed):
#%app: missing procedure expression;
probably originally (), which is an illegal empty application in: (#%app)
How can these be corrected so that the code works and searches for paths between a and g ?

The Datalog module in DrRacket is not an implementation of Prolog, and the syntax that you have used is not allowed (see the manual for the syntax allowed).
In particular terms cannot be data structures like lists ([]). To run a program like that of above you need a Prolog interpreter with data structures.
What you can do is define for instance a predicate path, like in the example that you have linked:
path(X,Y):- arc(X,Y).
path(X,Y):- arc(X,Z),path(Z,Y).
and, for instance, ask if a path exists or not, as in:
path(a,g)?
or print all the paths to a certain node with
path(X,g)?
etc.

Related

SWI-Prolog partition predicate works differently in REPL than in programme

I imlemented quicksort using SWISH this way:
qsort([],[]).
qsort([H|T],S) :-
partition([X,O]>>compare(O,X,H),T,L,E,G),
qsort(L,A),
qsort(G,Z),
append([A,[H|E],Z],S).
main :-
length(L,22),
maplist(random(0,9),L),
qsort(L,S),
maplist(writeln,[L,S]).
It doesn't work correctly. The input and output lists are the same. However when I run this in the REPL there on the right:
length(S,22), maplist(random(0,9),S),[H|T]=S, partition([X,O]>>compare(O,X,H),T,L,E,G).
the random lists do get sorted. Whence the difference?
When the second clause for the qsort/2 predicate is compiled, there's no information on H other than it's a variable when compiling the lambda expression. Any variable occurring in the lambda expression that's not find in a local lambda parameter must be declared using the {}/1 construct. But when running your query at the top-level interpreter, by the time the lambda expression is interpreted, H is bound and thus no longer a variable (making the use of the {}/1 construct unnecessary).
Note that there are several details here at play that are out of scope of the lambda library itself: (1) is the compiler recognizing at compile time that you're calling a meta-predicate with an argument that's a lambda expression? (2) how's a top-level query interpreted? Is the full query first fully compiled or is it meta-interpreted? These details depend on the system itself.
It works when I add {H}/ in front of [X,O]>>compare(O,X,H). Might be a bug that toplevel doesn't require (but allows) it for the expected behaviour. But I'm not sure, so answers welcome from those in the know.

Lexical Analyzer Prolog

I must make a lexical analyzer in Prolog and C++. My for lexical analyzer in C++ is working, but i have some problems with my prolog code. I can't make it to recognize the keywords
This is my prolog code for it without including the keywords which works\
predicates
string_processing
det_lexical_atom_type(char)
is_identif(char)
is_op(char)
is_delim(char)
is_const(char)
p1(string)
clauses
string_processing:-write("Write the expression"),nl,readln(S),p1(S).
p1(S):-frontchar(S,C,R),det_lexical_atom_type(C),p1(R).
p1("#"):-!.
det_lexical_atom_type(C):-is_identif(C),write("\n Is identif",C).
det_lexical_atom_type(C):-is_op(C),write("\n is op",C).
det_lexical_atom_type(C):-is_delim(C),write("\n is delim",C).
det_lexical_atom_type(C):-is_const(C),write("\n is const",C).
det_lexical_atom_type(C):-write("\n Unknown lexical atom").
is_identif(C):-C='A'.
is_op(C):-C='+';C='*'.
is_delim(C):-C='(';C=')'.
is_const(C):-C='0';C='1'.
And this is my prolog code modified to recognize keywords, but it doesn't work .The program stops reading the expression I give right after the first letter and it doesn't continue to recognize the rest of expression. For example is i type T=3+a, it only reads the T and then it stops
predicates
string_processing
is_identif(char)
is_op(char)
is_delim(char)
is_const(char)
is_keyword(string)
p2(string)
determine_lexical_atom_type(char)
determine_keyword(string)
clauses
is_identif(C):-C='A';C='B';C='C';C='D'.
is_op(C):-C='+';C='-';C='/';C='*';C='='.
is_delim(C):-C=';';C=',';C='(';C=')'.
is_const(C):-C='0';C='1';C='2';C='3';C='4';C='5';C='6';C='7';C='8';C='9'.
is_keyword(T):-T="if";T="while";T="do";T="switch";T="for";
T="break";T="until";T="then".
determine_keyword(T):-is_keyword(T),write("\nIs keyword: ",T).
determine_lexical_atom_type(C):-is_identif(C),write("\nIs identif:",C).
determine_lexical_atom_type(C):-is_op(C),write("\nIs operator: ",C).
determine_lexical_atom_type(C):-is_delim(C),write("\nIs delimiter: ",C).
determine_lexical_atom_type(C):-is_const(C),write("\n Is constant ",C).
determine_lexical_atom_type(C):-write("\n Unknown lexical atom").
p2(S):- fronttoken(S,T,R),write("\nT=",T),determine_keyword(T),frontchar(R,C,R1),determine_lexical_atom_type(C),p2(R1).
p2("#"):-!.
string_processing:-write("Write expression"),nl,readln(S),p2(S),nl.
The problem is quite simple:
Just move determine_keyword/1 before fronttoken/3, code fragment is below. Keyword recognition should work after doing that.
p2(S):-
determine_keyword(T), //output var
fronttoken(S,T,R),
write("\nT=",T),
frontchar(R,C,R1),
determine_lexical_atom_type(C),
fail.
p2(_).
determine_keyword/1 generates list of all the keywords on backtracking

ERROR: Stream user_input:8:5 Syntax error: Operator expected in Prolog

I have to write a simple expert system in Prolog for scheduling of classes. In this code part, I want that user add an instructor to system. For this, reading two input value but I am getting this error.
addinstructor() :-
read(id),
read(courseid),
assert(instructor(id, courseid)),
write("added").
Query:
?- addinstructor().
5
cse102.
Then, I am getting operator expected error.
How do i fix this to work my code?
The predicate read/1 reads Prolog terms not raw data. Prolog terms end with a period.
So if instead of entering 5 if you enter 5. you will not get the error.
Instead of using the predicates found in Term reading and writing, e.g. read/1, you should use the predicates in Primitive character I/O for reading characters or Predicates that operate on strings for reading strings, e.g. read_string/3
To answer your next question of how do I implement this, see Prolog - Write out facts and reading a users input and then this.

A tuprolog syntax error.Syntax error at/before line -1

I am new to prolog. I have a .pl file consulting normally on swi-prolog, but when I consult it on tu-prolog, crazy things always happen. Here are parts of my codes.
:- dynamic(assignopT/6).
:- multifile(assignopT/6).
assignopT(30246,30244,30210,30247,+,30248).
When I consulted it on tu-prolog,it said syntax error at/before line 12219,which is the third line above. It work all right on swi-prolog. Then I thought maybe there is something wrong with +, so I changed it to this.
assignopT(30246,30244,30210,30247,'+',30248).
This time,it said syntax error at/before line -1. I really don't get this, what line -1 even suppose to mean. The .pl named swi2tu.pl is on https://drive.google.com/folderview?id=0B4KCEwRVmr_yWjQwOEp3LWpYdk0&usp=sharing
Try instead:
assignopT(30246,30244,30210,30247,(+),30248).
Writing an atom, such as +, between single quotes changes nothing and the error is possibly due to its operator status. Assuming that's the case, writing it between ()'s should fix the possible operator conflict when loading the code in tuProlog (not Turbo Prolog, I assume!).

I want to create dynamic facts in prolog

I wrote the following simple code, and I expect that when I write 'male.', this code ask me once "is it male?" and if i input 'No' it write on screen "she is female".
male :- ( print('is it male ? '),read(yes)) -> true; asserta( not(male)),female.
female:- not(male),print('she is female').
not(P) :- (call(P) -> fail ; true) .
but this code has following error:
uncaught exception: error(permission_error(modify,static_procedure,not/1),asserta/1);
the error in swi-prolog is :
ERROR: asserta/1: No permission to modify static_procedure `not/1'
As gusbro said, not/1 is a predefined static procedure (and therefore it is not a good idea to use the same name). However, this is not the reason you get the error in swi-prolog as you can overwrite the standard definition:
?- assert(not(42)).
true.
?- not(42).
true.
the problem is that you have already defined not/1 in your code and, when you do not declare a predicate explicitly as dynamic, swi-prolog will assume that it's static and will not allow you to change it.
You can declare it as dynamic by inserting this line in your code:
:-dynamic(not/1).
I think that this will not solve the problem in other prolog implementations (eg gnu-prolog) as the error message says permission_error(modify,static_procedure,not/1); in any case it is highly recommended to change the name.
By the way, it would be simpler and cleaner to simply test what the argument is and print the corresponding message. If, however, you want to create something more complex (using a state maybe) you could use global variables since they are more efficient that assert/retract.

Resources