The functionality is similar in spirit to, but not the same as, the one provided by the spdet tool and the Determinacy Checker library.
The determinacy analyzer in SPIDER can help you spot unwanted nondeterminacy in your programs. SPIDER examines your program source code and points out places where nondeterminacy may arise. It is not in general possible to find exactly which parts of a program will be nondeterminate (or determinate) without actually running the program. However, SPIDER can find some, and perhaps most, unwanted nondeterminacy.
Unintended nondeterminacy should be eradicated because:
:- name/arity is nondet.
in your source file. This is similar to a dynamic or discontiguous declaration.
Similarly, a predicate P/N may be classified as nondeterminate by the analyzer, whereas in reality it is determinate. This may happen e.g. if P/N calls a dynamic predicate that in reality never has more than one (determinate) clause. To prevent false alarms arising from this, you can inform the analyzer about determinate predicates by declarations of the form:
Using is/2 as a directive in this way is supported natively in SICStus Prolog 4.2.1. For older versions of SICStus you can wrap the directive in a conditional so that only SPIDER sees it, something like::- name/arity is semidet.
A complete example would look like::- if current_prolog_flag(dialect, spider). :- name/arity is semidet. :- endif. % SPIDER
An alternative, older, syntax is also available, see below.% parent.pl (this code requires SICStus Prolog 4.2.1) :- module(parent, [parent/2, is_parent/1]). :- parent/2 is nondet. parent(abe, rob). parent(abe, sam). parent(betty, rob). parent(betty, sam). :- is_parent/1 is nondet. is_parent(Parent) :- parent(Parent, _).
The determinacy analyzer looks for the following sources of nondeterminacy:
The above description is a simplification. In addition, the analyzer uses special knowledge about many builtins and library predicates and of the SICStus Prolog compiler in order to increase the accuracy of the inferred information.
By default SICStus Prolog does not recognize the nondet/1 and det/1 directives. Instead they will be treated as calls to undefined predicates and lead to errors during loading of the program and warnings in SPIDER.% Older syntax, requires det/1 to be defined. :- det name/arity. % corresponds to: name/arity is semidet. :- nondet name/arity. % corresponds to: name/arity is nondet.
One way to solve this is to define nondet/1 and det/1 as predicates that does nothing. This is what library(nondetdecl) does and it also defines nondet and det as prefix operators, similar to directives like mode/1. A downside to this method is that the calls will still be performed when your code is loaded. It may therefore be preferable to wrap the code with a conditional directive that ensures that only SPIDER sees the determinacy declarations (but in that case you may as well use the new is/2 directives).
So, to make a long story short, to use the old syntax, do this after you have declared your module:
and, when you want to declare the determinacy of some predicate you wrap that too in a conditional directive, so a complete example would look like::- if(current_prolog_flag(dialect, spider)). :- ensure_loaded(library(nondetdecl)). :- endif.
By using conditional compilation only SPIDER sees the determinacy directives, thus ensuring that there are no costs when the code is compiled or loaded in SICStus Prolog.% parent.pl (this code works in any version of SICStus Prolog) :- module(parent, [parent/2, is_parent/1]). :- if(current_prolog_flag(dialect, spider)). :- use_module(library(nondetdecl)). :- endif. :- if(current_prolog_flag(dialect, spider)). :- nondet parent/2. :- nondet is_parent/1. :- endif. parent(abe, rob). parent(abe, sam). parent(betty, rob). parent(betty, sam). is_parent(Parent) :- parent(Parent, _).
Note: The documentation for library(nondetdecl) and library(detcheck) claims that you only need to load them at compile time (using the when(compile_time) option to load_files/2). Unfortunately there is a bug in current versions of those libraries which makes it necessary for the libraries to be loaded also at load time. We expect that this will be fixed in a future version of SICStus Prolog. Using the is/2 directive or the SPIDER-only conditional compilation, as above, works around this bug.