Prolog "Out of local stack" Error - prolog

Here is my simple Prolog program:
friend(X,Y):-
knows(X,Y).
friend(X,Z):-
friend(X,Y),
friend(Y,Z).
knows(brian,tom).
knows(tom,peter).
If I type the following query
friend(brian,peter).
Prolog will give the following output:
?- friend(brian,peter).
true
If a further type a semicolon, Prolog will say:
ERROR: Out of local stack
What am I doing wrong here?

The error is in the second clause. It should be instead:
friend(X,Z):-
knows(X,Y),
friend(Y,Z).
Otherwise, when you ask Prolog for more solutions, you end up having the friend/2predicate recursively calling itself without first establishing a knows/2intermediate relation. You can learn more about the bug in your program by tracing the calls to the friend/2 predicate. Try:
?- trace, friend(brian,peter).

The understand the source of non-termination in your program it suffices to look at the following failure-slice:
friend(X,Y):- false,
knows(X,Y).
friend(X,Z):-
friend(X,Y), false,
friend(Y,Z).
knows(brian,tom) :- false.
knows(tom,peter) :- false.
It is because of friend(X, Z) :- friend(X, Y), ... that your program will not terminate. It will produce answers, here and there, but ultimately it will loop. For more, see failure-slice.

Related

Prolog singleton variables in rule head causes program to output booleans for all queries

I have this prolog program.
red(rose).
red(anthurium).
white(rose).
white(gardenia).
white(jasmine).
like(Y,X) :-
red(X),!,
fail
;
white(X).
And below is how it responds to different queries.
?- like(rose,gardenia).
true.
?- like(rose,P).
false.
?- like(Val,anthurium).
false.
?- like(rose,X).
false
The problem I now have is this:
When querying with a variable within the query (Eg: ?- like(rose,X).), Prolog usually responds by returning a value, (something like X=some_val). Why I don't get any value for those variables, but either true or false?
All helpful answers are highly appreciated. Thanks in advance.
Think about what Prolog is doing here:
like(rose,P) succeeds if red(P), so it grabs a possible substitution for P, namely rose or anthurium. Then it traverses the cut and then it fails. But "failing" means that the proof search down that path didn't bring any solution, there are no successful bindings to report (the only fail to get information out of a failing branch is to side-effect to a log file and read check it later). In fact, all bindings will be undone on backtracking. The second branch is white(X), but rose is not white, so we fail here, too.
You can also write:
like(_,X) :- \+ red(X).
like(_,X) :- white(X).
which is a bit more readable. One notices that when calling like(_,X), the goal enclosed by the negation-as-failure operator \+ is nonground. This is bad, and causes a floundering query (in other words, don't do that). I have written this little page on "floundering".

How can I check that a particular constant exists in Prolog?

Say I have the following:
person(james).
person(pete).
father(james, pete).
Is there a way to validate that both the arguments to father have been defined i.e to stop a typo such as father(jmes, pete).
There is an easy way of checking these kinds of errors using Prolog: You can call rules at initialization time, i.e. one that checks that your fathers relations is properly defined. This can be useful to catch those typo errors.
:- use_module(library(error)).
check_fathers :-
% Take an element of the father relation
(father(P, _); father(_, P)),
% Proceed, if P is not a person
\+ person(P),
% Throw an error
syntax_error(father_is_no_person(P)).
check_fathers.
:- check_fathers.
person(james).
person(pete).
father(jame, pete). % TYPO! jame instead of james
Then, the program will produce the following output:
ERROR: Syntax error: father_is_no_person(jame)
Warning: <filename>:<line>:
Warning: Goal (directive) failed: user:check_fathers
Your assumptions are wrong in this sense:
father(james, pete). is a fact. It is something that you tell the Prolog processor is uneniably true (similar to a row in a table in a relational database).
So is father(jmes, pete).. Another fact. You are stating that this is so.
There is nothing to check, really.
On the other hand, if father(jmes, pete) appears in a a goal position, the Prolog processor will say "no, I have no indiciation that this is true":
father(james, pete). % that's a fat fact!
?- father(jmes, pete). % that's a query
false. % and the answer is "no, there is no evidence of that"
What you you would like to have is to have something like Java enum types: have the compiler make sure that a keyword comes indeed from a selected set of allowed keywords.
Prolog has has only basic typing, so this cannot be done directly.
But you could do this:
% if X is an unbound variable or a member of the indicated list,
% we are good
allowed_father(X) :-
(var(X);memberchk(X,[james,vader])),!.
% otherwise, we don't just fail, we actually throw an exception
allowed_father(X) :-
throw(error(unknown_father(X))).
% ---
% if X is an unbound variable or a member of the indicated list,
% we are good
allowed_son(X) :-
(var(X);memberchk(X,[pete,luke])),!.
% otherwise, we don't just fail, we actually throw an exception
allowed_father(X) :-
throw(error(unknown_son(X))).
and then you can call the above predicates whenever you need to perform a check:
query_anout(Father) :-
allowed_father(Father),
...
But it's rather awkward. Plus the thrown exception is not ISO-standard and the resulting error message may be confusing (I always rage against ISO standard exceptions which are doubleplusungood awkward)

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.

Prolog no operand Predicates

I am examining a Prolog example as a tutorial. In this example I have a predicate with Zero operand like this:
print_all_solutions :-
findall(_,print_solution,_).
how can I call print_all_solution in the console?
When I ask this in the Prolog console I get nothing:
?- print_all_solutions
no answer, also :
?- print_all_solutions.
no answer.
While i get correct answers to other questions like:
?- goal(state([],right,[a,b,c,d],12)).
true.
?- goal(state([],right,[a,b,c,d],19)).
false.
How should I ask a question about predicates with no operand ( /0 ), to see the solution in the console?
I guess your problem is that either init(State) or, more probably, solve(State,Solution,EndState) don't work.
You need to debug: enter these commands after you consulted the source file
?- leash(-all),trace.
?- print_solution.
and you'll get some clue from the Prolog engine
I simply typed this in the console:
findall(_,print_all_solutions,_).
and i get the answer.

Resources