12444 lines
407 KiB
TeX
12444 lines
407 KiB
TeX
|
\input texinfo @c -*-texinfo-*-
|
|||
|
|
|||
|
@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.18
|
|||
|
@set EDITION 4.1.0
|
|||
|
@set UPDATED April 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
|
|||
|
* 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 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
|
|||
|
* 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-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 alphabeticall 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 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-parallelism=@{env-copy,sba,a-cow@}} allows
|
|||
|
or-parallelism supported by one of these three forms. This option is
|
|||
|
still highly experimental.
|
|||
|
|
|||
|
@item @code{--enable-tabling=@{local,batched@}} allows one of the two
|
|||
|
forms of tabling. This option is still experimental.
|
|||
|
@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 examplef
|
|||
|
|
|||
|
@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} 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 can also check the default installation path which is set to
|
|||
|
"/PROGRA~1/Yap" in the Makefile. This corresponds to "c:\Program Files\Yap".
|
|||
|
|
|||
|
@end table
|
|||
|
|
|||
|
@node Compiling Under Visual C++, Tuning for SGI cc, Tuning for GCC, Machine Options
|
|||
|
@subsection Compiling Under SGI's cc
|
|||
|
|
|||
|
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 set @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 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
|
|||
|
|
|||
|
@cindex booting
|
|||
|
The operating system command for invoking YAP is described
|
|||
|
below.
|
|||
|
|
|||
|
Assuming that YAP is in the user's search path, it 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
|
|||
|
where 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 from Prolog @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.
|
|||
|
|
|||
|
YAP can now be used to run Prolog files as scripts in Unix systems. A
|
|||
|
simple example is shown next:
|
|||
|
|
|||
|
@example
|
|||
|
@cartouche
|
|||
|
#!yap -L $0 "$@"
|
|||
|
#
|
|||
|
# Hello World script file using Yap
|
|||
|
#
|
|||
|
|
|||
|
:- write('Hello World'), nl.
|
|||
|
|
|||
|
@end cartouche
|
|||
|
@end example
|
|||
|
|
|||
|
You should write the first line as shown in the example. The @code{#!}
|
|||
|
characters specify that the Operating System should call @code{yap}. The
|
|||
|
@code{-L} flag indicates that YAP should consult the file "$0" at
|
|||
|
booting and then halt. The remaining arguments are then passed to
|
|||
|
YAP. Note that YAP will skip the first lines if they start with # (the
|
|||
|
comment sign for Unix's shell). YAP will consult the file and
|
|||
|
execute any commands.
|
|||
|
|
|||
|
@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 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})
|
|||
|
@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 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) :- write('Undefined predicate: '), write(A), 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_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.
|
|||
|
|
|||
|
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 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
|
|||
|
numbers are sorted in increasing order. Integers precede their floating
|
|||
|
point equivalents;
|
|||
|
@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).
|
|||
|
@end table
|
|||
|
|
|||
|
@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. YAP only supports the predefined aliases
|
|||
|
@code{user}, @code{user_input}, @code{user_output},and
|
|||
|
@code{user_error}.
|
|||
|
|
|||
|
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}
|
|||
|
|
|||
|
@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, @code{code/1} will also try to close a stream for a given
|
|||
|
file name. 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}.
|
|||
|
|
|||
|
@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 <= 3} (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 <= 3} (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. 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 listing.
|
|||
|
|
|||
|
@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{A} 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 shell(+@var{S})
|
|||
|
@findex shell/1
|
|||
|
@snindex shell/1
|
|||
|
@cnindex shell/1
|
|||
|
Passes command @var{S} to the current shell (on UNIX environments).
|
|||
|
|
|||
|
@item system(+@var{S})
|
|||
|
@findex system/1
|
|||
|
@snindex system/1
|
|||
|
@cyindex system/1
|
|||
|
Passes command @var{S} to the Bourne shell (on UNIX 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),
|
|||
|
% and output (note the most often called predicates will come last
|
|||
|
write_profile_data(SLP).
|
|||
|
|
|||
|
write_profile_data([]).
|
|||
|
write_profile_data([D-P|SLP]) :-
|
|||
|
% just swap the two calls to get 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
|
|||
|
Gives 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.
|
|||
|
|
|||
|
@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 yap_flag(?@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. Takes the value
|
|||
|
@code{true} for the current version of YAP.
|
|||
|
|
|||
|
@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}.
|
|||
|
|
|||
|
@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.
|
|||
|
|
|||
|
@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.
|
|||
|
|
|||
|
@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.
|
|||
|
|
|||
|
@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
|
|||
|
* 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 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 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.
|
|||
|
|
|||
|
@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.
|
|||
|
|
|||
|
@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.
|
|||
|
|
|||
|
@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_element(+@var{Element}, +@var{Set})
|
|||
|
@findex ord_element/2
|
|||
|
@syindex ord_element/2
|
|||
|
@cnindex ord_element/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. The random numbers packages
|
|||
|
uses the Operating underlying random number generator, so random numbers
|
|||
|
are not necessarily repeatable.
|
|||
|
|
|||
|
@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<>...@var{HIGH})}.
|
|||
|
|
|||
|
@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<>...@var{HIGH})}.
|
|||
|
|
|||
|
@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, Terms, 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 Terms, Timeout, String I/O, 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{Vertices}, +@var{Graph}, -@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([0,2,9,10,11],[1-[3,5],2-[4],3-[],4-[5],5-[],6-[],7-[],8-[]],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}
|
|||
|
|
|||
|
Extensions to Traditional Prolog
|
|||
|
@menu
|
|||
|
|
|||
|
* Rational Trees:: Working with Rational Trees
|
|||
|
* Coroutining:: Changing the Execution of Goals
|
|||
|
* Attributed Variables:: Using attributed Variables
|
|||
|
* CLPQR:: The CLP(Q,R) 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(_24)
|
|||
|
Y = _92
|
|||
|
Z = _24
|
|||
|
L = [[_92]-dif(f(_24),_92)]
|
|||
|
dif(f(_24),_92) ;
|
|||
|
|
|||
|
X = _86
|
|||
|
Y = f(_24)
|
|||
|
Z = _24
|
|||
|
L = [[_86]-dif(_86,f(_24))]
|
|||
|
dif(_86,f(_24)) ;
|
|||
|
|
|||
|
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
|
|||
|
update 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
|
|||
|
implement 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
|
|||
|
@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 algoritm calls 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 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 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
|
|||
|
sketchs the implementation of simple a 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 invoke @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 constants
|
|||
|
@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, Parallelism, 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 on @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,...,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,...,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
|
|||
|
@ctrl{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 Parallelism, Tabling, CHR, 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 -shared -fPIC my_process.c -o 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
|
|||
|
* WritingC:: Writing Predicates in C
|
|||
|
* LoadingO:: Loading Object Files
|
|||
|
* Sav&Rest:: Saving and Restoring
|
|||
|
* Yap4 Notes:: Changes in Foreign Predicates Interface
|
|||
|
@end menu
|
|||
|
|
|||
|
@node Manipulating Terms, WritingC, , 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.
|
|||
|
|
|||
|
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.
|
|||
|
|
|||
|
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 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.
|
|||
|
|
|||
|
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.
|
|||
|
|
|||
|
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 WritingC, LoadingO, Manipulating Terms, 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 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 LoadingO, Sav&Rest, WritingC, 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, LoadingO, 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 initialization/1 as in 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{print_message/2},
|
|||
|
@code{portray_message/2}, @code{reinitialize/0}, @code{help/0},
|
|||
|
@code{help/1}, @code{module/3}, @code{trimcore/0}.
|
|||
|
|
|||
|
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 YAP does not include object oriented extensions.If you
|
|||
|
require an object-oriented system, Paulo Moura's Logtalk system is
|
|||
|
compatible with YAP.
|
|||
|
|
|||
|
@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
|
|||
|
|
|||
|
|