# 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 System-Independent Features. Section Compilation and Installation explains how the various incarnations of the Prolog interface are compiled and installed. Section System-Dependent Features illustrates the system-dependent features of the interface for all the supported systems.

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

# System-Independent Features

The Prolog interface provides access to the PPL polyhedra. A general introduction to convex polyhedra, their representation in the PPL and the operations provided by the PPL is given in Sections The Main Features, Convex Polyhedra, Representations of Convex Polyhedra and Operations on Convex Polyhedra of this manual. Here we just describe those aspects that are specific to the Prolog interface.

## Overview

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

- The Prolog interface files are all installed in the directory `prefix/lib/ppl`. 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 `man ld.so` and `man ldconfig` for more information.
- The Prolog interface to the PPL is initialized and finalized by the predicates `ppl_initialize/0` and `ppl_finalize/0`. Thus the only interface predicates callable after `ppl_finalize/0` are `ppl_finalize/0` itself (this further call has no effect) and `ppl_initialize/0`, 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 `ppl_initialize/0` and/or `ppl_finalize/0` are called automatically. Section 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 `ppl_initialize/0` and `ppl_finalize/0` 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 polyhedron can only be accessed by means of a Prolog term called a handle. 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 by using predicates such as

        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,
        ppl_new_C_Polyhedron_from_bounding_box/2.

  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 polyhedron is no longer required, the memory occupied by it should be released using the PPL predicate `ppl_delete_Polyhedron/1`. 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 `ppl_delete_Polyhedron/1`, it becomes invalid.

- For a PPL polyhedron with space dimension `k`, the identifiers used for the PPL variables must lie between 0 and and correspond to the indices of the associated Cartesian axes. 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 Representations of Convex Polyhedra.

- 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 Representations of Convex Polyhedra.

- Any application using the PPL should make sure that only the intended version(s) of the library are ever used. Predicates

        ppl_version_major/1,
        ppl_version_minor/1,
        ppl_version_revision/1,
        ppl_version_beta/1,
        ppl_version/1,
        ppl_banner.

  allow run-time checking of information about the version being used.

## PPL Predicate List

Here is a list of all the PPL predicates provided by the Prolog interface.

`ppl_version_major(?C_int)`

`ppl_version_minor(?C_int)`

`ppl_version_revision(?C_int)`

`ppl_version_beta(?C_int)`

`ppl_version(?Atom)`

`ppl_banner(?Atom)`

`ppl_max_space_dimension(?Dimension_Type)`

`ppl_Coefficient_is_bounded`

`ppl_Coefficient_max(?Coefficient)`

`ppl_Coefficient_min(?Coefficient)`

`ppl_initialize`

`ppl_finalize`

`ppl_set_timeout_exception_atom(+Atom)`

`ppl_set_timeout(+C_unsigned)`

`ppl_reset_timeout`

`ppl_new_C_Polyhedron_from_space_dimension(+Dimension_Type, +Universe_or_Empty, -Handle)`

`ppl_new_NNC_Polyhedron_from_space_dimension(+Dimension_Type, +Universe_or_Empty, -Handle)`

`ppl_new_C_Polyhedron_from_C_Polyhedron(+Handle_1, -Handle_2)`

`ppl_new_C_Polyhedron_from_NNC_Polyhedron(+Handle_1, -Handle_2)`

`ppl_new_NNC_Polyhedron_from_C_Polyhedron(+Handle_1, -Handle_2)`

`ppl_new_NNC_Polyhedron_from_NNC_Polyhedron(+Handle_1, -Handle_2)`

`ppl_new_C_Polyhedron_from_constraints(+Constraint_System, -Handle)`

`ppl_new_NNC_Polyhedron_from_constraints(+Constraint_System, -Handle)`

`ppl_new_C_Polyhedron_from_generators(+Generator_System, -Handle)`

`ppl_new_NNC_Polyhedron_from_generators(+Generator_System, -Handle)`

`ppl_new_C_Polyhedron_from_bounding_box(+Box, -Handle)`

`ppl_new_NNC_Polyhedron_from_bounding_box(+Box, -Handle)`

`ppl_Polyhedron_swap(+Handle_1, +Handle_2)`

`ppl_delete_Polyhedron(+Handle)`

`ppl_Polyhedron_space_dimension(+Handle, ?Dimension_Type)`

`ppl_Polyhedron_affine_dimension(+Handle, ?Dimension_Type)`

`ppl_Polyhedron_get_constraints(+Handle, -Constraint_System)`

`ppl_Polyhedron_get_minimized_constraints(+Handle, -Constraint_System)`

`ppl_Polyhedron_get_generators(+Handle, -Generator_System)`

`ppl_Polyhedron_get_minimized_generators(+Handle, -Generator_System)`

`ppl_Polyhedron_relation_with_constraint(+Handle, +Constraint, -Relation)`

`ppl_Polyhedron_relation_with_generator(+Handle, +Generator, -Relation)`

`ppl_Polyhedron_get_bounding_box(+Handle, +Complexity, -Box)`

`ppl_Polyhedron_is_empty(+Handle)`

`ppl_Polyhedron_is_universe(+Handle)`

`ppl_Polyhedron_is_bounded(+Handle)`

`ppl_Polyhedron_bounds_from_above(+Handle, +Lin_Expr)`

`ppl_Polyhedron_bounds_from_below(+Handle, +Lin_Expr)`

`ppl_Polyhedron_maximize(+Handle, +Lin_Expr, ?Coefficient_1, ?Coefficient_2, ?Boolean)`

`ppl_Polyhedron_maximize_with_point(+Handle, +Lin_Expr, ?Coefficient_1, ?Coefficient_2, ?Boolean, ?Point)`

`ppl_Polyhedron_minimize(+Handle, +Lin_Expr, ?Coefficient_1, ?Coefficient_2, ?Boolean)`

`ppl_Polyhedron_minimize_with_point(+Handle, +Lin_Expr, ?Coefficient_1, ?Coefficient_2, ?Boolean, ?Point)`

`ppl_Polyhedron_is_topologically_closed(+Handle)`

`ppl_Polyhedron_contains_Polyhedron(+Handle_1, +Handle_2)`

`ppl_Polyhedron_strictly_contains_Polyhedron(+Handle_1, +Handle_2)`

