Assertz causing "no permission to modify static procedure" error - prolog

I am trying to define initial position of the agent as direction/2:
direction(1, west).
And then define a predicate to change agent's direction:
turnLeft(T) :-
TNext is T+1,
direction(T, west), assertz(direction(TNext, north)),!,
direction(T, south), assertz(direction(TNext, west)),!,
direction(T, east), assertz(direction(TNext, south)),!,
direction(T, north), assertz(direction(TNext, east)).
However, when I invoke i.e. turnLeft(1), a following error occurs:
No permission to modify static procedure `direction/2'
I am using online SWISH IDE, does it have anything to do with it or does the problem lie in something else?

Predicates are static by default. To make a predicate dynamic, i.e. to allow its definition to change at runtime by asserting and retracting clauses for it, you need to use the standard dynamic/1 predicate directive.
Add at the top of the file the directive:
:- dynamic(direction/2).

Related

Prolog: subsets facts not working

I've never written in Prolog before. I have to provide facts so that when it runs it displays:
?- subset([a,b],[a,c,d,b]).
true.
?-include([],[a,b]).
true.
So far, I've written this:
subset([],_Y).
subset([X|T],Y):- member(X,Y),subset(T,Y).
But include doesn't work when I write include([],[a,b]). . It shows this:
ERROR: toplevel: Undefined procedure: include/2 (DWIM could not correct goal)
Any help would be appreciated. Thanks
You get the error because you didn't define the predicate include/2. Your given example looks like include/2 should be describing the same relation as subset/2. So you can either rename your definition from subset/2 to include/2 and then run the query or you can use subset/2 to define include/2:
include(X,Y) :-
subset(X,Y).
Note that in order to use member/2 you have to use library(lists). However, in some Prolog systems (e.g. SWI) this library includes a predicate subset/2 thus leading to a warning when you consult your source file:
Warning: ...
Local definition of user:subset/2 overrides weak import from lists
If you want to implement your own version of subset/2 anyway and not get this warning, you can rename your predicate or not use library(lists) and implement your version of member/2, for example:
subset([],_Y).
subset([X|T],Y) :-
element_in(X,Y),
subset(T,Y).
element_in(X,[X|_]).
element_in(X,[Y|Ys]) :-
dif(X,Y),
element_in(X,Ys).

Unable to make facts dynamic in SWI-Prolog

I would like to be able to retract and assert facts dynamically for the procedure location:
location(egg, duck_pen).
Based on advice online (including No permission to modify static procedure), I've tried adding each of the following to my source code, which otherwise contains only the above assertion:
dynamic location/2.
dynamic(location/2).
dynamic(location)/2.
The first two versions give me this error at compile-time (when loaded into SWI-Prolog):
No permission to redefine built-in predicate `(dynamic)/1'
Use :- redefine_system_predicate(+Head) if redefinition is intended
The last version does not give me an error at compile-time, but, whether I put it at the beginning or end of the file, I get an error when I try retracting my fact:
?- retract(location(egg,duck_pen)).
ERROR: retract/1: No permission to modify static procedure `location/2'
I am using SWI-Prolog version 6.6.5.
Use
:- dynamic location/2.
location(X, Y) blah blah

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.

Defining a rule that the user cannot query

How do I define a rule that the user cannot query?
I only want the program itself to call this rule through another rule.
Ex:
rule1():- rule2().
rule2():- 1<5.
?-rule1().
true
?-rule2().
(I don't know what the answer will be, I just want this query to fail!)
Use a Logtalk object to encapsulate your predicates. Only the predicates that you declare public can be called (from outside the object). Prolog modules don't prevent calling any predicate as using explcit qualification bypasses the list of explicitly exported predicates.
A simple example:
:- object(rules).
:- public(rule1/1).
rule1(X) :-
rule2(X).
rule2(X) :-
X < 5.
:- end_object.
After compiling and loading the object above:
?- rules::rule1(3).
true.
?- rules::rule2(3).
error(existence_error(predicate_declaration,rule2(3)),rules::rule2(3),user)
If you edit the object code and explicitly declare rule2/1 as private you would get instead the error:
?- rules::rule2(3).
error(permission_error(access,private_predicate,rule2(3)),rules::rule2(3),user)
More information and plenty of examples at http://logtalk.org/
First, some notes:
I think you mean "predicate" instead of "rule". A predicate is a name/k thing such as help/0 (and help/1 is another) and can have multiple clauses, among them facts and rules, e.g. length([], 0). (a fact) and length([H|T], L) :- ... . (a rule) are two clauses of one predicate length/2.
Do not use empty parenthesis for predicates with no arguments – in SWI-Prolog at least, this will not work at all. Just use predicate2 instead of predicate2() in all places.
If you try to call an undefined predicate, SWI-Prolog will say ERROR: toplevel: Undefined procedure: predicate2/0 (DWIM could not correct goal) and Sicstus-Prolog will say {EXISTENCE ERROR: predicate2: procedure user:predicate2/0 does not exist}
Now, to the answer. Two ideas come to my mind.
(1) This is a hack, but you could assert the predicate(s) every time you need them and retract them immediately afterwards:
predicate1 :-
assert(predicate2), predicate2, retractall(predicate2).
If you want a body and arguments for predicate2, do assert(predicate2(argument1, argument2) :- (clause1, clause2, clause3)).
(2) Another way to achieve this would be to introduce an extra argument for the predicate which you do not want to be called by the user and use it for an identification that the user cannot possibly provide, but which you can provide from your calling predicate. This might be a large constant number which looks random, or even a sentence. This even enables you to output a custom error message in case the wrong identification was provided.
Example:
predicate1 :-
predicate2("Identification: 2349860293587").
predicate2(Identification) :-
Identification = "Identification: 2349860293587",
1 < 5.
predicate2(Identification) :- Identification \= "Identification: 2349860293587",
write("Error: this procedure cannot be called by the user. Use predicate1/0 instead."),
fail.
I don't use the equivalent predicate2("Identification: 2349860293587") for the first clause of predicate2/0, because I'm not sure where the head of the clause might appear in Prolog messages and you don't want that. I use a fail in the end of the second clause just so that Prolog prints false instead of true after the error message. And finally, I have no idea how to prevent the user from looking up the source code with listing(predicate2) so that will still make it possible to simply look up the correct identification code if s/he really wants to. If it's just to keep the user from doing accidental harm, it should however suffice as a protection.
This reminds me to facility found in Java. There one can query the
curent call stack, and use this to regulate permissions of calling
a method. Translated to Prolog we find in the old DEC-10 Prolog the
following predicate:
ancestors(L)
Unifies L with a list of ancestor goals for the current clause.
The list starts with the parent goal and ends with the most recent
ancestor coming from a call in a compiled clause. The list is printed
using print and each entry is preceded by the invocation number in
parentheses followed by the depth number (as would be given in a
trace message). If the invocation does not have a number (this will
occur if Debug Mode was not switched on until further into the execution)
then this is marked by "-". Not available for compiled code.
Since the top level is usually a compiled predicate prolog/0, this could be
used to write a predicate that inspects its own call stack, and then decides
whether it wants to go into service or not.
rule2 :- ancestors(L), length(L,N), N<2, !, write('Don't call me'), fail.
rule2 :- 1<5.
In modern Prologs we don't find so often the ancestors/1 predicate anymore.
But it can be simulated along the following lines. Just throw an error, and
in case that the error is adorned with a stack trace, you get all you need:
ancestors(L) :- catch(sys_throw_error(ignore),error(ignore,L),true).
But beware stack eliminiation optimization might reduce the stack and thus
the list returned by ancestors/1.
Best Regards
P.S.: Stack elimination optimization is already explained here:
[4] Warren, D.H.D. (1983): An Abstract Prolog Instruction Set, Technical Note 309, SRI International, October, 1983
A discussion for Jekejeke Prolog is found here:
http://www.jekejeke.ch/idatab/doclet/prod/en/docs/10_pro08/13_press/03_bench/05_optimizations/03_stack.html

How to verify if a rule exists in a prolog file clause database

I'm working on a college assignment where I must verify if a certain clause (as a fact or as a rule) exists in the current clause database.
The idea is to use a rule whose head is verify(+name, +arguments). This rule should be true if in the database exists another rule whose head is name(arguments)
Any help would be greatly appreciated...
Using call/1 is not a good idea because call/1 actually calls the goal, but you just want to find out if the fact/rule exists, and you don't want to wait after a long calculation that the call might trigger, and you don't want to have something printed on the screen if the called rule in turn calls e.g. writeln/1. In addition, you would want verify/2 to succeed even if the call failed (but the fact/rule is otherwise there).
As a solution, SWI-Prolog offers callable/1
callable(+Term)
True if Term is bound to an atom or a compound term,
so it can be handed without type-error to call/1, functor/3 and =../2.
Here are two version of verify/2, one using call/1 and the other using callable/1.
verify1(Name, Arguments) :-
Term =.. [Name | Arguments],
call(Term).
verify2(Name, Arguments) :-
Term =.. [Name | Arguments],
callable(Term).
father(abraham, isaac) :-
writeln('hello').
father(abraham, adam) :-
fail.
Are you familiar with the concept of unification? What you have to do is: just call a predicate that looks like the one you're trying to find.
So, say in your database is:
father(abraham,isaac).
Now you want to call something like:
verify(father,[abraham,isaac]).
Your predicate body will then have to contain a mechanism of calling father(abraham,isaac). which should then return true. Calling father(abraham,adam) should fail.
You will need two predicates for this: =../2 and call/2. If you are using SWI-Prolog, call help(=..). and help(call) from the interpreter's command line to access the documentation.
I hope I didn't spoil the assignment for you. You still have to find out what to do with partially instantiated predicates (so, say something like verify(father,[abraham,X]). on your own, but it shouldn't be hard from here.
Good luck.

Resources