5d57058e8e
git-svn-id: https://yap.svn.sf.net/svnroot/yap/trunk@132 b08c6af1-5177-4d33-ba66-4b1c6b8b522a
13154 lines
429 KiB
TeX
13154 lines
429 KiB
TeX
\input texinfo @c -*- mode: texinfo; coding: latin-1; -*-
|
||
|
||
@c %**start of header
|
||
@setfilename yap.info
|
||
@setcontentsaftertitlepage
|
||
@settitle YAP Prolog User's Manual
|
||
@c For double-sided printing, uncomment:
|
||
@c @setchapternewpage odd
|
||
@c %**end of header
|
||
|
||
@set VERSION 4.3.20
|
||
@set EDITION 4.1.0
|
||
@set UPDATED July 2001
|
||
|
||
@c Index for C-Prolog compatible predicate
|
||
@defindex cy
|
||
@c Index for predicates not in C-Prolog
|
||
@defindex cn
|
||
@c Index for predicates sort of (almost) in C-Prolog
|
||
@defindex ca
|
||
|
||
@c Index for SICStus Prolog compatible predicate
|
||
@defindex sy
|
||
@c Index for predicates not in SICStus Prolog
|
||
@defindex sn
|
||
@c Index for predicates sort of (almost) in SICStus Prolog
|
||
@defindex sa
|
||
|
||
|
||
@setchapternewpage odd
|
||
@c @smallbook
|
||
@comment %** end of header
|
||
|
||
@ifinfo
|
||
@format
|
||
START-INFO-DIR-ENTRY
|
||
* Yap: (yap). YAP Prolog User's Manual.
|
||
END-INFO-DIR-ENTRY
|
||
@end format
|
||
@end ifinfo
|
||
|
||
@titlepage
|
||
@title YAP User's Manual
|
||
@subtitle Version @value{VERSION}
|
||
@author V@'{@dotless{i}}tor Santos Costa,
|
||
@author Lu@'{@dotless{i}}s Damas,
|
||
@author Rog@'erio Reis, and
|
||
@author R@'uben Azevedo
|
||
@page
|
||
@vskip 2pc
|
||
Copyright @copyright{} 1989-2000 L. Damas, V. Santos Costa and Universidade
|
||
do Porto.
|
||
|
||
Permission is granted to make and distribute verbatim copies of
|
||
this manual provided the copyright notice and this permission notice
|
||
are preserved on all copies.
|
||
|
||
Permission is granted to copy and distribute modified versions of this
|
||
manual under the conditions for verbatim copying, provided that the entire
|
||
resulting derived work is distributed under the terms of a permission
|
||
notice identical to this one.
|
||
|
||
Permission is granted to copy and distribute translations of this manual
|
||
into another language, under the above conditions for modified versions.
|
||
|
||
@end titlepage
|
||
|
||
@ifinfo
|
||
@node Top, , , (dir)
|
||
@top YAP Prolog
|
||
|
||
This file documents the YAP Prolog System version @value{VERSION}, a
|
||
high-performance Prolog compiler developed at LIACC, Universidade do
|
||
Porto. YAP is based on David H. D. Warren's WAM (Warren Abstract
|
||
Machine), with several optimizations for better performance. YAP follows
|
||
the Edinburgh tradition, and is largely compatible with DEC-10 Prolog,
|
||
Quintus Prolog, and especially with C-Prolog.
|
||
|
||
This file contains the CLP(Q,R) manual as distributed by the Austrian
|
||
Research Institute for Artificial Intelligence (OFAI). Permission on
|
||
this document follows the following license:
|
||
|
||
Copyright @copyright{} 1992,1993,1994,1995 OFAI Austrian Research
|
||
Institute for Artificial Intelligence (OFAI) Schottengasse 3 A-1010
|
||
Vienna, Austria
|
||
|
||
Permission is granted to make and distribute verbatim copies of this
|
||
manual provided the copyright notice and this permission notice are
|
||
preserved on all copies.
|
||
|
||
Permission is granted to copy and distribute modified versions of this
|
||
manual under the conditions for verbatim copying, provided that the
|
||
entire resulting derived work is distributed under the terms of a
|
||
permission notice identical to this one.
|
||
|
||
Permission is granted qto copy and distribute translations of this
|
||
manual into another language, under the above conditions for modified
|
||
versions, except that this permission notice may be stated in a
|
||
translation approved by the OFAI.
|
||
|
||
This file contains a chapter on CHR. This package is distributed under
|
||
license from LMU (Ludwig-Maximilians-University), Munich, Germany:
|
||
|
||
Permission is granted to copy and distribute modified versions of this
|
||
chapter under the conditions for verbatim copying, provided that the entire
|
||
resulting derived work is distributed under the terms of a permission
|
||
notice identical to this one.
|
||
|
||
Permission is granted to copy and distribute translations of this chapter
|
||
into another language, under the above conditions for modified versions,
|
||
except that this permission notice may be stated in a translation approved
|
||
by LMU.
|
||
|
||
Copyright @copyright{} 1996-98 LMU (Ludwig-Maximilians-University)@*
|
||
Munich, Germany
|
||
@menu
|
||
* Intro:: Introduction
|
||
* Install:: Installation
|
||
* Run:: Running YAP
|
||
* Syntax:: The syntax of YAP
|
||
* Loading Programs:: Loading Prolog programs
|
||
* Modules:: Using Modules in YAP
|
||
* Builtins:: Built In Predicates
|
||
* Library:: Library Predicates
|
||
* Extensions:: Extensions to Standard YAP
|
||
* Rational Trees:: Working with Rational Trees
|
||
* Coroutining:: Changing the Execution of Goals
|
||
* Attributed Variables:: Using attributed Variables
|
||
* CLPQR:: The CLP(Q,R) System
|
||
* CHR:: The CHR System
|
||
* Logtalk:: The Logtalk Object-Oriented System
|
||
* Parallelism:: Running in Or-Parallel
|
||
* Tabling:: Storing Intermediate Solutions of programs
|
||
* Low Level Profiling:: Profiling Abstract Machine Instructions
|
||
* Low Level Tracing:: Tracing at Abstract Machine Level
|
||
* Debugging:: Using the Debugger
|
||
* Efficiency:: Efficiency Considerations
|
||
* C-Interface:: Interfacing predicates written in C
|
||
* YapLibrary:: Using YAP as a library in other programs
|
||
* Compatibility:: Compatibility with other Prolog systems
|
||
* Predicate Index:: An item for each predicate
|
||
* Concept Index:: An item for each concept
|
||
|
||
Built In Predicates
|
||
* Control:: Controlling the execution of Prolog programs
|
||
* Undefined Procedures:: Handling calls to Undefined Procedures
|
||
* Testing Terms:: Predicates on Terms
|
||
* Comparing Terms:: Comparison of Terms
|
||
* Arithmetic:: Arithmetic in YAP
|
||
* I/O:: Input/Output with YAP
|
||
* Database:: Modifying Prolog's Database
|
||
* Sets:: Finding All Possible Solutions
|
||
* Grammars:: Grammar Rules
|
||
* Preds:: Predicate Information
|
||
* OS:: Access to Operating System Functionality
|
||
* Term Modification:: Updating Prolog Terms
|
||
* Profiling:: Profiling Prolog Execution
|
||
* Arrays:: Supporting Global and Local Arrays
|
||
* Preds:: Information on Predicates
|
||
* Misc:: Miscellaneous Predicates
|
||
|
||
|
||
Subnodes of Running
|
||
* Interactive Mode:: Running Yap Interactively
|
||
* Script Mode:: Running Prolog files as scripts
|
||
|
||
Subnodes of Syntax
|
||
* Formal Syntax:: Syntax of Terms
|
||
* Tokens:: Syntax of Prolog tokens
|
||
|
||
Subnodes of Tokens
|
||
* Numbers:: Integer and Floating-Point Numbers
|
||
* Strings:: Sequences of Characters
|
||
* Atoms:: Atomic Constants
|
||
* Variables:: Logical Variables
|
||
* Punctuation Tokens:: Tokens that separate other tokens
|
||
* Layout:: Comments and Other Layout Rules
|
||
|
||
Subnodes of Numbers
|
||
* Integers:: How Integers are read and represented
|
||
* Floats:: Floating Point Numbers
|
||
|
||
Subnodes of Loading Programs
|
||
* Compiling:: Program Loading and Updating
|
||
* Setting the Compiler:: Changing the compiler's parameters
|
||
* Saving:: Saving and Restoring Programs
|
||
|
||
Subnodes of Modules
|
||
* Module Concepts:: The Key Ideas in Modules
|
||
* Defining Modules:: How To Define a New Module
|
||
* Using Modules:: How to Use a Module
|
||
* Meta-Predicates in Modules:: How to Handle New Meta-Predicates
|
||
|
||
Subnodes of Input/Output
|
||
* Streams and Files:: Handling Streams and Files
|
||
* C-Prolog File Handling:: C-Prolog Compatible File Handling
|
||
* I/O of Terms:: Input/Output of terms
|
||
* I/O of Characters:: Input/Output of Characters
|
||
* I/O for Streams:: Input/Output using Streams
|
||
* C-Prolog to Terminal:: C-Prolog compatible Character I/O to terminal
|
||
* I/O Control:: Controlling your Input/Output
|
||
* Sockets:: Using Sockets from YAP
|
||
|
||
Subnodes of Database
|
||
* Modifying the Database:: Asserting and Retracting
|
||
* Looking at the Database:: Finding out what is in the Data Base
|
||
* Database References:: Using Data Base References
|
||
* Internal Database:: YAP's Internal Database
|
||
* BlackBoard:: Storing and Fetching Terms in the BlackBoard
|
||
|
||
Subnodes of Library
|
||
* Association Lists:: Binary Tree Implementation of Association Lists
|
||
* AVL Trees:: Predicates to add and lookup balanced binary trees.
|
||
* Heaps:: Labelled binary tree where the key of each node is less
|
||
than or equal to the keys of its sons
|
||
* Lists:: List Manipulation
|
||
* Ordered Sets:: Ordered Set Manipulation
|
||
* Pseudo Random:: Pseudo Random Numbers
|
||
* Queues:: Queue Manipulation
|
||
* Random:: Random Numbers
|
||
* RegExp:: Regular Expression Manipulation
|
||
* Splay Trees:: Splay Trees
|
||
* String I/O:: Writing To and Reading From Strings
|
||
* System:: System Utilities
|
||
* Terms:: Utilities on Terms
|
||
* Timeout:: Call With Timeout
|
||
* Trees:: Updatable Binary Trees
|
||
* UGraphs:: Unweighted Graphs
|
||
|
||
Subnodes of Debugging
|
||
* Deb Preds:: Debugging Predicates
|
||
* Deb Interaction:: Interacting with the debugger
|
||
|
||
Subnodes of Compatibility
|
||
* C-Prolog:: Compatibility with the C-Prolog interpreter
|
||
* SICStus Prolog:: Compatibility with the Quintus and SICStus Prolog systems
|
||
* ISO Prolog:: Compatibility with the ISO Prolog standard
|
||
|
||
Subnodes of Attributes
|
||
* Attribute Declarations:: Declaring New Attributes
|
||
* Attribute Manipulation:: Setting and Reading Attributes
|
||
* Attributed Unification:: Tuning the Unification Algorithm
|
||
* Displaying Attributes:: Displaying Attributes in User-Readable Form
|
||
* Projecting Attributes:: Obtaining the Attributes of Interest
|
||
* Attribute Examples:: Two Simple Examples of how to use Attributes.
|
||
|
||
Subnodes of CLP(Q,R)
|
||
* Introduction to CLPQR:: The CLP(Q,R) System
|
||
* Referencing CLPQR:: How to Reference CLP(Q,R)
|
||
* CLPQR Acknowledgments:: Acknowledgments for CLP(Q,R)
|
||
* Solver Interface:: Using the CLP(Q,R) System
|
||
* Notational Conventions:: The CLP(Q,R) Notation
|
||
* Solver Predicates:: The CLP(Q,R) Interface Predicates
|
||
* Unification:: Unification and CLP(Q,R)
|
||
* Feedback and Bindings:: Information flow in CLP(Q,R)
|
||
* Linearity and Nonlinear Residues:: Linear and Nonlinear Constraints
|
||
* How Nonlinear Residues are made to disappear:: Handling Nonlinear Residues
|
||
* Isolation Axioms:: Isolating the Variable to be Solved
|
||
* Numerical Precision and Rationals:: Reals and Rationals
|
||
* Projection and Redundancy Elimination:: Presenting Bindings for Query Variables
|
||
* Variable Ordering:: Linear Relationships between Variables
|
||
* Turning Answers into Terms:: using @code{call_residue/2}
|
||
* Projecting Inequalities:: How to project linear inequations
|
||
* Why Disequations:: Using Disequations in CLP(Q,R)
|
||
* Syntactic Sugar:: An easier syntax
|
||
* Monash Examples:: The Monash Library
|
||
* Compatibility Notes:: CLP(Q,R) and the clp(R) interpreter
|
||
* A Mixed Integer Linear Optimization Example:: MIP models
|
||
* Implementation Architecture:: CLP(Q,R) Components
|
||
* Fragments and Bits:: Final Last Words on CLP(Q,R)
|
||
* CLPQR Bugs:: Bugs in CLP(Q,R)
|
||
* CLPQR References:: References for CLP(Q,R)
|
||
|
||
Subnodes of CHR
|
||
* CHR Copyright::
|
||
* CHR Introduction::
|
||
* CHR Introductory Examples::
|
||
* CHR Library::
|
||
* CHR Debugging::
|
||
* CHR Programming Hints::
|
||
* CHR Constraint Handlers::
|
||
* CHR Backward Compatibility::
|
||
|
||
Subnodes of C-Interface
|
||
* Manipulating Terms:: Primitives available to the C programmer
|
||
* Unifying Terms:: How to Unify Two Prolog Terms
|
||
* Manipulating Strings:: From character arrays to Lists of codes and back
|
||
* Memory Allocation:: Stealing Memory From Yap
|
||
* Controlling Streams:: Control How Yap sees Streams
|
||
* Calling Yap From C:: From C to Yap to C to Yap
|
||
* Writing C:: Writing Predicates in C
|
||
* Loading Objects:: Loading Object Files
|
||
* Sav&Rest:: Saving and Restoring
|
||
* Yap4 Notes:: Changes in Foreign Predicates Interface
|
||
|
||
Subnodes of C-Prolog
|
||
* Major Differences with C-Prolog:: Major Differences between YAP and C-Prolog
|
||
* Fully C-Prolog Compatible:: Yap predicates fully compatible with
|
||
C-Prolog
|
||
* Not Strictly C-Prolog Compatible:: Yap predicates not strictly as C-Prolog
|
||
* Not in C-Prolog:: Yap predicates not available in C-Prolog
|
||
* Not in YAP:: C-Prolog predicates not available in YAP
|
||
|
||
Subnodes of SICStus Prolog
|
||
* Major Differences with SICStus:: Major Differences between YAP and SICStus Prolog
|
||
* Fully SICStus Compatible:: Yap predicates fully compatible with
|
||
SICStus Prolog
|
||
* Not Strictly SICStus Compatible:: Yap predicates not strictly as
|
||
SICStus Prolog
|
||
* Not in SICstus Prolog:: Yap predicates not available in SICStus Prolog
|
||
|
||
|
||
Tables
|
||
* Operators:: Predefined operators
|
||
|
||
@end menu
|
||
|
||
@end ifinfo
|
||
|
||
|
||
@node Intro, Install, , Top
|
||
@unnumbered Introduction
|
||
|
||
This document provides User information on version @value{VERSION} of
|
||
YAP (@emph{yet another prolog}). The YAP Prolog System is a
|
||
high-performance Prolog compiler developed at LIACC, Universidade do
|
||
Porto. YAP provides several important features:
|
||
|
||
@itemize @bullet
|
||
@item Speed: YAP is widely considered one of the fastest available Prolog
|
||
systems.
|
||
|
||
@item Functionality: it supports stream I/O, sockets, modules,
|
||
exceptions, Prolog debugger, C-interface, dynamic code, internal
|
||
database, DCGs, saved states, co-routining, arrays.
|
||
|
||
@item We explicitly allow both commercial and non-commercial use of YAP.
|
||
@end itemize
|
||
|
||
YAP is based on the David H. D. Warren's WAM (Warren Abstract Machine),
|
||
with several optimizations for better performance. YAP follows the
|
||
Edinburgh tradition, and was originally designed to be largely
|
||
compatible with DEC-10 Prolog, Quintus Prolog, and especially with
|
||
C-Prolog.
|
||
|
||
YAP implements most of the ISO-Prolog standard. We are striving at
|
||
full compatibility, and the manual describes what is still
|
||
missing. The manual also includes a (largely incomplete) comparison
|
||
with SICStus Prolog.
|
||
|
||
The document is intended neither as an introduction to Prolog nor to the
|
||
implementation aspects of the compiler. A good introduction to
|
||
programming in Prolog is the book @cite{The Art of Prolog}, by
|
||
L. Sterling and E. Shapiro, published by "The MIT Press, Cambridge
|
||
MA". Other references should include the classical @cite{Programming in
|
||
Prolog}, by W.F. Clocksin and C.S. Mellish, published by
|
||
Springer-Verlag.
|
||
|
||
YAP 4.3 is known to build with many versions of gcc (<= gcc-2.7.2, >=
|
||
gcc-2.8.1, >= egcs-1.0.1, gcc-2.95.*) and on a variety of Unixen:
|
||
SunOS 4.1, Solaris 2.*, Irix 5.2, HP-UX 10, Dec Alpha Unix, Linux 1.2
|
||
and Linux 2.* (RedHat 4.0 thru 5.2, Debian 2.*) in both the x86 and
|
||
alpha platforms. It has been built on Windows NT 4.0 using Cygwin from
|
||
Cygnus Solutions (see README.nt) and using Visual C++ 6.0.
|
||
|
||
The overall copyright and permission notice for YAP4.3 can be found in
|
||
the Artistic file in this directory. YAP follows the Perl Artistic
|
||
license, and it is thus non-copylefted freeware.
|
||
|
||
If you have a question about this software, desire to add code, found a
|
||
bug, want to request a feature, or wonder how to get further assistance,
|
||
please send e-mail to @email{yappers@@ncc.up.pt}. To subscribe to the
|
||
mailing list, send a request to @email{majordomo@@ncc.up.pt} with body
|
||
"subscribe yappers".
|
||
|
||
Online documentation is available for YAP at:
|
||
|
||
@url{http://www.ncc.up.pt/~vsc/Yap/}
|
||
|
||
Recent versions of Yap, including both source and selected binaries,
|
||
can be found from this same URL.
|
||
|
||
This manual was written by V@'{@dotless{i}}tor Santos Costa,
|
||
Lu@'{@dotless{i}}s Damas, Rog@'erio Reis, and R@'uben Azevedo. The
|
||
manual is largely based on the DECsystem-10 Prolog User's Manual by
|
||
D.L. Bowen, L. Byrd, F. C. N. Pereira, L. M. Pereira, and
|
||
D. H. D. Warren. We have also used comments from the Edinburgh Prolog
|
||
library written by R. O'Keefe. We would also like to gratefully
|
||
acknowledge the contributions from Ashwin Srinivasian.
|
||
|
||
We are happy to include in YAP several excellent packages developed
|
||
under separate licenses. Our thanks to the authors for their kind
|
||
authorisation to include these packages.
|
||
|
||
The packages are, in alphabetical order:
|
||
|
||
@itemize @bullet
|
||
@item The CHR package developed at TUM by
|
||
Ludwig-Maximilians-Universitaet Muenchen (LMU) by Dr. Fruehwirth Thom
|
||
and by Dr. Christian Holzbaur. The package is distributed under license
|
||
from LMU (Ludwig-Maximilians-University), Munich, Germany:
|
||
|
||
Permission is granted to copy and distribute modified versions of this
|
||
chapter under the conditions for verbatim copying, provided that the entire
|
||
resulting derived work is distributed under the terms of a permission
|
||
notice identical to this one.
|
||
|
||
Permission is granted to copy and distribute translations of this chapter
|
||
into another language, under the above conditions for modified versions,
|
||
except that this permission notice may be stated in a translation approved
|
||
by LMU.
|
||
|
||
Copyright @copyright{} 1996-98 LMU (Ludwig-Maximilians-University)@*
|
||
Munich, Germany
|
||
|
||
@item The CLP(Q,R) package developed at OFAI Austrian Research
|
||
Institute for Artificial Intelligence by Christian Holzbaur. The package
|
||
is distributed under the OFAI license. Documentation on this package is
|
||
a chapter of this manual, which is covered by the OFAI license:
|
||
|
||
Copyright @copyright{} 1992,1993,1994,1995 OFAI Austrian Research
|
||
Institute for Artificial Intelligence (OFAI) Schottengasse 3 A-1010
|
||
Vienna, Austria
|
||
|
||
Permission is granted to make and distribute verbatim copies of this
|
||
manual provided the copyright notice and this permission notice are
|
||
preserved on all copies.
|
||
|
||
Permission is granted to copy and distribute modified versions of this
|
||
manual under the conditions for verbatim copying, provided that the
|
||
entire resulting derived work is distributed under the terms of a
|
||
permission notice identical to this one.
|
||
|
||
Permission is granted qto copy and distribute translations of this
|
||
manual into another language, under the above conditions for modified
|
||
versions, except that this permission notice may be stated in a
|
||
translation approved by the OFAI.
|
||
|
||
@item The Logtalk Object-Oriented system is developed at the University
|
||
of Beira Interior, Portugal, by Paulo Moura.
|
||
The package is distributed under the Perl Artistic License.
|
||
Instructions about loading this package are included in this document.
|
||
The documentation on this package is distributed separately from yap.tex.
|
||
|
||
Copyright @copyright{} 1998-2001 Paulo Moura
|
||
|
||
@item The Pillow WEB library developed at Universidad Politecnica de
|
||
Madrid by the CLIP group. This package is distributed under the FSF's
|
||
LGPL. Documentation on this package is distributed separately from
|
||
yap.tex.
|
||
@end itemize
|
||
|
||
@node Install, Run, Intro, Top
|
||
@chapter Installing YAP
|
||
@cindex installation
|
||
|
||
|
||
@menu
|
||
* Configuration Options:: Tuning the Functionality of YAP Machine
|
||
* Machine Options:: Tuning YAP for a Particular Machine and Compiler
|
||
@end menu
|
||
|
||
To compile YAP it should be sufficient to:
|
||
|
||
@enumerate
|
||
@item @code{mkdir ARCH}.
|
||
|
||
@item @code{cd ARCH}.
|
||
|
||
@item @code{../configure}.
|
||
|
||
@item check the Makefile for any extensions or changes you want to
|
||
make.
|
||
|
||
YAP uses @code{autoconf}. Recent versions of Yap try to follow GNU
|
||
conventions on where to place software.
|
||
|
||
@itemize @bullet
|
||
@item The main executable is placed at @code{BINDIR}. This executable is
|
||
actually a script that calls the Prolog engine, stored at @code{LIBDIR}.
|
||
|
||
@item @code{LIBDIR} is the directory where libraries are stored. YAPLIBDIR is a
|
||
subsdirectory that contains the Prolog engine and a Prolog library.
|
||
|
||
@item @code{INCLUDEDIR} is used if you want to use Yap as a library.
|
||
|
||
@item @code{INFODIR} is where to store @code{info} files. Usually
|
||
@code{/usr/local/info}, @code{/usr/info}, or @code{/usr/share/info}.
|
||
@end itemize
|
||
|
||
@item @code{make}.
|
||
|
||
@item If the compilation succeeds, try @code{./yap}.
|
||
|
||
@item If you feel satisfied with the result, do @code{make install}.
|
||
|
||
@item @code{make install-info} will create the info files in the
|
||
standard info directory.
|
||
|
||
@item @code{make html} will create documentation in html format in the
|
||
predefined directory.
|
||
|
||
In most systems you will need to be superuser in order to do @code{make
|
||
install} and @code{make info} on the standard directories.
|
||
@end enumerate
|
||
|
||
@node Configuration Options, Machine Options, ,Install
|
||
@section Tuning the Functionality of YAP
|
||
@cindex syntax
|
||
|
||
Compiling Yap with the standard options give you a plain vanilla
|
||
Prolog. You can tune Yap to include extra functionality by calling
|
||
@code{configure} with the appropriate options:
|
||
|
||
@itemize @bullet
|
||
@item @code{--enable-rational-trees=yes} gives you support for infinite
|
||
rational trees.
|
||
|
||
@item @code{--enable-coroutining=yes} gives you support for coroutining,
|
||
including freezing of goals, attributed variables, and
|
||
constraints. This will also enable support for infinite rational
|
||
trees.
|
||
|
||
@item @code{--enable-depth-limit=yes} allows depth limited evaluation, say for
|
||
implementing iterative deepening.
|
||
|
||
@item @code{--enable-low-level-tracer=yes} allows support for tracing all calls,
|
||
retries, and backtracks in the system. This can help in debugging your
|
||
application, but results in performance loss.
|
||
|
||
@item @code{--enable-wam-profile=yes} allows profiling of abstract machine
|
||
instructions. This is useful when developing YAP, should not be so
|
||
useful for normal users.
|
||
|
||
@item @code{--enable-tabling=@{local,batched@}} allows one of the two
|
||
forms of tabling. This option is still experimental.
|
||
|
||
@item @code{--enable-parallelism=@{env-copy,sba,a-cow@}} allows
|
||
or-parallelism supported by one of these three forms. This option is
|
||
still highly experimental.
|
||
|
||
@item @code{--with-gmp[=DIR]} give a path to where one can find the
|
||
@code{GMP} library if not installed in the default path.
|
||
|
||
@end itemize
|
||
|
||
Next follow machine dependent details:
|
||
|
||
@node Machine Options, , Configuration Options,Install
|
||
@section Tuning YAP for a Particular Machine and Compiler
|
||
@cindex machine optimizations
|
||
|
||
The default options should give you best performance under
|
||
@code{GCC}. Although the system is tuned for this compiler
|
||
we have been able to compile versions of Yap under lcc in Linux,
|
||
Sun's cc compiler, IBM's xlc, SGI's cc, and Microsoft's Visual C++
|
||
6.0.
|
||
|
||
@menu
|
||
* Tuning for GCC:: Using the GNUCC ncompiler
|
||
* Compiling Under Visual C++:: Using Microsoft's Visual C++ environment
|
||
* Tuning for SGI cc:: Compiling Under SGI's @code{cc}
|
||
@end menu
|
||
|
||
|
||
@node Tuning for GCC, Compiling Under Visual C++, , Machine Options
|
||
@section Tuning YAP for @code{GCC}.
|
||
|
||
Yap has been developed to take advantage of @code{GCC} (but not to
|
||
depend on it). The major advantage of @code{GCC} is threaded code and
|
||
explicit register reservation.
|
||
|
||
YAP is set by default to compile with the best compilation flags we
|
||
know. Even so, a few specific options reduce portability. The option
|
||
@itemize @bullet
|
||
@item @code{--enable-max-performance=yes} will try to support the best
|
||
available flags for a specific architecural model. Currently, the option
|
||
assumes a recent version of @code{GCC}.
|
||
@item @code{--enable-debug-yap} compiles Yap so that it can be debugged
|
||
by tools such as @code{dbx} or @code{gdb}.
|
||
@end itemize
|
||
|
||
Here follow a few hints:
|
||
|
||
On x86 machines the flags:
|
||
|
||
@example
|
||
YAP_EXTRAS= ... -DBP_FREE=1
|
||
@end example
|
||
|
||
tells us to use the @code{%bp} register (frame-pointer) as the emulator's
|
||
program counter. This seems to be stable and is now default.
|
||
|
||
On Sparc/Solaris2 use:
|
||
|
||
@example
|
||
YAP_EXTRAS= ... -mno-app-regs -DOPTIMISE_ALL_REGS_FOR_SPARC=1
|
||
@end example
|
||
|
||
and YAP will get two extra registers! This trick does not work on
|
||
SunOS 4 machines.
|
||
|
||
Note that versions of GCC can be tweaked to recognise different
|
||
processors within the same instruction set, eg, 486, Pentium, and
|
||
PentiumPro for the x86; or Ultrasparc, and Supersparc for
|
||
Sparc. Unfortunately, some of these tweaks do may make Yap run slower or
|
||
not at all in other machines with the same instruction set, so they
|
||
cannot be made default.
|
||
|
||
Last, the best options also depends on the version of GCC you are using, and
|
||
it is a good idea to consult the GCC manual under the menus "Invoking
|
||
GCC"/"Submodel Options". Specifically, you should check
|
||
@code{-march=XXX} for recent versions of GCC/EGCS. In the case of
|
||
@code{GCC2.7} and other recent versions of @code{GCC} you can check:
|
||
|
||
@table @code
|
||
|
||
@item 486:
|
||
In order to take advantage of 486 specific optimisations in GCC 2.7.*:
|
||
|
||
@example
|
||
YAP_EXTRAS= ... -m486 -DBP_FREE=1
|
||
@end example
|
||
|
||
@item Pentium:
|
||
@example
|
||
YAP_EXTRAS= ... -m486 -malign-loops=2 -malign-jumps=2 \
|
||
-malign-functions=2
|
||
@end example
|
||
|
||
@item PentiumPro and other recent Intel and AMD machines:
|
||
PentiumPros are known not to require alignment. Check your version of
|
||
@code{GCC} for the best @code{-march} option.
|
||
|
||
@item Super and UltraSparcs:
|
||
@example
|
||
YAP_EXTRAS= ... -msupersparc
|
||
@end example
|
||
|
||
@item MIPS: if have a recent machine and you need a 64 bit wide address
|
||
space you can use the abi 64 bits or eabi option, as in:
|
||
@example
|
||
CC="gcc -mabi=64" ./configure --...
|
||
@end example
|
||
Be careful. At least for some versions of @code{GCC}, compiling with
|
||
@code{-g} seems to result in broken code.
|
||
|
||
@item WIN32: The cygwin environment is our suggested approach. The
|
||
CygWin environment is available from the URL:
|
||
|
||
|
||
@code{http://sourceware.cygnus.com}
|
||
|
||
@noindent
|
||
and mirrors. Yap should compile under cygwin 20.1 but we suggest using
|
||
the newer 1.1.1 (April Release), which has a more complete
|
||
implementation of the WIN32 API and uses GCC2.95.2 instead of egcs. The
|
||
compilation steps under the cygwin shell are as follows:
|
||
|
||
@example
|
||
mkdir cyg
|
||
$YAPSRC/configure --enable-coroutining \\
|
||
--enable-max-performance
|
||
make
|
||
make install
|
||
@end example
|
||
|
||
By default, Yap will use the @code{-mno-cygwin} option to disable the
|
||
use of the cygwin dll and to enables the mingw32 subsystem. Yap does not
|
||
need the cygwin dll. It instead accesses the system's @code{CRTDLL.DLL}
|
||
@code{C} run time library supplied with Win32 platforms through the
|
||
mingw32 interface.
|
||
|
||
You should check the default installation path which is set to
|
||
@code{/PROGRA~1/Yap} in the standard Makefile. This string will usually
|
||
be expanded into @code{c:\Program Files\Yap} by Windows.
|
||
|
||
The cygwin environment does not provide @t{gm}. You can fecth a dll for
|
||
the @t{gmp} library from @url{http://www.sf.net/projects/mingwrep}.
|
||
@end table
|
||
|
||
@node Compiling Under Visual C++, Tuning for SGI cc, Tuning for GCC, Machine Options
|
||
@subsection Compiling Under Visual C++
|
||
|
||
Yap compiles cleanly under Microsoft's Visual C++ release 6.0. We next
|
||
give a step-by-step tutorial on how to compile Yap manually using this
|
||
environment.
|
||
|
||
First, it is a good idea to build Yap as a DLL:
|
||
|
||
@enumerate
|
||
|
||
@item create a project named yapdll using File.New. The project will be a
|
||
DLL project, initially empty.
|
||
|
||
Notice that either the project is named yapdll or you must replace the
|
||
preprocessor's variable @var{YAPDLL_EXPORTS} to match your project names
|
||
in the files @code{c_interface.h} and @code{c_interface.c}.
|
||
|
||
@item add all .c files in the @var{$YAPSRC/C} directory and in the
|
||
@var{$YAPSRC\OPTYap} directory to the Project's @code{Source Files} (use
|
||
FileView).
|
||
|
||
@item add all .h files in the @var{$YAPSRC/H} directory,
|
||
@var{$YAPSRC\include} directory and in the @var{$YAPSRC\OPTYap}
|
||
subdirectory to the Project's @code{Header Files}.
|
||
|
||
@item Ideally, you should now use @code{m4} to generate extra .h from .m4 files and use
|
||
@code{configure} to create a @code{config.h}. Or, you can be lazy, and
|
||
fetch these files from @var{$YAPSRC\VC\include}.
|
||
|
||
@item You may want to go to @code{Build.Set Active Configuration} and set @code{Project
|
||
Type} to @code{Release}
|
||
|
||
@item To use Yap's own include directories you have to set the Project
|
||
option @code{Project.Project Settings.C/C++.Preprocessor.Additional
|
||
Include Directories} to include the directories @var{$YAPSRC\H},
|
||
@var{$YAPSRC\VC\include}, @var{$YAPSRC\OPTYap} and
|
||
@var{$YAPSRC\include}. The syntax is:
|
||
|
||
@example
|
||
$YAPSRC\H, $YAPSRC\VC\include, $YAPSRC\OPTYap, $YAPSRC\include
|
||
@end example
|
||
|
||
@item Build: the system should generate an @code{yapdll.dll} and an @code{yapdll.lib}.
|
||
|
||
@item Copy the file @code{yapdll.dll} to your path. The file
|
||
@code{yapdll.lib} should also be copied to a location where the linker can find it.
|
||
@end enumerate
|
||
|
||
Now you are ready to create a console interface for Yap:
|
||
@enumerate
|
||
@item create a second project say @code{wyap} with @code{File.New}. The project will be a
|
||
WIN32 console project, initially empty.
|
||
|
||
@item add @var{$YAPSRC\console\yap.c} to the @code{Source Files}.
|
||
|
||
@item add @var{$YAPSRC\VC\include\config.h} and the files in @var{$YAPSRC\include} to
|
||
the @code{Header Files}.
|
||
|
||
@item You may want to go to @code{Build.Set Active Configuration} and set
|
||
@code{Project Type} to @code{Release}.
|
||
|
||
@item you will eventually need to bootstrap the system by booting from
|
||
@code{boot.yap}, so write:
|
||
|
||
@example
|
||
-b $YAPSRC\pl\boot.yap
|
||
@end example
|
||
|
||
in @code{Project.Project Settings.Debug.Program Arguments}.
|
||
|
||
@item You need the sockets and yap libraries. Add
|
||
|
||
@example
|
||
ws2_32.lib yapdll.lib to
|
||
@end example
|
||
|
||
to
|
||
|
||
to @code{Project.Project Settings.Link.Object/Library Modules}
|
||
|
||
You may also need to set the @code{Link Path} so that VC++ will find @code{yapdll.lib}.
|
||
|
||
@item set @code{Project.Project Settings.C/C++.Preprocessor.Additional
|
||
Include Directories} to include the @var{$YAPSRC/VC/include} and
|
||
@var{$YAPSRC/include}.
|
||
|
||
The syntax is:
|
||
|
||
@example
|
||
$YAPSRC\VC\include, $YAPSRC\include
|
||
@end example
|
||
|
||
@item Build the system.
|
||
|
||
@item Use @code{Build.Start Debug} to boot the system, and then create the saved state with
|
||
|
||
@example
|
||
['$YAPSRC\\pl\\init'].
|
||
save_program(startup).
|
||
^Z
|
||
@end example
|
||
|
||
That's it, you've got Yap and the saved state!
|
||
@end enumerate
|
||
|
||
The $YAPSRC\VC directory has the make files to build Yap4.3.17 under VC++ 6.0.
|
||
|
||
@node Tuning for SGI cc, , Compiling Under Visual C++ ,Machine Options
|
||
@subsection Compiling Under SGI's cc
|
||
|
||
YAP should compile under the Silicon Graphic's @code{cc} compiler,
|
||
although we advise using the GNUCC compiler, if available.
|
||
|
||
@table @code
|
||
@item 64 bit
|
||
Support for 64 bits should work by using (under Bourne shell syntax):
|
||
@example
|
||
CC="cc -64" $YAP_SRC_PATH/configure --...
|
||
@end example
|
||
@end table
|
||
@node Run, Syntax, Install, Top
|
||
@chapter Running YAP
|
||
|
||
@menu
|
||
* Interactive Mode:: Running Yap Interactively
|
||
* Script Mode:: Running Prolog files as scripts
|
||
@end menu
|
||
|
||
@cindex booting
|
||
We next describe how to invoke Yap in Unix systems.
|
||
|
||
@section Running Yap Interactively
|
||
@node Interactive Mode, Script Mode, ,Run
|
||
|
||
Most often you will want to use Yap in interactive mode. Assuming that
|
||
YAP is in the user's search path, the top-level can be invoked under
|
||
Unix with the following command:
|
||
|
||
@example
|
||
yap [-s n] [-h n] [-a n] [-c IP_HOST port ] [filename]
|
||
@end example
|
||
|
||
@noindent
|
||
All the arguments and flags are optional and have the following meaning:
|
||
@table @code
|
||
@item -?
|
||
print a short error message.
|
||
@item -s @var{n}
|
||
allocate @var{n} K bytes for local and global stacks
|
||
@item -h @var{n}
|
||
allocate @var{n} K bytes for heap and auxiliary stacks
|
||
@item -t @var{n}
|
||
allocate @var{n} K bytes for the trail stack
|
||
@item -l @var{YAP_FILE}
|
||
compile the Prolog file @var{YAP_FILE} before entering the top-level.
|
||
@item -L @var{YAP_FILE}
|
||
compile the Prolog file @var{YAP_FILE} and then halt. This option is
|
||
useful for implementing scripts.
|
||
@item -b @var{BOOT_FILE}
|
||
boot code is in Prolog file @var{BOOT_FILE}. The filename must define
|
||
the predicate '$live'/0.
|
||
@item -c @t{IP_HOST} @t{port}
|
||
connect standard streams to host @t{IP_HOST} at port @t{port}
|
||
@item filename
|
||
restore state saved in the given file
|
||
@item --
|
||
separator for arguments to Prolog code. These arguments are visible
|
||
through the unix/1 built-in.
|
||
@end table
|
||
|
||
Note that YAP will output an error message on the following conditions:
|
||
|
||
@itemize @bullet
|
||
@item
|
||
a file name was given but the file does not exist or is not a saved
|
||
YAP state;
|
||
@item
|
||
the necessary amount of memory could not be allocated;
|
||
@item
|
||
the allocated memory is not enough to restore the state.
|
||
@end itemize
|
||
|
||
When restoring a saved state, YAP will allocate the
|
||
same amount of memory as that in use when the state was saved, unless a
|
||
different amount is specified by flags in the command line. By default,
|
||
YAP restores the file @samp{startup} from the current directory or from
|
||
the YAP library.
|
||
@cindex environment variables
|
||
|
||
@findex YAPBINDIR
|
||
YAP can boot from a saved state. The saved state will use the default
|
||
installation directory to search for the YAP binary unless you define
|
||
the environment variable YAPBINDIR.
|
||
|
||
@findex YAPLIBDIR
|
||
YAP always tries to find saved states from the current directory
|
||
first. If it cannot it will use the environment variable YAPLIBDIR, if
|
||
defined, or search the default library directory.
|
||
|
||
@section Running Yap as a script
|
||
@node Script Mode, ,Interactive Mode, Run
|
||
|
||
YAP can also be used to run Prolog files as scripts, at least in
|
||
Unix-like environments. A simple example is shown next:
|
||
|
||
@example
|
||
@cartouche
|
||
#!/usr/local/bin/yap -L
|
||
#
|
||
# Hello World script file using Yap
|
||
#
|
||
|
||
:- write('Hello World'), nl.
|
||
|
||
@end cartouche
|
||
@end example
|
||
|
||
The @code{#!} characters specify that the script should call the binary
|
||
file Yap. Notice that many systems will require the complete path to the
|
||
Yap binary. The @code{-L} flag indicates that YAP should consult the
|
||
current file when booting and then halt. The remaining arguments are
|
||
then passed to YAP. Note that YAP will skip the first lines if they
|
||
start with @code{#} (the comment sign for Unix's shell). YAP will
|
||
consult the file and execute any commands.
|
||
|
||
A slightly more sophisticated example is:
|
||
|
||
@example
|
||
@cartouche
|
||
#!/usr/bin/yap -L
|
||
#
|
||
# Hello World script file using Yap
|
||
#
|
||
|
||
:- initialization(main).
|
||
|
||
main :- write('Hello World'), nl.
|
||
|
||
@end cartouche
|
||
@end example
|
||
|
||
The @code{initialization} directive tells Yap to execute the goal main
|
||
after consulting the file. Source code is thus compiled and @code{main}
|
||
executed at the end.
|
||
|
||
By default, arguments to a script are considered arguments to YAP. As an
|
||
example, consider the following script @code{dump_args}:
|
||
|
||
@example
|
||
@cartouche
|
||
#!/usr/bin/yap -L
|
||
|
||
main( [] ).
|
||
main( [H|T] ) :-
|
||
write( H ), nl,
|
||
main( T ).
|
||
|
||
:- unix( argv(AllArgs) ), main( AllArgs ).
|
||
|
||
@end cartouche
|
||
@end example
|
||
|
||
If you this run this script with the arguments:
|
||
@example
|
||
./dump_args -s 10000
|
||
@end example
|
||
@noindent
|
||
the script will start an YAP process with stack size @code{10MB}, and
|
||
the list of arguments to the process will be empty.
|
||
|
||
Often one wants to run the script as any other program, and for this it
|
||
is convenient to ignore arguments to YAP. This is possible by using
|
||
@code{L --} as in the next version of @code{dump_args}:
|
||
|
||
@example
|
||
@cartouche
|
||
#!/usr/bin/yap -L --
|
||
|
||
main( [] ).
|
||
main( [H|T] ) :-
|
||
write( H ), nl,
|
||
main( T ).
|
||
|
||
:- unix( argv(AllArgs) ), main( AllArgs ).
|
||
|
||
@end cartouche
|
||
@end example
|
||
|
||
The @code{--} indicates the next arguments are not for YAP. Instead,
|
||
they must be sent directly to the @code{argv} builtin. Hence, running
|
||
@example
|
||
./dump_args test
|
||
@end example
|
||
@noindent
|
||
will write @code{test} on the standard output.
|
||
|
||
|
||
@node Syntax, Loading Programs, Run, Top
|
||
@chapter Syntax
|
||
|
||
We will describe the syntax of YAP at two levels. We first will
|
||
describe the syntax for Prolog terms. In a second level we describe
|
||
the @i{tokens} from which Prolog @i{terms} are
|
||
built.
|
||
|
||
@menu
|
||
* Formal Syntax:: Syntax of terms
|
||
* Tokens:: Syntax of Prolog tokens
|
||
@end menu
|
||
|
||
@node Formal Syntax, Tokens, ,Syntax
|
||
@section Syntax of Terms
|
||
@cindex syntax
|
||
|
||
Below, we describe the syntax of YAP terms from the different
|
||
classes of tokens defined above. The formalism used will be @emph{BNF},
|
||
extended where necessary with attributes denoting integer precedence or
|
||
operator type.
|
||
|
||
@example
|
||
|
||
@code{
|
||
term ----> subterm(1200) end_of_term_marker
|
||
|
||
subterm(N) ----> term(M) [M <= N]
|
||
|
||
term(N) ----> op(N, fx) subterm(N-1)
|
||
| op(N, fy) subterm(N)
|
||
| subterm(N-1) op(N, xfx) subterm(N-1)
|
||
| subterm(N-1) op(N, xfy) subterm(N)
|
||
| subterm(N) op(N, yfx) subterm(N-1)
|
||
| subterm(N-1) op(N, xf)
|
||
| subterm(N) op(N, yf)
|
||
|
||
term(0) ----> atom '(' arguments ')'
|
||
| '(' subterm(1200) ')'
|
||
| '@{' subterm(1200) '@}'
|
||
| list
|
||
| string
|
||
| number
|
||
| atom
|
||
| variable
|
||
|
||
arguments ----> subterm(999)
|
||
| subterm(999) ',' arguments
|
||
|
||
list ----> '[]'
|
||
| '[' list_expr ']'
|
||
|
||
list_expr ----> subterm(999)
|
||
| subterm(999) list_tail
|
||
|
||
list_tail ----> ',' list_expr
|
||
| ',..' subterm(999)
|
||
| '|' subterm(999)
|
||
}
|
||
@end example
|
||
|
||
@noindent
|
||
Notes:
|
||
|
||
@itemize @bullet
|
||
|
||
@item
|
||
@i{op(N,T)} denotes an atom which has been previously declared with type
|
||
@i{T} and base precedence @i{N}.
|
||
|
||
@item
|
||
Since ',' is itself a pre-declared operator with type @i{xfy} and
|
||
precedence 1000, is @i{subterm} starts with a '(', @i{op} must be
|
||
followed by a space to avoid ambiguity with the case of a functor
|
||
followed by arguments, eg:
|
||
|
||
@example
|
||
@code{ + (a,b) [the same as '+'(','(a,b)) of arity one]}
|
||
@end example
|
||
versus
|
||
@example
|
||
@code{ +(a,b) [the same as '+'(a,b) of arity two]}
|
||
@end example
|
||
|
||
@item
|
||
In the first rule for term(0) no blank space should exist between
|
||
@i{atom} and '('.
|
||
|
||
@item
|
||
@cindex end of term
|
||
Each term to be read by the YAP parser must end with a single
|
||
dot, followed by a blank (in the sense mentioned in the previous
|
||
paragraph). When a name consisting of a single dot could be taken for
|
||
the end of term marker, the ambiguity should be avoided by surrounding the
|
||
dot with single quotes.
|
||
|
||
@end itemize
|
||
|
||
@node Tokens, , Formal Syntax, Syntax
|
||
@section Prolog Tokens
|
||
@cindex token
|
||
|
||
Prolog tokens are grouped into the following categories:
|
||
|
||
@menu
|
||
* Numbers:: Integer and Floating-Point Numbers
|
||
* Strings:: Sequences of Characters
|
||
* Atoms:: Atomic Constants
|
||
* Variables:: Logical Variables
|
||
* Punctuation Tokens:: Tokens that separate other tokens
|
||
* Layout:: Comments and Other Layout Rules
|
||
@end menu
|
||
|
||
@node Numbers, Strings, ,Tokens
|
||
@subsection Numbers
|
||
@cindex number
|
||
|
||
Numbers can be further subdivided into integer and floating-point numbers.
|
||
|
||
@menu
|
||
* Integers:: How Integers are read and represented
|
||
* Floats:: Floating Point Numbers
|
||
@end menu
|
||
|
||
@node Integers, Floats, ,Numbers
|
||
@subsubsection Integers
|
||
@cindex integer
|
||
|
||
Integer numbers
|
||
are described by the following regular expression:
|
||
|
||
@example
|
||
@code{
|
||
<integer> := @{<digit>+<single-quote>|0@{xXo@}@}<alpha_numeric_char>+
|
||
}
|
||
@end example
|
||
@noindent
|
||
where @{...@} stands for optionality, @i{+} optional repetition (one or
|
||
more times), @i{<digit>} denotes one of the characters 0 ... 9, @i{|}
|
||
denotes or, and @i{<single-quote>} denotes the character "'". The digits
|
||
before the @i{<single-quote>} character, when present, form the number
|
||
basis, that can go from 0, 1 and up to 36. Letters from @code{A} to
|
||
@code{Z} are used when the basis is larger than 10.
|
||
|
||
Note that if no basis is specified then base 10 is assumed. Note also
|
||
that the last digit of an integer token can not be immediately followed
|
||
by one of the characters 'e', 'E', or '.'.
|
||
|
||
Following the ISO standard, YAP also accepts directives of the
|
||
form @code{0x} to represent numbers in hexadecimal base and of the form
|
||
@code{0o} to represent numbers in octal base. For usefulness,
|
||
YAP also accepts directives of the form @code{0X} to represent
|
||
numbers in hexadecimal base.
|
||
|
||
Example:
|
||
the following tokens all denote the same integer
|
||
@example
|
||
@code{10 2'1010 3'101 8'12 16'a 36'a 0xa 0o12}
|
||
@end example
|
||
|
||
Numbers of the form @code{0'a} are used to represent character
|
||
constants. So, the following tokens denote the same integer:
|
||
@example
|
||
@code{0'd 100}
|
||
@end example
|
||
|
||
YAP (version @value{VERSION}) supports integers that can fit
|
||
the word size of the machine. This is 32 bits in most current machines,
|
||
but 64 in some others, such as the Alpha running Linux or Digital
|
||
Unix. The scanner will read larger or smaller integers erroneously.
|
||
|
||
@node Floats, , Integers,Numbers
|
||
@subsubsection Floating-point Numbers
|
||
@cindex floating-point number
|
||
|
||
Floating-point numbers are described by:
|
||
|
||
@example
|
||
@code{
|
||
<float> := <digit>+@{<dot><digit>+@}
|
||
<exponent-marker>@{<sign>@}<digit>+
|
||
|<digit>+<dot><digit>+
|
||
@{<exponent-marker>@{<sign>@}<digit>+@}
|
||
}
|
||
@end example
|
||
|
||
@noindent
|
||
where @i{<dot>} denotes the decimal-point character '.',
|
||
@i{<exponent-marker>} denotes one of 'e' or 'E', and @i{<sign>} denotes
|
||
one of '+' or '-'.
|
||
|
||
Examples:
|
||
@example
|
||
@code{10.0 10e3 10e-3 3.1415e+3}
|
||
@end example
|
||
|
||
Floating-point numbers are represented as a double in the target
|
||
machine. This is usually a 64-bit number.
|
||
|
||
@node Strings, Atoms, Numbers,Tokens
|
||
@subsection Character Strings
|
||
@cindex string
|
||
|
||
Strings are described by the following rules:
|
||
@example
|
||
string --> '"' string_quoted_characters '"'
|
||
|
||
string_quoted_characters --> '"' '"' string_quoted_characters
|
||
string_quoted_characters --> '\'
|
||
escape_sequence string_quoted_characters
|
||
string_quoted_characters -->
|
||
string_character string_quoted_characters
|
||
|
||
escape_sequence --> 'a' | 'b' | 'r' | 'f' | 't' | 'n' | 'v'
|
||
escape_sequence --> '\' | '"' | ''' | '`'
|
||
escape_sequence --> at_most_3_octal_digit_seq_char '\'
|
||
escape_sequence --> 'x' at_most_2_hexa_digit_seq_char '\'
|
||
@end example
|
||
where @code{string_character} in any character except the double quote
|
||
and escape characters.
|
||
|
||
Examples:
|
||
@example
|
||
@code{"" "a string" "a double-quote:""" }
|
||
@end example
|
||
|
||
The first string is an empty string, the last string shows the use of
|
||
double-quoting. The implementation of YAP represents strings as
|
||
lists of integers. Since Yap4.3.0 there is no static limit on string
|
||
size.
|
||
|
||
Escape sequences can be used to include the non-printable characters
|
||
@code{a} (alert), @code{b} (backspace), @code{r} (carriage return),
|
||
@code{f} (form feed), @code{t} (horizontal tabulation), @code{n} (new
|
||
line), and @code{v} (vertical tabulation). Escape sequences also be
|
||
include the meta-characters @code{\}, @code{"}, @code{'}, and
|
||
@code{`}. Last, one can use escape sequences to include the characters
|
||
either as an octal or hexadecimal number.
|
||
|
||
The next examples demonstrates the use of escape sequences in YAP:
|
||
|
||
@example
|
||
@code{"\x0c\" "\01\" "\f" "\\" }
|
||
@end example
|
||
|
||
The first three examples return a list including only character 12 (form
|
||
feed). The last example escapes the escape character.
|
||
|
||
Escape sequences were not available in C-Prolog and in origional
|
||
versions of YAP up to 4.2.0. Escape sequences can be disable by using:
|
||
@example
|
||
@code{:- yap_flag(character_escapes,off).}
|
||
@end example
|
||
|
||
|
||
@node Atoms, Variables, Strings, Tokens
|
||
@subsection Atoms
|
||
@cindex atom
|
||
|
||
Atoms are defined by one of the following rules:
|
||
@example
|
||
atom --> solo-character
|
||
atom --> lower-case-letter name-character*
|
||
atom --> symbol-character+
|
||
atom --> single-quote single-quote
|
||
atom --> ''' atom_quoted_characters '''
|
||
|
||
|
||
atom_quoted_characters --> ''' ''' atom_quoted_characters
|
||
atom_quoted_characters --> '\' atom_sequence string_quoted_characters
|
||
atom_quoted_characters --> character string_quoted_characters
|
||
|
||
@end example
|
||
|
||
where:
|
||
@example
|
||
<solo-character> denotes one of: ! ;
|
||
<symbol-character> denotes one of: # & * + - . / : <
|
||
= > ? @@ \ ^ ` ~
|
||
<lower-case-letter> denotes one of: a...z
|
||
<name-character> denotes one of: _ a...z A...Z 0....9
|
||
<single-quote> denotes: '
|
||
@end example
|
||
|
||
and @code{string_character} denotes any character except the double quote
|
||
and escape characters. Note that escape sequences in strings and atoms
|
||
follow the same rules.
|
||
|
||
Examples:
|
||
@example
|
||
@code{a a12x '$a' ! => '1 2'}
|
||
@end example
|
||
|
||
@c From version @code{4.1.8} onwards YAP supports the 8-bit
|
||
@c ISO-latin-1 character set. The following new symbol characters have
|
||
@c been introduced: @code{<EFBFBD>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>. <20>, <20>, <20>, <20>, <20>,
|
||
@c <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>}. The following new
|
||
@c lower-case-characters have been introduced: @code{<EFBFBD>, <20>, <20>, <20>, <20>, <20>, <20>,
|
||
@c <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>,
|
||
@c <20>, <20>, <20>, <20>, <20>, <20>, <20>}. Last, the following upper-case characters have been
|
||
@c introduced: @code{<EFBFBD>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>,
|
||
@c <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>, <20>}.
|
||
|
||
Version @code{4.2.0} of YAP removed the previous limit of 256
|
||
characters on an atom. Size of an atom is now only limited by the space
|
||
available in the system.
|
||
|
||
@node Variables, Punctuation Tokens, Atoms, Tokens
|
||
@subsection Variables
|
||
@cindex variable
|
||
|
||
Variables are described by:
|
||
@example
|
||
<variable-starter><variable-character>+
|
||
@end example
|
||
where
|
||
@example
|
||
<variable-starter> denotes one of: _ A...Z
|
||
<variable-character> denotes one of: _ a...z A...Z
|
||
@end example
|
||
|
||
@cindex anonymous variable
|
||
If a variable is referred only once in a term, it needs not to be named
|
||
and one can use the character @code{_} to represent the variable. These
|
||
variables are known as anonymous variables. Note that different
|
||
occurrences of @code{_} on the same term represent @emph{different}
|
||
anonymous variables.
|
||
|
||
@node Punctuation Tokens, Layout, Variables, Tokens
|
||
@subsection Punctuation Tokens
|
||
@cindex punctuation token
|
||
|
||
Punctuation tokens consist of one of the following characters:
|
||
@example
|
||
@center ( ) , [ ] @{ @} |
|
||
@end example
|
||
|
||
These characters are used to group terms.
|
||
|
||
@node Layout, ,Punctuation Tokens, Tokens
|
||
@subsection Layout
|
||
@cindex comment
|
||
Any characters with ASCII code less than or equal to 32 appearing before
|
||
a token are ignored.
|
||
|
||
All the text appearing in a line after the character @i{%} is taken to
|
||
be a comment and ignored (including @i{%}). Comments can also be
|
||
inserted by using the sequence @code{/*} to start the comment and
|
||
@code{*/} to finish it. In the presence of any sequence of comments or
|
||
layout characters, the YAP parser behaves as if it had found a
|
||
single blank character. The end of a file also counts as a blank
|
||
character for this purpose.
|
||
|
||
@node Loading Programs, Modules, Syntax, Top
|
||
@chapter Loading Programs
|
||
|
||
@menu
|
||
|
||
Loading Programs
|
||
* Compiling:: Program Loading and Updating
|
||
* Setting the Compiler:: Changing the compiler's parameters
|
||
* Saving:: Saving and Restoring Programs
|
||
|
||
@end menu
|
||
|
||
|
||
@node Compiling, Setting the Compiler, , Loading Programs
|
||
@section Program loading and updating
|
||
|
||
@table @code
|
||
|
||
@item consult(@var{+F})
|
||
@findex consult/1
|
||
@snindex consult/1
|
||
@cyindex consult/1
|
||
Adds the clauses written in file @var{F} or in the list of files @var{F}
|
||
to the program.
|
||
|
||
In YAP @code{consult/1} does not remove previous clauses for
|
||
the procedures defined in @var{F}. Moreover, note that all code in YAP
|
||
is compiled.
|
||
|
||
@item reconsult(@var{+F})
|
||
@findex reconsult/1
|
||
@snindex reconsult/1
|
||
@cyindex reconsult/1
|
||
Updates the program replacing the
|
||
previous definitions for the predicates defined in @var{F}.
|
||
|
||
|
||
@item [@var{+F}]
|
||
@findex []/1
|
||
@saindex []/1
|
||
@cyindex []/1
|
||
The same as @code{consult(F)}.
|
||
|
||
@item [-@var{+F}]
|
||
@findex [-]/1
|
||
@saindex [-]/1
|
||
@cyindex [-]/1
|
||
The same as @code{reconsult(F)}
|
||
|
||
Example:
|
||
|
||
@example
|
||
?- [file1, -file2, -file3, file4].
|
||
@end example
|
||
@noindent
|
||
will consult @code{file1} @code{file4} and reconsult @code{file2} and
|
||
@code{file3}.
|
||
|
||
@item compile(@var{+F})
|
||
@findex compile/1
|
||
@syindex compile/1
|
||
@cnindex compile/1
|
||
@noindent
|
||
In YAP, the same as @code{reconsult/1}.
|
||
|
||
@item ensure_loaded(@var{+F}) [ISO]
|
||
@findex ensure_loaded/1
|
||
@syindex compile/1
|
||
@cnindex compile/1
|
||
When the files specified by @var{F} are module files,
|
||
@code{ensure_loaded/1} loads them if they have note been previously
|
||
loaded, otherwise advertises the user about the existing name clashes
|
||
and prompts about importing or not those predicates. Predicates which
|
||
are not public remain invisible.
|
||
|
||
When the files are not module files, @code{ensure_loaded/1} loads them
|
||
if they have not been loaded before, does nothing otherwise.
|
||
|
||
@var{F} must be a list containing the names of the files to load.
|
||
|
||
@item include(@var{+F}) [ISO]
|
||
@findex include/1 (directive)
|
||
@snindex compile/1 (directive)
|
||
@cnindex compile/1 (directive)
|
||
The @code{include} directive includes the text files or sequence of text
|
||
files specified by @var{F} into the file being currently consulted.
|
||
|
||
@end table
|
||
|
||
@node Setting the Compiler, Saving, Compiling, Loading Programs
|
||
@section Changing the Compiler's Behaviour
|
||
|
||
This section presents a set of built-ins predicates designed to set the
|
||
environment for the compiler.
|
||
|
||
@table @code
|
||
|
||
@item source_mode(-@var{O},+@var{N})
|
||
@findex source_mode/2
|
||
@snindex source_mode/2
|
||
@cnindex source_mode/2
|
||
The state of source mode can either be on or off. When the source mode
|
||
is on, all clauses are kept both as compiled code and in a "hidden"
|
||
database. @var{O} is unified with the previous state and the mode is set
|
||
according to @var{N}.
|
||
|
||
@item source
|
||
@findex source/0
|
||
@snindex source/0
|
||
@cnindex source/0
|
||
After executing this goal, YAP keeps information on the source
|
||
of the predicates that will be consulted. This enables the use of
|
||
@code{listing/0}, @code{listing/1} and @code{clause/2} for those
|
||
clauses.
|
||
|
||
The same as @code{source_mode(_,on)} or as declaring all newly defined
|
||
static procedures as @code{public}.
|
||
|
||
@item no_source
|
||
@findex no_source/0
|
||
@snindex no_source/0
|
||
@cnindex no_source/0
|
||
The opposite to @code{source}.
|
||
|
||
The same as @code{source_mode(_,off)}.
|
||
|
||
@item compile_expressions
|
||
@findex compile_expressions/0
|
||
@snindex compile_expressions/0
|
||
@cnindex compile_expressions/0
|
||
After a call to this predicate, arithmetical expressions will be compiled.
|
||
(see example below). This is the default behaviour.
|
||
|
||
@item do_not_compile_expressions
|
||
@findex do_not_compile_expressions/0
|
||
@snindex do_not_compile_expressions/0
|
||
@cnindex do_not_compile_expressions/0
|
||
After a call to this predicate, arithmetical expressions will not be compiled.
|
||
@example
|
||
?- source, do_not_compile_expressions.
|
||
yes
|
||
?- [user].
|
||
| p(X) :- X is 2 * (3 + 8).
|
||
| :- end_of_file.
|
||
?- compile_expressions.
|
||
yes
|
||
?- [user].
|
||
| q(X) :- X is 2 * (3 + 8).
|
||
| :- end_of_file.
|
||
:- listing.
|
||
|
||
p(A):-
|
||
A is 2 * (3 + 8).
|
||
|
||
q(A):-
|
||
A is 22.
|
||
@end example
|
||
|
||
@item expand_exprs(-@var{O},+@var{N})
|
||
@findex expand_exprs/2
|
||
@snindex expand_exprs/2
|
||
@cyindex expand_exprs/2
|
||
Puts YAP in state @var{N} (@code{on} or @code{off}) and unify
|
||
@var{O} with the previous state, where @var{On} is equivalent to
|
||
@code{compile_expressions} and @code{off} is equivalent to
|
||
@code{do_not_compile_expressions}. This predicate was kept to maintain
|
||
compatibility with C-Prolog.
|
||
|
||
@item path(-@var{D})
|
||
@findex path/1
|
||
@snindex path/1
|
||
@cnindex path/1
|
||
Unifies @var{D} with the current directory search-path of YAP.
|
||
Note that this search-path is only used by YAP to find the
|
||
files for @code{consult/1}, @code{reconsult/1} and @code{restore/1} and
|
||
should not be taken for the system search path.
|
||
|
||
@item add_to_path(+@var{D})
|
||
@findex add_to_path/1
|
||
@snindex path/1
|
||
@cnindex path/1
|
||
Adds @var{D} to the end of YAP's directory search path.
|
||
|
||
@item add_to_path(+@var{D},+@var{N})
|
||
@findex add_to_path/2
|
||
@snindex path/1
|
||
@cnindex path/1
|
||
Inserts @var{D} in thgoe position, of the directory search path of
|
||
YAP, specified by @var{N}. @var{N} must be either of
|
||
@code{first} or @code{last}.
|
||
|
||
@item remove_from_path(+@var{D})
|
||
@findex remove_from_path/1
|
||
@snindex remove_from_path/1
|
||
@cnindex remove_from_path/1
|
||
Remove @var{D} from YAP's directory search path.
|
||
|
||
@item style_check(+@var{X})
|
||
@findex style_check/1
|
||
@snindex style_check/1
|
||
@cnindex style_check/1
|
||
Turns on style checking according to the attribute specified by @var{X},
|
||
which must be one of the following:
|
||
@table @code
|
||
@item single_var
|
||
Checks single occurrences of named variables in a clause.
|
||
@item discontiguous
|
||
Checks non-contiguous clauses for the same predicate in a file.
|
||
@item multiple
|
||
Checks the presence of clauses for the same predicate in more than one
|
||
file when the predicate has not been declared as @code{multifile}
|
||
@item all
|
||
Performs style checking for all the cases mentioned above.
|
||
@end table
|
||
By default, style checking is disabled in YAP unless we are in
|
||
@code{sicstus} or @code{iso} language mode.
|
||
|
||
The @code{style_check/1} built-in is now deprecated. Please use the
|
||
@code{set_prolog_flag/1} instead.
|
||
|
||
@item no_style_check(+@var{X})
|
||
@findex no_style_check/1
|
||
@snindex style_check/1
|
||
@cnindex style_check/1
|
||
Turns off style checking according to the attribute specified by
|
||
@var{X}, which has the same meaning as in @code{style_check/1}.
|
||
|
||
The @code{no_style_check/1} built-in is now deprecated. Please use the
|
||
@code{set_prolog_flag/1} instead.
|
||
|
||
@item multifile @var{P} [ISO]
|
||
@findex multifile/1 (directive)
|
||
@syindex multifile/1 (directive)
|
||
@cnindex multifile/1 (directive)
|
||
Instructs the compiler about the declaration of a predicate @var{P} in
|
||
more than one file. It must appear in the first of the loaded files
|
||
where the predicate is declared, and before declaration of any of its
|
||
clauses.
|
||
|
||
Multifile declarations affect @code{reconsult/1} and @code{compile/1}:
|
||
when a multifile predicate is reconsulted, only the clauses from the
|
||
same file are removed.
|
||
|
||
Since Yap4.3.0 multifile procedures can be static or dynamic.
|
||
|
||
@item discontiguous(+@var{G}) [ISO]
|
||
@findex discontiguous/1 (directive)
|
||
@syindex discontiguous/1 (directive)
|
||
@cnindex discontiguous/1 (directive)
|
||
|
||
Declare that the arguments are discontiguous procedures, that is,
|
||
clauses for discontigous procedures may be separated by clauses from
|
||
other procedures.
|
||
|
||
@item initialization(+@var{G}) [ISO]
|
||
@findex initialization/1 (directive)
|
||
@snindex initialization/1 (directive)
|
||
@cnindex initialization/1 (directive)
|
||
The compiler will execute goals @var{G} after consulting the current
|
||
file.
|
||
|
||
@item library_directory(+@var{D})
|
||
@findex library_directory/1
|
||
@snindex library_directory/1
|
||
@cnindex library_directory/1
|
||
Succeeds when @var{D} is a current library directory name. Library
|
||
directories are the places where files specified in the form
|
||
@code{library(@var{File})} are searched by the predicates
|
||
@code{consult/1}, @code{reconsult/1}, @code{use_module/1} or
|
||
@code{ensure_loaded/1}.
|
||
|
||
@item prolog_file_name(+@var{Name},-@var{FullPath})
|
||
@findex prolog_file_name/2
|
||
@syindex prolog_file_name/1
|
||
@cnindex prolog_file_name/2
|
||
Unify @var{FullPath} with the absolute path YAP would use to consult
|
||
file @var{Name}.
|
||
|
||
@item public @var{P} [ISO]
|
||
@findex public/1 (directive)
|
||
@snindex public/1 (directive)
|
||
@cnindex public/1 (directive)
|
||
Instructs the compiler that the source of a predicate of a list of
|
||
predicates @var{P} must be kept. This source is then accessible through
|
||
the @code{clause/2} procedure and through the @code{listing} family of
|
||
built-ins.
|
||
|
||
Note that all dynamic procedures are public. The @code{source} directive
|
||
defines all new or redefined predicates to be public.
|
||
|
||
Since Yap4.3.0 multifile procedures can be static or dynamic.
|
||
|
||
@end table
|
||
|
||
@node Saving, , Setting the Compiler, Loading Programs
|
||
@section Saving and Loading Prolog States
|
||
|
||
@table @code
|
||
@item save(+@var{F})
|
||
@findex save/1
|
||
@snindex save/1
|
||
@cyindex save/1
|
||
Saves an image of the current state of YAP in file @var{F}. From
|
||
@strong{Yap4.1.3} onwards, YAP saved states are executable
|
||
files in the Unix ports.
|
||
|
||
@item save(+@var{F},-@var{OUT})
|
||
@findex save/2
|
||
@snindex save/2
|
||
@cnindex save/2
|
||
Saves an image of the current state of YAP in file @var{F}. From
|
||
@strong{Yap4.1.3} onwards, YAP saved states are executable
|
||
files in the Unix ports.
|
||
|
||
Unify @var{OUT} with 1 when saving the file and @var{OUT} with 0 when
|
||
restoring the saved state.
|
||
|
||
@item save_program(+@var{F})
|
||
@findex save_program/1
|
||
@syindex save_program/1
|
||
@cnindex save_program/1
|
||
Saves an image of the current state of the YAP database in file
|
||
@var{F}.
|
||
|
||
@item save_program(+@var{F}, :@var{G})
|
||
@findex save_program/2
|
||
@syindex save_program/2
|
||
@cnindex save_program/2
|
||
Saves an image of the current state of the YAP database in file
|
||
@var{F}, and guarantee that execution of the restored code will start by
|
||
trying goal @var{G}.
|
||
|
||
@item restore(+@var{F})
|
||
@findex restore/1
|
||
@syindex restore/1
|
||
@cnindex restore/1
|
||
Restores a previously saved state of YAP from file @var{F}.
|
||
|
||
YAP always tries to find saved states from the current directory
|
||
first. If it cannot it will use the environment variable YAPLIBDIR, if
|
||
defined, or search the default library directory.
|
||
@end table
|
||
|
||
|
||
@node Modules, Builtins, Loading Programs, Top
|
||
@chapter The Module System
|
||
|
||
Module systems are quite important for the development of large
|
||
applications. YAP implements a module system compatible with the Quintus
|
||
Prolog module system.
|
||
|
||
The YAP module system is predicate-based. This means a module consists
|
||
of a set of predicates (or procedures), such that some predicates are
|
||
public and the others are local to a module. Atoms and terms in general
|
||
are global to the system. Moreover, the module system is flat, meaning
|
||
that we do not support an hierarchy of modules. Modules can
|
||
automatically import other modules, though. For compatibility with other
|
||
module systems the YAP module system is non-strict, meaning both that
|
||
there is both a way to access predicates private to a module and that is
|
||
possible to declare predicates for a module from some other module.
|
||
|
||
YAP allows one to ignore the module system if one does not want to use
|
||
it. Last note that using the module system does not introduce any
|
||
significant overheads: only meta-calls that cross module boundaries are
|
||
slowed down by the presence of modules.
|
||
|
||
@menu
|
||
|
||
* Module Concepts:: The Key Ideas in Modules
|
||
* Defining Modules:: How To Define a New Module
|
||
* Using Modules:: How to Use a Module
|
||
* Meta-Predicates in Modules:: How to Handle New Meta-Predicates
|
||
|
||
@end menu
|
||
|
||
@node Module Concepts, Defining Modules, , Modules
|
||
@section Module Concepts
|
||
|
||
The YAP module system applies to predicates. All predicates belong to a
|
||
module. System predicates belong to the module @code{primitives}, and by
|
||
default new predicates belong to the module @code{user}. Predicates from
|
||
the module @code{primitives} are automatically visible to every module.
|
||
|
||
Every predicate must belong to a module. This module is called its
|
||
@emph{source module}.
|
||
|
||
By default, the source module for a clause occurring in a source file
|
||
with a module declaration is the declared module. For goals typed in
|
||
a source file without module declarations, their module is the module
|
||
the file is being loaded into. If no module declarations exist, this is
|
||
the current @emph{type-in module}. The default type-in module is
|
||
@code{user}, but one can set the current module by using the built-in
|
||
@code{module/1}.
|
||
|
||
Note that in this module system one can explicitly specify the source
|
||
mode for a clause by prefixing a clause with its module, say:
|
||
@example
|
||
user:(a :- b).
|
||
@end example
|
||
@noindent
|
||
In fact, to specify the source module for a clause it is sufficient to
|
||
specify the source mode for the clause's head:
|
||
@example
|
||
user:a :- b.
|
||
@end example
|
||
@noindent
|
||
|
||
The rules for goals are similar. If a goal appears in a text file with a
|
||
module declaration, the goal's source module is the declared
|
||
module. Otherwise, it is the module the file is being loaded into or the
|
||
type-in module.
|
||
|
||
One can override this rule by prefixing a goal with the module it is
|
||
supposed to be executed into, say:
|
||
@example
|
||
nasa:launch(apollo,13).
|
||
@end example
|
||
will execute the goal @code{launch(apollo,13)} as if the current source
|
||
module was @code{nasa}.
|
||
|
||
Note that this rule breaks encapsulation and should be used with care.
|
||
|
||
@node Defining Modules, Using Modules, Module Concepts, Modules
|
||
@section Defining a New Module
|
||
|
||
A new module is defined by a @code{module} declaration:
|
||
|
||
@table @code
|
||
|
||
@item module(+@var{M},+@var{L})
|
||
@findex module/2 (directive)
|
||
@syindex module/2 (directive)
|
||
@cnindex module/2 (directive)
|
||
This predicate defines the file where it appears as a module file; it
|
||
must be the first declaration in the file.
|
||
@var{M} must be an atom specifying the module name; @var{L} must be a list
|
||
containing the module's public predicates specification, in the form
|
||
@code{[predicate_name/arity,...]}.
|
||
|
||
The public predicates of a module file can be made accessible by other
|
||
files through the predicates @code{consult/1}, @code{reconsult/1},
|
||
@code{ensure_loaded/1} or @code{use_module/2}. The non-public predicates
|
||
of a module file are not visible by other files; they can, however, be
|
||
accessed if the module name is prefixed to the file name through the
|
||
@code{:/2} operator.
|
||
|
||
@end table
|
||
|
||
The built-in @code{module/1} sets the current source module:
|
||
@table @code
|
||
|
||
@item module(+@var{M},+@var{L}, +@var{Options})
|
||
@findex module/3 (directive)
|
||
@syindex module/3 (directive)
|
||
@cnindex module/3 (directive)
|
||
Similar to @code{module/2}, this predicate defines the file where it
|
||
appears as a module file; it must be the first declaration in the file.
|
||
@var{M} must be an atom specifying the module name; @var{L} must be a
|
||
list containing the module's public predicates specification, in the
|
||
form @code{[predicate_name/arity,...]}.
|
||
|
||
The last argument @var{Options} must be a list of options, which can be:
|
||
|
||
@table @code
|
||
@item filename
|
||
the filename for a module to import into the current module.
|
||
|
||
@item library(file)
|
||
a library file to import into the current module.
|
||
|
||
@item hide(@var{Opt})
|
||
if @var{Opt} is @code{false}, keep source code for current module, if
|
||
@code{true}, disable.
|
||
@end table
|
||
|
||
@item module(+@var{M})
|
||
@findex module/1
|
||
@syindex module/1
|
||
@cnindex module/1
|
||
Defines @var{M} to be the current working or type-in module. All files
|
||
which are not binded to a module are assumed to belong to the working
|
||
module (also referred to as type-in module). To compile a non-module
|
||
file into a module which is not the working one, prefix the file name
|
||
with the module name, in the form @code{@var{Module}:@var{File}}, when
|
||
loading the file.
|
||
|
||
@end table
|
||
|
||
@node Using Modules, Meta-Predicates in Modules, Defining Modules, Modules
|
||
@section Using Modules
|
||
|
||
By default, all procedures to consult a file will load the modules
|
||
defined therein. The two following declarations allow one to import a
|
||
module explicitly. They differ on whether one imports all predicate
|
||
declared in the module or not.
|
||
|
||
@table @code
|
||
|
||
@item use_module(+@var{F})
|
||
@findex use_module/1
|
||
@syindex use_module/1
|
||
@cnindex use_module/1
|
||
Loads the files specified by @var{F}, importing all their public
|
||
predicates. Predicate name clashes are resolved by asking the user about
|
||
importing or not the predicate. A warning is displayed when @var{F} is
|
||
not a module file.
|
||
|
||
@item use_module(+@var{F},+@var{L})
|
||
@findex use_module/2
|
||
@syindex use_module/2
|
||
@cnindex use_module/2
|
||
Loads the files specified by @var{F}, importing the predicates specified
|
||
in the list @var{L}. Predicate name clashes are resolved by asking the
|
||
user about importing or not the predicate. A warning is displayed when
|
||
@var{F} is not a module file.
|
||
|
||
@item use_module(?@var{M},?@var{F},+@var{L})
|
||
@findex use_module/3
|
||
@syindex use_module/3
|
||
@cnindex use_module/3
|
||
If module @var{M} has been defined, import the procedures in @var{L} to
|
||
the current module. Otherwise, load the files specified by @var{F},
|
||
importing the predicates specified in the list @var{L}.
|
||
@end table
|
||
|
||
@node Meta-Predicates in Modules, , Using Modules, Modules
|
||
@section Meta-Predicates in Modules
|
||
|
||
The module system must know whether predicates operate on goals or
|
||
clauses. Otherwise, such predicates would call a goal in the module they
|
||
were defined, instead of calling it in the module they are currently
|
||
executing. So, for instance:
|
||
@example
|
||
:- module(example,[a/1]).
|
||
|
||
...
|
||
|
||
a(G) :- call(G)
|
||
|
||
...
|
||
|
||
@end example
|
||
The expected behaviour for this procedure is to execute goal @var{G}
|
||
within the current module, that is, within @code{example}.
|
||
On the other hand, when executing @code{call/1} the system only knows
|
||
where @code{call/1} was defined, that is, it only knows of
|
||
@code{primitives}. A similar problem arises for @code{assert/1} and
|
||
friends.
|
||
|
||
The @code{meta_call/1} declaration informs the system that some
|
||
arguments of a procedure are goals, clauses or clauses heads, and that
|
||
these arguments must be expanded to receive the current source module:
|
||
|
||
@table @code
|
||
|
||
@item meta_predicate @var{G1},....,@var{Gn}
|
||
@findex meta_predicate/1 (directive)
|
||
@syindex meta_predicate/1 (directive)
|
||
@cnindex meta_predicate/1 (directive)
|
||
Each @var{Gi} is a mode specification. For example, a declaration for
|
||
@code{call/1} and @code{setof/3} would be of the form:
|
||
|
||
@example
|
||
:- meta_predicate call(:), setof(?,:,?).
|
||
@end example
|
||
|
||
If the argument is @code{:} or an integer, the argument is a call and
|
||
must be expanded. Otherwise, the argument should not be expanded. Note
|
||
that the system already includes declarations for all built-ins.
|
||
|
||
@end table
|
||
|
||
In the previous example, the only argument to @code{call/1} must be
|
||
expanded, resulting in the following code:
|
||
|
||
@example
|
||
:- module(example,[a/1]).
|
||
|
||
...
|
||
|
||
a(G) :- call(example:G)
|
||
|
||
...
|
||
|
||
@end example
|
||
|
||
@node Builtins, Library, Modules, Top
|
||
|
||
@chapter Built-In Predicates
|
||
|
||
@menu
|
||
|
||
Builtins, Debugging, Syntax, Top
|
||
* Control:: Controlling the Execution of Prolog Programs
|
||
* Undefined Procedures:: Handling calls to Undefined Procedures
|
||
* Testing Terms:: Predicates on Terms
|
||
* Comparing Terms:: Comparison of Terms
|
||
* Arithmetic:: Arithmetic in Yap
|
||
* I/O:: Input/Output with Yap
|
||
* Database:: Modifying Prolog's Database
|
||
* Sets:: Finding All Possible Solutions
|
||
* Grammars:: Grammar Rules
|
||
* Preds:: Predicate Information
|
||
* OS:: Access to Operating System Functionality
|
||
* Term Modification:: Updating Prolog Terms
|
||
* Profiling:: Profiling Prolog Execution
|
||
* Arrays:: Supporting Global and Local Arrays
|
||
* Preds:: Information on Predicates
|
||
* Misc:: Miscellaneous Predicates
|
||
|
||
@end menu
|
||
|
||
@node Control, Undefined Procedures, , Top
|
||
@section Control Predicates
|
||
|
||
|
||
This chapter describes the predicates for controlling the execution of
|
||
Prolog programs.
|
||
|
||
In the description of the arguments of functors the following notation
|
||
will be used:
|
||
|
||
@itemize @bullet
|
||
@item
|
||
a preceding plus signal will denote an argument as an "input argument" -
|
||
it cannot be a free variable at the time of the call;
|
||
@item
|
||
a preceding minus signal will denote an "output argument";
|
||
@item
|
||
an argument with no preceding symbol can be used in both ways.
|
||
@end itemize
|
||
|
||
|
||
@table @code
|
||
|
||
@item +@var{P}, +@var{Q} [ISO]
|
||
@findex ,/2
|
||
@syindex ,/2
|
||
@cyindex ,/2
|
||
Conjunction of goals (and).
|
||
|
||
@noindent
|
||
Example:
|
||
@example
|
||
p(X) :- q(X), r(X).
|
||
@end example
|
||
|
||
@noindent
|
||
should be read as "p(@var{X}) if q(@var{X}) and r(@var{X})".
|
||
|
||
@item +@var{P} ; +@var{Q} [ISO]
|
||
@findex ;/2
|
||
@syindex ;/2
|
||
@cyindex ;/2
|
||
Disjunction of goals (or).
|
||
|
||
@noindent
|
||
Example:
|
||
@example
|
||
p(X) :- q(X); r(X).
|
||
@end example
|
||
@noindent
|
||
should be read as "p(@var{X}) if q(@var{X}) or r(@var{X})".
|
||
|
||
@item true [ISO]
|
||
@findex true/0
|
||
@syindex true/0
|
||
@cyindex true/0
|
||
Succeeds once.
|
||
|
||
@item fail [ISO]
|
||
@findex fail/0
|
||
@syindex fail/0
|
||
@cyindex fail/0
|
||
Fails always.
|
||
|
||
@item false
|
||
@findex false/0
|
||
@syindex false/0
|
||
@cnindex false/0
|
||
The same as fail
|
||
|
||
@item ! [ISO]
|
||
@findex !/0
|
||
@syindex !/0
|
||
@cyindex !/0
|
||
Read as "cut". Cuts any choices taken in the current procedure.
|
||
When first found "cut" succeeds as a goal, but if backtracking should
|
||
later return to it, the parent goal (the one which matches the head of
|
||
the clause containing the "cut", causing the clause activation) will
|
||
fail. This is an extra-logical predicate and cannot be explained in
|
||
terms of the declarative semantics of Prolog.
|
||
|
||
example:
|
||
|
||
@example
|
||
member(X,[X|_]).
|
||
member(X,[_|L]) :- member(X,L).
|
||
@end example
|
||
|
||
@noindent
|
||
With the above definition
|
||
|
||
@example
|
||
?- member(X,[1,2,3]).
|
||
@end example
|
||
|
||
@noindent
|
||
will return each element of the list by backtracking. With the following
|
||
definition:
|
||
|
||
@example
|
||
member(X,[X|_]) :- !.
|
||
member(X,[_|L]) :- member(X,L).
|
||
@end example
|
||
|
||
@noindent
|
||
the same query would return only the first element of the
|
||
list, since backtracking could not "pass through" the cut.
|
||
|
||
@item \+ +@var{P} [ISO]
|
||
@findex \+/1
|
||
@syindex \+/1
|
||
@cyindex \+/1
|
||
Goal @var{P} is not provable. The execution of this predicate fails if
|
||
and only if the goal @var{P} finitely succeeds. It is not a true logical
|
||
negation, which is impossible in standard Prolog, but
|
||
"negation-by-failure".
|
||
|
||
@noindent
|
||
This predicate might be defined as:
|
||
@example
|
||
\+(P) :- P, !, fail.
|
||
\+(_).
|
||
@end example
|
||
@noindent
|
||
if @var{P} did not include "cuts".
|
||
|
||
@item not +@var{P}
|
||
@findex not/1
|
||
@snindex not/1
|
||
@cyindex not/1
|
||
Goal @var{P} is not provable. The same as @code{'\+ @var{P}'}.
|
||
|
||
This predicate is kept for compatibility with C-Prolog and previous
|
||
versions of YAP. Uses of @code{not/1} should be replace by
|
||
@code{(\+)/1}, as YAP does not implement true negation.
|
||
|
||
@item +@var{P} -> +@var{Q} [ISO]
|
||
@findex ->/2
|
||
@syindex ->/2
|
||
@cnindex ->/2
|
||
Read as "if-then-else" or "commit". This operator is similar to the
|
||
conditional operator of imperative languages and can be used alone or
|
||
with an else part as follows:
|
||
|
||
@table @code
|
||
@item +P -> +Q
|
||
"if P then Q".
|
||
@item +P -> +Q; +R
|
||
"if P then Q else R".
|
||
@end table
|
||
|
||
@noindent
|
||
These two predicates could be defined respectively in Prolog as:
|
||
@example
|
||
(P -> Q) :- P, !, Q.
|
||
@end example
|
||
@noindent
|
||
and
|
||
@example
|
||
(P -> Q; R) :- P, !, Q.
|
||
(P -> Q; R) :- R.
|
||
@end example
|
||
@noindent
|
||
if there were no "cuts" in @var{P}, @var{Q} and @var{R}.
|
||
|
||
Note that the commit operator works by "cutting" any alternative
|
||
solutions of @var{P}.
|
||
|
||
Note also that you can use chains of commit operators like:
|
||
@example
|
||
P -> Q ; R -> S ; T.
|
||
@end example
|
||
@noindent
|
||
Note that @code{(->)/2} does not affect the scope of cuts in its
|
||
arguments.
|
||
|
||
@item repeat [ISO]
|
||
@findex repeat/0
|
||
@syindex repeat/0
|
||
@cyindex repeat/0
|
||
Succeeds repeatedly.
|
||
|
||
In the next example, @code{repeat} is used as an efficient way to implement
|
||
a loop. The next example reads all terms in a file:
|
||
|
||
@example
|
||
a :- repeat, read(X), write(X), nl, X=end_of_file, !.
|
||
@end example
|
||
@noindent
|
||
the loop is effectively terminated by the cut-goal, when the test-goal
|
||
@code{X=end} succeeds. While the test fails, the goals @code{read(X)},
|
||
@code{write(X)}, and @code{nl} are executed repeatedly, because
|
||
backtracking is caught by the @code{repeat} goal.
|
||
|
||
The built-in @code{repeat/1} could be defined in Prolog by:
|
||
@example
|
||
repeat.
|
||
repeat :- repeat.
|
||
@end example
|
||
|
||
@item call(+@var{P}) [IS0]
|
||
@findex call/1
|
||
@syindex call/1
|
||
@cyindex call/1
|
||
If @var{P} is instantiated to an atom or a compound term, the goal
|
||
@code{call(@var{P})} is executed as if the value of @code{P} was found
|
||
instead of the call to @code{call/1}, except that any "cut" occurring in
|
||
@var{P} only cuts alternatives in the execution of @var{P}.
|
||
|
||
@item incore(+@var{P})
|
||
@findex incore/1
|
||
@syindex incore/1
|
||
@cnindex incore/1
|
||
The same as @code{call/1}.
|
||
|
||
@item call_with_args(+@var{Name},...,?@var{Ai},...)
|
||
@findex call_with_args/n
|
||
@snindex call_with_args/n
|
||
@cnindex call_with_args/n
|
||
Meta-call where @var{Name} is the name of the procedure to be called and
|
||
the @var{Ai} are the arguments. The number of arguments varies between 0
|
||
and 10.
|
||
|
||
@item +@var{P}
|
||
The same as @code{call(@var{P})}. This feature has been kept to provide
|
||
compatibility with C-Prolog. When compiling a goal, YAP
|
||
generates a @code{call(@var{X})} whenever a variable @var{X} is found as
|
||
a goal.
|
||
|
||
@example
|
||
a(X) :- X.
|
||
@end example
|
||
@noindent
|
||
is converted to:
|
||
@example
|
||
a(X) :- call(X).
|
||
@end example
|
||
|
||
@item if(?@var{G},?@var{H},?@var{I}) [IS0]
|
||
@findex if/3
|
||
@syindex if/3
|
||
@cnindex if/3
|
||
Call goal @var{H} once per each solution of goal @var{H}. If goal
|
||
@var{H} has no solutions, call goal @var{I}.
|
||
|
||
The builtin @code{if/3} is similar to @code{->/3}, with the difference
|
||
that it will backtrack over the test goal. Consider the following
|
||
small data-base:
|
||
|
||
@example
|
||
a(1). b(a). c(x).
|
||
a(2). b(b). c(y).
|
||
@end example
|
||
|
||
Execution of an @code{if/3} query will proceed as follows:
|
||
|
||
@example
|
||
?- if(a(X),b(Y),c(Z)).
|
||
|
||
X = 1,
|
||
Y = a ? ;
|
||
|
||
X = 1,
|
||
Y = b ? ;
|
||
|
||
X = 2,
|
||
Y = a ? ;
|
||
|
||
X = 2,
|
||
Y = b ? ;
|
||
|
||
no
|
||
@end example
|
||
|
||
|
||
@noindent
|
||
The system will backtrack over the two solutions for @code{a/1} and the
|
||
two solutions for @code{b/1}, generating four solutions.
|
||
|
||
Cuts are allowed inside the first goal @var{G}, but they will only prune
|
||
over @var{G}.
|
||
|
||
If you want @var{G} to be deterministic you should use if-then-else, as
|
||
it is both more efficient and more portable.
|
||
|
||
@item once(+@var{G}) [IS0]
|
||
@findex once/1
|
||
@snindex once/1
|
||
@cnindex once/1
|
||
Execute the goal @var{G} only once. The predicate is defined by:
|
||
|
||
@example
|
||
once(G) :- call(G), !.
|
||
@end example
|
||
|
||
@noindent
|
||
Note that cuts inside @code{once/1} can only cut the other goals inside
|
||
@code{once/1}.
|
||
|
||
@item abort
|
||
@findex abort/0
|
||
@syindex abort/0
|
||
@cyindex abort/0
|
||
Abandons the execution of the current goal and returns to top level. All
|
||
break levels (see @code{break/0} below) are terminated. It is mainly
|
||
used during debugging or after a serious execution error, to return to
|
||
the top-level.
|
||
|
||
|
||
@item break
|
||
@findex break/0
|
||
@syindex break/0
|
||
@cyindex break/0
|
||
Suspends the execution of the current goal and creates a new execution
|
||
level similar to the top level, displaying the following message:
|
||
|
||
@example
|
||
[ Break (level <number>) ]
|
||
@end example
|
||
@noindent
|
||
telling the depth of the break level just entered. To return to the
|
||
previous level just type the end-of-file character or call the
|
||
end_of_file predicate. This predicate is especially useful during
|
||
debugging.
|
||
|
||
@item halt [ISO]
|
||
@findex halt/0
|
||
@syindex halt/0
|
||
@cyindex halt/0
|
||
Halts Prolog, and exits to the calling application. In YAP,
|
||
@code{halt/0} returns the exit code @code{0}.
|
||
|
||
@item halt(+ @var{I}) [ISO]
|
||
@findex halt/1
|
||
@syindex halt/1
|
||
@cnindex halt/1
|
||
Halts Prolog, and exits to the calling application returning the code
|
||
given by the integer @var{I}.
|
||
|
||
@item catch(+@var{Goal},+@var{Exception},+@var{Action}) [IS0]
|
||
@findex catch/3
|
||
@snindex catch/3
|
||
@cnindex catch/3
|
||
The goal @code{catch(@var{Goal},@var{Exception},@var{Action})} tries to
|
||
execute goal @var{Goal}. If during its execution, @var{Goal} throws an
|
||
exception @var{E'} and this exception unifies with @var{Exception}, the
|
||
exception is considered to be caught and @var{Action} is executed. If
|
||
the exception @var{E'} does not unify with @var{Exception}, control
|
||
again throws the exception.
|
||
|
||
The top-level of YAP maintains a default exception handler that
|
||
is responsible to capture uncaught exceptions.
|
||
|
||
@item throw(+@var{Ball}) [ISO]
|
||
@findex throw/1
|
||
@snindex throw/1
|
||
@cnindex throw/1
|
||
The goal @code{throw(@var{Ball})} throws an exception. Execution is
|
||
stopped, and the exception is sent to the ancestor goals until reaching
|
||
a matching @code{catch/3}, or until reaching top-level.
|
||
|
||
@item garbage_collect
|
||
@findex garbage_collect/0
|
||
@syindex garbage_collect/0
|
||
@cnindex garbage_collect/0
|
||
The goal @code{garbage_collect} forces a garbage collection.
|
||
|
||
@item gc
|
||
@findex gc/0
|
||
@syindex gc/0
|
||
@cnindex gc/0
|
||
The goal @code{gc} enables garbage collection. The same as
|
||
@code{yap_flag(gc,on)}.
|
||
|
||
@item nogc
|
||
@findex nogc/0
|
||
@syindex nogc/0
|
||
@cnindex nogc/0
|
||
The goal @code{nogc} disables garbage collection. The same as
|
||
@code{yap_flag(gc,off)}.
|
||
|
||
@item grow_heap(+@var{Size})
|
||
@snindex grow_heap/1
|
||
@cnindex grow_heap/1
|
||
Increase heap size @var{Size} kilobytes.
|
||
|
||
@item grow_stack(+@var{Size})
|
||
@findex grow_stack/1
|
||
@snindex grow_stack/1
|
||
@cnindex grow_stack/1
|
||
Increase stack size @var{Size} kilobytes.
|
||
|
||
@end table
|
||
|
||
@node Undefined Procedures, Testing Terms, Control, Top
|
||
@section Handling Undefined Procedures
|
||
|
||
A predicate in a module is said to be undefined if there are no clauses
|
||
defining the predicate, and if the predicate has not been declared to be
|
||
dynamic. What YAP does when trying to execute undefined predicates can
|
||
be specified through three different ways:
|
||
@itemize @bullet
|
||
@item By setting an YAP flag, through the @code{yap_flag/2} or
|
||
@code{set_prolog_flag/2} built-ins. This solution generalises the
|
||
ISO standard.
|
||
@item By using the @code{unknown/2} built-in (this solution is
|
||
compatible with previous releases of YAP).
|
||
@item By defining clauses for the hook predicate
|
||
@code{user:unknown_predicate_handler/3}. This solution is compatible
|
||
with SICStus Prolog.
|
||
@end itemize
|
||
|
||
In more detail:
|
||
@table @code
|
||
@item unknown(-@var{O},+@var{N})
|
||
@findex unknown/2
|
||
@saindex unknown/2
|
||
@cnindex unknown/2
|
||
Specifies an handler to be called is a program tries to call an
|
||
undefined static procedure @var{P}.
|
||
|
||
The arity of @var{N} may be zero or one. If the arity is @code{0}, the
|
||
new action must be one of @code{fail}, @code{warning}, or
|
||
@code{error}. If the arity is @code{1}, @var{P} is an user-defined
|
||
handler and at run-time, the argument to the handler @var{P} will be
|
||
unified with the undefined goal. Note that @var{N} must be defined prior
|
||
to calling @code{unknown/2}, and that the single argument to @var{N} must
|
||
be unbound.
|
||
|
||
In YAP, the default action is to @code{fail} (note that in the ISO
|
||
Prolog standard the default action is @code{error}).
|
||
|
||
After defining @code{undefined/1} by:
|
||
@example
|
||
undefined(A) :- format('Undefined predicate: ~w~n'), fail.
|
||
@end example
|
||
@noindent
|
||
and executing the goal:
|
||
@example
|
||
unknown(U,undefined(X)).
|
||
@end example
|
||
@noindent
|
||
a call to a predicate for which no clauses were defined will result in
|
||
the output of a message of the form:
|
||
@example
|
||
Undefined predicate: user:xyz(A1,A2)
|
||
@end example
|
||
@noindent
|
||
followed by the failure of that call.
|
||
|
||
@item yap_flag(unknown,+SPEC)
|
||
Alternatively, one can use @code{yap_flag/2},
|
||
@code{current_prolog_flag/2}, or @code{set_prolog_flag/2}, to set this
|
||
functionality. In this case, the first argument for the built-ins should
|
||
be @code{unknown}, and the second argument should be either
|
||
@code{error}, @code{warning}, @code{fail}, or a goal.
|
||
|
||
@item user:unknown_predicate_handler(+G,+M,?NG)
|
||
@findex user:unknown_predicate_handler/3
|
||
@syindex user:unknown_predicate_handler/3
|
||
@cnindex user:unknown_predicate_handler/3
|
||
The user may also define clauses for
|
||
@code{user:unknown_predicate_handler/3} hook predicate. This
|
||
user-defined procedure is called before any system processing for the
|
||
undefined procedure, with the first argument @var{G} set to the current
|
||
goal, and the second @var{M} set to the current module.
|
||
|
||
If @code{user:unknown_predicate_handler/3} succeeds, the system will
|
||
execute @var{NG}. If @code{user:unknown_predicate_handler/3} fails, the
|
||
system will execute default action as specified by @code{unknown/2}.
|
||
@end table
|
||
|
||
@node Testing Terms, Comparing Terms, Undefined Procedures, Top
|
||
@section Predicates on terms
|
||
|
||
@table @code
|
||
|
||
@item var(@var{T}) [ISO]
|
||
@findex var/1
|
||
@syindex var/1
|
||
@cyindex var/1
|
||
Succeeds if @var{T} is currently a free variable, otherwise fails.
|
||
|
||
@item atom(@var{T}) [ISO]
|
||
@findex atom/1
|
||
@syindex atom/1
|
||
@cyindex atom/1
|
||
Succeeds if and only if @var{T} is currently instantiated to an atom.
|
||
|
||
@item atomic(T) [ISO]
|
||
@findex atomic/1
|
||
@syindex atomic/1
|
||
@cyindex atomic/1
|
||
Checks whether @var{T} is an atomic symbol (atom or number).
|
||
|
||
@item compound(@var{T}) [ISO]
|
||
@findex compound/1
|
||
@syindex compound/1
|
||
@cnindex compound/1
|
||
Checks whether @var{T} is a compound term.
|
||
|
||
@item db_reference(@var{T})
|
||
@findex db_reference/1C
|
||
@syindex db_reference/1
|
||
@cyindex db_reference/1
|
||
Checks whether @var{T} is a database reference.
|
||
|
||
@item float(@var{T}) [ISO]
|
||
@findex float/1
|
||
@syindex float/1
|
||
@cnindex float/1
|
||
Checks whether @var{T} is a floating point number.
|
||
|
||
@item integer(@var{T}) [ISO]
|
||
@findex integer/1
|
||
@syindex integer/1
|
||
@cyindex integer/1
|
||
Succeeds if and only if @var{T} is currently instantiated to an integer.
|
||
|
||
@item nonvar(@var{T}) [ISO]
|
||
@findex nonvar/1
|
||
@syindex nonvar/1
|
||
@cyindex nonvar/1
|
||
The opposite of @code{var(@var{T})}.
|
||
|
||
@item number(@var{T}) [ISO]
|
||
@findex number/1
|
||
@syindex number/1
|
||
@cyindex number/1
|
||
Checks whether @code{T} is an integer or a float.
|
||
|
||
@item primitive(@var{T})
|
||
@findex primitive/1
|
||
@syindex primitive/1
|
||
@cyindex primitive/1
|
||
Checks whether @var{T} is an atomic term or a database reference.
|
||
|
||
@item simple(@var{T})
|
||
@findex simple/1
|
||
@syindex simple/1
|
||
@cnindex simple/1
|
||
Checks whether @var{T} is unbound, an atom, or a number.
|
||
|
||
@item callable(@var{T})
|
||
@findex callable/1
|
||
@syindex callable/1
|
||
@cnindex callable/1
|
||
Checks whether @var{T} is a callable term, that is, an atom or a
|
||
compound term.
|
||
|
||
@item name(@var{A},@var{L})
|
||
@findex name/2
|
||
@syindex name/2
|
||
@cyindex name/2
|
||
The predicate holds when at least one of the arguments is ground
|
||
(otherwise, an error message will be displayed). The argument @var{A} will
|
||
be unified with an atomic symbol and @var{L} with the list of the ASCII
|
||
codes for the characters of the external representation of @var{A}.
|
||
|
||
@example
|
||
name(yap,L).
|
||
@end example
|
||
@noindent
|
||
will return:
|
||
@example
|
||
L = [121,97,112].
|
||
@end example
|
||
@noindent
|
||
and
|
||
@example
|
||
name(3,L).
|
||
@end example
|
||
@noindent
|
||
will return:
|
||
@example
|
||
L = [51].
|
||
@end example
|
||
|
||
@item atom_chars(?@var{A},?@var{L}) [ISO]
|
||
@findex atom_chars/2
|
||
@saindex atom_chars/2
|
||
@cnindex atom_chars/2
|
||
The predicate holds when at least one of the arguments is ground
|
||
(otherwise, an error message will be displayed). The argument @var{A} must
|
||
be unifiable with an atom, and the argument @var{L} with the list of the
|
||
ASCII codes for the characters of the external representation of @var{A}.
|
||
|
||
The ISO-Prolog standard dictates that @code{atom_chars/2} should unify
|
||
the second argument with a list of one-char atoms, and not the character
|
||
codes. For compatibility with previous versions of YAP, and
|
||
with other Prolog implementations, YAP unifies the second
|
||
argument with the character codes, as in @code{atom_codes/2}. Use the
|
||
@code{set_prolog_flag(to_chars_mode,iso)} to obtain ISO standard
|
||
compatibility.
|
||
|
||
@item atom_codes(?@var{A},?@var{L}) [ISO]
|
||
@findex atom_codes/2
|
||
@syindex atom_codes/2
|
||
@cnindex atom_codes/2
|
||
The predicate holds when at least one of the arguments is ground
|
||
(otherwise, an error message will be displayed). The argument @var{A} will
|
||
be unified with an atom and @var{L} with the list of the ASCII
|
||
codes for the characters of the external representation of @var{A}.
|
||
|
||
@item atom_concat(+@var{As},?@var{A})
|
||
@findex atom_concat/2
|
||
@snindex atom_concat/2
|
||
@cnindex atom_concat/2
|
||
The predicate holds when the first argument is a list of atoms, and the
|
||
second unifies with the atom obtained by concatenating all the atoms in
|
||
the first list.
|
||
|
||
@item atom_length(+@var{A},?@var{I}) [ISO]
|
||
@findex atom_length/2
|
||
@snindex atom_length/2
|
||
@cnindex atom_length/2
|
||
The predicate holds when the first argument is an atom, and the second
|
||
unifies with the number of characters forming that atom.
|
||
|
||
@item atom_concat(?@var{A1},?@var{A2},?@var{A12}) [ISO]
|
||
@findex atom_concat/3
|
||
@snindex atom_concat/3
|
||
@cnindex atom_concat/3
|
||
The predicate holds when the third argument unifies with an atom, and
|
||
the first and second unify with atoms such that their representations
|
||
concatenated are the representation for @var{A12}.
|
||
|
||
If @var{A1} and @var{A2} are unbound, the built-in will find all the atoms
|
||
that concatenated give @var{A12}.
|
||
|
||
@item number_chars(?@var{I},?@var{L})
|
||
@findex number_chars/2
|
||
@saindex number_chars/2
|
||
@cnindex number_chars/2
|
||
|
||
The predicate holds when at least one of the arguments is ground
|
||
(otherwise, an error message will be displayed). The argument @var{I} must
|
||
be unifiable with a number, and the argument @var{L} with the list of the
|
||
ASCII codes for the characters of the external representation of @var{I}.
|
||
|
||
The ISO-Prolog standard dictates that @code{number_chars/2} should unify
|
||
the second argument with a list of one-char atoms, and not the character
|
||
codes. For compatibility with previous versions of YAP, and
|
||
with other Prolog implementations, YAP unifies the second
|
||
argument with the character codes, as in @code{number_codes/2}. Use the
|
||
@code{set_prolog_flag(to_chars_mode,iso)} to obtain ISO standard
|
||
compatibility.
|
||
|
||
@item number_codes(?@var{A},?@var{L}) [ISO]
|
||
@findex number_codes/2
|
||
@syindex number_codes/2
|
||
@cnindex number_codes/2
|
||
The predicate holds when at least one of the arguments is ground
|
||
(otherwise, an error message will be displayed). The argument @var{A}
|
||
will be unified with a number and @var{L} with the list of the ASCII
|
||
codes for the characters of the external representation of @var{A}.
|
||
|
||
@item number_atom(?@var{I},?@var{L})
|
||
@findex number_atom/2
|
||
@snindex number_atom/2
|
||
@cnindex number_atom/2
|
||
|
||
The predicate holds when at least one of the arguments is ground
|
||
(otherwise, an error message will be displayed). The argument @var{I} must
|
||
be unifiable with a number, and the argument @var{L} must be unifiable
|
||
with an atom representing the number.
|
||
|
||
@item char_code(?@var{A},?@var{I}) [ISO]
|
||
@findex char_code/2
|
||
@syindex char_code/2
|
||
@cnindex char_code/2
|
||
The built-in succeeds with @var{A} bound to character represented as an
|
||
atom, and @var{I} bound to the character code represented as an
|
||
integer. At least, one of either @var{A} or @var{I} must be bound before
|
||
the call.
|
||
|
||
@item sub_atom(+@var{A},?@var{Bef}, ?@var{Size}, ?@var{After}, ?@var{At_out}) [ISO]
|
||
@findex sub_atom/5
|
||
@snindex sub_atom/5
|
||
@cnindex sub_atom/5
|
||
True when @var{A} and @var{At_out} are atoms such that the name of
|
||
@var{At_out} has size @var{Size} and is a substring of the name of
|
||
@var{A}, such that @var{Bef} is the number of characters before and
|
||
@var{After} the number of characters afterwards.
|
||
|
||
Note that @var{A} must always be known, but @var{At_out} can be unbound when
|
||
calling this built-in. If all the arguments for @code{sub_atom/5} but @var{A}
|
||
are unbound, the built-in will backtrack through all possible
|
||
substrings of @var{A}.
|
||
|
||
@item numbervars(@var{T},+@var{N1},-@var{Nn})
|
||
@findex numbervars/3
|
||
@syindex numbervars/3
|
||
@cnindex numbervars/3
|
||
Instantiates each variable in term @var{T} to a term of the form:
|
||
@code{'$VAR'(@var{I})}, with @var{I} increasing from @var{N1} to @var{Nn}.
|
||
|
||
@item ground(@var{T})
|
||
@findex ground/1
|
||
@syindex ground/1
|
||
@cnindex ground/1
|
||
Succeeds if there are no free variables in the term @var{T}.
|
||
|
||
@item arg(+@var{N},+@var{T},@var{A}) [ISO]
|
||
@findex arg/3
|
||
@syindex arg/3
|
||
@cnindex arg/3
|
||
Succeeds if the argument @var{N} of the term @var{T} unifies with
|
||
@var{A}. The arguments are numbered from 1 to the arity of the term.
|
||
|
||
The current version will generate an error if @var{T} or @var{N} are
|
||
unbound, if @var{T} is not a compound term, of if @var{N} is not a positive
|
||
integer. Note that previous versions of YAP would fail silently
|
||
under these errors.
|
||
|
||
@item functor(@var{T},@var{F},@var{N})
|
||
@findex functor/3
|
||
@syindex functor/3
|
||
@cyindex functor/3
|
||
The top functor of term @var{T} is named @var{F} and has arity @var{N}.
|
||
|
||
When @var{T} is not instantiated, @var{F} and @var{N} must be. If
|
||
@var{N} is 0, @var{F} must be an atomic symbol, which will be unified
|
||
with @var{T}. If @var{N} is not 0, then @var{F} must be an atom and
|
||
@var{T} becomes instantiated to the most general term having functor
|
||
@var{F} and arity @var{N}. If @var{T} is instantiated to a term then
|
||
@var{F} and @var{N} are respectively unified with its top functor name
|
||
and arity.
|
||
|
||
In the current version of YAP the arity @var{N} must be an
|
||
integer. Previous versions allowed evaluable expressions, as long as the
|
||
expression would evaluate to an integer. This feature is not available
|
||
in the ISO Prolog standard.
|
||
|
||
@item @var{T} =.. @var{L} [ISO]
|
||
@findex =../2
|
||
@syindex =../2
|
||
@cyindex =../2
|
||
The list @var{L} is built with the functor and arguments of the term
|
||
@var{T}. If @var{T} is instantiated to a variable, then @var{L} must be
|
||
instantiated either to a list whose head is an atom, or to a list
|
||
consisting of just a number.
|
||
|
||
@item @var{X} = @var{Y} [ISO]
|
||
@findex =/2
|
||
@syindex =/2
|
||
@cnindex =/2
|
||
Tries to unify terms @var{X} and @var{Y}.
|
||
|
||
@item @var{X} \= @var{Y} [ISO]
|
||
@findex \=/2
|
||
@snindex \=/2
|
||
@cnindex \=/2
|
||
Succeeds if terms @var{X} and @var{Y} are not unifiable.
|
||
|
||
@item term_variables(?T,+L)
|
||
@findex term_variables/2
|
||
@syindex term_variables/2
|
||
@cnindex term_variables/2
|
||
Unify the second argument with the list of variables occurring in @var{T}.
|
||
|
||
@item term_hash(+@var{T},+@var{Depth},+@var{Max},-@var{O})
|
||
@findex term_hash/4
|
||
@syindex term_hash/4
|
||
@cnindex term_hash/4
|
||
Unify the last argument with a number, called the hash function for
|
||
term. This integer can be used to implement efficient term access
|
||
schemes. The number @var{O} is such that:
|
||
@itemize @bullet
|
||
@item The function only considers constants and functors from @var{T} up
|
||
to depth @var{Depth} are considered. The @emph{depth} of a term is defined as
|
||
follows:
|
||
@itemize @minus
|
||
@item The depth of a constant of is 1.
|
||
@item The depth of term is 1 plus the maximum depth of its sub-terms.
|
||
@end itemize
|
||
|
||
@item If a variable is found up to depth @var{Depth}, @var{O} will be
|
||
left unbound.
|
||
|
||
@item If @var{Depth} is bound to -1, the term will be fully
|
||
investigated. If the term is bound to an infinite rational tree, the
|
||
predicate will loop.
|
||
|
||
@item If the term includes floating point numbers or integers whose
|
||
absolute value is larger than 7829367, than the result is considered to
|
||
be implementation defined. Otherwise, the result is platform indepent.
|
||
|
||
@item The variable @var{Max} must be bound to a positive
|
||
integer. If bound, @var{O} will be in the range going from 0 up to, but
|
||
not including, @var{Max}.
|
||
@end itemize
|
||
|
||
@item term_hash(+@var{T},-@var{O})
|
||
@findex term_hash/2
|
||
@syindex term_hash/2
|
||
@cnindex term_hash/2
|
||
Simplified version of @code{term_hash/4} such that @var{Depth} is bound
|
||
to -1 and @var{Max} is bound to a large platform-indepent integer.
|
||
|
||
@item unify_with_occurs_check(?T1,?T2) [ISO]
|
||
@findex unify_with_occurs_check/2
|
||
@syindex unify_with_occurs_check/2
|
||
@cnindex unify_with_occurs_check/2
|
||
Obtain the most general unifier of terms @var{T1} and @var{T2}, if there
|
||
is one.
|
||
|
||
This predicate implements the full unification algorithm. An example:n
|
||
@example
|
||
unify_with_occurs_check(a(X,b,Z),a(X,A,f(B)).
|
||
@end example
|
||
@noindent
|
||
will succeed with the bindings @code{A = b} and @code{Z = f(B)}. On the
|
||
other hand:
|
||
@example
|
||
unify_with_occurs_check(a(X,b,Z),a(X,A,f(Z)).
|
||
@end example
|
||
@noindent
|
||
would fail, because @code{Z} is not unifiable with @code{f(Z)}. Note that
|
||
@code{(=)/2} would succeed for the previous examples, giving the following
|
||
bindings @code{A = b} and @code{Z = f(Z)}.
|
||
|
||
|
||
@item copy_term(?@var{TI},-@var{TF}) [ISO]
|
||
@findex copy_term/2
|
||
@syindex copy_term/2
|
||
@cnindex copy_term/2
|
||
Term @var{TF} is a variant of the original term @var{TI}, such that for
|
||
each variable @var{V} in the term @var{TI} there is a new variable @var{V'}
|
||
in term @var{TF}.
|
||
|
||
@end table
|
||
|
||
@node Comparing Terms, Arithmetic, Testing Terms, Top
|
||
@section Comparing Terms
|
||
|
||
The following predicates are used to compare and order terms, using the
|
||
standard ordering:
|
||
|
||
@itemize @bullet
|
||
@item
|
||
variables come before numbers, numbers come before atoms which in turn
|
||
come before compound terms, ie: variables @@< numbers @@< atoms @@<
|
||
compound terms.
|
||
@item
|
||
variables are roughly ordered by "age" (the "oldest" variable is put
|
||
first);
|
||
@item
|
||
floating point numbers are sorted in increasing order;
|
||
@item
|
||
Integers are sorted in increasing order;
|
||
@item
|
||
atoms are sorted in lexicographic order;
|
||
@item
|
||
compound terms are ordered first by name, then by arity of the main
|
||
functor and finally by their arguments i left-to-right order.
|
||
@end itemize
|
||
|
||
@table @code
|
||
|
||
@item compare(@var{C},@var{X},@var{Y})
|
||
@findex compare/3
|
||
@syindex compare/3
|
||
@cyindex compare/3
|
||
As a result of comparing @var{X} and @var{Y}, @var{C} may take one of
|
||
the following values:
|
||
|
||
@itemize @bullet
|
||
@item
|
||
@code{=} if @var{X} and @var{Y} are identical;
|
||
@item
|
||
@code{<} if @var{X} precedes @var{Y} in the defined order;
|
||
@item
|
||
@code{>} if @var{Y} precedes @var{X} in the defined order;
|
||
@end itemize
|
||
|
||
@item @var{X} == @var{Y} [ISO]
|
||
@findex ==/2
|
||
@syindex ==/2
|
||
@cyindex ==/2
|
||
Succeeds if terms @var{X} and @var{Y} are strictly identical. The
|
||
difference between this predicate and @code{=/2} is that, if one of the
|
||
arguments is a free variable, it only succeeds when they have already
|
||
been unified.
|
||
|
||
@example
|
||
?- X == Y.
|
||
@end example
|
||
@noindent
|
||
fails, but,
|
||
@example
|
||
?- X = Y, X == Y.
|
||
@end example
|
||
@noindent
|
||
succeeds.
|
||
@example
|
||
?- X == 2.
|
||
@end example
|
||
@noindent
|
||
fails, but,
|
||
@example
|
||
?- X = 2, X == 2.
|
||
@end example
|
||
@noindent
|
||
succeeds.
|
||
|
||
|
||
@item @var{X} \== @var{Y} [ISO]
|
||
@findex \==/2
|
||
@syindex \==/2
|
||
@cyindex \==/2
|
||
Terms @var{X} and @var{Y} are not strictly identical.
|
||
|
||
@item @var{X} @@< @var{Y} [ISO]
|
||
@findex @@</2
|
||
@syindex @@</2
|
||
@cyindex @@</2
|
||
Term @var{X} precedes term @var{Y} in the standard order.
|
||
|
||
@item @var{X} @@=< @var{Y} [ISO]
|
||
@findex @@=</2
|
||
@syindex @@</2
|
||
@cyindex @@</2
|
||
Term @var{X} does not follow term @var{Y} in the standard order.
|
||
|
||
@item @var{X} @@> @var{Y} [ISO]
|
||
@findex @@>/2
|
||
@syindex @@>/2
|
||
@cyindex @@>/2
|
||
Term @var{X} follows term @var{Y} in the standard order.
|
||
|
||
@item @var{X} @@>= @var{Y} [ISO]
|
||
@findex @@>=/2
|
||
@syindex @@>=/2
|
||
@cyindex @@>=/2
|
||
Term @var{X} does not precede term @var{Y} in the standard order.
|
||
|
||
@item sort(+@var{L},-@var{S})
|
||
@findex sort/2
|
||
@syindex sort/2
|
||
@cyindex sort/2
|
||
Unifies @var{S} with the list obtained by sorting @var{L} and merging
|
||
identical (in the sense of @code{==}) elements.
|
||
|
||
@item keysort(+@var{L},@var{S})
|
||
@findex keysort/2
|
||
@syindex keysort/2
|
||
@cyindex keysort/2
|
||
Assuming L is a list of the form @code{@var{Key}-@var{Value}},
|
||
@code{keysort(+@var{L},@var{S})} unifies @var{S} with the list obtained
|
||
from @var{L}, by sorting its elements according to the value of
|
||
@var{Key}.
|
||
@example
|
||
?- keysort([3-a,1-b,2-c,1-a,1-b],S).
|
||
@end example
|
||
@noindent
|
||
would return:
|
||
@example
|
||
S = [1-b,1-a,1-b,2-c,3-a]
|
||
@end example
|
||
|
||
@end table
|
||
|
||
|
||
@node Arithmetic, I/O, Comparing Terms, Top
|
||
@section Arithmetic
|
||
Arithmetic expressions in YAP may use the following operators
|
||
or @i{evaluable predicates}:
|
||
|
||
@table @code
|
||
|
||
@item +@var{X}
|
||
The value of @var{X} itself.
|
||
|
||
@item -@var{X} [ISO]
|
||
Symmetric value.
|
||
|
||
@item @var{X}+@var{Y} [ISO]
|
||
Sum.
|
||
|
||
@item @var{X}-@var{Y} [ISO]
|
||
Difference.
|
||
|
||
@item @var{X}*@var{Y} [ISO]
|
||
Product.
|
||
|
||
@item @var{X}/@var{Y} [ISO]
|
||
Quotient.
|
||
|
||
@item @var{X}//@var{Y} [ISO]
|
||
Integer quotient.
|
||
|
||
@item @var{X} mod @var{Y} [ISO]
|
||
Integer remainder.
|
||
|
||
@item @var{X} rem @var{Y}
|
||
Integer remainder, the same as @code{mod}.
|
||
|
||
@item exp(@var{X}) [ISO]
|
||
Natural exponential.
|
||
|
||
@item log(@var{X}) [ISO]
|
||
Natural logarithm.
|
||
|
||
@item log10(@var{X})
|
||
Decimal logarithm.
|
||
|
||
@item sqrt(@var{X}) [ISO]
|
||
Square root.
|
||
|
||
@item sin(@var{X}) [ISO]
|
||
Sine.
|
||
|
||
@item cos(@var{X}) [ISO]
|
||
Cosine.
|
||
|
||
@item tan(@var{X})
|
||
Tangent.
|
||
|
||
@item asin(@var{X})
|
||
Arc sine.
|
||
|
||
@item acos(@var{X})
|
||
Arc cosine.
|
||
|
||
@item atan(@var{X}) [ISO]
|
||
Arc tangent.
|
||
|
||
@item atan2(@var{X})
|
||
Four-quadrant arc tangent.
|
||
|
||
@item sinh(@var{X})
|
||
Hyperbolic sine.
|
||
|
||
@item cosh(@var{X})
|
||
Hyperbolic cosine.
|
||
|
||
@item tanh(@var{X})
|
||
Hyperbolic tangent.
|
||
|
||
@item asinh(@var{X})
|
||
Hyperbolic arc sine.
|
||
|
||
@item acosh(@var{X})
|
||
Hyperbolic arc cosine.
|
||
|
||
@item atanh(@var{X})
|
||
Hyperbolic arc tangent.
|
||
|
||
@item integer(@var{X}) [ISO]
|
||
If @var{X} evaluates to a float, the integer between the value of @var{X}
|
||
and 0 closest to the value of @var{X}, else if @var{X} evaluates to an
|
||
integer, the value of @var{X}.
|
||
|
||
@item float(@var{X}) [ISO]
|
||
If @var{X} evaluates to an integer, the corresponding float, else the float
|
||
itself.
|
||
|
||
@item float_fractional_part(@var{X}) [ISO]
|
||
The fractional part of the floating point number @var{X}, or @code{0.0}
|
||
if @var{X} is an integer. In the @code{iso} language mode,
|
||
@var{X} must be an integer.
|
||
|
||
@item float_integer_part(@var{X}) [ISO]
|
||
The float giving the integer part of the floating point number @var{X},
|
||
or @var{X} if @var{X} is an integer. In the @code{iso} language mode,
|
||
@var{X} must be an integer.
|
||
|
||
@item abs(@var{X}) [ISO]
|
||
The absolute value of @var{X}.
|
||
|
||
@item ceiling(@var{X}) [ISO]
|
||
The float that is the smallest integral value not smaller than @var{X}.
|
||
|
||
In @code{iso} language mode the argument must be a floating
|
||
point-number and the result is an integer.
|
||
|
||
@item floor(@var{X}) [ISO]
|
||
The float that is the greatest integral value not greater than @var{X}.
|
||
|
||
In @code{iso} language mode the argument must be a floating
|
||
point-number and the result is an integer.
|
||
|
||
@item round(@var{X}) [ISO]
|
||
The nearest integral value to @var{X}. If @var{X} is
|
||
equidistant to two integers, it will be rounded to the closest even
|
||
integral value.
|
||
|
||
In @code{iso} language mode the argument must be a floating
|
||
point-number, the result is an integer and it the float is equidistant
|
||
it is rounded up, that is, to the least integer greater than @var{X}.
|
||
|
||
@item sign(@var{X}) [ISO]
|
||
Return 1 if the @var{X} evaluates to a positive integer, 0 it if
|
||
evaluates to 0, and -1 if it evaluates to a negative integer. If @var{X}
|
||
evaluates to a floating-point number return 1.0 for a positive @var{X},
|
||
0.0 for 0.0, and -1.0 otherwise.
|
||
|
||
@item truncate(@var{X})
|
||
The float that is the integral value between @var{X} and 0 closest to
|
||
@var{X}.
|
||
|
||
@item max(@var{X},@var{Y})
|
||
The greater value of @var{X} and @var{Y}.
|
||
|
||
@item min(@var{X},@var{Y})
|
||
The lesser value of @var{X} and @var{Y}.
|
||
|
||
@item @var{X} ^ @var{Y}
|
||
@var{X} raised to the power of @var{Y}, (from the C-Prolog syntax).
|
||
|
||
@item exp(@var{X},@var{Y})
|
||
@var{X} raised to the power of @var{Y}, (from the Quintus Prolog syntax).
|
||
|
||
@item @var{X} ** @var{Y} [ISO]
|
||
@var{X} raised to the power of @var{Y} (from ISO).
|
||
|
||
@item @var{X} /\ @var{Y} [ISO]
|
||
Integer bitwise conjunction.
|
||
|
||
@item @var{X} \/ @var{Y} [ISO]
|
||
Integer bitwise disjunction.
|
||
|
||
@item @var{X} # @var{Y} [ISO]
|
||
Integer bitwise exclusive disjunction.
|
||
|
||
@item @var{X} << @var{Y}
|
||
Integer bitwise left logical shift of @var{X} by @var{Y} places.
|
||
|
||
@item @var{X} >> @var{Y} [ISO]
|
||
Integer bitwise right logical shift of @var{X} by @var{Y} places.
|
||
|
||
@item \ @var{X} [ISO]
|
||
Integer bitwise negation.
|
||
|
||
@item gcd(@var{X},@var{Y})
|
||
The greatest common divisor of the two integers @var{X} and @var{Y}.
|
||
|
||
@item msb(@var{X})
|
||
The most significant bit of the integer @var{X}.
|
||
|
||
@item [@var{X}]
|
||
Evaluates to @var{X} for expression @var{X}. Useful because character
|
||
strings in Prolog are lists of character codes.
|
||
|
||
@example
|
||
X is Y*10+C-"0"
|
||
@end example
|
||
@noindent
|
||
is the same as
|
||
@example
|
||
X is Y*10+C-[48].
|
||
@end example
|
||
@noindent
|
||
which would be evaluated as:
|
||
@example
|
||
X is Y*10+C-48.
|
||
@end example
|
||
|
||
@end table
|
||
|
||
Besides numbers and the arithmetic operators described above, certain
|
||
atoms have a special meaning when present in arithmetic expressions:
|
||
|
||
@table @code
|
||
@item pi
|
||
The value of @emph{pi}, the ratio of a circle's circumrefence to its
|
||
diameter.
|
||
|
||
@item e
|
||
The base of the natural logarithms.
|
||
|
||
@item inf
|
||
Infinity according to the IEEE Floating-Point standard. Note that
|
||
evaluating this term will generate a domain error in the @code{iso}
|
||
language mode.
|
||
|
||
@item nan
|
||
Not-a-number according to the IEEE Floating-Point standard. Note that
|
||
evaluating this term will generate a domain error in the @code{iso}
|
||
language mode.
|
||
|
||
@item cputime
|
||
CPU time in seconds, since YAP was invoked.
|
||
|
||
@item heapused
|
||
Heap space used, in bytes.
|
||
|
||
@item local
|
||
Local stack in use, in bytes.
|
||
|
||
@item global
|
||
Global stack in use, in bytes.
|
||
|
||
@item random
|
||
A "random" floating point number between 0 and 1.
|
||
|
||
@end table
|
||
|
||
The primitive YAP predicates involving arithmetic expressions are:
|
||
|
||
@table @code
|
||
|
||
@item @var{X} is +@var{Y} [2]
|
||
@findex is/2
|
||
@syindex is/2
|
||
@caindex is/2
|
||
This predicate succeeds iff the result of evaluating the expression
|
||
@var{Y} unifies with @var{X}. This is the predicate normally used to
|
||
perform evaluation of arithmetic expressions:
|
||
|
||
@example
|
||
X is 2+3*4
|
||
@end example
|
||
@noindent
|
||
succeeds with @code{X = 14}.
|
||
|
||
@item +@var{X} < +@var{Y} [ISO]
|
||
@findex </2
|
||
@syindex </2
|
||
@cyindex </2
|
||
The value of the expression @var{X} is less than the value of expression
|
||
@var{Y}.
|
||
|
||
@item +@var{X} =< +@var{Y} [ISO]
|
||
@findex =</2
|
||
@syindex =</2
|
||
@cyindex =</2
|
||
The value of the expression @var{X} is less than or equal to the value
|
||
of expression @var{Y}.
|
||
|
||
|
||
@item +@var{X} > +@var{Y} [ISO]
|
||
@findex >/2
|
||
@syindex >/2
|
||
@cyindex >/2
|
||
The value of the expression @var{X} is greater than the value of
|
||
expression @var{Y}.
|
||
|
||
@item +@var{X} >= +@var{Y} [ISO]
|
||
@findex >=/2
|
||
@syindex >=/2
|
||
@cyindex >=/2
|
||
The value of the expression @var{X} is greater than or equal to the
|
||
value of expression @var{Y}.
|
||
|
||
@item +@var{X} =:= +@var{Y} [ISO]
|
||
@findex =:=/2
|
||
@syindex =:=/2
|
||
@cyindex =:=/2
|
||
The value of the expression @var{X} is equal to the value of expression
|
||
@var{Y}.
|
||
|
||
@item +@var{X} =\= +@var{Y} [ISO]
|
||
@findex =\=/2
|
||
@syindex =\=/2
|
||
@cyindex =\=/2
|
||
The value of the expression @var{X} is different from the value of
|
||
expression @var{Y}.
|
||
|
||
@item srandom(+@var{X})
|
||
@findex srandom/1
|
||
@snindex srandom/1
|
||
@cnindex srandom/1
|
||
Use the argument @var{X} as a new seed for YAP's random number
|
||
generator. The argument should be an integer, but floats are acceptable.
|
||
@end table
|
||
|
||
@noindent
|
||
@strong{Notes:}
|
||
|
||
@itemize @bullet
|
||
@item
|
||
In contrast to previous versions of Yap, Yap4 @emph{does not} convert
|
||
automatically between integers and floats.
|
||
@item
|
||
arguments to trigonometric functions are expressed in radians.
|
||
@item
|
||
if a (non-instantiated) variable occurs in an arithmetic expression
|
||
YAP will generate an exception. If no error handler is
|
||
available, execution will be thrown back to the top-level.
|
||
@end itemize
|
||
|
||
|
||
@node I/O, Database, Arithmetic, Top
|
||
@section I/O Predicates
|
||
|
||
Some of the I/O predicates described below will in certain conditions
|
||
provide error messages and abort only if the file_errors flag is set.
|
||
If this flag is cleared the same predicates will just fail. Details on
|
||
setting and clearing this flag are given under 7.7.
|
||
|
||
@menu
|
||
|
||
Subnodes of Input/Output
|
||
* Streams and Files:: Handling Streams and Files
|
||
* C-Prolog File Handling:: C-Prolog Compatible File Handling
|
||
* I/O of Terms:: Input/Output of terms
|
||
* I/O of Characters:: Input/Output of Characters
|
||
* I/O for Streams:: Input/Output using Streams
|
||
* C-Prolog to Terminal:: C-Prolog compatible Character I/O to terminal
|
||
* I/O Control:: Controlling your Input/Output
|
||
* Sockets:: Using Sockets from Yap
|
||
|
||
@end menu
|
||
|
||
@node Streams and Files, C-Prolog File Handling, , I/O
|
||
@subsection Handling Streams and Files
|
||
|
||
@table @code
|
||
|
||
@item open(+@var{F},+@var{M},-@var{S}) [ISO]
|
||
@findex open/3
|
||
@syindex open/3
|
||
@cnindex open/3
|
||
Opens the file with name @var{F} in mode @var{M} ('read', 'write' or
|
||
'append'), returning @var{S} unified with the stream name.
|
||
|
||
At most, there are 17 streams opened at the same time. Each stream is
|
||
either an input or an output stream but not both. There are always 3
|
||
open streams: @code{user_input} for reading, @code{user_output} for writing
|
||
and @code{user_error} for writing. If there is no ambiguity, the atoms
|
||
@code{user_input} and @code{user_output} may be referred to as @code{user}.
|
||
|
||
The @code{file_errors} flag controls whether errors are reported when in
|
||
mode 'read' or 'append' the file @var{F} does not exist or is not
|
||
readable, and whether in mode 'write' or 'append' the file is not
|
||
writable.
|
||
|
||
@item open(+@var{F},+@var{M},-@var{S},+@var{Opts}) [ISO]
|
||
@findex open/4
|
||
@saindex open/4
|
||
@cnindex open/4
|
||
Opens the file with name @var{F} in mode @var{M} ('read', 'write' or
|
||
'append'), returning @var{S} unified with the stream name, and following
|
||
these options:
|
||
|
||
@table @code
|
||
|
||
@item type(+@var{T})
|
||
Specify whether the stream is a @code{text} stream (default), or a
|
||
@code{binary} stream.
|
||
|
||
@item reposition(+@var{Bool})
|
||
Specify whether it is possible to reposition the stream (@code{true}), or
|
||
not (@code{false}). By default, YAP enables repositioning for all
|
||
files, except terminal files and sockets.
|
||
|
||
@item eof_action(+@var{Action})
|
||
Specify the action to take if attempting to input characters from a
|
||
stream where we have previously found an @code{end-of-file}. The possible
|
||
actions are @code{error}, that raises an error, @code{reset}, that tries to
|
||
reset the stream and is used for @code{tty} type files, and @code{eof_code},
|
||
which generates a new @code{end-of-file} (default for non-tty files).
|
||
|
||
@item alias(+@var{Name})
|
||
Specify an alias to the file. The alias @t{Name} must be an atom. The
|
||
alias can be used instead of the file descriptor for every operation
|
||
concerning the file.
|
||
|
||
The operation will fail and give an error if the alias name is already
|
||
in use. YAP allows several aliases for the same file, but only
|
||
one is returned by @code{stream_property/2}
|
||
@end table
|
||
|
||
@item close(+@var{S}) [ISO]
|
||
@findex close/1
|
||
@syindex close/1
|
||
@cyindex close/1
|
||
Closes the stream @var{S}. If @var{S} does not stand for a stream
|
||
currently opened an error is reported. The streams @code{user_input},
|
||
@code{user_output}, and @code{user_error} can never be closed.
|
||
|
||
By default, give a file name, @code{close/1} will also try to close a
|
||
corresponding open stream. This feature is not available in ISO or
|
||
SICStus languages mode and is deprecated.
|
||
|
||
@item close(+@var{S},+@var{O}) [ISO]
|
||
@findex close/2
|
||
@saindex close/2
|
||
@cnindex close/2
|
||
Closes the stream @var{S}, following options @var{O}.
|
||
|
||
The only valid options are @code{force(true)} and @code{force(false)}.
|
||
YAP currently ignores these options.
|
||
|
||
@item current_stream(@var{F},@var{M},@var{S})
|
||
@findex current_stream/3
|
||
@syindex current_stream/3
|
||
@cnindex current_stream/3
|
||
Defines the relation: The stream @var{S} is opened on the file @var{F}
|
||
in mode @var{M}. It might be used to obtain all open streams (by
|
||
backtracking) or to access the stream for a file @var{F} in mode
|
||
@var{M}, or to find properties for a stream @var{S}.
|
||
|
||
@item flush_output [ISO]
|
||
@findex flush_output/0
|
||
@syindex flush_output/0
|
||
@cnindex flush_output/0
|
||
Send all data in the output buffer to current output stream.
|
||
|
||
@item flush_output(+@var{S}) [ISO]
|
||
@findex flush_output/1
|
||
@syindex flush_output/1
|
||
@cnindex flush_output/1
|
||
Send all data in the output buffer to stream @var{S}.
|
||
|
||
@item set_input(+@var{S})
|
||
@findex set_input/1
|
||
@syindex set_input/1
|
||
@cnindex set_input/1
|
||
Set stream @var{S} as the current input stream. Predicates like @code{read/1}
|
||
and @code{get/1} will start using stream @var{S}.
|
||
|
||
@item set_output(+@var{S})
|
||
@findex set_output/1
|
||
@syindex set_output/1
|
||
@cnindex set_output/1
|
||
Set stream @var{S} as the current output stream. Predicates like
|
||
@code{write/1} and @code{put/1} will start using stream @var{S}.
|
||
|
||
@item stream_select(+@var{STREAMS},+@var{TIMEOUT},-@var{READSTREAMS})
|
||
@findex stream_select/3
|
||
@syindex stream_select/3
|
||
@cnindex stream_select/3
|
||
Given a list of open @var{STREAMS} openeded in read mode and a @var{TIMEOUT}
|
||
return a list of streams who are now available for reading.
|
||
|
||
If the @var{TIMEOUT} is instantiated to @code{off},
|
||
@code{stream_select/3} will wait indefinitely for a stream to become
|
||
open. Otherwise the timeout must be of the form @code{SECS:USECS} where
|
||
@code{SECS} is an integer gives the number of seconds to wait for a timeout
|
||
and @code{USECS} adds the number of micro-seconds.
|
||
|
||
This built-in is only defined if the system call @code{select} is
|
||
available in the system.
|
||
|
||
@item current_input(-@var{S}) [ISO]
|
||
@findex current_input/1
|
||
@syindex current_input/1
|
||
@cnindex current_input/1
|
||
Unify @var{S} with the current input stream.
|
||
|
||
@item current_output(-@var{S}) [ISO]
|
||
@findex current_output/1
|
||
@syindex current_output/1
|
||
@cnindex current_output/1
|
||
Unify @var{S} with the current output stream.
|
||
|
||
@item at_end_of_stream [ISO]
|
||
@findex at_end_of_stream/0
|
||
@syindex at_end_of_stream/0
|
||
@cnindex at_end_of_stream/0
|
||
Succeed if the current stream has stream position end-of-stream or
|
||
past-end-of-stream.
|
||
|
||
@item at_end_of_stream(+@var{S}) [ISO]
|
||
@findex at_end_of_stream/1
|
||
@syindex at_end_of_stream/1
|
||
@cnindex at_end_of_stream/1
|
||
Succeed if the stream @var{S} has stream position end-of-stream or
|
||
past-end-of-stream. Note that @var{S} must be a readable stream.
|
||
|
||
@item set_stream_position(+@var{S}, +@var{POS}) [ISO]
|
||
@findex set_stream_position/2
|
||
@syindex set_stream_position/2
|
||
@cnindex set_stream_position/2
|
||
Given a stream position @var{POS} for a stream @var{S}, set the current
|
||
stream position for @var{S} to be @var{POS}.
|
||
|
||
@item stream_property(?@var{Stream},?@var{Prop}) [ISO]
|
||
@findex stream_property/2
|
||
@snindex stream_property/2
|
||
@cnindex stream_property/2
|
||
|
||
Obtain the properties for the open streams. If the first argument is
|
||
unbound, the procedure will backtrack through all open
|
||
streams. Otherwise, the first argument must be a stream term (you may
|
||
use @code{current_stream} to obtain a current stream given a file name).
|
||
|
||
The following properties are recognised:
|
||
|
||
@table @code
|
||
|
||
@item file_name(@var{P})
|
||
An atom giving the file name for the current stream. The file names are
|
||
@code{user_input}, @code{user_output}, and @code{user_error} for the
|
||
standard streams.
|
||
|
||
@item mode(@var{P})
|
||
The mode used to open the file. It may be one of @code{append},
|
||
@code{read}, or @code{write}.
|
||
|
||
@item input
|
||
The stream is readable.
|
||
|
||
@item output
|
||
The stream is writable.
|
||
|
||
@item alias(@var{A})
|
||
ISO-Prolog primitive for stream aliases. @t{Yap} returns one of the
|
||
existing aliases for the stream.
|
||
|
||
@item position(@var{P})
|
||
A term describing the position in the stream.
|
||
|
||
@item end_of_stream(@var{E})
|
||
Whether the stream is @code{at} the end of stream, or it has found the
|
||
end of stream and is @code{past}, or whether it has @code{not} yet
|
||
reached the end of stream.
|
||
|
||
@item eof_action(@var{A})
|
||
The action to take when trying to read after reaching the end of
|
||
stream. The action may be one of @code{error}, generate an error,
|
||
@code{eof_code}, return character code @code{-1}, or @code{reset} the
|
||
stream.
|
||
|
||
@item reposition(@var{B})
|
||
Whether the stream can be repositioned or not, that is, whether it is
|
||
seekable.
|
||
|
||
@item type(@var{T})
|
||
Whether the stream is a @code{text} stream or a @code{binary} stream.
|
||
|
||
@end table
|
||
|
||
@end table
|
||
|
||
@node C-Prolog File Handling, I/O of Terms, Streams and Files, I/O
|
||
@subsection Handling Streams and Files
|
||
|
||
@table @code
|
||
|
||
@item tell(+@var{S})
|
||
@findex tell/1
|
||
@syindex tell/1
|
||
@cyindex tell/1
|
||
If @var{S} is a currently opened stream for output, it becomes the
|
||
current output stream. If @var{S} is an atom it is taken to be a
|
||
filename. If there is no output stream currently associated with it,
|
||
then it is opened for output, and the new output stream created becomes
|
||
the current output stream. If it is not possible to open the file, an
|
||
error occurs. If there is a single opened output stream currently
|
||
associated with the file, then it becomes the current output stream; if
|
||
there are more than one in that condition, one of them is chosen.
|
||
|
||
Whenever @var{S} is a stream not currently opened for output, an error
|
||
may be reported, depending on the state of the file_errors flag. The
|
||
predicate just fails, if @var{S} is neither a stream nor an atom.
|
||
|
||
@item telling(-@var{S})
|
||
@findex telling/1
|
||
@syindex telling/1
|
||
@cyindex telling/1
|
||
The current output stream is unified with @var{S}.
|
||
|
||
@item told
|
||
@findex told/0
|
||
@syindex told/0
|
||
@cyindex told/0
|
||
Closes the current output stream, and the user's terminal becomes again
|
||
the current output stream. It is important to remember to close streams
|
||
after having finished using them, as the maximum number of
|
||
simultaneously opened streams is 17.
|
||
|
||
@item see(+@var{S})
|
||
@findex see/1
|
||
@syindex see/1
|
||
@cyindex see/1
|
||
If @var{S} is a currently opened input stream then it is assumed to be
|
||
the current input stream. If @var{S} is an atom it is taken as a
|
||
filename. If there is no input stream currently associated with it, then
|
||
it is opened for input, and the new input stream thus created becomes
|
||
the current input stream. If it is not possible to open the file, an
|
||
error occurs. If there is a single opened input stream currently
|
||
associated with the file, it becomes the current input stream; if there
|
||
are more than one in that condition, then one of them is chosen.
|
||
|
||
When @var{S} is a stream not currently opened for input, an error may be
|
||
reported, depending on the state of the @code{file_errors} flag. If
|
||
@var{S} is neither a stream nor an atom the predicates just fails.
|
||
|
||
@item seeing(-@var{S})
|
||
@findex seeing/1
|
||
@syindex seeing/1
|
||
@cyindex seeing/1
|
||
The current input stream is unified with @var{S}.
|
||
|
||
@item seen
|
||
@findex seen/0
|
||
@syindex seen/0
|
||
@cyindex seen/0
|
||
Closes the current input stream (see 6.7.).
|
||
|
||
@end table
|
||
|
||
@node I/O of Terms, I/O of Characters, C-Prolog File Handling, I/O
|
||
@subsection Handling Input/Output of Terms
|
||
|
||
@table @code
|
||
|
||
@item read(-@var{T}) [ISO]
|
||
@findex read/1
|
||
@syindex read/1
|
||
@cyindex read/1
|
||
Reads the next term from the current input stream, and unifies it with
|
||
@var{T}. The term must be followed by a dot ('.') and any blank-character
|
||
as previously defined. The syntax of the term must match the current
|
||
declarations for operators (see op). If the end-of-stream is reached,
|
||
@var{T} is unified with the atom @code{end_of_file}. Further reads from of
|
||
the same stream may cause an error failure (see @code{open/3}).
|
||
|
||
@item read_term(-@var{T},+@var{Options}) [ISO]
|
||
@findex read_term/2
|
||
@saindex read_term/2
|
||
@cnindex read_term/2
|
||
Reads term @var{T} from the current input stream with execution
|
||
controlled by the following options:
|
||
|
||
@table @code
|
||
|
||
@item singletons(-@var{Names})
|
||
@findex singletons/1 (read_term/2 option)
|
||
Unify @var{Names} with a list of the form @var{Name=Var}, where
|
||
@var{Name} is the name of a non-anonymous singleton variable in the
|
||
original term, and @code{Var} is the variable's representation in
|
||
YAP.
|
||
|
||
@item syntax_errors(+@var{Val})
|
||
@findex syntax_errors/1 (read_term/2 option)
|
||
Control action to be taken after syntax errors. See @code{yap_flag/2}
|
||
for detailed information.
|
||
|
||
@item variable_names(-@var{Names})
|
||
@findex variable_names/1 (read_term/2 option)
|
||
Unify @var{Names} with a list of the form @var{Name=Var}, where @var{Name} is
|
||
the name of a non-anonymous variable in the original term, and @var{Var}
|
||
is the variable's representation in YAP.
|
||
|
||
@item variables(-@var{Names})
|
||
@findex variables/1 (read_term/2 option)
|
||
Unify @var{Names} with a list of the variables in term @var{T}.
|
||
|
||
@end table
|
||
|
||
@item char_conversion(+@var{IN},+@var{OUT}) [ISO]
|
||
@findex char_conversion/2
|
||
@syindex char_conversion/2
|
||
@cnindex char_conversion/2
|
||
While reading terms convert unquoted occurrences of the character
|
||
@var{IN} to the character @var{OUT}. Both @var{IN} and @var{OUT} must be
|
||
bound to single characters atoms.
|
||
|
||
Character conversion only works if the flag @code{char_conversion} is
|
||
on. This is default in the @code{iso} and @code{sicstus} language
|
||
modes. As an example, character conversion can be used for instance to
|
||
convert characters from the ISO-LATIN-1 character set to ASCII.
|
||
|
||
If @var{IN} is the same character as @var{OUT}, @code{char_conversion/2}
|
||
will remove this conversion from the table.
|
||
|
||
@item current_char_conversion(?@var{IN},?@var{OUT}) [ISO]
|
||
@findex current_char_conversion/2
|
||
@syindex current_char_conversion/2
|
||
@cnindex current_char_conversion/2
|
||
If @var{IN} is unbound give all current character
|
||
translations. Otherwise, give the translation for @var{IN}, if one
|
||
exists.
|
||
|
||
@item write(@var{T}) [ISO]
|
||
@findex write/1
|
||
@syindex write/1
|
||
@cyindex write/1
|
||
The term @var{T} is written to the current output stream according to
|
||
the operator declarations in force.
|
||
|
||
@item display(+@var{T})
|
||
@findex display/1
|
||
@syindex display/1
|
||
@cyindex display/1
|
||
Displays term @var{T} on the current output stream. All Prolog terms are
|
||
written in standard parenthesized prefix notation.
|
||
|
||
@item write_canonical(+@var{T}) [ISO]
|
||
@findex display/1
|
||
@syindex display/1
|
||
@cnindex display/1
|
||
Displays term @var{T} on the current output stream. Atoms are quoted
|
||
when necessary, and operators are ignored, that is, the term is written
|
||
in standard parenthesized prefix notation.
|
||
|
||
@item write_term(+@var{T}, +@var{Opts}) [ISO]
|
||
@findex write_term/2
|
||
@syindex write_term/2
|
||
@cnindex write_term/2
|
||
Displays term @var{T} on the current output stream, according to the
|
||
following options:
|
||
|
||
@table @code
|
||
@item quoted(+@var{Bool})
|
||
If @code{true}, quote atoms if this would be necessary for the atom to
|
||
be recognised as an atom by YAP's parser. The default value is
|
||
@code{false}.
|
||
|
||
@item ignore_ops(+@var{Bool})
|
||
If @code{true}, ignore operator declarations when writing the term. The
|
||
default value is @code{false}.
|
||
|
||
@item numbervars(+@var{Bool})
|
||
If @code{true}, output terms of the form
|
||
@code{'$VAR'(N)}, where @var{N} is an integer, as a sequence of capital
|
||
letters. The default value is @code{false}.
|
||
|
||
@item portrayed(+@var{Bool})
|
||
If @code{true}, use @t{portray/1} to portray bound terms. The default
|
||
value is @code{false}.
|
||
|
||
@item max_depth(+@var{Depth})
|
||
If @code{Depth} is a positive integer, use @t{Depth} as
|
||
the maximum depth to portray a term. The default is @code{0}, that is,
|
||
unlimited depth.
|
||
|
||
@end table
|
||
|
||
@item writeq(@var{T}) [ISO]
|
||
@findex writeq/1
|
||
@syindex writeq/1
|
||
@cyindex writeq/1
|
||
Writes the term @var{T}, quoting names to make the result acceptable to
|
||
the predicate 'read' whenever necessary.
|
||
|
||
@item print(@var{T})
|
||
@findex print/1
|
||
@syindex print/1
|
||
@cyindex print/1
|
||
Prints the term @var{T} to the current output stream using @code{write/1}
|
||
unless T is bound and a call to the user-defined predicate
|
||
@code{portray/1} succeeds. To do pretty printing of terms the user should
|
||
define suitable clauses for @code{portray/1} and use @code{print/1}.
|
||
|
||
@item format(+@var{T},+@var{L})
|
||
@findex format/2
|
||
@saindex format/2
|
||
@cnindex format/2
|
||
Print formatted output to the current output stream. The arguments in
|
||
list @var{L} are output according to the string or atom @var{T}.
|
||
|
||
A control sequence is introduced by a @code{w}. The following control
|
||
sequences are available in YAP:
|
||
|
||
@table @code
|
||
|
||
@item '~~'
|
||
Print a single tilde.
|
||
|
||
@item '~a'
|
||
The next argument must be an atom, that will be printed as if by @code{write}.
|
||
|
||
@item '~Nc'
|
||
The next argument must be an integer, that will be printed as a
|
||
character code. The number @var{N} is the number of times to print the
|
||
character (default 1).
|
||
|
||
@item '~Ne'
|
||
@itemx '~NE'
|
||
@itemx '~Nf'
|
||
@itemx '~Ng'
|
||
@itemx '~NG'
|
||
The next argument must be a floating point number. The float @var{F}, the number
|
||
@var{N} and the control code @code{c} will be passed to @code{printf} as:
|
||
|
||
@example
|
||
printf("%s.Nc", F)
|
||
@end example
|
||
|
||
As an example:
|
||
|
||
@example
|
||
?- format("~8e, ~8E, ~8f, ~8g, ~8G~w",
|
||
[3.14,3.14,3.14,3.14,3.14,3.14]).
|
||
3.140000e+00, 3.140000E+00, 3.140000, 3.14, 3.143.14
|
||
@end example
|
||
|
||
@item '~Nd'
|
||
The next argument must be an integer, and @var{N} is the number of digits
|
||
after the decimal point. If @var{N} is @code{0} no decimal points will be
|
||
printed. The default is @var{N = 0}.
|
||
|
||
@example
|
||
?- format("~2d, ~d",[15000, 15000]).
|
||
150.00, 15000
|
||
@end example
|
||
|
||
@item '~ND'
|
||
Identical to @code{'~Nd'}, except that commas are used to separate groups
|
||
of three digits.
|
||
|
||
@example
|
||
?- format("~2D, ~D",[150000, 150000]).
|
||
1,500.00, 150,000
|
||
@end example
|
||
|
||
@item '~ND'
|
||
Identical to @code{'~Nd'}, except that @code{','} is used to separate groups
|
||
of three digits.
|
||
|
||
@example
|
||
?- format("~2D, ~D",[150000, 150000]).
|
||
1,500.00, 150,000
|
||
@end example
|
||
|
||
@item '~i'
|
||
Ignore the next argument in the list of arguments:
|
||
|
||
@example
|
||
?- format('The ~i met the boregrove',[mimsy]).
|
||
The met the boregrove
|
||
@end example
|
||
|
||
@item '~k'
|
||
Print the next argument with @code{write_canonical}:
|
||
|
||
@example
|
||
?- format("Good night ~k",a+[1,2]).
|
||
Good night +(a,[1,2])
|
||
@end example
|
||
|
||
@item '~Nn'
|
||
Print @var{N} newlines (where @var{N} defaults to 1).
|
||
|
||
@item '~NN'
|
||
Print @var{N} newlines if at the beginning of the line (where @var{N}
|
||
defaults to 1).
|
||
|
||
@item '~Nr'
|
||
The next argument must be an integer, and @var{N} is interpreted as a
|
||
radix, such that @code{2 <= N <= 36} (the default is 8).
|
||
|
||
@example
|
||
?- format("~2r, 0x~16r, ~r",
|
||
[150000, 150000, 150000]).
|
||
100100100111110000, 0x249f0, 444760
|
||
@end example
|
||
|
||
@noindent
|
||
Note that the letters @code{a-z} denote digits larger than 9.
|
||
|
||
@item '~NR'
|
||
Similar to '~NR'. The next argument must be an integer, and @var{N} is
|
||
interpreted as a radix, such that @code{2 <= N <= 36} (the default is 8).
|
||
|
||
@example
|
||
?- format("~2r, 0x~16r, ~r",
|
||
[150000, 150000, 150000]).
|
||
100100100111110000, 0x249F0, 444760
|
||
@end example
|
||
|
||
@noindent
|
||
The only difference is that letters @code{A-Z} denote digits larger than 9.
|
||
|
||
@item '~p'
|
||
Print the next argument with @code{print/1}:
|
||
|
||
@example
|
||
?- format("Good night ~p",a+[1,2]).
|
||
Good night a+[1,2]
|
||
@end example
|
||
|
||
@item '~q'
|
||
Print the next argument with @code{writeq/1}:
|
||
|
||
@example
|
||
?- format("Good night ~q",'Hello'+[1,2]).
|
||
Good night 'Hello'+[1,2]
|
||
@end example
|
||
|
||
@item '~Ns'
|
||
The next argument must be a list of character codes. The system then
|
||
outputs their representation as a string, where @var{N} is the maximum
|
||
number of characters for the string (@var{N} defaults to the length of the
|
||
string).
|
||
|
||
@example
|
||
?- format("The ~s are ~4s",["woods","lovely"]).
|
||
The woods are love
|
||
@end example
|
||
|
||
@item '~w'
|
||
Print the next argument with @code{writeq/1}:
|
||
|
||
@example
|
||
?- format("Good night ~w",'Hello'+[1,2]).
|
||
Good night Hello+[1,2]
|
||
@end example
|
||
|
||
@end table
|
||
|
||
The @code{format/2} built-in also allows for formatted output. One can
|
||
specify column boundaries and fill the intermediate space by a padding
|
||
character:
|
||
|
||
@table @code
|
||
@item '~N|'
|
||
Set a column boundary at position @var{N}, where @var{N} defaults to the
|
||
current position.
|
||
|
||
@item '~N+'
|
||
Set a column boundary at @var{N} characters past the current position, where
|
||
@var{N} defaults to @code{8}.
|
||
|
||
|
||
@item '~Nt'
|
||
Set padding for a column, where @var{N} is the fill code (default is
|
||
@key{SPC}).
|
||
|
||
@end table
|
||
|
||
The next example shows how to align columns and padding. We first show
|
||
left-alignment:
|
||
|
||
@example
|
||
|
||
@code{
|
||
?- format("~n*Hello~16+*~n",[]).
|
||
*Hello *
|
||
}
|
||
@end example
|
||
|
||
Note that we reserve 16 characters for the column.
|
||
|
||
The following example shows how to do right-alignment:
|
||
|
||
|
||
@example
|
||
@code{
|
||
?- format("*~tHello~16+*~n",[]).
|
||
* Hello*
|
||
}
|
||
|
||
@end example
|
||
|
||
|
||
The @code{~t} escape sequence forces filling before @code{Hello}.
|
||
|
||
We next show how to do centering:
|
||
|
||
@example
|
||
@code{
|
||
?- format("*~tHello~t~16+*~n",[]).
|
||
* Hello *
|
||
}
|
||
@end example
|
||
|
||
|
||
The two @code{~t} escape sequence force filling both before and after
|
||
@code{Hello}. Space is then evenly divided bewteen the right and the
|
||
left sides.
|
||
|
||
@item format(+@var{S},+@var{T},+@var{L})
|
||
@findex format/3
|
||
@saindex format/3
|
||
@cnindex format/3
|
||
Print formatted output to stream @var{S}.
|
||
|
||
|
||
@end table
|
||
|
||
@node I/O of Characters, I/O for Streams, I/O of Terms, I/O
|
||
@subsection Handling Input/Output of Characters
|
||
|
||
@table @code
|
||
|
||
@item put(+@var{N})
|
||
@findex put/1
|
||
@syindex put/1
|
||
@cyindex put/1
|
||
Outputs to the current output stream the character whose ASCII code is
|
||
@var{N}. The character @var{N} must be a legal ASCII character code, an
|
||
expression yielding such a code, or a list in which case only the first
|
||
element is used.
|
||
|
||
@item put_byte(+@var{N}) [ISO]
|
||
@findex put_byte/1
|
||
@snindex put_byte/1
|
||
@cnindex put_byte/1
|
||
Outputs to the current output stream the character whose code is
|
||
@var{N}. The current output stream must be a binary stream.
|
||
|
||
@item put_char(+@var{N}) [ISO]
|
||
@findex put_char/1
|
||
@snindex put_char/1
|
||
@cnindex put_char/1
|
||
Outputs to the current output stream the character who is used to build
|
||
the representation of atom @code{A}. The current output stream must be a
|
||
text stream.
|
||
|
||
@item put_code(+@var{N}) [ISO]
|
||
@findex put_code/1
|
||
@snindex put_code/1
|
||
@cnindex put_code/1
|
||
Outputs to the current output stream the character whose ASCII code is
|
||
@var{N}. The current output stream must be a text stream. The character
|
||
@var{N} must be a legal ASCII character code, an expression yielding such
|
||
a code, or a list in which case only the first element is used.
|
||
|
||
@item get(-@var{C})
|
||
@findex get/1
|
||
@syindex get/1
|
||
@cyindex get/1
|
||
The next non-blank character from the current input stream is unified
|
||
with @var{C}. Blank characters are the ones whose ASCII codes are not
|
||
greater than 32. If there are no more non-blank characters in the
|
||
stream, @var{C} is unified with -1. If @code{end_of_stream} has already
|
||
been reached in the previous reading, this call will give an error message.
|
||
|
||
@item get0(-@var{C})
|
||
@findex get0/1
|
||
@syindex get0/1
|
||
@cyindex get0/1
|
||
The next character from the current input stream is consumed, and then
|
||
unified with @var{C}. There are no restrictions on the possible
|
||
values of the ASCII code for the character, but the character will be
|
||
internally converted by YAP.
|
||
|
||
@item get_byte(-@var{C}) [ISO]
|
||
@findex get_byte/1
|
||
@snindex get_byte/1
|
||
@cnindex get_byte/1
|
||
If @var{C} is unbound, or is a character code, and the current stream is a
|
||
binary stream, read the next byte from the current stream and unify its
|
||
code with @var{C}.
|
||
|
||
@item get_char(-@var{C}) [ISO]
|
||
@findex get_char/1
|
||
@snindex get_char/1
|
||
@cnindex get_char/1
|
||
If @var{C} is unbound, or is an atom representation of a character, and
|
||
the current stream is a text stream, read the next character from the
|
||
current stream and unify its atom representation with @var{C}.
|
||
|
||
@item get_code(-@var{C}) [ISO]
|
||
@findex get_code/1
|
||
@snindex get_code/1
|
||
@cnindex get_code/1
|
||
If @var{C} is unbound, or is the code for a character, and
|
||
the current stream is a text stream, read the next character from the
|
||
current stream and unify its code with @var{C}.
|
||
|
||
@item peek_byte(-@var{C}) [ISO]
|
||
@findex peek_byte/1
|
||
@snindex peek_byte/1
|
||
@cnindex peek_byte/1
|
||
If @var{C} is unbound, or is a character code, and the current stream is a
|
||
binary stream, read the next byte from the current stream and unify its
|
||
code with @var{C}, while leaving the current stream position unaltered.
|
||
|
||
@item peek_char(-@var{C}) [ISO]
|
||
@findex peek_char/1
|
||
@syindex peek_char/1
|
||
@cnindex peek_char/1
|
||
If @var{C} is unbound, or is an atom representation of a character, and
|
||
the current stream is a text stream, read the next character from the
|
||
current stream and unify its atom representation with @var{C}, while
|
||
leaving the current stream position unaltered.
|
||
|
||
@item peek_code(-@var{C}) [ISO]
|
||
@findex peek_code/1
|
||
@snindex peek_code/1
|
||
@cnindex peek_code/1
|
||
If @var{C} is unbound, or is the code for a character, and
|
||
the current stream is a text stream, read the next character from the
|
||
current stream and unify its code with @var{C}, while
|
||
leaving the current stream position unaltered.
|
||
|
||
@item skip(+@var{N})
|
||
@findex skip/1
|
||
@syindex skip/1
|
||
@cyindex skip/1
|
||
Skips input characters until the next occurrence of the character with
|
||
ASCII code @var{N}. The argument to this predicate can take the same forms
|
||
as those for @code{put} (see 6.11).
|
||
|
||
@item tab(+@var{N})
|
||
@findex tab/1
|
||
@syindex tab/1
|
||
@cyindex tab/1
|
||
Outputs @var{N} spaces to the current output stream.
|
||
|
||
@item nl [ISO]
|
||
@findex nl/0
|
||
@syindex nl/0
|
||
@cyindex nl/0
|
||
Outputs a new line to the current output stream.
|
||
|
||
@end table
|
||
|
||
@node I/O for Streams, C-Prolog to Terminal, I/O of Characters, I/O
|
||
@subsection Input/Output Predicates applied to Streams
|
||
|
||
@table @code
|
||
|
||
@item read(+@var{S},-@var{T}) [ISO]
|
||
@findex read/2
|
||
@syindex read/2
|
||
@cnindex read/2
|
||
Reads term @var{T} from the stream @var{S} instead of from the current input
|
||
stream.
|
||
|
||
@item read_term(+@var{S},-@var{T},+@var{Options}) [ISO]
|
||
@findex read_term/3
|
||
@saindex read_term/3
|
||
@cnindex read_term/3
|
||
Reads term @var{T} from stream @var{S} with execution controlled by the
|
||
same options as @code{read_term/2}.
|
||
|
||
@item write(+@var{S},@var{T}) [ISO]
|
||
@findex write/2
|
||
@syindex write/2
|
||
@cnindex write/2
|
||
Writes term @var{T} to stream @var{S} instead of to the current output
|
||
stream.
|
||
|
||
@item write_canonical(+@var{S},+@var{T}) [ISO]
|
||
@findex display/1
|
||
@syindex display/1
|
||
@cnindex display/1
|
||
Displays term @var{T} on the stream @var{S}. Atoms are quoted when
|
||
necessary, and operators are ignored.
|
||
|
||
@item write_term(+@var{S}, +@var{T}, +@var{Opts}) [ISO]
|
||
@findex write_term/3
|
||
@syindex write_term/3
|
||
@cnindex write_term/3
|
||
Displays term @var{T} on the current output stream, according to the same
|
||
options used by @code{write_term/3}.
|
||
|
||
@item writeq(+@var{S},@var{T}) [ISO]
|
||
@findex writeq/2
|
||
@syindex writeq/2
|
||
@cnindex writeq/2
|
||
As @code{writeq/1}, but the output is sent to the stream @var{S}.
|
||
|
||
@item display(+@var{S},@var{T})
|
||
@findex display/2
|
||
@syindex display/2
|
||
@cnindex display/2
|
||
Like @code{display/1}, but using stream @var{S} to display the term.
|
||
|
||
@item print(+@var{S},@var{T})
|
||
@findex print/2
|
||
@syindex print/2
|
||
@cnindex print/2
|
||
Prints term @var{T} to the stream @var{S} instead of to the current output
|
||
stream.
|
||
|
||
@item put(+@var{S},+@var{N})
|
||
@findex put/2
|
||
@syindex put/2
|
||
@cnindex put/2
|
||
As @code{put(N)}, but to stream @var{S}.
|
||
|
||
@item put_byte(+@var{S},+@var{N}) [ISO]
|
||
@findex put_byte/2
|
||
@snindex put_byte/2
|
||
@cnindex put_byte/2
|
||
As @code{put_byte(N)}, but to binary stream @var{S}.
|
||
|
||
@item put_char(+@var{S},+@var{A}) [ISO]
|
||
@findex put_char/2
|
||
@snindex put_char/2
|
||
@cnindex put_char/2
|
||
As @code{put_char(A)}, but to text stream @var{S}.
|
||
|
||
@item put_code(+@var{S},+@var{N}) [ISO]
|
||
@findex put_code/2
|
||
@snindex put_code/2
|
||
@cnindex put_code/2
|
||
As @code{put_code(N)}, but to text stream @var{S}.
|
||
|
||
@item get(+@var{S},-@var{C})
|
||
@findex get/2
|
||
@syindex get/2
|
||
@cnindex get/2
|
||
The same as @code{get(C)}, but from stream @var{S}.
|
||
|
||
@item get0(+@var{S},-@var{C})
|
||
@findex get0/2
|
||
@syindex get0/2
|
||
@cnindex get0/2
|
||
The same as @code{get0(C)}, but from stream @var{S}.
|
||
|
||
@item get_byte(+@var{S},-@var{C}) [ISO]
|
||
@findex get_byte/2
|
||
@snindex get_byte/2
|
||
@cnindex get_byte/2
|
||
If @var{C} is unbound, or is a character code, and the stream @var{S} is a
|
||
binary stream, read the next byte from that stream and unify its
|
||
code with @var{C}.
|
||
|
||
@item get_char(+@var{S},-@var{C}) [ISO]
|
||
@findex get_char/2
|
||
@snindex get_char/2
|
||
@cnindex get_char/2
|
||
If @var{C} is unbound, or is an atom representation of a character, and
|
||
the stream @var{S} is a text stream, read the next character from that
|
||
stream and unify its representation as an atom with @var{C}.
|
||
|
||
@item get_code(+@var{S},-@var{C}) [ISO]
|
||
@findex get_code/2
|
||
@snindex get_code/2
|
||
@cnindex get_code/2
|
||
If @var{C} is unbound, or is a character code, and the stream @var{S} is a
|
||
text stream, read the next character from that stream and unify its
|
||
code with @var{C}.
|
||
|
||
@item peek_byte(+@var{S},-@var{C}) [ISO]
|
||
@findex peek_byte/2
|
||
@snindex peek_byte/2
|
||
@cnindex peek_byte/2
|
||
If @var{C} is unbound, or is a character code, and @var{S} is a binary
|
||
stream, read the next byte from the current stream and unify its code
|
||
with @var{C}, while leaving the current stream position unaltered.
|
||
|
||
@item peek_char(+@var{S},-@var{C}) [ISO]
|
||
@findex peek_char/2
|
||
@snindex peek_char/2
|
||
@cnindex peek_char/2
|
||
If @var{C} is unbound, or is an atom representation of a character, and
|
||
the stream @var{S} is a text stream, read the next character from that
|
||
stream and unify its representation as an atom with @var{C}, while leaving
|
||
the current stream position unaltered.
|
||
|
||
@item peek_code(+@var{S},-@var{C}) [ISO]
|
||
@findex peek_code/2
|
||
@snindex peek_code/2
|
||
@cnindex peek_code/2
|
||
If @var{C} is unbound, or is an atom representation of a character, and
|
||
the stream @var{S} is a text stream, read the next character from that
|
||
stream and unify its representation as an atom with @var{C}, while leaving
|
||
the current stream position unaltered.
|
||
|
||
@item skip(+@var{S},-@var{C})
|
||
@findex skip/2
|
||
@syindex skip/2
|
||
@cnindex skip/2
|
||
Like @code{skip/1}, but using stream @var{S} instead of the current
|
||
input stream.
|
||
|
||
@item tab(+@var{S},+@var{N})
|
||
@findex tab/2
|
||
@syindex tab/2
|
||
@cnindex tab/2
|
||
The same as @code{tab/1}, but using stream @var{S}.
|
||
|
||
@item nl(+@var{S})
|
||
@findex nl/1
|
||
@syindex nl/1
|
||
@cnindex nl/1
|
||
Outputs a new line to stream @var{S}.
|
||
|
||
@end table
|
||
|
||
@node C-Prolog to Terminal, I/O Control, I/O for Streams, I/O
|
||
@subsection Compatible C-Prolog predicates for Terminal I/O
|
||
|
||
@table @code
|
||
|
||
@item ttyput(+@var{N})
|
||
@findex ttyput/1
|
||
@syindex ttyput/1
|
||
@cnindex ttyput/1
|
||
As @code{put(N)} but always to @code{user_output}.
|
||
|
||
@item ttyget(-@var{C})
|
||
@findex ttyget/1
|
||
@syindex ttyget/1
|
||
@cnindex ttyget/1
|
||
The same as @code{get(C)}, but from stream @code{user_input}.
|
||
|
||
@item ttyget0(-@var{C})
|
||
@findex ttyget0/1
|
||
@syindex ttyget0/1
|
||
@cnindex ttyget0/1
|
||
The same as @code{get0(C)}, but from stream @code{user_input}.
|
||
|
||
@item ttyskip(-@var{C})
|
||
@findex ttyskip/1
|
||
@syindex ttyskip/1
|
||
@cnindex ttyskip/1
|
||
Like @code{skip/1}, but always using stream @code{user_input}.
|
||
stream.
|
||
|
||
@item ttytab(+@var{N})
|
||
@findex ttytab/1
|
||
@syindex ttytab/1
|
||
@cnindex ttytab/1
|
||
The same as @code{tab/1}, but using stream @code{user_output}.
|
||
|
||
@item ttynl
|
||
@findex ttynl/0
|
||
@syindex ttynl/0
|
||
@cnindex ttynl/0
|
||
Outputs a new line to stream @code{user_output}.
|
||
|
||
@end table
|
||
|
||
@node I/O Control, Sockets, C-Prolog to Terminal, I/O
|
||
@subsection Controlling Input/Output
|
||
|
||
@table @code
|
||
|
||
@item exists(+@var{F})
|
||
@findex exists/1
|
||
@snindex exists/1
|
||
@cyindex exists/1
|
||
Checks if file @var{F} exists in the current directory.
|
||
|
||
@item nofileerrors
|
||
@findex nofileerrors/0
|
||
@syindex nofileerrors/0
|
||
@cyindex nofileerrors/0
|
||
Switches off the file_errors flag, so that the predicates @code{see/1},
|
||
@code{tell/1}, @code{open/3} and @code{close/1} just fail, instead of producing
|
||
an error message and aborting whenever the specified file cannot be
|
||
opened or closed.
|
||
|
||
@item fileerrors
|
||
@findex fileerrors/0
|
||
@syindex fileerrors/0
|
||
@cyindex fileerrors/0
|
||
Switches on the file_errors flag so that in certain error conditions
|
||
I/O predicates will produce an appropriated message and abort.
|
||
|
||
@item write_depth(@var{T},@var{L})
|
||
@findex write_depth/2
|
||
@snindex write_depth/2
|
||
@cnindex write_depth/2
|
||
Unifies @var{T} and L, respectively, with the values of the maximum depth
|
||
of a term and the maximum length of a list, that will be used by
|
||
@code{write/1} or @code{write/2}. The default value for both arguments is 0,
|
||
meaning unlimited depth and length.
|
||
|
||
@example
|
||
?- write_depth(3,5).
|
||
yes
|
||
?- write(a(b(c(d(e(f(g))))))).
|
||
a(b(c(....)))
|
||
yes
|
||
?- write([1,2,3,4,5,6,7,8]).
|
||
[1,2,3,4,5,...]
|
||
yes
|
||
@end example
|
||
|
||
@item always_prompt_user
|
||
@findex always_prompt_user/0
|
||
@snindex always_prompt_user/0
|
||
@cnindex always_prompt_user/0
|
||
Force the system to prompt the user even if the @code{user_input} stream
|
||
is not a terminal. This command is useful if you want to obtain
|
||
interactive control from a pipe or a socket.
|
||
|
||
@end table
|
||
|
||
@node Sockets, , I/O Control, I/O
|
||
@subsection Using Sockets From Yap
|
||
|
||
YAP includes a SICStus Prolog compatible socket interface. This
|
||
is a low level interface that provides direct access to the major socket
|
||
system calls. These calls can be used both to open a new connection in
|
||
the network or connect to a networked server. Socket connections are
|
||
described as read/write streams, and standard I/O builtins can be used
|
||
to write on or read from sockets. The following calls are available:
|
||
|
||
@table @code
|
||
|
||
@item socket(+@var{DOMAIN},+@var{TYPE},+@var{PROTOCOL},-@var{SOCKET})
|
||
@findex socket/4
|
||
@syindex socket/4
|
||
@cnindex socket/4
|
||
Corresponds to the BSD system call @code{socket}. Create a socket for
|
||
domain @var{DOMAIN} of type @var{TYPE} and protocol
|
||
@var{PROTOCOL}. Both @var{DOMAIN} and @var{TYPE} should be atoms,
|
||
whereas @var{PROTOCOL} must be an integer. The new socket object is
|
||
accessible through a descriptor bound to the variable @var{SOCKET}.
|
||
|
||
The current implementation of YAP only accepts two socket
|
||
domains: @code{'AF_INET'} and @code{'AF_UNIX'}. Socket types depend on the
|
||
underlying operating system, but at least the following types are
|
||
supported: @code{'SOCK_STREAM'} and @code{'SOCK_DGRAM'}.
|
||
|
||
@item socket(+@var{DOMAIN},-@var{SOCKET})
|
||
@findex socket/2
|
||
@syindex socket/2
|
||
@cnindex socket/2
|
||
|
||
Call @code{socket/4} with @var{TYPE} bound to @code{'SOCK_STREAM'} and
|
||
@var{PROTOCOL} bound to @code{0}.
|
||
|
||
@item socket_close(+@var{SOCKET})
|
||
@findex socket_close/1
|
||
@syindex socket_close/1
|
||
@cnindex socket_close/1
|
||
|
||
Close socket @var{SOCKET}. Note that sockets used in
|
||
@code{socket_connet} (that is, client sockets) should not be closed with
|
||
@code{socket_close}, as they will be automatically closed when the
|
||
corresponding stream is closed with @code{close/1} or @code{close/2}.
|
||
|
||
@item socket_bind(+@var{SOCKET}, ?@var{PORT})
|
||
@findex socket_bind/2
|
||
@syindex socket_bind/2
|
||
@cnindex socket_bind/2
|
||
|
||
Interface to system call @code{bind}, as used for servers: bind socket
|
||
to a port. Port information depends on the domain:
|
||
@table @code
|
||
@item 'AF_UNIX'(+@var{FILENAME})
|
||
@item 'AF_FILE'(+@var{FILENAME})
|
||
use file name @var{FILENAME} for UNIX or local sockets.
|
||
|
||
@item 'AF_INET'(?@var{HOST},?PORT)
|
||
If @var{HOST} is bound to an atom, bind to host @var{HOST}, otherwise
|
||
if unbound bind to local host (@var{HOST} remains unbound). If port
|
||
@var{PORT} is bound to an integer, try to bind to the corresponding
|
||
port. If variable @var{PORT} is unbound allow operating systems to
|
||
choose a port number, which is unified with @var{PORT}.
|
||
|
||
@end table
|
||
|
||
@item socket_connect(+@var{SOCKET}, +@var{PORT}, -@var{STREAM})
|
||
@findex socket_connect/3
|
||
@syindex socket_connect/3
|
||
@cnindex socket_connect/3
|
||
|
||
Interface to system call @code{connect}, used for clients: connect
|
||
socket @var{SOCKET} to @var{PORT}. The connection results in the
|
||
read/write stream @var{STREAM}.
|
||
|
||
Port information depends on the domain:
|
||
@table @code
|
||
@item 'AF_UNIX'(+@var{FILENAME})
|
||
@item 'AF_FILE'(+@var{FILENAME})
|
||
connect to socket at file @var{FILENAME}.
|
||
|
||
@item 'AF_INET'(+@var{HOST},+@var{PORT})
|
||
Connect to socket at host @var{HOST} and port @var{PORT}.
|
||
@end table
|
||
|
||
@item socket_listen(+@var{SOCKET}, +@var{LENGTH})
|
||
@findex socket_listen/2
|
||
@syindex socket_listen/2
|
||
@cnindex socket_listen/2
|
||
Interface to system call @code{listen}, used for servers to indicate
|
||
willingness to wait for connections at socket @var{SOCKET}. The
|
||
integer @var{LENGTH} gives the queue limit for incoming connections,
|
||
and should be limited to @code{5} for portable applications. The socket
|
||
must be of type @code{SOCK_STREAM} or @code{SOCK_SEQPACKET}.
|
||
|
||
@item socket_accept(+@var{SOCKET}, -@var{STREAM})
|
||
@findex socket_accept/2
|
||
@syindex socket_accept/2
|
||
@cnindex socket_accept/2
|
||
|
||
@item socket_accept(+@var{SOCKET}, -@var{CLIENT}, -@var{STREAM})
|
||
@findex socket_accept/3
|
||
@syindex socket_accept/3
|
||
@cnindex socket_accept/3
|
||
Interface to system call @code{accept}, used for servers to wait for
|
||
connections at socket @var{SOCKET}. The stream descriptor @var{STREAM}
|
||
represents the resulting connection. If the socket belongs to the
|
||
domain @code{'AF_INET'}, @var{CLIENT} unifies with an atom containing
|
||
the IP address for the client in numbers and dots notation.
|
||
|
||
@item socket_accept(+@var{SOCKET}, -@var{STREAM})
|
||
@findex socket_accept/2
|
||
@syindex socket_accept/2
|
||
@cnindex socket_accept/2
|
||
Accept a connection but do not return client information.
|
||
|
||
@item socket_select(+@var{SOCKETS}, -@var{NEWSTREAMS}, +@var{TIMEOUT}, +@var{STREAMS}, -@var{READSTREAMS})
|
||
@findex socket_select/5
|
||
@syindex socket_select/5
|
||
@cnindex socket_select/5
|
||
Interface to system call @code{select}, used for servers to wait for
|
||
connection requests or for data at sockets. The variable
|
||
@var{SOCKETS} is a list of form @var{KEY-SOCKET}, where @var{KEY} is
|
||
an user-defined identifier and @var{SOCKET} is a socket descriptor. The
|
||
variable @var{TIMEOUT} is either @code{off}, indicating execution will
|
||
wait until something is available, or of the form @var{SEC-USEC}, where
|
||
@var{SEC} and @var{USEC} give the seconds and microseconds before
|
||
@code{socket_select/5} returns. The variable @var{SOCKETS} is a list of
|
||
form @var{KEY-STREAM}, where @var{KEY} is an user-defined identifier
|
||
and @var{STREAM} is a stream descriptor
|
||
|
||
Execution of @code{socket_select/5} unifies @var{READSTREAMS} from
|
||
@var{STREAMS} with readable data, and @var{NEWSTREAMS} with a list of
|
||
the form @var{KEY-STREAM}, where @var{KEY} was the key for a socket
|
||
with pending data, and @var{STREAM} the stream descriptor resulting
|
||
from accepting the connection.
|
||
|
||
@item current_hostname(?@var{HOSTNAME})
|
||
Unify @var{HOSTNAME} with an atom representing the fully qualified
|
||
hostname for the current host. Also succeeds if @var{HOSTNAME} is bound
|
||
to the unqualified hostname.
|
||
|
||
@item hostname_address(?@var{HOSTNAME},?@var{IP_ADDRESS})
|
||
@var{HOSTNAME} is an host name and @var{IP_ADDRESS} its IP
|
||
address in number and dots notation.
|
||
|
||
|
||
@end table
|
||
|
||
@node Database, Sets, I/O, Top
|
||
@section Using the Clausal Data Base
|
||
|
||
Predicates in YAP may be dynamic or static. By default, when
|
||
consulting or reconsulting, predicates are assumed to be static:
|
||
execution is faster and the code will probably use less space.
|
||
Static predicates impose some restrictions: in general there can be no
|
||
addition or removal of clauses for a procedure if it is being used in the
|
||
current execution.
|
||
|
||
Dynamic predicates allow programmers to change the Clausal Data Base with
|
||
the same flexibility as in C-Prolog. With dynamic predicates it is
|
||
always possible to add or remove clauses during execution and the
|
||
semantics will be the same as for C-Prolog. But the programmer should be
|
||
aware of the fact that asserting or retracting are still expensive operations,
|
||
and therefore he should try to avoid them whenever possible.
|
||
|
||
@table @code
|
||
|
||
@item dynamic +@var{P}
|
||
@findex dynamic/1
|
||
@saindex dynamic/1
|
||
@cnindex dynamic/1
|
||
Declares predicate @var{P} or list of predicates [@var{P1},...,@var{Pn}]
|
||
as a dynamic predicate. @var{P} must be written in form:
|
||
@var{name/arity}.
|
||
|
||
@example
|
||
:- dynamic god/1.
|
||
@end example
|
||
|
||
@noindent
|
||
a more convenient form can be used:
|
||
|
||
@example
|
||
:- dynamic son/3, father/2, mother/2.
|
||
@end example
|
||
|
||
or, equivalently,
|
||
|
||
@example
|
||
:- dynamic [son/3, father/2, mother/2].
|
||
@end example
|
||
|
||
@noindent
|
||
Note:
|
||
|
||
a predicate is assumed to be dynamic when
|
||
asserted before being defined.
|
||
|
||
@item dynamic_predicate(+@var{P},+@var{Semantics})
|
||
@findex dynamic_predicate/2
|
||
@snindex dynamic_predicate/2
|
||
@cnindex dynamic_predicate/2
|
||
Declares predicate @var{P} or list of predicates [@var{P1},...,@var{Pn}]
|
||
as a dynamic predicate following either @code{logical} or
|
||
@code{immediate} semantics.
|
||
|
||
@menu
|
||
|
||
Subnodes of Database
|
||
* Modifying the Database:: Asserting and Retracting
|
||
* Looking at the Database:: Finding out what is in the Data Base
|
||
* Database References:: Using Data Base References
|
||
* Internal Database:: Yap's Internal Database
|
||
* BlackBoard:: Storing and Fetching Terms in the BlackBoard
|
||
|
||
@end menu
|
||
|
||
@end table
|
||
|
||
@node Modifying the Database, Looking at the Database, , Database
|
||
@subsection Modification of the Data Base
|
||
|
||
These predicates can be used either for static or for dynamic
|
||
predicates:
|
||
|
||
@table @code
|
||
|
||
@item assert(+@var{C})
|
||
@findex assert/1
|
||
@saindex assert/1
|
||
@caindex assert/1
|
||
Adds clause @var{C} to the program. If the predicate is undefined,
|
||
declare it as dynamic.
|
||
|
||
Most Prolog systems only allow asserting clauses for dynamic
|
||
predicates. This is also as specified in the ISO standard. YAP allows
|
||
asserting clauses for static predicates, as long as the predicate is not
|
||
in use and the language flag is @t{cprolog}. Note that this feature is
|
||
deprecated, if you want to assert clauses for static procedures you
|
||
should use @code{assert_static/1}.
|
||
|
||
@item asserta(+@var{C}) [ISO]
|
||
@findex asserta/1
|
||
@saindex asserta/1
|
||
@caindex asserta/1
|
||
Adds clause @var{C} to the beginning of the program. If the predicate is
|
||
undefined, declare it as dynamic.
|
||
|
||
@item assertz(+@var{C}) [ISO]
|
||
@findex assertz/1
|
||
@saindex assertz/1
|
||
@caindex assertz/1
|
||
Adds clause @var{C} to the end of the program. If the predicate is
|
||
undefined, declare it as dynamic.
|
||
|
||
Most Prolog systems only allow asserting clauses for dynamic
|
||
predicates. This is also as specified in the ISO
|
||
standard. YAP allows asserting clauses for static predicates,
|
||
as long as the predicate is not in use. The current version of
|
||
YAP supports this feature, but this feature is deprecated and
|
||
support may go away in future versions.
|
||
|
||
@item abolish(+@var{PredSpec}) [ISO]
|
||
@findex abolish/1
|
||
@saindex abolish/1
|
||
@caindex abolish/1
|
||
Deletes the predicate given by @var{PredSpec} from the database. If
|
||
@var{PredSpec} is an unbound variable, delete all predicates for the
|
||
current module. The
|
||
specification must include the name and arity, and it may include module
|
||
information. Under @t{iso} language mode this builtin will only abolish
|
||
dynamic procedures. Under other modes it will abolish any procedures, as
|
||
long as they are not currently in use.
|
||
|
||
@item abolish(+@var{P},+@var{N})
|
||
@findex abolish/2
|
||
@saindex abolish/2
|
||
@caindex abolish/2
|
||
Deletes the predicate with name @var{P} and arity @var{N}. It will remove
|
||
both static and dynamic predicates.
|
||
|
||
@item assert_static(+@var{C})
|
||
@findex assert_static/1
|
||
@snindex assert_static/1
|
||
@cnindex assert_static/1
|
||
Adds clause @var{C} to a static procedure.
|
||
|
||
@item asserta_static(+@var{C})
|
||
@findex asserta_static/1
|
||
@snindex asserta_static/1
|
||
@cnindex asserta_static/1
|
||
Adds clause @var{C} to the beginning of a static procedure. Note that
|
||
the operation may fail if pointers to the procedure are in the stacks.
|
||
|
||
@item assertz_static(+@var{C})
|
||
@findex assertz_static/1
|
||
@snindex assertz_static/1
|
||
@cnindex assertz_static/1
|
||
Adds clause @var{C} to the end of a static procedure. Note that
|
||
the operation may fail if pointers to the procedure are in the stacks.
|
||
|
||
@end table
|
||
|
||
The following predicate can be used for dynamic predicates and for static
|
||
predicates, but only if source mode was on when they were compiled:
|
||
|
||
@table @code
|
||
|
||
@item clause(+@var{H},@var{B}) [ISO]
|
||
@findex clause/2
|
||
@saindex clause/2
|
||
@caindex clause/2
|
||
A clause whose head matches @var{H} is searched for in the
|
||
program. Its head and body are respectively unified with @var{H} and
|
||
@var{B}. If the clause is a unit clause, @var{B} is unified with
|
||
@var{true}.
|
||
|
||
This predicate is applicable to static procedures compiled with
|
||
@code{source} active, and to all the dynamic procedures.
|
||
|
||
@end table
|
||
|
||
The following predicate can only be used for dynamic predicates:
|
||
|
||
@table @code
|
||
|
||
@item retract(+@var{C}) [ISO]
|
||
@findex retract/1
|
||
@saindex retract/1
|
||
@cnindex retract/1
|
||
Erases the first clause in the program that matches @var{C}. This
|
||
predicate may also be used for the static predicates that have been
|
||
compiled when the source mode was @code{on}. For more information on
|
||
@code{source/0} (@pxref{Setting the Compiler}).
|
||
|
||
@item retractall(+@var{G})
|
||
@findex retractall/1
|
||
@saindex retractall/1
|
||
@cnindex retractall/1
|
||
Retract all the clauses whose head matches the goal @var{G}. Goal
|
||
@var{G} must be a call to a dynamic predicate.
|
||
|
||
@end table
|
||
|
||
@node Looking at the Database, Database References, Modifying the Database, Database
|
||
@subsection Looking at the Data Base
|
||
|
||
@table @code
|
||
|
||
@item listing
|
||
@findex listing/0
|
||
@saindex listing/0
|
||
@caindex listing/0
|
||
Lists in the current output stream all the clauses for which source code
|
||
is available (these include all clauses for dynamic predicates and
|
||
clauses for static predicates compiled when source mode was @code{on}).
|
||
|
||
@item listing +@var{P}
|
||
@findex listing/1
|
||
@syindex listing/1
|
||
@caindex listing/1
|
||
Lists predicate @var{P} if its source code is available.
|
||
|
||
@item portray_clause(+@var{C})
|
||
@findex portray_clause/1
|
||
@syindex portray_clause/1
|
||
@cnindex portray_clause/1
|
||
Write clause @var{C} as if written by @code{listing/0}.
|
||
|
||
@item portray_clause(+@var{S},+@var{C})
|
||
@findex portray_clause/2
|
||
@syindex portray_clause/2
|
||
@cnindex portray_clause/2
|
||
Write clause @var{C} on stream @var{S} as if written by @code{listing/0}.
|
||
|
||
@item current_atom(@var{A})
|
||
@findex current_atom/1
|
||
@syindex current_atom/1
|
||
@cyindex current_atom/1
|
||
Checks whether @var{A} is a currently defined atom. It is used to find all
|
||
currently defined atoms by backtracking.
|
||
|
||
@item current_predicate(@var{F}) [ISO]
|
||
@findex current_predicate/1
|
||
@syindex current_predicate/1
|
||
@cyindex current_predicate/1
|
||
@var{F} is the predicate indicator for a currently defined user or
|
||
library predicate. @var{F} is of the form @var{Na/Ar}, where the atom
|
||
@var{Na} is the name of the predicate, and @var{Ar} its arity.
|
||
|
||
@item current_predicate(@var{A},@var{P})
|
||
@findex current_predicate/2
|
||
@syindex current_predicate/2
|
||
@cnindex current_predicate/2
|
||
Defines the relation: @var{P} is a currently defined predicate whose
|
||
name is the atom @var{A}.
|
||
|
||
@item system_predicate(@var{A},@var{P})
|
||
@findex system_predicate/2
|
||
@syindex system_predicate/2
|
||
@cnindex system_predicate/2
|
||
Defines the relation: @var{P} is a built-in predicate whose name
|
||
is the atom @var{A}.
|
||
|
||
@item predicate_property(@var{P},@var{Prop})
|
||
@findex predicate_property/2
|
||
@saindex predicate_property/2
|
||
@cnindex predicate_property/2
|
||
For the predicates obeying the specification @var{P} unify @var{Prop}
|
||
with a property of @var{P}. These properties may be:
|
||
@table @code
|
||
@item built_in
|
||
true for built-in predicates,
|
||
@item dynamic
|
||
true if the predicate is dynamic
|
||
@item static
|
||
true if the predicate is static
|
||
@item meta_predicate(@var{M})
|
||
true if the predicate has a meta_predicate declaration @var{M}.
|
||
@item multifile
|
||
true if the predicate was declared to be multifile
|
||
@item imported_from(@var{Mod})
|
||
true if the predicate was imported from module @var{Mod}.
|
||
@item exported
|
||
true if the predicate is exported in the current module.
|
||
@item public
|
||
true if the predicate is public; note that all dynamic predicates are
|
||
public.
|
||
@end table
|
||
|
||
@end table
|
||
|
||
@node Database References, Internal Database, Looking at the Database, Database
|
||
@subsection Using Data Base References
|
||
|
||
Data Base references are a fast way of accessing terms. The predicates
|
||
@code{erase/1} and @code{instance/1} also apply to these references and may
|
||
sometimes be used instead of @code{retract/1} and @code{clause/2}.
|
||
|
||
@table @code
|
||
|
||
@item assert(+@var{C},-@var{R})
|
||
@findex assert/2
|
||
@saindex assert/2
|
||
@caindex assert/2
|
||
The same as @code{assert(C)} (@pxref{Modifying the Database}) but
|
||
unifies @var{R} with the database reference that identifies the new
|
||
clause, in a one-to-one way. Note that @code{asserta/2} only works for dynamic
|
||
predicates. If the predicate is undefined, it will automatically be
|
||
declared dynamic.
|
||
|
||
@item asserta(+@var{C},-@var{R})
|
||
@findex asserta/2
|
||
@saindex asserta/2
|
||
@caindex asserta/2
|
||
The same as @code{asserta(C)} but unifying @var{R} with
|
||
the database reference that identifies the new clause, in a
|
||
one-to-one way. Note that @code{asserta/2} only works for dynamic
|
||
predicates. If the predicate is undefined, it will automatically be
|
||
declared dynamic.
|
||
|
||
@item assertz(+@var{C},-@var{R})
|
||
@findex assertz/2
|
||
@saindex assertz/2
|
||
@caindex assertz/2
|
||
The same as @code{assertz(C)} but unifying @var{R} with
|
||
the database reference that identifies the new clause, in a
|
||
one-to-one way. Note that @code{asserta/2} only works for dynamic
|
||
predicates. If the predicate is undefined, it will automatically be
|
||
declared dynamic.
|
||
|
||
@item retract(+@var{C},-@var{R})
|
||
@findex retract/2
|
||
@saindex retract/2
|
||
@caindex retract/2
|
||
Erases from the program the clause @var{C} whose
|
||
database reference is @var{R}.
|
||
|
||
|
||
@item clause(+H,B,-@var{R})
|
||
@findex clause/3
|
||
@saindex clause/3
|
||
@caindex clause/3
|
||
The same as @code{clause(H,B)} but @var{R} is unified with the
|
||
reference to the clause in the database.
|
||
|
||
@end table
|
||
|
||
@node Internal Database, BlackBoard, Database References, Database
|
||
@section Internal Data Base
|
||
Some programs need global information for, eg., counting or collecting
|
||
data obtained by backtracking. As a rule, to keep this information, the
|
||
internal data base should be used instead of asserting and retracting
|
||
clauses (as most novice programmers do), .
|
||
In YAP (as in some other Prolog systems) the internal data base (i.d.b.
|
||
for short) is faster, needs less space and provides a better insulation of
|
||
program and data than using asserted/retracted clauses.
|
||
The i.d.b. is implemented as a set of terms, accessed by keys that
|
||
unlikely what happens in (non-Prolog) data bases are not part of the
|
||
term. Under each key a list of terms is kept. References are provided so that
|
||
terms can be identified: each term in the i.d.b. has a unique reference
|
||
(references are also available for clauses of dynamic predicates).
|
||
|
||
@table @code
|
||
|
||
@item recorda(+@var{K},@var{T},-@var{R})
|
||
@findex recorda/3
|
||
@saindex recorda/3
|
||
@cyindex recorda/3
|
||
Makes term @var{T} the first record under key @var{K} and unifies @var{R}
|
||
with its reference.
|
||
|
||
@item recordz(+@var{K},@var{T},-@var{R})
|
||
@findex recordz/3
|
||
@saindex recordz/3
|
||
@cyindex recordz/3
|
||
Makes term @var{T} the last record under key @var{K} and unifies @var{R}
|
||
with its reference.
|
||
|
||
@item recordaifnot(+@var{K},@var{T},-@var{R})
|
||
@findex recordaifnot/3
|
||
@saindex recordaifnot/3
|
||
@cnindex recordaifnot/3
|
||
If a term equal to @var{T} up to variable renaming is stored under key
|
||
@var{K} fail. Otherwise, make term @var{T} the first record under key
|
||
@var{K} and unify @var{R} with its reference.
|
||
|
||
@item recordzifnot(+@var{K},@var{T},-@var{R})
|
||
@findex recorda/3
|
||
@saindex recorda/3
|
||
@cnindex recorda/3
|
||
If a term equal to @var{T} up to variable renaming is stored under key
|
||
@var{K} fail. Otherwise, make term @var{T} the first record under key
|
||
@var{K} and unify @var{R} with its reference.
|
||
|
||
@item recorded(+@var{K},@var{T},@var{R})
|
||
@findex recorded/3
|
||
@saindex recorded/3
|
||
@cyindex recorded/3
|
||
Searches in the internal database under the key @var{K}, a term that
|
||
unifies with @var{T} and whose reference matches @var{R}.
|
||
|
||
@item erase(+@var{R})
|
||
@findex erase/1
|
||
@saindex erase/1
|
||
@cyindex erase/1
|
||
The term referred to by @var{R} is erased from the internal database. If
|
||
reference @var{R} does not exist in the database, @code{erase} just fails.
|
||
|
||
@item erased(+@var{R})
|
||
@findex erased/1
|
||
@saindex erased/1
|
||
@cyindex erased/1
|
||
Succeeds if the object whose database reference is @var{R} has been
|
||
erased.
|
||
|
||
@item instance(+@var{R},-@var{T})
|
||
@findex instance/2
|
||
@saindex instance/2
|
||
@cyindex instance/2
|
||
If @var{R} refers to a clause or a recorded term, @var{T} is unified
|
||
with its most general instance. If @var{R} refers to an unit clause
|
||
@var{C}, then @var{T} is unified with @code{@var{C} :- true}. When
|
||
@var{R} is not a reference to an existing clause or a recorded term,
|
||
this goal fails.
|
||
|
||
@item eraseall(+@var{R})
|
||
@findex eraseall/1
|
||
@snindex eraseall/1
|
||
@cnindex eraseall/1
|
||
All terms referred to by @var{R} are erased from the internal
|
||
database. If reference @var{R} does not exist in the database,
|
||
@code{eraseall} just fails.
|
||
|
||
@item current_key(@var{A},@var{P})
|
||
@findex current_key/2
|
||
@syindex current_key/2
|
||
@cnindex current_key/2
|
||
Defines the relation: @var{P} is a currently defined database key whose
|
||
name is the atom @var{A}.
|
||
|
||
@item get_value(+@var{A},-@var{V})
|
||
@findex get_value/2
|
||
@snindex get_value/2
|
||
@cnindex get_value/2
|
||
In YAP, atoms can be associated with constants. If one such
|
||
association exists for atom @var{A}, unify the second argument with the
|
||
constant. Otherwise, unify @var{V} with @code{[]}.
|
||
|
||
This predicate is YAP specific.
|
||
|
||
@item set_value(+@var{A},+@var{C})
|
||
@findex set_value/2
|
||
@snindex set_value/2
|
||
@cnindex set_value/2
|
||
Associate atom @var{A} with constant @var{C}.
|
||
|
||
The @code{set_value} and @code{get_value} built-ins give a fast alternative to
|
||
the internal data-base. This is a simple form of implementing a global
|
||
counter.
|
||
@example
|
||
read_and_increment_counter(Value) :-
|
||
get_value(counter, Value),
|
||
Value1 is Value+1,
|
||
set_value(counter, Value1).
|
||
@end example
|
||
@noindent
|
||
This predicate is YAP specific.
|
||
|
||
@item recordzifnot(+@var{K},@var{T},-@var{R})
|
||
@findex recordzifnot/3
|
||
@snindex recordzifnot/3
|
||
@cnindex recordzifnot/3
|
||
If a variant of @var{T} is stored under key @var{K} fail. Otherwise, make
|
||
term @var{T} the last record under key @var{K} and unify @var{R} with its
|
||
reference.
|
||
|
||
This predicate is YAP specific.
|
||
|
||
@item recordaifnot(+@var{K},@var{T},-@var{R})
|
||
@findex recordaifnot/3
|
||
@snindex recordaifnot/3
|
||
@cnindex recordaifnot/3
|
||
If a variant of @var{T} is stored under key @var{K} fail. Otherwise, make
|
||
term @var{T} the first record under key @var{K} and unify @var{R} with its
|
||
reference.
|
||
|
||
This predicate is YAP specific.
|
||
|
||
@end table
|
||
|
||
There is a strong analogy between the i.d.b. and the way dynamic
|
||
predicates are stored. In fact, the main i.d.b. predicates might be
|
||
implemented using dynamic predicates:
|
||
|
||
@example
|
||
recorda(X,T,R) :- asserta(idb(X,T),R).
|
||
recordz(X,T,R) :- assertz(idb(X,T),R).
|
||
recorded(X,T,R) :- clause(idb(X,T),R).
|
||
@end example
|
||
@noindent
|
||
We can take advantage of this, the other way around, as it is quite
|
||
easy to write a simple Prolog interpreter, using the i.d.b.:
|
||
|
||
@example
|
||
asserta(G) :- recorda(interpreter,G,_).
|
||
assertz(G) :- recordz(interpreter,G,_).
|
||
retract(G) :- recorded(interpreter,G,R), !, erase(R).
|
||
call(V) :- var(V), !, fail.
|
||
call((H :- B)) :- !, recorded(interpreter,(H :- B),_), call(B).
|
||
call(G) :- recorded(interpreter,G,_).
|
||
@end example
|
||
@noindent
|
||
In YAP, much attention has been given to the implementation of the
|
||
i.d.b., especially to the problem of accelerating the access to terms kept in
|
||
a large list under the same key. Besides using the key, YAP uses an internal
|
||
lookup function, transparent to the user, to find only the terms that might
|
||
unify. For instance, in a data base containing the terms
|
||
|
||
@example
|
||
b
|
||
b(a)
|
||
c(d)
|
||
e(g)
|
||
b(X)
|
||
e(h)
|
||
@end example
|
||
|
||
@noindent
|
||
stored under the key k/1, when executing the query
|
||
|
||
@example
|
||
:- recorded(k(_),c(_),R).
|
||
@end example
|
||
|
||
@noindent
|
||
@code{recorded} would proceed directly to the third term, spending almost the
|
||
time as if @code{a(X)} or @code{b(X)} was being searched.
|
||
The lookup function uses the functor of the term, and its first three
|
||
arguments (when they exist). So, @code{recorded(k(_),e(h),_)} would go
|
||
directly to the last term, while @code{recorded(k(_),e(_),_)} would find
|
||
first the fourth term, and then, after backtracking, the last one.
|
||
|
||
This mechanism may be useful to implement a sort of hierarchy, where
|
||
the functors of the terms (and eventually the first arguments) work as
|
||
secondary keys.
|
||
|
||
In the YAP's i.d.b. an optimized representation is used for
|
||
terms without free variables. This results in a faster retrieval of terms
|
||
and better space usage. Whenever possible, avoid variables in terms in terms stored in the i.d.b.
|
||
|
||
|
||
@node BlackBoard, , Internal Database, Database
|
||
@section The Blackboard
|
||
|
||
YAP implements a blackboard in the style of the SICStus Prolog
|
||
blackboard. The blackboard uses the same underlying mechanism as the
|
||
internal data-base but has several important differences:
|
||
@itemize @bullet
|
||
@item It is module aware, in contrast to the internal data-base.
|
||
@item Keys can only be atoms or integers, and not compound terms.
|
||
@item A single term can be stored per key.
|
||
@item An atomic update operation is provides; this is useful for
|
||
parallelism.
|
||
@end itemize
|
||
|
||
|
||
@table @code
|
||
@item bb_put(+@var{Key},?@var{Term})
|
||
@findex bb_put/2
|
||
@syindex bb_put/2
|
||
@cnindex bb_put/2
|
||
Store term table @var{Term} in the blackboard under key @var{Key}. If a
|
||
previous term was stored under key @var{Key} it is simply forgotten.
|
||
|
||
@item bb_get(+@var{Key},?@var{Term})
|
||
@findex bb_get/2
|
||
@syindex bb_get/2
|
||
@cnindex bb_get/2
|
||
Unify @var{Term} with a term stored in the blackboard under key
|
||
@var{Key}, or fail silently if no such term exists.
|
||
|
||
@item bb_delete(+@var{Key},?@var{Term})
|
||
@findex bb_delete/2
|
||
@syindex bb_delete/2
|
||
@cnindex bb_delete/2
|
||
Delete any term stored in the blackboard under key @var{Key} and unify
|
||
it with @var{Term}. Fail silently if no such term exists.
|
||
|
||
@item bb_update(+@var{Key},?@var{Term},?@var{New})
|
||
@findex bb_update/3
|
||
@syindex bb_update/3
|
||
@cnindex bb_update/3
|
||
Atomically unify a term stored in the blackboard under key @var{Key}
|
||
with @var{Term}, and if the unification succeeds replace it by
|
||
@var{New}. Fail silently if no such term exists or if unification fails.
|
||
|
||
@end table
|
||
|
||
@node Sets, Grammars, Database, Top
|
||
@section Collecting Solutions to a Goal
|
||
|
||
When there are several solutions to a goal, if the user wants to collect all
|
||
the solutions he may be led to use the data base, because backtracking will
|
||
forget previous solutions.
|
||
|
||
YAP allows the programmer to choose from several system
|
||
predicates instead of writing his own routines. @code{findall/3} gives you
|
||
the fastest, but crudest solution. The other built-in predicates
|
||
postprocess the result of the query in several different ways:
|
||
|
||
@table @code
|
||
|
||
@item findall(@var{T},+@var{G},-@var{L}) [ISO]
|
||
@findex findall/3
|
||
@syindex findall/3
|
||
@cyindex findall/3
|
||
Unifies @var{L} with a list that contains all the instantiations of the
|
||
term @var{T} satisfying the goal @var{G}.
|
||
|
||
With the following program:
|
||
@example
|
||
a(2,1).
|
||
a(1,1).
|
||
a(2,2).
|
||
@end example
|
||
@noindent
|
||
the answer to the query
|
||
@example
|
||
findall(X,a(X,Y),L).
|
||
@end example
|
||
@noindent
|
||
would be:
|
||
@example
|
||
X = _32
|
||
Y = _33
|
||
L = [2,1,2];
|
||
no
|
||
@end example
|
||
|
||
@item findall(@var{T},+@var{G},+@var{L},-@var{L0})
|
||
@findex findall/4
|
||
@syindex findall/4
|
||
@cnindex findall/4
|
||
Similar to @code{findall/3}, but appends all answers to list @var{L0}.
|
||
|
||
@item all(@var{T},+@var{G},-@var{L})
|
||
@findex all/3
|
||
@snindex all/3
|
||
@cnindex all/3
|
||
Similar to @code{findall(@var{T},@var{G},@var{L})} but eliminating
|
||
repeated elements. Thus, assuming the same clauses as in the above
|
||
example, the reply to the query
|
||
|
||
@example
|
||
all(X,a(X,Y),L).
|
||
@end example
|
||
@noindent
|
||
would be:
|
||
|
||
@example
|
||
X = _32
|
||
Y = _33
|
||
L = [2,1];
|
||
no
|
||
@end example
|
||
|
||
@item bagof(@var{T},+@var{G},-@var{L}) [ISO]
|
||
@findex bagof/3
|
||
@saindex bagof/3
|
||
@cyindex bagof/3
|
||
For each set of possible instances of the free variables occurring in
|
||
@var{G} but not in @var{T}, generates the list @var{L} of the instances of
|
||
@var{T} satisfying @var{G}. Again, assuming the same clauses as in the
|
||
examples above, the reply to the query
|
||
|
||
@example
|
||
bagof(X,a(X,Y),L).
|
||
|
||
would be:
|
||
X = _32
|
||
Y = 1
|
||
L = [2,1];
|
||
X = _32
|
||
Y = 2
|
||
L = [2];
|
||
no
|
||
@end example
|
||
|
||
@item setof(@var{X},+@var{P},-@var{B}) [ISO]
|
||
@findex setof/3
|
||
@saindex setof/3
|
||
@cyindex setof/3
|
||
Similar to @code{bagof(@var{T},@var{G},@var{L})} but sorting list
|
||
@var{L} and keeping only one copy of each element. Again, assuming the
|
||
same clauses as in the examples above, the reply to the query
|
||
@example
|
||
setof(X,a(X,Y),L).
|
||
@end example
|
||
@noindent
|
||
would be:
|
||
@example
|
||
X = _32
|
||
Y = 1
|
||
L = [1,2];
|
||
X = _32
|
||
Y = 2
|
||
L = [2];
|
||
no
|
||
@end example
|
||
|
||
@end table
|
||
|
||
@node Grammars, OS, Sets, Top
|
||
@section Grammar Rules
|
||
|
||
Grammar rules in Prolog are both a convenient way to express definite
|
||
clause grammars and an extension of the well known context-free grammars.
|
||
|
||
A grammar rule is of the form:
|
||
|
||
@example
|
||
@i{ head --> body }
|
||
@end example
|
||
@noindent
|
||
where both @i{head} and @i{body} are sequences of one or more items
|
||
linked by the standard conjunction operator ','.
|
||
|
||
@emph{Items can be:}
|
||
|
||
@itemize @bullet
|
||
@item
|
||
a @emph{non-terminal} symbol may be either a complex term or an atom.
|
||
@item
|
||
a @emph{terminal} symbol may be any Prolog symbol. Terminals are
|
||
written as Prolog lists.
|
||
@item
|
||
an @emph{empty body} is written as the empty list '[ ]'.
|
||
@item
|
||
@emph{extra conditions} may be inserted as Prolog procedure calls, by being
|
||
written inside curly brackets '@{' and '@}'.
|
||
@item
|
||
the left side of a rule consists of a nonterminal and an optional list
|
||
of terminals.
|
||
@item
|
||
alternatives may be stated in the right-hand side of the rule by using
|
||
the disjunction operator ';'.
|
||
@item
|
||
the @emph{cut} and @emph{conditional} symbol ('->') may be inserted in the
|
||
right hand side of a grammar rule
|
||
@end itemize
|
||
|
||
Grammar related built-in predicates:
|
||
|
||
@table @code
|
||
|
||
@item expand_term(@var{T},-@var{X})
|
||
@findex expand_term/2
|
||
@syindex expand_term/2
|
||
@cyindex expand_term/2
|
||
@findex term_expansion/2
|
||
@syindex term_expansion/2
|
||
@cyindex term_expansion/2
|
||
This predicate is used by YAP for preprocessing each top level
|
||
term read when consulting a file and before asserting or executing it.
|
||
It rewrites a term @var{T} to a term @var{X} according to the following
|
||
rules: first try to use the user defined predicate
|
||
@code{term_expansion/2}. If this call fails then the translating process
|
||
for DCG rules is applied, together with the arithmetic optimizer
|
||
whenever the compilation of arithmetic expressions is in progress.
|
||
|
||
@item user:goal_expansion(+@var{G},+@var{M},-@var{NG})
|
||
@findex user:goal_expansion/3
|
||
@snindex user:goal_expansion/3
|
||
@cnindex user:goal_expansion/3
|
||
Yap now supports @code{goal_expansion/3}. This is an user-defined
|
||
procedure that is called after term expansion when compiling or
|
||
asserting goals for each sub-goal in a clause. The first argument is
|
||
bound to the goal and the second to the module under which the goal
|
||
@var{G} will execute. If @code{goal_expansion/3} succeeds the new
|
||
sub-goal @var{NG} will replace @var{G} and will be processed in the same
|
||
way. If @code{goal_expansion/3} fails the system will use the default
|
||
rules.
|
||
|
||
@item phrase(+@var{P},@var{L},@var{R})
|
||
@findex phrase/3
|
||
@syindex phrase/3
|
||
@cnindex phrase/3
|
||
This predicate succeeds when the difference list @code{@var{L}-@var{R}}
|
||
is a phrase of type @var{P}.
|
||
|
||
@item phrase(+@var{P},@var{L})
|
||
@findex phrase/2
|
||
@syindex phrase/2
|
||
@cnindex phrase/2
|
||
This predicate succeeds when @var{L} is a phrase of type @var{P}. The
|
||
same as @code{phrase(P,L,[])}.
|
||
|
||
Both this predicate and the previous are used as a convenient way to
|
||
start execution of grammar rules.
|
||
|
||
@item 'C'(@var{S1},@var{T},@var{S2})
|
||
@findex C/3
|
||
@syindex C/3
|
||
@cnindex C/3
|
||
This predicate is used by the grammar rules compiler and is defined as
|
||
@code{'C'([H|T],H,T)}.
|
||
|
||
@end table
|
||
|
||
@node OS, Term Modification, Grammars, Top
|
||
@section Access to Operating System Functionality
|
||
|
||
The following built-in predicates allow access to underlying
|
||
Operating System functionality:
|
||
|
||
@table @code
|
||
|
||
@item cd(+@var{D})
|
||
@findex cd/1
|
||
@snindex cd/1
|
||
@cnindex cd/1
|
||
Changes the current directory (on UNIX environments).
|
||
|
||
@item environ(?@var{E},-@var{S})
|
||
@findex environ/2
|
||
@syindex environ/2
|
||
@cnindex environ/2
|
||
This backtrackable predicate unifies the first argument with an
|
||
environment variable @var{E}, and the second with its value @var{S}. It
|
||
can used to detect all environment variables.
|
||
|
||
@item getcwd(-@var{D})
|
||
@findex getcwd/1
|
||
@snindex getcwd/1
|
||
@cnindex getcwd/1
|
||
Unify the current directory, represented as an atom, with the argument
|
||
@var{D}.
|
||
|
||
@item putenv(+@var{E},+@var{S})
|
||
@findex putenv/2
|
||
@snindex putenv/2
|
||
@cnindex putenv/2
|
||
Set environment variable @var{E} to the value @var{S}. If the
|
||
environment variable @var{E} does not exist, create a new one. Both the
|
||
environment variable and the value must be atoms.
|
||
|
||
@item rename(+@var{F},+@var{G})
|
||
@findex rename/2
|
||
@snindex rename/2
|
||
@cyindex rename/2
|
||
Renames file @var{F} to @var{G}.
|
||
|
||
@item sh
|
||
@findex sh/0
|
||
@snindex sh/0
|
||
@cyindex sh/0
|
||
Creates a new shell interaction.
|
||
|
||
@item system(+@var{S})
|
||
@findex system/1
|
||
@snindex system/1
|
||
@cyindex system/1
|
||
Passes command @var{S} to the Bourne shell (on UNIX environments) or the
|
||
current command interpreter in WIN32 environments.
|
||
|
||
@item unix(+@var{S})
|
||
@findex unix/1
|
||
@snindex unix/1
|
||
@cnindex unix/1
|
||
Access to Unix-like functionality:
|
||
@table @code
|
||
@item argv/1
|
||
Return a list of arguments to the program. These are the arguments that
|
||
follow a @code{--}, as in the usual Unix convention.
|
||
@item cd/0
|
||
Change to home directory.
|
||
@item cd/1
|
||
Change to given directory. Acceptable directory names are strings or
|
||
atoms.
|
||
@item environ/2
|
||
Unify the first argument with an
|
||
environment variable, and the second with its value.
|
||
@item getcwd/1
|
||
Unify the first argument with an atom representing the current directory.
|
||
@item putenv/2
|
||
Set environment variable @var{E} to the value @var{S}. If the
|
||
environment variable @var{E} does not exist, create a new one. Both the
|
||
environment variable and the value must be atoms.
|
||
@item shell/1
|
||
Execute command under current shell. Acceptable commands are strings or
|
||
atoms.
|
||
@item system/1
|
||
Execute command with @code{/bin/sh}. Acceptable commands are strings or
|
||
atoms.
|
||
@item shell/0
|
||
Execute a new shell.
|
||
@end table
|
||
|
||
@item alarm(+@var{Seconds},+@var{Callable},+@var{OldAlarm})
|
||
@findex alarm/3
|
||
@snindex alarm/3
|
||
@cnindex alarm/3
|
||
Arranges for YAP to be interrupted in @var{Seconds}
|
||
seconds. When interrupted, YAP will execute @var{Callable} and
|
||
then return to the previous execution. If @var{Seconds} is @code{0}, no
|
||
new alarm is scheduled. In any event, any previously set alarm is
|
||
cancelled.
|
||
|
||
The variable @var{OldAlarm} unifies with the number of seconds remaining
|
||
until any previously scheduled alarm was due to be delivered, or with
|
||
@code{0} if there was no previously scheduled alarm.
|
||
|
||
Note that execution of @var{Callable} will wait if YAP is
|
||
executing built-in predicates, such as Input/Output operations.
|
||
|
||
The next example shows how @var{alarm/3} can be used to implement a
|
||
simple clock:
|
||
|
||
@example
|
||
loop :- loop.
|
||
|
||
ticker :- write('.'), flush_output,
|
||
get_value(tick, yes),
|
||
alarm(1,ticker,_).
|
||
|
||
:- set_value(tick, yes), alarm(1,ticker,_), loop.
|
||
@end example
|
||
|
||
The clock, @code{ticker}, writes a dot and then checks the flag
|
||
@code{tick} to see whether it can continue ticking. If so, it calls
|
||
itself again. Note that there is no guarantee that the each dot
|
||
corresponds a second: for instance, if the YAP is waiting for
|
||
user input, @code{ticker} will wait until the user types the entry in.
|
||
|
||
The next example shows how @code{alarm/3} can be used to guarantee that
|
||
a certain procedure does not take longer than a certain amount of time:
|
||
|
||
@example
|
||
loop :- loop.
|
||
|
||
:- alarm(10, throw(ball), _),
|
||
catch(loop, ball, format('Quota exhausted.~n',[])).
|
||
@end example
|
||
In this case after @code{10} seconds our @code{loop} is interrupted,
|
||
@code{ball} is thrown, and the handler writes @code{Quota exhausted}.
|
||
Execution then continues from the handler.
|
||
|
||
@end table
|
||
|
||
@node Term Modification, Profiling, OS, Top
|
||
@section Term Modification
|
||
|
||
@cindex updating terms
|
||
It is sometimes useful to change the value of instantiated
|
||
variables. Although, this is against the spirit of logic programming, it
|
||
is sometimes useful. As in other Prolog systems, YAP has
|
||
several primitives that allow updating Prolog terms. Note that these
|
||
primitives are also backtrackable.
|
||
|
||
The @code{setarg/3} primitive allows updating any argument of a Prolog
|
||
compound terms. The @code{mutable} family of predicates provides
|
||
@emph{mutable variables}. They should be used instead of @code{setarg/3},
|
||
as they allow the encapsulation of accesses to updatable
|
||
variables. Their implementation can also be more efficient for long
|
||
deterministic computations.
|
||
|
||
@table @code
|
||
@item setarg(+@var{I},+@var{S},?@var{T})
|
||
@findex setarg/3n
|
||
@snindex setarg/3n
|
||
@cnindex setarg/3n
|
||
Set the value of the @var{I}th argument of term @var{S} to term @var{T}.
|
||
|
||
@cindex mutable variables
|
||
@item create_mutable(+@var{D},-@var{M})
|
||
@findex create_mutable/2
|
||
@syindex create_mutable/2
|
||
@cnindex create_mutable/2
|
||
Create new mutable variable @var{M} with initial value @var{D}.
|
||
|
||
@item get_mutable(?@var{D},+@var{M})
|
||
@findex get_mutable/2
|
||
@syindex get_mutable/2
|
||
@cnindex get_mutable/2
|
||
Unify the current value of mutable term @var{M} with term @var{D}.
|
||
|
||
@item is_mutable(?@var{D})
|
||
@findex is_mutable/1
|
||
@syindex is_mutable/1
|
||
@cnindex is_mutable/1
|
||
Holds if @var{D} is a mutable term.
|
||
|
||
@item set_mutable(?@var{D},+@var{M})
|
||
@findex set_mutable/2
|
||
@syindex set_mutable/2
|
||
@cnindex set_mutable/2
|
||
Unify the current value of mutable term @var{M} with term @var{D}.
|
||
|
||
@item update_mutable(+@var{D},+@var{M})
|
||
@findex update_mutable/2
|
||
@syindex update_mutable/2
|
||
@cnindex update_mutable/2
|
||
Set the current value of mutable term @var{M} to term @var{D}.
|
||
@end table
|
||
|
||
@node Profiling, Arrays, Term Modification, Top
|
||
@section Profiling Prolog Programs
|
||
|
||
@cindex profiling
|
||
Predicates compiled with YAP's flag @code{profiling} set to
|
||
@code{on}, keep information on the number of times the predicate was
|
||
called. This information can be used to detect what are the most
|
||
commonly called predicates in the program.
|
||
|
||
The YAP profiling sub-system is currently
|
||
under-development. Functionality for this sub-system will increase with
|
||
newer implementation.
|
||
|
||
@strong{Notes:}
|
||
|
||
@itemize @bullet
|
||
@item Profiling works for both static and dynamic predicates.
|
||
@item Currently only information on entries and retries to a predicate
|
||
are maintained. This may change in the future.
|
||
@item As an example, the following user-level program gives a list of
|
||
the most often called procedures in a program:
|
||
@example
|
||
list_profile :-
|
||
% get number of calls for each profiled procedure
|
||
findall(D-P,profile_data(P,calls,D),LP),
|
||
% sort them
|
||
sort(LP,SLP),
|
||
% output so that the most often called
|
||
% predicates will come last:
|
||
write_profile_data(SLP).
|
||
|
||
write_profile_data([]).
|
||
write_profile_data([D-P|SLP]) :-
|
||
% swap the two calls if you want the most often
|
||
% called predicates first.
|
||
format('~w: ~w~n', [P,D]),
|
||
write_profile_data(SLP).
|
||
@end example
|
||
@end itemize
|
||
|
||
These are the current predicates to access and clear profiling data:
|
||
|
||
@table @code
|
||
@item profile_data(?@var{Na/Ar}, ?@var{Paramater}, -@var{Data})
|
||
@findex profile_data/3
|
||
@snindex profile_data/3
|
||
@cnindex profile_data/3
|
||
Give current profile data on @var{Parameter} for a predicate described
|
||
by the predicate indicator @var{Na/Ar}. If any of @var{Na/Ar} or
|
||
@var{Parameter} are unbound, backtrack through all profiled predicates
|
||
or stored parameters. Current parameters are:
|
||
|
||
@table @code
|
||
@item calls
|
||
Number of times a procedure was called.
|
||
|
||
@item retries
|
||
Number of times a call to the procedure was backtracked to and retried.
|
||
@end table
|
||
|
||
@item profile_reset
|
||
@findex profiled_reset/0
|
||
@snindex profiled_reset/0
|
||
@cnindex profiled_reset/0
|
||
Reset all profiling information.
|
||
|
||
@end table
|
||
|
||
@node Arrays, Preds, Profiling , Top
|
||
@section Arrays
|
||
|
||
The YAP system includes experimental support for arrays. The
|
||
support is enabled with the option @code{YAP_ARRAYS}.
|
||
|
||
There are two very distinct forms of arrays in YAP. The
|
||
@emph{dynamic arrays} are a different way to access compound terms
|
||
created during the execution. Like any other terms, any bindings to
|
||
these terms and eventually the terms themselves will be destroyed during
|
||
backtracking. Our goal in supporting dynamic arrays is twofold. First,
|
||
they provide an alternative to the standard @code{arg/3}
|
||
built-in. Second, because dynamic arrays may have name that are globally
|
||
visible, a dynamic array can be visible from any point in the
|
||
program. In more detail, the clause
|
||
@example
|
||
g(X) :- array_element(a,2,X).
|
||
@end example
|
||
will succeed as long as the programmer has used the builtin @t{array/2}
|
||
to create an array term with at least 3 elements in the current
|
||
environment, and the array was associated with the name @code{a}. The
|
||
element @code{X} is a Prolog term, so one can bind it and any such
|
||
bindings will be undone when backtracking. Note that dynamic arrays do
|
||
not have a type: each element may be any Prolog term.
|
||
|
||
The @emph{static arrays} are an extension of the database. They provide
|
||
a compact way for manipulating data-structures formed by characters,
|
||
integers, or floats imperatively. They can also be used to provide
|
||
two-way communication between YAP and external programs through
|
||
shared memory.
|
||
|
||
In order to efficiently manage space elements in a static array must
|
||
have a type. Currently, elements of static arrays in YAP should
|
||
have one of the following predefined types:
|
||
|
||
@itemize @bullet
|
||
@item @code{byte}: an 8-bit signed character.
|
||
@item @code{unsigned_byte}: an 8-bit unsigned character.
|
||
@item @code{int}: Prolog integers. Size would be the natural size for
|
||
the machine's architecture.
|
||
@item @code{float}: Prolog floating point number. Size would be equivalent
|
||
to a double in @code{C}.
|
||
@item @code{atom}: a Prolog atom.
|
||
@item @code{dbref}: an internal database reference.
|
||
@item @code{term}: a generic Prolog term. Note that this will term will
|
||
not be stored in the array itself, but instead will be stored in the
|
||
Prolog internal database.
|
||
@end itemize
|
||
|
||
Arrays may be @emph{named} or @emph{anonymous}. Most arrays will be
|
||
@emph{named}, that is associated with an atom that will be used to find
|
||
the array. Anonymous arrays do not have a name, and they are only of
|
||
interest if the @code{TERM_EXTENSIONS} compilation flag is enabled. In
|
||
this case, the unification and parser are extended to replace
|
||
occurrences of Prolog terms of the form @code{X[I]} by run-time calls to
|
||
@code{array_element/3}, so that one can use array references instead of
|
||
extra calls to @code{arg/3}. As an example:
|
||
@example
|
||
g(X,Y,Z,I,J) :- X[I] is Y[J]+Z[I].
|
||
@end example
|
||
should give the same results as:
|
||
@example
|
||
G(X,Y,Z,I,J) :-
|
||
array_element(X,I,E1),
|
||
array_element(Y,J,E2),
|
||
array_element(Z,I,E3),
|
||
E1 is E2+E3.
|
||
@end example
|
||
|
||
Note that the only limitation on array size are the stack size for
|
||
dynamic arrays; and, the heap size for static (not memory mapped)
|
||
arrays. Memory mapped arrays are limited by available space in the file
|
||
system and in the virtual memory space.
|
||
|
||
The following predicates manipulate arrays:
|
||
|
||
@table @code
|
||
|
||
@item array(+@var{Name}, +@var{Size})
|
||
@findex array/2
|
||
@snindex array/2
|
||
@cnindex array/2
|
||
Creates a new dynamic array. The @var{Size} must evaluate to an
|
||
integer. The @var{Name} may be either an atom (named array) or an
|
||
unbound variable (anonymous array).
|
||
|
||
Dynamic arrays work as standard compound terms, hence space for the
|
||
array is recovered automatically on backtracking.
|
||
|
||
@item static_array(+@var{Name}, +@var{Size}, +@var{Type})
|
||
@findex static_array/3
|
||
@snindex static_array/3
|
||
@cnindex static_array/3
|
||
Create a new static array with name @var{Name}. Note that the @var{Name}
|
||
must be an atom (named array). The @var{Size} must evaluate to an
|
||
integer. The @var{Type} must be bound to one of types mentioned
|
||
previously.
|
||
|
||
@item mmapped_array(+@var{Name}, +@var{Size}, +@var{Type}, +@var{File})
|
||
@findex static_array/3
|
||
@snindex static_array/3
|
||
@cnindex static_array/3
|
||
Similar to @code{static_array/3}, but the array is memory mapped to file
|
||
@var{File}. This means that the array is initialised from the file, and
|
||
that any changes to the array will also be stored in the file.
|
||
|
||
This built-in is only available in operating systems that support the
|
||
system call @code{mmap}. Moreover, mmapped arrays do not store generic
|
||
terms (type @code{term}).
|
||
|
||
@item close_static_array(+@var{Name})
|
||
@findex close_static_array/3
|
||
@snindex close_static_array/3
|
||
@cnindex close_static_array/3
|
||
Close an existing static array of name @var{Name}. The @var{Name} must
|
||
be an atom (named array). Space for the array will be recovered and
|
||
further accesses to the array will return an error.
|
||
|
||
@item resize_static_array(+@var{Name}, -@var{OldSize}, +@var{NewSize})
|
||
@findex resize_static_array/3
|
||
@snindex resize_static_array/3
|
||
@cnindex resize_static_array/3
|
||
Expand or reduce a static array, The @var{Size} must evaluate to an
|
||
integer. The @var{Name} must be an atom (named array). The @var{Type}
|
||
must be bound to one of @code{int}, @code{dbref}, @code{float} or
|
||
@code{atom}.
|
||
|
||
Note that if the array is a mmapped array the size of the mmapped file
|
||
will be actually adjusted to correspond to the size of the array.
|
||
|
||
@item array_element(+@var{Name}, +@var{Index}, ?@var{Element})
|
||
@findex access_array/3
|
||
@snindex access_array/3
|
||
@cnindex access_array/3
|
||
Unify @var{Element} with @var{Name}[@var{Index}]. It works for both
|
||
static and dynamic arrays, but it is read-only for static arrays, while
|
||
it can be used to unify with an element of a dynamic array.
|
||
|
||
@item update_array(+@var{Name}, +@var{Index}, ?@var{Value})
|
||
@findex update_array/3
|
||
@snindex update_array/3
|
||
@cnindex update_array/3
|
||
Attribute value @var{Value} to @var{Name}[@var{Index}]. Type
|
||
restrictions must be respected for static arrays. This operation is
|
||
available for dynamic arrays if @code{MULTI_ASSIGNMENT_VARIABLES} is
|
||
enabled (true by default). Backtracking undoes @var{update_array/3} for
|
||
dynamic arrays, but not for static arrays.
|
||
|
||
Note that @code{update_array/3} actually uses @code{setarg/3} to update
|
||
elements of dynamic arrays, and @code{setarg/3} spends an extra cell for
|
||
every update. For intensive operations we suggest it may be less
|
||
expensive to unify each element of the array with a mutable terms and
|
||
to use the operations on mutable terms.
|
||
|
||
@end table
|
||
|
||
@node Preds, Misc, Arrays, Top
|
||
@section Predicate Information
|
||
|
||
Built-ins that return information on the current predicates and modules:
|
||
|
||
@table @code
|
||
@c ......... begin of 'module' documentation .........
|
||
@item current_module(@var{M})
|
||
@findex current_module/1
|
||
@syindex current_module/1
|
||
@cnindex current_module/1
|
||
Succeeds if @var{M} are current modules. A module becomes current since
|
||
some predicate defined in it is loaded.
|
||
|
||
@item current_module(@var{M},@var{F})
|
||
@findex current_module/2
|
||
@syindex current_module/2
|
||
@cnindex current_module/2
|
||
Succeeds if @var{M} are current modules associated to the file @var{F}.
|
||
|
||
@c .......... end of 'module' documentation ..........
|
||
@end table
|
||
|
||
@node Misc, , Preds, Top
|
||
@section Miscellaneous
|
||
|
||
@table @code
|
||
|
||
@item statistics/0
|
||
@findex statistics/0
|
||
@saindex statistics/0
|
||
@cyindex statistics/0
|
||
Send to the current user error stream general information on space used and time
|
||
spent by the system.
|
||
@example
|
||
?- statistics.
|
||
Heap space : 2441216
|
||
Heap in use: 820220, max. used: 1623516
|
||
Trail space : 131068
|
||
Trail in use: 16, max. used: 13048
|
||
Stack space : 1523712
|
||
Global in use: 88, max. used: 658700
|
||
Local in use: 276, max. used: 515336
|
||
|
||
|
||
90 msec. for 5 heap overflows.
|
||
90 msec. for 3 stack overflows.
|
||
0 msec. for 0 trail overflows.
|
||
800 msec. for 3 garbage collections which
|
||
collected 208348 bytes.
|
||
Runtime : 23.07 sec.
|
||
@end example
|
||
|
||
@item statistics(?@var{Param},-@var{Info})
|
||
@findex statistics/2
|
||
@saindex statistics/2
|
||
@cnindex statistics/2
|
||
Gives statistical information on the system parameter given by first
|
||
argument:
|
||
|
||
@table @code
|
||
|
||
@item cputime
|
||
@findex cputime (statistics/2 option)
|
||
@code{[@var{Time since Boot},@var{Time From Last Call to Cputime}]}
|
||
@*
|
||
This gives the total cputime in milliseconds spent executing Prolog code,
|
||
garbage collection and stack shifts time included.
|
||
|
||
@item garbage_collection
|
||
@findex garbage_collection (statistics/2 option)
|
||
@code{[@var{Number of GCs},@var{Total Global Recovered},@var{Total Time
|
||
Spent}]}
|
||
@*
|
||
Number of garbage collections, amount of space recovered in kbytes, and
|
||
total time spent doing garbage collection in milliseconds. More detailed
|
||
information is available using @code{yap_flag(gc_trace,verbose)}.
|
||
|
||
@item global_stack
|
||
@findex global_stack (statistics/2 option)
|
||
@code{[@var{Global Stack Used},@var{Execution Stack Free}]}
|
||
@*
|
||
Space in kbytes currently used in the global stack, and space available for
|
||
expansion by the local and global stacks.
|
||
|
||
@item local_stack
|
||
@findex local_stack (statistics/2 option)
|
||
@code{[@var{Local Stack Used},@var{Execution Stack Free}]}
|
||
@*
|
||
Space in kbytes currently used in the local stack, and space available for
|
||
expansion by the local and global stacks.
|
||
|
||
@item heap
|
||
@findex heap (statistics/2 option)
|
||
@code{[@var{Heap Used},@var{Heap Free}]}
|
||
@*
|
||
Total space in kbytes not recoverable
|
||
in backtracking. It includes the program code, internal data base, and,
|
||
atom symbol table.
|
||
|
||
@item program
|
||
@findex program (statistics/2 option)
|
||
@code{[@var{Program Space Used},@var{Program Space Free}]}
|
||
@*
|
||
Equivalent to @code{heap}.
|
||
|
||
@item runtime
|
||
@findex runtime (statistics/2 option)
|
||
@code{[@var{Time since Boot},@var{Time From Last Call to Runtime}]}
|
||
@*
|
||
This gives the total cputime in milliseconds spent executing Prolog
|
||
code, not including garbage collections and stack shifts. Note that
|
||
until Yap4.1.2 the @code{runtime} statistics would return time spent on
|
||
garbage collection and stack shifting.
|
||
|
||
@item stack_shifts
|
||
@findex stack_shifts (stack_shifts/3 option)
|
||
@code{[@var{Number of Heap Shifts},@var{Number of Stack
|
||
Shifts},@var{Number of Trail Shifts}]}
|
||
@*
|
||
Number of times YAP had to
|
||
expand the heap, the stacks, or the trail. More detailed information is
|
||
available using @code{yap_flag(gc_trace,verbose)}.
|
||
|
||
@item trail
|
||
@findex trail (statistics/2 option)
|
||
@code{[@var{Trail Used},@var{Trail Free}]}
|
||
@*
|
||
Space in kbytes currently being used and still available for the trail.
|
||
|
||
@item walltime
|
||
@findex walltime (statistics/2 option)
|
||
@code{[@var{Time since Boot},@var{Time From Last Call to Runtime}]}
|
||
@*
|
||
This gives the clock time in milliseconds since starting Prolog.
|
||
|
||
@end table
|
||
|
||
@item yap_fla
|
||
g(?@var{Param},?@var{Value})
|
||
@findex yap_flag/2
|
||
@snindex yap_flag/2
|
||
@cnindex yap_flag/2
|
||
Set or read system properties for @var{Param}:
|
||
|
||
@table @code
|
||
|
||
@item bounded [ISO]
|
||
@findex bounded (yap_flag/2 option)
|
||
@*
|
||
Read-only flag telling whether integers are bounded. The value depends
|
||
on whether YAP uses the GMP library or not.
|
||
|
||
@item char_conversion [ISO]
|
||
@findex char_conversion (yap_flag/2 option)
|
||
@*
|
||
Writable flag telling whether a character conversion table is used when
|
||
reading terms. The default value for this flag is @code{off} except in
|
||
@code{sicstus} and @code{iso} language modes, where it is @code{on}.
|
||
|
||
@item character_escapes [ISO]
|
||
@findex character_escapes (yap_flag/2 option)
|
||
@* Writable flag telling whether a character escapes are enables,
|
||
@code{on}, or disabled, @code{off}. The default value for this flag is
|
||
@code{on}.
|
||
|
||
@c You can also use @code{cprolog} mode, which corresponds to @code{off},
|
||
@c @code{iso} mode, which corresponds to @code{on}, and @code{sicstus}
|
||
@c mode, which corresponds to the mode traditionally used in SICStus
|
||
@c Prolog. In this mode back-quoted escape sequences should not close with
|
||
@c a backquote and unrecognised escape codes do not result in error.
|
||
|
||
@item debug [ISO]
|
||
@findex debug (yap_flag/2 option)
|
||
@*
|
||
If @var{Value} is unbound, tell whether debugging is @code{on} or
|
||
@code{off}. If @var{Value} is bound to @code{on} enable debugging, and if
|
||
it is bound to @code{off} disable debugging.
|
||
|
||
@item discontiguous_warnings
|
||
@findex discontiguous_warnings (yap_flag/2 option)
|
||
@*
|
||
If @var{Value} is unbound, tell whether warnings for discontiguous
|
||
predicates are @code{on} or
|
||
@code{off}. If @var{Value} is bound to @code{on} enable these warnings,
|
||
and if it is bound to @code{off} disable them. The default for YAP is
|
||
@code{off}, unless we are in @code{sicstus} or @code{iso} mode.
|
||
|
||
@item dollar_as_lower_case
|
||
@findex dollar_as_lower_case (yap_flag/2 option)
|
||
@*
|
||
If @code{off} (default) consider the character '$' a control character, if
|
||
@code{on} consider '$' a lower case character.
|
||
|
||
@item double_quotes [ISO]
|
||
@findex double_quotes (yap_flag/2 option)
|
||
@*
|
||
If @var{Value} is unbound, tell whether a double quoted list of characters
|
||
token is converted to a list of atoms, @code{chars}, to a list of integers,
|
||
@code{codes}, or to a single atom, @code{atom}. If @var{Value} is bound, set to
|
||
the corresponding behaviour. The default value is @code{codes}.
|
||
|
||
@item fast
|
||
@findex fast (yap_flag/2 option)
|
||
@*
|
||
If @code{on} allow fast machine code, if @code{off} (default) disable it. Only
|
||
available in experimental implementations.
|
||
|
||
@item gc
|
||
@findex gc (yap_flag/2 option)
|
||
@*
|
||
If @code{on} allow garbage collection (default), if @code{off} disable it.
|
||
|
||
@item gc_margin
|
||
@findex gc_margin (yap_flag/2 option)
|
||
@*
|
||
Set or show the minimum free stack before starting garbage
|
||
collection. The default depends on total stack size.
|
||
|
||
@item gc_trace
|
||
@findex gc_trace (yap_flag/2 option)
|
||
@*
|
||
If @code{off} (default) do not show information on garbage collection and
|
||
stack shifts, if @code{on} inform when a garbage collection or stack shift
|
||
happened, if @code{verbose} give detailed information on garbage collection
|
||
and stack shifts.
|
||
|
||
@item index
|
||
@findex index (yap_flag/2 option)
|
||
@*
|
||
If @code{on} allow indexing (default), if @code{off} disable it.
|
||
|
||
@item integer_rounding_function [ISO]
|
||
@findex integer_rounding_function (yap_flag/2 option)
|
||
@*
|
||
Read-only flag telling the rounding function used for integers. Takes the value
|
||
@code{down} for the current version of YAP.
|
||
|
||
@item language
|
||
@findex language (yap_flag/2 option)
|
||
@*
|
||
Choose whether YAP is closer to C-Prolog, @code{cprolog}, iso-prolog,
|
||
@code{iso} or SICStus Prolog, @code{sicstus}. The current default is
|
||
@code{cprolog}. This flag affects update semantics, leashing mode,
|
||
style_checking, handling calls to undefined procedures, how directives
|
||
are interpreted, when to use dynamic, character escapes, and how files
|
||
are consulted.
|
||
|
||
@item max_arity [ISO]
|
||
@findex max_arity (yap_flag/2 option)
|
||
@*
|
||
Read-only flag telling the maximum arity of a functor. Takes the value
|
||
@code{unbounded} for the current version of YAP.
|
||
|
||
@item max_integer [ISO]
|
||
@findex max_integer (yap_flag/2 option)
|
||
@*
|
||
Read-only flag telling the maximum integer in the
|
||
implementation. Depends on machine and Operating System
|
||
architecture, and on whether YAP uses the @code{GMP} multiprecision
|
||
library. If @code{bounded} is false, requestes for @code{max_integer}
|
||
will fail.
|
||
|
||
@item min_integer [ISO]
|
||
@findex min_integer (yap_flag/2 option)
|
||
@* Read-only flag telling the minimum integer in the
|
||
implementation. Depends on machine and Operating System architecture,
|
||
and on whether YAP uses the @code{GMP} multiprecision library. If
|
||
@code{bounded} is false, requestes for @code{min_integer} will fail.
|
||
|
||
@item n_of_integer_keys_in_bb
|
||
@findex n_of_integer_keys_in_bb (yap_flag/2 option)
|
||
@*
|
||
Read or set the size of the hash table that is used for looking up the
|
||
blackboard when the key is an integer.
|
||
|
||
@item n_of_integer_keys_in_db
|
||
@findex n_of_integer_keys_in_db (yap_flag/2 option)
|
||
@*
|
||
Read or set the size of the hash table that is used for looking up the
|
||
internal data-base when the key is an integer.
|
||
|
||
@item profiling
|
||
@findex profiling (yap_flag/2 option)
|
||
@*
|
||
If @code{off} (default) do not compile profiling information for
|
||
procedures. If @code{on} compile predicates so that they will output
|
||
profiling information. Profiling data can be read through the
|
||
@code{profile_data/3} built-in.
|
||
|
||
@item redefine_warnings
|
||
@findex discontiguous_warnings (yap_flag/2 option)
|
||
@*
|
||
If @var{Value} is unbound, tell whether warnings for procedures defined
|
||
in several different files are @code{on} or
|
||
@code{off}. If @var{Value} is bound to @code{on} enable these warnings,
|
||
and if it is bound to @code{off} disable them. The default for YAP is
|
||
@code{off}, unless we are in @code{sicstus} or @code{iso} mode.
|
||
|
||
@item single_var_warnings
|
||
@findex single_var_warnings (yap_flag/2 option)
|
||
@*
|
||
If @var{Value} is unbound, tell whether warnings for singleton variables
|
||
are @code{on} or @code{off}. If @var{Value} is bound to @code{on} enable
|
||
these warnings, and if it is bound to @code{off} disable them. The
|
||
default for YAP is @code{off}, unless we are in @code{sicstus} or
|
||
@code{iso} mode.
|
||
|
||
@item strict_iso
|
||
@findex strict_iso (prolog_flag/2 option)
|
||
@*
|
||
If @var{Value} is unbound, tell whether strict ISO compatibility mode
|
||
is @code{on} or @code{off}. If @var{Value} is bound to @code{on} set
|
||
language mode to @code{iso} and enable strict mode. If @var{Value} is
|
||
bound to @code{off} disable strict mode, and keep the current language
|
||
mode. The default for YAP is @code{off}.
|
||
|
||
Under strict ISO prolog mode all calls to non-ISO built-ins generate an
|
||
error. Compilation of clauses that would call non-ISO built-ins will
|
||
also generate errors. Pre-processing for grammar rules is also
|
||
disabled. Module expansion is still performed.
|
||
|
||
Arguably, ISO Prolog does not provide all the functionality required
|
||
from a modern Prolog system. Moreover, because most Prolog
|
||
implementations do not fully implement the standard and because the
|
||
standard itself gives the implementor latitude in a few important
|
||
questions, such as the unification algorithm and maximum size for
|
||
numbers there is not guarantee that prolograms compliant with this mode
|
||
will work the same way in every Prolog and in every platform. We thus
|
||
believe this mode is mostly useful when investigating how a program
|
||
depends on a Prolog's platform specific features.
|
||
|
||
@item syntax_errors
|
||
@findex syntax_errors (yap_flag/2 option)
|
||
@*
|
||
Control action to be taken after syntax errors while executing @code{read/1},
|
||
@code{read/2}, or @code{read_term/3}:
|
||
@table @code
|
||
|
||
@item dec10
|
||
@*
|
||
Report the syntax error and retry reading the term.
|
||
|
||
@item fail
|
||
@*
|
||
Report the syntax error and fail (default).
|
||
|
||
@item error
|
||
@*
|
||
Report the syntax error and generate an error.
|
||
|
||
@item quiet
|
||
@*
|
||
Just fail
|
||
@end table
|
||
|
||
@item to_chars_mode
|
||
@findex to_chars_modes (yap_flag/2 option)
|
||
@* Define whether YAP should follow @code{quintus}-like
|
||
semantics for the @code{atom_chars/1} or @code{number_chars/1} built-in,
|
||
or whether it should follow the ISO standard (@code{iso} option).
|
||
|
||
@item toplevel_hook(@var{G})
|
||
@findex toplevel_hook (yap_flag/2 option)
|
||
@*
|
||
If bound, set @var{G} to a goal to be executed before entering the
|
||
top-level. If unbound show the current goal or @code{true} if none is
|
||
presented. Only the first solution is considered and the goal is not
|
||
backtracked into.
|
||
|
||
@item typein_module
|
||
@findex typein_module (yap_flag/2 option)
|
||
@*
|
||
If bound, set the current working or type-in module to the argument,
|
||
which must be an atom. If unbound, unify the argument with the current
|
||
working module.
|
||
|
||
@item unknown [ISO]
|
||
@findex unknown (yap_flag/2 option)
|
||
@*
|
||
Corresponds to calling the @code{unknown/2} built-in.
|
||
|
||
@item update_semantics
|
||
@findex update_semantics (yap_flag/2 option)
|
||
@*
|
||
Define whether YAP should follow @code{immediate} update
|
||
semantics, as in C-Prolog (default), @code{logical} update semantics,
|
||
as in Quintus Prolog, SICStus Prolog, or in the ISO standard. There is
|
||
also an intermediate mode, @code{logical_assert}, where dynamic
|
||
procedures follow logical semantics but the internal data base still
|
||
follows immediate semantics.
|
||
|
||
@item user_error
|
||
@findex user_error (yap_flag/2 option)
|
||
@*
|
||
If the second argument is bound to a stream, set @code{user_error} to
|
||
this stream. If the second argument is unbound, unify the argument with
|
||
the current @code{user_error} stream.
|
||
|
||
By default, the @code{user_error} stream is set to a stream
|
||
corresponding to the Unix @code{stderr} stream.
|
||
|
||
The next example shows how to use this flag:
|
||
@example
|
||
?- open( '/dev/null', append, Error,
|
||
[alias(mauri_tripa)] ).
|
||
|
||
Error = '$stream'(3) ? ;
|
||
|
||
no
|
||
?- set_prolog_flag(user_error, mauri_tripa).
|
||
|
||
close(mauri_tripa).
|
||
|
||
yes
|
||
?-
|
||
@end example
|
||
We first opened a stream in write mode and gave it an alias. Next, we
|
||
set @code{user_error} to the stream via the alias. Note that after we
|
||
did so prompts from the system were redirected to the stream
|
||
@code{mauri_tripa}. Last, when we closed the stream we automatically
|
||
redirect the @code{user_error} alias to the original @code{stderr}.
|
||
|
||
@item user_input
|
||
@findex user_input (yap_flag/2 option)
|
||
@*
|
||
If the second argument is bound to a stream, set @code{user_input} to
|
||
this stream. If the second argument is unbound, unify the argument with
|
||
the current @code{user_input} stream.
|
||
|
||
By default, the @code{user_input} stream is set to a stream
|
||
corresponding to the Unix @code{stdin} stream.
|
||
|
||
@item user_output
|
||
@findex user_output (yap_flag/2 option)
|
||
@*
|
||
If the second argument is bound to a stream, set @code{user_output} to
|
||
this stream. If the second argument is unbound, unify the argument with
|
||
the current @code{user_output} stream.
|
||
|
||
By default, the @code{user_output} stream is set to a stream
|
||
corresponding to the Unix @code{stdout} stream.
|
||
|
||
@item version
|
||
@findex version (yap_flag/2 option)
|
||
@*
|
||
Read-only flag that giving the current version of Yap.
|
||
|
||
@item write_strings
|
||
@findex write_strings (yap_flag/2 option)
|
||
@* Writable flag telling whether the system should write lists of
|
||
integers that are writable character codes using the list notation. It
|
||
is @code{on} if enables or @code{off} if disabled. The default value for
|
||
this flag is @code{off}.
|
||
|
||
@end table
|
||
|
||
@item current_prolog_flag(?@var{Flag},-@var{Value}) [ISO]
|
||
@findex current_prolog_flag/2
|
||
@snindex current_prolog_flag/2
|
||
@cnindex current_prolog_flag/2
|
||
|
||
Obtain the value for a YAP Prolog flag. Equivalent to calling
|
||
@code{yap_flag/2} with the second argument unbound, and unifying the
|
||
returned second argument with @var{Value}.
|
||
|
||
@item prolog_flag(?@var{Flag},-@var{OldValue},+@var{NewValue})
|
||
@findex prolog_flag/3
|
||
@syindex prolog_flag/3
|
||
@cnindex prolog_flag/3
|
||
|
||
Obtain the value for a YAP Prolog flag and then set it to a new
|
||
value. Equivalent to first calling @code{current_prolog_flag/2} with the
|
||
second argument @var{OldValue} unbound and then calling
|
||
@code{set_prolog_flag/2} with the third argument @var{NewValue}.
|
||
|
||
@item set_prolog_flag(+@var{Flag},+@var{Value}) [ISO]
|
||
@findex set_prolog_flag/2
|
||
@snindex set_prolog_flag/2
|
||
@cnindex set_prolog_flag/2
|
||
|
||
Set the value for YAP Prolog flag @code{Flag}. Equivalent to
|
||
calling @code{yap_flag/2} with both arguments bound.
|
||
|
||
@item op(+@var{P},+@var{T},+@var{A}) [ISO]
|
||
@findex op/3
|
||
@syindex op/3
|
||
@cyindex op/3
|
||
Defines the operator @var{A} or the list of operators @var{A} with type
|
||
@var{T} (which must be one of @code{xfx}, @code{xfy},@code{yfx},
|
||
@code{xf}, @code{yf}, @code{fx} or @code{fy}) and precedence @var{P}
|
||
(see appendix iv for a list of predefined operators).
|
||
|
||
Note that if there is a preexisting operator with the same name and
|
||
type, this operator will be discarded. Also, @code{','} may not be defined
|
||
as an operator, and it is not allowed to have the same for an infix and
|
||
a posfix operator.
|
||
|
||
@item current_op(@var{P},@var{T},@var{F}) [ISO]
|
||
@findex current_op/3
|
||
@syindex current_op/3
|
||
@cnindex current_op/3
|
||
Defines the relation: @var{P} is a currently defined operator of type
|
||
@var{T} and precedence @var{P}.
|
||
|
||
@item prompt(-@var{A},+@var{B})
|
||
@findex prompt/2
|
||
@syindex prompt/2
|
||
@cyindex prompt/2
|
||
Changes YAP input prompt from @var{A} to @var{B}.
|
||
|
||
@item initialization
|
||
@findex initialization/0
|
||
@syindex initialization/0
|
||
@cnindex initialization/0
|
||
Execute the goals defined by initialization/1. Only the first answer is
|
||
considered.
|
||
|
||
@item prolog_initialization(@var{G})
|
||
@findex prolog_initialization/1
|
||
@saindex prolog_initialization/1
|
||
@cnindex prolog_initialization/1
|
||
Add a goal to be executed on system initialization. This is compatible
|
||
with SICStus Prolog's @code{initialization/1}.
|
||
|
||
@item version
|
||
@findex version/0
|
||
@saindex version/0
|
||
@cnindex version/0
|
||
Write YAP's boot message.
|
||
|
||
@item version(-@var{Message})
|
||
@findex version/1
|
||
@syindex version/1
|
||
@cnindex version/1
|
||
Add a message to be written when yap boots or after aborting. It is not
|
||
possible to remove messages.
|
||
|
||
@item prolog_load_context(?@var{Key}, ?@var{Value})
|
||
@findex prolog_load_context/2
|
||
@syindex prolog_load_context/2
|
||
@cnindex prolog_load_context/2
|
||
Obtain information on what is going on in the compilation process. The
|
||
following keys are available:
|
||
|
||
@table @code
|
||
|
||
@item directory
|
||
@findex directory (prolog_load_context/2 option)
|
||
@*
|
||
Full name for the directory where YAP is currently consulting the
|
||
file.
|
||
|
||
@item file
|
||
@findex file (prolog_load_context/2 option)
|
||
@*
|
||
Full name for the file currently being consulted. Notice that included
|
||
filed are ignored.
|
||
|
||
@item module
|
||
@findex module (prolog_load_context/2 option)
|
||
@*
|
||
Current source module.
|
||
|
||
@item source
|
||
@findex file (prolog_load_context/2 option)
|
||
@*
|
||
Full name for the file currently being read in, which may be consulted,
|
||
reconsulted, or included.
|
||
|
||
@item stream
|
||
@findex file (prolog_load_context/2 option)
|
||
@*
|
||
Stream currently being read in.
|
||
|
||
@item term_position
|
||
@findex file (prolog_load_context/2 option)
|
||
@*
|
||
Stream position at the stream currently being read in.
|
||
@end table
|
||
|
||
|
||
@end table
|
||
|
||
@node Library, Extensions, Builtins, Top
|
||
|
||
@chapter Library Predicates
|
||
|
||
Library files reside in the library_directory path (set by the
|
||
@code{LIBDIR} variable in the Makefile for YAP). Currently,
|
||
most files in the library are from the Edinburgh Prolog library.
|
||
|
||
@menu
|
||
|
||
Library, Extensions, Builtins, Top
|
||
* Association Lists:: Binary Tree Implementation of Association Lists
|
||
* AVL Trees:: Predicates to add and lookup balanced binary trees.
|
||
* Heaps:: Labelled binary tree where the key of each node is less
|
||
than or equal to the keys of its sons
|
||
* Lists:: List Manipulation
|
||
* Ordered Sets:: Ordered Set Manipulation
|
||
* Pseudo Random:: Pseudo Random Numbers
|
||
* Queues:: Queue Manipulation
|
||
* Random:: Random Numbers
|
||
* RegExp:: Regular Expression Manipulation
|
||
* Splay Trees:: Splay Trees
|
||
* String I/O:: Writing To and Reading From Strings
|
||
* System:: System Utilities
|
||
* Terms:: Utilities on Terms
|
||
* Timeout:: Call With Timeout
|
||
* Trees:: Updatable Binary Trees
|
||
* UGraphs:: Unweighted Graphs
|
||
|
||
|
||
@end menu
|
||
|
||
@node Association Lists, AVL Trees, , Library
|
||
@section Association Lists
|
||
@cindex association list
|
||
|
||
The following association list manipulation predicates are available
|
||
once included with the @code{use_module(library(assoc))} command.
|
||
|
||
@table @code
|
||
@item assoc_to_list(+@var{Assoc},?@var{List})
|
||
@findex assoc_to_list/2
|
||
@syindex assoc_to_list/2
|
||
@cnindex assoc_to_list/2
|
||
Given an association list @var{Assoc} unify @var{List} with a list of
|
||
the form @var{Key-Val}, where the elements @var{Key} are in ascending
|
||
order.
|
||
|
||
@item empty_assoc(+@var{Assoc})
|
||
@findex empty_assoc/1
|
||
@syindex empty_assoc/1
|
||
@cnindex empty_assoc/1
|
||
Succeeds if association list @var{Assoc} is empty.
|
||
|
||
@item gen_assoc(+@var{Assoc},?@var{Key},?@var{Value})
|
||
@findex gen_assoc/3
|
||
@syindex gen_assoc/3
|
||
@cnindex gen_assoc/3
|
||
Given the association list @var{Assoc}, unify @var{Key} and @var{Value}
|
||
with two associated elements. It can be used to enumerate all elements
|
||
in the association list.
|
||
|
||
@item get_assoc(+@var{Key},+@var{Assoc},?@var{Value})
|
||
@findex get_assoc/3
|
||
@syindex get_assoc/3
|
||
@cnindex get_assoc/3
|
||
If @var{Key} is one of the elements in the association list @var{Assoc},
|
||
return the associated value.
|
||
|
||
@item get_assoc(+@var{Key},+@var{Assoc},?@var{Value},+@var{NAssoc},?@var{NValue})
|
||
@findex get_assoc/5
|
||
@syindex get_assoc/5
|
||
@cnindex get_assoc/5
|
||
If @var{Key} is one of the elements in the association list @var{Assoc},
|
||
return the associated value @var{Value} and a new association list
|
||
@var{NAssoc} where @var{Key} is associated with @var{NValue}.
|
||
|
||
@item list_to_assoc(+@var{List},?@var{Assoc})
|
||
@findex list_to_assoc/2
|
||
@syindex list_to_assoc/2
|
||
@cnindex list_to_assoc/2
|
||
Given a list @var{List} such that each element of @var{List} is of the
|
||
form @var{Key-Val}, and all the @var{Keys} are unique, @var{Assoc} is
|
||
the corresponding association list.
|
||
|
||
@item map_assoc(+@var{Pred},+@var{Assoc},?@var{New})
|
||
@findex map_assoc/3
|
||
@syindex map_assoc/3
|
||
@cnindex map_assoc/3
|
||
Given the binary predicate name @var{Pred} and the association list
|
||
@var{Assoc}, @var{New} in an association list with keys in @var{Assoc},
|
||
and such that if @var{Key-Val} is in @var{Assoc}, and @var{Key-Ans} is in
|
||
@var{New}, then @var{Pred}(@var{Val},@var{Ans}) holds.
|
||
|
||
@item ord_list_to_assoc(+@var{List},?@var{Assoc})
|
||
@findex ord_list_to_assoc/2
|
||
@syindex ord_list_to_assoc/2
|
||
@cnindex ord_list_to_assoc/2
|
||
Given an ordered list @var{List} such that each element of @var{List} is
|
||
of the form @var{Key-Val}, and all the @var{Keys} are unique, @var{Assoc} is
|
||
the corresponding association list.
|
||
|
||
@item put_assoc(+@var{Key},+@var{Assoc},+@var{Val},+@var{New})
|
||
@findex put_assoc/4
|
||
@syindex put_assoc/4
|
||
@cnindex put_assoc/4
|
||
The association list @var{New} includes and element of association
|
||
@var{key} with @var{Val}, and all elements of @var{Assoc} that did not
|
||
have key @var{Key}.
|
||
|
||
@end table
|
||
|
||
@node AVL Trees, Heaps, Association Lists, Library
|
||
@section AVL Trees
|
||
@cindex AVL trees
|
||
|
||
AVL trees are balanced search binary trees. They are named after their
|
||
inventors, Adelson-Velskii and Landis, and they were the first
|
||
dynamically balanced trees to be proposed. The YAP AVL tree manipulation
|
||
predicates library uses code originally written by Martin van Emdem and
|
||
published in the Logic Programming Newsletter, Autumn 1981. A bug in
|
||
this code was fixed by Philip Vasey, in the Logic Programming
|
||
Newsletter, Summer 1982. The library currently only includes routines to
|
||
insert and lookup elements in the tree.
|
||
|
||
@table @code
|
||
@item avl_insert(+@var{Key},?@var{Value},+@var{T0},+@var{TF})
|
||
@findex avl_insert/4
|
||
@snindex avl_insert/4
|
||
@cnindex avl_insert/4
|
||
Add an element with key @var{Key} and @var{Value} to the AVL tree
|
||
@var{T0} creating a new AVL tree @var{TF}. Duplicated elements are
|
||
allowed.
|
||
|
||
@item avl_lookup(+@var{Key},-@var{Value},+@var{T})
|
||
@findex avl_lookup/3
|
||
@snindex avl_lookup/3
|
||
@cnindex avl_lookup/3
|
||
Lookup an element with key @var{Key} in the AVL tree
|
||
@var{T}, returning the value @var{Value}.
|
||
|
||
@end table
|
||
|
||
@node Heaps, Lists, AVL Trees, Library
|
||
@section Heaps
|
||
@cindex heap
|
||
|
||
A heap is a labelled binary tree where the key of each node is less than
|
||
or equal to the keys of its sons. The point of a heap is that we can
|
||
keep on adding new elements to the heap and we can keep on taking out
|
||
the minimum element. If there are N elements total, the total time is
|
||
O(NlgN). If you know all the elements in advance, you are better off
|
||
doing a merge-sort, but this file is for when you want to do say a
|
||
best-first search, and have no idea when you start how many elements
|
||
there will be, let alone what they are.
|
||
|
||
The following heap manipulation routines are available once included
|
||
with the @code{use_module(library(heaps))} command.
|
||
|
||
@table @code
|
||
|
||
@item add_to_heap(+@var{Heap},+@var{key},+@var{Datum},-@var{NewHeap})
|
||
@findex add_to_heap/4
|
||
@syindex add_to_heap/4
|
||
@cnindex add_to_heap/4
|
||
Inserts the new @var{Key-Datum} pair into the heap. The insertion is not
|
||
stable, that is, if you insert several pairs with the same @var{Key} it
|
||
is not defined which of them will come out first, and it is possible for
|
||
any of them to come out first depending on the history of the heap.
|
||
|
||
@item get_from_heap(+@var{Heap},-@var{key},-@var{Datum},-@var{Heap})
|
||
@findex get_from_heap/4
|
||
@syindex get_from_heap/4
|
||
@cnindex get_from_heap/4
|
||
Returns the @var{Key-Datum} pair in @var{OldHeap} with the smallest
|
||
@var{Key}, and also a @var{Heap} which is the @var{OldHeap} with that
|
||
pair deleted.
|
||
|
||
@item heap_size(+@var{Heap}, -@var{Size})
|
||
@findex heap_size/2
|
||
@syindex heap_size/2
|
||
@cnindex heap_size/2
|
||
Reports the number of elements currently in the heap.
|
||
|
||
@item heap_to_list(+@var{Heap}, -@var{List})
|
||
@findex heap_to_list/2
|
||
@syindex heap_to_list/2
|
||
@cnindex heap_to_list/2
|
||
Returns the current set of @var{Key-Datum} pairs in the @var{Heap} as a
|
||
@var{List}, sorted into ascending order of @var{Keys}.
|
||
|
||
@item list_to_heap(+@var{List}, -@var{Heap})
|
||
@findex list_to_heap/2
|
||
@syindex list_to_heap/2
|
||
@cnindex list_to_heap/2
|
||
Takes a list of @var{Key-Datum} pairs (such as keysort could be used to sort)
|
||
and forms them into a heap.
|
||
|
||
@item min_of_heap(+@var{Heap}, -@var{Key}, -@var{Datum})
|
||
@findex min_of_heap/3
|
||
@syindex min_of_heap/3
|
||
@cnindex min_of_heap/3
|
||
Returns the Key-Datum pair at the top of the heap (which is of course
|
||
the pair with the smallest Key), but does not remove it from the heap.
|
||
|
||
@item min_of_heap(+@var{Heap}, -@var{Key1}, -@var{Datum1},
|
||
-@var{Key2}, -@var{Datum2})
|
||
@findex min_of_heap/5
|
||
@syindex min_of_heap/5
|
||
@cnindex min_of_heap/5
|
||
Returns the smallest (Key1) and second smallest (Key2) pairs in the
|
||
heap, without deleting them.
|
||
@end table
|
||
|
||
@node Lists, Ordered Sets, Heaps, Library
|
||
@section List Manipulation
|
||
@cindex list manipulation
|
||
|
||
The following list manipulation routines are available once included
|
||
with the @code{use_module(library(lists))} command.
|
||
|
||
@table @code
|
||
|
||
@item append(?@var{Prefix},?@var{Suffix},?@var{Combined})
|
||
@findex append/3
|
||
@syindex append/3
|
||
@cnindex append/3
|
||
True when all three arguments are lists, and the members of
|
||
@var{Combined} are the members of @var{Prefix} followed by the members of @var{Suffix}.
|
||
It may be used to form @var{Combined} from a given @var{Prefix}, @var{Suffix} or to take
|
||
a given @var{Combined} apart.
|
||
|
||
@item delete(+@var{List}, ?@var{Element}, ?@var{Residue})
|
||
@findex delete/3
|
||
@syindex delete/3
|
||
@cnindex delete/3
|
||
True when @var{List} is a list, in which @var{Element} may or may not
|
||
occur, and @var{Residue} is a copy of @var{List} with all elements
|
||
identical to @var{Element} deleted.
|
||
|
||
@item is_list(+@var{List})
|
||
@findex is_list/1
|
||
@syindex is_list/1
|
||
@cnindex is_list/1
|
||
True when @var{List} is a proper list. That is, @var{List}
|
||
is bound to the empty list (nil) or a term with functor '.' and arity 2.
|
||
|
||
@item last(+@var{List},?@var{Last})
|
||
@findex last/2
|
||
@syindex last/2
|
||
@cnindex last/2
|
||
True when @var{List} is a list and @var{Last} is identical to its last element.
|
||
|
||
@item list_concat(+@var{Lists},?@var{List})
|
||
@findex list_concat/2
|
||
@snindex list_concat/2
|
||
@cnindex list_concat/2
|
||
True when @var{Lists} is a list of lists and @var{List} is the
|
||
concatenation of @var{Lists}.
|
||
|
||
@item member(?@var{Element}, ?@var{Set})
|
||
@findex member/2
|
||
@syindex member/2
|
||
@cnindex member/2
|
||
True when @var{Set} is a list, and @var{Element} occurs in it. It may be used
|
||
to test for an element or to enumerate all the elements by backtracking.
|
||
|
||
@item memberchk(+@var{Element}, +@var{Set})
|
||
@findex memberchk/2
|
||
@syindex memberchk/2
|
||
@cnindex memberchk/2
|
||
As @code{member/2}, but may only be used to test whether a known
|
||
@var{Element} occurs in a known Set. In return for this limited use, it
|
||
is more efficient when it is applicable.
|
||
|
||
@item nth0(+@var{N}, +@var{List}, ?@var{Elem})
|
||
@findex nth0/2
|
||
@syindex nth0/2
|
||
@cnindex nth0/2
|
||
True when @var{Elem} is the Nth member of @var{List},
|
||
counting the first as element 0. (That is, throw away the first
|
||
N elements and unify @var{Elem} with the next.) It can only be used to
|
||
select a particular element given the list and index. For that
|
||
task it is more efficient than @code{member/2}
|
||
|
||
@item nth(+@var{N}, +@var{List}, ?@var{Elem})
|
||
@findex nth/2
|
||
@syindex nth/2
|
||
@cnindex nth/2
|
||
The same as @code{nth0/3}, except that it counts from
|
||
1, that is @code{nth(1, [H|_], H)}.
|
||
|
||
@item nth0(+@var{N}, ?@var{List}, ?@var{Elem}, ?@var{Rest})
|
||
@findex nth0/4
|
||
@syindex nth0/4
|
||
@cnindex nth0/4
|
||
Unifies @var{Elem} with the Nth element of @var{List},
|
||
counting from 0, and @var{Rest} with the other elements. It can be used
|
||
to select the Nth element of @var{List} (yielding @var{Elem} and @var{Rest}), or to
|
||
insert @var{Elem} before the Nth (counting from 1) element of @var{Rest}, when
|
||
it yields @var{List}, e.g. @code{nth0(2, List, c, [a,b,d,e])} unifies List with
|
||
@code{[a,b,c,d,e]}. nth is the same except that it counts from 1. nth
|
||
can be used to insert Elem after the Nth element of Rest.
|
||
|
||
@item permutation(+@var{List},?@var{Perm})
|
||
@findex permutation/2
|
||
@syindex permutation/2
|
||
@cnindex permutation/2
|
||
True when @var{List} and @var{Perm} are permutations of each other.
|
||
|
||
@item remove_dups(+@var{List}, ?@var{Pruned})
|
||
@findex remove_dups/2
|
||
@syindex remove_dups/2
|
||
@cnindex remove_dups/2
|
||
Removes duplicated elements from @var{List}. Beware: if the @var{List} has
|
||
non-ground elements, the result may surprise you.
|
||
|
||
@item reverse(+@var{List}, ?@var{Reversed})
|
||
@findex reverse/2
|
||
@syindex reverse/2
|
||
@cnindex reverse/2
|
||
True when @var{List} and @var{Reversed} are lists with the same elements
|
||
but in opposite orders.
|
||
|
||
@item same_length(?@var{List1}, ?@var{List2})
|
||
@findex same_length/2
|
||
@syindex same_length/2
|
||
@cnindex same_length/2
|
||
True when @var{List1} and @var{List2} are both lists and have the same number
|
||
of elements. No relation between the values of their elements is
|
||
implied.
|
||
Modes @code{same_length(-,+)} and @code{same_length(+,-)} generate either list given
|
||
the other; mode @code{same_length(-,-)} generates two lists of the same length,
|
||
in which case the arguments will be bound to lists of length 0, 1, 2, ...
|
||
|
||
@item select(?@var{Element}, ?@var{Set}, ?@var{Residue})
|
||
@findex select/3
|
||
@syindex select/3
|
||
@cnindex select/3
|
||
True when @var{Set} is a list, @var{Element} occurs in @var{Set}, and @var{Residue} is
|
||
everything in @var{Set} except @var{Element} (things stay in the same order).
|
||
|
||
@item sublist(?@var{Sublist}, ?@var{List})
|
||
@findex sublist/2
|
||
@syindex sublist/2
|
||
@cnindex sublist/2
|
||
True when both @code{append(_,Sublist,S)} and @code{append(S,_,List)} hold.
|
||
|
||
@item suffix(?@var{Suffix}, ?@var{List})
|
||
@findex suffix/2
|
||
@syindex suffix/2
|
||
@cnindex suffix/2
|
||
Holds when @code{append(_,Suffix,List)} holds.
|
||
|
||
@item sum_list(?@var{Numbers}, ?@var{Total})
|
||
@findex sum_list/2
|
||
@snindex sum_list/2
|
||
@cnindex sum_list/2
|
||
True when @var{Numbers} is a list of integers, and @var{Total} is their sum.
|
||
|
||
@item sumlist(?@var{Numbers}, ?@var{Total})
|
||
@findex sumlist/2
|
||
@syindex sumlist/2
|
||
@cnindex sumlist/2
|
||
True when @var{Numbers} is a list of integers, and @var{Total} is their
|
||
sum. The same as @code{sum_list/2}, please do use @code{sum_list/2}
|
||
instead.
|
||
|
||
@end table
|
||
|
||
@node Ordered Sets, Pseudo Random, Lists, Library
|
||
@section Ordered Sets
|
||
@cindex ordered set
|
||
|
||
The following ordered set manipulation routines are available once
|
||
included with the @code{use_module(library(ordsets))} command. An
|
||
ordered set is represented by a list having unique and ordered
|
||
elements. Output arguments are guaranteed to be ordered sets, if the
|
||
relevant inputs are. This is a slightly patched version of Richard
|
||
O'Keefe's original library.
|
||
|
||
@table @code
|
||
@item list_to_ord_set(+@var{List}, ?@var{Set})
|
||
@findex list_to_ord_set/2
|
||
@syindex list_to_ord_set/2
|
||
@cnindex list_to_ord_set/2
|
||
Holds when @var{Set} is the ordered representation of the set
|
||
represented by the unordered representation @var{List}.
|
||
|
||
@item merge(+@var{List1}, +@var{List2}, -@var{Merged})
|
||
@findex merge/3
|
||
@syindex merge/3
|
||
@cnindex merge/3
|
||
Holds when @var{Merged} is the stable merge of the two given lists.
|
||
|
||
Notice that @code{merge/3} will not remove duplicates, so merging
|
||
ordered sets will not necessarily result in an ordered set. Use
|
||
@code{ord_union/3} instead.
|
||
|
||
@item ord_add_element(+@var{Set1}, +@var{Element}, ?@var{Set2})
|
||
@findex ord_add_element/3
|
||
@syindex ord_add_element/3
|
||
@cnindex ord_add_element/3
|
||
Insering @var{Element} in @var{Set1} returns @var{Set2}. It should give
|
||
exactly the same result as @code{merge(Set1, [Element], Set2)}, but a
|
||
bit faster, and certainly more clearly. The same as @code{ord_insert/3}.
|
||
|
||
@item ord_del_element(+@var{Set1}, +@var{Element}, ?@var{Set2})
|
||
@findex ord_del_element/3
|
||
@syindex ord_del_element/3
|
||
@cnindex ord_del_element/3
|
||
Removing @var{Element} from @var{Set1} returns @var{Set2}.
|
||
|
||
@item ord_disjoint(+@var{Set1}, +@var{Set2})
|
||
@findex ord_disjoint/2
|
||
@syindex ord_disjoint/2
|
||
@cnindex ord_disjoint/2
|
||
Holds when the two ordered sets have no element in common.
|
||
|
||
@item ord_member(+@var{Element}, +@var{Set})
|
||
@findex ord_member/2
|
||
@syindex ord_member/2
|
||
@cnindex ord_member/2
|
||
Holds when @var{Element} is a member of @var{Set}.
|
||
|
||
@item ord_insert(+@var{Set1}, +@var{Element}, ?@var{Set2})
|
||
@findex ord_insert/3
|
||
@syindex ord_insert/3
|
||
@cnindex ord_insert/3
|
||
Insering @var{Element} in @var{Set1} returns @var{Set2}. It should give
|
||
exactly the same result as @code{merge(Set1, [Element], Set2)}, but a
|
||
bit faster, and certainly more clearly. The same as @code{ord_add_element/3}.
|
||
|
||
@item ord_intersect(+@var{Set1}, +@var{Set2})
|
||
@findex ord_intersect/2
|
||
@syindex ord_intersect/2
|
||
@cnindex ord_intersect/2
|
||
Holds when the two ordered sets have at least one element in common.
|
||
|
||
@item ord_intersection(+@var{Set1}, +@var{Set2}, ?@var{Intersection})
|
||
@findex ord_intersect/3
|
||
@syindex ord_intersect/3
|
||
@cnindex ord_intersect/3
|
||
Holds when Intersection is the ordered representation of @var{Set1}
|
||
and @var{Set2}.
|
||
|
||
@item ord_seteq(+@var{Set1}, +@var{Set2})
|
||
@findex ord_seteq/2
|
||
@syindex ord_seteq/2
|
||
@cnindex ord_seteq/2
|
||
Holds when the two arguments represent the same set.
|
||
|
||
@item ord_setproduct(+@var{Set1}, +@var{Set2}, -@var{Set})
|
||
@findex ord_setproduct/3
|
||
@syindex ord_setproduct/3
|
||
@cnindex ord_setproduct/3
|
||
If Set1 and Set2 are ordered sets, Product will be an ordered
|
||
set of x1-x2 pairs.
|
||
|
||
@item ord_subset(+@var{Set1}, +@var{Set2})
|
||
@findex ordsubset/2
|
||
@syindex ordsubset/2
|
||
@cnindex ordsubset/2
|
||
Holds when every element of the ordered set @var{Set1} appears in the
|
||
ordered set @var{Set2}.
|
||
|
||
@item ord_subtract(+@var{Set1}, +@var{Set2}, ?@var{Difference})
|
||
@findex ord_subtract/3
|
||
@syindex ord_subtract/3
|
||
@cnindex ord_subtract/3
|
||
Holds when @var{Difference} contains all and only the elements of @var{Set1}
|
||
which are not also in @var{Set2}.
|
||
|
||
@item ord_symdiff(+@var{Set1}, +@var{Set2}, ?@var{Difference})
|
||
@findex ord_symdiff/3
|
||
@syindex ord_symdiff/3
|
||
@cnindex ord_symdiff/3
|
||
Holds when @var{Difference} is the symmetric difference of @var{Set1}
|
||
and @var{Set2}.
|
||
|
||
@item ord_union(+@var{Sets}, ?@var{Union})
|
||
@findex ord_union/2
|
||
@syindex ord_union/2
|
||
@cnindex ord_union/2
|
||
Holds when @var{Union} is the union of the lists @var{Sets}.
|
||
|
||
@item ord_union(+@var{Set1}, +@var{Set2}, ?@var{Union})
|
||
@findex ord_union/3
|
||
@syindex ord_union/3
|
||
@cnindex ord_union/3
|
||
Holds when @var{Union} is the union of @var{Set1} and @var{Set2}.
|
||
|
||
@item ord_union(+@var{Set1}, +@var{Set2}, ?@var{Union}, ?@var{Diff})
|
||
@findex ord_union/4
|
||
@syindex ord_union/4
|
||
@cnindex ord_union/4
|
||
Holds when @var{Union} is the union of @var{Set1} and @var{Set2} and
|
||
@var{Diff} is the difference.
|
||
|
||
@end table
|
||
|
||
@node Pseudo Random, Queues, Ordered Sets, Library
|
||
@section Pseudo Random Number Integer Generator
|
||
@cindex pseudo random
|
||
|
||
The following routines produce random non-negative integers in the range
|
||
0 .. 2^(w-1) -1, where w is the word size available for integers, e.g.,
|
||
32 for Intel machines and 64 for Alpha machines. Note that the numbers
|
||
generated by this random number generator are repeatable. This generator
|
||
was originally written by Allen Van Gelder and is based on Knuth Vol 2.
|
||
|
||
@table @code
|
||
@item rannum(-@var{I})
|
||
@findex rannum/1
|
||
@snindex rannum/1
|
||
@cnindex rannum/1
|
||
Produces a random non-negative integer @var{I} whose low bits are not
|
||
all that random, so it should be scaled to a smaller range in general.
|
||
The integer @var{I} is in the range 0 .. 2^(w-1) - 1. You can use:
|
||
@example
|
||
rannum(X) :- yap_flag(max_integer,MI), rannum(R), X is R/MI.
|
||
@end example
|
||
to obtain a floating point number uniformly distributed between 0 and 1.
|
||
|
||
@item ranstart
|
||
@findex ranstart/0
|
||
@snindex ranstart/0
|
||
@cnindex ranstart/0
|
||
Initialise the random number generator using a built-in seed. The
|
||
@code{ranstart/0} built-in is always called by the system when loading
|
||
the package.
|
||
|
||
@item ranstart(+@var{Seed})
|
||
@findex ranstart/1
|
||
@snindex ranstart/1
|
||
@cnindex ranstart/1
|
||
Initialise the random number generator with user-defined @var{Seed}. The
|
||
same @var{Seed} always produces the same sequence of numbers.
|
||
|
||
@item ranunif(+@var{Range},-@var{I})
|
||
@findex ranunif/2
|
||
@snindex ranunif/2
|
||
@cnindex ranunif/2
|
||
@code{ranunif/2} produces a uniformly distributed non-negative random
|
||
integer @var{I} over a caller-specified range @var{R}. If range is @var{R},
|
||
the result is in 0 .. @var{R}-1.
|
||
|
||
@end table
|
||
|
||
@node Queues, Random, Pseudo Random, Library
|
||
@section Queues
|
||
@cindex queue
|
||
|
||
The following queue manipulation routines are available once
|
||
included with the @code{use_module(library(queues))} command. Queues are
|
||
implemented with difference lists.
|
||
|
||
@table @code
|
||
|
||
@item make_queue(+@var{Queue})
|
||
@findex make_queue/1
|
||
@syindex make_queue/1
|
||
@cnindex make_queue/1
|
||
Creates a new empty queue. It should only be used to create a new queue.
|
||
|
||
@item join_queue(+@var{Element}, +@var{OldQueue}, -@var{NewQueue})
|
||
@findex join_queue/3
|
||
@syindex join_queue/3
|
||
@cnindex join_queue/3
|
||
Adds the new element at the end of the queue.
|
||
|
||
@item list_join_queue(+@var{List}, +@var{OldQueue}, -@var{NewQueue})
|
||
@findex list_join_queue/3
|
||
@syindex list_join_queue/3
|
||
@cnindex list_join_queue/3
|
||
Ads the new elements at the end of the queue.
|
||
|
||
@item jump_queue(+@var{Element}, +@var{OldQueue}, -@var{NewQueue})
|
||
@findex jump_queue/3
|
||
@syindex jump_queue/3
|
||
@cnindex jump_queue/3
|
||
Adds the new element at the front of the list.
|
||
|
||
@item list_jump_queue(+@var{List}, +@var{OldQueue}, +@var{NewQueue})
|
||
@findex list_jump_queue/3
|
||
@syindex list_jump_queue/3
|
||
@cnindex list_jump_queue/3
|
||
Adds all the elements of @var{List} at the front of the queue.
|
||
|
||
@item head_queue(+@var{Queue}, ?@var{Head})
|
||
@findex head_queue/2
|
||
@syindex head_queue/2
|
||
@cnindex head_queue/2
|
||
Unifies Head with the first element of the queue.
|
||
|
||
@item serve_queue(+@var{OldQueue}, +@var{Head}, -@var{NewQueue})
|
||
@findex serve_queue/3
|
||
@syindex serve_queue/3
|
||
@cnindex serve_queue/3
|
||
Removes the first element of the queue for service.
|
||
|
||
@item empty_queue(+@var{Queue})
|
||
@findex empty_queue/1
|
||
@syindex empty_queue/1
|
||
@cnindex empty_queue/1
|
||
Tests whether the queue is empty.
|
||
|
||
@item length_queue(+@var{Queue}, -@var{Length})
|
||
@findex length_queue/2
|
||
@syindex length_queue/2
|
||
@cnindex length_queue/2
|
||
Counts the number of elements currently in the queue.
|
||
|
||
@item list_to_queue(+@var{List}, -@var{Queue})
|
||
@findex list_to_queue/2
|
||
@syindex list_to_queue/2
|
||
@cnindex list_to_queue/2
|
||
Creates a new queue with the same elements as @var{List.}
|
||
|
||
@item queue_to_list(+@var{Queue}, -@var{List})
|
||
@findex queue_to_list/2
|
||
@syindex queue_to_list/2
|
||
@cnindex queue_to_list/2
|
||
Creates a new list with the same elements as @var{Queue}.
|
||
|
||
@end table
|
||
|
||
|
||
@node Random, RegExp, Queues, Library
|
||
@section Random Number Generator
|
||
@cindex queue
|
||
|
||
The following random number operations are included with the
|
||
@code{use_module(library(random))} command. Since Yap-4.3.19 Yap uses
|
||
the O'Keefe public-domain algorithm, based on the "Applied Statistics"
|
||
algorithm AS183.
|
||
|
||
@table @code
|
||
|
||
@item getrand(-@var{Key})
|
||
@findex getrand/1
|
||
@syindex getrand/1
|
||
@cnindex getrand/1
|
||
Unify @var{Key} with a term of the form @code{rand(X,Y,Z)} describing the
|
||
current state of the random number generator.
|
||
|
||
@item random(-@var{Number})
|
||
@findex random/1
|
||
@syindex random/1
|
||
@cnindex random/1
|
||
Unify @var{Number} with a floating-point number in the range @code{[0...1)}.
|
||
|
||
@item random(-@var{Number}, +@var{LOW}, +@var{HIGH})
|
||
@findex random/3
|
||
@syindex random/3
|
||
@cnindex random/3
|
||
Unify @var{Number} with a number in the range
|
||
@code{[LOW...HIGH)}. If both @var{LOW} and @var{HIGH} are
|
||
integers then @var{NUMBER} will also be an integer, otherwise
|
||
@var{NUMBER} will be a floating-point number.
|
||
|
||
@item randseq(+@var{LENGTH}, +@var{MAX}, -@var{Numbers})
|
||
@findex randseq/3
|
||
@syindex randseq/3
|
||
@cnindex randseq/3
|
||
Unify @var{Numbers} with a list of @var{LENGTH} unique random integers
|
||
in the range @code{[1<EFBFBD>...@var{MAX})}.
|
||
|
||
@item randset(+@var{LENGTH}, +@var{MAX}, -@var{Numbers})
|
||
@findex randset/3
|
||
@syindex randset/3
|
||
@cnindex randset/3
|
||
Unify @var{Numbers} with an ordered list of @var{LENGTH} unique random
|
||
integers in the range @code{[1<EFBFBD>...@var{MAX})}.
|
||
|
||
@item setrand(+@var{Key})
|
||
@findex setrand/1
|
||
@syindex setrand/1
|
||
@cnindex setrand/1
|
||
Use a term of the form @code{rand(X,Y,Z)} to set a new state for the
|
||
random number generator. The integer @code{X} must be in the range
|
||
@code{[1...30269)}, the integer @code{Y} must be in the range
|
||
@code{[1...30307)}, and the integer @code{Z} must be in the range
|
||
@code{[1...30323)}.
|
||
|
||
@end table
|
||
|
||
@node RegExp, Splay Trees, Random, Library
|
||
@section Regular Expressions
|
||
@cindex regular expressions
|
||
|
||
This library includes routines to determine whether a regular expression
|
||
matches part or all of a string. The routines can also return which
|
||
parts parts of the string matched the expression or subexpressions of
|
||
it. This library relies on Henry Spencer's @code{C}-package and is only
|
||
available in operating systems that support dynamic loading. The
|
||
@code{C}-code has been obtained from the sources of FreeBSD-4.0 and is
|
||
protected by copyright from Henry Spencer and from the Regents of the
|
||
University of California (see the file library/regex/COPYRIGHT for
|
||
further details).
|
||
|
||
Much of the description of regular expressions below is copied verbatim
|
||
from Henry Spencer's manual page.
|
||
|
||
A regular expression is zero or more branches, separated by ``|''. It
|
||
matches anything that matches one of the branches.
|
||
|
||
A branch is zero or more pieces, concatenated. It matches a match for
|
||
the first, followed by a match for the second, etc.
|
||
|
||
A piece is an atom possibly followed by ``*'', ``+'', or ``?''. An atom
|
||
followed by ``*'' matches a sequence of 0 or more matches of the atom.
|
||
An atom followed by ``+'' matches a sequence of 1 or more matches of the
|
||
atom. An atom followed by ``?'' matches a match of the atom, or the
|
||
null string.
|
||
|
||
An atom is a regular expression in parentheses (matching a match for the
|
||
regular expression), a range (see below), ``.'' (matching any single
|
||
character), ``^'' (matching the null string at the beginning of the
|
||
input string), ``$'' (matching the null string at the end of the input
|
||
string), a ``\'' followed by a single character (matching that
|
||
character), or a single character with no other significance (matching
|
||
that character).
|
||
|
||
A range is a sequence of characters enclosed in ``[]''. It normally
|
||
matches any single character from the sequence. If the sequence begins
|
||
with ``^'', it matches any single character not from the rest of the
|
||
sequence. If two characters in the sequence are separated by ``-'',
|
||
this is shorthand for the full list of ASCII characters between them
|
||
(e.g. ``[0-9]'' matches any decimal digit). To include a literal ``]''
|
||
in the sequence, make it the first character (following a possible
|
||
``^''). To include a literal ``-'', make it the first or last
|
||
character.
|
||
|
||
@table @code
|
||
|
||
@item regexp(+@var{RegExp},+@var{String},+@var{Opts})
|
||
@findex regexp/3
|
||
@snindex regexp/3
|
||
@cnindex regexp/3
|
||
|
||
Match regular expression @var{RegExp} to input string @var{String}
|
||
according to options @var{Opts}. The options may be:
|
||
@itemize @bullet
|
||
@item @code{nocase}: Causes upper-case characters in @var{String} to
|
||
be treated as lower case during the matching process.
|
||
@end itemize
|
||
|
||
@item regexp(+@var{RegExp},+@var{String},+@var{Opts},@var{SubMatchVars})
|
||
@findex regexp/4
|
||
@snindex regexp/4
|
||
@cnindex regexp/4
|
||
|
||
Match regular expression @var{RegExp} to input string @var{String}
|
||
according to options @var{Opts}. The variable @var{SubMatchVars} should
|
||
be originally a list of unbound variables all will contain a sequence of
|
||
matches, that is, the head of @var{SubMatchVars} will contain the
|
||
characters in @var{String} that matched the leftmost parenthesized
|
||
subexpression within @var{RegExp}, the next head of list will contain
|
||
the characters that matched the next parenthesized subexpression to the
|
||
right in @var{RegExp}, and so on.
|
||
|
||
The options may be:
|
||
@itemize @bullet
|
||
@item @code{nocase}: Causes upper-case characters in @var{String} to
|
||
be treated as lower case during the matching process.
|
||
@item @code{indices}: Changes what is stored in
|
||
@var{SubMatchVars}. Instead of storing the matching characters from
|
||
@var{String}, each variable will contain a term of the form @var{IO-IF}
|
||
giving the indices in @var{String} of the first and last characters in
|
||
the matching range of characters.
|
||
|
||
@end itemize
|
||
|
||
In general there may be more than one way to match a regular expression
|
||
to an input string. For example, consider the command
|
||
@example
|
||
regexp("(a*)b*","aabaaabb", [], [X,Y])
|
||
@end example
|
||
Considering only the rules given so far, @var{X} and @var{Y} could end up
|
||
with the values @code{"aabb"} and @code{"aa"}, @code{"aaab"} and
|
||
@code{"aaa"}, @code{"ab"} and @code{"a"}, or any of several other
|
||
combinations. To resolve this potential ambiguity regexp chooses among
|
||
alternatives using the rule ``first then longest''. In other words, it
|
||
considers the possible matches in order working from left to right
|
||
across the input string and the pattern, and it attempts to match longer
|
||
pieces of the input string before shorter ones. More specifically, the
|
||
following rules apply in decreasing order of priority:
|
||
|
||
|
||
@enumerate
|
||
@item If a regular expression could match two different parts of an
|
||
input string then it will match the one that begins earliest.
|
||
|
||
@item If a regular expression contains "|" operators then the leftmost matching sub-expression is chosen.
|
||
|
||
@item In *, +, and ? constructs, longer matches are chosen in preference to shorter ones.
|
||
|
||
@item In sequences of expression components the components are considered from left to right.
|
||
@end enumerate
|
||
|
||
In the example from above, @code{"(a*)b*"} matches @code{"aab"}: the
|
||
@code{"(a*)"} portion of the pattern is matched first and it consumes
|
||
the leading @code{"aa"}; then the @code{"b*"} portion of the pattern
|
||
consumes the next @code{"b"}. Or, consider the following example:
|
||
@example
|
||
regexp("(ab|a)(b*)c", "abc", [], [X,Y,Z])
|
||
@end example
|
||
|
||
After this command @var{X} will be @code{"abc"}, @var{Y} will be
|
||
@code{"ab"}, and @var{Z} will be an empty string. Rule 4 specifies that
|
||
@code{"(ab|a)"} gets first shot at the input string and Rule 2 specifies
|
||
that the @code{"ab"} sub-expression is checked before the @code{"a"}
|
||
sub-expression. Thus the @code{"b"} has already been claimed before the
|
||
@code{"(b*)"} component is checked and @code{(b*)} must match an empty string.
|
||
|
||
@end table
|
||
|
||
@node Splay Trees, String I/O, RegExp, Library
|
||
@section Splay Trees
|
||
@cindex splay trees
|
||
|
||
Splay trees are explained in the paper "Self-adjusting Binary Search
|
||
Trees", by D.D. Sleator and R.E. Tarjan, JACM, vol. 32, No.3, July 1985,
|
||
p. 668. They are designed to support fast insertions, deletions and
|
||
removals in binary search trees without the complexity of traditional
|
||
balanced trees. The key idea is to allow the tree to become
|
||
unbalanced. To make up for this, whenever we find a node, we move it up
|
||
to the top. We use code by Vijay Saraswat originally posted to the Prolog
|
||
mailing-list.
|
||
|
||
@table @code
|
||
|
||
@item splay_access(-@var{Return},+@var{Key},?@var{Val},+@var{Tree},-@var{NewTree})
|
||
@findex splay_access/5
|
||
@snindex splay_access/5
|
||
@cnindex splay_access/5
|
||
If item @var{Key} is in tree @var{Tree}, return its @value{Val} and unify
|
||
@var{Return} with @code{true}. Otherwise unify @var{Return} with
|
||
@code{null}. The variable @var{NewTree} unifies with the new tree.
|
||
|
||
@item splay_delete(+@var{Key},?@var{Val},+@var{Tree},-@var{NewTree})
|
||
@findex splay_delete/4
|
||
@snindex splay_delete/4
|
||
@cnindex splay_delete/4
|
||
Delete item @var{Key} from tree @var{Tree}, assuming that it is present
|
||
already. The variable @var{Val} unifies with a value for key @var{Key},
|
||
and the variable @var{NewTree} unifies with the new tree. The predicate
|
||
will fail if @var{Key} is not present.
|
||
|
||
@item splay_insert(+@var{Key},?@var{Val},+@var{Tree},-@var{NewTree})
|
||
@findex splay_insert/4
|
||
@snindex splay_insert/4
|
||
@cnindex splay_insert/4
|
||
Insert item @var{Key} in tree @var{Tree}, assuming that it is not there
|
||
already. The variable @var{Val} unifies with a value for key @var{Key},
|
||
and the variable @var{NewTree} unifies with the new tree. In our
|
||
implementation, @var{Key} is not inserted if it is already there:
|
||
rather it is unified with the item already in the tree.
|
||
|
||
@item splay_join(+@var{LeftTree},+@var{RighTree},-@var{NewTree})
|
||
@findex splay_join/3
|
||
@snindex splay_join/3
|
||
@cnindex splay_join/3
|
||
Combine trees @var{LeftTree} and @var{RighTree} into a single
|
||
tree@var{NewTree} containing all items from both trees. This operation
|
||
assumes that all items in @var{LeftTree} are less than all those in
|
||
@var{RighTree} and destroys both @var{LeftTree} and @var{RighTree}.
|
||
|
||
@item splay_split(+@var{Key},?@var{Val},+@var{Tree},-@var{LeftTree},-@var{RightTree})
|
||
@findex splay_split/5
|
||
@snindex splay_split/5
|
||
@cnindex splay_split/5
|
||
Construct and return two trees @var{LeftTree} and @var{RightTree}, where
|
||
@var{LeftTree} contains all items in @var{Tree} less than @var{Key}, and
|
||
@var{RightTree} contains all items in @var{Tree} greater than
|
||
@var{Key}. This operations destroys @var{Tree}.
|
||
|
||
@end table
|
||
|
||
@node String I/O, System, Splay Trees, Library
|
||
@section Reading From and Writing To Strings
|
||
@cindex string I/O
|
||
|
||
From Version 4.3.2 onwards YAP implements SICStus Prolog compatible
|
||
String I/O. The library allows users to read from and write to a memory
|
||
buffer as if it was a file. The memory buffer is built from or converted
|
||
to a string of character codes by the routines in library. Therefore, if
|
||
one wants to read from a string the string must be fully instantiated
|
||
before the library builtin opens the string for reading. These commands
|
||
are available through the @code{use_module(library(charsio))} command.
|
||
|
||
@table @code
|
||
|
||
@item format_to_chars(+@var{Form}, +@var{Args}, -@var{Result})
|
||
@findex format_to_chars/3
|
||
@syindex format_to_chars/3
|
||
@cnindex format_to_chars/3
|
||
|
||
Execute the built-in procedure @code{format/2} with form @var{Form} and
|
||
arguments @var{Args} outputting the result to the string of character
|
||
codes @var{Result}.
|
||
|
||
@item format_to_chars(+@var{Form}, +@var{Args}, -@var{Result0}, -@var{Result})
|
||
@findex format_to_chars/4
|
||
@syindex format_to_chars/4
|
||
@cnindex format_to_chars/4
|
||
|
||
Execute the built-in procedure @code{format/2} with form @var{Form} and
|
||
arguments @var{Args} outputting the result to the difference list of
|
||
character codes @var{Result-Result0}.
|
||
|
||
@item write_to_chars(+@var{Term}, -@var{Result})
|
||
@findex write_to_chars/2
|
||
@syindex write_to_chars/2
|
||
@cnindex write_to_chars/2
|
||
|
||
Execute the built-in procedure @code{write/1} with argument @var{Term}
|
||
outputting the result to the string of character codes @var{Result}.
|
||
|
||
@item write_to_chars(+@var{Term}, -@var{Result0}, -@var{Result})
|
||
@findex write_to_chars/3
|
||
@syindex write_to_chars/3
|
||
@cnindex write_to_chars/3
|
||
|
||
Execute the built-in procedure @code{write/1} with argument @var{Term}
|
||
outputting the result to the difference list of character codes
|
||
@var{Result-Result0}.
|
||
|
||
@item atom_to_chars(+@var{Atom}, -@var{Result})
|
||
@findex atom_to_chars/2
|
||
@syindex atom_to_chars/2
|
||
@cnindex atom_to_chars/2
|
||
|
||
Convert the atom @var{Atom} to the string of character codes
|
||
@var{Result}.
|
||
|
||
@item atom_to_chars(+@var{Atom}, -@var{Result0}, -@var{Result})
|
||
@findex atom_to_chars/3
|
||
@syindex atom_to_chars/3
|
||
@cnindex atom_to_chars/3
|
||
|
||
Convert the atom @var{Atom} to the difference list of character codes
|
||
@var{Result-Result0}.
|
||
|
||
@item number_to_chars(+@var{Number}, -@var{Result})
|
||
@findex number_to_chars/2
|
||
@syindex number_to_chars/2
|
||
@cnindex number_to_chars/2
|
||
|
||
Convert the number @var{Number} to the string of character codes
|
||
@var{Result}.
|
||
|
||
@item number_to_chars(+@var{Number}, -@var{Result0}, -@var{Result})
|
||
@findex number_to_chars/3
|
||
@syindex number_to_chars/3
|
||
@cnindex number_to_chars/3
|
||
|
||
Convert the atom @var{Number} to the difference list of character codes
|
||
@var{Result-Result0}.
|
||
|
||
@item read_from_chars(+@var{Chars}, -@var{Term})
|
||
@findex read_from_chars/2
|
||
@syindex read_from_chars/2
|
||
@cnindex read_from_chars/2
|
||
|
||
Parse the list of character codes @var{Chars} and return the result in
|
||
the term @var{Term}. The character codes to be read must terminate with
|
||
a dot character such that either (i) the dot character is followed by
|
||
blank characters; or (ii) the dot character is the last character in the
|
||
string.
|
||
|
||
@item open_chars_stream(+@var{Chars}, -@var{Stream})
|
||
@findex open_chars_stream/2
|
||
@syindex open_chars_stream/2
|
||
@cnindex open_chars_stream/2
|
||
|
||
Open the list of character codes @var{Chars} as a stream @var{Stream}.
|
||
|
||
@item with_output_to_chars(?@var{Goal}, -@var{Chars})
|
||
@findex with_output_to_chars/2
|
||
@syindex with_output_to_chars/2
|
||
@cnindex with_output_to_chars/2
|
||
|
||
Execute goal @var{Goal} such that its standard output will be sent to a
|
||
memory buffer. After successful execution the contents of the memory
|
||
buffer will be converted to the list of character codes @var{Chars}.
|
||
|
||
@item with_output_to_chars(?@var{Goal}, ?@var{Chars0}, -@var{Chars})
|
||
@findex with_output_to_chars/3
|
||
@syindex with_output_to_chars/3
|
||
@cnindex with_output_to_chars/3
|
||
|
||
Execute goal @var{Goal} such that its standard output will be sent to a
|
||
memory buffer. After successful execution the contents of the memory
|
||
buffer will be converted to the difference list of character codes
|
||
@var{Chars-Chars0}.
|
||
|
||
@item with_output_to_chars(?@var{Goal}, -@var{Stream}, ?@var{Chars0}, -@var{Chars})
|
||
@findex with_output_to_chars/4
|
||
@syindex with_output_to_chars/4
|
||
@cnindex with_output_to_chars/4
|
||
|
||
Execute goal @var{Goal} such that its standard output will be sent to a
|
||
memory buffer. After successful execution the contents of the memory
|
||
buffer will be converted to the difference list of character codes
|
||
@var{Chars-Chars0} and @var{Stream} receives the stream corresponding to
|
||
the memory buffer.
|
||
|
||
@end table
|
||
|
||
The implementation of the character IO operations relies on three YAP
|
||
builtins:
|
||
@table @code
|
||
|
||
@item charsio:open_mem_read_stream(+@var{String}, -@var{Stream})
|
||
Store a string in a memory buffer and output a stream that reads from this
|
||
memory buffer.
|
||
|
||
@item charsio:open_mem_write_stream(-@var{Stream})
|
||
Create a new memory buffer and output a stream that writes to it.
|
||
|
||
@item charsio:peek_mem_write_stream(-@var{Stream}, L0, L)
|
||
Convert the memory buffer associated with stream @var{Stream} to the
|
||
difference list of character codes @var{L-L0}.
|
||
|
||
@end table
|
||
@noindent
|
||
These builtins are initialised to belong to the module @code{charsio} in
|
||
@code{init.yap}. Novel procedures for manipulating strings by explicitly
|
||
importing these built-ins.
|
||
|
||
YAP does not currently support opening a @code{charsio} stream in
|
||
@code{append} mode, or seeking in such a stream.
|
||
|
||
@node System, Terms, String I/O, Library
|
||
@section Calling The Operating System from YAP
|
||
@cindex Operating System Utilities
|
||
|
||
Yap now provides a library of system utilities compatible with the
|
||
SICStus Prolog system library. This library extends and to some point
|
||
replaces the functionality of Operating System access routines. The
|
||
library includes Unix/Linux and Win32 @code{C} code. They
|
||
are available through the @code{use_module(library(system))} command.
|
||
|
||
@table @code
|
||
|
||
@item datime(datime(-@var{Year}, -@var{Month}, -@var{DayOfTheMonth},
|
||
-@var{Hour}, -@var{Minute}, -@var{Second})
|
||
@findex datime/1
|
||
@syindex datime/1
|
||
@cnindex datime/1
|
||
The @code{datime/1} procedure returns the current date and time, with
|
||
information on @var{Year}, @var{Month}, @var{DayOfTheMonth},
|
||
@var{Hour}, @var{Minute}, and @var{Second}. The @var{Hour} is returned
|
||
on local time. This function uses the WIN32
|
||
@code{GetLocalTime} function or the Unix @code{localtime} function.
|
||
|
||
@example
|
||
?- datime(X).
|
||
|
||
X = datime(2001,5,28,15,29,46) ?
|
||
@end example
|
||
|
||
@item delete_file(+@var{File})
|
||
@findex delete_file/1
|
||
@syindex delete_file/1
|
||
@cnindex delete_file/1
|
||
The @code{delete_file/1} procedure removes file @var{File}. If
|
||
@var{File} is a directory, remove the directory @emph{and all its
|
||
subdirectories}.
|
||
|
||
@example
|
||
?- delete_file(x).
|
||
@end example
|
||
|
||
@item delete_file(+@var{File},+@var{Opts})
|
||
@findex delete_file/2
|
||
@syindex delete_file/2
|
||
@cnindex delete_file/2
|
||
The @code{delete_file/2} procedure removes file @var{File} according to
|
||
options @var{Opts}. These options are @code{directory} if one should
|
||
remove directories, @code{recursive} if one should remove directories
|
||
recursively, and @code{ignore} if errors are not to be reported.
|
||
|
||
This example is equivalent to using the @code{delete_file/1} predicate:
|
||
@example
|
||
?- delete_file(x, [recursive]).
|
||
@end example
|
||
|
||
|
||
@item directory_files(+@var{Dir},+@var{List})
|
||
@findex directory_files/2
|
||
@syindex directory_files/2
|
||
@cnindex directory_files/2
|
||
Given a directory @var{Dir}, @code{directory_files/2} procedures a
|
||
listing of all files and directories in the directory:
|
||
@example
|
||
?- directory_files('.',L), writeq(L).
|
||
['Makefile.~1~','sys.so','Makefile','sys.o',x,..,'.']
|
||
@end example
|
||
The predicates uses the @code{dirent} family of routines in Unix
|
||
environments, and @code{findfirst} in WIN32.
|
||
|
||
@item file_exists(+@var{File})
|
||
@findex file_exists/1
|
||
@syindex file_exists/1
|
||
@cnindex file_exists/1
|
||
The atom @var{File} corresponds to an existing file.
|
||
|
||
@item file_exists(+@var{File},+@var{Permissions})
|
||
@findex file_exists/2
|
||
@syindex file_exists/2
|
||
@cnindex file_exists/2
|
||
The atom @var{File} corresponds to an existing file with permissions
|
||
compatible with @var{Permissions}. YAP currently only accepts for
|
||
permissions to be described as a number. The actual meaning of this
|
||
number is Operating System dependent.
|
||
|
||
@item file_property(+@var{File},?@var{Property})
|
||
@findex file_property/2
|
||
@syindex file_property/2
|
||
@cnindex file_property/2
|
||
The atom @var{File} corresponds to an existing file, and @var{Property}
|
||
will be unified with a property of this file. The poperties are of the
|
||
form @code{type(@var{Type})}, which gives whether the file is a regular
|
||
file, a directory, a fifo file, or of unknown type;
|
||
@code{size(@var{Size})}, with gives the size for a file, and
|
||
@code{mod_time(@var{Time})}, which gives the last time a file was
|
||
modified according to some Operating System dependent
|
||
timestamp. Properties can be obtained through backtracking:
|
||
|
||
@example
|
||
?- file_property('Makefile',P).
|
||
|
||
P = type(regular) ? ;
|
||
|
||
P = size(2375) ? ;
|
||
|
||
P = mod_time(990826911) ? ;
|
||
|
||
no
|
||
@end example
|
||
|
||
@item make_directory(+@var{Dir})
|
||
@findex make_directory/2
|
||
@syindex make_directory/2
|
||
@cnindex make_directory/2
|
||
Create a directory @var{Dir}. The name of the directory must be an atom.
|
||
|
||
@item rename_file(+@var{OldFile},+@var{NewFile})
|
||
@findex rename_file/2
|
||
@syindex rename_file/2
|
||
@cnindex rename_file/2
|
||
Create file @var{OldFile} to @var{NewFile}. This predicate uses the
|
||
@code{C} builtin function @code{rename}.
|
||
|
||
|
||
@item environ(?@var{EnvVar},+@var{EnvValue})
|
||
@findex environ/2
|
||
@syindex environ/2
|
||
@cnindex environ/2
|
||
Unify environment variable @var{EnvVar} with its value @var{EnvValue},
|
||
if there is one. This predicate is backtrackable in Unix systems, but
|
||
not currently in Win32 configurations.
|
||
|
||
@example
|
||
?- environ('HOME',X).
|
||
|
||
X = 'C:\\cygwin\\home\\administrator' ?
|
||
@end example
|
||
|
||
@item host_id(-@var{Id})
|
||
@findex host_id/1
|
||
@syindex host_id/1
|
||
@cnindex host_id/1
|
||
|
||
Unify @var{Id} with an identifier of the current host. Yap uses the
|
||
@code{hostid} function when available,
|
||
|
||
@item host_name(-@var{Name})
|
||
@findex host_name/1
|
||
@syindex host_name/1
|
||
@cnindex host_name/1
|
||
|
||
Unify @var{Name} with a name for the current host. Yap uses the
|
||
@code{hostname} function in Unix systems when available, and the
|
||
@code{GetComputerName} function in WIN32 systems.
|
||
|
||
@item kill(@var{Id},+@var{SIGNAL})
|
||
@findex kill/2
|
||
@syindex kill/2
|
||
@cnindex kill/2
|
||
|
||
Send signal @var{SIGNAL} to process @var{Id}. In Unix this predicate is
|
||
a direct interface to @code{kill} so one can send signals to groups of
|
||
processes. In WIN32 the predicate is an interface to
|
||
@code{TerminateProcess}, so it kills @var{Id} indepent of @var{SIGNAL}.
|
||
|
||
@item mktemp(@var{Spec},-@var{File})
|
||
@findex mktemp/2
|
||
@syindex mktemp/2
|
||
@cnindex mktemp/2
|
||
|
||
Direct interface to @code{mktemp}: given a @var{Spec}, that is a file
|
||
name with six @var{X} to it, create a file name @var{File}. Use
|
||
@code{tmpnam/1} instead.
|
||
|
||
@item pid(-@var{Id})
|
||
@findex pid/1
|
||
@syindex pid/1
|
||
@cnindex pid/1
|
||
|
||
Unify @var{Id} with the process identifier for the current
|
||
process. An interface to the @t{getpid} function.
|
||
|
||
@item tmpnam(-@var{File})
|
||
@findex tmpnam/1
|
||
@syindex tmpnam/1
|
||
@cnindex tmpnam/1
|
||
|
||
Interface with @var{tmpnam}: create an unique file and unify its name
|
||
with @var{File}.
|
||
|
||
@item
|
||
exec(+@var{Command},[+@var{InputStream},+@var{OutputStream},+@var{ErrorStream}],
|
||
-@var{Status})
|
||
@findex exec/3
|
||
@syindex exec/3
|
||
@cnindex exec/3
|
||
Execute command @var{Command} with its streams connected to
|
||
@var{InputStream}, @var{OutputStream}, and @var{ErrorStream}. The result
|
||
for the command is returned in @var{Status}. The command is executed by
|
||
the default shell @code{bin/sh -c} in Unix.
|
||
|
||
The following example demonstrates the use of @code{exec/3} to send a
|
||
command and process its output:
|
||
|
||
@example
|
||
exec(ls,[std,pipe(S),null],P),repeat, get0(S,C), (C = -1, close(S) ! ; put(C)).
|
||
@end example
|
||
|
||
The streams may be one of standard stream, @code{std}, null stream,
|
||
@code{null}, or @code{pipe(S)}, where @var{S} is a pipe stream. Note
|
||
that it is up to the user to close the pipe.
|
||
|
||
@item working_directory(-@var{CurDir},?@var{NextDir})
|
||
@findex working_directory/2
|
||
@syindex working_directory/2
|
||
@cnindex working_directory/2
|
||
Fetch the current directory at @var{CurDir}. If @var{NextDir} is bound
|
||
to an atom, make its value the current working directory.
|
||
|
||
@item popen(+@var{Command}, +@var{TYPE}, -@var{Stream})
|
||
@findex popen/3
|
||
@syindex popen/3
|
||
@cnindex popen/3
|
||
Interface to the @t{popen} function. It opens a process by creating a
|
||
pipe, forking and invoking @var{Command} on the current shell. Since a
|
||
pipe is by definition unidirectional the @var{Type} argument may be
|
||
@code{read} or @code{write}, not both. The stream should be closed
|
||
using @code{close/1}, there is no need for a special @code{pclose}
|
||
command.
|
||
|
||
The following example demonstrates the use of @code{popen/3} to process
|
||
the output of a command, as @code{exec/3} would do:
|
||
|
||
@example
|
||
?- popen(ls,read,X),repeat, get0(X,C), (C = -1, ! ; put(C)).
|
||
|
||
X = 'C:\\cygwin\\home\\administrator' ?
|
||
@end example
|
||
|
||
|
||
The WIN32 implementation of @code{popen/3} relies on @code{exec/3}.
|
||
|
||
@item shell
|
||
@findex shell/0
|
||
@syindex shell/0
|
||
@cnindex shell/0
|
||
Start a new shell and leave Yap in background until the shell
|
||
completes. Yap uses the shell given by the environment variable
|
||
@code{SHELL}. In WIN32 environment YAP will use @code{COMSPEC} if
|
||
@code{SHELL} is undefined.
|
||
|
||
@item shell(+@var{Command})
|
||
@findex shell/1
|
||
@syindex shell/1
|
||
@cnindex shell/1
|
||
Execute command @var{Command} under a new shell. Yap will be in
|
||
background until the command completes. In Unix environments Yap uses
|
||
the shell given by the environment variable @code{SHELL} with the option
|
||
@code{" -c "}. In WIN32 environment YAP will use @code{COMSPEC} if
|
||
@code{SHELL} is undefined, in this case with the option @code{" /c "}.
|
||
|
||
@item shell(+@var{Command},-@var{Status})
|
||
@findex shell/1
|
||
@syindex shell/1
|
||
@cnindex shell/1
|
||
Execute command @var{Command} under a new shell and unify @var{Status}
|
||
with the exit for the command. Yap will be in background until the
|
||
command completes. In Unix environments Yap uses the shell given by the
|
||
environment variable @code{SHELL} with the option @code{" -c "}. In
|
||
WIN32 environment YAP will use @code{COMSPEC} if @code{SHELL} is
|
||
undefined, in this case with the option @code{" /c "}.
|
||
|
||
@item sleep(+@var{Time})
|
||
@findex sleep/1
|
||
@syindex sleep/1
|
||
@cnindex sleep/1
|
||
Block the current process for @var{Time} seconds. The number of seconds
|
||
must be a positive number, and it may an integer or a float. The Unix
|
||
implementation uses @code{usleep} if the number of seconds is below one,
|
||
and @code{sleep} if it is over a second. The WIN32 implementation uses
|
||
@code{Sleep} for both cases.
|
||
|
||
@item system
|
||
@findex system/0
|
||
@syindex system/0
|
||
@cnindex system/0
|
||
Start a new default shell and leave Yap in background until the shell
|
||
completes. Yap uses @code{/bin/sh} in Unix systems and @code{COMSPEC} in
|
||
WIN32.
|
||
|
||
@item system(+@var{Command},-@var{Res})
|
||
@findex system/2
|
||
@syindex system/2
|
||
@cnindex system/2
|
||
Interface to @code{system}: execute command @var{Command} and unify
|
||
@var{Res} with the result.
|
||
|
||
@item wait(+@var{PID},-@var{Status})
|
||
@findex wait/2
|
||
@syindex wait/2
|
||
@cnindex wait/2
|
||
Wait until process @var{PID} terminates, and return its exits @var{Status}.
|
||
|
||
@end table
|
||
|
||
|
||
@node Terms, Timeout, System, Library
|
||
@section Utilities On Terms
|
||
@cindex utilities on terms
|
||
|
||
The next routines provide a set of commonly used utilities to manipulate
|
||
terms. Most of these utilities have been implemented in @code{C} for
|
||
efficiency. They are available through the
|
||
@code{use_module(library(timeout))} command.
|
||
|
||
@table @code
|
||
|
||
@item term_hash(+@var{Term}, ?@var{Hash})
|
||
@findex term_hash/2
|
||
@syindex term_hash/2
|
||
@cnindex term_hash/2
|
||
|
||
If @var{Term} is ground unify @var{Hash} with a positive integer
|
||
calculated from the structure of the term. Otherwise the argument
|
||
@var{Hash} is left unbound. The range of the positive integer is from
|
||
@code{0} to, but not including, @code{33554432}.
|
||
|
||
@item term_hash(+@var{Term}, +@var{Depth}, +@var{Range}, ?@var{Hash})
|
||
@findex term_hash/4
|
||
@syindex term_hash/4
|
||
@cnindex term_hash/4
|
||
|
||
Unify @var{Hash} with a positive integer calculated from the structure
|
||
of the term. The range of the positive integer is from @code{0} to, but
|
||
not including, @var{Range}. If @var{Depth} is @code{-1} the whole term
|
||
is considered. Otherwise, the term is considered only up to depth
|
||
@code{1}, where the constants and the principal functor have depth
|
||
@code{1}, and an argument of a term with depth @var{I} has depth @var{I+1}.
|
||
|
||
@item term_variables(?@var{Term}, -@var{Variables})
|
||
@findex term_variables/2
|
||
@syindex term_variables/2
|
||
@cnindex term_variables/2
|
||
|
||
Unify @var{Variables} with a list of all variables in term @var{Term}.
|
||
|
||
@item variant(?@var{Term1}, ?@var{Term2})
|
||
@findex variant/2
|
||
@syindex variant/2
|
||
@cnindex variant/2
|
||
|
||
Succeed if @var{Term1} and @var{Term2} are variant terms.
|
||
|
||
@item subsumes(?@var{Term1}, ?@var{Term2})
|
||
@findex subsumes/2
|
||
@syindex subsumes/2
|
||
@cnindex subsumes/2
|
||
|
||
Succeed if @var{Term1} subsumes @var{Term2}. Variables in term
|
||
@var{Term1} are bound so that the two terms become equal.
|
||
|
||
|
||
@item subsumes_chk(?@var{Term1}, ?@var{Term2})
|
||
@findex subsumes_chk/2
|
||
@syindex subsumes_chk/2
|
||
@cnindex subsumes_chk/2
|
||
|
||
Succeed if @var{Term1} subsumes @var{Term2} but does not bind any
|
||
variable in @var{Term1}.
|
||
|
||
|
||
|
||
@end table
|
||
|
||
@node Timeout, Trees, Terms, Library
|
||
@section Calls With Timeout
|
||
@cindex timeout
|
||
|
||
The @t{time_out/3} command relies on the @t{alarm/3} built-in to
|
||
implement a call with a maximum time of execution. The command is
|
||
available with the @code{use_module(library(timeout))} command.
|
||
|
||
@table @code
|
||
|
||
@item time_out(+@var{Goal}, +@var{Timeout}, -@var{Result})
|
||
@findex time_out/3
|
||
@syindex time_out/3
|
||
@cnindex time_out/3
|
||
Execute goal @var{Goal} with time limite @var{Timeout}, where
|
||
@var{Timeout} is measured in milliseconds. If the goal succeeds, unify
|
||
@var{Result} with success. If the timer expires before the goal
|
||
terminates, unify @var{Result} with @t{timeout}.
|
||
|
||
This command is implemented by activating an alarm at procedure
|
||
entry. If the timer expires before the goal completes, the alarm will
|
||
through an exception @var{timeout}.
|
||
|
||
One should note that @code{time_out/3} is not reentrant, that is, a goal
|
||
called from @code{time_out} should never itself call
|
||
@t{time_out}. Moreover, @code{time_out/3} will deactivate any previous
|
||
alarms set by @code{alarm/3} and vice-versa, hence only one of these
|
||
calls should be used in a program.
|
||
|
||
Last, even though the timer is set in milliseconds, the current
|
||
implementation relies on @t{alarm/3}, and therefore can only offer
|
||
precision on the scale of seconds.
|
||
|
||
@end table
|
||
|
||
@node Trees, UGraphs, Timeout, Library
|
||
@section Updatable Binary Trees
|
||
@cindex updatable tree
|
||
|
||
The following queue manipulation routines are available once
|
||
included with the @code{use_module(library(trees))} command.
|
||
|
||
@table @code
|
||
|
||
@item get_label(+@var{Index}, +@var{Tree}, ?@var{Label})
|
||
@findex get_label/3
|
||
@syindex get_label/3
|
||
@cnindex get_label/3
|
||
Treats the tree as an array of @var{N} elements and returns the
|
||
@var{Index}-th.
|
||
|
||
@item list_to_tree(+@var{List}, -@var{Tree})
|
||
@findex list_to_tree/2
|
||
@syindex list_to_tree/2
|
||
@cnindex list_to_tree/2
|
||
Takes a given @var{List} of @var{N} elements and constructs a binary
|
||
@var{Tree}.
|
||
|
||
@item map_tree(+@var{Pred}, +@var{OldTree}, -@var{NewTree})
|
||
@findex map_tree/3
|
||
@syindex map_tree/3
|
||
@cnindex map_tree/3
|
||
Holds when @var{OldTree} and @var{NewTree} are binary trees of the same shape
|
||
and @code{Pred(Old,New)} is true for corresponding elements of the two trees.
|
||
|
||
@item put_label(+@var{Index}, +@var{OldTree}, +@var{Label}, -@var{NewTree})
|
||
@findex put_label/4
|
||
@syindex put_label/4
|
||
@cnindex put_label/4
|
||
constructs a new tree the same shape as the old which moreover has the
|
||
same elements except that the @var{Index}-th one is @var{Label}.
|
||
|
||
@item tree_size(+@var{Tree}, -@var{Size})
|
||
@findex tree_size/2
|
||
@syindex tree_size/2
|
||
@cnindex tree_size/2
|
||
Calculates the number of elements in the @var{Tree}.
|
||
|
||
@item tree_to_list(+@var{Tree}, -@var{List})
|
||
@findex tree_to_list/2
|
||
@syindex tree_to_list/2
|
||
@cnindex tree_to_list/2
|
||
Is the converse operation to list_to_tree.
|
||
|
||
@end table
|
||
|
||
@node UGraphs, , Trees, Library
|
||
@section Unweighted Graphs
|
||
@cindex unweighted graphs
|
||
|
||
The following graph manipulation routines are based from code originally
|
||
written by Richard O'Keefe. The code was then extended to be compatible
|
||
with the SICStus Prolog ugraphs library. The routines assume directed
|
||
graphs, undirected graphs may be implemented by using two edges. Graphs
|
||
are represented in one of two ways:
|
||
|
||
@itemize @bullet
|
||
@item The P-representation of a graph is a list of (from-to) vertex
|
||
pairs, where the pairs can be in any old order. This form is
|
||
convenient for input/output.
|
||
|
||
@item The S-representation of a graph is a list of (vertex-neighbours)
|
||
pairs, where the pairs are in standard order (as produced by keysort)
|
||
and the neighbours of each vertex are also in standard order (as
|
||
produced by sort). This form is convenient for many calculations.
|
||
@end itemize
|
||
|
||
These builtins are available once included with the
|
||
@code{use_module(library(ugraphs))} command.
|
||
|
||
@table @code
|
||
|
||
@item vertices_edges_to_ugraph(+@var{Vertices}, +@var{Edges}, -@var{Graph})
|
||
@findex vertices_edges_to_ugraph/3
|
||
@syindex vertices_edges_to_ugraph/3
|
||
@cnindex vertices_edges_to_ugraph/3
|
||
Given a graph with a set of vertices @var{Vertices} and a set of edges
|
||
@var{Edges}, @var{Graph} must unify with the corresponding
|
||
s-representation. Note that the vertices without edges will appear in
|
||
@var{Vertices} but not in @var{Edges}. Moreover, it is sufficient for a
|
||
vertice to appear in @var{Edges}.
|
||
@example
|
||
?- vertices_edges_to_ugraph([],[1-3,2-4,4-5,1-5],L).
|
||
|
||
L = [1-[3,5],2-[4],3-[],4-[5],5-[]] ?
|
||
|
||
@end example
|
||
In this case all edges are defined implicitly. The next example shows
|
||
three unconnected edges:
|
||
@example
|
||
?- vertices_edges_to_ugraph([6,7,8],[1-3,2-4,4-5,1-5],L).
|
||
|
||
L = [1-[3,5],2-[4],3-[],4-[5],5-[],6-[],7-[],8-[]] ?
|
||
|
||
@end example
|
||
|
||
@item vertices(+@var{Graph}, -@var{Vertices})
|
||
@findex vertices/2
|
||
@syindex vertices/2
|
||
@cnindex vertices/2
|
||
Unify @var{Vertices} with all vertices appearing in graph
|
||
@var{Graph}. In the next example:
|
||
@example
|
||
?- vertices([1-[3,5],2-[4],3-[],4-[5],5-[]], V).
|
||
|
||
L = [1,2,3,4,5]
|
||
@end example
|
||
|
||
@item edges(+@var{Graph}, -@var{Edges})
|
||
@findex vertices/2
|
||
@syindex vertices/2
|
||
@cnindex vertices/2
|
||
Unify @var{Edges} with all edges appearing in graph
|
||
@var{Graph}. In the next example:
|
||
@example
|
||
?- vertices([1-[3,5],2-[4],3-[],4-[5],5-[]], V).
|
||
|
||
L = [1,2,3,4,5]
|
||
@end example
|
||
|
||
@item add_vertices(+@var{Graph}, +@var{Vertices}, -@var{NewGraph})
|
||
@findex add_vertices/3
|
||
@syindex add_vertices/3
|
||
@cnindex add_vertices/3
|
||
Unify @var{NewGraph} with a new graph obtained by adding the list of
|
||
vertices @var{Vertices} to the graph @var{Graph}. In the next example:
|
||
@example
|
||
?- add_vertices([1-[3,5],2-[4],3-[],4-[5],
|
||
5-[],6-[],7-[],8-[]],
|
||
[0,2,9,10,11],
|
||
NG).
|
||
|
||
NG = [0-[],1-[3,5],2-[4],3-[],4-[5],5-[],
|
||
6-[],7-[],8-[],9-[],10-[],11-[]]
|
||
@end example
|
||
|
||
@item del_vertices(+@var{Vertices}, +@var{Graph}, -@var{NewGraph})
|
||
@findex del_vertices/3
|
||
@syindex del_vertices/3
|
||
@cnindex del_vertices/3
|
||
Unify @var{NewGraph} with a new graph obtained by deleting the list of
|
||
vertices @var{Vertices} and all the edges that start from or go to a
|
||
vertex in @var{Vertices} to the graph @var{Graph}. In the next example:
|
||
@example
|
||
?- del_vertices([2,1],[1-[3,5],2-[4],3-[],
|
||
4-[5],5-[],6-[],7-[2,6],8-[]],NL).
|
||
|
||
NL = [3-[],4-[5],5-[],6-[],7-[6],8-[]]
|
||
@end example
|
||
|
||
@item add_edges(+@var{Graph}, +@var{Edges}, -@var{NewGraph})
|
||
@findex add_edges/3
|
||
@syindex add_edges/3
|
||
@cnindex add_edges/3
|
||
Unify @var{NewGraph} with a new graph obtained by adding the list of
|
||
edges @var{Edges} to the graph @var{Graph}. In the next example:
|
||
@example
|
||
?- add_edges([1-[3,5],2-[4],3-[],4-[5],5-[],6-[],
|
||
7-[],8-[]],[1-6,2-3,3-2,5-7,3-2,4-5],NL).
|
||
|
||
NL = [1-[3,5,6],2-[3,4],3-[2],4-[5],5-[7],6-[],7-[],8-[]]
|
||
@end example
|
||
|
||
@item sub_edges(+@var{Graph}, +@var{Edges}, -@var{NewGraph})
|
||
@findex sub_edges/3
|
||
@syindex sub_edges/3
|
||
@cnindex sub_edges/3
|
||
Unify @var{NewGraph} with a new graph obtained by removing the list of
|
||
edges @var{Edges} from the graph @var{Graph}. Notice that no vertices
|
||
are deleted. In the next example:
|
||
@example
|
||
?- del_edges([1-[3,5],2-[4],3-[],4-[5],5-[],
|
||
6-[],7-[],8-[]],
|
||
[1-6,2-3,3-2,5-7,3-2,4-5,1-3],NL).
|
||
|
||
NL = [1-[5],2-[4],3-[],4-[],5-[],6-[],7-[],8-[]]
|
||
@end example
|
||
|
||
@item transpose(+@var{Graph}, -@var{NewGraph})
|
||
@findex transpose/3
|
||
@syindex transpose/3
|
||
@cnindex transpose/3
|
||
Unify @var{NewGraph} with a new graph obtained from @var{Graph} by
|
||
replacing all edges of the form @var{V1-V2} by edges of the form
|
||
@var{V2-V1}. The cost is @code{O(|V|^2)}. In the next example:
|
||
@example
|
||
?- transpose([1-[3,5],2-[4],3-[],
|
||
4-[5],5-[],6-[],7-[],8-[]], NL).
|
||
|
||
NL = [1-[],2-[],3-[1],4-[2],5-[1,4],6-[],7-[],8-[]]
|
||
@end example
|
||
Notice that an undirected graph is its own transpose.
|
||
|
||
@item neighbors(+@var{Vertex}, +@var{Graph}, -@var{Vertices})
|
||
@findex neighbors/3
|
||
@syindex neighbors/3
|
||
@cnindex neighbors/3
|
||
Unify @var{Vertices} with the list of neighbors of vertex @var{Vertex}
|
||
in @var{Graph}. If the vertice is not in the graph fail. In the next
|
||
example:
|
||
@example
|
||
?- neighbors(4,[1-[3,5],2-[4],3-[],
|
||
4-[1,2,7,5],5-[],6-[],7-[],8-[]],
|
||
NL).
|
||
|
||
NL = [1,2,7,5]
|
||
@end example
|
||
|
||
@item neighbours(+@var{Vertex}, +@var{Graph}, -@var{Vertices})
|
||
@findex neighbours/3
|
||
@syindex neighbours/3
|
||
@cnindex neighbours/3
|
||
Unify @var{Vertices} with the list of neighbours of vertex @var{Vertex}
|
||
in @var{Graph}. In the next example:
|
||
@example
|
||
?- neighbours(4,[1-[3,5],2-[4],3-[],
|
||
4-[1,2,7,5],5-[],6-[],7-[],8-[]], NL).
|
||
|
||
NL = [1,2,7,5]
|
||
@end example
|
||
|
||
@item complement(+@var{Graph}, -@var{NewGraph})
|
||
@findex complement/2
|
||
@syindex complement/2
|
||
@cnindex complement/2
|
||
Unify @var{NewGraph} with the graph complementar to @var{Graph}.
|
||
In the next example:
|
||
@example
|
||
?- complement([1-[3,5],2-[4],3-[],
|
||
4-[1,2,7,5],5-[],6-[],7-[],8-[]], NL).
|
||
|
||
NL = [1-[2,4,6,7,8],2-[1,3,5,6,7,8],3-[1,2,4,5,6,7,8],
|
||
4-[3,5,6,8],5-[1,2,3,4,6,7,8],6-[1,2,3,4,5,7,8],
|
||
7-[1,2,3,4,5,6,8],8-[1,2,3,4,5,6,7]]
|
||
@end example
|
||
|
||
@item compose(+@var{LeftGraph}, +@var{RightGraph}, -@var{NewGraph})
|
||
@findex compose/3
|
||
@syindex compose/3
|
||
@cnindex compose/3
|
||
Compose the graphs @var{LeftGraph} and @var{RightGraph} to form @var{NewGraph}.
|
||
In the next example:
|
||
@example
|
||
?- compose([1-[2],2-[3]],[2-[4],3-[1,2,4]],L).
|
||
|
||
L = [1-[4],2-[1,2,4],3-[]]
|
||
@end example
|
||
|
||
@item top_sort(+@var{Graph}, +@var{Sort})
|
||
@findex top_sort/2
|
||
@syindex top_sort/2
|
||
@cnindex top_sort/2
|
||
Generate the set of nodes @var{Sort} as a topological sorting of graph
|
||
@var{Graph}, if one is possible.
|
||
In the next example we show how topological sorting works for a linear graph:
|
||
@example
|
||
?- top_sort([_138-[_219],_219-[_139], _139-[]],L).
|
||
|
||
L = [_138,_219,_139]
|
||
@end example
|
||
|
||
@item transitive_closure(+@var{Graph}, +@var{Closure})
|
||
@findex transitive_closure/2
|
||
@syindex transitive_closure/2
|
||
@cnindex transitive_closure/2
|
||
Generate the graph @var{Closure} as the transitive closure of graph
|
||
@var{Graph}.
|
||
In the next example:
|
||
@example
|
||
?- transitive_closure([1-[2,3],2-[4,5],4-[6]],L).
|
||
|
||
L = [1-[2,3,4,5,6],2-[4,5,6],4-[6]]
|
||
@end example
|
||
|
||
@end table
|
||
|
||
@node Extensions,Debugging,Library,Top
|
||
@chapter Extensions
|
||
|
||
YAP includes several extensions that are not enabled by
|
||
default, but that can be used to extend the functionality of the
|
||
system. These options can be set at compilation time by enabling the
|
||
related compilation flag, as explained in the @code{Makefile}
|
||
|
||
@menu
|
||
|
||
Extensions to Traditional Prolog
|
||
|
||
* Rational Trees:: Working with Rational Trees
|
||
* Coroutining:: Changing the Execution of Goals
|
||
* Attributed Variables:: Using attributed Variables
|
||
* CLPQR:: The CLP(Q,R) System
|
||
* Logtalk:: The Logtalk Object-Oriented system
|
||
* Parallelism:: Running in Or-Parallel
|
||
* Tabling:: Storing Intermediate Solutions of programs
|
||
* Low Level Profiling:: Profiling Abstract Machine Instructions
|
||
* Low Level Tracing:: Tracing at Abstract Machine Level
|
||
@end menu
|
||
|
||
@node Rational Trees, Coroutining, , Extensions
|
||
@chapter Rational Trees
|
||
|
||
Prolog unification is not a complete implementation. For efficiency
|
||
considerations, Prolog systems do not perform occur checks while
|
||
unifying terms. As an example, @code{X = a(X)} will not fail but instead
|
||
will create an infinite term of the form @code{a(a(a(a(a(...)))))}, or
|
||
@emph{rational tree}.
|
||
|
||
By default, rational trees are not supported in YAP, and these
|
||
terms can easily lead to infinite computation. For example, @code{X =
|
||
a(X), X = X} will enter an infinite loop.
|
||
|
||
The @code{RATIONAL_TREES} flag improves support for these
|
||
terms. Internal primitives are now aware that these terms can exist, and
|
||
will not enter infinite loops. Hence, the previous unification will
|
||
succeed. Another example, @code{X = a(X), ground(X)} will succeed
|
||
instead of looping. Other affected builtins include the term comparison
|
||
primitives, @code{numbervars/3}, @code{copy_term/2}, and the internal
|
||
data base routines. The support does not extend to Input/Output routines
|
||
or to @code{assert/1} YAP does not allow directly reading
|
||
rational trees, and you need to use @code{write_depth/2} to avoid
|
||
entering an infinite cycle when trying to write an infinite term.
|
||
|
||
@node Coroutining, Attributed Variables, Rational Trees, Extensions
|
||
@chapter Coroutining
|
||
|
||
Prolog uses a simple left-to-right flow of control. It is sometimes
|
||
convenient to change this control so that goals will only be executed
|
||
when conditions are fulfilled. This may result in a more "data-driven"
|
||
execution, or may be necessary to correctly implement extensions such as
|
||
negation by default.
|
||
|
||
The @code{COROUTINING} flag enables this option. Note that the support for
|
||
coroutining will in general slow down execution.
|
||
|
||
The following declaration is supported:
|
||
|
||
@table @code
|
||
@item block/1
|
||
The argument to @code{block/1} is a condition on a goal or a conjunction
|
||
of conditions, with each element separated by commas. Each condition is
|
||
of the form @code{predname(@var{C1},...,@var{CN})}, where @var{N} is the
|
||
arity of the goal, and each @var{CI} is of the form @code{-}, if the
|
||
argument must suspend until the variable is bound, or @code{?}, otherwise.
|
||
|
||
@item wait/1
|
||
The argument to @code{wait/1} is a predicate descriptor or a conjunction
|
||
of these predicates. These predicates will suspend until their first
|
||
argument is bound.
|
||
@end table
|
||
|
||
The following primitives are supported:
|
||
|
||
@table @code
|
||
@item dif(@var{X},@var{Y})
|
||
@findex dif/2
|
||
@syindex dif/2
|
||
@cnindex dif/2
|
||
Succeed if the two arguments do not unify. A call to @code{dif/2} will
|
||
suspend if unification may still succeed or fail, and will fail if they
|
||
always unify.
|
||
|
||
@item freeze(@var{X},@var{G})
|
||
@findex freeze/2
|
||
@syindex freeze/2
|
||
@cnindex freeze/2
|
||
Delay execution of goal @var{G} until the variable @var{X} is bound.
|
||
|
||
@item frozen(@var{X},@var{G})
|
||
@findex frozen/2
|
||
@syindex frozen/2
|
||
@cnindex frozen/2
|
||
Unify @var{G} with a conjunction of goals suspended on variable @var{X},
|
||
or @code{true} if no goal has suspended.
|
||
|
||
@item when(@var{C},@var{G})
|
||
@findex when/2
|
||
@syindex when/2
|
||
@cnindex when/2
|
||
Delay execution of goal @var{G} until the conditions @var{C} are
|
||
satisfied. The conditions are of the following form:
|
||
|
||
@table @code
|
||
@item @var{C1},@var{C2}
|
||
Delay until both conditions @var{C1} and @var{C2} are satisfied.
|
||
@item @var{C1};@var{C2}
|
||
Delay until either condition @var{C1} or condition @var{C2} is satisfied.
|
||
@item ?=(@var{V1},@var{C2})
|
||
Delay until terms @var{V1} and @var{V1} have been unified.
|
||
@item nonvar(@var{V})
|
||
Delay until variable @var{V} is bound.
|
||
@item ground(@var{V})
|
||
Delay until variable @var{V} is ground.
|
||
@end table
|
||
|
||
Note that @code{when/2} will fail if the conditions fail.
|
||
|
||
@item call_residue(@var{G},@var{L})
|
||
@findex call_residue/2
|
||
@syindex call_residue/2
|
||
@cnindex call_residue/2
|
||
|
||
Call goal @var{G}. If subgoals of @var{G} are still blocked, return
|
||
a list containing these goals and the variables they are blocked in. The
|
||
goals are then considered as unblocked. The next example shows a case
|
||
where @code{dif/2} suspends twice, once outside @code{call_residue/2},
|
||
and the other inside:
|
||
|
||
@example
|
||
?- dif(X,Y),
|
||
call_residue((dif(X,Y),(X = f(Z) ; Y = f(Z))), L).
|
||
|
||
X = f(Z),
|
||
L = [[Y]-dif(f(Z),Y)],
|
||
dif(f(Z),Y) ? ;
|
||
|
||
Y = f(Z),
|
||
L = [[X]-dif(X,f(Z))],
|
||
dif(X,f(Z)) ? ;
|
||
|
||
no
|
||
@end example
|
||
The system only reports one invocation of @code{dif/2} as having
|
||
suspended.
|
||
|
||
@end table
|
||
|
||
|
||
@node Attributed Variables, CLPQR, Coroutining, Extensions
|
||
@chapter Attributed Variables
|
||
@cindex attributed variables
|
||
|
||
@menu
|
||
|
||
* Attribute Declarations:: Declaring New Attributes
|
||
* Attribute Manipulation:: Setting and Reading Attributes
|
||
* Attributed Unification:: Tuning the Unification Algorithm
|
||
* Displaying Attributes:: Displaying Attributes in User-Readable Form
|
||
* Projecting Attributes:: Obtaining the Attributes of Interest
|
||
* Attribute Examples:: Two Simple Examples of how to use Attributes.
|
||
@end menu
|
||
|
||
YAP now supports the attributed variables packaged developed at OFAI by
|
||
Christian Holzbaur. Attributes are a means of declaring that an
|
||
arbitrary term is a property for a variable. These properties can be
|
||
updated during forward execution. Moreover, the unification algorithm is
|
||
aware of attributed variables and will call user defined handlers when
|
||
trying to unify these variables.
|
||
|
||
Attributed variables provide an elegant abstraction over which one can
|
||
extend Prolog systems. Their main application so far has been in
|
||
implementing constraint handlers, such as Holzbaur's CLPQR and Fruewirth
|
||
and Holzbaur's CHR, but other applications have been proposed in the
|
||
literature.
|
||
|
||
|
||
The command
|
||
@example
|
||
| ?- use_module(library(atts)).
|
||
@end example
|
||
enables the use of attributed variables. The package provides the
|
||
following functionality:
|
||
@itemize @bullet
|
||
@item Each attribute must be declared first. Attributes are described by a functor
|
||
and are declared per module. Each Prolog module declares its own sets of
|
||
attributes. Different modules may have different functors with the same
|
||
module.
|
||
@item The built-in @code{put_atts/2} adds or deletes attributes to a
|
||
variable. The variable may be unbound or may be an attributed
|
||
variable. In the latter case, YAP discards previous values for the
|
||
attributes.
|
||
@item The built-in @code{get_atts/2} can be used to check the values of
|
||
an attribute associated with a variable.
|
||
@item The unification algorit mcalls the user-defined predicate
|
||
@t{verify_attributes/3} before trying to bind an attributed
|
||
variable. Unification will resume after this call.
|
||
@item The user-defined predicate
|
||
@t{attribute_goal/2} converts from an attribute to a goal.
|
||
@item The user-defined predicate
|
||
@t{project_attributes/2} is used from a set of variables into a set of
|
||
constraints or goals. One application of @t{project_attributes/2}d is in
|
||
the top-level, where it is used to output the set of
|
||
floundered constraints at the end of a query.
|
||
@end itemize
|
||
|
||
@node Attribute Declarations, Attribute Manipulation, , Attributed Variables
|
||
|
||
Attributes are compound terms associated with a variable. Each attribute
|
||
has a @emph{name} which is @emph{private} to the module in which the
|
||
attribute was defined. Variables may have at most one attribute with a
|
||
name. Attribute names are defined with the following declaration:
|
||
|
||
@cindex attribute declaration
|
||
@cindex declaration, attribute
|
||
@findex attribute/1 (declaration)
|
||
|
||
@example
|
||
:- attribute @var{AttributeSpec}, ..., @var{AttributeSpec}.
|
||
@end example
|
||
|
||
@noindent
|
||
where each @var{AttributeSpec} has the form (@var{Name}/@var{Arity}).
|
||
One single such declaration is allowed per module @var{Module}.
|
||
|
||
Although the YAP module system is predicate based, attributes are local
|
||
to modules. This is implemented by rewriting all calls to the
|
||
builtins that manipulate attributes so that attribute names are
|
||
preprocessed depending on the module. The @code{user:goal_expansion/3}
|
||
mechanism is used for this purpose.
|
||
|
||
|
||
@node Attribute Manipulation, Attributed Unification, Attribute Declarations, Attributed Variables
|
||
|
||
|
||
The attribute manipulation predicates always work as follows:
|
||
@enumerate
|
||
@item The first argument is the unbound variable associated with
|
||
attributes,
|
||
@item The second argument is a list of attributes. Each attribute will
|
||
be a Prolog term or a constant, prefixed with the @t{+} and @t{-} unary
|
||
operators. The prefix @t{+} may be dropped for convenience.
|
||
@end enumerate
|
||
|
||
The following three procedures are available to the user. Notice that
|
||
these builtins are rewritten by the system into internal builtins, and
|
||
that the rewriting process @emph{depends} on the module on which the
|
||
builtins have been invoked.
|
||
|
||
@table @code
|
||
@item @var{Module}:get_atts(@var{-Var},@var{?ListOfAttributes})
|
||
@findex get_atts/2
|
||
@syindex get_atts/2
|
||
@cnindex get_atts/2
|
||
Unify the list @var{?ListOfAttributes} with the attributes for the unbound
|
||
variable @var{Var}. Each member of the list must be a bound term of the
|
||
form @code{+(@var{Attribute})}, @code{-(@var{Attribute})} (the @t{kbd}
|
||
prefix may be dropped). The meaning of @t{+} and @t{-} is:
|
||
@table @code
|
||
@item +(@var{Attribute})
|
||
Unifies @var{Attribute} with a corresponding attribute associated with
|
||
@var{Var}, fails otherwise.
|
||
|
||
@item -(@var{Attribute})
|
||
Succeeds if a corresponding attribute is not associated with
|
||
@var{Var}. The arguments of @var{Attribute} are ignored.
|
||
@end table
|
||
|
||
@item @var{Module}:put_atts(@var{-Var},@var{?ListOfAttributes})
|
||
@findex put_atts/2
|
||
@syindex put_atts/2
|
||
@cnindex put_atts/2
|
||
Associate with or remove attributes from a variable @var{Var}. The
|
||
attributes are given in @var{?ListOfAttributes}, and the action depends
|
||
on how they are prefixed:
|
||
@item +(@var{Attribute})
|
||
Associate @var{Var} with @var{Attribute}. A previous value for the
|
||
attribute is simply replace (like with @code{set_mutable/2}).
|
||
|
||
@item -(@var{Attribute})
|
||
Remove the attribute with the same name. If no such attribute existed,
|
||
simply succeed.
|
||
@end table
|
||
|
||
@node Attributed Unification, Displaying Attributes, Attribute Manipulation, Attributed Variables
|
||
|
||
The user-predicate predicate @code{verify_attributes/3} is called when
|
||
attempting to unify an attributed variable which might have attributes
|
||
in some @var{Module}.
|
||
|
||
@table @code
|
||
@item @var{Module}:verify_attributes(@var{-Var}, @var{+Value}, @var{-Goals})
|
||
@findex verify_attributes/3
|
||
@syindex verify_attributes/3
|
||
@cnindex verify_attributes/3
|
||
|
||
The predicate is called when trying to unify the attributed variable
|
||
@var{Var} with the Prolog term @var{Value}. Note that @var{Value} may be
|
||
itself an attributed variable, or may contain attributed variables. The
|
||
goal @t{verify_attributes/3} is actually called before @var{Var} is
|
||
unified with @var{Value}.
|
||
|
||
It is up to the user to define which actions may be performed by
|
||
@t{verify_attributes/3} but the procedure is expected to return in
|
||
@var{Goals} a list of goals to be called @emph{after} @var{Var} is
|
||
unified with @var{Value}. If @t{verify_attributes/3} fails, the
|
||
unification will fail.
|
||
|
||
Notice that the @t{verify_attributes/3} may be called even if @var{Var}
|
||
has no attributes in module @t{Module}. In this case the routine should
|
||
simply succeed with @var{Goals} unified with the empty list.
|
||
@end table
|
||
|
||
@node Displaying Attributes, Projecting Attributes,Attributed Unification, Attributed Variables
|
||
|
||
Attributes are usually presented as goals. The following routines are
|
||
used by builtin predicates such as @code{call_residue/2} and by the
|
||
Prolog top-level to display attributes:
|
||
|
||
@table @code
|
||
@item @var{Module}:attribute_goal(@var{-Var}, @var{-Goal})
|
||
@findex attribute_goal/2
|
||
@syindex attribute_goal/2
|
||
@cnindex attribute_goal/2
|
||
User-defined procedure, called to convert the attributes in @var{Var} to
|
||
a @var{Goal}. Should fail when no interpretation is available.
|
||
|
||
@item @var{Module}:project_attributes(@var{-QueryVars}, @var{+AttrVars})
|
||
@findex attribute_goal/2
|
||
@syindex attribute_goal/2
|
||
@cnindex attribute_goal/2
|
||
User-defined procedure, called to convert the attributes in @var{Var} to
|
||
a @var{Goal}. Should fail when no interpretation is available.
|
||
|
||
@end table
|
||
|
||
@node Projecting Attributes, Attribute Examples, Displaying Attributes, Attributed Variables
|
||
|
||
Constraint solvers must be able to project a set of constraints to a set
|
||
of variables. This is useful when displaying the solution to a goal, but
|
||
may also be used to manipulate computations. The user-defined
|
||
@code{project_attributes/2} is responsible for implementing this
|
||
projection.
|
||
|
||
|
||
|
||
@table @code
|
||
@item @var{Module}:project_attributes(@var{+QueryVars}, @var{+AttrVars})
|
||
@findex project_attributes/2
|
||
@syindex project_attributes/2
|
||
@cnindex project_attributes/2
|
||
Given a list of variables @var{QueryVars} and list of attributed
|
||
variables @var{AttrVars}, project all attributes in @var{AttrVars} to
|
||
@var{QueryVars}. Although projection is constraint system dependent,
|
||
typically this will involve expressing all constraints in terms of
|
||
@var{QueryVars} and considering all remaining variables as existentially
|
||
quantified.
|
||
@end table
|
||
|
||
Projection interacts with @code{attribute_goal/2} at the prolog top
|
||
level. When the query succeeds, the system first calls
|
||
@code{project_attributes/2}. The system then calls
|
||
@code{attribute_goal/2} to get a user-level representation of the
|
||
constraints. Typically, @code{attribute_goal/2} will convert from the
|
||
original constraints into a set of new constraints on the projection,
|
||
and these constraints are the ones that will have an
|
||
@code{attribute_goal/2} handler.
|
||
|
||
@node Attribute Examples, ,Projecting Attributes, Attributed Variables
|
||
|
||
The following two examples example is taken from the SICStus Prolog manual. It
|
||
sketches the implementation of a simple finite domain ``solver''. Note
|
||
that an industrial strength solver would have to provide a wider range
|
||
of functionality and that it quite likely would utilize a more efficient
|
||
representation for the domains proper. The module exports a single
|
||
predicate @code{domain(@var{-Var},@var{?Domain})} which associates
|
||
@var{Domain} (a list of terms) with @var{Var}. A variable can be
|
||
queried for its domain by leaving @var{Domain} unbound.
|
||
|
||
We do not present here a definition for @code{project_attributes/2}.
|
||
Projecting finite domain constraints happens to be difficult.
|
||
|
||
|
||
@example
|
||
:- module(domain, [domain/2]).
|
||
|
||
:- use_module(library(atts)).
|
||
:- use_module(library(ordsets), [
|
||
ord_intersection/3,
|
||
ord_intersect/2,
|
||
list_to_ord_set/2
|
||
]).
|
||
|
||
:- attribute dom/1.
|
||
|
||
verify_attributes(Var, Other, Goals) :-
|
||
get_atts(Var, dom(Da)), !, % are we involved?
|
||
( var(Other) -> % must be attributed then
|
||
( get_atts(Other, dom(Db)) -> % has a domain?
|
||
ord_intersection(Da, Db, Dc),
|
||
Dc = [El|Els], % at least one element
|
||
( Els = [] -> % exactly one element
|
||
Goals = [Other=El] % implied binding
|
||
; Goals = [],
|
||
put_atts(Other, dom(Dc))% rescue intersection
|
||
)
|
||
; Goals = [],
|
||
put_atts(Other, dom(Da)) % rescue the domain
|
||
)
|
||
; Goals = [],
|
||
ord_intersect([Other], Da) % value in domain?
|
||
).
|
||
verify_attributes(_, _, []). % unification triggered
|
||
% because of attributes
|
||
% in other modules
|
||
|
||
attribute_goal(Var, domain(Var,Dom)) :- % interpretation as goal
|
||
get_atts(Var, dom(Dom)).
|
||
|
||
domain(X, Dom) :-
|
||
var(Dom), !,
|
||
get_atts(X, dom(Dom)).
|
||
domain(X, List) :-
|
||
list_to_ord_set(List, Set),
|
||
Set = [El|Els], % at least one element
|
||
( Els = [] -> % exactly one element
|
||
X = El % implied binding
|
||
; put_atts(Fresh, dom(Set)),
|
||
X = Fresh % may call
|
||
% verify_attributes/3
|
||
).
|
||
@end example
|
||
|
||
Note that the ``implied binding'' @code{Other=El} was deferred until after
|
||
the completion of @code{verify_attribute/3}. Otherwise, there might be a
|
||
danger of recursively invoking @code{verify_attribute/3}, which might bind
|
||
@code{Var}, which is not allowed inside the scope of @code{verify_attribute/3}.
|
||
Deferring unifications into the third argument of @code{verify_attribute/3}
|
||
effectively serializes th calls to @code{verify_attribute/3}.
|
||
|
||
Assuming that the code resides in the file @file{domain.yap}, we
|
||
can use it via:
|
||
|
||
@example
|
||
| ?- use_module(domain).
|
||
@end example
|
||
|
||
Let's test it:
|
||
|
||
@example
|
||
| ?- domain(X,[5,6,7,1]), domain(Y,[3,4,5,6]), domain(Z,[1,6,7,8]).
|
||
|
||
domain(X,[1,5,6,7]),
|
||
domain(Y,[3,4,5,6]),
|
||
domain(Z,[1,6,7,8]) ?
|
||
|
||
yes
|
||
| ?- domain(X,[5,6,7,1]), domain(Y,[3,4,5,6]), domain(Z,[1,6,7,8]),
|
||
X=Y.
|
||
|
||
Y = X,
|
||
domain(X,[5,6]),
|
||
domain(Z,[1,6,7,8]) ?
|
||
|
||
yes
|
||
| ?- domain(X,[5,6,7,1]), domain(Y,[3,4,5,6]), domain(Z,[1,6,7,8]),
|
||
X=Y, Y=Z.
|
||
|
||
X = 6,
|
||
Y = 6,
|
||
Z = 6
|
||
@end example
|
||
|
||
To demonstrate the use of the @var{Goals} argument of
|
||
@code{verify_attributes/3}, we give an implementation of
|
||
@code{freeze/2}. We have to name it @code{myfreeze/2} in order to
|
||
avoid a name clash with the built-in predicate of the same name.
|
||
|
||
@example
|
||
:- module(myfreeze, [myfreeze/2]).
|
||
|
||
:- use_module(library(atts)).
|
||
|
||
:- attribute frozen/1.
|
||
|
||
verify_attributes(Var, Other, Goals) :-
|
||
get_atts(Var, frozen(Fa)), !, % are we involved?
|
||
( var(Other) -> % must be attributed then
|
||
( get_atts(Other, frozen(Fb)) % has a pending goal?
|
||
-> put_atts(Other, frozen((Fa,Fb))) % rescue conjunction
|
||
; put_atts(Other, frozen(Fa)) % rescue the pending goal
|
||
),
|
||
Goals = []
|
||
; Goals = [Fa]
|
||
).
|
||
verify_attributes(_, _, []).
|
||
|
||
attribute_goal(Var, Goal) :- % interpretation as goal
|
||
get_atts(Var, frozen(Goal)).
|
||
|
||
myfreeze(X, Goal) :-
|
||
put_atts(Fresh, frozen(Goal)),
|
||
Fresh = X.
|
||
@end example
|
||
|
||
Assuming that this code lives in file @file{myfreeze.yap},
|
||
we would use it via:
|
||
|
||
@example
|
||
| ?- use_module(myfreeze).
|
||
| ?- myfreeze(X,print(bound(x,X))), X=2.
|
||
|
||
bound(x,2) % side effect
|
||
X = 2 % bindings
|
||
@end example
|
||
|
||
The two solvers even work together:
|
||
|
||
@example
|
||
| ?- myfreeze(X,print(bound(x,X))), domain(X,[1,2,3]),
|
||
domain(Y,[2,10]), X=Y.
|
||
|
||
bound(x,2) % side effect
|
||
X = 2, % bindings
|
||
Y = 2
|
||
@end example
|
||
|
||
The two example solvers interact via bindings to shared attributed
|
||
variables only. More complicated interactions are likely to be found
|
||
in more sophisticated solvers. The corresponding
|
||
@code{verify_attributes/3} predicates would typically refer to the
|
||
attributes from other known solvers/modules via the module prefix in
|
||
@code{@var{Module}:get_atts/2}.
|
||
|
||
|
||
@node CLPQR, CHR, Attributed Variables, Extensions
|
||
@chapter CLP(Q,R) Manual
|
||
@cindex CLPQ
|
||
@cindex CLPR
|
||
|
||
@menu
|
||
* Introduction to CLPQR:: The CLP(Q,R) System
|
||
* Referencing CLPQR:: How to Reference CLP(Q,R)
|
||
* CLPQR Acknowledgments:: Acknowledgments for CLP(Q,R)
|
||
* Solver Interface:: Using the CLP(Q,R) System
|
||
* Notational Conventions:: The CLP(Q,R) Notation
|
||
* Solver Predicates:: The CLP(Q,R) Interface Predicates
|
||
* Unification:: Unification and CLP(Q,R)
|
||
* Feedback and Bindings:: Information flow in CLP(Q,R)
|
||
* Linearity and Nonlinear Residues:: Linear and Nonlinear Constraints
|
||
* How Nonlinear Residues are made to disappear:: Handling Nonlinear Residues
|
||
* Isolation Axioms:: Isolating the Variable to be Solved
|
||
* Numerical Precision and Rationals:: Reals and Rationals
|
||
* Projection and Redundancy Elimination:: Presenting Bindings for Query Variables
|
||
* Variable Ordering:: Linear Relationships between Variables
|
||
* Turning Answers into Terms:: using @code{call_residue/2}
|
||
* Projecting Inequalities:: How to project linear inequations
|
||
* Why Disequations:: Using Disequations in CLP(Q,R)
|
||
* Syntactic Sugar:: An easier syntax
|
||
* Monash Examples:: The Monash Library
|
||
* Compatibility Notes:: CLP(Q,R) and the clp(R) interpreter
|
||
* A Mixed Integer Linear Optimization Example:: MIP models
|
||
* Implementation Architecture:: CLP(Q,R) Components
|
||
* Fragments and Bits:: Final Last Words on CLP(Q,R)
|
||
* CLPQR Bugs:: Bugs in CLP(Q,R)
|
||
* CLPQR References:: References for CLP(Q,R)
|
||
@end menu
|
||
|
||
This Manual documents a Prolog implementation of clp(Q,R), based on
|
||
SICStus featuring extensible unification via attributed variables.
|
||
|
||
Edition 1.3.3 December 1995
|
||
|
||
Christian Holzbaur @code{christian@@ai.univie.ac.at}
|
||
|
||
Copyright @copyright{} 1992,1993,1994,1995 OFAI Austrian Research
|
||
Institute for Artificial Intelligence (OFAI) Schottengasse 3 A-1010
|
||
Vienna, Austria
|
||
|
||
Permission is granted to make and distribute verbatim copies of this
|
||
manual provided the copyright notice and this permission notice are
|
||
preserved on all copies.
|
||
|
||
Permission is granted to copy and distribute modified versions of this
|
||
manual under the conditions for verbatim copying, provided that the
|
||
entire resulting derived work is distributed under the terms of a
|
||
permission notice identical to this one.
|
||
|
||
Permission is granted qto copy and distribute translations of this
|
||
manual into another language, under the above conditions for modified
|
||
versions, except that this permission notice may be stated in a
|
||
translation approved by the OFAI.
|
||
|
||
@node Introduction to CLPQR, Referencing CLPQR, , CLPQR
|
||
@section Introduction to CLP(Q,R)
|
||
|
||
The clp(Q,R) system described in this document is an instance of the
|
||
general Constraint Logic Programming scheme introduced by [Jaffar &
|
||
Michaylov 87].
|
||
|
||
The implementation is at least as complete as other existing clp(R)
|
||
implementations: It solves linear equations over rational or real
|
||
valued variables, covers the lazy treatment of nonlinear equations,
|
||
features a decision algorithm for linear inequalities that detects
|
||
implied equations, removes redundancies, performs projections
|
||
(quantifier elimination), allows for linear dis-equations, and
|
||
provides for linear optimization.
|
||
|
||
The full clp(Q,R) distribution, including a stand-alone manual and an
|
||
examples directory that is possibly more up to date than the version
|
||
in the SICStus Prolog distribution, is available from:
|
||
http://www.ai.univie.ac.at/clpqr/.
|
||
|
||
@node Referencing CLPQR, CLPQR Acknowledgments, Introduction to CLPQR, CLPQR
|
||
@section Referencing CLP(Q,R)
|
||
|
||
When referring to this implementation of clp(Q,R) in publications, you
|
||
should use the following reference:
|
||
|
||
Holzbaur C.: OFAI clp(q,r) Manual, Edition 1.3.3, Austrian Research
|
||
Institute for Artificial Intelligence, Vienna, TR-95-09, 1995.
|
||
|
||
@node CLPQR Acknowledgments, Solver Interface, Referencing CLPQR, CLPQR
|
||
@section CLP(QR) Acknowledgments
|
||
Acknowledgments
|
||
|
||
The development of this software was supported by the Austrian Fonds
|
||
zur Foerderung der Wissenschaftlichen Forschung under grant
|
||
P9426-PHY. Financial support for the Austrian Research Institute for
|
||
Artificial Intelligence is provided by the Austrian Federal Ministry
|
||
for Science and Research.
|
||
|
||
We include a collection of examples that has been distributed with the
|
||
Monash University version of clp(R) [Heintze et al. 87], and its
|
||
inclusion into this distribution was kindly permitted by Roland Yap.
|
||
|
||
@node Solver Interface, Notational Conventions, CLPQR Acknowledgments, CLPQR
|
||
@section Solver Interface
|
||
|
||
Rational numbers are not first class citizens in SICStus Prolog, so
|
||
rational arithmetics has to be emulated. Because of the emulation it
|
||
is too expensive to support arithmetics with automatic coercion
|
||
between all sorts of numbers, like you find it in CommonLisp, for
|
||
example.
|
||
|
||
You must choose whether you want to operate in the field of Q
|
||
(Rationals) or R (Reals):
|
||
|
||
@example
|
||
?- use_module(library(clpq)).
|
||
@end example
|
||
|
||
or
|
||
@example
|
||
?- use_module(library(clpr)).
|
||
@end example
|
||
|
||
@node Notational Conventions, Solver Predicates, Solver Interface, CLPQR
|
||
@section Notational Conventions
|
||
|
||
Throughout this chapter, the prompts @code{clp(q) ?-} and @code{clp(r)
|
||
?-} are used to differentiate between clp(Q) and clp(R) in exemplary
|
||
interactions.
|
||
|
||
In general there are many ways to express the same linear
|
||
relationship. This degree of freedom is manifest in the fact that the
|
||
printed manual and an actual interaction with the current version of
|
||
clp(Q,R) may show syntactically different answer constraints, despite
|
||
the fact the same semantic relationship is being expressed. There are
|
||
means to control the presentation, see @pxref{Variable Ordering}. The
|
||
approximative nature of floating point numbers may also produce
|
||
numerical differences between the text in this manual and the actual
|
||
results of clp(R), for a given edition of the software.
|
||
|
||
@node Solver Predicates, Unification, Notational Conventions, CLPQR
|
||
@section Solver Predicates
|
||
|
||
The solver interface for both Q and R consists of the following
|
||
predicates which are exported from module(linear).
|
||
|
||
@table @code
|
||
@item @{+@var{Constraint}@}
|
||
|
||
@var{Constraint} is a term accepted by the the grammar below. The
|
||
corresponding constraint is added to the current constraint store and
|
||
checked for satisfiability. If you want to overload @{@}/1 with other
|
||
solvers, you can avoid its importation via: @code{use_module(clpq, [])}.
|
||
|
||
@example
|
||
@var{Constraint} --> @var{C}
|
||
| @var{C} , @var{C} conjunction
|
||
|
||
@var{C} --> @var{Expr} =:= @var{Expr} equation
|
||
| @var{Expr} = @var{Expr} equation
|
||
| @var{Expr} < @var{Expr} strict inequation
|
||
| @var{Expr} > @var{Expr} strict inequation
|
||
| @var{Expr} =< @var{Expr} nonstrict inequation
|
||
| @var{Expr} >= @var{Expr} nonstrict inequation
|
||
| @var{Expr} =\= @var{Expr} disequation
|
||
|
||
@var{Expr} --> variable Prolog variable
|
||
| number floating point or integer
|
||
| + @var{Expr} unary plus
|
||
| - @var{Expr} unary minus
|
||
| @var{Expr} + @var{Expr} addition
|
||
| @var{Expr} - @var{Expr} subtraction
|
||
| @var{Expr} * @var{Expr} multiplication
|
||
| @var{Expr} / @var{Expr} division
|
||
| abs(@var{Expr}) absolute value
|
||
| sin(@var{Expr}) trigonometric sine
|
||
| cos(@var{Expr}) trigonometric cosine
|
||
| tan(@var{Expr}) trigonometric tangent
|
||
| pow(@var{Expr},@var{Expr}) raise to the power
|
||
| exp(@var{Expr},@var{Expr}) raise to the power
|
||
| min(@var{Expr},@var{Expr}) minimum of the two
|
||
arguments
|
||
| max(@var{Expr},@var{Expr}) maximum of the two
|
||
arguments
|
||
| #(Const) symbolic numerical
|
||
constant
|
||
@end example
|
||
|
||
Conjunctive constraints @t{@{-C,C@}} have been made part of the syntax
|
||
in order to enable grouped submission of constraints, which could be
|
||
exploited by future versions of this software. Symbolic numerical
|
||
constants are provided for compatibility only, see @pxref{Monash Examples}.
|
||
|
||
@item entailed(+@var{Constraint})
|
||
|
||
Succeeds iff the linear @var{Constraint} is entailed by the current
|
||
constraint store. This predicate does not change the state of the
|
||
constraint store.
|
||
|
||
@example
|
||
clp(q) ?- @{A =< 4@}, entailed(A=\=5).
|
||
|
||
@{A=<4@}
|
||
yes
|
||
|
||
clp(q) ?- @{A =< 4@}, entailed(A=\=3).
|
||
no
|
||
@end example
|
||
|
||
@item inf(+@var{Expr}, -@var{Inf} )
|
||
Computes the infimum of the linear expression @var{Expr} and unifies it
|
||
with @var{Inf}. Failure indicates unboundedness.
|
||
|
||
@item sup(+@var{Expr}, -@var{Sup})
|
||
|
||
Computes the supremum of the linear expression @var{Expr} and unifies it
|
||
with @var{Sup}. Failure indicates unboundedness.
|
||
|
||
@example
|
||
clp(q) ?- @{ 2*X+Y =< 16, X+2*Y =< 11,
|
||
X+3*Y =< 15, Z = 30*X+50*Y
|
||
@}, sup(Z, Sup).
|
||
|
||
Sup = 310,
|
||
@{Z=30*X+50*Y@},
|
||
@{X+1/2*Y=<8@}
|
||
|
||
@{X+3*Y=<15@},
|
||
@{X+2*Y=<11@}
|
||
@end example
|
||
|
||
@item minimize(+@var{Expr})
|
||
|
||
Computes the infimum of the linear expression @var{Expr} and equates it
|
||
with the expression, i.e. as if defined as:
|
||
|
||
@example
|
||
minimize(Expr) :- inf(Expr, Expr).
|
||
@end example
|
||
|
||
@item maximize(+@var{Expr})
|
||
|
||
Computes the supremum of the linear expression @var{Expr} and equates it
|
||
with the expression.
|
||
|
||
@example
|
||
clp(q) ?- @{ 2*X+Y =< 16, X+2*Y =< 11,
|
||
X+3*Y =< 15, Z = 30*X+50*Y
|
||
@}, maximize(Z).
|
||
|
||
X = 7,
|
||
Y = 2,
|
||
Z = 310
|
||
@end example
|
||
|
||
@item bb_inf(+@var{Ints}, +@var{Expr}, -@var{Inf})
|
||
|
||
Computes the infimum of the linear expression @var{Expr} under the
|
||
additional constraint that all of variables in the list @var{Ints}
|
||
assume integral values at the infimum. This allows for the solution of
|
||
mixed integer linear optimization problems, see @pxref{A Mixed Integer
|
||
Linear Optimization Example}.
|
||
|
||
@item ordering(+@var{Spec})
|
||
|
||
Provides a means to control one aspect of the presentation of the answer
|
||
constraints, see @pxref{Variable Ordering}.
|
||
@end table
|
||
|
||
@node Unification, Feedback and Bindings, Solver Predicates, CLPQR
|
||
@section Unification
|
||
|
||
Equality constraints are added to the store implicitly each time
|
||
variables that have been mentioned in explicit constraints are bound -
|
||
either to another such variable or to a number.
|
||
|
||
@example
|
||
clp(r) ?- @{2*A+3*B=C/2@}, C=10.0, A=B.
|
||
|
||
A = 1.0,
|
||
B = 1.0,
|
||
C = 10.0
|
||
@end example
|
||
|
||
Is equivalent modulo rounding errors to
|
||
|
||
@example
|
||
clp(r) ?- @{2*A+3*B=C/2, C=10, A=B@}.
|
||
|
||
A = 1.0,
|
||
B = 0.9999999999999999,
|
||
C = 10.0
|
||
@end example
|
||
|
||
The shortcut bypassing the use of @{@}q/1 is allowed and makes sense
|
||
because the interpretation of this equality in Prolog and clp(R)
|
||
coincides. In general, equations involving interpreted functors,
|
||
@code{+/2} in this case, must be fed to the solver explicitly:
|
||
|
||
@example
|
||
clp(r) ?- X=3.0+1.0, X=4.0.
|
||
|
||
no
|
||
@end example
|
||
|
||
Further, variables known by clp(R) may be bound directly to floats
|
||
only. Likewise, variables known by clp(Q) may be bound directly to
|
||
rational numbers only, see @pxref{Numerical Precision and
|
||
Rationals}. Failing to do so is rewarded with an exception:
|
||
|
||
@example
|
||
clp(q) ?- @{2*A+3*B=C/2@}, C=10.0, A=B.
|
||
|
||
[ERROR: not.normalized(10.0)]
|
||
@end example
|
||
|
||
This is because 10.0 is not a rational constant. To make clp(Q) happy
|
||
you have to say:
|
||
|
||
@example
|
||
clp(q) ?- @{2*A+3*B=C/2@}, C=rat(10,1), A=B.
|
||
|
||
A = 1,
|
||
B = 1,
|
||
C = 10
|
||
@end example
|
||
|
||
If you use @code{@{@}/1}, you don't have to worry about such
|
||
details. Alternatively, you may use the automatic expansion facility,
|
||
check @pxref{Syntactic Sugar}.
|
||
|
||
@node Feedback and Bindings, Linearity and Nonlinear Residues,Unification, CLPQR
|
||
@section Feedback and Bindings
|
||
|
||
What was covered so far was how the user populates the constraint
|
||
store. The other direction of the information flow consists of the
|
||
success and failure of the above predicates and the binding of variables
|
||
to numerical values and the aliasing of variables. Example:
|
||
|
||
@example
|
||
clp(r) ?- @{A-B+C=10, C=5+5@}.
|
||
|
||
B = A,
|
||
C = 10.0
|
||
@end example
|
||
|
||
The linear constraints imply @code{A=B} and the solver consequently
|
||
exports this binding to the Prolog world, which is manifest in the fact
|
||
that the test @code{A==B} will succeed. More about answer presentation
|
||
in @pxref{Projection and Redundancy Elimination}.
|
||
|
||
@node Linearity and Nonlinear Residues, How Nonlinear Residues are made to disappear,Feedback and Bindings, CLPQR
|
||
@section Linearity and Nonlinear Residues
|
||
|
||
The clp(Q,R) system is restricted to deal with linear constraints
|
||
because the decision algorithms for general nonlinear constraints are
|
||
prohibitively expensive to run. If you need this functionality badly,
|
||
you should look into symbolic algebra packages. Although the clp(Q,R)
|
||
system cannot solve nonlinear constraints, it will collect them
|
||
faithfully in the hope that through the addition of further (linear)
|
||
constraints they might get simple enough to solve eventually. If an
|
||
answer contains constraints, you have to be aware of the fact that
|
||
success is qualified modulo the existence of a solution to the system of
|
||
residual (nonlinear) constraints:
|
||
|
||
@example
|
||
clp(r) ?- @{sin(X) = cos(X)@}.
|
||
|
||
nonlin:@{sin(X)-cos(X)=0.0@}
|
||
@end example
|
||
|
||
There are indeed infinitely many solutions to this constraint (@code{X =
|
||
0.785398 + n*Pi}), but clp(Q,R) has no direct means to find and
|
||
represent them.
|
||
|
||
The systems goes through some lengths to recognize linear expressions as
|
||
such. The method is based on a normal form for multivariate
|
||
polynomials. In addition, some simple isolation axioms, that can be used
|
||
in equality constraints, have been added. The current major limitation
|
||
of the method is that full polynomial division has not been implemented.
|
||
|
||
This is an example where the isolation axioms are sufficient to
|
||
determine the value of X.
|
||
|
||
@example
|
||
clp(r) ?- @{sin(cos(X)) = 1/2@}.
|
||
|
||
X = 1.0197267436954502
|
||
@end example
|
||
|
||
If we change the equation into an inequation, clp(Q,R) gives up:
|
||
|
||
@example
|
||
clp(r) ?- @{sin(cos(X)) < 1/2@}.
|
||
|
||
nonlin:@{sin(cos(X))-0.5!0.0@}
|
||
@end example
|
||
|
||
The following is easy again:
|
||
|
||
@example
|
||
clp(r) ?- @{sin(X+2+2)/sin(4+X) = Y@}.
|
||
|
||
Y = 1.0
|
||
@end example
|
||
|
||
And so is this:
|
||
|
||
@example
|
||
clp(r) ?- @{(X+Y)*(Y+X)/X = Y*Y/X+99@}.
|
||
|
||
@{Y=49.5-0.5*X@}
|
||
@end example
|
||
|
||
An ancient symbol manipulation benchmark consists in rising the
|
||
expression @code{X+Y+Z+1} to the 15th power:
|
||
|
||
@example
|
||
clp(q) ?- @{exp(X+Y+Z+1,15)=0@}.
|
||
|
||
nonlin:@{Z^15+Z^14*15+Z^13*105+Z^12*455+Z^11*1365+Z^10*3003+...
|
||
... polynomial continues for a few pages ...
|
||
=0@}
|
||
@end example
|
||
|
||
Computing its roots is another story.
|
||
|
||
@node How Nonlinear Residues are made to disappear, Isolation Axioms,Linearity and Nonlinear Residues, CLPQR
|
||
@section How Nonlinear Residues are made to disappear
|
||
|
||
Binding variables that appear in nonlinear residues will reduce the
|
||
complexity of the nonlinear expressions and eventually results in linear
|
||
expressions:
|
||
|
||
@example
|
||
clp(q) ?- @{exp(X+Y+1,2) = 3*X*X+Y*Y@}.
|
||
|
||
nonlin:@{Y*2-X^2*2+Y*X*2+X*2+1=0@}
|
||
@end example
|
||
|
||
Equating X and Y collapses the expression completely and even determines
|
||
the values of the two variables:
|
||
|
||
@example
|
||
clp(q) ?- @{exp(X+Y+1,2) = 3*X*X+Y*Y@}, X=Y.
|
||
|
||
X = -1/4,
|
||
Y = -1/4
|
||
@end example
|
||
|
||
@node Isolation Axioms, Numerical Precision and Rationals,How Nonlinear Residues are made to disappear, CLPQR
|
||
@section Isolation Axioms
|
||
|
||
These axioms are used to rewrite equations such that the variable to be
|
||
solved for is moved to the left hand side and the result of the
|
||
evaluation of the right hand side can be assigned to the variable. This
|
||
allows, for example, to use the exponentiation operator for the
|
||
computation of roots and logarithms, see below.
|
||
|
||
@table @code
|
||
@item @var{A} = @var{B} * @var{C}
|
||
Residuates unless @var{B} or @var{C} is ground or @var{A} and @var{B}
|
||
or @var{C} are ground.
|
||
|
||
@item @var{A} = @var{B} / @var{C}
|
||
Residuates unless @var{C} is ground or @var{A} and @var{B} are ground.
|
||
|
||
@item @var{X} = min(@var{Y},@var{Z})
|
||
Residuates unless @var{Y} and @var{Z} are ground.
|
||
|
||
@item @var{X} = max(@var{Y},@var{Z})
|
||
Residuates unless @var{Y} and @var{Z} are ground.
|
||
|
||
@item @var{X} = abs(@var{Y})
|
||
Residuates unless @var{Y} is ground.
|
||
|
||
@item @var{X} = pow(@var{Y},@var{Z}), @var{X} = exp(@var{Y},@var{Z})
|
||
Residuates unless any pair of two of the three variables is ground. Example:
|
||
|
||
@example
|
||
clp(r) ?- @{ 12=pow(2,X) @}.
|
||
|
||
X = 3.5849625007211565
|
||
|
||
clp(r) ?- @{ 12=pow(X,3.585) @}.
|
||
|
||
X = 1.9999854993443926
|
||
|
||
clp(r) ?- @{ X=pow(2,3.585) @}.
|
||
|
||
X = 12.000311914286545
|
||
@end example
|
||
|
||
@item @var{X} = sin(@var{Y})
|
||
Residuates unless @var{X} or @var{Y} is ground. Example:
|
||
|
||
@example
|
||
clp(r) ?- @{ 1/2 = sin(X) @}.
|
||
|
||
X = 0.5235987755982989
|
||
@end example
|
||
|
||
@item @var{X} = cos(@var{Y})
|
||
Residuates unless @var{X} or @var{Y} is ground.
|
||
|
||
@item @var{X} = tan(@var{Y})
|
||
Residuates unless @var{X} or @var{Y} is ground.
|
||
@end table
|
||
|
||
@node Numerical Precision and Rationals, Projection and Redundancy Elimination,Isolation Axioms, CLPQR
|
||
@section Numerical Precision and Rationals
|
||
|
||
The fact that you can switch between clp(R) and clp(Q) should solve most
|
||
of your numerical problems regarding precision. Within clp(Q), floating
|
||
point constants will be coerced into rational numbers
|
||
automatically. Transcendental functions will be approximated with
|
||
rationals. The precision of the approximation is limited by the floating
|
||
point precision. These two provisions allow you to switch between clp(R)
|
||
and clp(Q) without having to change your programs.
|
||
|
||
What is to be kept in mind however is the fact that it may take quite
|
||
big rationals to accommodate the required precision. High levels of
|
||
precision are for example required if your linear program is
|
||
ill-conditioned, i.e., in a full rank system the determinant of the
|
||
coefficient matrix is close to zero. Another situation that may call for
|
||
elevated levels of precision is when a linear optimization problem
|
||
requires exceedingly many pivot steps before the optimum is reached.
|
||
|
||
If your application approximates irrational numbers, you may be out of
|
||
space particularly soon. The following program implements N steps of
|
||
Newton's approximation for the square root function at point 2.
|
||
|
||
@example
|
||
%
|
||
% from file: library('clpqr/examples/root')
|
||
%
|
||
|
||
root(N, R) :-
|
||
root(N, 1, R).
|
||
|
||
root(0, S, R) :- !, S=R.
|
||
root(N, S, R) :-
|
||
N1 is N-1,
|
||
@{ S1 = S/2 + 1/S @},
|
||
root(N1, S1, R).
|
||
@end example
|
||
|
||
It is known that this approximation converges quadratically, which means
|
||
that the number of correct digits in the decimal expansion roughly
|
||
doubles with each iteration. Therefore the numerator and denominator of
|
||
the rational approximation have to grow likewise:
|
||
|
||
@example
|
||
clp(q) ?- use+odule(library('clpqr/examples/root')).
|
||
clp(q) ?- root(3,R),print_decimal(R,70).
|
||
1.4142156862 7450980392 1568627450 9803921568 6274509803 9215686274
|
||
5098039215
|
||
|
||
R = 577/408
|
||
|
||
clp(q) ?- root(4,R),print_decimal(R,70).
|
||
1.4142135623 7468991062 6295578890 1349101165 5962211574 4044584905
|
||
0192000543
|
||
|
||
R = 665857/470832
|
||
|
||
clp(q) ?- root(5,R),print_decimal(R,70).
|
||
|
||
1.4142135623 7309504880 1689623502 5302436149 8192577619 7428498289
|
||
4986231958
|
||
|
||
R = 886731088897/627013566048
|
||
|
||
clp(q) ?- root(6,R),print_decimal(R,70).
|
||
|
||
1.4142135623 7309504880 1688724209 6980785696 7187537723 4001561013
|
||
1331132652
|
||
|
||
R = 1572584048032918633353217/1111984844349868137938112
|
||
|
||
clp(q) ?- root(7,R),print_decimal(R,70).
|
||
|
||
1.4142135623 7309504880 1688724209 6980785696 7187537694 8073176679
|
||
7379907324
|
||
|
||
R = 4946041176255201878775086487573351061418968498177 /
|
||
3497379255757941172020851852070562919437964212608
|
||
@end example
|
||
|
||
Iterating for 8 steps produces no further change in the first 70 decimal
|
||
digits of @code{sqrt(2)}. After 15 steps the approximating rational
|
||
number has a numerator and a denominator with 12543 digits each, and the
|
||
next step runs out of memory.
|
||
|
||
Another irrational number that is easily computed is @code{e}. The
|
||
following program implements an alternating series for @code{1/e}, where
|
||
the absolute value of last term is an upper bound on the error.
|
||
|
||
@example
|
||
%
|
||
% from file: library('clpqr/examples/root')
|
||
%
|
||
|
||
e(N, E) :-
|
||
@{ Err =:= exp(10,-(N+2)), Half =:= 1/2 @},
|
||
inv_e_series(Half, Half, 3, Err, Inv.E),
|
||
@{ E =:= 1/Inv_E @}.
|
||
|
||
inv_e_series(Term, S0, ., Err, Sum) :-
|
||
@{ abs(Term) =< Err @}, !,
|
||
S0 = Sum.
|
||
|
||
inv_e_series(Term, S0, N, Err, Sum) :-
|
||
N1 is N+1,
|
||
@{ Term1 =:= -Term/N, S1 =:= Term1+S0 @},
|
||
inv_e_series(Term1, S1, N1, Err, Sum).
|
||
@end example
|
||
|
||
The computation of the rational number @var{E} that approximates
|
||
@code{e} up to at least 1000 digits in its decimal expansion requires
|
||
the evaluation of 450 terms of the series, i.e. 450 calls of
|
||
inv.e. series/5.
|
||
|
||
@example
|
||
clp(q) ?- e(1000,E).
|
||
|
||
E = 7149056228932760213666809592072842334290744221392610955845565494
|
||
3708750229467761730471738895197792271346693089326102132000338192
|
||
0131874187833985420922688804220167840319199699494193852403223700
|
||
5853832741544191628747052136402176941963825543565900589161585723
|
||
4023097417605004829991929283045372355639145644588174733401360176
|
||
9953973706537274133283614740902771561159913069917833820285608440
|
||
3104966899999651928637634656418969027076699082888742481392304807
|
||
9484725489080844360397606199771786024695620205344042765860581379
|
||
3538290451208322129898069978107971226873160872046731879753034549
|
||
3130492167474809196348846916421782850086985668680640425192038155
|
||
4902863298351349469211627292865440876581064873866786120098602898
|
||
8799130098877372097360065934827751120659213470528793143805903554
|
||
7928682131082164366007016698761961066948371407368962539467994627
|
||
1374858249110795976398595034606994740186040425117101588480000000
|
||
0000000000000000000000000000000000000000000000000000000000000000
|
||
00000000000000000000000000000000000000
|
||
/
|
||
2629990810403002651095959155503002285441272170673105334466808931
|
||
6863103901346024240326549035084528682487048064823380723787110941
|
||
6809235187356318780972302796570251102928552003708556939314795678
|
||
1978390674393498540663747334079841518303636625888963910391440709
|
||
0887345797303470959207883316838346973393937778363411195624313553
|
||
8835644822353659840936818391050630360633734935381528275392050975
|
||
7271468992840907541350345459011192466892177866882264242860412188
|
||
0652112744642450404625763019639086944558899249788084559753723892
|
||
1643188991444945360726899532023542969572584363761073528841147012
|
||
2634218045463494055807073778490814692996517359952229262198396182
|
||
1838930043528583109973872348193806830382584040536394640895148751
|
||
0766256738740729894909630785260101721285704616818889741995949666
|
||
6303289703199393801976334974240815397920213059799071915067856758
|
||
6716458821062645562512745336709063396510021681900076680696945309
|
||
3660590933279867736747926648678738515702777431353845466199680991
|
||
73361873421152165477774911660108200059
|
||
@end example
|
||
|
||
The decimal expansion itself looks like this:
|
||
|
||
@example
|
||
clp(q) ?- e(1000, E), print_decimal(E, 1000).
|
||
2.
|
||
7182818284 5904523536 0287471352 6624977572 4709369995 9574966967
|
||
6277240766 3035354759 4571382178 5251664274 2746639193 2003059921
|
||
8174135966 2904357290 0334295260 5956307381 3232862794 3490763233
|
||
8298807531 9525101901 1573834187 9307021540 8914993488 4167509244
|
||
7614606680 8226480016 8477411853 7423454424 3710753907 7744992069
|
||
5517027618 3860626133 1384583000 7520449338 2656029760 6737113200
|
||
7093287091 2744374704 7230696977 2093101416 9283681902 5515108657
|
||
4637721112 5238978442 5056953696 7707854499 6996794686 4454905987
|
||
9316368892 3009879312 7736178215 4249992295 7635148220 8269895193
|
||
6680331825 2886939849 6465105820 9392398294 8879332036 2509443117
|
||
3012381970 6841614039 7019837679 3206832823 7646480429 5311802328
|
||
7825098194 5581530175 6717361332 0698112509 9618188159 3041690351
|
||
5988885193 4580727386 6738589422 8792284998 9208680582 5749279610
|
||
4841984443 6346324496 8487560233 6248270419 7862320900 2160990235
|
||
3043699418 4914631409 3431738143 6405462531 5209618369 0888707016
|
||
7683964243 7814059271 4563549061 3031072085 1038375051 0115747704
|
||
1718986106 8739696552 1267154688 9570350354
|
||
@end example
|
||
|
||
@node Projection and Redundancy Elimination, Variable Ordering,Numerical Precision and Rationals, CLPQR
|
||
@section Projection and Redundancy Elimination
|
||
|
||
Once a derivation succeeds, the Prolog system presents the bindings for
|
||
the variables in the query. In a CLP system, the set of answer
|
||
constraints is presented in analogy. A complication in the CLP context
|
||
are variables and associated constraints that were not mentioned in the
|
||
query. A motivating example is the familiar mortgage relation:
|
||
|
||
@example
|
||
%
|
||
% from file: library('clpqr/examples/mg')
|
||
%
|
||
|
||
mg(P,T,I,B,MP):-
|
||
@{
|
||
T = 1,
|
||
B + MP = P * (1 + I)
|
||
@}.
|
||
mg(P,T,I,B,MP):-
|
||
@{
|
||
T > 1,
|
||
P1 = P * (1 + I) - MP,
|
||
T1 = T - 1
|
||
@}, mg(P1, T1, I, B, MP).
|
||
@end example
|
||
|
||
A sample query yields:
|
||
|
||
@example
|
||
clp(r) ?- use_module(library('clpqr/examples/mg')).
|
||
|
||
clp(r) ?- mg(P,12,0.01,B,Mp).
|
||
|
||
@{B=1.1268250301319698*P-12.682503013196973*Mp@}
|
||
@end example
|
||
|
||
Without projection of the answer constraints onto the query variables we
|
||
would observe the following interaction:
|
||
|
||
@example
|
||
clp(r) ?- mg(P,12,0.01,B,Mp).
|
||
|
||
@{B=12.682503013196973*_A-11.682503013196971*P@},
|
||
@{Mp= -(_A)+1.01*P@},
|
||
@{_B=2.01*_A-1.01*P@}
|
||
@{_C=3.0301*_A-2.0301*P@},
|
||
@{_D=4.060401000000001*_A-3.0604009999999997*P@},
|
||
@{_E=5.101005010000001*_A-4.10100501*P@},
|
||
@{_F=6.152015060100001*_A-5.152015060099999*P@},
|
||
@{_G=7.213535210701001*_A-6.213535210700999*P@},
|
||
@{_H=8.285670562808011*_A-7.285670562808009*P@},
|
||
@{_I=9.368527268436091*_A-8.36852726843609*P@},
|
||
@{_J=10.462212541120453*_A-9.46221254112045*P@},
|
||
@{_K=11.566834666531657*_A-10.566834666531655*P@}
|
||
@end example
|
||
|
||
The variables @var{_A ... _K} are not part of the query, they originate
|
||
from the mortgage program proper. Although the latter answer is
|
||
equivalent to the former in terms of linear algebra, most users would
|
||
prefer the former.
|
||
|
||
@node Variable Ordering, Turning Answers into Terms,Projection and Redundancy Elimination, CLPQR
|
||
@section Variable Ordering
|
||
|
||
In general, there are many ways to express the same linear relationship
|
||
between variables. clp(Q,R) does not care to distinguish between them,
|
||
but the user might. The predicate ordering(+@var{Spec}) gives you some
|
||
control over the variable ordering. Suppose that instead of @var{B}, you
|
||
want @var{Mp} to be the defined variable:
|
||
|
||
@example
|
||
clp(r) ?- mg(P,12,0.01,B,Mp).
|
||
|
||
@{B=1.1268250301319698*P-12.682503013196973*Mp@}
|
||
@end example
|
||
|
||
This is achieved with:
|
||
|
||
@example
|
||
clp(r) ?- mg(P,12,0.01,B,Mp), ordering([Mp]).
|
||
|
||
@{Mp= -0.0788487886783417*B+0.08884878867834171*P@}
|
||
@end example
|
||
|
||
One could go one step further and require @var{P} to appear before (to
|
||
the left of) @var{B} in a addition:
|
||
|
||
@example
|
||
clp(r) ?- mg(P,12,0.01,B,Mp), ordering([Mp,P]).
|
||
|
||
@{Mp=0.08884878867834171*P-0.0788487886783417*B@}
|
||
@end example
|
||
|
||
@var{Spec} in ordering(+@var{Spec}) is either a list of variables with
|
||
the intended ordering, or of the form @code{@var{A}<@var{B}}. The latter
|
||
form means that @var{A} goes to the left of @var{B}. In fact,
|
||
@code{ordering([@var{A},@var{B},@var{C},@var{D}])} is shorthand for:
|
||
|
||
@example
|
||
ordering(A < B), ordering(A < C), ordering(A < D),
|
||
ordering(B < C), ordering(B < D),
|
||
ordering(C < D)
|
||
@end example
|
||
|
||
The ordering specification only affects the final presentation of the
|
||
constraints. For all other operations of clp(Q,R), the ordering is
|
||
immaterial. Note that ordering/1 acts like a constraint: you can put it
|
||
anywhere in the computation, and you can submit multiple specifications.
|
||
|
||
@example
|
||
clp(r) ?- ordering(B < Mp), mg(P,12,0.01,B,Mp).
|
||
|
||
@{B= -12.682503013196973*Mp+1.1268250301319698*P@}
|
||
|
||
yes
|
||
clp(r) ?- ordering(B < Mp), mg(P,12,0.01,B,Mp), ordering(P < Mp).
|
||
|
||
@{P=0.8874492252651537*B+11.255077473484631*Mp@}
|
||
@end example
|
||
|
||
@node Turning Answers into Terms, Projecting Inequalities,Variable Ordering, CLPQR
|
||
@section Turning Answers into Terms
|
||
|
||
In meta-programming applications one needs to get a grip on the results
|
||
computed by the clp(Q,R) solver. The SISCtus Prolog predicate
|
||
@code{call_residue/2} provides this functionality:
|
||
|
||
@example
|
||
clp(r) ?- call_residue(@{2*A+B+C=10,C-D=E,A<10@}, Constraints).
|
||
|
||
Constraints = [
|
||
[A]-@{A<10.0@},
|
||
[B]-@{B=10.0-2.0*A-C@},
|
||
[D]-@{D=C-E@}
|
||
]
|
||
@end example
|
||
|
||
@node Projecting Inequalities, Why Disequations,Turning Answers into Terms, CLPQR
|
||
@section Projecting Inequalities
|
||
|
||
As soon as linear inequations are involved, projection gets more
|
||
demanding complexity wise. The current clp(Q,R) version uses a
|
||
Fourier-Motzkin algorithm for the projection of linear inequalities. The
|
||
choice of a suitable algorithm is somewhat dependent on the number of
|
||
variables to be eliminated, the total number of variables, and other
|
||
factors. It is quite easy to produce problems of moderate size where the
|
||
elimination step takes some time. For example, when the dimension of the
|
||
projection is 1, you might be better off computing the supremum and the
|
||
infimum of the remaining variable instead of eliminating n-1 variables
|
||
via implicit projection.
|
||
|
||
In order to make answers as concise as possible, redundant constraints
|
||
are removed by the system as well. In the following set of inequalities,
|
||
half of them are redundant.
|
||
|
||
@example
|
||
%
|
||
% from file: library('clpqr/examples/elimination')
|
||
%
|
||
|
||
example(2, [X0,X1,X2,X3,X4]) :-
|
||
@{
|
||
+87*X0 +52*X1 +27*X2 -54*X3 +56*X4 =< -93,
|
||
+33*X0 -10*X1 +61*X2 -28*X3 -29*X4 =< 63,
|
||
-68*X0 +8*X1 +35*X2 +68*X3 +35*X4 =< -85,
|
||
+90*X0 +60*X1 -76*X2 -53*X3 +24*X4 =< -68,
|
||
-95*X0 -10*X1 +64*X2 +76*X3 -24*X4 =< 33,
|
||
+43*X0 -22*X1 +67*X2 -68*X3 -92*X4 =< -97,
|
||
+39*X0 +7*X1 +62*X2 +54*X3 -26*X4 =< -27,
|
||
+48*X0 -13*X1 +7*X2 -61*X3 -59*X4 =< -2,
|
||
+49*X0 -23*X1 -31*X2 -76*X3 +27*X4 =< 3,
|
||
-50*X0 +58*X1 -1*X2 +57*X3 +20*X4 =< 6,
|
||
-13*X0 -63*X1 +81*X2 -3*X3 +70*X4 =< 64,
|
||
+20*X0 +67*X1 -23*X2 -41*X3 -66*X4 =< 52,
|
||
-81*X0 -44*X1 +19*X2 -22*X3 -73*X4 =< -17,
|
||
-43*X0 -9*X1 +14*X2 +27*X3 +40*X4 =< 39,
|
||
+16*X0 +83*X1 +89*X2 +25*X3 +55*X4 =< 36,
|
||
+2*X0 +40*X1 +65*X2 +59*X3 -32*X4 =< 13,
|
||
-65*X0 -11*X1 +10*X2 -13*X3 +91*X4 =< 49,
|
||
+93*X0 -73*X1 +91*X2 -1*X3 +23*X4 =< -87
|
||
@}.
|
||
@end example
|
||
|
||
Consequently, the answer consists of the system of nine non-redundant
|
||
inequalities only:
|
||
|
||
@example
|
||
clp(q) ?- use_module(library('clpqr/examples/elimination')).
|
||
clp(q) ?- example(2, [X0,X1,X2,X3,X4]).
|
||
|
||
@{X0-2/17*X1-35/68*X2-X3-35/68*X4?=5/4@},
|
||
@{X0-73/93*X1+91/93*X2-1/93*X3+23/93*X4=<-29/31@},
|
||
@{X0-29/25*X1+1/50*X2-57/50*X3-2/5*X4>=-3/25@},
|
||
@{X0+7/39*X1+62/39*X2+18/13*X3-2/3*X4=<-9/13@},
|
||
@{X0+2/19*X1-64/95*X2-4/5*X3+24/95*X4>=-33/95@},
|
||
@{X0+2/3*X1-38/45*X2-53/90*X3+4/15*X4=<-34/45@},
|
||
@{X0-23/49*X1-31/49*X2-76/49*X3+27/49*X4=<3/49@},
|
||
@{X0+44/81*X1-19/81*X2+22/81*X3+73/81*X4>=17/81@},
|
||
@{X0+9/43*X1-14/43*X2-27/43*X3-40/43*X4>=-39/43@}
|
||
@end example
|
||
|
||
The projection (the shadow) of this polyhedral set into the
|
||
@var{X0},@var{X1} space can be computed via the implicit elimination of
|
||
non-query variables:
|
||
|
||
@example
|
||
clp(q) ?- example(2, [X0,X1--.]).
|
||
|
||
@{X0+2619277/17854273*X1>=-851123/17854273@},
|
||
@{X0+6429953/16575801*X1=<-12749681/16575801@},
|
||
@{X0+19130/1213083*X1>=795400/404361@},
|
||
@{X0-1251619/3956679*X1?=21101146/3956679@},
|
||
@{X0+601502/4257189*X1>=220850/473021@}
|
||
@end example
|
||
|
||
Projection is quite a powerful concept that leads to surprisingly terse
|
||
executable specifications of nontrivial problems like the computation of
|
||
the convex hull from a set of points in an n-dimensional space: Given
|
||
the program
|
||
|
||
@example
|
||
%
|
||
% from file: library('clpqr/examples/elimination')
|
||
%
|
||
conv.hull(Points, Xs) :-
|
||
lin_comb(Points, Lambdas, Zero, Xs),
|
||
zero(Zero),
|
||
polytope(Lambdas).
|
||
|
||
polytope(Xs) :-
|
||
positive_sum(Xs, 1).
|
||
|
||
positive_sum([], Z) :- @{Z=0@}.
|
||
positive_sum([X--Xs], SumX) :-
|
||
@{X >= 0, SumX = X+Sum @},
|
||
positive_sum(Xs, Sum).
|
||
|
||
zero([]).
|
||
zero([Z--Zs]) :- @{Z=0@}, zero(Zs).
|
||
|
||
lin_comb([], [], S1, S1).
|
||
lin_comb([Ps--Rest], [K--Ks], S1, S3) :-
|
||
lin_comb_r(Ps, K, S1, S2),
|
||
lin_comb(Rest, Ks, S2, S3).
|
||
|
||
lin_comb_r([], ., [], []).
|
||
lin_comb_r([P--Ps], K, [S--Ss], [Kps--Ss1]) :-
|
||
@{ Kps = K*P+S @},
|
||
lin_comb_r(Ps, K, Ss, Ss1).
|
||
@end example
|
||
|
||
we can post the following query:
|
||
|
||
@example
|
||
clp(q) ?- conv.hull([ [1,1], [2,0], [3,0], [1,2], [2,2] ], [X,Y]).
|
||
|
||
@{Y=<2@},
|
||
@{X+1/2*Y=<3@},
|
||
@{X>=1@},
|
||
@{Y>=0@},
|
||
@{X+Y>=2@}
|
||
@end example
|
||
|
||
This answer is easily verified graphically:
|
||
|
||
@example
|
||
|
|
||
2- * *
|
||
|
|
||
|
|
||
1| *
|
||
|
|
||
|
|
||
0 ---|---*---*----
|
||
1 2 3
|
||
@end example
|
||
|
||
The convex hull program directly corresponds to the mathematical
|
||
definition of the convex hull. What does the trick in operational terms
|
||
is the implicit elimination of the Lambdas from the program
|
||
formulation. Please note that this program does not limit the number of
|
||
points or the dimension of the space they are from. Please note further
|
||
that quantifier elimination is a computationally expensive operation and
|
||
therefore this program is only useful as a benchmark for the projector
|
||
and not so for the intended purpose.
|
||
|
||
@node Why Disequations, Syntactic Sugar,Projecting Inequalities, CLPQR
|
||
@section Why Disequations
|
||
|
||
A beautiful example of disequations at work is due to [Colmerauer
|
||
90]. It addresses the task of tiling a rectangle with squares of
|
||
all-different, a priori unknown sizes. Here is a translation of the
|
||
original Prolog-III program to clp(Q,R):
|
||
|
||
@example
|
||
%
|
||
% from file: library('clpqr/examples/squares')
|
||
filled_rectangle( A, C) :-
|
||
@{ A >= 1 @},
|
||
distinct_squares( C),
|
||
filled_zone( [-1,A,1], _, C, []).
|
||
|
||
distinct_squares( []).
|
||
distinct_squares( [B|C]) :-
|
||
@{ B > 0 @},
|
||
outof( C, B),
|
||
distinct_squares( C).
|
||
|
||
outof( [], _).
|
||
outof( [B1|C], B) :-
|
||
@{ B =\= B1 @}, % *** note disequation ***
|
||
outof( C, B).
|
||
|
||
filled_zone( [V|L], [V|L], C0, C0) :-
|
||
@{ V >= 0 @}.
|
||
filled_zone( [V|L], L3, [B|C], C2) :-
|
||
@{ V < 0 @},
|
||
placed_square( B, L, L1),
|
||
filled_zone( L1, L2, C, C1),
|
||
@{ Vb=V+B @},
|
||
filled_zone( [Vb,B|L2], L3, C1, C2).
|
||
|
||
placed_square( B, [H,H0,H1|L], L1) :-
|
||
@{ B > H, H0=0, H2=H+H1 @},
|
||
placed_square( B, [H2|L], L1).
|
||
placed_square( B, [B,V|L], [X|L]) :-
|
||
@{ X=V-B @}.
|
||
placed_square( B, [H|L], [X,Y|L]) :-
|
||
@{ B < H, X= -B, Y=H-B @}.
|
||
@end example
|
||
|
||
There are no tilings with less than nine squares except the trivial one
|
||
where the rectangle equals the only square. There are eight solutions
|
||
for nine squares. Six further solutions are rotations of the first two.
|
||
|
||
@example
|
||
clp(q) ?- use_module(library('clpqr/examples/squares')).
|
||
clp(q) ?- filled_rectangle(A, Squares).
|
||
|
||
A = 1,f
|
||
Squares = [1] ? ;
|
||
|
||
A = 33/32,
|
||
Squares = [15/32,9/16,1/4,7/32,1/8,7/16,1/32,5/16,9/32] ? ;
|
||
|
||
A = 69/61,
|
||
Squares = [33/61,36/61,28/61,5/61,2/61,9/61,25/61,7/61,16/61]
|
||
@end example
|
||
|
||
Depending on your hardware, the above query may take a few
|
||
minutes. Supplying the knowledge about the minimal number of squares
|
||
beforehand cuts the computation time by a factor of roughly four:
|
||
|
||
@example
|
||
clp(q) ?- length(Squares, 9), filled.rectangle(A, Squares).
|
||
|
||
A = 33/32,
|
||
Squares = [15/32,9/16,1/4,7/32,1/8,7/16,1/32,5/16,9/32] ? ;
|
||
|
||
A = 69/61,
|
||
Squares = [33/61,36/61,28/61,5/61,2/61,9/61,25/61,7/61,16/61]
|
||
@end example
|
||
|
||
@node Syntactic Sugar, Monash Examples,Why Disequations, CLPQR
|
||
@section Syntactic Sugar
|
||
|
||
There is a package that transforms programs and queries from a
|
||
eval-quote variant of clp(Q,R) into corresponding programs and queries
|
||
in a quote-eval variant. Before you use it, you need to know that in an
|
||
eval-quote language, all symbols are interpreted unless explicitly
|
||
quoted. This means that interpreted terms cannot be manipulated
|
||
syntactically directly. Meta-programming in a CLP context by definition
|
||
manipulates interpreted terms, therefore you need @code{quote/1} (just
|
||
as in LISP) and some means to put syntactical terms back to their
|
||
interpreted life: @code{@{@}/1}.
|
||
|
||
In a quote-eval language, meta-programming is (pragmatically) simpler
|
||
because everything is implicitly quoted until explicitly evaluated. On
|
||
the other hand, now object programming suffers from the dual
|
||
inconvenience.
|
||
|
||
We chose to make our version of clp(Q,R) of the quote-eval type because
|
||
this matches the intended use of the already existing boolean solver of
|
||
SICStus. In order to keep the users of the eval-quote variant happy, we
|
||
provide a source transformation package. It is activated via:
|
||
|
||
@example
|
||
| ?- use_module(library('clpqr/expand')).
|
||
@end example
|
||
|
||
Loading the package puts you in a mode where the arithmetic functors
|
||
like @code{+/2}, @code{*/2} and all numbers (functors of arity 0) are
|
||
interpreted semantically.
|
||
|
||
@example
|
||
clp(r) ?- 2+2=X. X = 4.0
|
||
@end example
|
||
|
||
The package works by purifying programs and queries in the sense that
|
||
all references to interpreted terms are made explicit. The above query
|
||
is expanded prior to evaluation into:
|
||
|
||
@example
|
||
linear:@{2.0+2.0=X@}
|
||
@end example
|
||
|
||
The same mechanism applies when interpreted terms are nested deeper:
|
||
|
||
@example
|
||
some_predicate(10, f(A+B/2), 2*cos(A))
|
||
@end example
|
||
|
||
Expands into:
|
||
|
||
@example
|
||
linear:@{Xc=2.0*cos(A)@},
|
||
linear:@{Xb=A+B/2@},
|
||
linear:@{Xa=10.0@},
|
||
some_predicate(Xa, f(Xb), Xc)
|
||
@end example
|
||
|
||
This process also applies when files are consulted or compiled. In fact,
|
||
this is the only situation where expansion can be applied with relative
|
||
safety. To see this, consider what happens when the toplevel evaluates
|
||
the expansion, namely some calls to the clp(Q,R) solver, followed by the
|
||
call of the purified query. As we learned in @pxref{Feedback and
|
||
Bindings}, the solver may bind variables, which produces a goal with
|
||
interpreted functors in it (numbers), which leads to another stage of
|
||
expansion, and so on.
|
||
|
||
We recommend that you only turn on expansion temporarily while
|
||
consulting or compiling files needing expansion with @code{expand/0} and
|
||
@code{noexpand/0}.
|
||
|
||
@node Monash Examples,Compatibility Notes ,Syntactic Sugar, CLPQR
|
||
@section Monash Examples
|
||
|
||
This collection of examples has been distributed with the Monash
|
||
University Version of clp(R) [Heintze et al. 87], and its inclusion into
|
||
this distribution was kindly permitted by Roland Yap.
|
||
|
||
In order to execute the examples, a small compatibility package has to
|
||
be loaded first:
|
||
|
||
@example
|
||
clp(r) ?- use_module(library('clpqr/monash')).
|
||
@end example
|
||
|
||
Then, assuming you are using clp(R):
|
||
|
||
@example
|
||
clp(r) ?- expand, [library('clpqr/examples/monash/rkf45')],
|
||
noexpand.
|
||
|
||
clp(r) ?- go.
|
||
Point 0.00000 : 0.75000 0.00000
|
||
Point 0.50000 : 0.61969 0.47793
|
||
Point 1.00000 : 0.29417 0.81233
|
||
Point 1.50000 : -0.10556 0.95809
|
||
Point 2.00000 : -0.49076 0.93977
|
||
Point 2.50000 : -0.81440 0.79929
|
||
Point 3.00000 : -1.05440 0.57522
|
||
|
||
Iteration finished
|
||
------------------
|
||
439 derivative evaluations
|
||
@end example
|
||
|
||
@node Compatibility Notes, A Mixed Integer Linear Optimization Example,Monash Examples, CLPQR
|
||
@section Compatibility Notes
|
||
|
||
The Monash examples have been written for clp(R). Nevertheless, all but
|
||
rkf45 complete nicely in clp(Q). With @code{rkf45}, clp(Q) runs out of
|
||
memory. This is an instance of the problem discussed in @pxref{Numerical
|
||
Precision and Rationals}.
|
||
|
||
The Monash University clp(R) interpreter features a @code{dump/n}
|
||
predicate. It is used to print the target variables according to the
|
||
given ordering. Within this version of clp(Q,R), the corresponding
|
||
functionality is provided via @code{ordering/1}. The difference is that
|
||
@code{ordering/1} does only specify the ordering of the variables and no
|
||
printing is performed. We think Prolog has enough predicates to perform
|
||
output already. You can still run the examples referring to
|
||
@code{dump/n} from the Prolog toplevel:
|
||
|
||
@example
|
||
clp(r) ?- expand, [library('clpqr/examples/monash/mortgage')], noexpand.
|
||
|
||
% go2
|
||
%
|
||
clp(r) ?- mg(P,120,0.01,0,MP), dump([P,MP]).
|
||
|
||
@{P=69.7005220313972*MP@}
|
||
|
||
% go3
|
||
%
|
||
clp(r) ?- mg(P,120,0.01,B,MP), dump([P,B,MP]).
|
||
|
||
@{P=0.30299477968602706*B+69.7005220313972*MP@}
|
||
|
||
% go4
|
||
%
|
||
clp(r) ?- mg(999, 3, Int, 0, 400), dump.
|
||
|
||
nonlin:@{_B-_B*Int+.A+400.0=0.0@},
|
||
nonlin:@{_A-_A*Int+400.0=0.0@},
|
||
@{_B=599.0+999.0*Int@}
|
||
@end example
|
||
|
||
@node A Mixed Integer Linear Optimization Example, Implementation Architecture,Compatibility Notes, CLPQR
|
||
@
|
||
|
||
In this section we are going to exercise our solver a little by the
|
||
computation of a small mixed integer optimization problem (MIP) from
|
||
miplib, a collection of MIP models, housed at Rice University. Here are
|
||
the original comments on the example:
|
||
|
||
@example
|
||
NAME: flugpl
|
||
ROWS: 18
|
||
COLUMNS: 18
|
||
INTEGER: 11
|
||
NONZERO: 46
|
||
BEST SOLN: 1201500 (opt)
|
||
LP SOLN: 1167185.73
|
||
SOURCE: Harvey M. Wagner
|
||
John W. Gregory (Cray Research)
|
||
E. Andrew Boyd (Rice University)
|
||
APPLICATION: airline model
|
||
COMMENTS: no integer variables are binary
|
||
@end example
|
||
|
||
@example
|
||
%
|
||
% from file: library('clpqr/examples/mip')
|
||
%
|
||
example(flugpl, Obj, Vs, Ints, []) :-
|
||
Vs = [ Anm1,Anm2,Anm3,Anm4,Anm5,Anm6,
|
||
Stm1,Stm2,Stm3,Stm4,Stm5,Stm6,
|
||
UE1,UE2,UE3,UE4,UE5,UE6],
|
||
Ints = [Stm6, Stm5, Stm4, Stm3, Stm2,
|
||
Anm6, Anm5, Anm4, Anm3, Anm2, Anm1],
|
||
|
||
Obj = 2700*Stm1 + 1500*Anm1 + 30*UE1
|
||
+ 2700*Stm2 + 1500*Anm2 + 30*UE2
|
||
+ 2700*Stm3 + 1500*Anm3 + 30*UE3
|
||
+ 2700*Stm4 + 1500*Anm4 + 30*UE4
|
||
+ 2700*Stm5 + 1500*Anm5 + 30*UE5
|
||
+ 2700*Stm6 + 1500*Anm6 + 30*UE6,
|
||
|
||
allpos(Vs),
|
||
@{ Stm1 = 60, 0.9*Stm1 +1*Anm1 -1*Stm2 = 0,
|
||
0.9*Stm2 +1*Anm2 -1*Stm3 = 0, 0.9*Stm3 +1*Anm3 -1*Stm4 = 0,
|
||
0.9*Stm4 +1*Anm4 -1*Stm5 = 0, 0.9*Stm5 +1*Anm5 -1*Stm6 = 0,
|
||
150*Stm1 -100*Anm1 +1*UE1 >= 8000,
|
||
150*Stm2 -100*Anm2 +1*UE2 >= 9000,
|
||
150*Stm3 -100*Anm3 +1*UE3 >= 8000,
|
||
150*Stm4 -100*Anm4 +1*UE4 >= 10000,
|
||
150*Stm5 -100*Anm5 +1*UE5 >= 9000,
|
||
150*Stm6 -100*Anm6 +1*UE6 >= 12000,
|
||
-20*Stm1 +1*UE1 =< 0, -20*Stm2 +1*UE2 =< 0, -20*Stm3 +1*UE3 =< 0,
|
||
-20*Stm4 +1*UE4 =< 0, -20*Stm5 +1*UE5 =< 0, -20*Stm6 +1*UE6 =< 0,
|
||
Anm1 =< 18, 57 =< Stm2, Stm2 =< 75, Anm2 =< 18,
|
||
57 =< Stm3, Stm3 =< 75, Anm3 =< 18, 57 =< Stm4,
|
||
Stm4 =< 75, Anm4 =< 18, 57 =< Stm5, Stm5 =< 75,
|
||
Anm5 =< 18, 57 =< Stm6, Stm6 =< 75, Anm6 =< 18
|
||
@}.
|
||
|
||
allpos([]).
|
||
allpos([X|Xs]) :- @{X >= 0@}, allpos(Xs).
|
||
@end example
|
||
|
||
We can first check whether the relaxed problem has indeed the quoted
|
||
infimum:
|
||
|
||
@example
|
||
clp(r) ?- example(flugpl, Obj, _, _, _), inf(Obj, Inf).
|
||
|
||
Inf = 1167185.7255923203
|
||
@end example
|
||
|
||
Computing the infimum under the additional constraints that @var{Stm6},
|
||
@var{Stm5}, @var{Stm4}, @var{Stm3}, @var{Stm2}, @var{Anm6}, @var{Anm5},
|
||
@var{Anm4}, @var{Anm3}, @var{Anm2}, @var{Anm1} assume integer values at
|
||
the infimum is computationally harder, but the query does not change
|
||
much:
|
||
|
||
@example
|
||
clp(r) ?- example(flugpl, Obj, _, Ints, _), bb_inf(Ints, Obj, Inf).
|
||
|
||
Inf = 1201500.0000000005
|
||
@end example
|
||
|
||
@section Implementation Architecture
|
||
@node Implementation Architecture, Fragments and Bits,A Mixed Integer Linear Optimization Example, CLPQR
|
||
|
||
The system consists roughly of the following components:
|
||
@itemize @bullet
|
||
@item A polynomial normal form expression simplification mechanism.
|
||
@item A solver for linear equations [Holzbaur 92].
|
||
@item A simplex algorithm to decide linear inequalities [Holzbaur 94].
|
||
@end itemize
|
||
|
||
@section Fragments and Bits
|
||
@node Fragments and Bits, CLPQR Bugs,Implementation Architecture, CLPQR
|
||
|
||
The internal data structure for rational numbers is
|
||
@code{rat(@var{Num},@var{Den})}. @var{Den} is always positive, i.e. the
|
||
sign of the rational number is the sign of @var{Num}. Further, @var{Num}
|
||
and @var{Den} are relative prime. Note that integer @var{N} looks like
|
||
@code{rat(@var{N},1)} in this representation. You can control printing
|
||
of terms with @code{portray/1}.
|
||
|
||
Partial Evaluation
|
||
|
||
Once one has a working solver, it is obvious and attractive to run the
|
||
constraints in a clause definition at read time or compile time and
|
||
proceed with the answer constraints in place of the original
|
||
constraints. This gets you constant folding and in fact the full
|
||
algebraic power of the solver applied to the avoidance of computations
|
||
at runtime. The mechanism to realize this idea is to use
|
||
@code{call_residue/2} for the expansion of @code{@{@}/1}.
|
||
|
||
Asserting with Constraints
|
||
|
||
If you use the dynamic data base, the clauses you assert might have
|
||
constraints on the variables occurring in the clause. This should work
|
||
as follows:
|
||
|
||
@example
|
||
clp(r) ?- @{A < 10@}, assert(p(A)).
|
||
|
||
@{A < 10.0@}
|
||
yes
|
||
|
||
clp(r) ?- p(X).
|
||
|
||
@{X<10.0@}
|
||
@end example
|
||
|
||
YAP currently does not implement this feature.
|
||
|
||
@node CLPQR Bugs, CLPQR References, Fragments and Bits, CLPQR
|
||
@section Bugs
|
||
|
||
@itemize @bullet
|
||
@item The fuzzy comparison of floats is the source for all sorts of
|
||
weirdness. If a result in R surprises you, try to run the program in Q
|
||
before you send me a bug report.
|
||
|
||
@item The projector for floundered nonlinear relations keeps too many
|
||
variables. Its output is rather unreadable.
|
||
|
||
@item Disequations are not projected properly.
|
||
|
||
@item This list is probably incomplete.
|
||
@end itemize
|
||
|
||
Please send bug reports to @code{christian@@ai.univie.ac.at}.
|
||
|
||
@node CLPQR References, ,CLPQR Bugs, CLPQR
|
||
@section References
|
||
|
||
[Colmerauer 90] Colmerauer A.: An Introduction to Prolog III,
|
||
Communications of the ACM, 33(7), 69-90, 1990.
|
||
|
||
[Heintze et al. 87] Heintze N., Jaffar J., Michaylov S., Stuckey P., Yap
|
||
R.: The CLP(R) Programmers Manual, Monash University, Clayton, Victoria,
|
||
Australia, Department of Computer Science, 1987.
|
||
|
||
[Holzbaur 92] Holzbaur C.: A High-Level Approach to the Realization of
|
||
CLP Languages, in Proceedings of the JICSLP92 Post-Conference Workshop
|
||
on Constraint Logic Programming Systems, Washington D.C., 1992.
|
||
|
||
[Holzbaur 92] Holzbaur C.: Metastructures vs. Attributed Variables in
|
||
the Context of Extensible Unification, in Bruynooghe M. & Wirsing
|
||
M.(eds.), Programming Language Implementation and Logic Programming,
|
||
Springer, LNCS 631, pp.260- 268, 1992.
|
||
|
||
[Holzbaur 94] Holzbaur C.: A Specialized, Incremental Solved Form
|
||
Algorithm for Systems of Linear Inequalities, Austrian Research
|
||
Institute for Artificial Intelligence, Vienna, TR-94-07, 1994.
|
||
|
||
[Jaffar & Michaylov 87] Jaffar J., Michaylov S.: Methodology and
|
||
Implementation of a CLP System, in Lassez J.L.(ed.), Logic Programming -
|
||
Proceedings of the 4th International Conference - Volume 1, MIT Press,
|
||
Cambridge, MA, 1987.
|
||
|
||
@node CHR, Logtalk, CLPQR, Top
|
||
@chapter Constraint Handling Rules
|
||
|
||
@menu
|
||
* CHR Copyright::
|
||
* CHR Introduction::
|
||
* CHR Introductory Examples::
|
||
* CHR Library::
|
||
* CHR Debugging::
|
||
* CHR Programming Hints::
|
||
* CHR Constraint Handlers::
|
||
* CHR Backward Compatibility::
|
||
@end menu
|
||
|
||
@node CHR Copyright, CHR Introduction, CHR, CHR
|
||
@unnumberedsec Copyright
|
||
|
||
This chapter is Copyright @copyright{} 1996-98 LMU
|
||
|
||
LMU (Ludwig-Maximilians-University)@*
|
||
Munich, Germany
|
||
|
||
Permission is granted to make and distribute verbatim copies of
|
||
this chapter provided the copyright notice and this permission notice
|
||
are preserved on all copies.
|
||
|
||
Permission is granted to copy and distribute modified versions of this
|
||
chapter under the conditions for verbatim copying, provided that the entire
|
||
resulting derived work is distributed under the terms of a permission
|
||
notice identical to this one.
|
||
|
||
Permission is granted to copy and distribute translations of this chapter
|
||
into another language, under the above conditions for modified versions,
|
||
except that this permission notice may be stated in a translation approved
|
||
by LMU.
|
||
|
||
@node CHR Introduction, CHR Introductory Examples, CHR Copyright, CHR
|
||
@comment node-name, next, previous, up
|
||
@section Introduction
|
||
|
||
Experience from real-life applications using constraint-based
|
||
programming has shown that typically, one is confronted with a
|
||
heterogeneous mix of different types of constraints. To be able to
|
||
express constraints as they appear in the application and to write and
|
||
combine constraint systems, a special purpose language for writing
|
||
constraint systems called @dfn{constraint handling rules} (CHR) was
|
||
developed. CHR have been used to encode a wide range of constraint
|
||
handlers (solvers), including new domains such as terminological and
|
||
temporal reasoning. Several CHR libraries exist in declarative
|
||
languages such as Prolog and LISP, worldwide more than 20 projects use
|
||
CHR. You can find more information about CHR at URL:
|
||
@code{http://www.pst.informatik.uni-muenchen.de/personen/fruehwir/chr-intro.html}
|
||
|
||
The high-level CHR are an excellent tool for rapid prototyping
|
||
and implementation of constraint handlers. The usual abstract formalism
|
||
to describe a constraint system, i.e.@: inference rules, rewrite rules,
|
||
sequents, formulas expressing axioms and theorems, can be written as
|
||
CHR in a straightforward way. Starting from this executable
|
||
specification, the rules can be refined and adapted to the specifics of
|
||
the application.
|
||
|
||
The CHR library includes a compiler, which translates
|
||
CHR programs into Prolog programs on the fly, and a runtime system,
|
||
which includes a stepper for debugging. Many constraint
|
||
handlers are provided in the example directory of the library.
|
||
|
||
CHR are essentially a committed-choice language consisting of guarded
|
||
rules that rewrite constraints into simpler ones until they are solved.
|
||
CHR define both @dfn{simplification} of and @dfn{propagation} over
|
||
constraints. Simplification replaces constraints by
|
||
simpler constraints while preserving logical equivalence (e.g.@:
|
||
@code{X>Y,Y>X <=> fail}). Propagation adds new constraints which are
|
||
logically redundant but may cause further simplification (e.g.@:
|
||
@code{X>Y,Y>Z ==> X>Z}). Repeatedly applying CHR incrementally simplifies
|
||
and finally solves constraints (e.g.@: @code{A>B,B>C,C>A}
|
||
leads to @code{fail}.
|
||
|
||
With multiple heads and propagation rules, CHR provide two features
|
||
which are essential for non-trivial constraint handling. The
|
||
declarative reading of CHR as formulas of first order logic allows
|
||
one to reason about their correctness. On the other hand, regarding
|
||
CHR as a rewrite system on logical formulas allows one to reason
|
||
about their termination and confluence.
|
||
|
||
In case the implementation of CHR disagrees with your expectations
|
||
based on this chapter, drop a line to the current maintainer:
|
||
@code{christian@@ai.univie.ac.at} (Christian Holzbaur).
|
||
|
||
@node CHR Introductory Examples, CHR Library, CHR Introduction, CHR
|
||
@comment node-name, next, previous, up
|
||
@section Introductory Examples
|
||
|
||
We define a CHR constraint for less-than-or-equal, @code{leq}, that can
|
||
handle variable arguments. This handler can be found in the library as
|
||
the file @code{leq.pl}. (The code works regardless of options switched
|
||
on or off.)
|
||
@example
|
||
:- use_module(library(chr)).
|
||
|
||
handler leq.
|
||
constraints leq/2.
|
||
:- op(500, xfx, leq).
|
||
|
||
reflexivity @@ X leq Y <=> X=Y | true.
|
||
antisymmetry @@ X leq Y , Y leq X <=> X=Y.
|
||
idempotence @@ X leq Y \ X leq Y <=> true.
|
||
transitivity @@ X leq Y , Y leq Z ==> X leq Z.
|
||
@end example
|
||
|
||
The CHR specify how @code{leq} simplifies and propagates as a
|
||
constraint. They implement reflexivity, idempotence, antisymmetry and
|
||
transitivity in a straightforward way. CHR @code{reflexivity} states
|
||
that @code{X leq Y} simplifies to @code{true}, provided it is the case that
|
||
@code{X=Y}. This test forms the (optional) guard of a rule, a
|
||
precondition on the applicability of the rule. Hence, whenever we see a
|
||
constraint of the form @code{A leq A} we can simplify it to @code{true}.
|
||
|
||
The rule @code{antisymmetry} means that if we find @code{X leq Y} as well as
|
||
@code{Y leq X} in the constraint store, we can replace it by the
|
||
logically equivalent @code{X=Y}. Note the different use of @code{X=Y} in
|
||
the two rules: In the @code{reflexivity} rule the equality is a
|
||
precondition (test) on the rule, while in the @code{antisymmetry} rule
|
||
it is enforced when the rule fires. (The reflexivity rule could also have
|
||
been written as @code{reflexivity @ X leq X <=> true}.)
|
||
|
||
The rules @code{reflexivity} and @code{antisymmetry} are
|
||
@dfn{simplification CHR}. In such rules, the constraints found are
|
||
removed when the rule applies and fires. The rule @code{idempotence} is
|
||
a @dfn{simpagation CHR}, only the constraints right of @code{'\'} will
|
||
be removed. The rule says that if we find @code{X leq Y} and another @code{X
|
||
leq Y} in the constraint store, we can remove one.
|
||
|
||
Finally, the rule @code{transitivity} states that the conjunction
|
||
@code{X leq Y, Y leq Z} implies @code{X leq Z}. Operationally, we add
|
||
@code{X leq Z} as (redundant) constraint, without removing the
|
||
constraints @code{X leq Y, Y leq Z}. This kind of CHR is called
|
||
@dfn{propagation CHR}.
|
||
|
||
Propagation CHR are useful, as the query @code{A leq B,C leq A,B leq C}
|
||
illustrates: The first two constraints cause CHR @code{transitivity} to
|
||
fire and add @code{C leq B} to the query. This new constraint together
|
||
with @code{B leq C} matches the head of CHR @code{antisymmetry}, @code{X
|
||
leq Y, Y leq X}. So the two constraints are replaced by
|
||
@code{B=C}. Since @code{B=C} makes @code{B} and @code{C} equivalent, CHR
|
||
@code{antisymmetry} applies to the constraints @code{A leq B, C leq A},
|
||
resulting in @code{A=B}. The query contains no more CHR constraints, the
|
||
simplification stops. The constraint handler we built has solved
|
||
@code{A leq B, C leq A, B leq C} and produced the answer @code{A=B,
|
||
B=C}:
|
||
|
||
@example
|
||
A leq B,C leq A,B leq C.
|
||
% C leq A, A leq B propagates C leq B by transitivity.
|
||
% C leq B, B leq C simplifies to B=C by antisymmetry.
|
||
% A leq B, C leq A simplifies to A=B by antisymmetry since B=C.
|
||
A=B,B=C.
|
||
@end example
|
||
|
||
Note that multiple heads of rules are essential in solving these
|
||
constraints. Also note that this handler implements a (partial) order
|
||
constraint over any constraint domain, this generality is only possible
|
||
with CHR.
|
||
|
||
As another example, we can implement the sieve of Eratosthenes to
|
||
compute primes simply as (for variations see the handler
|
||
@file{primes.pl}):
|
||
|
||
@example
|
||
:- use_module(library(chr)).
|
||
handler eratosthenes.
|
||
constraints primes/1,prime/1.
|
||
|
||
primes(1) <=> true.
|
||
primes(N) <=> N>1 | M is N-1,prime(N),primes(M). % generate candidates
|
||
|
||
absorb(J) @@ prime(I) \ prime(J) <=> J mod I =:= 0 | true.
|
||
@end example
|
||
|
||
The constraint @code{primes(N)} generates candidates for prime numbers,
|
||
@code{prime(M)}, where @code{M} is between @code{1} and @code{N}.
|
||
The candidates react with each other such that each
|
||
number absorbs multiples of itself. In the end, only prime numbers remain.
|
||
|
||
Looking at the two rules defining @code{primes/1}, note that head
|
||
matching is used in CHR, so the first rule will only apply to
|
||
@code{primes(1)}. The test @code{N>1} is a guard (precondition) on the
|
||
second rule. A call with a free variable, like @code{primes(X)},
|
||
will delay (suspend). The third, multi-headed rule @code{absorb(J)}
|
||
reads as follows:
|
||
If there is a constraint @code{prime(I)} and some other constraint
|
||
@code{prime(J)} such that @code{J mod I =:= 0} holds, i.e.@: @code{J} is a
|
||
multiple of @code{I}, then keep @code{prime(I)} but remove
|
||
@code{prime(J)} and execute the body of the rule,
|
||
@code{true}.
|
||
|
||
@node CHR Library, CHR Debugging, CHR Introductory Examples, CHR
|
||
@section CHR Library
|
||
|
||
CHR extend the Prolog syntax by a few constructs introduced in the next
|
||
sections. Technically, the extension is achieved through the
|
||
@code{user:term_expansion/2} mechanism. A file that contains a constraint
|
||
handler may also contain arbitrary Prolog code. Constraint handling
|
||
rules can be scattered across a file. Declarations and options should
|
||
precede rules. There can only be at most one constraint handler per module.
|
||
|
||
@menu
|
||
* CHR Loading the Library::
|
||
* CHR Declarations::
|
||
* CHR Syntax::
|
||
* How CHR work::
|
||
* CHR Pragmas::
|
||
* CHR Options::
|
||
* CHR Built-In Predicates::
|
||
* CHR Consulting and Compiling::
|
||
* CHR Compiler-generated Predicates::
|
||
* CHR Operator Declarations::
|
||
* CHR Exceptions::
|
||
@end menu
|
||
|
||
@node CHR Loading the Library, CHR Declarations, CHR Library, CHR Library
|
||
@subsection Loading the Library
|
||
|
||
Before you can load or compile any file containing a
|
||
constraint handler (solver) written in CHR, the @code{chr} library
|
||
module has to be imported:
|
||
@example
|
||
| ?- use_module(library(chr)).
|
||
@end example
|
||
It is recommended to include the corresponding directive at the
|
||
start of your files containing handlers:
|
||
@example
|
||
:- use_module(library(chr)).
|
||
@end example
|
||
|
||
@node CHR Declarations, CHR Syntax, CHR Loading the Library, CHR Library
|
||
@subsection Declarations
|
||
|
||
Declarations in files containing CHR affect the compilation and thus
|
||
the behavior of the rules at runtime.
|
||
|
||
The mandatory handler declaration precedes any other CHR specific
|
||
code.
|
||
Example:
|
||
@example
|
||
handler minmax.
|
||
@end example
|
||
A handler name must be a valid Prolog @code{atom}.
|
||
Per module, only one constraint handler can be defined.
|
||
|
||
The constraints must be declared before they are used by rules.
|
||
With this mandatory declaration one lists the constraints
|
||
the rules will later talk about. The declaration can be used more
|
||
than once per handler.
|
||
Example:
|
||
@example
|
||
constraints leq/2, minimum/3, maximum/3.
|
||
@end example
|
||
|
||
|
||
The following
|
||
optional declaration allows for conditional rule compilation.
|
||
Only the rules mentioned get compiled. Rules are referred to by their
|
||
names (@pxref{CHR Syntax}). The latest occurrence takes precedence if used
|
||
more than once per handler. Although it can be put anywhere in the handler
|
||
file, it makes sense, as with other declarations, to use it early.
|
||
Example:
|
||
@example
|
||
rules antisymmetry, transitivity.
|
||
@end example
|
||
|
||
To simplify the handling of operator declarations, in particular
|
||
during @code{fcompile/1}, @code{operator/3} declarations with the
|
||
same denotation as @code{op/3}, but
|
||
taking effect during compilation and loading, are helpful.
|
||
Example:
|
||
@example
|
||
operator(700, xfx, ::).
|
||
operator(600, xfx, :).
|
||
@end example
|
||
|
||
@node CHR Syntax, How CHR work, CHR Declarations, CHR Library
|
||
@subsection Constraint Handling Rules, Syntax
|
||
|
||
A constraint handling rule has one or more heads, an optional guard, a
|
||
body and an optional name. A @dfn{Head} is a @dfn{Constraint}. A
|
||
constraint is a callable Prolog term,
|
||
whose functor is a declared constraint.
|
||
The @dfn{Guard} is a Prolog goal.
|
||
The @dfn{Body} of a rule is a Prolog
|
||
goal (including constraints).
|
||
A rule can be named with
|
||
a @dfn{Name} which can be any Prolog term (including variables
|
||
from the rule).
|
||
|
||
There are three kinds of constraint handling rules:
|
||
@example
|
||
Rule --> [Name @@]
|
||
(Simplification | Propagation | Simpagation)
|
||
[pragma Pragma].
|
||
|
||
Simplification --> Heads <=> [Guard '|'] Body
|
||
Propagation --> Heads ==> [Guard '|'] Body
|
||
Simpagation --> Heads \ Heads <=> [Guard '|'] Body
|
||
|
||
Heads --> Head | Head, Heads
|
||
Head --> Constraint | Constraint # Id
|
||
Constraint --> a callable term declared as constraint
|
||
Id --> a unique variable
|
||
|
||
Guard --> Ask | Ask & Tell
|
||
Ask --> Goal
|
||
Tell --> Goal
|
||
Goal --> a callable term,
|
||
including conjunction and disjunction etc.
|
||
|
||
Body --> Goal
|
||
|
||
Pragma --> a conjunction of terms usually referring to
|
||
one or more heads identified via #/2
|
||
@end example
|
||
|
||
The symbol @samp{|} separates the guard (if present) from the body of a
|
||
rule. Since @samp{|} is read as @samp{;} (disjunction) by the
|
||
reader, care has to be taken when using disjunction in the guard
|
||
or body of the rule. The top level disjunction will always be
|
||
interpreted as guard-body separator @samp{|}, so proper bracketing has
|
||
to be used, e.g.@: @code{a <=> (b;c) | (d;e)} instead of @code{a <=> b;c |
|
||
d;e} and @code{a <=> true | (d;e)} instead of @code{a <=> (d;e)}.
|
||
|
||
In simpagation rules, @samp{\} separates the heads of the rule into two parts.
|
||
|
||
Individual head constraints may be tagged with variables via
|
||
@samp{#}, which may be used as identifiers in pragma declarations, for
|
||
example. Constraint identifiers must be distinct variables, not
|
||
occurring elsewhere in the heads.
|
||
|
||
Guards test the applicability of a rule. Guards come in two
|
||
parts, tell and ask, separated by @samp{&}.
|
||
If the @samp{&} operator is not present, the whole guard is
|
||
assumed to be of the ask type.
|
||
|
||
Declaratively, a rule relates heads and body @dfn{provided the guard is
|
||
true}. A simplification rule means that the heads are true if and only
|
||
if the body is true. A propagation rule means that the body is true if
|
||
the heads are true. A simpagation rule combines a simplification and a
|
||
propagation rule. The rule @code{Heads1 \ Heads2 <=> Body} is
|
||
equivalent to the simplification rule @code{Heads1, Heads2 <=> Heads1,
|
||
Body}. However, the simpagation rule is more compact to write, more
|
||
efficient to execute and has better termination behavior than the
|
||
corresponding simplification rule, since the constraints comprising
|
||
@code{Heads1} will not be removed and inserted again.
|
||
|
||
@node How CHR work, CHR Pragmas, CHR Syntax, CHR Library
|
||
@subsection How CHR work
|
||
|
||
Each CHR constraint is associated with all rules in whose heads it
|
||
occurs by the CHR compiler. Every time a CHR constraint is executed
|
||
(called) or woken and reconsidered, it checks itself the applicability
|
||
of its associated CHR by @dfn{trying} each CHR. By default, the rules
|
||
are tried in textual order, i.e.@: in the order they occur in the defining
|
||
file. To try a CHR, one of its heads is matched against the constraint.
|
||
Matching succeeds if the constraint is an instance of the head.
|
||
If a CHR has more than one head, the constraint store is searched for
|
||
@dfn{partner} constraints that match the other heads. Heads are tried
|
||
from left to right, except that in simpagation rules, the heads to be
|
||
removed are tried before the head constraints to be kept (this is done
|
||
for efficiency reasons). If the matching succeeds, the guard is
|
||
executed. Otherwise the next rule is tried.
|
||
|
||
The guard either succeeds or fails. A guard succeeds if the execution
|
||
of its Ask and Tell parts succeeds and in the ask part no variable that
|
||
occurs also in the heads was touched or the cause of an instantiation
|
||
error. The ask guard will fail otherwise. A variable is @dfn{touched}
|
||
if it is unified with a term (including other variables from other
|
||
constraints) different from itself. Tell guards, on the contrary, are
|
||
trusted and not checked for that property. If the guard succeeds, the
|
||
rule applies. Otherwise the next rule is tried.
|
||
|
||
If the firing CHR is a simplification rule, the matched constraints are
|
||
removed from the store and the body of the CHR is executed. Similarly
|
||
for a firing simpagation rule, except that the constraints that matched
|
||
the heads preceding @samp{\} are kept. If the firing CHR is a
|
||
propagation rule the body of the CHR is executed without removing any
|
||
constraints. It is remembered that the propagation rule fired, so it
|
||
will not fire again with the same constraints if the constraint is woken
|
||
and reconsidered. If the currently active constraint has not been
|
||
removed, the next rule is tried.
|
||
|
||
If the current constraint has not been removed and all rules have been
|
||
tried, it delays until a variable occurring in the constraint is
|
||
touched. Delaying means that the constraint is inserted into the
|
||
constraint store. When a constraint is woken, all its rules are tried
|
||
again. (This process can be watched and inspected with the CHR debugger,
|
||
see below.)
|
||
|
||
|
||
@node CHR Pragmas, CHR Options, How CHR work, CHR Library
|
||
@subsection Pragmas
|
||
|
||
Pragmas are annotations to rules and constraints that enable the
|
||
compiler to generate more specific, more optimized code. A pragma
|
||
can be a conjunction of the following terms:
|
||
|
||
@table @code
|
||
|
||
@item already_in_heads
|
||
The intention of simplification and simpagation rules is often
|
||
to combine the heads into a stronger version of one of them.
|
||
Depending on the strength of the guard, the new constraint may
|
||
be identical to one of the heads to removed by the rule.
|
||
This removal followed by addition is inefficient and may even cause
|
||
termination problems. If the pragma is used, this situation is
|
||
detected and the corresponding problems are avoided.
|
||
The pragma applies to all constraints removed by the rule.
|
||
|
||
@item already_in_head(Id)
|
||
Shares the intention of the previous pragma, but affects only
|
||
the constraint indicated via @var{Id}. Note that one can use more
|
||
than one pragma per rule.
|
||
|
||
@item passive(Id)
|
||
No code will be generated for the specified constraint in the particular
|
||
head position. This means that the constraint will not see the rule, it
|
||
is passive in that rule. This changes the behavior of the CHR system,
|
||
because normally, a rule can be entered starting from each head constraint.
|
||
Usually this pragma will improve the efficiency of the
|
||
constraint handler, but care has to be taken in order not to lose
|
||
completeness.
|
||
|
||
For example, in the handler @code{leq}, any pair of constraints, say
|
||
@code{A leq B, B leq A}, that matches the head @code{X leq Y , Y leq X}
|
||
of the @code{antisymmetry} rule, will also match it when the constraints
|
||
are exchanged, @code{B leq A, A leq B}. Therefore it is enough if a
|
||
currently active constraint enters this rule in the first head only,
|
||
the second head can be declared to be passive. Similarly for the
|
||
@code{idempotence} rule. For this rule, it is more efficient to declare
|
||
the first head passive, so that the currently active constraint will be
|
||
removed when the rule fires (instead of removing the older constraint
|
||
and redoing all the propagation with the currently active constraint).
|
||
Note that the compiler itself detects the symmetry of the two head
|
||
constraints in the simplification rule @code{antisymmetry}, thus it is
|
||
automatically declared passive and the compiler outputs @code{CHR
|
||
eliminated code for head 2 in antisymmetry}.
|
||
@example
|
||
antisymmetry @ X leq Y, Y leq X # Id <=> X=Y
|
||
pragma passive(Id).
|
||
idempotence @ X leq Y # Id \ X leq Y <=> true
|
||
pragma passive(Id).
|
||
transitivity @ X leq Y # Id, Y leq Z ==> X leq Z
|
||
pragma passive(Id).
|
||
@end example
|
||
Declaring the first head of rule @code{transitivity} passive changes the
|
||
behavior of the handler. It will propagate less depending on the order in
|
||
which the constraints arrive:
|
||
@example
|
||
?- X leq Y, Y leq Z.
|
||
X leq Y,
|
||
Y leq Z,
|
||
X leq Z ?
|
||
|
||
?- Y leq Z, X leq Y.
|
||
Y leq Z,
|
||
X leq Y ?
|
||
|
||
?- Y leq Z, X leq Y, Z leq X.
|
||
Y = X,
|
||
Z = X ?
|
||
@end example
|
||
The last query shows that the handler is still complete in the sense
|
||
that all circular chains of leq-relations are collapsed into equalities.
|
||
|
||
@end table
|
||
|
||
@node CHR Options, CHR Built-In Predicates, CHR Pragmas, CHR Library
|
||
@subsection Options
|
||
|
||
Options parametrise the rule compilation process.
|
||
Thus they should precede the rule definitions. Example:
|
||
@example
|
||
option(check_guard_bindings, off).
|
||
@end example
|
||
|
||
The format below lists the names of the recognized options together with
|
||
the acceptable values. The first entry in the lists is the default
|
||
value.
|
||
|
||
@table @code
|
||
|
||
@item option(debug_compile, [off,on]).
|
||
Instruments the generated code such that the execution
|
||
of the rules may be traced (@pxref{CHR Debugging}).
|
||
|
||
@item option(check_guard_bindings, [on,off]).
|
||
Per default, for guards of type ask the CHR runtime system makes sure
|
||
that no variables are touched or the cause of an instantiation
|
||
error. These checks may be turned off with this option, i.e.@: all guards
|
||
are treated as if they were of the tell variety. The option was
|
||
kept for backward compatibility. Tell and ask guards offer better
|
||
granularity.
|
||
|
||
@item option(already_in_store, [off,on]).
|
||
If this option is on, the CHR runtime system checks for the presence of
|
||
an identical constraint upon the insertion into the store. If present,
|
||
the attempted insertion has no effect. Since checking for duplicates for
|
||
all constraints costs, duplicate removal specific to individual
|
||
constraints, using a few simpagation rules of the following form instead,
|
||
may be a better solution.
|
||
@example
|
||
Constraint \ Constraint <=> true.
|
||
@end example
|
||
|
||
@item option(already_in_heads, [off,on]).
|
||
The intention of simplification and simpagation rules is often
|
||
to combine the heads into a stronger version of one of them.
|
||
Depending on the strength of the guard, the new constraint may
|
||
be identical to one of the heads removed by the rule.
|
||
This removal followed by addition is inefficient and may even cause
|
||
termination problems. If the option is enabled, this situation is
|
||
detected and the corresponding problems are avoided.
|
||
This option applies to all constraints and is provided mainly
|
||
for backward compatibility. Better grained control can be achieved
|
||
with corresponding pragmas. (@pxref{CHR Pragmas}).
|
||
|
||
@end table
|
||
|
||
The remaining options are meant for CHR implementors only:
|
||
@table @code
|
||
@item option(flatten, [on,off]).
|
||
@item option(rule_ordering, [canonical,heuristic]).
|
||
@item option(simpagation_scheme, [single,multi]).
|
||
@item option(revive_scheme, [new,old]).
|
||
@item option(dead_code_elimination, [on,off]).
|
||
@end table
|
||
|
||
@node CHR Built-In Predicates, CHR Consulting and Compiling, CHR Options, CHR Library
|
||
@subsection Built-In Predicates
|
||
|
||
This table lists the predicates made available by the CHR library. They
|
||
are meant for advanced users, who want to tailor the CHR system
|
||
towards their specific needs.
|
||
@table @code
|
||
@item current_handler(?Handler, ?Module)
|
||
@findex current_handler/2
|
||
Nondeterministically enumerates the defined handlers
|
||
with the module they are defined in.
|
||
|
||
@item current_constraint(?Handler, ?Constraint)
|
||
@findex current_constraint/2
|
||
Nondeterministically enumerates the defined constraints
|
||
in the form @var{Functor/Arity} and the handlers they are
|
||
defined in.
|
||
|
||
@item insert_constraint(+Constraint, -Id)
|
||
@findex insert_constraint/2
|
||
Inserts @var{Constraint} into the constraint store
|
||
without executing any rules. The constraint will be woken and reconsidered
|
||
when one of the variables in @var{Constraint} is touched. @var{Id} is
|
||
unified with an internal object representing the constraint.
|
||
This predicate only gets defined when a handler and constraints are
|
||
declared (@pxref{CHR Declarations}).
|
||
|
||
@item insert_constraint(+Constraint, -Id, ?Term)
|
||
@findex insert_constraint/3
|
||
Inserts @var{Constraint} into the constraint store without executing
|
||
any rules. The constraint will be woken and reconsidered when one of the
|
||
variables in @var{Term} is touched. @var{Id} is
|
||
unified with an internal object representing the constraint.
|
||
This predicate only gets defined when a handler and constraints are
|
||
declared (@pxref{CHR Declarations}).
|
||
|
||
@item find_constraint(?Pattern, -Id)
|
||
@findex find_constraint/2
|
||
Nondeterministically enumerates constraints from the constraint
|
||
store that match @var{Pattern}, i.e.@: which are instances of
|
||
@var{Pattern}. @var{Id} is
|
||
unified with an internal object representing the constraint.
|
||
|
||
@item find_constraint(-Var, ?Pattern, -Id)
|
||
@findex find_constraint/3
|
||
Nondeterministically enumerates constraints from the constraint
|
||
store that delay on @var{Var} and match @var{Pattern},
|
||
i.e.@: which are instances of
|
||
@var{Pattern}. The identifier @var{Id} can be used to
|
||
refer to the constraint later, e.g.@: for removal.
|
||
|
||
@item findall_constraints(?Pattern, ?List)
|
||
@findex findall_constraints/2
|
||
Unifies @var{List} with a list of @code{Constraint # Id} pairs
|
||
from the constraint store that match @var{Pattern}.
|
||
|
||
@item findall_constraints(-Var, ?Pattern, ?List)
|
||
@findex findall_constraints/3
|
||
Unifies @var{List} with a list of @code{Constraint # Id} pairs
|
||
from the constraint store that delay on @var{Var} and
|
||
match @var{Pattern}.
|
||
|
||
@item remove_constraint(+Id)
|
||
@findex remove_constraint/1
|
||
Removes the constraint @var{Id}, obtained with one of the previous predicates,
|
||
from the constraint store.
|
||
|
||
@item unconstrained(?Var)
|
||
@findex unconstrained/1
|
||
Succeeds if no CHR constraint delays on @var{Var}. Defined as:
|
||
@example
|
||
unconstrained(X) :-
|
||
find_constraint(X, _, _), !, fail.
|
||
unconstrained(_).
|
||
@end example
|
||
|
||
@item notify_constrained(?Var)
|
||
@findex notify_constrained/1
|
||
Leads to the reconsideration of the constraints associated with @var{Var}.
|
||
This mechanism allows solvers to communicate reductions on the set of
|
||
possible values of variables prior to making bindings.
|
||
@end table
|
||
|
||
@node CHR Consulting and Compiling, CHR Compiler-generated Predicates, CHR Built-In Predicates, CHR Library
|
||
@subsection Consulting and Compiling Constraint Handlers
|
||
|
||
The CHR compilation process has been made as transparent as possible.
|
||
The user deals with files containing CHR just as with files containing
|
||
ordinary Prolog predicates. Thus CHR may be consulted, compiled with
|
||
various compilation modes, and compiled to file.
|
||
|
||
@node CHR Compiler-generated Predicates, CHR Operator Declarations, CHR Consulting and Compiling, CHR Library
|
||
@subsection Compiler-generated Predicates
|
||
|
||
Besides predicates for the defined constraints,
|
||
the CHR compiler generates some support predicates in the
|
||
module containing the handler. To avoid naming conflicts,
|
||
the following predicates must not be defined or referred to
|
||
by user code in the same module:
|
||
@table @code
|
||
@item verify_attributes/3
|
||
@item attribute_goal/2
|
||
@item attach_increment/2
|
||
@item 'attach_F/A'/2
|
||
for every defined constraint F/A.
|
||
@item 'F/A_N_M_...'/Arity
|
||
for every defined constraint F/A. N,M is are integers, Arity > A.
|
||
@end table
|
||
|
||
For the prime number example that is:
|
||
@example
|
||
attach_increment/2
|
||
attach_prime/1/2
|
||
attach_primes/1/2
|
||
attribute_goal/2
|
||
goal_expansion/3
|
||
prime/1
|
||
prime/1_1/2
|
||
prime/1_1_0/3
|
||
prime/1_2/2
|
||
primes/1
|
||
primes/1_1/2
|
||
verify_attributes/3
|
||
@end example
|
||
|
||
If an author of a handler wants to avoid naming conflicts with the
|
||
code that uses the handler, it is easy to encapsulate the handler.
|
||
The module declaration below puts the handler into module @code{primes},
|
||
which exports only selected predicates - the constraints in our example.
|
||
@example
|
||
:- module(primes, [primes/1,prime/1]).
|
||
|
||
:- use_module(library(chr)).
|
||
|
||
handler eratosthenes.
|
||
constraints primes/1,prime/1.
|
||
...
|
||
@end example
|
||
|
||
@node CHR Operator Declarations, CHR Exceptions, CHR Compiler-generated Predicates, CHR Library
|
||
@subsection Operator Declarations
|
||
|
||
This table lists the operators as used by the CHR library:
|
||
@example
|
||
@group
|
||
:- op(1200, xfx, @@).
|
||
:- op(1190, xfx, pragma).
|
||
:- op(1180, xfx, [==>,<=>]).
|
||
:- op(1180, fy, chr_spy).
|
||
:- op(1180, fy, chr_nospy).
|
||
:- op(1150, fx, handler).
|
||
:- op(1150, fx, constraints).
|
||
:- op(1150, fx, rules).
|
||
:- op(1100, xfx, '|').
|
||
:- op(1100, xfx, \ ).
|
||
:- op(1050, xfx, &).
|
||
:- op( 500, yfx, #).
|
||
@end group
|
||
@end example
|
||
|
||
@node CHR Exceptions, , CHR Operator Declarations, CHR Library
|
||
@subsection Exceptions
|
||
|
||
The CHR runtime system reports instantiation and type errors for the predicates:
|
||
@table @code
|
||
@item find_constraint/2
|
||
@item findall_constraints/3
|
||
@item insert_constraint/2
|
||
@item remove_constraint/1
|
||
@item notify_constrained/1
|
||
@end table
|
||
|
||
The only other CHR specific runtime error is:
|
||
@table @code
|
||
@item @{CHR ERROR: registering <New>, module <Module> already hosts <Old>@}
|
||
An attempt to load a second handler New into module <Module> already
|
||
hosting handler <Old> was made.
|
||
@end table
|
||
|
||
The following exceptional conditions are detected by the CHR
|
||
compiler:
|
||
|
||
@table @code
|
||
@item @{CHR Compiler ERROR: syntax rule <N>: <Term>@}
|
||
If the N-th <Term> in the file being loaded violates the CHR syntax (@pxref{CHR Syntax}).
|
||
|
||
@item @{CHR Compiler ERROR: too many general heads in <Name>@}
|
||
Unspecific heads in definitions like
|
||
@code{C \ C <=> true}
|
||
must not be combined with other heads in rule <Name>.
|
||
|
||
@item @{CHR Compiler ERROR: bad pragma <Pragma> in <Name>@}
|
||
The pragma <Pragma> used in rule <Name> does not qualify. Currently this only happens if
|
||
<Pragma> is unbound.
|
||
|
||
@item @{CHR Compiler ERROR: found head <F/A> in <Name>, expected one of: <F/A list>@}
|
||
Rule <Name> has a head of given F/A which is not among the defined constraints.
|
||
|
||
@item @{CHR Compiler ERROR: head identifiers in <Name> are not unique variables@}
|
||
The identifiers to refer to individual constraints (heads) via @samp{#} in
|
||
rule <Name> do not meet the indicated requirements.
|
||
|
||
@item @{CHR Compiler ERROR: no handler defined@}
|
||
CHR specific language elements, declarations or rules for example, are
|
||
used before a handler was defined. This error is usually reported a couple
|
||
of times, i.e.@: as often as there are CHR forms in the file expecting the missing
|
||
definition.
|
||
|
||
@item @{CHR Compiler ERROR: compilation failed@}
|
||
Not your fault. Send us a bug report.
|
||
@end table
|
||
|
||
@node CHR Debugging, CHR Programming Hints, CHR Library, CHR
|
||
@section Debugging CHR Programs
|
||
|
||
Use @code{option(debug_compile,on)} preceding any rules
|
||
in the file containing the handler to enable CHR debugging.
|
||
The CHR debugging mechanism works by instrumenting the code
|
||
generated by the CHR compiler.
|
||
Basically, the CHR debugger works like the Prolog debugger.
|
||
The main differences are: there are extra ports specific to CHR,
|
||
and the CHR debugger provides no means for the user to change
|
||
the flow of control, i.e.@: there are currently no @var{retry} and @var{fail}
|
||
options available.
|
||
|
||
@menu
|
||
* CHR Control Flow Model::
|
||
* CHR Debugging Predicates::
|
||
* CHR Spy-points::
|
||
* CHR Debugging Messages::
|
||
* CHR Debugging Options::
|
||
@end menu
|
||
|
||
@node CHR Control Flow Model, CHR Debugging Predicates, CHR Debugging, CHR Debugging
|
||
@subsection Control Flow Model
|
||
@cindex CHR control flow model
|
||
|
||
The entities reflected by the CHR debugger are constraints
|
||
and rules. Constraints are treated like ordinary Prolog goals
|
||
with the usual ports: @code{[call,exit,redo,fail]}.
|
||
In addition, constraints may get inserted into or removed from the
|
||
constraint store (ports: @code{insert,remove}), and stored
|
||
constraints containing variables will be woken and reconsidered
|
||
(port: @code{wake}) when variables are touched.
|
||
|
||
The execution of a constraint consists of trying to apply the rules
|
||
mentioning the constraint in their heads. Two ports for rules reflect this
|
||
process: At a @code{try} port the active constraint matches one of the
|
||
heads of the rule, and matching constraints for the remaining heads of
|
||
the rule, if any, have been found as well. The transition from a
|
||
@code{try} port to an @code{apply} port takes place when the guard has
|
||
been successfully evaluated, i.e.@: when the rule commits. At the
|
||
@code{apply} port, the body of the rule is just about to be executed. The
|
||
body is a Prolog goal transparent to the CHR debugger. If the
|
||
rule body contains CHR constraints, the CHR debugger will track
|
||
them again. If the rules were consulted, the Prolog debugger can be
|
||
used to study the evaluations of the other predicates in the body.
|
||
|
||
@node CHR Debugging Predicates, CHR Spy-points, CHR Control Flow Model, CHR Debugging
|
||
@subsection CHR Debugging Predicates
|
||
@cindex CHR debugging predicates
|
||
|
||
The following predicates control the operation of the CHR debugger:
|
||
|
||
@table @code
|
||
@item chr_trace
|
||
@findex chr_trace/0
|
||
Switches the CHR debugger on and ensures that the
|
||
next time control enters a CHR port, a message will be produced and
|
||
you will be asked to interact. @refill
|
||
|
||
@noindent
|
||
At this point you have a number of options. @xref{CHR Debugging Options}. In
|
||
particular, you can just type @key{cr} (Return) to @dfn{creep} (or single-step)
|
||
into your program. You will
|
||
notice that the CHR debugger stops at many ports. If this is not
|
||
what you want, the predicate @code{chr_leash} gives full control over
|
||
the ports at which you are prompted. @refill
|
||
|
||
@item chr_debug
|
||
@findex chr_debug/0
|
||
Switches the CHR debugger on and ensures that the next time
|
||
control enters a CHR port with a spy-point set, a message will be produced
|
||
and you will be asked to interact. @refill
|
||
@refill
|
||
|
||
@item chr_nodebug
|
||
@findex chr_nodebug/0
|
||
Switches the CHR debugger off. If there are any spy-points set then they
|
||
will be kept. @refill
|
||
|
||
@item chr_notrace
|
||
@findex chr_notrace/0
|
||
Equivalent to @code{chr_nodebug}. @refill
|
||
|
||
@item chr_debugging
|
||
@findex chr_debugging/0
|
||
Prints onto the standard error stream information about the current
|
||
CHR debugging state. This will show: @refill
|
||
|
||
@enumerate
|
||
@item
|
||
Whether the CHR debugger is switched on.
|
||
@item
|
||
What spy-points have been set (see below).
|
||
@item
|
||
What mode of leashing is in force (see below).
|
||
@end enumerate
|
||
|
||
@item chr_leash(@var{+Mode})
|
||
@findex chr_leash/1
|
||
The leashing mode is set to @var{Mode}. It determines the CHR ports at
|
||
which you are to be prompted when you @dfn{creep} through your program.
|
||
At unleashed ports a tracing message is still output, but program
|
||
execution does not stop to allow user interaction. Note that the ports
|
||
of spy-points are always leashed (and cannot be unleashed). @var{Mode}
|
||
is a list containing none, one or more of the following port names:
|
||
@refill
|
||
|
||
@table @code
|
||
@item call
|
||
Prompt when a constraint is executed for the first time.
|
||
|
||
@item exit
|
||
Prompt when the constraint is successfully processed, i.e.@: the applicable
|
||
rules have applied.
|
||
|
||
@item redo
|
||
Prompt at subsequent exits generated by non-deterministic rule bodies.
|
||
|
||
@item fail
|
||
Prompt when a constraint fails.
|
||
|
||
@item wake
|
||
Prompt when a constraint from the constraint store is woken and
|
||
reconsidered because one of its variables has been touched.
|
||
|
||
@item try
|
||
Prompt just before the guard evaluation of a rule, after constraints
|
||
matching the heads have been found.
|
||
|
||
@item apply
|
||
Prompt upon the application of a rule, after the successful guard evaluation,
|
||
when the rule commits and fires, just before evaluating the body.
|
||
|
||
@item insert
|
||
Prompt when a constraint gets inserted into the constraint store,
|
||
i.e.@: after all rules have been tried.
|
||
|
||
@item remove
|
||
Prompt when a constraint gets removed from the constraint store, e.g.
|
||
when a simplification rule applies.
|
||
|
||
@end table
|
||
|
||
@noindent
|
||
The initial value of the CHR leashing mode is
|
||
@code{[call,exit,fail,wake,apply]}. Predefined shortcuts are:
|
||
@table @code
|
||
@item chr_leash(none), chr_leash(off)
|
||
To turn leashing off.
|
||
|
||
@item chr_leash(all)
|
||
To prompt at every port.
|
||
|
||
@item chr_leash(default)
|
||
Same as @code{chr_leash([call,exit,fail,wake,apply])}.
|
||
|
||
@item chr_leash(call)
|
||
No need to use a list if only a singular port is to be leashed.
|
||
@end table
|
||
|
||
@end table
|
||
|
||
@node CHR Spy-points, CHR Debugging Messages, CHR Debugging Predicates, CHR Debugging
|
||
@subsection CHR Spy-points
|
||
@cindex CHR spy-points
|
||
|
||
For CHR programs of any size, it is clearly impractical to creep through the
|
||
entire program. @dfn{Spy-points} make it possible to stop the program
|
||
upon an event of interest. Once
|
||
there, one can set further spy-points in order to catch the control flow
|
||
a bit further on, or one can start creeping.
|
||
|
||
Setting a spy-point on a constraint or a rule indicates that you wish to
|
||
see all control flow through the various ports involved, except during
|
||
skips. When control passes through any port with a spy-point set on it,
|
||
a message is output and the user is asked to interact. Note that the
|
||
current mode of leashing does not affect spy-points: user interaction is
|
||
requested at @emph{every} port.
|
||
|
||
Spy-points are set and removed by the following predicates,
|
||
which are declared as prefix operators:
|
||
|
||
@table @code
|
||
@item chr_spy @var{Spec}
|
||
@findex chr_spy/1
|
||
Sets spy-points on constraints and rules given by @var{Spec}, which is
|
||
is of the form:
|
||
|
||
@table @asis
|
||
@item @var{_} (variable)
|
||
denoting all constraints and rules, or:
|
||
|
||
@item @var{constraints Cs}
|
||
where @var{Cs} is one of
|
||
@table @asis
|
||
|
||
@item @var{_} (variable)
|
||
denoting all constraints
|
||
|
||
@item @var{C},...,@var{C}
|
||
denoting a list of constraints @var{C}
|
||
|
||
@item @var{Name}
|
||
denoting all constraints with this functor, regardless of arity
|
||
|
||
@item @var{Name/Arity}
|
||
denoting the constraint of that name and arity
|
||
@end table
|
||
|
||
@item @var{rules Rs}
|
||
where @var{Rs} is one of:
|
||
@table @asis
|
||
|
||
@item @var{_} (variable)
|
||
denoting all rules
|
||
|
||
@item @var{R},...,@var{R}
|
||
denoting a list of rules @var{R}
|
||
|
||
@item @var{Name}
|
||
where @var{Name} is the name of a rule in any handler.
|
||
|
||
@item @var{already_in_store}
|
||
The name of a rule implicitly defined by the system when
|
||
the option @code{already_in_store} is in effect.
|
||
|
||
@item @var{already_in_heads}
|
||
The name of a rule implicitly defined by the system when
|
||
the option @code{already_in_heads} or the corresponding
|
||
pragmas are in effect.
|
||
|
||
@item @var{Handler:Name}
|
||
where @var{Handler} is the name of a constraint handler
|
||
and @var{Name} is the name of a rule in that handler
|
||
|
||
@end table
|
||
@end table
|
||
|
||
@noindent
|
||
Examples:
|
||
|
||
@example
|
||
| ?- chr_spy rules rule(3), transitivity, already_in_store.
|
||
| ?- chr_spy constraints prime/1.
|
||
@end example
|
||
|
||
If you set spy-points, the CHR debugger will be switched on.
|
||
|
||
@item chr_nospy @var{Spec}
|
||
@findex chr_nospy/1
|
||
Removes spy-points on constraints and rules given by @var{Spec}, where
|
||
@var{Spec} is of the form as described for @code{chr_spy @var{Spec}}.
|
||
There is no @code{chr_nospyall/0}. To remove all CHR spy-points use
|
||
@code{chr_nospy _}.
|
||
@refill
|
||
|
||
@end table
|
||
|
||
@noindent
|
||
The options available when you arrive at a spy-point are described later.
|
||
@xref{CHR Debugging Options}.
|
||
|
||
@node CHR Debugging Messages, CHR Debugging Options, CHR Spy-points, CHR Debugging
|
||
@subsection CHR Debugging Messages
|
||
@cindex CHR debugging messages
|
||
|
||
All trace messages are output to the standard error
|
||
stream. This allows you to trace programs while they are performing
|
||
file I/O. The basic format is as follows:
|
||
|
||
@example
|
||
@var{S} 3 1 try eratosthenes:absorb(10) @@ prime(9)#<c4>, prime(10)#<c2> ?
|
||
@end example
|
||
|
||
@noindent
|
||
@var{S} is a spy-point indicator. It is printed as @samp{@ } if there is
|
||
no spy-point, as @samp{r}, indicating that there is a spy-point on this
|
||
rule, or as @samp{c} if one of the involved constraints has a spy-point.
|
||
|
||
The first number indicates the current depth of the execution; i.e.@:
|
||
the number of direct @dfn{ancestors} the currently active constraint
|
||
has.
|
||
@refill
|
||
|
||
The second number indicates the head position of the currently active
|
||
constraint at rule ports.
|
||
|
||
The next item tells you which port is currently traced.
|
||
|
||
A constraint or a matching rule are printed next.
|
||
Constraints print as @code{Term#Id}, where @var{Id} is a unique
|
||
identifier pointing into the constraint store.
|
||
Rules are printed as @code{Handler:Name @@}, followed by the constraints
|
||
matching the heads.
|
||
|
||
The final @samp{?} is the prompt indicating that you should type in one of the
|
||
debug options (@pxref{CHR Debugging Options}). @refill
|
||
|
||
@node CHR Debugging Options, , CHR Debugging Messages, CHR Debugging
|
||
@subsection CHR Debugging Options
|
||
@cindex CHR debugging options
|
||
|
||
This section describes the options available when the system prompts you
|
||
after printing out a debugging message. Most of them you know from the
|
||
standard Prolog debugger. All the options are one letter mnemonics, some
|
||
of which can be optionally followed by a decimal integer. They are read
|
||
from the standard input stream up to the end of the line
|
||
(Return, @key{<cr>}). Blanks will be ignored.
|
||
|
||
The only option which you really have to remember is @samp{h}. This
|
||
provides help in the form of the following list of available options.
|
||
|
||
@example
|
||
@group
|
||
CHR debugging options:
|
||
<cr> creep c creep
|
||
l leap
|
||
s skip s <i> skip (ancestor i)
|
||
g ancestors
|
||
& constraints & <i> constraints (details)
|
||
n nodebug = debugging
|
||
+ spy this
|
||
- nospy this . show rule
|
||
< reset printdepth < <n> set printdepth
|
||
a abort b break
|
||
? help h help
|
||
@end group
|
||
@end example
|
||
|
||
@table @kbd
|
||
@item c
|
||
@itemx @key{<cr>}
|
||
@dfn{creep} causes the debugger to single-step to the very next port
|
||
and print a message. Then if the port is leashed, the
|
||
user is prompted for further interaction. Otherwise, it continues creeping.
|
||
If leashing is off, creep is the same as @dfn{leap} (see below) except that a
|
||
complete trace is printed on the standard error stream. @refill
|
||
|
||
@item l
|
||
@dfn{leap} causes the debugger to resume running your program, only
|
||
stopping when a spy-point is reached (or when the program terminates).
|
||
Leaping can thus be used to follow the execution at a higher level than
|
||
exhaustive tracing. @refill
|
||
|
||
@item s
|
||
@itemx s i
|
||
@dfn{skip} over the entire execution of the constraint. That is, you
|
||
will not see anything until control comes back to this constraint (at
|
||
either the @code{exit} port or the @code{fail} port). This includes
|
||
ports with spy-points set; they will be masked out during the skip.
|
||
The command can be used with a numeric argument to skip the execution
|
||
up to and including the ancestor indicated by the argument.
|
||
Example:
|
||
@example
|
||
@group
|
||
...
|
||
4 - exit prime(8)#<c6> ? g
|
||
Ancestors:
|
||
1 1 apply eratosthenes:rule(2) @@ primes(10)#<c1>
|
||
2 1 apply eratosthenes:rule(2) @@ primes(9)#<c3>
|
||
3 1 apply eratosthenes:rule(2) @@ primes(8)#<c5>
|
||
4 - call prime(8)#<c6>
|
||
|
||
4 - exit prime(8)#<c6> ? s 2
|
||
2 - exit primes(9)#<c3> ?
|
||
@end group
|
||
@end example
|
||
|
||
@item g
|
||
@dfn{print ancestors} provides you with a list of ancestors to the
|
||
currently active constraint, i.e.@: all constraints not yet exited that led
|
||
to the current constraint in the derivation sequence.
|
||
The format is the same as with trace messages.
|
||
Constraints start with @code{call} entries in the stack.
|
||
The subsequent application of a rule replaces the call entry
|
||
in the stack with an @code{apply} entry. Later the constraint
|
||
shows again as @code{redo} or @code{fail} entry.
|
||
Example:
|
||
@example
|
||
@group
|
||
0 - call primes(10)#<c1> ?
|
||
1 1 try eratosthenes:rule(2) @@ primes(10)#<c1> ? g
|
||
|
||
Ancestors:
|
||
1 - call primes(10)#<c1>
|
||
|
||
1 1 try eratosthenes:rule(2) @@ primes(10)#<c1> ?
|
||
1 1 apply eratosthenes:rule(2) @@ primes(10)#<c1> ?
|
||
1 - call prime(10)#<c2> ?
|
||
2 - insert prime(10)#<c2>
|
||
2 - exit prime(10)#<c2> ? g
|
||
|
||
Ancestors:
|
||
1 1 apply eratosthenes:rule(2) @@ primes(10)#<c1>
|
||
2 - call prime(10)#<c2>
|
||
@end group
|
||
@end example
|
||
|
||
@item &
|
||
@dfn{print constraints} prints a list of the constraints in the
|
||
constraint store. With a numeric argument, details relevant primarily to
|
||
CHR implementors are shown. @refill
|
||
|
||
@item n
|
||
@dfn{nodebug} switches the CHR debugger off. @refill
|
||
|
||
@item =
|
||
@dfn{debugging} outputs information concerning the status of the CHR debugger
|
||
as via @code{chr_debugging/0}
|
||
|
||
@item +
|
||
@dfn{spy this} sets a spy-point on the current constraint or rule.
|
||
|
||
@item -
|
||
@dfn{nospy this} removes the spy-point from the current constraint or
|
||
rule, if it exists.
|
||
|
||
@item .
|
||
@dfn{show rule}
|
||
prints the current rule instantiated by the matched constraints. Example:
|
||
@example
|
||
8 1 apply era:absorb(8) @@ prime(4)#<c14> \ prime(8)#<c6> ? .
|
||
|
||
absorb(8) @@
|
||
prime(4)#<c14> \
|
||
prime(8)#<c6> <=>
|
||
|
||
8 mod 4=:=0
|
||
|
|
||
true.
|
||
@end example
|
||
|
||
@item <
|
||
@itemx < n
|
||
While in the debugger, a @dfn{printdepth} is in effect for limiting
|
||
the subterm nesting level when printing rules and constraints.
|
||
The limit is initially 10. This command, without arguments, resets the
|
||
limit to 10. With an argument of @var{n}, the limit is set to @var{n},
|
||
treating 0 as infinity.
|
||
@refill
|
||
|
||
@item a
|
||
@dfn{abort} calls the built-in predicate @code{abort/0}.
|
||
@refill
|
||
|
||
@item b
|
||
@dfn{break} calls the built-in predicate @code{break/0}, thus putting
|
||
you at a recursive top-level. When you end the break (entering ^D)
|
||
you will be re-prompted at the port at which you broke. The
|
||
CHR debugger is temporarily switched off as you call the break and will
|
||
be switched on again when you finish the break and go back to the old
|
||
execution. Any changes to the CHR leashing or to spy-points during the
|
||
break will remain in effect.
|
||
@refill
|
||
|
||
@item ?
|
||
@itemx h
|
||
@dfn{help} displays the table of options given above. @refill
|
||
|
||
@end table
|
||
|
||
|
||
|
||
|
||
@node CHR Programming Hints, CHR Constraint Handlers, CHR Debugging, CHR
|
||
@section Programming Hints
|
||
|
||
This section gives you some programming hints for CHR. For maximum
|
||
efficiency of your constraint handler, see also the previous subsections
|
||
on declarations and options.
|
||
|
||
Constraint handling rules for a given constraint system can often be
|
||
derived from its definition in formalisms such as inference rules,
|
||
rewrite rules, sequents, formulas expressing axioms and theorems.
|
||
CHR can also be found by first considering
|
||
special cases of each constraint and then looking at interactions of
|
||
pairs of constraints sharing a variable. Cases that do not occur in the
|
||
application can be ignored.
|
||
|
||
It is important to find the right @dfn{granularity} of the constraints.
|
||
Assume one wants to express that @dfn{n} variables are different from
|
||
each other. It is more efficient to have a single constraint
|
||
@code{all_different(List_of_n_Vars)} than @dfn{n*n} inequality
|
||
constraints between each pair of different variables. However, the
|
||
extreme case of having a single constraint modeling the whole constraint
|
||
store will usually be inefficient.
|
||
|
||
Starting from an executable specification, the rules can then be refined
|
||
and adapted to the specifics of the application. Efficiency can be
|
||
improved by weakening the guards to perform simplification as early as
|
||
needed and by strengthening the guards to do the @dfn{just right} amount
|
||
of propagation. Propagation rules can be expensive, because no
|
||
constraints are removed.
|
||
|
||
The more heads a rule has, the more expensive it is. @dfn{Rules with
|
||
several heads} are more efficient, if the heads of the rule share a
|
||
variable (which is usually the case). Then the search for a partner
|
||
constraint has to consider less candidates. In the current
|
||
implementation, constraints are indexed by their functors, so that the
|
||
search is only performed among the constraints containing the shared
|
||
variable. Moreover, two rules with identical
|
||
(or sufficiently similar) heads can be merged into one rule so that the
|
||
search for a partner constraint is only performed once instead of twice.
|
||
|
||
As @dfn{guards} are tried frequently, they should be simple @dfn{tests}
|
||
not involving side-effects. Head matching is more efficient than
|
||
explicitly checking equalities in the ask-part of the guard. In the
|
||
tell part of a guard, it should be made sure that variables from the
|
||
head are never touched (e.g.@: by using @code{nonvar} or @code{ground} if
|
||
necessary). For efficiency and clarity reasons, one should also avoid
|
||
using constraints in guards. Besides conjunctions, disjunctions are
|
||
allowed in the guard, but they should be used with care. The use of
|
||
other control built-in predicates in the guard is
|
||
discouraged. Negation and if-then-else in the ask part of a guard can
|
||
give wrong results, since e.g.@: failure of the negated goal may be due to
|
||
touching its variables.
|
||
|
||
@dfn{Several handlers can be used simultaneously if} they do not share
|
||
constraints with the same name. The implementation will not work
|
||
correctly if the same constraint is defined in rules of different
|
||
handlers that have been compiled separately. In such a case, the
|
||
handlers must be merged @dfn{by hand}. This means that the source code
|
||
has to be edited so that the rules for the shared constraint are
|
||
together (in one module). Changes may be necessary (like
|
||
strengthening guards) to avoid divergence or loops in the computation.
|
||
|
||
|
||
@node CHR Constraint Handlers, CHR Backward Compatibility, CHR Programming Hints, CHR
|
||
@section Constraint Handlers
|
||
|
||
The CHR library comes with plenty of constraint handlers written in CHR.
|
||
The most recent versions of these are maintained at:
|
||
|
||
@example
|
||
http://www.pst.informatik.uni-muenchen.de/~fruehwir/chr-solver.html
|
||
@end example
|
||
|
||
@table @file
|
||
|
||
@item arc.pl
|
||
classical arc-consistency over finite domains
|
||
|
||
@item bool.pl
|
||
simple Boolean constraints
|
||
|
||
@item cft.pl
|
||
feature term constraints according to the CFT theory
|
||
|
||
@item domain.pl
|
||
finite domains over arbitrary ground terms and interval domains over integers and reals, but without arithmetic functions
|
||
|
||
@item gcd.pl
|
||
elegant two-liner for the greatest common divisor
|
||
|
||
@item interval.pl
|
||
straightforward interval domains over integers and reals, with arithmetic functions
|
||
|
||
@item kl-one.pl
|
||
terminological reasoning similar to KL-ONE or feature trees
|
||
|
||
@item leq.pl
|
||
standard introductory CHR example handler for less-than-or-equal
|
||
|
||
@item list.pl
|
||
equality constraints over concatenations of lists (or strings)
|
||
|
||
@item listdom.pl
|
||
a straightforward finite enumeration list domains over integers, similar to @file{interval.pl}
|
||
|
||
@item math-elim.pl
|
||
solves linear polynomial equations and inequations using variable elimination, several variations possible
|
||
|
||
@item math-fougau.pl
|
||
solves linear polynomial equations and inequations by combining variable elimination for equations with Fourier's algorithm for inequations, several variations possible
|
||
|
||
@item math-fourier.pl
|
||
a straightforward Fouriers algorithm to solve polynomial inequations
|
||
over the real or rational numbers
|
||
|
||
@item math-gauss.pl
|
||
a straightforward, elegant implementation of variable elimination for equations in one rule
|
||
|
||
@item minmax.pl
|
||
simple less-than and less-than-or-equal ordering constraints together with minimum and maximum constraints
|
||
|
||
@item modelgenerator.pl
|
||
example of how to use CHR for model generation in theorem proving
|
||
|
||
@item monkey.pl
|
||
classical monkey and banana problem, illustrates how CHR can be used as
|
||
a fairly efficient production rule system
|
||
|
||
@item osf.pl
|
||
constraints over order sorted feature terms according to the OSF theory
|
||
|
||
@item oztype.pl
|
||
rational trees with disequality and OZ type constraint with intersection
|
||
|
||
@item pathc.pl
|
||
the most simple example of a handler for path consistency - two rules
|
||
|
||
@item primes.pl
|
||
elegant implementations of the sieve of Eratosthenes reminiscent of the
|
||
chemical abstract machine model, also illustrates use of CHR as a
|
||
general purpose concurrent constraint language
|
||
|
||
@item scheduling.pl
|
||
simple classical constraint logic programming scheduling example on building a house
|
||
|
||
@item tarski.pl
|
||
most of Tarski's axiomatization of geometry as constraint system
|
||
|
||
@item term.pl
|
||
Prolog term manipulation built-in predicates @code{functor/3, arg/3, =../2} as constraints
|
||
|
||
@item time-pc.pl
|
||
grand generic handler for path-consistency over arbitrary constraints,
|
||
load via @file{time.pl} to get a powerful solver for temporal constraints based on Meiri's unifying framework. @file{time-rnd.pl} contains a generator for random test problems.
|
||
|
||
@item time-point.pl
|
||
quantitative temporal constraints over time points using path-consistency
|
||
|
||
@item tree.pl
|
||
equality and disequality over finite and infinite trees (terms)
|
||
|
||
@item type.pl
|
||
equalities and type constraints over finite and infinite trees (terms)
|
||
|
||
@end table
|
||
|
||
You can consult or compile a constraint handler from the CHR library using
|
||
e.g.:
|
||
@example
|
||
?- [library('chr/examples/gcd')].
|
||
?- compile(library('chr/examples/gcd')).
|
||
@end example
|
||
If you want to learn more about the handlers,
|
||
look at their documented source code.
|
||
|
||
In addition, there are files with example queries for some handlers,
|
||
their file name starts with @file{examples-} and the file extension
|
||
indicates the handler, e.g.@: @file{.bool}:
|
||
|
||
@example
|
||
examples-adder.bool
|
||
examples-benchmark.math
|
||
examples-deussen.bool
|
||
examples-diaz.bool
|
||
examples-fourier.math
|
||
examples-holzbaur.math
|
||
examples-lim1.math
|
||
examples-lim2.math
|
||
examples-lim3.math
|
||
examples-puzzle.bool
|
||
examples-queens.bool
|
||
examples-queens.domain
|
||
examples-stuckey.math
|
||
examples-thom.math
|
||
@end example
|
||
|
||
|
||
@node CHR Backward Compatibility, , CHR Constraint Handlers, CHR
|
||
@section Backward Compatibility
|
||
|
||
In this section, we discuss backward compatibility with the CHR library
|
||
of Eclipse Prolog.
|
||
|
||
@enumerate
|
||
|
||
@item
|
||
The restriction on at most two heads in a rule has been abandoned. A
|
||
rule can have as many heads as you like. Note however, that searching
|
||
for partner constraints can be expensive.
|
||
|
||
@item
|
||
By default, rules are compiled in textual order. This gives the
|
||
programmer more control over the constraint handling process. In the
|
||
Eclipse library of CHR, the compiler was optimizing the order of
|
||
rules. Therefore, when porting a handler, rules may have to
|
||
be reordered. A good heuristic is to prefer simplification to
|
||
simpagation and propagation and to prefer rules with single heads to
|
||
rules with several heads. Instead of manually rearranging an old handler
|
||
one may also use the following combination of options to get the
|
||
corresponding effect:
|
||
@example
|
||
option(rule_ordering,heuristic).
|
||
option(revive_scheme,old).
|
||
@end example
|
||
|
||
@item
|
||
For backward compatibility, the @code{already_in_store},
|
||
@code{already_in_head} and @code{guard_bindings} options
|
||
are still around, but there are CHR syntax extensions: @ref{CHR Syntax}
|
||
and pragmas @ref{CHR Pragmas}
|
||
offering better grained control.
|
||
|
||
@item
|
||
The Eclipse library of CHR provided automatic built-in labeling through
|
||
the @code{label_with} declaration. Since it was not widely used and can
|
||
be easily simulated, built-in labeling was dropped. The same effect can
|
||
be achieved by replacing the declaration @code{label_with Constraint if
|
||
Guard} by the simplification rule @code{chr_labeling, Constraint <=>
|
||
Guard | Constraint', chr_labeling} and by renaming the head in each
|
||
clause @code{Constraint :- Body} into @code{Constraint' :- Body} where
|
||
@code{Constraint'} is a new predicate. Efficiency can be improved by
|
||
declaring @code{Constraint} to be passive: @code{chr_labeling,
|
||
Constraint#Id <=> Guard | Constraint', chr_labeling pragma passive(Id)}.
|
||
This translation will not work if @code{option(already_in_heads,on)}.
|
||
In that case use e.g.@: @code{chr_labeling(_), Constraint <=> Guard |
|
||
Constraint', chr_labeling(_)} to make the new call to
|
||
@code{chr_labeling} differ from the head occurrence.
|
||
|
||
@item
|
||
The set of built-in predicates for advanced CHR users is now larger
|
||
and better designed. Also the debugger has been improved. The Opium
|
||
debugging environment is not available in SICStus Prolog.
|
||
@end enumerate
|
||
|
||
|
||
@node Logtalk, Parallelism, CHR, Extensions
|
||
@chapter Logtalk
|
||
@cindex logtalk
|
||
|
||
The Logtalk object-oriented extension is available once included
|
||
with the @code{use_module(library(logtalk))} command. Note that,
|
||
although we load Logtalk using the @code{use_module/1} built-in
|
||
predicate, the system is not packaged as a module not does it use
|
||
modules in its implementation.
|
||
|
||
Logtalk documentation is included in the Logtalk directory. For the
|
||
latest news, please see the URL @url{http://www.ci.uc.pt/logtalk/logtalk.html}.
|
||
|
||
|
||
@node Parallelism, Tabling, Logtalk, Extensions
|
||
@chapter Parallelism
|
||
|
||
@cindex parallelism
|
||
@cindex or-parallelism
|
||
There has been a sizeable amount of work on an or-parallel
|
||
implementation for YAP, called @strong{YapOr}. Most of this work has
|
||
been performed by Ricardo Rocha. In this system parallelism is exploited
|
||
implicitly by running several alternatives in or-parallel. This option
|
||
can be enabled from the @code{configure} script or by checking the
|
||
system's @code{Makefile}.
|
||
|
||
@strong{YapOr} is still a very experimental system, going through rapid
|
||
development. The following restrictions are of note:
|
||
|
||
@itemize @bullet
|
||
@item @strong{YapOr} currently only supports the Linux/X86 and SPARC/Solaris
|
||
platforms. Porting to other Unix-like platforms should be straightforward.
|
||
|
||
@item @strong{YapOr} does not support parallel updates to the
|
||
data-base.
|
||
|
||
@item @strong{YapOr} does not support opening or closing of streams during
|
||
parallel execution.
|
||
|
||
@item Garbage collection and stack shifting are not supported in
|
||
@strong{YapOr}.
|
||
|
||
@item Built-ins that cause side-effects can only be executed when
|
||
left-most in the search-tree. There are no primitives to provide
|
||
asynchronous or cavalier execution of these built-ins, as in Aurora or
|
||
Muse.
|
||
|
||
@item YAP does not support voluntary suspension of work.
|
||
@end itemize
|
||
|
||
We expect that some of these restrictions will be removed in future
|
||
releases.
|
||
|
||
@node Tabling, Low Level Tracing, Parallelism , Extensions
|
||
@chapter Tabling
|
||
|
||
@cindex tabling
|
||
An initial cut for an implementation of tabling in the style of
|
||
XSB-Prolog is now available. Tabling was implemented by Ricardo
|
||
Rocha. To experiment with tabling use @code{-DTABLING} to
|
||
@code{YAP_EXTRAS} in the system's @code{Makefile}.
|
||
|
||
You can use the directive @code{table} to force calls for the argument
|
||
predicate to be tabled. Tabling information is stored in a trie, as for
|
||
XSB-Prolog.
|
||
|
||
@node Low Level Tracing, Low Level Profiling, Tabling, Extensions
|
||
@chapter Tracing at Low Level
|
||
|
||
It is possible to follow the flow at abstract machine level if
|
||
YAP is compiled with the flag @code{LOW_LEVEL_TRACER}. Note
|
||
that this option is of most interest to implementers, as it quickly generates
|
||
an huge amount of information.
|
||
|
||
Low level tracing can be toggled from an interrupt handler by using the
|
||
option @code{T}. There are also two builtins that activate and
|
||
deactivate low level tracing:
|
||
|
||
@table @code
|
||
@item start_low_level_trace
|
||
@findex start_low_level_trace/0
|
||
@snindex start_low_level_trace/0
|
||
@cnindex start_low_level_trace/0
|
||
Begin display of messages at procedure entry and retry.
|
||
|
||
@item stop_low_level_trace
|
||
@findex start_low_level_trace/0
|
||
@snindex start_low_level_trace/0
|
||
@cnindex start_low_level_trace/0
|
||
Stop display of messages at procedure entry and retry.
|
||
@end table
|
||
|
||
Note that this compile-time option will slow down execution.
|
||
|
||
@node Low Level Profiling, , Low Level Tracing, Extensions
|
||
@chapter Profiling the Abstract Machine
|
||
|
||
Implementors may be interested in detecting on which abstract machine
|
||
instructions are executed by a program. The @code{ANALYST} flag can give
|
||
WAM level information. Note that this option slows down execution very
|
||
substantially, and is only of interest to developers of the system
|
||
internals, or to system debuggers.
|
||
|
||
@table @code
|
||
@item reset_op_counters
|
||
@findex reset_op_counters/0
|
||
@snindex reset_op_counters/0
|
||
@cnindex reset_op_counters/0
|
||
Reinitialise all counters.
|
||
|
||
@item show_op_counters(+@var{A})
|
||
@findex show_op_counters/1
|
||
@snindex show_op_counters/1
|
||
@cnindex show_op_counters/1
|
||
Display the current value for the counters, using label @var{A}. The
|
||
label must be an atom.
|
||
|
||
@item show_ops_by_group(+@var{A})
|
||
@findex show_ops_by_group/1
|
||
@snindex show_ops_by_group/1
|
||
@cnindex show_ops_by_group/1
|
||
Display the current value for the counters, organised by groups, using
|
||
label @var{A}. The label must be an atom.
|
||
|
||
@end table
|
||
|
||
@node Debugging,Efficiency,Extensions,Top
|
||
@chapter Debugging
|
||
|
||
@menu
|
||
* Deb Preds:: Debugging Predicates
|
||
* Deb Interaction:: Interacting with the debugger
|
||
@end menu
|
||
|
||
@node Deb Preds, Deb Interaction, , Debugging
|
||
@section Debugging Predicates
|
||
|
||
The following predicates are available to control the debugging of
|
||
programs:
|
||
|
||
@table @code
|
||
@item debug
|
||
@findex debug/0
|
||
@saindex debug/0
|
||
@cyindex debug/0
|
||
Switches the debugger on.
|
||
|
||
@item debugging
|
||
@findex debugging/0
|
||
@syindex debugging/0
|
||
@cyindex debugging/0
|
||
Outputs status information about the debugger which includes the leash
|
||
mode and the existing spy-points, when the debugger is on.
|
||
|
||
@item nodebug
|
||
@findex nodebug/0
|
||
@syindex nodebug/0
|
||
@cyindex nodebug/0
|
||
Switches the debugger off.
|
||
|
||
@item spy +@var{P}
|
||
@findex spy/1
|
||
@syindex spy/1
|
||
@cyindex spy/1
|
||
Sets spy-points on all the predicates represented by
|
||
@var{P}. @var{P} can either be a single specification or a list of
|
||
specifications. Each one must be of the form @var{Name/Arity}
|
||
or @var{Name}. In the last case all predicates with the name
|
||
@var{Name} will be spied. As in C-Prolog, system predicates and
|
||
predicates written in C, cannot be spied.
|
||
|
||
@item nospy +@var{P}
|
||
@findex nospy/1
|
||
@syindex nospy/1
|
||
@cyindex nospy/1
|
||
Removes spy-points from all predicates specified by @var{P}.
|
||
The possible forms for @var{P} are the same as in @code{spy P}.
|
||
|
||
@item nospyall
|
||
@findex nospyall/0
|
||
@syindex nospyall/0
|
||
@cnindex nospyall/0
|
||
Removes all existing spy-points.
|
||
|
||
@item leash(+@var{M})
|
||
@findex leash/1
|
||
@syindex leash/1
|
||
@cyindex leash/1
|
||
Sets leashing mode to @var{M}.
|
||
The mode can be specified as:
|
||
@table @code
|
||
@item full
|
||
prompt on Call, Exit, Redo and Fail
|
||
@item tight
|
||
prompt on Call, Redo and Fail
|
||
@item half
|
||
prompt on Call and Redo
|
||
@item loose
|
||
prompt on Call
|
||
@item off
|
||
never prompt
|
||
@end table
|
||
@noindent
|
||
The initial leashing mode is half.
|
||
|
||
|
||
@noindent
|
||
The user may also specify directly the debugger ports
|
||
where he wants to be prompted. If the argument for leash
|
||
is a number @var{N}, each of lower four bits of the number is used to
|
||
control prompting at one the ports of the box model. The debugger will
|
||
prompt according to the following conditions:
|
||
|
||
@itemize @bullet
|
||
@item
|
||
if @code{N/\ 1 =\= 0} prompt on fail
|
||
@item
|
||
if @code{N/\ 2 =\= 0} prompt on redo
|
||
@item
|
||
if @code{N/\ 4 =\= 0} prompt on exit
|
||
@item
|
||
if @code{N/\ 8 =\= 0} prompt on call
|
||
@end itemize
|
||
@noindent
|
||
Therefore, @code{leash(15)} is equivalent to @code{leash(full)} and
|
||
@code{leash(0)} is equivalent to @code{leash(off)}.
|
||
|
||
@noindent
|
||
Another way of using @code{leash} is to give it a list with the names of
|
||
the ports where the debugger should stop. For example,
|
||
@code{leash([call,exit,redo,fail])} is the same as @code{leash(full)} or
|
||
@code{leash(15)} and @code{leash([fail])} might be used instead of
|
||
@code{leash(1)}.
|
||
|
||
@item spy_write(+@var{Stream},Term)
|
||
@findex spy_write/2
|
||
@snindex spy_write/2
|
||
@cnindex spy_write/2
|
||
If defined by the user, this predicate will be used to print goals by
|
||
the debugger instead of @code{write/2}.
|
||
|
||
@end table
|
||
|
||
|
||
@node Deb Interaction, , Deb Preds, Debugging
|
||
@section Interacting with the debugger
|
||
|
||
Debugging with YAP is similar to debugging with C-Prolog. Both
|
||
systems include a procedural debugger, based in the four port model. In
|
||
this model, execution is seen at the procedure level: each activation of
|
||
a procedure is seen as a box with control flowing into and out of that
|
||
box.
|
||
|
||
In the four port model control is caught at four key points: before
|
||
entering the procedure, after exiting the procedure (meaning successful
|
||
evaluation of all queries activated by the procedure), after backtracking but
|
||
before trying new alternative to the procedure and after failing the
|
||
procedure. Each one of these points is named a port:
|
||
|
||
@smallexample
|
||
@group
|
||
*--------------------------------------*
|
||
Call | | Exit
|
||
---------> + descendant(X,Y) :- offspring(X,Y). + --------->
|
||
| |
|
||
| descendant(X,Z) :- |
|
||
<--------- + offspring(X,Y), descendant(Y,Z). + <---------
|
||
Fail | | Redo
|
||
*--------------------------------------*
|
||
@end group
|
||
@end smallexample
|
||
|
||
@table @code
|
||
|
||
@item Call
|
||
The call port is activated before initial invocation of
|
||
procedure. Afterwards, execution will try to match the goal with the
|
||
head of existing clauses for the procedure.
|
||
@item Exit
|
||
This port is activated if the procedure succeeds.
|
||
Control will now leave the procedure and return to its ancestor.
|
||
@item Redo
|
||
if the goal, or goals, activated after the call port
|
||
fail then backtracking will eventually return control to this procedure
|
||
through the redo port.
|
||
@item Fail
|
||
If all clauses for this predicate fail, then the
|
||
invocation fails, and control will try to redo the ancestor of this
|
||
invocation.
|
||
@end table
|
||
|
||
To start debugging, the user will usually spy the relevant procedures,
|
||
entering debug mode, and start execution of the program. When finding
|
||
the first spy-point, YAP's debugger will take control and show a
|
||
message like:
|
||
|
||
@example
|
||
* (1) call: quicksort([1,2,3],_38) ?
|
||
@end example
|
||
|
||
The debugger message will be shown while creeping, or at spy-points,
|
||
and it includes four or five fields:
|
||
|
||
@itemize @bullet
|
||
@item
|
||
The first two characters are used to point out special states of the
|
||
debugger. If the first character is a @code{*}, execution is at a
|
||
spy-point. If the second character is a @code{>}, execution has returned
|
||
either from a skip, a fail or a redo command.
|
||
@item
|
||
The second field is the activation number, and uniquely identifies the
|
||
activation. The number will start from 1 and will be incremented for
|
||
each activation found by the debugger.
|
||
@item
|
||
In the third field, the debugger shows the active port.
|
||
@item
|
||
The fourth field is the goal. The goal is written by @code{write/1}.
|
||
@end itemize
|
||
|
||
If the active port is leashed, the debugger will prompt the user with a
|
||
@code{?}, and wait for a command. A debugger command is just a
|
||
character, followed by a return. By default, only the call and redo
|
||
entries are leashed, but the @code{leash/1} predicate can be used in
|
||
order to make the debugger stop where needed.
|
||
|
||
There are several commands available, but the user only needs to
|
||
remember the help command, which is @code{h}. This command shows all the
|
||
available options, which are:
|
||
@table @code
|
||
@item c - creep
|
||
this command makes YAP continue execution and stop at the next
|
||
leashed port.
|
||
@item return - creep
|
||
the same as c
|
||
@item l - leap
|
||
YAP will continue execution until a port of a spied predicate
|
||
is found;
|
||
@item k - quasi-leap
|
||
similar to leap but faster since the computation history is
|
||
not kept; useful when leap becomes too slow.
|
||
@item s - skip
|
||
YAP will continue execution without showing any messages until
|
||
returning to the current activation. Spy-points will be ignored in this
|
||
mode. This command is meaningless, and therefore illegal, in the fail
|
||
and exit ports.
|
||
@item t - fast-skip
|
||
similar to skip but faster since the computation history is not
|
||
kept; useful when skip becomes too slow.
|
||
@item q - quasi-leap
|
||
YAP will continue execution until a port of a spied
|
||
predicate is found or until returning to the current activation.
|
||
@item f - fail
|
||
forces YAP to fail the goal proceeding directly to the fail port.
|
||
The command is not available in the fail port.
|
||
@item r - retry
|
||
after this command, YAP will retry the present goal, and so go
|
||
back to the call port. Note that any side effects of the goal will not
|
||
be undone. This command is not available at the call port.
|
||
@item a - abort
|
||
execution will be aborted, and the interpreter will return to the
|
||
top-level.
|
||
@item n - nodebug
|
||
stop debugging but continue execution. The command will clear all active
|
||
spy-points, leave debugging mode and continue execution.
|
||
@item e - exit
|
||
leave YAP.
|
||
@item h - help
|
||
show the debugger commands.
|
||
@item ! Query
|
||
execute a query. YAP will not show the result of the query.
|
||
@item b - break
|
||
break active execution and launch a break level. This is the same as !
|
||
break.
|
||
@item + - spy this goal
|
||
start spying the active goal. The same as @code{! spy G} where @var{G}
|
||
is the active goal.
|
||
@item - - nospy this goal
|
||
stop spying the active goal. The same as @code{! nospy G} where @var{G} is
|
||
the active goal.
|
||
@item p - print
|
||
shows the active goal using print/1
|
||
@item d - display
|
||
shows the active goal using display/1
|
||
@item <Depth - debugger write depth
|
||
sets the maximum write depth, both for composite terms and lists, that
|
||
will be used by @code{write/1} or @code{write/2}. For more
|
||
information about @code{write_depth/2} (@pxref{I/O Control}).
|
||
@item < - full term
|
||
resets to infinite the debugger's maximum write depth. For
|
||
more information about @code{write_depth/2} (@pxref{I/O Control}).
|
||
@end table
|
||
|
||
The debugging information, when fast-skip @code{quasi-leap} is used, will
|
||
be lost.
|
||
|
||
@node Efficiency, C-Interface, Debugging, Top
|
||
@chapter Indexing
|
||
The indexation mechanism restricts the set of clauses to be tried in a
|
||
procedure by using information about the status of a selected argument of
|
||
the goal (in YAP, as in most compilers, the first argument).
|
||
This argument
|
||
is then used as a key, selecting a restricted set of a clauses from all the
|
||
clauses forming the procedure.
|
||
|
||
As an example, the two clauses for concatenate:
|
||
|
||
@example
|
||
concatenate([],L,L).
|
||
concatenate([H|T],A,[H|NT]) :- concatenate(T,A,NT).
|
||
@end example
|
||
|
||
If the first argument for the goal is a list, then only the second clause
|
||
is of interest. If the first argument is the nil atom, the system needs to
|
||
look only for the first clause. The indexation generates instructions that
|
||
test the value of the first argument, and then proceed to a selected clause,
|
||
or group of clauses.
|
||
|
||
Note that if the first argument was a free variable, then both clauses
|
||
should be tried. In general, indexation will not be useful if the first
|
||
argument is a free variable.
|
||
|
||
When activating a predicate, a Prolog system needs to store state
|
||
information. This information, stored in a structure known as choice point
|
||
or fail point, is necessary when backtracking to other clauses for the
|
||
predicate. The operations of creating and using a choice point are very
|
||
expensive, both in the terms of space used and time spent.
|
||
Creating a choice point is not necessary if there is only a clause for
|
||
the predicate as there are no clauses to backtrack to. With indexation, this
|
||
situation is extended: in the example, if the first argument was the atom
|
||
nil, then only one clause would really be of interest, and it is pointless to
|
||
create a choice point. This feature is even more useful if the first argument
|
||
is a list: without indexation, execution would try the first clause, creating
|
||
a choice point. The clause would fail, the choice point would then be used to
|
||
restore the previous state of the computation and the second clause would
|
||
be tried. The code generated by the indexation mechanism would behave
|
||
much more efficiently: it would test the first argument and see whether it
|
||
is a list, and then proceed directly to the second clause.
|
||
|
||
An important side effect concerns the use of "cut". In the above
|
||
example, some programmers would use a "cut" in the first clause just to
|
||
inform the system that the predicate is not backtrackable and force the
|
||
removal the choice point just created. As a result, less space is needed but
|
||
with a great loss in expressive power: the "cut" would prevent some uses of
|
||
the procedure, like generating lists through backtracking. Of course, with
|
||
indexation the "cut" becomes useless: the choice point is not even created.
|
||
|
||
Indexation is also very important for predicates with a large number
|
||
of clauses that are used like tables:
|
||
|
||
@example
|
||
logician(aristhoteles,greek).
|
||
logician(frege,german).
|
||
logician(russel,english).
|
||
logician(godel,german).
|
||
logician(whitehead,english).
|
||
@end example
|
||
|
||
An interpreter like C-Prolog, trying to answer the query:
|
||
|
||
@example
|
||
?- logician(godel,X).
|
||
@end example
|
||
|
||
@noindent
|
||
would blindly follow the standard Prolog strategy, trying first the
|
||
first clause, then the second, the third and finally finding the
|
||
relevant clause. Also, as there are some more clauses after the
|
||
important one, a choice point has to be created, even if we know the
|
||
next clauses will certainly fail. A "cut" would be needed to prevent
|
||
some possible uses for the procedure, like generating all logicians. In
|
||
this situation, the indexing mechanism generates instructions that
|
||
implement a search table. In this table, the value of the first argument
|
||
would be used as a key for fast search of possibly matching clauses. For
|
||
the query of the last example, the result of the search would be just
|
||
the fourth clause, and again there would be no need for a choice point.
|
||
|
||
If the first argument is a complex term, indexation will select clauses
|
||
just by testing its main functor. However, there is an important
|
||
exception: if the first argument of a clause is a list, the algorithm
|
||
also uses the list's head if not a variable. For instance, with the
|
||
following clauses,
|
||
|
||
@example
|
||
rules([],B,B).
|
||
rules([n(N)|T],I,O) :- rules_for_noun(N,I,N), rules(T,N,O).
|
||
rules([v(V)|T],I,O) :- rules_for_verb(V,I,N), rules(T,N,O).
|
||
rules([q(Q)|T],I,O) :- rules_for_qualifier(Q,I,N), rules(T,N,O).
|
||
@end example
|
||
@noindent
|
||
if the first argument of the goal is a list, its head will be tested, and only
|
||
the clauses matching it will be tried during execution.
|
||
|
||
Some advice on how to take a good advantage of this mechanism:
|
||
|
||
@itemize @bullet
|
||
|
||
@item
|
||
Try to make the first argument an input argument.
|
||
|
||
@item
|
||
Try to keep together all clauses whose first argument is not a
|
||
variable, that will decrease the number of tests since the other clauses are
|
||
always tried.
|
||
|
||
@item
|
||
Try to avoid predicates having a lot of clauses with the same key.
|
||
For instance, the procedure:
|
||
|
||
@end itemize
|
||
|
||
@example
|
||
type(n(mary),person).
|
||
type(n(john), person).
|
||
type(n(chair),object).
|
||
type(v(eat),active).
|
||
type(v(rest),passive).
|
||
@end example
|
||
|
||
@noindent
|
||
becomes more efficient with:
|
||
|
||
@example
|
||
type(n(N),T) :- type_of_noun(N,T).
|
||
type(v(V),T) :- type_of_verb(V,T).
|
||
|
||
type_of_noun(mary,person).
|
||
type_of_noun(john,person).
|
||
type_of_noun(chair,object).
|
||
|
||
type_of_verb(eat,active).
|
||
type_of_verb(rest,passive).
|
||
@end example
|
||
|
||
@node C-Interface,YapLibrary,Efficiency,Top
|
||
@chapter C Language interface to YAP
|
||
|
||
YAP provides the user with the necessary facilities for writing
|
||
predicates in a language other than prolog. Since, under Unix systems,
|
||
most language implementations are link-able to C, we will describe here
|
||
only the YAP interface to the C language.
|
||
|
||
Before describing in full detail how to interface to C code, we will examine
|
||
a brief example.
|
||
|
||
Assume the user requires a predicate @code{my_process_id(Id)} which succeeds
|
||
when @var{Id} unifies with the number of the process under which YAP is running.
|
||
|
||
In this case we will create a @code{my_process.c} file containing the
|
||
C-code described below.
|
||
|
||
@example
|
||
@cartouche
|
||
#include "../c_interface.h"
|
||
|
||
static int my_process_id(void)
|
||
@{
|
||
Term pid = MkIntTerm(getpid());
|
||
Term out = ARG1;
|
||
return(unify(out,pid));
|
||
@}
|
||
|
||
void init_my_predicates()
|
||
@{
|
||
UserCPredicate("my_process_id",my_process_id,1);
|
||
@}
|
||
@end cartouche
|
||
@end example
|
||
|
||
The commands to compile the above file depend on the operating
|
||
system. Under Linux (i386 and Alpha) you should use:
|
||
@example
|
||
gcc -c -shared -fPIC my_process.c
|
||
ld -shared -o my_process.so my_process.o
|
||
@end example
|
||
@noindent
|
||
Under Solaris2 it is sufficient to use:
|
||
@example
|
||
gcc -fPIC -c my_process.c
|
||
@end example
|
||
@noindent
|
||
Under SunOS it is sufficient to use:
|
||
@example
|
||
gcc -c my_process.c
|
||
@end example
|
||
@noindent
|
||
Under Digital Unix you need to create a @code{so} file. Use:
|
||
@example
|
||
gcc tst.c -c -fpic
|
||
ld my_process.o -o my_process.so -shared -expect_unresolved '*'
|
||
@end example
|
||
@noindent
|
||
and replace my @code{process.so} for my @code{process.o} in the
|
||
remainder of the example.
|
||
@noindent
|
||
And could be loaded, under YAP, by executing the following prolog goal
|
||
@example
|
||
load_foreign_files(['my_process'],[],init_my_predicates).
|
||
@end example
|
||
Note that since Yap4.3.3 you should not give the suffix for object
|
||
files. YAP will deduce the correct suffix from the operating system it
|
||
is running under.
|
||
|
||
Yap4.3.3 now supports loading WIN/NT DLLs. Currently you must compile
|
||
YAP under cygwin to create a library yap.dll first. You can then use
|
||
this dll to create your own dlls. Have a look at the code in
|
||
library/regex to see how to create a dll under the cygwin/mingw32
|
||
environment.
|
||
|
||
After loading that file the following prolog goal
|
||
@example
|
||
my_process_id(N)
|
||
@end example
|
||
@noindent
|
||
would unify N with the number of the process under which Yap is running.
|
||
|
||
|
||
Having presented a full example, we will now examine in more detail the
|
||
contents of the C source code file presented above.
|
||
|
||
The include statement is used to make available to the C source code the
|
||
macros for the handling of prolog terms and also some Yap public
|
||
definitions.
|
||
|
||
The function @code{my_process_id} is the implementation, in C, of the
|
||
desired predicate. Note that it returns an integer denoting the success
|
||
of failure of the goal and also that it has no arguments even though the
|
||
predicate being defined has one.
|
||
In fact the arguments of a prolog predicate written in C are accessed
|
||
through macros, defined in the include file, with names @var{ARG1},
|
||
@var{ARG2}, ..., @var{ARG16} or with @var{ARG}(@var{N}) where @var{N} is
|
||
the argument number (starting with 1). In the present case the function
|
||
uses just one local variable of type @code{ Term}, the type used for
|
||
holding Yap terms, where the integer returned by the standard unix
|
||
function @code{getpid()} is stored as an integer term (the conversion is
|
||
done by @code{MkIntTerm(Int))}. Then it calls the pre-defined routine
|
||
@code{unify(Term*, Term*)} which in turn returns an integer denoting
|
||
success or failure of the unification.
|
||
|
||
The role of the procedure @code{init_my_predicates} is to make known to
|
||
YAP, by calling @code{UserCPredicate}, the predicates being
|
||
defined in the file. This is in fact why, in the example above,
|
||
@code{init_my_predicates} was passed as the third argument to
|
||
@code{load_foreign_files}.
|
||
|
||
The rest of this appendix describes exhaustively how to interface C to YAP.
|
||
|
||
@menu
|
||
* Manipulating Terms:: Primitives available to the C programmer
|
||
* Unifying Terms:: How to Unify Two Prolog Terms
|
||
* Manipulating Strings:: From character arrays to Lists of codes and back
|
||
* Memory Allocation:: Stealing Memory From Yap
|
||
* Controlling Streams:: Control How Yap sees Streams
|
||
* Calling Yap From C:: From C to Yap to C to Yap
|
||
* Writing C:: Writing Predicates in C
|
||
* Loading Objects:: Loading Object Files
|
||
* Sav&Rest:: Saving and Restoring
|
||
* Yap4 Notes:: Changes in Foreign Predicates Interface
|
||
@end menu
|
||
|
||
@node Manipulating Terms, Unifying Terms, , C-Interface
|
||
@section Terms
|
||
|
||
This section provides information about the primitives available to the C
|
||
programmer for manipulating prolog terms.
|
||
|
||
Several C typedefs are included in the header file @code{yap/c_interface.h} to
|
||
describe, in a portable way, the C representation of prolog terms.
|
||
The user should write is programs using this macros to ensure portability of
|
||
code across different versions of YAP.
|
||
|
||
|
||
The more important typedef is @var{Term} which is used to denote the type of a
|
||
prolog term.
|
||
|
||
Terms, from a point of view of the C-programmer, can be classified as
|
||
follows
|
||
@table @i
|
||
@item uninstantiated variables
|
||
@item instantiated variables
|
||
@item integers
|
||
@item floating-point numbers
|
||
@item database references
|
||
@item atoms
|
||
@item pairs (lists)
|
||
@item compound terms
|
||
@end table
|
||
|
||
Before trying to find out the kind of a term, the C-programmer should insure
|
||
it is not an instantiated variable using the interface primitive
|
||
@example
|
||
Term Deref(Term)
|
||
@end example
|
||
@noindent
|
||
which follows a possibly empty chain of instantiations and returns a term which
|
||
is not an instantiated variable.
|
||
|
||
Having done so, the primitive
|
||
@example
|
||
Bool IsVarTerm(Term)
|
||
@end example
|
||
@noindent
|
||
returns true iff its argument is an uninstantiated variable. Conversely the
|
||
primitive
|
||
@example
|
||
Bool IsGroundTerm(Term)
|
||
@end example
|
||
@noindent
|
||
returns true iff its argument is not a variable.
|
||
|
||
|
||
The user can create a new uninstantiated variable using the primitive
|
||
@example
|
||
Term MkVarTerm()
|
||
@end example
|
||
|
||
|
||
The following primitives can be used to discriminate among the different kinds
|
||
of non-variable terms:
|
||
@example
|
||
Bool IsIntTerm(Term)
|
||
Bool IsFloatTerm(Term)
|
||
Bool IsDbRefTerm(Term)
|
||
Bool IsAtomTerm(Term)
|
||
Bool IsPairTerm(Term)
|
||
Bool IsApplTerm(Term)
|
||
@end example
|
||
@noindent
|
||
@strong{Important Note:} when used on variables the primitives above
|
||
will return an unpredictable result.
|
||
|
||
|
||
The following primitives are provided for creating an integer term from an
|
||
integer and to access the value of an integer term.
|
||
@example
|
||
Term MkIntTerm(Int)
|
||
Int IntOfTerm(Term)
|
||
@end example
|
||
@noindent
|
||
where @code{Int} is a typedef for the C integer type appropriate for the
|
||
machine or compiler in question (normally a 32 bit integer). Note that
|
||
the size of the allowed integers is implementation dependent but is always
|
||
greater or equal to 24 bits.
|
||
|
||
|
||
The two following primitives play a similar role for floating-point terms
|
||
@example
|
||
Term MkFloatTerm(flt)
|
||
flt FloatOfTerm(Term)
|
||
@end example
|
||
@noindent
|
||
where @code{flt} is a typedef for the appropriate C floating point type.
|
||
|
||
|
||
No primitives are supplied to users for manipulating data base
|
||
references.
|
||
|
||
A special typedef @code{Atom} is provided to describe prolog @i{atoms} and the
|
||
two following primitives can be used to manipulate atom terms
|
||
@example
|
||
Term MkAtomTerm(Atom)
|
||
Atom AtomOfTerm(Term)
|
||
@end example
|
||
@noindent
|
||
The two following primitives are available for associating atoms with their
|
||
names
|
||
@example
|
||
Atom LookupAtom(char *)
|
||
Atom FullLookupAtom(char *)
|
||
char* AtomName(Atom)
|
||
@end example
|
||
The function @code{LookupAtom} looks up an atom in the standard hash
|
||
table. The function @code{FullLookupAtom} will also search if the atom
|
||
had been "hidden".
|
||
|
||
|
||
A @i{pair} is a Prolog term which consists of a pair of prolog terms designated
|
||
as the @i{head} and the @i{tail} of the term. The following primitives can
|
||
be used to manipulate pairs
|
||
@example
|
||
Term MkPairTerm(Term Head, Term Tail)
|
||
Term HeadOfTerm(Term)
|
||
Term TailOfTerm(Term)
|
||
@end example
|
||
|
||
A @i{compound} term consists of a @i{functor} and a sequence of terms with
|
||
length equal to the @i{arity} of the functor. A functor, described in C by
|
||
the typedef @code{Functor}, consists of an atom and of an integer.
|
||
The following primitives were designed to manipulate compound terms and
|
||
functors
|
||
@example
|
||
Term MkApplTerm(Functor f, int n, Term[] args)
|
||
Functor FunctorOfTerm(Term)
|
||
Term ArgOfTerm(int argno,Term t)
|
||
Functor MkFunctor(Atom a,int arity)
|
||
Atom NameOfFunctor(Functor)
|
||
Int ArityOfFunctor(Functor)
|
||
@end example
|
||
@noindent
|
||
where @code{args} should be an array of @code{n} terms with @code{n} equal to the
|
||
arity of the functor, and @code{argno} should be greater or equal to 1 and less
|
||
or equal to the arity of the functor.
|
||
|
||
@strong{Note:} all the above primitives returning terms ensure that the
|
||
result is @i{dereferenced}, i.e. that it is not an instantiated variable.
|
||
|
||
@node Unifying Terms, Manipulating Strings, Manipulating Terms, C-Interface
|
||
@section Unification
|
||
|
||
The following routine is provided for attempting the unification of two
|
||
prolog terms
|
||
@example
|
||
Int unify(Term a, Term b)
|
||
@end example
|
||
@noindent
|
||
which attempts to unify the terms pointed to by @code{a} and @code{b} returning
|
||
a non-zero value if the unification succeeds and zero otherwise.
|
||
|
||
@node Manipulating Strings, Memory Allocation, Unifying Terms, C-Interface
|
||
@section Strings
|
||
|
||
The YAP C-interface now includes an utility routine to copy a string
|
||
represented as a list of a character codes to a previously allocated buffer
|
||
@example
|
||
int StringToBuffer(Term String, char *buf, unsigned int bufsize)
|
||
@end example
|
||
@noindent
|
||
The routine copies the list of character codes @code{String} to a
|
||
previously allocated buffer @code{buf}. The string including a
|
||
terminating null character must fit in @code{bufsize} characters,
|
||
otherwise the routine will simply fail. The @code{StringToBuffer}
|
||
routine fails and generates an exception if @code{String} is not a valid
|
||
string.
|
||
|
||
The C-interface also includes utility routines to do the reverse, that
|
||
is, to copy a from a buffer to a list of character codes or to a list of
|
||
character atomsr
|
||
@example
|
||
Term BufferToString(char *buf)
|
||
Term BufferToAtomList(char *buf)
|
||
@end example
|
||
@noindent
|
||
The user-provided string must include a terminating null character.
|
||
|
||
@node Memory Allocation, Controlling Streams, Manipulating Strings, C-Interface
|
||
@section Memory Allocation
|
||
|
||
The next routine can be used to ask space from the Prolog data-base:
|
||
@example
|
||
void *AllocSpaceFromYap(int size)
|
||
@end example
|
||
@noindent
|
||
The routine returns a pointer to a buffer allocated from the code area,
|
||
or @code{NULL} if no space was available.
|
||
|
||
This Space can be released by using:
|
||
@example
|
||
void FreeSpaceFromYap(void *buf)
|
||
@end example
|
||
@noindent
|
||
The routine releases a buffer allocated from the code area. The system
|
||
may crash if @code{buf} is not a valid pointer to a buffer in the code
|
||
area.
|
||
|
||
@node Controlling Streams, Calling Yap From C, Memory Allocation, C-Interface
|
||
@section Controlling Yap Streams from @code{C}
|
||
|
||
The C-Interface also provides the C-application with a measure of
|
||
control over the Yap Input/Output system. The first routine allows one
|
||
to find a file number given a current stream:
|
||
@example
|
||
int YapStreamToFileNo(Term stream)
|
||
@end example
|
||
@noindent
|
||
This function gives the file descriptor for a currently available
|
||
stream. Note that null streams and in memory streams do not have
|
||
corresponding open streams, so the routine will return a
|
||
negative. Moreover, Yap will not be aware of any direct operations on
|
||
this stream, so information on, say, current stream position, may become
|
||
stale.
|
||
|
||
A second routine that is sometimes useful is:
|
||
@example
|
||
void YapCloseAllOpenStreams(void)
|
||
@end example
|
||
@noindent
|
||
This routine closes the Yap Input/Output system except for the first
|
||
three streams, that are always associated with the three standard Unix
|
||
streams. It is most useful if you are doing @code{fork()}.
|
||
|
||
The next routine allows a currently open file to become a stream. The
|
||
routine receives as arguments a file descriptor, the true file name as a
|
||
string, an atom with the yser name, and a set of flags:
|
||
@example
|
||
void YapOpenStream(void *FD, char *true, Term t, int flags)
|
||
@end example
|
||
@noindent
|
||
The available flags are @code{YAP_INPUT_STREAM},
|
||
@code{YAP_OUTPUT_STREAM}, @code{YAP_APPEND_STREAM},
|
||
@code{YAP_PIPE_STREAM}, @code{YAP_TTY_STREAM}, @code{YAP_POPEN_STREAM},
|
||
@code{YAP_BINARY_STREAM}, and @code{YAP_SEEKABLE_STREAM}. By default, the
|
||
stream is supposed to be at position 0.
|
||
|
||
@node Calling Yap From C, Writing C, Controlling Streams, C-Interface
|
||
@section From @code{C} back to Prolog
|
||
|
||
Newer versions of YAP allow for calling the Prolog interpreter from
|
||
@code{C}. One must first construct a goal @code{G}, and then it is
|
||
sufficient to perform:
|
||
@example
|
||
Int YapCallProlog(Term G)
|
||
@end example
|
||
@noindent
|
||
the result will be @code{0}, if the goal failed, or @code{1}, if the
|
||
goal succeeded. In this case, the variables in @var{G} will store the
|
||
values they have been unified with. Execution only proceeds until
|
||
finding the first solution to the goal, but you can call
|
||
@code{findall/3} or friends if you need all the solutions.
|
||
|
||
@node Writing C, Loading Objects, Calling Yap From C, C-Interface
|
||
@section Writing predicates in C
|
||
|
||
We will distinguish two kinds of predicates:
|
||
@table @i
|
||
@item @i{deterministic} predicates which either fail or succeed but are not
|
||
backtrackable, like the one in the introduction;
|
||
@item @i{backtrackable}
|
||
predicates which can succeed more than once.
|
||
@end table
|
||
|
||
The first kind of predicates should be implemented as a C function with
|
||
no arguments which should return zero if the predicate fails and a
|
||
non-zero value otherwise. The predicate should be declared to
|
||
YAP, in the initialization routine, with a call to
|
||
@example
|
||
void UserCPredicate(char *name, int *fn(), int arity);
|
||
@end example
|
||
@noindent
|
||
where @code{name} is the name of the predicate, @code{fn} is the C function
|
||
implementing the predicate and @code{arity} is its arity.
|
||
|
||
For the second kind of predicates we need two C functions. The first one
|
||
which is called when the predicate is first activated, and the second one
|
||
to be called on backtracking to provide (possibly) other solutions. Note
|
||
also that we normally also need to preserve some information to find out
|
||
the next solution.
|
||
|
||
In fact the role of the two functions can be better understood from the
|
||
following prolog definition
|
||
@example
|
||
p :- start.
|
||
p :- repeat,
|
||
continue.
|
||
@end example
|
||
@noindent
|
||
where @code{start} and @code{continue} correspond to the two C functions
|
||
described above.
|
||
|
||
|
||
As an example we will consider implementing in C a predicate @code{n100(N)}
|
||
which, when called with an instantiated argument should succeed if that
|
||
argument is a numeral less or equal to 100, and, when called with an
|
||
uninstantiated argument, should provide, by backtracking, all the positive
|
||
integers less or equal to 100.
|
||
|
||
To do that we first declare a structure, which can only consist
|
||
of prolog terms, containing the information to be preserved on backtracking
|
||
and a pointer variable to a structure of that type.
|
||
|
||
@example
|
||
typedef struct @{
|
||
Term next_solution; /* the next solution */
|
||
@} n100_data_type;
|
||
|
||
n100_data_type *n100_data;
|
||
@end example
|
||
|
||
We now write the @code{C} function to handle the first call:
|
||
|
||
@example
|
||
static int start_n100()
|
||
@{
|
||
Term t = ARG1;
|
||
PRESERVE_DATA(n100_data,n100_data_type);
|
||
if(IsVarTerm(t)) @{
|
||
n100_data->next_solution = MkIntTerm(0);
|
||
return(continue_n100());
|
||
@}
|
||
if(!IsIntTerm(t) || IntOfTerm(t)<0 || IntOfTerm(t)>100) @{
|
||
cut_fail();
|
||
@} else @{
|
||
cut_succeed();
|
||
@}
|
||
@}
|
||
|
||
@end example
|
||
|
||
The routine starts by getting the dereference value of the argument.
|
||
The call to @code{PRESERVE_DATA} is used to initialize the memory which will
|
||
hold the information to be preserved across backtracking.
|
||
|
||
If the argument of the predicate is a variable, the routine initializes the
|
||
structure to be preserved across backtracking with the information
|
||
required to provide the next solution, and exits by calling @code{
|
||
continue_n100} to provide that solution.
|
||
|
||
If the argument was not a variable, the routine then checks if it was
|
||
an integer, and if so, if its value is positive and less than 100. In that case
|
||
it exits, denoting success, with @code{cut_succeed}, or otherwise exits with
|
||
@code{cut_fail} denoting failure.
|
||
|
||
The reason for using for using the macros @code{cut_succeed} and @code{cut_fail}
|
||
instead of just returning a non-zero value in the first case, and zero in the
|
||
second case, is that otherwise, if backtracking occurred later, the routine
|
||
@code{continue_n100} would be called to provide additional solutions.
|
||
|
||
The code required for the second function is
|
||
@example
|
||
static int continue_n100()
|
||
@{
|
||
int n;
|
||
Term t;
|
||
Term sol = ARG1;
|
||
PRESERVED_DATA(n100_data,n100_data_type);
|
||
n = IntOfTerm(n100_data->next_solution);
|
||
if( n == 100) @{
|
||
t = MkIntTerm(n);
|
||
unify(&sol,&t);
|
||
cut_succeed();
|
||
@}
|
||
else @{
|
||
unify(&sol,&(n100_data->next_solution));
|
||
n100_data->next_solution = MkIntTerm(n+1);
|
||
return(1);
|
||
@}
|
||
@}
|
||
@end example
|
||
|
||
Note that again the macro @code{PRESERVED_DATA} is used at the beginning of
|
||
the function to access the data preserved from the previous solution.
|
||
Then it checks if the last solution was found and in that case exits
|
||
with @code{cut_succeed} in order to cut any further backtracking. If this
|
||
is not the last solution then we save the value for the next solution in
|
||
the data structure and exit normally with 1 denoting success. Note also
|
||
that in any of the two cases we use the function @code{unify} to bind the
|
||
argument of the call to the value saved in @code{
|
||
n100_state->next_solution}.
|
||
|
||
|
||
Note also that the only correct way to signal failure in a backtrackable
|
||
predicate is to use the @code{cut_fail} macro.
|
||
|
||
Backtrackable predicates should be declared to YAP, in a way
|
||
similar to what happened with deterministic ones, but using instead a
|
||
call to
|
||
@example
|
||
void UserBackCPredicate(char *name,
|
||
int *init(), int *cont(), int arity, int sizeof);
|
||
@end example
|
||
@noindent
|
||
where @code{name} is a string with the name of the predicate, @code{init} and
|
||
@code{cont} are the C functions used to start and continue the execution of
|
||
the predicate, and @code{arity} is the predicate arity.
|
||
|
||
@node Loading Objects, Sav&Rest, Writing C, C-Interface
|
||
@section Loading Object Files
|
||
|
||
The primitive predicate
|
||
@example
|
||
load_foreign_files(@var{Files},@var{Libs},@var{InitRoutine})
|
||
@end example
|
||
@noindent
|
||
should be used, from inside YAP, to load object files produced by the C
|
||
compiler. The argument @var{ObjectFiles} should be a list of atoms
|
||
specifying the object files to load, @var{Libs} is a list (possibly
|
||
empty) of libraries to be passed to the unix loader (@code{ld}) and
|
||
InitRoutine is the name of the C routine (to be called after the files
|
||
are loaded) to perform the necessary declarations to YAP of the
|
||
predicates defined in the files.
|
||
|
||
YAP will search for @var{ObjectFiles} in the current directory first. If
|
||
it cannot find them it will search for the files using the environment
|
||
variable @code{YAPLIBDIR}, if defined, or in the default library.
|
||
|
||
In a.out systems YAP by default only reserves a fixed amount of memory
|
||
for object code (64 Kbytes in the current version). Should this size
|
||
prove inadequate the flag @code{-c n} can be passed to YAP (in the
|
||
command line invoking YAP) to force the allocation of @code{n} Kbytes.
|
||
|
||
@node Sav&Rest, Yap4 Notes, Loading Objects, C-Interface
|
||
@section Saving and Restoring
|
||
|
||
@comment The primitive predicates @code{save} and @code{restore} will save and restore
|
||
@comment object code loaded with @code{load_foreign_files}. However, the values of
|
||
@comment any non-static data created by the C files loaded will not be saved nor
|
||
@comment restored.
|
||
|
||
Yap4 currently does not support @code{save} and @code{restore} for object code
|
||
loaded with @code{load_foreign_files}. We plan to support save and restore
|
||
in future releases of Yap.
|
||
|
||
@node Yap4 Notes, , Sav&Rest, C-Interface
|
||
@section Changes to the C-Interface in Yap4
|
||
|
||
Yap4 includes several changes over the previous @code{load_foreign_files}
|
||
interface. These changes were required to support the new binary code
|
||
formats, such as ELF used in Solaris2 and Linux.
|
||
@itemize @bullet
|
||
@item Access to elements in the new interface always goes through
|
||
@emph{functions}. This includes access to the argument registers,
|
||
@code{ARG1} to @code{ARG16}. This change breaks code such as
|
||
@code{unify(&ARG1,&t)}:
|
||
@example
|
||
@{
|
||
unify(ARG1, t);
|
||
@}
|
||
@end example
|
||
|
||
@item @code{cut_fail()} and @code{cut_succeed()} are now functions.
|
||
|
||
@item The use of @code{Deref} is deprecated. All functions that return
|
||
Prolog terms, including the ones that access arguments, already
|
||
dereferenciate their arguments.
|
||
|
||
@item Space allocated with PRESERVE_DATA is ignored by garbage
|
||
collection and stack shifting. As a result, any pointers to a Prolog
|
||
stack object, including some terms, may be corrupted after garbage
|
||
collection or stack shifting. Prolog terms should instead be stored as
|
||
arguments to the backtrackable procedure.
|
||
|
||
@end itemize
|
||
|
||
@node YapLibrary, Compatibility, C-Interface, Top
|
||
@chapter Using YAP as a Library
|
||
|
||
YAP can be used as a library to be called from other
|
||
programs. To do so, you must first create the YAP library:
|
||
@example
|
||
make library
|
||
make install_library
|
||
@end example
|
||
This will install a file @code{libyap.a} in @var{LIBDIR} and the Prolog
|
||
headers in @var{INCLUDEDIR}. The library contains all the functionality
|
||
available in YAP, except the foreign function loader and for
|
||
@code{Yap}'s startup routines.
|
||
|
||
To actually use this library you must follow a five step process:
|
||
|
||
@enumerate
|
||
@item
|
||
You must initialise the YAP environment. A single function,
|
||
@code{YapFastInit} asks for a contiguous chunk in your memory space, fills
|
||
it in with the data-base, and sets up YAP's stacks and
|
||
execution registers. You can use a saved space from a standard system by
|
||
calling @code{save_program/1}.
|
||
|
||
@item You then have to prepare a query to give to
|
||
YAP. A query is a Prolog term, and you just have to use the same
|
||
functions that are available in the C-interface.
|
||
|
||
@item You can then use @code{YapRunGoal(query)} to actually evaluate your
|
||
query. The argument is the query term @code{query}, and the result is 1
|
||
if the query succeeded, and 0 if it failed.
|
||
|
||
@item You can use the term destructor functions to check how
|
||
arguments were instantiated.
|
||
|
||
@item If you want extra solutions, you can use
|
||
@code{YapRestartGoal()} to obtain the next solution.
|
||
|
||
@end enumerate
|
||
|
||
The next program shows how to use this system. We assume the saved
|
||
program contains two facts for the procedure @t{b}:
|
||
|
||
@example
|
||
@cartouche
|
||
#include <stdio.h>
|
||
#include "Yap/c_interface.h"
|
||
|
||
|
||
int
|
||
main(int argc, char *argv[]) @{
|
||
if (YapFastInit("saved_state") == YAP_BOOT_FROM_SAVED_ERROR)
|
||
exit(1);
|
||
if (YapRunGoal(MkAtomTerm(LookupAtom("do")))) @{
|
||
printf("Success\n");
|
||
while (YapRestartGoal())
|
||
printf("Success\n");
|
||
@}
|
||
printf("NO\n");
|
||
@}
|
||
@end cartouche
|
||
@end example
|
||
|
||
The program first initialises YAP, calls the query for the
|
||
first time and succeeds, and then backtracks twice. The first time
|
||
backtracking succeeds, the second it fails and exits.
|
||
|
||
To compile this program it should be sufficient to do:
|
||
|
||
@example
|
||
cc -o exem -I../Yap4.3.0 test.c -lyap -lreadline -lm
|
||
@end example
|
||
|
||
You may need to adjust the libraries and library paths depending on the
|
||
Operating System and your installation of Yap.
|
||
|
||
Note that Yap4.3.0 provides the first version of the interface. The
|
||
interface may change and improve in the future.
|
||
|
||
The following C-functions are available from Yap:
|
||
|
||
@itemize @bullet
|
||
@item YapCompileClause(@code{Term} @var{Clause})
|
||
@findex YapCompileClause/1
|
||
Compile the Prolog term @var{Clause} and assert it as the last clause
|
||
for the corresponding procedure.
|
||
|
||
@item @code{int} YapContinueGoal(@code{void})
|
||
@findex YapContinueGoal/0
|
||
Continue execution from the point where it stopped.
|
||
|
||
@item @code{void} YapError(@code{char *} @var{error_description})
|
||
@findex YapError/1
|
||
Generate an YAP System Error with description given by the string
|
||
@var{error_description}.
|
||
|
||
@item @code{void} YapExit(@code{int} @var{exit_code})
|
||
@findex YapExit/1
|
||
Exit YAP immediately. The argument @var{exit_code} gives the error code
|
||
and is supposed to be 0 after successful execution in Unix and Unix-like
|
||
systems.
|
||
|
||
@item @code{Term} YapGetValue(@code{Atom} @var{at})
|
||
@findex YapGetValue/1
|
||
Return the term @var{value} associated with the atom @var{at}. If no
|
||
such term exists the function will return the empty list.
|
||
|
||
@item YapFastInit(@code{char *} @var{SavedState})
|
||
@findex YapFastInit/1
|
||
Initialise a copy of YAP from @var{SavedState}. The copy is
|
||
monolithic and currently must be loaded at the same address where it was
|
||
saved. @code{YapFastInit} is a simpler version of @code{YapInit}.
|
||
|
||
@item YapInit(@code{char *} @var{SavedState}, @code{int}
|
||
@var{HeapSize}, @code{int} @var{StackSize}, @code{int}
|
||
@var{TrailSize}, @code{int} @var{NumberofWorkers}, @code{int}
|
||
@var{SchedulerLoop}, @code{int} @var{DelayedReleaseLoad}, @code{int}
|
||
@var{argc}, @code{char **} @var{argv})
|
||
@findex YapInit/9
|
||
Initialise YAP. In the future the arguments as a single @code{C}
|
||
structure.
|
||
|
||
If @var{SavedState} is not NULL, try to open and restore the file
|
||
@var{SavedState}. Initially YAP will search in the current directory. If
|
||
the saved state does not exist in the current directory YAP will use
|
||
either the default library directory or the directory given by the
|
||
environment variable @code{YAPLIBDIR}. Note that currently
|
||
the saved state must be loaded at the same address where it was saved.
|
||
|
||
If @var{HeapSize} is different from 0 use @var{HeapSize} as the minimum
|
||
size of the Heap (or code space). If @var{StackSize} is different from 0
|
||
use @var{HeapSize} as the minimum size for the Stacks. If
|
||
@var{TrailSize} is different from 0 use @var{TrailSize} as the minimum
|
||
size for the Trails.
|
||
|
||
The @var{NumberofWorkers}, @var{NumberofWorkers}, and
|
||
@var{DelayedReleaseLoad} are only of interest to the or-parallel system.
|
||
|
||
The argument count @var{argc} and string of arguments @var{argv}
|
||
arguments are to be passed to user programs as the arguments used to
|
||
call YAP.
|
||
|
||
@item @code{void} YapPutValue(@code{Atom} @var{at}, @code{Term} @var{value})
|
||
@findex YapPutValue/2
|
||
Associate the term @var{value} with the atom @var{at}. The term
|
||
@var{value} must be a constant. This functionality is used by YAP as a
|
||
simple way for controlling and communicating with the Prolog run-time.
|
||
|
||
@item @code{Term} YapRead(@code{int (*)(void)} @var{GetC})
|
||
@findex YapRead/1
|
||
Parse a Term using the function @var{GetC} to input characters.
|
||
|
||
@item @code{int} YapRunGoal(@code{Term} @var{Goal})
|
||
@findex YapRunGoal/1
|
||
Execute query @var{Goal} and return 1 if the query succeeds, and
|
||
0 otherwise.
|
||
|
||
@item @code{int} YapRestartGoal(@code{void})
|
||
@findex YapRestartGoal/0
|
||
Look for the next solution to the current query by forcing YAP to backtrack.
|
||
|
||
@item @code{int} YapReset(@code{void})
|
||
@findex YapReset/0
|
||
Reset execution environment (similar to the @code{abort/0}
|
||
builtin). This is useful when you want to start a new query before
|
||
asking all solutions to the previous query.
|
||
|
||
@item @code{void} YapWrite(@code{Term} @var{t}, @code{void (*)(int)}
|
||
@var{PutC}, @code{int} @var{flags})
|
||
@findex YapRead/1
|
||
Write a Term @var{t} using the function @var{PutC} to output
|
||
characters. The term is written according to a mask of the following
|
||
flags in the @code{flag} argument: @code{YAP_WRITE_QUOTED},
|
||
@code{YAP_WRITE_HANDLE_VARS}, and @code{YAP_WRITE_IGNORE_OPS}.
|
||
|
||
@item @code{void} YapInitConsult(@code{int} @var{mode}, @code{char *} @var{filename})
|
||
@findex YapInitConsult/2
|
||
Enter consult mode on file @var{filename}. This mode maintains a few
|
||
data-structures internally, for instanc to know whether a predicate
|
||
before or not. It is still possible to execute goals in consult mode.
|
||
|
||
If @var{mode} is @code{TRUE} the file will be reconsulted, otherwise
|
||
just consulted. In practice, this function is most useful for
|
||
bootstraping Prolog, as otherwise one may call the Prolog predicate
|
||
@code{compile/1} or @code{consult/1} to do compilation.
|
||
|
||
Note that it is up to the user to open the file @var{filename}. The
|
||
@code{YapInitConsult} function only uses the file name for internal
|
||
bookkeeping.
|
||
|
||
@item @code{void} YapEndConsult(@code{void})
|
||
@findex YapEndConsult/0
|
||
Finish consult mode.
|
||
|
||
@end itemize
|
||
|
||
Some observations:
|
||
|
||
@itemize @bullet
|
||
@item The system will core dump if you try to load the saved state in a
|
||
different address from where it was made. This may be a problem if
|
||
your program uses @code{mmap}. This problem will be addressed in future
|
||
versions of YAP.
|
||
|
||
@item Currently, the YAP library will pollute the name
|
||
space for your program.
|
||
|
||
@item The initial library includes the complete YAP system. In
|
||
the future we plan to split this library into several smaller libraries
|
||
(e.g., if you do not want to perform I/O).
|
||
|
||
@item You can generate your own saved states. Look at the
|
||
@code{boot.yap} and @code{init.yap} files.
|
||
|
||
@end itemize
|
||
|
||
@node Compatibility, Operators, YapLibrary, Top
|
||
@chapter Compatibility with Other Prolog systems
|
||
|
||
YAP has been designed to be as compatible as possible with
|
||
other Prolog systems, and initially with C-Prolog. More recent work on
|
||
YAP has included features initially proposed for the Quintus
|
||
and SICStus Prolog systems.
|
||
|
||
Developments since @code{Yap4.1.6} we have striven at making
|
||
YAP compatible with the ISO-Prolog standard.
|
||
|
||
@menu
|
||
* C-Prolog:: Compatibility with the C-Prolog interpreter
|
||
* SICStus Prolog:: Compatibility with the SICStus Prolog system
|
||
* ISO Prolog:: Compatibility with the ISO Prolog standard
|
||
@end menu
|
||
|
||
@node C-Prolog, SICStus Prolog, , Compatibility
|
||
@section Compatibility with the C-Prolog interpreter
|
||
|
||
@menu
|
||
C-Prolog Compatibility
|
||
* Major Differences with C-Prolog:: Major Differences between YAP and C-Prolog
|
||
* Fully C-Prolog Compatible:: Yap predicates fully compatible with
|
||
C-Prolog
|
||
* Not Strictly C-Prolog Compatible:: Yap predicates not strictly as C-Prolog
|
||
* Not in C-Prolog:: Yap predicates not available in C-Prolog
|
||
* Not in YAP:: C-Prolog predicates not available in YAP
|
||
@end menu
|
||
|
||
@node Major Differences with C-Prolog, Fully C-Prolog Compatible, , C-Prolog
|
||
@subsection Major Differences between YAP and C-Prolog.
|
||
|
||
YAP includes several extensions over the original C-Prolog system. Even
|
||
so, most C-Prolog programs should run under YAP without changes.
|
||
|
||
The most important difference between YAP and C-Prolog is that, being
|
||
YAP a compiler, some changes should be made if predicates such as
|
||
@code{assert}, @code{clause} and @code{retract} are used. First
|
||
predicates which will change during execution should be declared as
|
||
@code{dynamic} by using commands like:
|
||
|
||
@example
|
||
:- dynamic f/n.
|
||
@end example
|
||
|
||
@noindent where @code{f} is the predicate name and n is the arity of the
|
||
predicate. Note that several such predicates can be declared in a
|
||
single command:
|
||
@example
|
||
:- dynamic f/2, ..., g/1.
|
||
@end example
|
||
|
||
Primitive predicates such as @code{retract} apply only to dynamic
|
||
predicates. Finally note that not all the C-Prolog primitive predicates
|
||
are implemented in YAP. They can easily be detected using the
|
||
@code{unknown} system predicate provided by YAP.
|
||
|
||
Last, by default YAP enables character escapes in strings. You can
|
||
disable the special interpretation for the escape character by using:
|
||
@example
|
||
@code{:- yap_flag(character_escapes,off).}
|
||
@end example
|
||
@noindent
|
||
or by using:
|
||
@example
|
||
@code{:- yap_flag(language,cprolog).}
|
||
@end example
|
||
|
||
@node Fully C-Prolog Compatible, Not Strictly C-Prolog Compatible, Major Differences with C-Prolog, C-Prolog
|
||
@subsection Yap predicates fully compatible with C-Prolog
|
||
|
||
These are the Prolog built-ins that are fully compatible in both
|
||
C-Prolog and YAP:
|
||
|
||
@printindex cy
|
||
|
||
@node Not Strictly C-Prolog Compatible, Not in C-Prolog, Fully C-Prolog Compatible, C-Prolog
|
||
@subsection Yap predicates not strictly compatible with C-Prolog
|
||
|
||
These are YAP built-ins that are also available in C-Prolog, but
|
||
that are not fully compatible:
|
||
|
||
@printindex ca
|
||
|
||
@node Not in C-Prolog, Not in YAP, Not Strictly C-Prolog Compatible, C-Prolog
|
||
@subsection Yap predicates not available in C-Prolog
|
||
|
||
These are YAP built-ins not available in C-Prolog.
|
||
|
||
@printindex cn
|
||
|
||
@node Not in YAP, , Not in C-Prolog, C-Prolog
|
||
@subsection Yap predicates not available in C-Prolog
|
||
|
||
These are C-Prolog built-ins not available in YAP:
|
||
|
||
@table @code
|
||
@item notrace
|
||
Switches off the debugger and stops tracing.
|
||
|
||
@item trace
|
||
Switches on the debugger and starts tracing.
|
||
|
||
@item 'LC'
|
||
The following Prolog text uses lower case letters.
|
||
|
||
@item 'NOLC'
|
||
The following Prolog text uses upper case letters only.
|
||
@end table
|
||
|
||
@node SICStus Prolog, ISO Prolog, C-Prolog, Compatibility
|
||
@section Compatibility with the Quintus and SICStus Prolog systems
|
||
|
||
The Quintus Prolog system was the first Prolog compiler to use Warren's
|
||
Abstract Machine. This system was very influential in the Prolog
|
||
community. Quintus Prolog implemented compilation into an abstract
|
||
machine code, which was then emulated. Quintus Prolog also included
|
||
several new built-ins, an extensive library, and in later releases a
|
||
garbage collector. The SICStus Prolog system, developed at SICS (Swedish
|
||
Institute of Computer Science), is an emulator based Prolog system
|
||
largely compatible with Quintus Prolog. SICStus Prolog has evolved
|
||
through several versions. The current version includes several
|
||
extensions, such as an object implementation, co-routining, and
|
||
constraints.
|
||
|
||
Recent work in YAP has been influenced by work in Quintus and
|
||
SICStus Prolog. Wherever possible, we have tried to make YAP
|
||
compatible with recent versions of these systems, and specifically of
|
||
SICStus Prolog. You should use
|
||
@example
|
||
:- yap_flag(language, sicstus).
|
||
@end example
|
||
@noindent
|
||
for maximum compatibility with SICStus Prolog.
|
||
|
||
@menu
|
||
SICStus Compatibility
|
||
* Major Differences with SICStus:: Major Differences between YAP and SICStus Prolog
|
||
* Fully SICStus Compatible:: Yap predicates fully compatible with
|
||
SICStus Prolog
|
||
* Not Strictly SICStus Compatible:: Yap predicates not strictly as
|
||
SICStus Prolog
|
||
* Not in SICstus Prolog:: Yap predicates not available in SICStus Prolog
|
||
@end menu
|
||
|
||
@node Major Differences with SICStus, Fully SICStus Compatible, , SICStus Prolog
|
||
@subsection Major Differences between YAP and SICStus Prolog.
|
||
|
||
Both YAP and SICStus Prolog obey the Edinburgh Syntax and are based on
|
||
the WAM. Even so, there are quite a few important differences:
|
||
|
||
@itemize @bullet
|
||
@item Differently from SICStus Prolog, YAP does not have a
|
||
notion of interpreted code. All code in YAP is compiled.
|
||
|
||
@item YAP does not support an intermediate byte-code
|
||
representation, so the @code{fcompile/1} and @code{load/1} built-ins are
|
||
not available in YAP.
|
||
|
||
@item YAP implements escape sequences as in the ISO standard. SICStus
|
||
Prolog implements Unix-like escape sequences.
|
||
|
||
@item YAP implements @code{initialization/1} as per the ISO
|
||
standard. Use @code{prolog_initialization/1} for the SICStus Prolog
|
||
compatible built-in.
|
||
|
||
@item YAP does not implement the tabbing primitives in
|
||
@code{format/2} and @code{format/3}.
|
||
|
||
@item Prolog flags are different in SICStus Prolog and in YAP.
|
||
|
||
@item The SICStus Prolog @code{on_exception/3} and
|
||
@code{raise_exception} built-ins correspond to the ISO builtins
|
||
@code{catch/3} and @code{throw/1}.
|
||
|
||
@item The following SICStus Prolog v3 built-ins are not (currently)
|
||
implemented in YAP (note that this is only a partial list):
|
||
@code{call_cleanup/1}, @code{file_search_path/2},
|
||
@code{stream_interrupt/3}, @code{reinitialize/0}, @code{help/0},
|
||
@code{help/1}, @code{trimcore/0}, @code{load_files/1},
|
||
@code{load_files/2}, and @code{require/1}.
|
||
|
||
The previous list is incomplete. We also cannot guarantee full
|
||
compatibility for other built-ins (although we will try to address any
|
||
such incompatibilities). Last, SICStus Prolog is an evolving system, so
|
||
one can be expect new incompatibilities to be introduced in future
|
||
releases of SICStus Prolog.
|
||
|
||
@item YAP allows asserting and abolishing static code during
|
||
execution through the @code{assert_static/1} and @code{abolish/1}
|
||
builtins. This is not allowed in Quintus Prolog or SICStus Prolog.
|
||
|
||
@item YAP implements rational trees and co-routining but they
|
||
are not included by default in the system. You must enable these
|
||
extensions when compiling the system.
|
||
|
||
@item YAP does not currently implement constraints.
|
||
|
||
@item The socket predicates, although designed to be compatible with
|
||
SICStus Prolog, are built-ins, not library predicates, in YAP.
|
||
|
||
@item This list is incomplete.
|
||
|
||
@end itemize
|
||
|
||
The following differences only exist if the @code{language} flag is set
|
||
to @code{yap} (the default):
|
||
|
||
@itemize @bullet
|
||
@item The @code{consult/1} predicate in YAP follows C-Prolog
|
||
semantics. That is, it adds clauses to the data base, even for
|
||
preexisting procedures. This is different from @code{consult/1} in
|
||
SICStus Prolog.
|
||
|
||
@cindex update semantics
|
||
@item By default, the data-base in YAP follows "immediate update
|
||
semantics", instead of "logical update semantics", as Quintus Prolog or
|
||
SICStus Prolog do. The difference is depicted in the next example:
|
||
|
||
@example
|
||
:- dynamic a/1.
|
||
|
||
?- assert(a(1)).
|
||
|
||
?- retract(a(X)), X1 is X +1, assertz(a(X)).
|
||
@end example
|
||
With immediate semantics, new clauses or entries to the data base are
|
||
visible in backtracking. In this example, the first call to
|
||
@code{retract/1} will succeed. The call to @strong{assertz/1} will then
|
||
succeed. On backtracking, the system will retry
|
||
@code{retract/1}. Because the newly asserted goal is visible to
|
||
@code{retract/1}, it can be retracted from the data base, and
|
||
@code{retract(a(X))} will succeed again. The process will continue
|
||
generating integers for ever. Immediate semantics were used in C-Prolog.
|
||
|
||
With logical update semantics, any additions or deletions of clauses
|
||
for a goal @emph{will not affect previous activations of the
|
||
goal}. In the example, the call to @code{assertz/1} will not see the
|
||
update performed by the @code{assertz/1}, and the query will have a
|
||
single solution.
|
||
|
||
Calling @code{yap_flag(update_semantics,logical)} will switch
|
||
YAP to use logical update semantics.
|
||
|
||
@item @code{dynamic/1} is a built-in, not a directive, in YAP.
|
||
|
||
@item By default, YAP fails on undefined predicates. To follow default
|
||
SICStus Prolog use:
|
||
@example
|
||
:- yap_flag(unknown,error).
|
||
@end example
|
||
|
||
@item By default, directives in YAP can be called from the top level.
|
||
|
||
@end itemize
|
||
|
||
@node Fully SICStus Compatible, Not Strictly SICStus Compatible, Major Differences with SICStus, SICStus Prolog
|
||
@subsection Yap predicates fully compatible with SICStus Prolog
|
||
|
||
These are the Prolog built-ins that are fully compatible in both SICStus
|
||
Prolog and YAP:
|
||
|
||
@printindex sy
|
||
|
||
@node Not Strictly SICStus Compatible, Not in SICstus Prolog, Fully SICStus Compatible, SICStus Prolog
|
||
@subsection Yap predicates not strictly compatible with SICStus Prolog
|
||
|
||
These are YAP built-ins that are also available in SICStus Prolog, but
|
||
that are not fully compatible:
|
||
|
||
@printindex sa
|
||
|
||
@node Not in SICstus Prolog, , Not Strictly SICStus Compatible, SICStus Prolog
|
||
@subsection Yap predicates not available in SICStus Prolog
|
||
|
||
These are YAP built-ins not available in SICStus Prolog.
|
||
|
||
@printindex sn
|
||
|
||
|
||
@node ISO Prolog, , SICStus Prolog, Compatibility
|
||
@section Compatibility with the ISO Prolog standard
|
||
|
||
The Prolog standard was developed by ISO/IEC JTC1/SC22/WG17, the
|
||
international standardization working group for the programming language
|
||
Prolog. The book "Prolog: The Standard" by Deransart, Ed-Dbali and
|
||
Cervoni gives a complete description of this standard. Development in
|
||
YAP from YAP4.1.6 onwards have striven at making YAP
|
||
compatible with ISO Prolog. As such:
|
||
|
||
@itemize @bullet
|
||
@item YAP now supports all of the built-ins required by the
|
||
ISO-standard, and,
|
||
@item Error-handling is as required by the standard.
|
||
@end itemize
|
||
|
||
YAP by default is not fully ISO standard compliant. You can set the
|
||
@code{language} flag to @code{iso} to obtain very good
|
||
compatibility. Setting this flag changes the following:
|
||
|
||
@itemize @bullet
|
||
@item By default, YAP uses "immediate update semantics" for its
|
||
database, and not "logical update semantics", as per the standard,
|
||
(@pxref{SICStus Prolog}). This affects @code{assert/1},
|
||
@code{retract/1}, and friends.
|
||
|
||
Calling @code{set_prolog_flag(update_semantics,logical)} will switch
|
||
YAP to use logical update semantics.
|
||
|
||
@item By default, YAP implements the @code{atom_chars/2}
|
||
(@pxref{Testing Terms}), and @code{number_chars/2}, (@pxref{Testing
|
||
Terms}), built-ins as per the original Quintus Prolog definition, and
|
||
not as per the ISO definition.
|
||
|
||
Calling @code{set_prolog_flag(to_chars_mode,iso)} will switch
|
||
YAP to use the ISO definition for
|
||
@code{atom_chars/2} and @code{number_chars/2}.
|
||
|
||
@item By default, YAP fails on undefined predicates. To follow the ISO
|
||
Prolog standard use:
|
||
@example
|
||
:- set_prolog_flag(unknown,error).
|
||
@end example
|
||
|
||
@item By default, YAP allows executable goals in directives. In ISO mode
|
||
most directives can only be called from top level (the exceptions are
|
||
@code{set_prolog_flag/2} and @code{op/3}).
|
||
|
||
@item Error checking for meta-calls under ISO Prolog mode is stricter
|
||
than by default.
|
||
|
||
@item The @code{strict_iso} flag automatically enables the ISO Prolog
|
||
standard. This feature should disable all features not present in the
|
||
standard.
|
||
|
||
@end itemize
|
||
|
||
The following incompatibilities between YAP and the ISO standard are
|
||
known to still exist:
|
||
|
||
@itemize @bullet
|
||
|
||
@item Currently, YAP does not handle overflow errors in integer
|
||
operations, and handles floating-point errors only in some
|
||
architectures. Otherwise, YAP follows IEEE arithmetic.
|
||
|
||
@end itemize
|
||
|
||
Please inform the authors on other incompatibilities that may still
|
||
exist.
|
||
|
||
@node Operators, Predicate Index, Compatibility, Top
|
||
@appendix Summary of Yap Predefined Operators
|
||
|
||
|
||
The Prolog syntax caters for operators of three main kinds:
|
||
|
||
@itemize @bullet
|
||
@item
|
||
prefix;
|
||
@item
|
||
infix;
|
||
@item
|
||
postfix.
|
||
@end itemize
|
||
|
||
Each operator has precedence in the range 1 to 1200, and this
|
||
precedence is used to disambiguate expressions where the structure of the
|
||
term denoted is not made explicit using brackets. The operator of higher
|
||
precedence is the main functor.
|
||
|
||
If there are two operators with the highest precedence, the ambiguity
|
||
is solved analyzing the types of the operators. The possible infix types are:
|
||
xfx, xfy, yfx.
|
||
|
||
With an operator of type xfx both sub-expressions must have lower
|
||
precedence than the operator itself, unless they are bracketed (which
|
||
assigns to them zero precedence). With an operator type xfy only the
|
||
left-hand sub-expression must have lower precedence. The opposite happens
|
||
for yfx type.
|
||
|
||
A prefix operator can be of type fx or fy, and a postfix operator, xf, yf.
|
||
The meaning of the notation is analogous to the above.
|
||
@example
|
||
a + b * c
|
||
@end example
|
||
@noindent
|
||
means
|
||
@example
|
||
a + (b * c)
|
||
@end example
|
||
@noindent
|
||
as + and * have the following types and precedences:
|
||
@example
|
||
:-op(500,yfx,'+').
|
||
:-op(400,yfx,'*').
|
||
@end example
|
||
|
||
Now defining
|
||
@example
|
||
:-op(700,xfy,'++').
|
||
:-op(700,xfx,'=:=').
|
||
a ++ b =:= c
|
||
@end example
|
||
@noindent means
|
||
@example
|
||
a ++ (b =:= c)
|
||
@end example
|
||
|
||
|
||
The following is the list of the declarations of the predefined operators:
|
||
|
||
@example
|
||
:-op(1200,fx,['?-', ':-']).
|
||
:-op(1200,xfx,[':-','-->']).
|
||
:-op(1150,fx,[block,dynamic,mode,public,multifile,meta_predicate,
|
||
sequential,table,initialization]).
|
||
:-op(1100,xfy,[';','|']).
|
||
:-op(1050,xfy,->).
|
||
:-op(1000,xfy,',').
|
||
:-op(999,xfy,'.').
|
||
:-op(900,fy,['\+', not]).
|
||
:-op(900,fx,[nospy, spy]).
|
||
:-op(700,xfx,[@@>=,@@=<,@@<,@@>,<,=,>,=:=,=\=,\==,>=,=<,==,\=,=..,is]).
|
||
:-op(500,yfx,['\/','/\','+','-']).
|
||
:-op(500,fx,['+','-']).
|
||
:-op(400,yfx,['<<','>>','//','*','/']).
|
||
:-op(300,xfx,mod).
|
||
:-op(200,xfy,['^','**']).
|
||
:-op(50,xfx,same).
|
||
@end example
|
||
|
||
@node Predicate Index, Concept Index, Operators, Top
|
||
@unnumbered Predicate Index
|
||
@printindex fn
|
||
|
||
@node Concept Index, , Predicate Index, Top
|
||
@unnumbered Concept Index
|
||
@printindex cp
|
||
|
||
@contents
|
||
|
||
@bye
|