`ppl_Polyhedron_is_disjoint_from_Polyhedron(+Handle_1, +Handle_2)`

`ppl_Polyhedron_equals_Polyhedron(+Handle_1, +Handle_2)`

`ppl_Polyhedron_OK(+Handle)`

`ppl_Polyhedron_add_constraint(+Handle, +Constraint)`

`ppl_Polyhedron_add_constraint_and_minimize(+Handle, +Constraint)`

`ppl_Polyhedron_add_generator(+Handle, +Generator)`

`ppl_Polyhedron_add_generator_and_minimize(+Handle, +Generator)`

`ppl_Polyhedron_add_constraints(+Handle, +Constraint_System)`

`ppl_Polyhedron_add_constraints_and_minimize(+Handle, +Constraint_System)`

`ppl_Polyhedron_add_generators(+Handle, +Generator_System)`

`ppl_Polyhedron_add_generators_and_minimize(+Handle, +Generator_System)`

`ppl_Polyhedron_intersection_assign(+Handle_1, +Handle_2)`

`ppl_Polyhedron_intersection_assign_and_minimize(+Handle_1, +Handle_2)`

`ppl_Polyhedron_poly_hull_assign(+Handle_1, +Handle_2)`

`ppl_Polyhedron_poly_hull_assign_and_minimize(+Handle_1, +Handle_2)`

`ppl_Polyhedron_poly_difference_assign(+Handle_1, +Handle_2)`

`ppl_Polyhedron_affine_image(+Handle, +PPL_Var, +Lin_Expr, +Coefficient)`

`ppl_Polyhedron_affine_preimage(+Handle, +PPL_Var, +Lin_Expr, +Coefficient)`

`ppl_Polyhedron_bounded_affine_image(+Handle, +PPL_Var, +Lin_Expr_1, +Lin_Expr_2, +Coefficient)`

`ppl_Polyhedron_generalized_affine_image(+Handle, +PPL_Var, +Relation_Symbol, +Lin_Expr, +Coefficient)`

`ppl_Polyhedron_generalized_affine_image_lhs_rhs(+Handle, +Lin_Expr_1, +Relation_Symbol, +Lin_Expr_2)`

`ppl_Polyhedron_time_elapse_assign(+Handle_1, +Handle_2)`

`ppl_Polyhedron_BHRZ03_widening_assign_with_tokens(+Handle_1, +Handle_2, +C_unsigned_1, ?C_unsigned_2)`

`ppl_Polyhedron_BHRZ03_widening_assign(+Handle_1, +Handle_2)`

`ppl_Polyhedron_limited_BHRZ03_extrapolation_assign_with_tokens(+Handle_1, +Handle_2, +Constraint_System, +C_unsigned_1, ?C_unsigned_2)`

`ppl_Polyhedron_limited_BHRZ03_extrapolation_assign(+Handle_1, +Handle_2, +Constraint_System)`

`ppl_Polyhedron_bounded_BHRZ03_extrapolation_assign_with_tokens(+Handle_1, +Handle_2, +Constraint_System, +C_unsigned_1, ?C_unsigned_2)`

`ppl_Polyhedron_bounded_BHRZ03_extrapolation_assign(+Handle_1, +Handle_2, +Constraint_System)`

`ppl_Polyhedron_H79_widening_assign_with_tokens(+Handle_1, +Handle_2, +C_unsigned_1, ?C_unsigned_2)`

`ppl_Polyhedron_H79_widening_assign(+Handle_1, +Handle_2)`

`ppl_Polyhedron_limited_H79_extrapolation_assign_with_tokens(+Handle_1, +Handle_2, +Constraint_System, +C_unsigned_1, ?C_unsigned_2)`

`ppl_Polyhedron_limited_H79_extrapolation_assign(+Handle_1, +Handle_2, +Constraint_System)`

`ppl_Polyhedron_bounded_H79_extrapolation_assign_with_tokens(+Handle_1, +Handle_2, +Constraint_System, +C_unsigned_1, ?C_unsigned_2)`

`ppl_Polyhedron_bounded_H79_extrapolation_assign(+Handle_1, +Handle_2, +Constraint_System)`

`ppl_Polyhedron_topological_closure_assign(+Handle)`

`ppl_Polyhedron_add_space_dimensions_and_embed(+Handle, +Dimension_Type)`

`ppl_Polyhedron_add_space_dimensions_and_project(+Handle, +Dimension_Type)`

`ppl_Polyhedron_concatenate_assign(+Handle_1, +Handle_2)`

`ppl_Polyhedron_remove_space_dimensions(+Handle, +List_of_PPL_Vars)`

`ppl_Polyhedron_remove_higher_space_dimensions(+Handle, +Dimension_Type))`

`ppl_Polyhedron_expand_space_dimension(+Handle, +PPL_Var, +Dimension_Type))`

`ppl_Polyhedron_fold_space_dimensions(+Handle, +List_of_PPL_Vars, +PPL_Var))`

`ppl_Polyhedron_map_space_dimensions(+Handle, +P_Func))`

`ppl_new_LP_Problem_trivial(-Handle)`

`ppl_new_LP_Problem(+Constraint_System, +Lin_Expr, +Optimization_Mode, -Handle)`

`ppl_new_LP_Problem_from_LP_Problem(+Handle_1, -Handle_2)`

`ppl_LP_Problem_swap(+Handle_1, +Handle_2)`

`ppl_delete_LP_Problem(+Handle)`

`ppl_LP_Problem_space_dimension(+Handle, ?Dimension_Type)`

`ppl_LP_Problem_constraints(+Handle, -Constraint_System)`

`ppl_LP_Problem_objective_function(+Handle, -Lin_Expr)`

`ppl_LP_Problem_optimization_mode(+Handle, ?Optimization_Mode)`

`ppl_LP_Problem_clear(+Handle)`

`ppl_LP_Problem_add_constraint(+Handle, +Constraint)`

`ppl_LP_Problem_add_constraints(+Handle, +Constraint_System)`

`ppl_LP_Problem_set_objective_function(+Handle, +Lin_Expr)`

`ppl_LP_Problem_set_optimization_mode(+Handle, +Optimization_Mode)`

