predsort/3 existence_error [Prolog] - prolog

I'm trying to sort a list of lists by the third element in the sub-lists, and am doing so using a predicate for sorting defined as such:
sortData(X, [_,_,Z1], [_,_,Z2]) :- compare(X, Z1, Z2).
When I try to use this predicate in my Prolog console (predsort(sortData, [[0,5,2],[6,3,1]], X).), I get an error stating:
uncaught exception: error(existence_error(procedure,predsort/3),top_level/0)
I did some research and found this SO question on the matter, but was unable to use the tips suggested by the commenters to fix my error. I tried adding in :- use_module(library(sort)). to my code, but that gave a warning upon compilation (warning: unknown directive use_module/1 - maybe use initialization/1 - directive ignored).
Any tips as to why I may be getting the predsort/3 existence error?
EDIT: My desired output given the call above is: X = [[6, 3, 1], [0, 5, 2]].

Related

Why am I getting existence error when trying to remove doubles from a list?

Why am I getting existence error here, specifically:
uncaught exception: error(existence_error(procedure,list_append/2),noDoubles/2)
I would like to remove doubles from a list and I tried using the 'if' from prolog.
list_append(X,[],[X]).
list_append(X,L1,[X|L1]).
noDoubles([X],[X]).
noDoubles([H|T],L1):- (member(H,T) -> noDoubles(T,L1);(list_append(H,L1),noDoubles(T,L1))).
I have prolog 1.4.4
You've defined list_append with arity 3, and you're calling list_append predicate with arity 2.

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.

Prolog gives is_absolute_file_name unhandled exception

i'm a total newbie in Prolog and learning it while taking a course in school. We have this big test coming up tomorrow and as i'm studying here i tried to do some tasks from previous versions of this test. One particular task was to take a string and put a "-" after every character "a". So for example word "example" would look like "exa-mple".
I wrote a code for it:
kriipsuga(S6ne,R) :-
name(S6ne,X),
write(X),
goThrough(X,Y),
name(R,Y).
goThrough([X|Xs],Y) :-
X == 97,
append(Y,[97],Z),
append(Z,[45],O),
goThrough(Xs,O).
goThrough([X|Xs],Y) :-
X \= 97,
append(Y,[X],O),
goThrough(Xs,O).
goThrough([],Y) :- write(Y),Y.
This is the error:
?- goThrough([1,2,3,4],Y).
[1, 2, 3, 4]
ERROR: Unhandled exception: is_absolute_file_name/1: Type error: `text' expected, found `1'
Googling gave no results, maybe you guys could help me figure it out.
Thanks :)
The shortcut [File1, File2, ...] is traditionally used in Prolog as a shorthand to the predicate that compiles and load a source files (usually, consult/1). The file argument is expanded into an absolute file path. In you code, the last clause is:
goThrough([],Y) :- write(Y),Y.
In your sample query, this clause ends up being used and a call [1|_] is made, hence the error you get. To make it clear, try to trace execution using the query:
?- trace, goThrough([1,2,3,4],Y).

gprolog: Getting a stacktrace after an exception

While using gprolog I often have exceptions without any kind of line numbers or context like this one:
uncaught exception: error(instantiation_error,(is)/2)
Without any kind of context. I know I can do a trace but it would take very long to debug it with trace since I need to execute a lot of things before getting to the place where the error occur.
Any idea on how to have this stacktrace ? Or a dynamic trace / notrace ?
EDIT: Or just automate the printing of the whole trace output.
#gusbro's answer (s(X)) shows you how you somewhat solve this with GNU's debugger. However, if you cannot afford to see all the printing going on, or it is much too slow, you might consider the following "debugger" available as library(debug) in Scryer.
I personally do not use debuggers offered by Prolog systems for the simple reason that most of them print much too much, are often buggy themselves, and have their own specific ever changing conventions, I can't afford to learn.
:- op(900, fx, [#,$,$-]).
$-(G_0) :-
catch(G_0, Ex, ( portray_clause(exception:Ex:G_0), throw(Ex) ) ).
$(G_0) :-
portray_clause(call:G_0),
$-G_0,
portray_clause(exit:G_0).
#(G_0) :-
( $-G_0
*-> true
; portray_clause(badfail:G_0),
throw(goal_failed(G_0))
).
:- op(950, fy, *).
*(_).
To use it, simply add $-, $, or # in front of a specific goal.
$- means: only signal exceptions going through this goal
$ additionally show call and exit
# assures that there is at least one answer, and if not, it is reported and an exception is thrown.
Use above annotations sparingly!
* removes the goal. This is for generalizing a program doing program modification/program-slicing in a pure monotonic program. You need this in case of unexpected failures. For examples how to use it, see the following answers/debugging sessions
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13.
More.
_/*term*/ replaces a term by an anonymous variable. This generalizes a program even further than * alone. Example sessions:
1,
2,
3,
4,
5,
6,
7,
8,
9,
10.
In this manner you can reduce the information you watch significantly.
In other systems supporting meta_predicate directives like SICStus, YAP and SWI, add in front the following directive:
:- meta_predicate(( $-(0), $(0), #(0) )).
You may trace/0 and leash/1 only the exception port, e.g:
?- trace.
?- leash([exception]).
Then you run your program and it will print a trace on screen but only stop when an exception occurs. There you can see the "stack trace" (ancestors) by pressing letter g.

Why doesn't 'Q' unify in this PROLOG program

I am writing a PROLOG program in which the variable of interest (Q) refuses to unify. I have gotten around this with a hacky solution (include a write statement). But there has to be a way to make this unify, but for the love of me, I am not able to figure it out.
I'd really appreciate any help.
Thanks in advance.
Here is my code (I have annotated wherever I have excluded code for brevity)
:- use_module(library(bounds)).
:- use_module(library(lists)).
solve([17],Q,_,_,_):- write(Q). %this is the hacky workaround
solve(L,Q,1,3,2) :- jump(L,Q,N,1,3,2,R), solve(N,R,S,D,M), member([S|[D|[M|[]]]],[[1, 3, 2], [1, 9, 4], [2, 10, 5] this list contains 76 items - all of which are lists of length 3. I have omitted them here for the sake of brevity]).
% there are about 75 other definitions for solve, all of which are structured exactly the same. The only difference is that the numbers in the input parameters will be different in each definition
jump(L,Q,N,S,D,M,R):- member(S,L), not(member(D,L)), member(M,L), delete(L,S,X), delete(X,M,Y), append(Y,[D],N), append(Q,[[S,D]],R).
cross_sol(Q) :- solve([5,9,10,11,17,24],Q,S,D,M), member([S,D,M], [
I have edited out this list here for the sake of brevity. It is the same list found in the definition of solve
]).
For some reason, Q does not unify. Please help!
Thank you!
The cross_sol/1 predicate seems malformed.
cross_sol(Q) :- solve([5,9,10,11,17,24],[],S,D,M), member([S,D,M], [
I have edited out this list here for the sake of brevity. It is the same list found in the definition of solve
]).
The variable Q is a singleton -- it is not referenced anywhere in the body (unless it is the portion you have suppressed).

Resources