Prolog: subsets facts not working - prolog

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).

Related

On ways to work around an unexpected "Undefined procedure" error

NB: Just to be clear, my motivation for the question below is to learn my way around Prolog and SWI-Prolog, not to get past a particular error message. In fact, I already know one way to get past this error. My question asks about whether several other alternatives are also possible.
An exercise in my Prolog textbook asks one to describe the outcome one should expect from several queries, assuming one has consulted the following knowledgebase beforehand:
x(a).
z(b).
z(c).
z(d).
w(V) :- x(V).
w(V) :- y(V).
w(V) :- z(V).
On SWI-Prolog, at least, most of these queries fail, because SWI-Prolog intreprets y as undefined.
From the solutions to the exercises at the end of the book I can tell that this is not the authors' intended outcome. Maybe there's a Prolog implementation for which the exercise would turn as the solution presents it.
Be that as it may, I'd like to learn about good ways to work around the problem.
Consider, for example, the query w(x).. the book's solution claims that the query w(x). should evaluate to false.. In fact, this is what happens:
?- w(x).
ERROR: w/1: Undefined procedure: y/1
Exception: (7) y(x) ?
(At this point, SWI-Prolog is expecting me to enter some letter indicating how to respond to the exception. More about this later.)
I'm looking for ways to either turn the interaction above to
?- w(x).
false.
?-
...or at least for a suitable <ONE-LETTER RESPONSE> I could give to SWI-Prolog so that it arrives at the conclusion false. IOW, so that
?- w(x).
ERROR: w/1: Undefined procedure: y/1
Exception: (7) y(x) ? <ONE-LETTER RESPONSE>
false.
?-
I know of at least one answer to my question, namely simply to delete or comment out the line:
w(V) :- y(V).
I would like to know of other possible solutions, such as, for example, the "suitable " I alluded to earlier.
Another possibility would be some SWI-Prolog global configuration that would result in the above interaction to change to
?- w(x).
false.
?-
A third possibility would be to "define" y in some minimal way. The only way I can come up with is by adding the fact
y(dummy).
to the knowledgebase. Is there a more minimal way to define y, one that does not require introducing an extraneous constant into the domain of discourse?
(This is not specific to SWI)
The first Prolog systems back in the 1970s actually behaved in the way you describe. Soon it became apparent that this is a frequent source of errors. Simple misspellings remained undetected for too long. Current implementations produce a clean existence error. This is standard behaviour since 1995.
However, you can go back into the olden tymes with the ISO Prolog flag unknown which has three values error (default), fail, and warning.
?- inex.
ERROR: Undefined procedure: inex/0 (DWIM could not correct goal)
?- set_prolog_flag(unknown, fail).
Warning: Using a non-error value for unknown in the global module
Warning: causes most of the development environment to stop working.
Warning: Please use :- dynamic or limit usage of unknown to a module.
Warning: See http://www.swi-prolog.org/howto/database.html
true.
?- inex.
false.
?- set_prolog_flag(unknown, warning).
Warning: Using a non-error value for unknown in the global module
Warning: causes most of the development environment to stop working.
Warning: Please use :- dynamic or limit usage of unknown to a module.
Warning: See http://www.swi-prolog.org/howto/database.html
true.
?- inex.
Warning: toplevel: Undefined procedure: inex/0 (DWIM could not correct goal)
false.
As you can read above, SWI proposes to use a dynamic declaration in stead - which in turn has its own problems... It is much better to declare instead:
:- discontiguous(y/1).
An undefined procedure error raises an exception so if you want the exception to be raised because you don't want to change y/1 predicate (delete or define it) you need to catch the exception and then return false like this:
x(a).
z(b).
z(c).
z(d).
w(V) :- x(V).
w(V) :- catch(y(V), error(Err,_Context),my_handler(Err)).
w(V) :- z(V).
my_handler(Err):- write(Err),fail.
Example:
?- w(x).
existence_error(procedure,y/1)
false.

turning off Redefined static procedure in prolog

anyone of you could tell me how to turn off "Redefined static procedure" warnings?
I red online documentation of swi-prolog and i found this predicate no_style_check(ultimate) that in principle should turn off these warnings, but when i execute this predicate
main:-
no_style_check(singleton),
no_style_check(discontiguous),
no_style_check(multiple),
require,
test_all.
i received this error
ERROR: Domain error: style_name' expected, foundmultiple'
Anyone knows an alternative way to do this or could tell me why i receive this error ?
Thanks in advance!
Prolog is a pretty loosey-goosey language, so by default it warns you when you do certain things that are not wrong per se, but tend to be a good indication that you've made a typo.
Now, suppose you write something like this:
myfoo(3, 3).
myfoo(N, M) :- M is N*4+1.
Then from the prompt you write this:
?- asserta(myfoo(7,9)).
ERROR: asserta/1: No permission to modify static procedure `myfoo/2'
ERROR: Defined at user://1:9
What's happening here is that you haven't told Prolog that it's OK for you to modify myfoo/2 so it is stopping you. The trick is to add a declaration:
:- dynamic myfoo/2.
myfoo(3, 3).
myfoo(N, M) :- M is N*4+1.
Now it will let you modify it just fine:
?- asserta(myfoo(7,9)).
true.
Now suppose you have three modules and they each advertise themselves by defining some predicate. For instance, you might have three files.
foo.pl
can_haz(foo).
bar.pl
can_haz(bar).
When you load them both you're going to get a warning:
?- [foo].
true.
?- [bar].
Warning: /home/fox/HOME/Projects/bar.pl:1:
Redefined static procedure can_haz/1
Previously defined at /home/fox/HOME/Projects/foo.pl:1
true.
And notice this:
?- can_haz(X).
X = bar.
The foo solution is gone.
The trick here is to tell Prolog that clauses of this predicate may be defined in different files. The trick is multifile:
foo.pl
:- multifile can_haz/1.
can_haz(foo).
bar.pl
:- multifile can_haz/1.
can_haz(bar).
In use:
?- [foo].
true.
?- [bar].
true.
?- can_haz(X).
X = foo ;
X = bar.
:- discontiguous does the same thing as multifile except in a single file; so you define clauses of the same predicate in different places in one file.
Again, singleton warnings are a completely different beast and I would absolutely not modify the warnings on them, they're too useful in debugging.

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

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

Declaring a predicate dynamic in gprolog

I have this code in Prolog:
dynamic(player_at/1).
player_at(house).
goto(X) :- retract(player_at(house)), assert(player_at(X)).
But I still get this error:
uncaught exception: error(permission_error(modify,static_procedure,player_at/1),retract/1)
when I execute goto(foo).
I've read the dynamic documentation, but I can't figure out how to use it, at least in gprolog. Am I missing something?
Fix the first line by prepending :-:
:- dynamic(player_at/1).
Without :- the line would dreefine predicate dynamic/1, instead of executing the existing dynamic predicate.
Other prolog implementations (but not gprolog) support this as well:
:- dynamic player_at/1.

Resources