`ppl_LP_Problem_is_satisfiable(+Handle)`

`ppl_LP_Problem_solve(+Handle, ?LP_Problem_Status)`

`ppl_LP_Problem_feasible_point(+Handle, -Generator)`

`ppl_LP_Problem_optimizing_point(+Handle, -Generator)`

`ppl_LP_Problem_optimal_value(+Handle, ?Coefficient_1, ?Coefficient_2)`

`ppl_LP_Problem_evaluate_objective_function(+Handle, +Generator, ?Coefficient_1, ?Coefficient_2)`

`ppl_LP_Problem_OK(+Handle)`

## PPL Predicate Specifications

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

     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

     Poly_Relation_List                     list of polyhedron relations
                 --> []
                | [Poly_Relation | Poly_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

     LP_Problem_Status
                 --> unfeasible | unbounded | optimized

Below is a short description of each of the interface predicates. For full definitions of terminology used here, see Sections The Main Features, Convex Polyhedra, Representations of Convex Polyhedra and Operations on Convex Polyhedra of this manual.

## `ppl_version_major(?C_int)`

Unifies `C_int` with the major number of the PPL version.

## `ppl_version_minor(?C_int)`

Unifies `C_int` with the minor number of the PPL version.

## `ppl_version_revision(?C_int)`

Unifies `C_int` with the revision number of the PPL version.

## `ppl_version_beta(?C_int)`

Unifies `C_int` with the beta number of the PPL version.

## `ppl_version(?Atom)`

Unifies `Atom` with the PPL version.

## `ppl_banner(?Atom)`

Unifies `Atom` 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.

## `ppl_Coefficient_is_bounded`

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

## `ppl_Coefficient_max(Max)`

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

## `ppl_Coefficient_min(Min)`

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

## `ppl_max_space_dimension(?Dimension_Type)`

Unifies `Dimension_Type` with the maximum space dimension this library can handle.

## `ppl_initialize`

Initializes the PPL interface. Multiple calls to `ppl_initialize` does no harm.

## `ppl_finalize`

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

## `ppl_set_timeout_exception_atom(+Atom)`

Sets the atom to be thrown by timeout exceptions to `Atom`. The default value is `time_out`.

## `ppl_timeout_exception_atom(?Atom)`

The atom to be thrown by timeout exceptions is unified with `Atom`.

## `ppl_set_timeout(+C_unsigned)`

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

## `ppl_reset_timeout`

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

## `ppl_new_C_Polyhedron_from_space_dimension(+Dimension_Type, +Universe_or_Empty, -Handle)`

Creates a C polyhedron with `Dimension_Type` dimensions; it is empty or the universe polyhedron depending on whether `Atom` is `empty` or `universe`, respectively. `Handle` is unified with the handle for . Thus the query

       ?- ppl_new_C_Polyhedron_from_space_dimension(3, universe, X).

creates the C polyhedron defining the 3-dimensional vector space with `X` bound to a valid handle for accessing it.

## `ppl_new_NNC_Polyhedron_from_space_dimension(+Dimension_Type, +Universe_or_Empty, -Handle)`

Creates an NNC polyhedron with `Dimension_Type` dimensions; it is empty or the universe polyhedron depending on whether `Atom` is `empty` or `universe`, respectively. `Handle` is unified with the handle for . Thus the query

       ?- ppl_new_NNC_Polyhedron_from_space_dimension(3, empty, X).

creates an empty NNC polyhedron embedded in with `X` bound to a valid handle for accessing it.

## `ppl_new_C_Polyhedron_from_C_Polyhedron(+Handle_1, -Handle_2)`

If `Handle_1` refers to a C polyhedron , then this creates a copy of . `Handle_2` is unified with the handle for .

## `ppl_new_C_Polyhedron_from_NNC_Polyhedron(+Handle_1, -Handle_2)`

If `Handle_1` refers to an NNC polyhedron , then this creates a copy of as a C polyhedron . `Handle_2` is unified with the handle for . Thus the query

       ?- ppl_new_NNC_Polyhedron_from_space_dimension(3, empty, X),
          ppl_new_C_Polyhedron_from_NNC_Polyhedron(X, Y).

creates an empty NNC polyhedron embedded in referenced by `X` and then makes a copy, converting the topology to a C polyhedron. with `Y` bound to a valid handle for accessing it.

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

## `ppl_new_NNC_Polyhedron_from_C_Polyhedron(+Handle_1, -Handle_2)`

If `Handle_1` refers to a C polyhedron , then this creates a copy of as an NNC polyhedron . `Handle_2` is unified with the handle for .

## `ppl_new_NNC_Polyhedron_from_NNC_Polyhedron(+Handle_1, -Handle_2)`

If `Handle_1` refers to a NNC polyhedron , then this creates a copy of . `Handle_2` is unified with the handle for .

## `ppl_new_C_Polyhedron_from_constraints(+Constraint_System, -Handle)`

Creates a C polyhedron represented by `Constraint_System`. `Handle` is unified with the handle for .

## `ppl_new_NNC_Polyhedron_from_constraints(+Constraint_System, -Handle)`

Creates an NNC polyhedron represented by `Constraint_System`. `Handle` is unified with the handle for .

## `ppl_new_C_Polyhedron_from_generators(+Generator_System, -Handle)`

Creates a C polyhedron represented by `Generator_System`. `Handle` is unified with the handle for .

## `ppl_new_NNC_Polyhedron_from_generators(+Generator_System, -Handle)`

Creates an NNC polyhedron represented by `Generator_System`. `Handle` is unified with the handle for .

## `ppl_new_C_Polyhedron_from_bounding_box(+Box, -Handle)`

Creates a C polyhedron represented by `Box`. `Handle` is unified with the handle for . There must be no bounds of the form `o(Rational)` in an interval in `Box`.

## `ppl_new_NNC_Polyhedron_from_bounding_box(+Box, -Handle)`

Creates an NNC polyhedron represented by `Box`. `Handle` is unified with the handle for .

## `ppl_Polyhedron_swap(+Handle_1, +Handle_2)`

Swaps the polyhedron referenced by `Handle_1` with the one referenced by `Handle_2`. The polyhedra and must have the same topology.

## `ppl_delete_Polyhedron(+Handle)`

Deletes the polyhedron referenced by `Handle`. After execution, `Handle` is no longer a valid handle for a PPL polyhedron.

## `ppl_Polyhedron_space_dimension(+Handle, ?Dimension_Type)`

Unifies the dimension of the vector space in which the polyhedron referenced by `Handle` is embedded with `Dimension_Type`.

## `ppl_Polyhedron_affine_dimension(+Handle, ?Dimension_Type)`

Unifies the actual dimension of the polyhedron referenced by `Handle` with `Dimension_Type`.

## `ppl_Polyhedron_get_constraints(+Handle, ?Constraint_System)`

Unifies `Constraint_System` with a list of the constraints in the constraints system representing the polyhedron referenced by `Handle`.

## `ppl_Polyhedron_get_minimized_constraints(+Handle, ?Constraint_System)`

Unifies `Constraint_System` with a minimized list of the constraints in the constraints system representing the polyhedron referenced by `Handle`.

## `ppl_Polyhedron_get_generators(+Handle, ?Generator_System)`

Unifies `Generator_System` with a list of the generators in the generators system representing the polyhedron referenced by `Handle`.

## `ppl_Polyhedron_get_minimized_generators(+Handle, ?Generator_System)`

Unifies `Generator_System` with a minimized list of the generators in the generators system representing the polyhedron referenced by `Handle`.

## `ppl_Polyhedron_relation_with_constraint(+Handle, +Constraint, ?Poly_Relation_List)`

Unifies `Poly_Relation_List` with the list of relations the polyhedron referenced by `Handle` has with `Constraint`. The possible relations are listed in the grammar rules above; their meaning is given in Section specifying the relation_with operations.

## `ppl_Polyhedron_relation_with_generator(+Handle, +Generator, ?Poly_Relation_List)`

Unifies `Poly_Relation_List` with the list of relations the polyhedron referenced by `Handle` has with `Generator`. The possible relations are listed in the grammar rules above; their meaning is given in Section specifying the relation_with operations.

## `ppl_Polyhedron_get_bounding_box(+Handle, +Complexity, ?Box)`

Succeeds if and only if the bounding box of the polyhedron referenced by `Handle` unifies with the box defined by `Box`. E.g.,

       ?- 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))].

