m4_define(`dnl', `m4_dnl')`'dnl
/* Documentation for the Prolog interfaces.
   Copyright (C) 2001-2008 Roberto Bagnara <bagnara@cs.unipr.it>

This file is part of the Parma Polyhedra Library (PPL).

The PPL is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3 of the License, or (at your
option) any later version.

The PPL is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.

For the most up-to-date information see the Parma Polyhedra Library
site: http://www.cs.unipr.it/ppl/ . */

/*! \mainpage Prolog Language Interface

The Parma Polyhedra Library comes equipped with a Prolog interface.
Despite the lack of standardization of Prolog's foreign language interfaces,
the PPL Prolog interface supports several Prolog systems and, to the
extent this is possible, provides a uniform view of the library from
each such systems.

The system-independent features of the library are described in
Section \ref PI_SI_Features "System-Independent Features".
Section \ref PI_Compilation "Compilation and Installation"
explains how the various incarnations of the Prolog interface
are compiled and installed.
Section \ref PI_SD_Features "System-Dependent Features"
illustrates the system-dependent features of the interface
for all the supported systems.

In the sequel, <CODE>prefix</CODE> is the prefix under which
you have installed the library (typically <CODE>/usr</CODE>
or <CODE>/usr/local</CODE>).


\anchor PI_SI_Features
<H1>System-Independent Features</H1>

The Prolog interface provides access to the numerical abstractions
(convex polyhedra, BD shapes, octagonal shapes, etc.) implemented
by the PPL library.
A general introduction to the numerical abstractions,
their representation in the PPL and the operations provided
by the PPL is given in the main \extref{preamble, PPL user manual}.
Here we just describe those aspects that are specific to the Prolog interface.
<H4>Contents:</H4>
- \ref Prolog_Interface_Overview "Overview";
- \ref Predicate_Specifications "Predicate Specifications";
- \ref predicate_descriptions "Predicate Descriptions"
    - \ref di_predicates "Domain Independent Predicates",
    - \ref mip_predicates "MIP Predicates",
    - \ref main_polyhedron_predicates "Main Polyhedron Predicates";
- \ref generated_predicates "Examples of Generated Domains with Predicates".

\anchor Prolog_Interface_Overview
<H2>Overview</H2>

First, here is a list of notes with general information and advice
on the use of the interface.

- The numerical abstract domains available to the Prolog user consist
  of the <EM>simple</EM> domains, <EM>powersets</EM> of a simple domain and
  <EM>products</EM> of simple domains.
  - The simple domains are:
     - convex polyhedra, which consist of C_Polyhedron and
       NNC_Polyhedron;<BR>
     - weakly relational, which consist of BD_Shape_N and
       Octagonal_Shape_N
       where N is one of the numeric types
       short, signed_char, int, long, long_long,
       mpz_class, mpq_class;<BR>
     - boxes which consist of
       Int8_Box, Int16_Box,
       Int32_Box, Int64_Box,
       Uint8_Box, Uint16_Box,
       Uint32_Box, Uint64_Box,
       Double_Box, Long_Double_Box,
       Z_Box, Rational_Box, Float_Box; and<BR>
     - the Grid domain.
  - The powerset domains are Pointset_Powerset_S where S is
    a simple domain.
  - The product domains consist of
    Direct_Product_S_T,
    Smash_Product_S_T and
    Constraints_Product_S_T where S
    and T are simple domains.
- In the following, any of the above numerical
  abstract domains  is called a PPL <EM>domain</EM>
  and any element of a PPL domain is called a <EM>PPL object</EM>.
- The Prolog interface files are all installed in the directory
  <CODE>prefix/lib/ppl</CODE>.  Since this includes shared and
  dynamically loaded libraries, you must make your dynamic
  linker/loader aware of this fact.  If you use a GNU/Linux system,
  try the commands <CODE>man ld.so</CODE> and <CODE>man ldconfig</CODE>
  for more information.
- The Prolog interface to the PPL is initialized and finalized by the
  predicates <CODE>ppl_initialize/0</CODE> and <CODE>ppl_finalize/0</CODE>.
  Thus the only interface predicates callable after
  <CODE>ppl_finalize/0</CODE> are <CODE>ppl_finalize/0</CODE> itself
  (this further call has no effect) and <CODE>ppl_initialize/0</CODE>,
  after which the interface's services are usable again.
  Some Prolog systems allow the specification of initialization
  and deinitialization functions in their foreign language interfaces.
  The corresponding incarnations of the PPL-Prolog interface
  have been written so that <CODE>ppl_initialize/0</CODE> and/or
  <CODE>ppl_finalize/0</CODE> are called automatically.
  Section \ref PI_SD_Features "System-Dependent Features" will detail
  in which cases initialization and finalization is automatically
  performed or is left to the Prolog programmer's responsibility.
  However, for portable applications, it is best
  to invoke <CODE>ppl_initialize/0</CODE> and <CODE>ppl_finalize/0</CODE>
  explicitly: since they can be called multiple times without problems,
  this will result in enhanced portability at a cost that is, by all means,
  negligible.
- A PPL object such as a polyhedron can only be accessed
  by means of a Prolog term called a <EM>handle</EM>.
  Note, however, that the data structure of a handle,
  is implementation-dependent, system-dependent and
  version-dependent, and, for this reason, deliberately left unspecified.
  What we do guarantee is that the handle requires very little memory.
- A Prolog term can be bound to a valid handle for a PPL object by using
  predicates such as
\code
  ppl_new_C_Polyhedron_from_space_dimension/3,
  ppl_new_C_Polyhedron_from_C_Polyhedron/2,
  ppl_new_C_Polyhedron_from_constraints/2,
  ppl_new_C_Polyhedron_from_generators/2,
\endcode
  These predicates will create or copy a PPL polyhedron
  and construct a valid handle for referencing it.
  The last argument is a Prolog term that is
  unified with a new valid handle for accessing this polyhedron.

- As soon as a PPL object is no longer required,
  the memory occupied by it should be released
  using the PPL predicate such as <CODE>ppl_delete_Polyhedron/1</CODE>.
  To understand why this is important,
  consider a Prolog program and a variable that is bound to
  a Herbrand term.
  When the variable dies (goes out of scope) or is uninstantiated
  (on backtracking) the term it is bound to is amenable to garbage collection.
  But this only applies for the standard domain of the language:
  Herbrand terms.
  In Prolog+PPL, when a variable bound to a handle for a PPL Polyhedron dies
  or is uninstantiated,
  the handle can be garbage-collected, but the polyhedra to which
  the handle refers will not be released.
  Once a handle has been used as an argument in
  <CODE>ppl_delete_Polyhedron/1</CODE>,
  it becomes invalid.
- For a PPL object with space dimension \p k,
  the identifiers used for the PPL variables
  must lie between 0 and \f$k-1\f$ and correspond to the indices of the
  associated Cartesian axes.
  For example, when using the predicates that combine PPL polyhedra
  or add constraints or generators to a representation of
  a PPL polyhedron,
  the polyhedra referenced and any constraints or generators in the call
  should follow all the (space) dimension-compatibility rules stated in
  Section \extref{representation, Representations of Convex Polyhedra}
  of the main PPL user manual.
- As explained above, a polyhedron has a fixed topology C or NNC,
  that is determined at the time of its initialization.
  All subsequent operations on the polyhedron must respect all the
  topological compatibility rules stated in Section
  \extref{representation, Representations of Convex Polyhedra}
  of the main PPL user manual.
- Any application using the PPL should make sure that only the
  intended version(s) of the library are ever used.
  Predicates
\code
  ppl_version_major/1,
  ppl_version_minor/1,
  ppl_version_revision/1,
  ppl_version_beta/1,
  ppl_version/1,
  ppl_banner.
\endcode
  allow run-time checking of information about the version being used.

\anchor Predicate_Specifications
<H2>Predicate Specifications</H2>

The PPL predicates provided by the Prolog interface are specified below.
The specification uses the following grammar rules:
\code

 Number      --> unsigned integer	ranging from 0 to an upper bound
					depending on the actual Prolog system.

 C_int       --> Number | - Number	C integer

 C_unsigned  --> Number			C unsigned integer

 Coefficient --> Number			used in linear expressions;
					the upper bound will depend on how
					the PPL has been configured

 Dimension_Type
             --> Number			used for the number of affine and
					space dimensions and the names of
 					the dimensions;
					the upper bound will depend on
					the maximum number of dimensions
					allowed by the PPL
					(see ppl_max_space_dimensions/1)

 Boolean     --> true | false

 Handle      --> Prolog term		used to identify a Polyhedron

 Topology    --> c | nnc		Polyhedral kind;
					c is closed and nnc is NNC

 VarId       --> Dimension_Type 	variable identifier

 PPL_Var     --> '$VAR'(VarId)		PPL variable

 Lin_Expr    --> PPL_Var		PPL variable
            | Coefficient
            | Lin_Expr			unary plus
            | - Lin_Expr		unary minus
            | Lin_Expr + Lin_Expr	addition
            | Lin_Expr - Lin_Expr	subtraction
            | Coefficient * Lin_Expr	multiplication
            | Lin_Expr * Coefficient	multiplication

 Relation_Symbol
	     --> =			equals
            | =< 			less than or equal
            | >=			greater than or equal
            | < 			strictly less than
            | > 			strictly greater than

 Constraint  --> Lin_Expr Relation_Symbol Lin_Expr
					constraint

 Constraint_System			list of constraints
             --> []
            | [Constraint | Constraint_System]

 Generator_Denominator --> Coefficient	must be non-zero
	    | Coefficient
            | - Coefficient

 Generator   --> point(Lin_Expr)	point
            | point(Lin_Expr, Generator_Denominator)
					point
            | closure_point(Lin_Expr)	closure point
            | closure_point(Lin_Expr, Generator_Denominator)
					closure point
            | ray(Lin_Expr)		ray
            | line(Lin_Expr)		line

 Generator_System			list of generators
             --> []
	    | [Generator | Generator_System]

 Atom        --> Prolog atom

 Universe_or_Empty			polyhedron
             --> universe
            | empty

 Poly_Relation				polyhedron relation:
             --> is_disjoint		with a constraint
	    | strictly_intersects	with a constraint
	    | is_included		with a constraint
	    | saturates			with a constraint
            | subsumes			with a generator

 Relation_List			list of polyhedron relations
	     --> []
	    | [Poly_Relation | Relation_List]

 Complexity  --> polynomial | simplex | any

 Rational_Numerator
	     --> Coefficient | - Coefficient

 Rational_Denominator
	     --> Coefficient		must be non-zero

 Rational    --> Rational_Numerator	rational number
	    | Rational_Numerator/Rational_Denominator

 Bound       --> c(Rational)		closed rational limit
            | o(Rational)		open rational limit
            | o(pinf)			unbounded in the positive direction
            | o(minf)			unbounded in the negative direction

 Interval    --> i(Bound, Bound)	rational interval

 Box         --> []			list of intervals
            | [Interval | Box]

 Vars_Pair   --> PPLVar - PPLVar        map relation

 P_Func      --> []    			list of map relations
            | [Vars_Pair | P_Func].

 Optimization_Mode
             --> max | min

 MIP_Problem_Status
             --> unfeasible | unbounded | optimized

 Vars_List   --> []    			list of PPL variables
            | [PPL_Var | Vars_List].
\endcode

\anchor predicate_descriptions
<H2> Predicate Descriptions </H2>

Below is a short description of many of the interface predicates.
For full definitions of terminology used here, see the main PPL user manual.

\anchor di_predicates
<H3> Domain Independent Predicates </H3>

First we describe the domain independent predicates
that are included with all instantiations of the Prolog interfaces.

<H2><CODE> ppl_version_major(?C_int) </CODE></H2>
  Unifies <CODE>C_int</CODE> with the major number of the PPL version.

<H2><CODE> ppl_version_minor(?C_int) </CODE></H2>
  Unifies <CODE>C_int</CODE> with the minor number of the PPL version.

<H2><CODE> ppl_version_revision(?C_int) </CODE></H2>
  Unifies <CODE>C_int</CODE> with the revision number
  of the PPL version.

<H2><CODE> ppl_version_beta(?C_int) </CODE></H2>
  Unifies <CODE>C_int</CODE> with the beta number of the PPL version.

<H2><CODE> ppl_version(?Atom) </CODE></H2>
  Unifies <CODE>Atom</CODE> with the PPL version.

<H2><CODE> ppl_banner(?Atom) </CODE></H2>
  Unifies <CODE>Atom</CODE> with
  information about the PPL version, the licensing, the lack of any
  warranty whatsoever, the C++ compiler used to build the library,
  where to report bugs and where to look for further information.

<H2><CODE> ppl_Coefficient_is_bounded </CODE></H2>

  Succeeds if and only if the Coefficients in the C++ interface are bounded.

<H2><CODE> ppl_Coefficient_max(Max) </CODE></H2>

  If the Coefficients in the C++ interface are bounded,
  then the maximum coefficient the C++ interface can handle is
  unified with <CODE>Max</Code>.
  If the Prolog system cannot handle this coefficient, then
  an exception is thrown.
  It fails if the Coefficients in the C++ interface are unbounded.

<H2><CODE> ppl_Coefficient_min(Min) </CODE></H2>

  If the Coefficients in the C++ interface are bounded,
  then the minimum coefficient the C++ interface can handle is
  unified with <CODE>Min</Code>.
  If the Prolog system cannot handle this coefficient, then
  an exception is thrown.
  It fails if the Coefficients in the C++ interface are unbounded.

<H2><CODE> ppl_max_space_dimension(?Dimension_Type) </CODE></H2>

  Unifies <CODE>Dimension_Type</CODE> with the maximum space dimension
  this library can handle.

<H2><CODE>
  ppl_initialize
 </CODE></H2>

  Initializes the PPL interface.
  Multiple calls to <CODE>ppl_initialize</CODE> does no harm.

<H2><CODE>
  ppl_finalize
 </CODE></H2>

  Finalizes the PPL interface.
  Once this is executed, the next call to an interface predicate must
  either be to <CODE>ppl_initialize</CODE> or to <CODE>ppl_finalize</CODE>.
  Multiple calls to <CODE>ppl_finalize</CODE> does no harm.

<H2><CODE> ppl_set_timeout_exception_atom(+Atom) </CODE></H2>

   Sets the atom to be thrown by timeout exceptions
   to <CODE>Atom</CODE>.
   The default value is <CODE>time_out</CODE>.

<H2><CODE> ppl_timeout_exception_atom(?Atom) </CODE></H2>

   The atom to be thrown by timeout exceptions
   is unified with <CODE>Atom</CODE>.

<H2><CODE> ppl_set_timeout(+C_unsigned) </CODE></H2>

   Computations taking exponential time will be interrupted
   some time after <CODE>C_unsigned</CODE> ms after that call.
   If the computation is interrupted that way, the current timeout
   exception atom will be thrown.
   <CODE>C_unsigned</CODE> must be strictly greater than zero.

<H2><CODE> ppl_reset_timeout </CODE></H2>

   Resets the timeout time so that the computation is not interrupted.

<BR>

\anchor mip_predicates
<H3> MIP Predicates </H3>
Here we describe the predicates available for PPL objects
defining mixed integer (linear) programming problems.

<H2><CODE>
  ppl_new_MIP_Problem_from_space_dimension(+Dimension_Type, -Handle)
</CODE></H2>

   Creates an MIP Problem \f$\mathrm{MIP}\f$ with the feasible region
   the vector space of dimension <CODE>Dimension_Type</CODE>,
   objective function \f$0\f$ and optimization mode <CODE>max</CODE>.
   <CODE>Handle</CODE> is unified with the handle for \f$\mathrm{MIP}\f$.

<H2><CODE>
  ppl_new_MIP_Problem(+Constraint_System, +Lin_Expr, +Optimization_Mode,
                      -Handle)
</CODE></H2>

   Creates an MIP Problem \f$\mathrm{MIP}\f$ with
   the feasible region represented by <CODE>Constraint_System</CODE>,
   objective function <CODE>Lin_Expr</CODE> and optimization mode
   <CODE>Optimization_Mode</CODE>.
   <CODE>Handle</CODE> is unified with the handle for \f$\mathrm{MIP}\f$.

<H2><CODE>
  ppl_MIP_Problem_swap(+Handle_1, +Handle_2)
</CODE></H2>

   Swaps the MIP Problem referenced by <CODE>Handle_1</CODE>
   with the one referenced by <CODE>Handle_2</CODE>.

<H2><CODE>
  ppl_delete_MIP_Problem(+Handle)
</CODE></H2>

   Deletes the MIP Problem referenced by <CODE>Handle</CODE>.
   After execution,
   <CODE>Handle</CODE> is no longer a valid handle for a PPL MIP Problem.

<H2><CODE>
  ppl_MIP_Problem_space_dimension(+Handle, ?Dimension_Type)
</CODE></H2>

   Unifies the dimension of the vector space in which the
   MIP Problem referenced by <CODE>Handle</CODE> is embedded
   with <CODE>Dimension_Type</CODE>.

<H2><CODE>
  ppl_MIP_Problem_integer_space_dimensions(+Handle, -Vars_List)
</CODE></H2>

   Unifies <CODE>Vars_List</CODE> with a list of variables representing
   representing the integer space dimensions of the MIP Problem
   referenced by <CODE>Handle</CODE>.

<H2><CODE>
  ppl_MIP_Problem_constraints(+Handle, -Constraint_System)
</CODE></H2>

   Unifies <CODE>Constraint_System</CODE> with a list of
   the constraints in the constraints system
   representing the feasible region for the MIP Problem
   referenced by <CODE>Handle</CODE>.

<H2><CODE>
  ppl_MIP_Problem_objective_function(+Handle, -Lin_Expr)
</CODE></H2>

   Unifies <CODE>Lin_Expr</CODE> with the objective function
   for the MIP Problem referenced by <CODE>Handle</CODE>.

<H2><CODE>
  ppl_MIP_Problem_optimization_mode(+Handle, ?Optimization_Mode)
</CODE></H2>

   Unifies <CODE>Optimization_Mode</CODE> with the optimization mode
   for the MIP Problem referenced by <CODE>Handle</CODE>.

<H2><CODE>
  ppl_MIP_Problem_clear(+Handle)
</CODE></H2>

  Resets the MIP problem referenced by <CODE>Handle</CODE>
  to be the trivial problem with
  the feasible region the \f$0\f$-dimensional universe,
  objective function \f$0\f$ and optimization mode <CODE>max</CODE>.

<H2><CODE> ppl_MIP_Problem_add_space_dimensions_and_embed(
             +Handle, +Dimension_Type)
 </CODE></H2>

   Embeds the MIP problem referenced by <CODE>Handle</CODE>
   in a space that is enlarged by <CODE>Dimension_Type</CODE> dimensions,

<H2><CODE>
  ppl_MIP_Problem_add_to_integer_space_dimensions(+Handle, +Vars_List)
</CODE></H2>

   Updates the MIP Problem referenced by <CODE>Handle</CODE>
   so that the variables in <CODE>Vars_List</CODE> are added to
   the set of integer space dimensions.

<H2><CODE>
  ppl_MIP_Problem_add_constraint(+Handle, +Constraint)
</CODE></H2>

   Updates the MIP Problem referenced by <CODE>Handle</CODE>
   so that the feasible region is represented by the original constraint
   system together with the constraint <CODE>Constraint</CODE>.

<H2><CODE>
  ppl_MIP_Problem_add_constraints(+Handle, +Constraint_System)
</CODE></H2>

   Updates the MIP Problem referenced by <CODE>Handle</CODE>
   so that the feasible region is represented by the original constraint
   system together with all the constraints in <CODE>Constraint_System</CODE>.

<H2><CODE>
  ppl_MIP_Problem_set_objective_function(+Handle, +Lin_Expr)
</CODE></H2>

   Updates the MIP Problem referenced by <CODE>Handle</CODE>
   so that the objective function is changed to <CODE>Lin_Expr</CODE>.

<H2><CODE>
  ppl_MIP_Problem_set_optimization_mode(+Handle, +Optimization_Mode)
</CODE></H2>

   Updates the MIP Problem referenced by <CODE>Handle</CODE>
   so that the optimization mode is changed to <CODE>Optimization_Mode</CODE>.

<H2><CODE>
  ppl_MIP_Problem_is_satisfiable(+Handle)
</CODE></H2>

  Succeeds if and only if the MIP Problem referenced by
  <CODE>Handle</CODE> is satisfiable.

<H2><CODE>
  ppl_MIP_Problem_solve(+Handle, ?MIP_Problem_Status)
</CODE></H2>

  Solves the MIP problem  referenced by
  <CODE>Handle</CODE> and unifies <CODE>MIP_Problem_Status</CODE>
  with:
  <CODE>unfeasible</CODE>, if the MIP problem is not satisfiable;
  <CODE>unbounded</CODE>, if the MIP problem is satisfiable but
  there is no finite bound to the value of the objective function;
  <CODE>optimized</CODE>, if the MIP problem admits an optimal solution.

<H2><CODE>
  ppl_MIP_Problem_feasible_point(+Handle, ?Generator)
</CODE></H2>

  Unifies  <CODE>Generator</CODE> with a feasible point for the MIP problem
  referenced by <CODE>Handle</CODE>.

<H2><CODE>
  ppl_MIP_Problem_optimizing_point(+Handle, ?Generator)
</CODE></H2>

  Unifies  <CODE>Generator</CODE> with an optimizing point for the MIP problem
  referenced by <CODE>Handle</CODE>.

<H2><CODE>
  ppl_MIP_Problem_optimal_value(+Handle, ?Coefficient_1, ?Coefficient_2)
</CODE></H2>

  Unifies <CODE>Coefficient_1</CODE> and <CODE>Coefficient_2</CODE>
  with the numerator and denominator, respectively, for the optimal value
  for the MIP problem  referenced by <CODE>Handle</CODE>.

<H2><CODE>
  ppl_MIP_Problem_evaluate_objective_function(+Handle, +Generator,
                                             ?Coefficient_1, ?Coefficient_2)
</CODE></H2>
  Evaluates the objective function of the MIP problem  referenced by
  <CODE>Handle</CODE> at point <CODE>Generator</CODE>.
  <CODE>Coefficient_1</CODE> is unified with the numerator and
  <CODE>Coefficient_2</CODE> is unified with the denominator of the
  objective function value at <CODE>Generator</CODE>.

<H2><CODE>
  ppl_MIP_Problem_OK(+Handle)
</CODE></H2>

   Succeeds only if the MIP Problem referenced by
   <CODE>Handle</CODE> is well formed, i.e., if it
   satisfies all its implementation invariants.  Useful for debugging purposes.

<BR>

\anchor main_polyhedron_predicates
<H3> Convex Polyhedron Predicates </H3>
Here we describe the main predicates available for PPL objects
defining convex polyhedra. A full list of the available
PPL domains for convex polyhedra that have been instantiated
for the Prolog interface is given in
Section \ref Polyhedron_predicates "Polyhedron Predicate List".

<H2><CODE> ppl_delete_Polyhedron(+Handle) </CODE></H2>

   Deletes the polyhedron referenced by <CODE>Handle</CODE>.
   After execution,
   <CODE>Handle</CODE> is no longer a valid handle for a PPL polyhedron.

<H2><CODE>
  ppl_new_C_Polyhedron_from_space_dimension(+Dimension_Type,
                                          +Universe_or_Empty, -Handle)
</CODE>
</H2>

   Creates a C polyhedron \f$\cP\f$
   with <CODE>Dimension_Type</CODE> dimensions; it is empty
   or the universe polyhedron depending on whether <CODE>Atom</CODE>
   is <CODE>empty</CODE> or <CODE>universe</CODE>, respectively.
   <CODE>Handle</CODE> is unified with the handle for \f$\cP\f$.
   Thus the query
\code
   ?- ppl_new_C_Polyhedron_from_space_dimension(3, universe, X).
\endcode
   creates the C polyhedron defining the 3-dimensional vector space
   \f$\Rset^3\f$ with \p X bound to a valid handle for accessing it.

<H2><CODE>
  ppl_new_NNC_Polyhedron_from_space_dimension(+Dimension_Type,
                                          +Universe_or_Empty, -Handle)
</CODE>
</H2>

   Creates an NNC polyhedron \f$\cP\f$
   with <CODE>Dimension_Type</CODE> dimensions; it is empty
   or the universe polyhedron depending on whether <CODE>Atom</CODE>
   is <CODE>empty</CODE> or <CODE>universe</CODE>, respectively.
   <CODE>Handle</CODE> is unified with the handle for \f$\cP\f$.
   Thus the query
\code
   ?- ppl_new_NNC_Polyhedron_from_space_dimension(3, empty, X).
\endcode
   creates an empty NNC polyhedron embedded in \f$\Rset^3\f$ with
   \p X bound to a valid handle for accessing it.

<H2><CODE>
ppl_new_C_Polyhedron_from_C_Polyhedron(+Handle_1, -Handle_2)
 </CODE></H2>

   If <CODE>Handle_1</CODE> refers to a C polyhedron \f$\cP_1\f$,
   then this creates a copy \f$\cP_2\f$ of \f$\cP_1\f$.
   <CODE>Handle_2</CODE> is unified with the handle for \f$\cP_2\f$.

<H2><CODE>
ppl_new_C_Polyhedron_from_NNC_Polyhedron(+Handle_1, -Handle_2)
 </CODE></H2>

   If <CODE>Handle_1</CODE> refers to an NNC polyhedron \f$\cP_1\f$,
   then this creates a copy of \f$\cP_1\f$ as a C polyhedron \f$\cP_2\f$.
   <CODE>Handle_2</CODE> is unified with the handle for \f$\cP_2\f$.
   Thus the query
\code
   ?- ppl_new_NNC_Polyhedron_from_space_dimension(3, empty, X),
      ppl_new_C_Polyhedron_from_NNC_Polyhedron(X, Y).
\endcode
   creates an empty NNC polyhedron embedded in \f$\Rset^3\f$
   referenced by \p X
   and then makes a copy, converting the topology to a C polyhedron.
   with \p Y bound to a valid handle for accessing it.

   When using <CODE>ppl_new_C_Polyhedron_from_NNC_Polyhedron/2</CODE>,
   care must be taken that the source polyhedron referenced by
   <CODE>Handle_1</CODE> is topologically closed.

<H2><CODE>
ppl_new_NNC_Polyhedron_from_C_Polyhedron(+Handle_1, -Handle_2)
 </CODE></H2>

   If <CODE>Handle_1</CODE> refers to a C polyhedron \f$\cP_1\f$,
   then this creates a copy of \f$\cP_1\f$ as an NNC polyhedron \f$\cP_2\f$.
   <CODE>Handle_2</CODE> is unified with the handle for \f$\cP_2\f$.

<H2><CODE>
ppl_new_NNC_Polyhedron_from_NNC_Polyhedron(+Handle_1, -Handle_2)
 </CODE></H2>

   If <CODE>Handle_1</CODE> refers to a NNC polyhedron \f$\cP_1\f$,
   then this creates a copy \f$\cP_2\f$ of \f$\cP_1\f$.
   <CODE>Handle_2</CODE> is unified with the handle for \f$\cP_2\f$.

<H2><CODE>
   ppl_new_C_Polyhedron_from_constraints(+Constraint_System, -Handle)
 </CODE></H2>

   Creates a C polyhedron \f$\cP\f$ represented by
   <CODE>Constraint_System</CODE>.
   <CODE>Handle</CODE> is unified with the handle for \f$\cP\f$.

<H2><CODE>
   ppl_new_NNC_Polyhedron_from_constraints(+Constraint_System, -Handle)
 </CODE></H2>

   Creates an NNC polyhedron \f$\cP\f$ represented by
   <CODE>Constraint_System</CODE>.
   <CODE>Handle</CODE> is unified with the handle for \f$\cP\f$.

<H2><CODE>
   ppl_new_C_Polyhedron_from_generators(+Generator_System, -Handle)
 </CODE></H2>

   Creates a C polyhedron \f$\cP\f$ represented by
   <CODE>Generator_System</CODE>.
   <CODE>Handle</CODE> is unified with the handle for \f$\cP\f$.

<H2><CODE>
   ppl_new_NNC_Polyhedron_from_generators(+Generator_System, -Handle)
 </CODE></H2>

   Creates an NNC polyhedron \f$\cP\f$ represented by
   <CODE>Generator_System</CODE>.
   <CODE>Handle</CODE> is unified with the handle for \f$\cP\f$.

<H2><CODE>
   ppl_new_C_Polyhedron_from_bounding_box(+Box, -Handle)
 </CODE></H2>

   Creates a C polyhedron \f$\cP\f$ represented by <CODE>Box</CODE>.
   <CODE>Handle</CODE> is unified with the handle for \f$\cP\f$.
   There must be no bounds of the form <CODE>o(Rational)</CODE>
   in an interval in <CODE>Box</CODE>.

<H2><CODE>
   ppl_new_NNC_Polyhedron_from_bounding_box(+Box, -Handle)
 </CODE></H2>

   Creates an NNC polyhedron \f$\cP\f$ represented by <CODE>Box</CODE>.
   <CODE>Handle</CODE> is unified with the handle for \f$\cP\f$.

<H2><CODE> ppl_Polyhedron_swap(+Handle_1, +Handle_2) </CODE></H2>

   Swaps the polyhedron referenced by <CODE>Handle_1</CODE>
   with the one referenced by <CODE>Handle_2</CODE>.
   The polyhedra \f$\cP\f$ and \f$\cQ\f$ must have the same topology.

<H2><CODE> ppl_Polyhedron_space_dimension(+Handle, ?Dimension_Type) </CODE></H2>

   Unifies the dimension of the vector space in which the
   polyhedron referenced by
   <CODE>Handle</CODE> is embedded with <CODE>Dimension_Type</CODE>.

<H2><CODE> ppl_Polyhedron_affine_dimension(+Handle, ?Dimension_Type) </CODE></H2>

   Unifies the actual dimension of the polyhedron referenced by
   <CODE>Handle</CODE> with <CODE>Dimension_Type</CODE>.

<H2><CODE> ppl_Polyhedron_get_constraints(+Handle, ?Constraint_System)
 </CODE></H2>

   Unifies <CODE>Constraint_System</CODE> with a list of
   the constraints in the constraints system
   representing the polyhedron referenced by <CODE>Handle</CODE>.

<H2><CODE> ppl_Polyhedron_get_minimized_constraints(+Handle,
                                                   ?Constraint_System)
 </CODE></H2>

   Unifies <CODE>Constraint_System</CODE> with a minimized list of
   the constraints in the constraints system
   representing the polyhedron referenced by <CODE>Handle</CODE>.

<H2><CODE> ppl_Polyhedron_get_generators(+Handle, ?Generator_System)
 </CODE></H2>

   Unifies <CODE>Generator_System</CODE> with a list of
   the generators in the generators system
   representing the polyhedron referenced by <CODE>Handle</CODE>.

<H2><CODE> ppl_Polyhedron_get_minimized_generators(+Handle,
                                                  ?Generator_System)
 </CODE></H2>

   Unifies <CODE>Generator_System</CODE> with a minimized list of
   the generators in the generators system
   representing the polyhedron referenced by <CODE>Handle</CODE>.

<H2><CODE> ppl_Polyhedron_relation_with_constraint(+Handle, +Constraint,
               ?Relation_List) </CODE></H2>

Unifies <CODE>Relation_List</CODE> with the list of relations the
polyhedron referenced by <CODE>Handle</CODE> has with
<CODE>Constraint</CODE>.  The possible relations are listed in the
grammar rules above; their meaning is given in Section
\extref{relation_with, Relation-With Operators}
of the main PPL user manual.

<H2><CODE> ppl_Polyhedron_relation_with_generator(+Handle, +Generator,
               ?Relation_List) </CODE></H2>

Unifies <CODE>Relation_List</CODE> with the list of relations the
polyhedron referenced by <CODE>Handle</CODE> has with
<CODE>Generator</CODE>.  The possible relations are listed in the
grammar rules above; their meaning is given in
Section \extref{relation_with, Relation-With Operators}
of the main PPL user manual.

<H2><CODE> ppl_Polyhedron_get_bounding_box(+Handle,
                                          +Complexity,
            	                          ?Box) </CODE></H2>

   Succeeds if and only if the bounding box
   of the polyhedron referenced by
   <CODE>Handle</CODE>
   unifies with the box defined by <CODE>Box</CODE>.
   E.g.,
\code
   ?- A = '$VAR'(0), B = '$VAR'(1),
      ppl_new_NNC_Polyhedron_from_constraints([B > 0, 4*A =< 2], X),
      ppl_Polyhedron_get_bounding_box(X, any, Box).

   Box = [i(o(minf), c(1/2)), i(o(0), o(pinf))].
\endcode
Note that the rational numbers in <CODE>Box</CODE> are in canonical form.
E.g., the following will fail:
\code
   ?- A = '$VAR'(0), B = '$VAR'(1),
      ppl_new_NNC_Polyhedron_from_constraints([B > 0, 4*A =< 2], X),
      ppl_Polyhedron_get_bounding_box(X, any, Box),
      Box = [i(o(minf), c(2/4)), i(o(0), o(pinf))].
\endcode

The complexity class <CODE>Complexity</CODE> determining the algorithm
to be used has the following meaning:
- <CODE>polynomial</CODE> allows
  code of the worst-case polynomial complexity class;
- <CODE>simplex</CODE> allows
  code of the worst-case exponential but typically polynomial
  complexity class;
- <CODE>any</CODE> allows
  code of the universal complexity class.

<H2><CODE> ppl_Polyhedron_is_empty(+Handle) </CODE></H2>

   Succeeds if and only if the polyhedron referenced by
   <CODE>Handle</CODE> is empty.

<H2><CODE> ppl_Polyhedron_is_universe(+Handle) </CODE></H2>

   Succeeds if and only if the polyhedron referenced by
   <CODE>Handle</CODE> is the universe.

<H2><CODE> ppl_Polyhedron_is_bounded(+Handle) </CODE></H2>

   Succeeds if and only if the polyhedron referenced by
   <CODE>Handle</CODE> is bounded.

<H2><CODE> ppl_Polyhedron_contains_integer_point(+Handle) </CODE></H2>

   Succeeds if and only if the polyhedron referenced by
   <CODE>Handle</CODE> contains at least one integer point.

<H2><CODE> ppl_Polyhedron_bounds_from_above(+Handle,
                                   +Lin_Expr) </CODE></H2>

   Succeeds if and only if <CODE>Lin_Expr</CODE> is bounded from above in
   the polyhedron referenced by <CODE>Handle</CODE>.


<H2><CODE> ppl_Polyhedron_bounds_from_below(+Handle,
                                   +Lin_Expr) </CODE></H2>

   Succeeds if and only if <CODE>Lin_Expr</CODE> is bounded from below in
   the polyhedron referenced by <CODE>Handle</CODE>.


<H3><CODE>
  ppl_Polyhedron_maximize(+Handle, +Lin_Expr, ?Coefficient_1,
  			  ?Coefficient_2, ?Boolean)
 </CODE></H3>

  Succeeds if and only if the polyhedron \f$P\f$ referenced by
  <CODE>Handle</CODE> is not empty
  and <CODE>Lin_Expr</CODE> is bounded from above in \f$P\f$.

  <CODE>Coefficient_1</CODE> is unified with the numerator of
  the supremum value and <CODE>Coefficient_2</CODE> with the denominator
  of the supremum value.
  If the supremum is also the maximum,
  <CODE>Boolean</CODE> is unified with the atom <CODE>true</CODE>
  and, otherwise, unified with the atom <CODE>false</CODE>.

<H2><CODE>
  ppl_Polyhedron_maximize_with_point(+Handle, +Lin_Expr, ?Coefficient_1,
  			             ?Coefficient_2, ?Boolean, ?Point)
 </CODE></H2>

  Succeeds if and only if the polyhedron \f$P\f$ referenced by
  <CODE>Handle</CODE> is not empty
  and <CODE>Lin_Expr</CODE> is bounded from above in \f$P\f$.

  <CODE>Coefficient_1</CODE> is unified with the numerator of
  the supremum value,
  <CODE>Coefficient_2</CODE> with the denominator of the supremum value,
  and <CODE>Point</CODE> with a point or closure point where
  <CODE>Lin_Expr</CODE> reaches this value.
  If the supremum is also the maximum,
  <CODE>Boolean</CODE> is unified with the atom <CODE>true</CODE>
  and, otherwise, unified with the atom <CODE>false</CODE>.

<H2><CODE>
  ppl_Polyhedron_minimize(+Handle, +Lin_Expr, ?Coefficient_1,
			  ?Coefficient_2, ?Boolean)
</CODE></H2>

  Succeeds if and only if the polyhedron \f$P\f$ referenced by
  <CODE>Handle</CODE> is not empty
  and <CODE>Lin_Expr</CODE> is bounded from below in \f$P\f$.

  <CODE>Coefficient_1</CODE> is unified with the numerator of the infimum value
  and <CODE>Coefficient_2</CODE> with the denominator of the infimum value.
  If the infimum is also the minimum,
  <CODE>Boolean</CODE> is unified with the atom <CODE>true</CODE>
  and, otherwise, unified with the atom <CODE>false</CODE>.

<H2><CODE>
  ppl_Polyhedron_minimize_with_point(+Handle, +Lin_Expr, ?Coefficient_1,
  			             ?Coefficient_2, ?Boolean, ?Point)
</CODE></H2>

  Succeeds if and only if the polyhedron \f$P\f$ referenced by
  <CODE>Handle</CODE> is not empty
  and <CODE>Lin_Expr</CODE> is bounded from below in \f$P\f$.

  <CODE>Coefficient_1</CODE> is unified with the numerator of the
  infimum value, <CODE>Coefficient_2</CODE> with the denominator of
  the infimum value, and <CODE>Point</CODE> with  a point or
  closure point where <CODE>Lin_Expr</CODE> reaches this value.
  If the infimum is also the minimum,
  <CODE>Boolean</CODE> is unified with the atom <CODE>true</CODE>
  and, otherwise, unified with the atom <CODE>false</CODE>.

<H2><CODE> ppl_Polyhedron_is_topologically_closed(+Handle) </CODE></H2>

   Succeeds if and only if the polyhedron referenced by
   <CODE>Handle</CODE> is topologically closed.

<H2><CODE> ppl_Polyhedron_contains_Polyhedron(+Handle_1, +Handle_2) </CODE></H2>

   Succeeds if and only if the polyhedron referenced by
   <CODE>Handle_2</CODE> is included in or
   equal to the polyhedron referenced by <CODE>Handle_1</CODE>.

<H2><CODE> ppl_Polyhedron_strictly_contains_Polyhedron(+Handle_1, +Handle_2) </CODE></H2>

   Succeeds if and only if the polyhedron referenced by
   <CODE>Handle_2</CODE> is included in but not
   equal to the polyhedron referenced by <CODE>Handle_1</CODE>.

<H2><CODE> ppl_Polyhedron_is_disjoint_from_Polyhedron(+Handle_1, +Handle_2)
     </CODE></H2>

   Succeeds if and only if the polyhedron referenced by
   <CODE>Handle_1</CODE> is disjoint from
   the polyhedron referenced by <CODE>Handle_2</CODE>.

<H2><CODE> ppl_Polyhedron_equals_Polyhedron(+Handle_1, +Handle_2) </CODE></H2>

   Succeeds if and only if the polyhedron referenced by
   <CODE>Handle_1</CODE> is
   equal to the polyhedron referenced by <CODE>Handle_2</CODE>.

<H2><CODE> ppl_Polyhedron_OK(+Handle) </CODE></H2>

   Succeeds only if the polyhedron referenced by
   <CODE>Handle</CODE> is well formed, i.e., if it
   satisfies all its implementation invariants.  Useful for debugging purposes.

<H2><CODE> ppl_Polyhedron_add_constraint(+Handle, +Constraint) </CODE></H2>

<H2><CODE> ppl_Polyhedron_add_constraint_and_minimize(+Handle, +Constraint) </CODE></H2>

   Updates the polyhedron referenced by <CODE>Handle</CODE> to
   one obtained by adding
   <CODE>Constraint</CODE> to its constraint system.
   Thus, the query
\code
   ?- ppl_new_C_Polyhedron_from_space_dimension(3, universe, X),
      A = '$VAR'(0), B = '$VAR'(1), C = '$VAR'(2),
      ppl_Polyhedron_add_constraint(X, 4*A + B - 2*C >= 5).
\endcode
    will update the polyhedron with handle \p X to consist of
    the set of points
    in the vector space \f$\Rset^3\f$ satisfying the constraint
    \f$4x + y - 2z >= 5\f$.

   Note that <CODE>ppl_Polyhedron_add_constraint_and_minimize/2</CODE>
   will fail if, after adding the constraint, the polyhedron is empty.

<H2><CODE> ppl_Polyhedron_add_generator(+Handle, +Generator) </CODE></H2>

<H2><CODE> ppl_Polyhedron_add_generator_and_minimize(+Handle, +Generator) </CODE></H2>

   Updates the polyhedron referenced by <CODE>Handle</CODE> to
   one obtained by adding
   <CODE>Generator</CODE> to its generator system.
   Thus, after the query
\code
   ?- ppl_new_C_Polyhedron_from_space_dimension(3, universe, X),
      A = '$VAR'(0), B = '$VAR'(1), C = '$VAR'(2),
      ppl_Polyhedron_add_generator(X, point(-100*A - 5*B, 8)).
\endcode
    will update the polyhedron with handle \p X to be the single point
    \f$(-12.5, -0.625, 0)^\transpose\f$ in the vector space \f$\Rset^3\f$.

<H2><CODE> ppl_Polyhedron_add_constraints(+Handle, +Constraint_System)
 </CODE></H2>

   Updates the polyhedron referenced by <CODE>Handle</CODE> to
   one obtained by adding to its constraint system the constraints in
   <CODE>Constraint_System</CODE>.
   E.g.,
\code
   | ?- ppl_new_C_Polyhedron_from_space_dimension(2, universe, X),
        A = '$VAR'(0), B = '$VAR'(1),
        ppl_Polyhedron_add_constraints(X, [4*A + B >= 3, A = 1]),
        ppl_Polyhedron_get_constraints(X, CS).

   CS = [4*A+1*B>=3,1*A=1] ?
\endcode
The updated polyhedron referenced by <CODE>Handle</CODE> can be empty
and a query will succeed even when
<CODE>Constraint_System</CODE> is unsatisfiable.

<H2><CODE> ppl_Polyhedron_add_constraints_and_minimize(+Handle,
                                   +Constraint_System) </CODE></H2>

   Updates the polyhedron referenced by <CODE>Handle</CODE> to
   one obtained by adding to its constraint system the constraints in
   <CODE>Constraint_System</CODE>.
   E.g.,
\code
   ?- ppl_new_C_Polyhedron_from_space_dimension(2, universe, X),
      A = '$VAR'(0), B = '$VAR'(1),
      ppl_Polyhedron_add_constraints_and_minimize(X, [4*A + B >= 3, A = 1]),
      ppl_Polyhedron_get_constraints(X, CS).

   CS = [1*B>= -1,1*A=1]
\endcode                                                                          This will fail if, after adding the constraints, the polyhedron is empty.
   E.g., the following will fail,
\code
   ?- A = '$VAR'(0), B = '$VAR'(1),
      ppl_new_C_Polyhedron_from_space_dimension(2, universe, X),
      ppl_Polyhedron_add_constraints_and_minimize(X,
        [4*A + B >= 3, A = 0, B =< 0]),
      ppl_Polyhedron_get_constraints(X, CS).
\endcode
<H2><CODE> ppl_C_Polyhedron_add_generators(+Handle, +Generator_System)
 </CODE></H2>

   Updates the polyhedron referenced by <CODE>Handle</CODE> to
   one obtained by adding to its generator system the generators in
   <CODE>Generator_System</CODE>.

   If the system of generators representing a polyhedron
   is non-empty, then it must include a point
   (see Section \extref{Generators_Representation, Generators Representation}
    of the main PPL user manual).
   Thus care must be taken to ensure that, before calling this
   predicate, either the polyhedron referenced by <CODE>Handle</CODE>
   is non-empty or that whenever <CODE>Generator_System</CODE> is
   non-empty the first element defines a point.
   E.g.,
\code
   ?- ppl_new_C_Polyhedron_from_space_dimension(3, empty, X),
      A='$VAR'(0), B = '$VAR'(1), C = '$VAR'(2),
      ppl_Polyhedron_add_generators(X,
        [point(1*A + 1*B + 1*C, 1), ray(1*A), ray(2*A)]),
      ppl_Polyhedron_get_generators(X, GS).

   GS = [ray(2*A), point(1*A+1*B+1*C), ray(1*A)]
\endcode

<H2><CODE> ppl_Polyhedron_add_generators_and_minimize(+Handle,
                                   +Generator_System) </CODE></H2>

   Updates the polyhedron referenced by <CODE>Handle</CODE> to
   one obtained by adding to its generator system the generators in
   <CODE>Generator_System</CODE>.

   Unlike the predicate <CODE>ppl_add_generators</CODE>,
   the order of the generators in
   <CODE>Generator_System</CODE> is not important.
   E.g.,
\code
   ?- ppl_new_C_Polyhedron_from_space_dimension(3, empty, X),
      A='$VAR'(0), B = '$VAR'(1), C = '$VAR'(2),
      ppl_Polyhedron_add_generators_and_minimize(X,
        [ray(1*A), ray(2*A), point(1*A + 1*B + 1*C, 1)]),
      ppl_Polyhedron_get_generators(X, GS).

   GS = [point(1*A+1*B+1*C), ray(1*A)]
\endcode

<H2><CODE> ppl_Polyhedron_intersection_assign(+Handle_1, +Handle_2) </CODE></H2>
<H2><CODE> ppl_Polyhedron_intersection_assign_and_minimize(+Handle_1,
                     +Handle_2) </CODE></H2>

   Assigns to the polyhedron referenced by <CODE>Handle_1</CODE>
   its intersection with the polyhedron referenced by <CODE>Handle_2</CODE>.

<H2><CODE> ppl_Polyhedron_poly_hull_assign(+Handle_1, +Handle_2) </CODE></H2>
<H2><CODE> ppl_Polyhedron_poly_hull_assign_and_minimize(+Handle_1,
               +Handle_2) </CODE></H2>

   Assigns to the polyhedron referenced by <CODE>Handle_1</CODE>
   its poly-hull with the polyhedron referenced by <CODE>Handle_2</CODE>.

<H2><CODE> ppl_Polyhedron_poly_difference_assign(+Handle_1, +Handle_2) </CODE></H2>

   Assigns to the polyhedron referenced by <CODE>Handle_1</CODE>
   its poly-difference with the polyhedron referenced by <CODE>Handle_2</CODE>.

<H2><CODE> ppl_Polyhedron_affine_image(+Handle, +PPL_Var,
               +Lin_Expr, +Coefficient) </CODE></H2>

   Transforms the polyhedron referenced by <CODE>Handle</CODE>
   assigning the affine expression
   <CODE>Lin_Expr</CODE>/<CODE>Coefficient</CODE> to <CODE>PPL_Var</CODE>.

<H2><CODE> ppl_Polyhedron_affine_preimage(+Handle, +PPL_Var,
               +Lin_Expr, +Coefficient) </CODE></H2>

This is the inverse transformation to that for <CODE>ppl_affine_image</CODE>.

<H2><CODE> ppl_Polyhedron_bounded_affine_image(+Handle,
               +PPL_Var,
               +Lin_Expr_1,
               +Lin_Expr_2,
               +Coefficient) </CODE></H2>

   Transforms the polyhedron referenced by <CODE>Handle</CODE>
   assigning the image with respect to the transfer relation
   <CODE>Lin_Expr_1/Coefficient <= PPL_Var <= Lin_Expr_2/Coefficient</CODE>.

<H2><CODE> ppl_Polyhedron_generalized_affine_image(+Handle,
               +PPL_Var,
               +Relation_Symbol,
               +Lin_Expr,
               +Coefficient) </CODE></H2>

   Transforms the polyhedron referenced by <CODE>Handle</CODE>
   assigning the generalized
   affine image with respect to the transfer function
   <CODE>PPL_Var</CODE> <CODE>Relation_Symbol</CODE>
   <CODE>Lin_Expr</CODE>/<CODE>Coefficient</CODE>.


<H2><CODE> ppl_Polyhedron_generalized_affine_image_lhs_rhs(+Handle,
               +Lin_Expr_1,
               +Relation_Symbol,
               +Lin_Expr_2) </CODE></H2>

   Transforms the polyhedron referenced by <CODE>Handle</CODE>
   assigning the generalized
   affine image with respect to the transfer function
   <CODE>Lin_Expr_1</CODE> <CODE>Relation_Symbol</CODE>
   <CODE>Lin_Expr_2</CODE>.

<H2><CODE> ppl_Polyhedron_time_elapse_assign(+Handle_1, +Handle_2) </CODE></H2>

   Assigns to the polyhedron \f$\cP\f$ referenced by <CODE>Handle_1</CODE>
   the time-elapse \f$ (\cP \nearrow \cQ)\f$
   with the polyhedron \f$\cQ\f$ referenced by <CODE>Handle_2</CODE>.

<H2><CODE> ppl_Polyhedron_BHRZ03_widening_assign(+Handle_1,
               +Handle_2) </CODE></H2>

   If the polyhedron \f$\cP_1\f$ referenced by <CODE>Handle_1</CODE>
   contains the polyhedron \f$\cP_2\f$ referenced by <CODE>Handle_2</CODE>,
   then <CODE>Handle_1</CODE> will refer to
   the BHRZ03-widening of \f$\cP_1\f$ with \f$\cP_2\f$.

<H2><CODE> ppl_Polyhedron_BHRZ03_widening_assign_with_tokens(+Handle_1,
               +Handle_2, +C_unsigned_1, ?C_unsigned_2) </CODE></H2>

   It is assumed that the polyhedron \f$\cP_1\f$ referenced by
   <CODE>Handle_1</CODE> contains the polyhedron \f$\cP_2\f$
   referenced by <CODE>Handle_2</CODE>;
   let \f$\cP\f$ denote the BHRZ03-widening of
   \f$\cP_1\f$ with \f$\cP_2\f$,
   Assuming that the quantity \f$t_1\f$ given by <CODE>C_unsigned_1</CODE>
   is the number of tokens available,
   <CODE>C_unsigned_2</CODE> will be unified with the number of tokens
   \f$t_2\f$ remaining at the end of the operation.
   <BR>
   If \f$t_1 > 0 \f$, then the polyhedron referenced by <CODE>Handle_1</CODE>
   will remain as \f$\cP_1\f$ and either \f$t_2 = t_1 - 1\f$ or \f$t_2 = t_1\f$
   depending on whether or not \f$\cP\f$ is different from \f$\cP_1\f$ itself.
   <BR>
   If \f$t_1 = 0\f$, then \f$t_2 = 0\f$
   and the polyhedron referenced by <CODE>Handle_1</CODE> is
   updated to  \f$\cP\f$.
   <BR>
   In all cases, the polyhedron referenced by <CODE>Handle_2</CODE>
   will remain unchanged as \f$\cP_2\f$.

<H2><CODE> ppl_Polyhedron_limited_BHRZ03_extrapolation_assign(+Handle_1,
               +Handle_2,
               +Constraint_System) </CODE></H2>

   If the polyhedron \f$\cP_1\f$ referenced by <CODE>Handle_1</CODE>
   contains the polyhedron \f$\cP_2\f$ referenced by <CODE>Handle_2</CODE>,
   then <CODE>Handle_1</CODE> will refer to
   the BHRZ03-extrapolation of \f$\cP_1\f$ with \f$\cP_2\f$
   improved by enforcing the constraints in
   <CODE>Constraint_System</CODE>.

<H2><CODE> ppl_Polyhedron_limited_BHRZ03_extrapolation_assign_with_tokens(
               +Handle_1,
               +Handle_2,
               +Constraint_System,
               +C_unsigned_1,
               ?C_unsigned_2) </CODE></H2>

   It is assumed that the polyhedron \f$\cP_1\f$ referenced by
   <CODE>Handle_1</CODE> contains the polyhedron \f$\cP_2\f$
   referenced by <CODE>Handle_2</CODE>;
   let \f$\cP\f$ denote the BHRZ03-extrapolation of
   \f$\cP_1\f$ with \f$\cP_2\f$,
   improved by enforcing those constraints in <CODE>Constraint_System</CODE>.
   <BR>
   Assuming that the quantity \f$t_1\f$ given by <CODE>C_unsigned_1</CODE>
   is the number of tokens available,
   <CODE>C_unsigned_2</CODE> will be unified with the number of tokens
   \f$t_2\f$ remaining at the end of the operation.
   <BR>
   If \f$t_1 > 0 \f$, then the polyhedron referenced by <CODE>Handle_1</CODE>
   will remain as \f$\cP_1\f$ and either \f$t_2 = t_1 - 1\f$ or \f$t_2 = t_1\f$
   depending on whether or not \f$\cP\f$ is different from \f$\cP_1\f$ itself.
   <BR>
   If \f$t_1 = 0\f$, then \f$t_2 = 0\f$
   and the polyhedron referenced by <CODE>Handle_1</CODE> is
   updated to  \f$\cP\f$.
   <BR>
   In all cases, the polyhedron referenced by <CODE>Handle_2</CODE>
   will remain unchanged as  \f$\cP_2\f$.

<H2><CODE> ppl_Polyhedron_bounded_BHRZ03_extrapolation_assign(+Handle_1,
               +Handle_2,
               +Constraint_System) </CODE></H2>

   If the polyhedron \f$\cP_1\f$ referenced by <CODE>Handle_1</CODE>
   contains the polyhedron \f$\cP_2\f$ referenced by <CODE>Handle_2</CODE>,
   then <CODE>Handle_1</CODE> will refer to
   the BHRZ03-extrapolation of \f$\cP_1\f$ with \f$\cP_2\f$
   improved by enforcing the constraints in
   <CODE>Constraint_System</CODE> together with all constraints of
   the form \f$\pm x \leq r\f$ and \f$\pm x < r\f$ that are satisfied
   by every point in \f$\cP_1\f$.

<H2><CODE> ppl_Polyhedron_bounded_BHRZ03_extrapolation_assign_with_tokens(
               +Handle_1,
               +Handle_2,
               +Constraint_System,
               +C_unsigned_1,
               ?C_unsigned_2) </CODE></H2>

   It is assumed that the polyhedron \f$\cP_1\f$ referenced by
   <CODE>Handle_1</CODE> contains the polyhedron \f$\cP_2\f$
   referenced by <CODE>Handle_2</CODE>;
   let \f$\cP\f$ denote the BHRZ03-extrapolation of \f$\cP_1\f$ with
   \f$\cP_2\f$, improved by enforcing those constraints in
   <CODE>Constraint_System</CODE> together with all constraints of
   the form \f$\pm x \leq r\f$ and \f$\pm x < r\f$ that are satisfied
   by every point in \f$\cP_1\f$.
   <BR>
   Assuming that the quantity \f$t_1\f$ given by <CODE>C_unsigned_1</CODE>
   is the number of tokens available,
   <CODE>C_unsigned_2</CODE> will be unified with the number of tokens
   \f$t_2\f$ remaining at the end of the operation.
   <BR>
   If \f$t_1 > 0 \f$, then the polyhedron referenced by <CODE>Handle_1</CODE>
   will remain as \f$\cP_1\f$ and either \f$t_2 = t_1 - 1\f$ or \f$t_2 = t_1\f$
   depending on whether or not \f$\cP\f$ is different from \f$\cP_1\f$ itself.
   <BR>
   If \f$t_1 = 0\f$, then \f$t_2 = 0\f$
   and the polyhedron referenced by <CODE>Handle_1</CODE> is
   updated to \f$\cP\f$.
   <BR>
   In all cases, the polyhedron referenced by <CODE>Handle_2</CODE>
   will remain unchanged as  \f$\cP_2\f$.

<H2><CODE> ppl_Polyhedron_H79_widening_assign(+Handle_1,
               +Handle_2) </CODE></H2>

   If the polyhedron \f$\cP_1\f$ referenced by <CODE>Handle_1</CODE>
   contains the polyhedron \f$\cP_2\f$ referenced by <CODE>Handle_2</CODE>,
   then <CODE>Handle_1</CODE> will refer to
   the H79-widening of \f$\cP_1\f$ with \f$\cP_2\f$.

<H2><CODE> ppl_Polyhedron_H79_widening_assign_with_tokens(+Handle_1,
               +Handle_2, +C_unsigned_1, ?C_unsigned_2) </CODE></H2>

   It is assumed that the polyhedron \f$\cP_1\f$ referenced by
   <CODE>Handle_1</CODE> contains the polyhedron \f$\cP_2\f$
   referenced by <CODE>Handle_2</CODE>;
   let \f$\cP\f$ denote the H79-widening of
   \f$\cP_1\f$ with \f$\cP_2\f$,
   <BR>
   Assuming that the quantity \f$t_1\f$ given by <CODE>C_unsigned_1</CODE>
   is the number of tokens available,
   <CODE>C_unsigned_2</CODE> will be unified with the number of tokens
   \f$t_2\f$ remaining at the end of the operation.
   <BR>
   If \f$t_1 > 0 \f$, then the polyhedron referenced by <CODE>Handle_1</CODE>
   will remain as \f$\cP_1\f$and either \f$t_2 = t_1 - 1\f$ or \f$t_2 = t_1\f$
   depending on whether or not \f$\cP\f$ is different from \f$\cP_1\f$ itself.
   <BR>
   If \f$t_1 = 0\f$, then \f$t_2 = 0\f$
   and the polyhedron referenced by <CODE>Handle_1</CODE> is
   updated to  \f$\cP\f$.
   <BR>
   In all cases, the polyhedron referenced by <CODE>Handle_2</CODE>
   will remain unchanged as \f$\cP_2\f$.

<H2><CODE> ppl_Polyhedron_limited_H79_extrapolation_assign(+Handle_1,
               +Handle_2,
               +Constraint_System) </CODE></H2>

   If the polyhedron \f$\cP_1\f$ referenced by <CODE>Handle_1</CODE>
   contains the polyhedron \f$\cP_2\f$ referenced by <CODE>Handle_2</CODE>,
   then <CODE>Handle_1</CODE> will refer to
   the H79-extrapolation of \f$\cP_1\f$ with \f$\cP_2\f$
   improved by enforcing the constraints in
   <CODE>Constraint_System</CODE>.

<H2><CODE> ppl_Polyhedron_limited_H79_extrapolation_assign_with_tokens(
               +Handle_1,
               +Handle_2,
               +Constraint_System,
               +C_unsigned_1,
               ?C_unsigned_2) </CODE></H2>

   It is assumed that the polyhedron \f$\cP_1\f$ referenced by
   <CODE>Handle_1</CODE> contains the polyhedron \f$\cP_2\f$
   referenced by <CODE>Handle_2</CODE>;
   let \f$\cP\f$ denote the H79-extrapolation of
   \f$\cP_1\f$ with \f$\cP_2\f$,
   improved by enforcing those constraints in <CODE>Constraint_System</CODE>.
   <BR>
   Assuming that the quantity \f$t_1\f$ given by <CODE>C_unsigned_1</CODE>
   is the number of tokens available,
   <CODE>C_unsigned_2</CODE> will be unified with the number of tokens
   \f$t_2\f$ remaining at the end of the operation.
   <BR>
   If \f$t_1 > 0 \f$, then the polyhedron referenced by <CODE>Handle_1</CODE>
   will remain as \f$\cP_1\f$ and either \f$t_2 = t_1 - 1\f$ or \f$t_2 = t_1\f$
   depending on whether or not \f$\cP\f$ is different from \f$\cP_1\f$ itself.
   <BR>
   If \f$t_1 = 0\f$, then \f$t_2 = 0\f$
   and the polyhedron referenced by <CODE>Handle_1</CODE> is
   updated to  \f$\cP\f$.
   <BR>
   In all cases, the polyhedron referenced by <CODE>Handle_2</CODE>
   will remain unchanged as  \f$\cP_2\f$.

<H2><CODE> ppl_Polyhedron_bounded_H79_extrapolation_assign(+Handle_1,
               +Handle_2,
               +Constraint_System) </CODE></H2>

   If the polyhedron \f$\cP_1\f$ referenced by <CODE>Handle_1</CODE>
   contains the polyhedron \f$\cP_2\f$ referenced by <CODE>Handle_2</CODE>,
   then <CODE>Handle_1</CODE> will refer to
   the H79-extrapolation of \f$\cP_1\f$ with \f$\cP_2\f$
   improved by enforcing the constraints in
   <CODE>Constraint_System</CODE> together with all constraints of
   the form \f$\pm x \leq r\f$ and \f$\pm x < r\f$ that are satisfied
   by every point in \f$\cP_1\f$.

<H2><CODE> ppl_Polyhedron_bounded_H79_extrapolation_assign_with_tokens(
               +Handle_1,
               +Handle_2,
               +Constraint_System,
               +C_unsigned_1,
               ?C_unsigned_2) </CODE></H2>

   It is assumed that the polyhedron \f$\cP_1\f$ referenced by
   <CODE>Handle_1</CODE> contains the polyhedron \f$\cP_2\f$
   referenced by <CODE>Handle_2</CODE>;
   let \f$\cP\f$ denote the H79-extrapolation of \f$\cP_1\f$ with
   \f$\cP_2\f$, improved by enforcing those constraints in
   <CODE>Constraint_System</CODE> together with all constraints of
   the form \f$\pm x \leq r\f$ and \f$\pm x < r\f$ that are satisfied
   by every point in \f$\cP_1\f$.
   <BR>
   Assuming that the quantity \f$t_1\f$ given by <CODE>C_unsigned_1</CODE>
   is the number of tokens available,
   <CODE>C_unsigned_2</CODE> will be unified with the number of tokens
   \f$t_2\f$ remaining at the end of the operation.
   <BR>
   If \f$t_1 > 0 \f$, then the polyhedron referenced by <CODE>Handle_1</CODE>
   will remain as \f$\cP_1\f$ and either \f$t_2 = t_1 - 1\f$ or \f$t_2 = t_1\f$
   depending on whether or not \f$\cP\f$ is different from \f$\cP_1\f$ itself.
   <BR>
   If \f$t_1 = 0\f$, then \f$t_2 = 0\f$
   and the polyhedron referenced by <CODE>Handle_1</CODE> is
   updated to \f$\cP\f$.
   <BR>
   In all cases, the polyhedron referenced by <CODE>Handle_2</CODE>
   will remain unchanged as  \f$\cP_2\f$.

<H2><CODE> ppl_Polyhedron_topological_closure_assign(+Handle) </CODE></H2>

   Assigns to the polyhedron referenced by <CODE>Handle</CODE>
   its topological closure.

<H2><CODE> ppl_Polyhedron_add_space_dimensions_and_embed(+Handle,
	+Dimension_Type)
 </CODE></H2>

   Embeds the polyhedron  referenced by <CODE>Handle</CODE>
   in a space that is enlarged by <CODE>Dimension_Type</CODE> dimensions,
   E.g.,
\code
   ?- ppl_new_C_Polyhedron_from_space_dimension(0, empty, X),
      ppl_Polyhedron_add_space_dimensions_and_embed(X, 2),
      ppl_Polyhedron_get_constraints(X, CS),
      ppl_Polyhedron_get_generators(X, GS).

   CS = [],
   GS = [point(0),line(1*A),line(1*B)]
\endcode

<H2><CODE> ppl_Polyhedron_concatenate_assign(+Handle_1, +Handle_2) </CODE></H2>

   Updates the polyhedron \f$\cP_1\f$ referenced  by <CODE>Handle_1</CODE>
   by first embedding \f$\cP_1\f$ in a new space enlarged by
   the space dimensions
   of the polyhedron \f$\cP_2\f$ referenced by <CODE>Handle_2</CODE>,
   and then adds to its system of constraints
   a renamed-apart version of the constraints of  \f$\cP_2\f$.

   E.g.,
\code
   ?- ppl_new_NNC_Polyhedron_from_space_dimension(2, universe, X),
      A = '$VAR'(0), B = '$VAR'(1), C = '$VAR'(2),
      D = '$VAR'(3), E = '$VAR'(4),
      ppl_new_NNC_Polyhedron_from_constraints([A > 1, B >= 0, C >= 0], Y),
      ppl_Polyhedron_concatenate_assign(X, Y),
      ppl_Polyhedron_get_constraints(X, CS).

   CS = [1*C > 1, 1*D >= 0, 1*E >= 0]
\endcode

<H2><CODE> ppl_Polyhedron_add_space_dimensions_and_project(+Handle,
                   +Dimension_Type)
 </CODE></H2>

   Projects the polyhedron  referenced by <CODE>Handle</CODE>
   onto a space that is enlarged by <CODE>Dimension_Type</CODE> dimensions,
   E.g.,
\code
   ?- ppl_new_C_Polyhedron_from_space_dimension(0, empty, X),
      ppl_Polyhedron_add_space_dimensions_and_project(X, 2),
      ppl_Polyhedron_get_constraints(X, CS),
      ppl_Polyhedron_get_generators(X, GS).

   CS = [1*A = 0, 1*B = 0],
   GS = [point(0)]
\endcode

<H2><CODE> ppl_Polyhedron_remove_space_dimensions(+Handle,
               +List_of_PPL_Vars) </CODE></H2>

   Removes the space dimensions given by the identifiers of the
   PPL variables in list <CODE>List_of_PPL_Vars</CODE>
   from the polyhedron  referenced by <CODE>Handle</CODE>.
   The identifiers for the remaining PPL variables are renumbered so that
   they are consecutive and the maximum index is less than the number
   of dimensions.
   E.g.,
\code
   ?- ppl_new_C_Polyhedron_from_space_dimension(3, empty, X),
      A='$VAR'(0), B = '$VAR'(1), C = '$VAR'(2),
      ppl_Polyhedron_remove_space_dimensions(X, [B]),
      ppl_Polyhedron_space_dimension(X, K),
      ppl_Polyhedron_get_generators(X, GS).

   K = 2,
   GS = [point(0),line(1*A),line(1*B),line(0)]
\endcode

<H2><CODE> ppl_Polyhedron_remove_higher_space_dimensions(+Handle, +Dimension_Type) </CODE></H2>

   Projects the polyhedron  referenced to by <CODE>Handle</CODE>
   onto  the first <CODE>Dimension_Type</CODE> dimension.
   E.g.,
\code
   ?- ppl_new_C_Polyhedron_from_space_dimension(5, empty, X),
      ppl_Polyhedron_remove_higher_space_dimensions(X, 3),
      ppl_Polyhedron_space_dimension(X, K).
\endcode

<H2><CODE>
  ppl_Polyhedron_expand_space_dimension(+Handle, +PPL_Var, +Dimension_Type)
</CODE></H2>

   <CODE>Dimension_Type</CODE> copies of the space dimension referenced by
   <CODE>PPL_Var</CODE> are added to the polyhedron
   referenced to by <CODE>Handle</CODE>.

<H2><CODE>
  ppl_Polyhedron_fold_space_dimensions(+Handle, +List_of_PPL_Vars, +PPL_Var)
</CODE></H2>

   The space dimensions referenced by the PPL variables in list
   <CODE>List_of_PPL_Vars</CODE> are folded into the dimension referenced
   by <CODE>PPL_Var</CODE> and removed.
   The result is undefined if <CODE>List_of_PPL_Vars</CODE>
   does not have the properties described in Section
   \extref{fold_space_dimensions, Folding Multiple Dimensions of the Vector Space into One Dimension}
   of the main PPL user manual.

<H2><CODE> ppl_Polyhedron_map_space_dimensions(+Handle, +P_Func) </CODE></H2>

   Maps the space dimensions of the polyhedron referenced by
   <CODE>Handle</CODE>
   using the partial function defined by <CODE>P_Func</CODE>.
   The result is undefined if \p P_Func does not encode a partial
   function with the properties described in
   Section \extref{Mapping_the_Dimensions_of_the_Vector_Space, Mapping the Dimensions of the Vector Space}
   of the main PPL user manual.