Note that the rational numbers in `Box` are in canonical form. E.g., the following will fail:

       ?- 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))].

The complexity class `Complexity` determining the algorithm to be used has the following meaning:

- `polynomial` allows code of the worst-case polynomial complexity class;
- `simplex` allows code of the worst-case exponential but typically polynomial complexity class;
- `any` allows code of the universal complexity class.

## `ppl_Polyhedron_is_empty(+Handle)`

Succeeds if and only if the polyhedron referenced by `Handle` is empty.

## `ppl_Polyhedron_is_universe(+Handle)`

Succeeds if and only if the polyhedron referenced by `Handle` is the universe.

## `ppl_Polyhedron_is_bounded(+Handle)`

Succeeds if and only if the polyhedron referenced by `Handle` is bounded.

## `ppl_Polyhedron_bounds_from_above(+Handle, +Lin_Expr)`

Succeeds if and only if `Lin_Expr` is bounded from above in the polyhedron referenced by `Handle`.

## `ppl_Polyhedron_bounds_from_below(+Handle, +Lin_Expr)`

Succeeds if and only if `Lin_Expr` is bounded from below in the polyhedron referenced by `Handle`.

### `ppl_Polyhedron_maximize(+Handle, +Lin_Expr, ?Coefficient_1, ?Coefficient_2, ?Boolean)`

Succeeds if and only if the polyhedron referenced by `Handle` is not empty and `Lin_Expr` is bounded from above in .

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

## `ppl_Polyhedron_maximize_with_point(+Handle, +Lin_Expr, ?Coefficient_1, ?Coefficient_2, ?Boolean, ?Point)`

Succeeds if and only if the polyhedron referenced by `Handle` is not empty and `Lin_Expr` is bounded from above in .

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

## `ppl_Polyhedron_minimize(+Handle, +Lin_Expr, ?Coefficient_1, ?Coefficient_2, ?Boolean)`

Succeeds if and only if the polyhedron referenced by `Handle` is not empty and `Lin_Expr` is bounded from below in .

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

## `ppl_Polyhedron_minimize_with_point(+Handle, +Lin_Expr, ?Coefficient_1, ?Coefficient_2, ?Boolean, ?Point)`

Succeeds if and only if the polyhedron referenced by `Handle` is not empty and `Lin_Expr` is bounded from below in .

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

## `ppl_Polyhedron_is_topologically_closed(+Handle)`

Succeeds if and only if the polyhedron referenced by `Handle` is topologically closed.

## `ppl_Polyhedron_contains_Polyhedron(+Handle_1, +Handle_2)`

Succeeds if and only if the polyhedron referenced by `Handle_2` is included in or equal to the polyhedron referenced by `Handle_1`.

## `ppl_Polyhedron_strictly_contains_Polyhedron(+Handle_1, +Handle_2)`

Succeeds if and only if the polyhedron referenced by `Handle_2` is included in but not equal to the polyhedron referenced by `Handle_1`.

## `ppl_Polyhedron_is_disjoint_from_Polyhedron(+Handle_1, +Handle_2)`

Succeeds if and only if the polyhedron referenced by `Handle_1` is disjoint from the polyhedron referenced by `Handle_2`.

## `ppl_Polyhedron_equals_Polyhedron(+Handle_1, +Handle_2)`

Succeeds if and only if the polyhedron referenced by `Handle_1` is equal to the polyhedron referenced by `Handle_2`.

## `ppl_Polyhedron_OK(+Handle)`

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

## `ppl_Polyhedron_add_constraint(+Handle, +Constraint)`

## `ppl_Polyhedron_add_constraint_and_minimize(+Handle, +Constraint)`

Updates the polyhedron referenced by `Handle` to one obtained by adding `Constraint` to its constraint system. Thus, the query

       ?- 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).

will update the polyhedron with handle `X` to consist of the set of points in the vector space satisfying the constraint .

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

## `ppl_Polyhedron_add_generator(+Handle, +Generator)`

## `ppl_Polyhedron_add_generator_and_minimize(+Handle, +Generator)`

Updates the polyhedron referenced by `Handle` to one obtained by adding `Generator` to its generator system. Thus, after the query

       ?- 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)).

will update the polyhedron with handle `X` to be the single point in the vector space .

## `ppl_Polyhedron_add_constraints(+Handle, +Constraint_System)`

Updates the polyhedron referenced by `Handle` to one obtained by adding to its constraint system the constraints in `Constraint_System`. E.g.,

       | ?- 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] ?

The updated polyhedron referenced by `Handle` can be empty and a query will succeed even when `Constraint_System` is unsatisfiable.

## `ppl_Polyhedron_add_constraints_and_minimize(+Handle, +Constraint_System)`

Updates the polyhedron referenced by `Handle` to one obtained by adding to its constraint system the constraints in `Constraint_System`. E.g.,

       ?- 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]

This will fail if, after adding the constraints, the polyhedron is empty. E.g., the following will fail,

       ?- 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).

## `ppl_C_Polyhedron_add_generators(+Handle, +Generator_System)`

Updates the polyhedron referenced by `Handle` to one obtained by adding to its generator system the generators in `Generator_System`.

If the system of generators representing a polyhedron is non-empty, then it must include a point (see Section Generators Representation). Thus care must be taken to ensure that, before calling this predicate, either the polyhedron referenced by `Handle` is non-empty or that whenever `Generator_System` is non-empty the first element defines a point. E.g.,

       ?- 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)]

## `ppl_Polyhedron_add_generators_and_minimize(+Handle, +Generator_System)`

Updates the polyhedron referenced by `Handle` to one obtained by adding to its generator system the generators in `Generator_System`.

Unlike the predicate `ppl_add_generators`, the order of the generators in `Generator_System` is not important. E.g.,

       ?- 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)]

## `ppl_Polyhedron_intersection_assign(+Handle_1, +Handle_2)`

## `ppl_Polyhedron_intersection_assign_and_minimize(+Handle_1, +Handle_2)`

Assigns to the polyhedron referenced by `Handle_1` its intersection with the polyhedron referenced by `Handle_2`.

## `ppl_Polyhedron_poly_hull_assign(+Handle_1, +Handle_2)`

## `ppl_Polyhedron_poly_hull_assign_and_minimize(+Handle_1, +Handle_2)`

Assigns to the polyhedron referenced by `Handle_1` its poly-hull with the polyhedron referenced by `Handle_2`.

## `ppl_Polyhedron_poly_difference_assign(+Handle_1, +Handle_2)`

Assigns to the polyhedron referenced by `Handle_1` its poly-difference with the polyhedron referenced by `Handle_2`.

## `ppl_Polyhedron_affine_image(+Handle, +PPL_Var, +Lin_Expr, +Coefficient)`

Transforms the polyhedron referenced by `Handle` assigning the affine expression `Lin_Expr`/`Coefficient` to `PPL_Var`.

## `ppl_Polyhedron_affine_preimage(+Handle, +PPL_Var, +Lin_Expr, +Coefficient)`

This is the inverse transformation to that for `ppl_affine_image`.

## `ppl_Polyhedron_bounded_affine_image(+Handle, +PPL_Var, +Lin_Expr_1, +Lin_Expr_2, +Coefficient)`

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

## `ppl_Polyhedron_generalized_affine_image(+Handle, +PPL_Var, +Relation_Symbol +Lin_Expr, +Coefficient)`

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

## `ppl_Polyhedron_generalized_affine_image_lhs_rhs(+Handle, +Lin_Expr_1, +Relation_Symbol +Lin_Expr_2)`

Transforms the polyhedron referenced by `Handle` assigning the generalized affine image with respect to the transfer function `Lin_Expr_1` `Relation_Symbol` `Lin_Expr_2`.

## `ppl_Polyhedron_time_elapse_assign(+Handle_1, +Handle_2)`

Assigns to the polyhedron referenced by `Handle_1` the time-elapse with the polyhedron referenced by `Handle_2`.

## `ppl_Polyhedron_BHRZ03_widening_assign(+Handle_1, +Handle_2)`

If the polyhedron referenced by `Handle_1` contains the polyhedron referenced by `Handle_2`, then `Handle_1` will refer to the BHRZ03-widening of with .

## `ppl_Polyhedron_BHRZ03_widening_assign_with_tokens(+Handle_1, +Handle_2, +C_unsigned_1, ?C_unsigned_2)`

It is assumed that the polyhedron referenced by `Handle_1` contains the polyhedron referenced by `Handle_2`; let denote the BHRZ03-widening of with , Assuming that the quantity given by `C_unsigned_1` is the number of tokens available, `C_unsigned_2` will be unified with the number of tokens remaining at the end of the operation.
If , then the polyhedron referenced by `Handle_1` will remain as and either or depending on whether or not is different from itself.
If , then and the polyhedron referenced by `Handle_1` is updated to .
In all cases, the polyhedron referenced by `Handle_2` will remain unchanged as .

## `ppl_Polyhedron_limited_BHRZ03_extrapolation_assign(+Handle_1, +Handle_2, +Constraint_System)`

If the polyhedron referenced by `Handle_1` contains the polyhedron referenced by `Handle_2`, then `Handle_1` will refer to the BHRZ03-extrapolation of with improved by enforcing the constraints in `Constraint_System`.

## `ppl_Polyhedron_limited_BHRZ03_extrapolation_assign_with_tokens( +Handle_1, +Handle_2, +Constraint_System, +C_unsigned_1, ?C_unsigned_2)`

It is assumed that the polyhedron referenced by `Handle_1` contains the polyhedron referenced by `Handle_2`; let denote the BHRZ03-extrapolation of with , improved by enforcing those constraints in `Constraint_System`.
Assuming that the quantity given by `C_unsigned_1` is the number of tokens available, `C_unsigned_2` will be unified with the number of tokens remaining at the end of the operation.
If , then the polyhedron referenced by `Handle_1` will remain as and either or depending on whether or not is different from itself.
If , then and the polyhedron referenced by `Handle_1` is updated to .
In all cases, the polyhedron referenced by `Handle_2` will remain unchanged as .

## `ppl_Polyhedron_bounded_BHRZ03_extrapolation_assign(+Handle_1, +Handle_2, +Constraint_System)`

If the polyhedron referenced by `Handle_1` contains the polyhedron referenced by `Handle_2`, then `Handle_1` will refer to the BHRZ03-extrapolation of with improved by enforcing the constraints in `Constraint_System` together with all constraints of the form and that are satisfied by every point in .

## `ppl_Polyhedron_bounded_BHRZ03_extrapolation_assign_with_tokens( +Handle_1, +Handle_2, +Constraint_System, +C_unsigned_1, ?C_unsigned_2)`

It is assumed that the polyhedron referenced by `Handle_1` contains the polyhedron referenced by `Handle_2`; let denote the BHRZ03-extrapolation of with , improved by enforcing those constraints in `Constraint_System` together with all constraints of the form and that are satisfied by every point in .
Assuming that the quantity given by `C_unsigned_1` is the number of tokens available, `C_unsigned_2` will be unified with the number of tokens remaining at the end of the operation.
If , then the polyhedron referenced by `Handle_1` will remain as and either or depending on whether or not is different from itself.
If , then and the polyhedron referenced by `Handle_1` is updated to .
In all cases, the polyhedron referenced by `Handle_2` will remain unchanged as .

## `ppl_Polyhedron_H79_widening_assign(+Handle_1, +Handle_2)`

If the polyhedron referenced by `Handle_1` contains the polyhedron referenced by `Handle_2`, then `Handle_1` will refer to the H79-widening of with .

## `ppl_Polyhedron_H79_widening_assign_with_tokens(+Handle_1, +Handle_2, +C_unsigned_1, ?C_unsigned_2)`

It is assumed that the polyhedron referenced by `Handle_1` contains the polyhedron referenced by `Handle_2`; let denote the H79-widening of with ,
Assuming that the quantity given by `C_unsigned_1` is the number of tokens available, `C_unsigned_2` will be unified with the number of tokens remaining at the end of the operation.
If , then the polyhedron referenced by `Handle_1` will remain as and either or depending on whether or not is different from itself.
If , then and the polyhedron referenced by `Handle_1` is updated to .
In all cases, the polyhedron referenced by `Handle_2` will remain unchanged as .

## `ppl_Polyhedron_limited_H79_extrapolation_assign(+Handle_1, +Handle_2, +Constraint_System)`

If the polyhedron referenced by `Handle_1` contains the polyhedron referenced by `Handle_2`, then `Handle_1` will refer to the H79-extrapolation of with improved by enforcing the constraints in `Constraint_System`.

## `ppl_Polyhedron_limited_H79_extrapolation_assign_with_tokens( +Handle_1, +Handle_2, +Constraint_System, +C_unsigned_1, ?C_unsigned_2)`

It is assumed that the polyhedron referenced by `Handle_1` contains the polyhedron referenced by `Handle_2`; let denote the H79-extrapolation of with , improved by enforcing those constraints in `Constraint_System`.
Assuming that the quantity given by `C_unsigned_1` is the number of tokens available, `C_unsigned_2` will be unified with the number of tokens remaining at the end of the operation.
If , then the polyhedron referenced by `Handle_1` will remain as and either or depending on whether or not is different from itself.
If , then and the polyhedron referenced by `Handle_1` is updated to .
In all cases, the polyhedron referenced by `Handle_2` will remain unchanged as .

## `ppl_Polyhedron_bounded_H79_extrapolation_assign(+Handle_1, +Handle_2, +Constraint_System)`

If the polyhedron referenced by `Handle_1` contains the polyhedron referenced by `Handle_2`, then `Handle_1` will refer to the H79-extrapolation of with improved by enforcing the constraints in `Constraint_System` together with all constraints of the form and that are satisfied by every point in .

## `ppl_Polyhedron_bounded_H79_extrapolation_assign_with_tokens( +Handle_1, +Handle_2, +Constraint_System, +C_unsigned_1, ?C_unsigned_2)`

It is assumed that the polyhedron referenced by `Handle_1` contains the polyhedron referenced by `Handle_2`; let denote the H79-extrapolation of with , improved by enforcing those constraints in `Constraint_System` together with all constraints of the form and that are satisfied by every point in .
Assuming that the quantity given by `C_unsigned_1` is the number of tokens available, `C_unsigned_2` will be unified with the number of tokens remaining at the end of the operation.
If , then the polyhedron referenced by `Handle_1` will remain as and either or depending on whether or not is different from itself.
If , then and the polyhedron referenced by `Handle_1` is updated to .
In all cases, the polyhedron referenced by `Handle_2` will remain unchanged as .

## `ppl_Polyhedron_topological_closure_assign(+Handle)`

Assigns to the polyhedron referenced by `Handle` its topological closure.

## `ppl_Polyhedron_add_space_dimensions_and_embed( +Handle, +Dimension_Type)`

Embeds the polyhedron referenced by `Handle` in a space that is enlarged by `Dimension_Type` dimensions, E.g.,

       ?- 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)]

## `ppl_Polyhedron_concatenate_assign(+Handle_1, +Handle_2)`

Updates the polyhedron referenced by `Handle_1` by first embedding in a new space enlarged by the space dimensions of the polyhedron referenced by `Handle_2`, and then adds to its system of constraints a renamed-apart version of the constraints of .

E.g.,

       ?- 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]

## `ppl_Polyhedron_add_space_dimensions_and_project(+Handle, +Dimension_Type)`

Projects the polyhedron referenced by `Handle` onto a space that is enlarged by `Dimension_Type` dimensions, E.g.,

       ?- 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)]

## `ppl_Polyhedron_remove_space_dimensions(+Handle, +List_of_PPL_Vars)`

Removes the space dimensions given by the identifiers of the PPL variables in list `List_of_PPL_Vars` from the polyhedron referenced by `Handle`. 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.,

       ?- 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)]

## `ppl_Polyhedron_remove_higher_space_dimensions(+Handle, +Dimension_Type))`

Projects the polyhedron referenced to by `Handle` onto the first `Dimension_Type` dimension. E.g.,

       ?- ppl_new_C_Polyhedron_from_space_dimension(5, empty, X),
          ppl_Polyhedron_remove_higher_space_dimensions(X, 3),
          ppl_Polyhedron_space_dimension(X, K).

## `ppl_Polyhedron_expand_space_dimension(+Handle, +PPL_Var, +Dimension_Type))`

`Dimension_Type` copies of the space dimension referenced by `PPL_Var` are added to the polyhedron referenced to by `Handle`.

## `ppl_Polyhedron_fold_space_dimensions(+Handle, +List_of_PPL_Vars, +PPL_Var))`

The space dimensions referenced by the PPL variables in list `List_of_PPL_Vars` are folded into the dimension referenced by `PPL_Var` and removed. The result is undefined if `List_of_PPL_Vars` does not have the properties described in Section fold_space_dimensions.

## `ppl_Polyhedron_map_space_dimensions(+Handle, +P_Func))`

Maps the space dimensions of the polyhedron referenced by `Handle` using the partial function defined by `P_Func`. The result is undefined if `P_Func` does not encode a partial function with the properties described in Section specifying the map_space_dimensions operator.

## `ppl_new_LP_Problem_trivial(-Handle)`

Creates an LP Problem with the feasible region the -dimensional universe, objective function and optimization mode `max`. `Handle` is unified with the handle for .

## `ppl_new_LP_Problem(+Constraint_System, +Lin_Expr, +Optimization_Mode, -Handle)`

Creates an LP Problem with the feasible region represented by `Constraint_System`, objective function `Lin_Expr` and optimization mode `Optimization_Mode`. `Handle` is unified with the handle for .

## `ppl_LP_Problem_swap(+Handle_1, +Handle_2)`

Swaps the LP Problem referenced by `Handle_1` with the one referenced by `Handle_2`.

## `ppl_delete_LP_Problem(+Handle)`

Deletes the LP Problem referenced by `Handle`. After execution, `Handle` is no longer a valid handle for a PPL LP Problem.

## `ppl_LP_Problem_space_dimension(+Handle, ?Dimension_Type)`

Unifies the dimension of the vector space in which the LP Problem referenced by `Handle` is embedded with `Dimension_Type`.

## `ppl_LP_Problem_constraints(+Handle, -Constraint_System)`

Unifies `Constraint_System` with a list of the constraints in the constraints system representing the feasible region for the LP Problem referenced by `Handle`.

## `ppl_LP_Problem_objective_function(+Handle, -Lin_Expr)`

Unifies `Lin_Expr` with the objective function for the LP Problem referenced by `Handle`.

## `ppl_LP_Problem_optimization_mode(+Handle, ?Optimization_Mode)`

Unifies `Optimization_Mode` with the optimization mode for the LP Problem referenced by `Handle`.

## `ppl_LP_Problem_clear(+Handle)`

Resets the LP problem referenced by `Handle` to be the trivial problem with the feasible region the -dimensional universe, objective function and optimization mode `max`.

## `ppl_LP_Problem_add_constraint(+Handle, +Constraint)`

Updates the LP Problem referenced by `Handle` so that the feasible region is represented by the original constraint system together with the constraint `Constraint`.

## `ppl_LP_Problem_add_constraints(+Handle, +Constraint_System)`

Updates the LP Problem referenced by `Handle` so that the feasible region is represented by the original constraint system together with all the constraints in `Constraint_System`.

## `ppl_LP_Problem_set_objective_function(+Handle, +Lin_Expr)`

Updates the LP Problem referenced by `Handle` so that the objective function is changed to `Lin_Expr`.

## `ppl_LP_Problem_set_optimization_mode(+Handle, +Optimization_Mode)`

Updates the LP Problem referenced by `Handle` so that the optimization mode is changed to `Optimization_Mode`.

## `ppl_LP_Problem_is_satisfiable(+Handle)`

Succeeds if and only if the LP Problem referenced by `Handle` is satisfiable.

## `ppl_LP_Problem_solve(+Handle, ?LP_Problem_Status)`

Solves the LP problem referenced by `Handle` and unifies `LP_Problem_Status` with: `unfeasible`, if the LP problem is not satisfiable; `unbounded`, if the LP problem is satisfiable but there is no finite bound to the value of the objective function; `optimized`, if the LP problem admits an optimal solution.

## `ppl_LP_Problem_feasible_point(+Handle, ?Generator)`

Unifies `Generator` with a feasible point for the LP problem referenced by `Handle`.

## `ppl_LP_Problem_optimizing_point(+Handle, ?Generator)`

Unifies `Generator` with an optimizing point for the LP problem referenced by `Handle`.

## `ppl_LP_Problem_optimal_value(+Handle, ?Coefficient_1, ?Coefficient_2)`

Unifies `Coefficient_1` and `Coefficient_2` with the numerator and denominator, respectively, for the optimal value for the LP problem referenced by `Handle`.

## `ppl_LP_Problem_evaluate_objective_function(+Handle, +Generator, ?Coefficient_1, ?Coefficient_2)`

Evaluates the objective function of the LP problem referenced by `Handle` at point `Generator`. `Coefficient_1` is unified with the numerator and `Coefficient_2` is unified with the denominator of the objective function value at `Generator`.

## `ppl_LP_Problem_OK(+Handle)`

Succeeds only if the LP Problem referenced by `Handle` is well formed, i.e., if it satisfies all its implementation invariants. Useful for debugging purposes.

# Compilation and Installation

When the Parma Polyhedra Library is configured, it tests for the existence of each supported Prolog system. If a supported Prolog system is correctly installed in a standard location, things are arranged so that the corresponding interface is built and installed.

As an option, the Prolog interface can track the creation and disposal of polyhedra. In fact, differently from native Prolog data, PPL polyhedra must be explicitly disposed and forgetting to do so is a very common mistake. To enable this option, configure the library adding `-DPROLOG_TRACK_ALLOCATION` to the options passed to the C++ compiler. Your configure command would then look like

      path/to/configure --with-cxxflags="-DPROLOG_TRACK_ALLOCATION" ...

# System-Dependent Features

## CIAO Prolog

The Ciao Prolog interface to the PPL is available both as ``PPL enhanced'' Ciao Prolog interpreter and as a library that can be linked to Ciao Prolog programs. Only Ciao Prolog versions 1.10 #5 and later are supported.

So that it can be used with the Ciao Prolog PPL interface, the Ciao Prolog installation must be configured with the `--disable-regs` option.

### The `ppl_ciao` Executable

If an appropriate version of Ciao Prolog is installed on the machine on which you compiled the library, the command `make install` will install the executable `ppl_ciao` in the directory `prefix/bin`. The `ppl_ciao` executable is simply the Ciao Prolog interpreter with the Parma Polyhedra Library linked in. The only thing you should do to use the library is to call `ppl_initialize/0` before any other PPL predicate and to call `ppl_finalize/0` when you are done with the library.

### Linking the Library To Ciao Prolog Programs

In order to allow linking Ciao Prolog programs to the PPL, the following files are installed in the directory `prefix/lib/ppl`: `ppl_ciao.pl` contains the required foreign declarations; `libppl_ciao.*` contain the executable code for the Ciao Prolog interface in various formats (static library, shared library, libtool library). If your Ciao Prolog program is constituted by, say, `source1.pl` and `source2.pl` and you want to create the executable `myprog`, your compilation command may look like

    ciaoc -o myprog prefix/lib/ppl/ppl_ciao.pl ciao_pl_check.pl \
      -L '-Lprefix/lib/ppl -lppl_ciao -Lprefix/lib -lppl -lgmpxx -lgmp -lstdc++'

## GNU Prolog

The GNU Prolog interface to the PPL is available both as a ``PPL enhanced'' GNU Prolog interpreter and as a library that can be linked to GNU Prolog programs. The only GNU Prolog version that is known to work is a patched version of the ``unstable version'' tagged 20040608 (which unpacks to a directory called `gprolog-1.2.18`). The patch is contained in the `interfaces/Prolog/GNU/README` file of the PPL's distribution.

So that it can be used with the GNU Prolog PPL interface (and, for that matter, with any foreign code), the GNU Prolog installation must be configured with the `--disable-regs` option.

### The `ppl_gprolog` Executable

If an appropriate version of GNU Prolog is installed on the machine on which you compiled the library, the command `make install` will install the executable `ppl_gprolog` in the directory `prefix/bin`. The `ppl_gprolog` executable is simply the GNU Prolog interpreter with the Parma Polyhedra Library linked in. The only thing you should do to use the library is to call `ppl_initialize/0` before any other PPL predicate and to call `ppl_finalize/0` when you are done with the library.

### Linking the Library To GNU Prolog Programs

In order to allow linking GNU Prolog programs to the PPL, the following files are installed in the directory `prefix/lib/ppl`: `ppl_gprolog.pl` contains the required foreign declarations; `libppl_gprolog.*` contain the executable code for the GNU Prolog interface in various formats (static library, shared library, libtool library). If your GNU Prolog program is constituted by, say, `source1.pl` and `source2.pl` and you want to create the executable `myprog`, your compilation command may look like

    gplc -o myprog prefix/lib/ppl/ppl_gprolog.pl source1.pl source2.pl \
      -L '-Lprefix/lib/ppl -lppl_gprolog -Lprefix/lib -lppl -lgmpxx -lgmp -lstdc++'

## SICStus Prolog

The SICStus Prolog interface to the PPL is available both as a statically linked module or as a dynamically linked one. Only SICStus Prolog versions 3.9.0 and later are supported.

### The Statically Linked `ppl_sicstus` Executable

If an appropriate version of SICStus Prolog is installed on the machine on which you compiled the library, the command `make install` will install the executable `ppl_sicstus` in the directory `prefix/bin`. The `ppl_sicstus` executable is simply the SICStus Prolog system with the Parma Polyhedra Library statically linked. The only thing you should do to use the library is to load `prefix/lib/ppl/ppl_sicstus.pl`.

### Loading the SICStus Interface Dynamically

In order to dynamically load the library from SICStus Prolog you should simply load `prefix/lib/ppl/ppl_sicstus.pl`. Notice that, for dynamic linking to work, you should have configured the library with the `--enable-shared` option.

## SWI-Prolog

The SWI-Prolog interface to the PPL is available both as a statically linked module or as a dynamically linked one. Only SWI-Prolog version 5.6.0 and later versions are supported.

### The `ppl_pl` Executable

If an appropriate version of SWI-Prolog is installed on the machine on which you compiled the library, the command `make install` will install the executable `ppl_pl` in the directory `prefix/bin`. The `ppl_pl` executable is simply the SWI-Prolog shell with the Parma Polyhedra Library statically linked: from within `ppl_pl` all the services of the library are available without further action.

### Loading the SWI-Prolog Interface Dynamically

In order to dynamically load the library from SWI-Prolog you should simply load `prefix/lib/ppl/ppl_swiprolog.pl`. This will invoke `ppl_initialize/0` and `ppl_finalize/0` automatically. Alternatively, you can load the library directly with

    :- load_foreign_library('prefix/lib/ppl/libppl_swiprolog').

This will call `ppl_initialize/0` automatically. Analogously,

    :- unload_foreign_library('prefix/lib/ppl/libppl_swiprolog').

will, as part of the unload process, invoke `ppl_finalize/0`.

Notice that, for dynamic linking to work, you should have configured the library with the `--enable-shared` option.

## XSB

The XSB Prolog interface to the PPL is available as a dynamically linked module. Only some CVS versions of XSB starting from 2 July 2005 are known to work. CVS versions starting from 11 November 2005 are known not to work.

In order to dynamically load the library from XSB you should load the `ppl_xsb` module and import the predicates you need. For things to work, you may have to copy the files `prefix/lib/ppl/ppl_xsb.xwam` and `prefix/lib/ppl/ppl_xsb.so` in your current directory or in one of the XSB library directories.

## YAP

The YAP Prolog interface to the PPL is available as a dynamically linked module. Only YAP versions following 5.1.0 and CVS HEAD versions starting from 4 January 2006 are supported. Notice that support for unbounded integers in YAP is young and may have errors that could affect programs using the PPL (see, e.g., http://www.cs.unipr.it/pipermail/ppl-devel/2006-January/007780.html).

In order to dynamically load the library from YAP you should simply load `prefix/lib/ppl/ppl_yap.pl`. This will invoke `ppl_initialize/0` automatically; it is the programmer's responsibility to call `ppl_finalize/0` when the PPL library is no longer needed. Notice that, for dynamic linking to work, you should have configured the library with the `--enable-shared` option.