next up previous index
Next: Multiple Solver States Up: EPLEX: The ECLiPSe/CPLEX Interface Previous: Advanced Use of Eplex   Index

Subsections

Low-Level Solver Interface

For many applications, the facilities presented so far should be appropriate for using Simplex/MIP through ECLiPSe. However, sometimes it may be more convenient or efficient to directly access the solver state instead of going through the abstraction of the eplex instances. This section describes lower level operations like how to set up solvers manually. In fact, these lower level predicates are used to implement the predicates provided with eplex instances.

These predicates accesses the external solver state via a handle, which is returned when the solver state is set up, and subsequently used to access a particular solver state by the other predicates. The handle should be treated as a opaque data structure that is used by the eplex library to refer to a particular solver state.

Setting Up a Solver State


lp_demon_setup(+Objective, -Cost, +ListOfOptions, +Priority, +TriggerModes, -Handle)

This is used to set up a demon solver, and eplex_solver_setup/5 calls this predicate. There is one extra argument compared to eplex_solver_setup/5: the solver state handle Handle, which is returned by this predicate when the new solver state is created. The other arguments are the same as in eplex_solver_setup/5, except that there is an additional option in ListOfOptions: collect_from/1. This is used to specify which, if any, eplex instance the solver state should be collecting constraints from. If an eplex instance is specified (as pool(Instance)), then the solver state is associated with that instance. If the eplex instance is not to be associated with an eplex instance, none should be given as the argument to collect_from. This allows a solver state to be set up without the overhead of an eplex instance. The solver state will not collect any constraints automatically when it is invoked; instead the constraints must be added explicitly via the handle (using lp_add_constraints/3).

By default, the external solver is invoked once after set up by lp_demon_setup, if any TriggerModes is specified. Otherwise, the solver is not invoked and the predicate returns after set up.


lp_setup(+NormConstraints, +Objective, +ListOfOptions, -Handle)

This is an even lower-level primitive, setting up a solver state without any automatic triggering. It creates a new solver state for the set of constraints NormConstraints (see below for how to obtain a set of normalised constraints). Apart from the explicitly listed constraints, the variable's ranges will be taken into account as the variable bounds for the simplex algorithm. Undeclared variables are implicitly declared as reals/1.

However, when variables have been declared integers (using ::/2 or range:integers/1 or ic:integers/1), that is not taken into account by the solver by default. This means that the solver will only work on the relaxed problem (ie. ignoring the integrality constraints), unless specified otherwise in the options. Objective is either min(Expr) or max(Expr) where Expr is a linear (or quadratic) expression. ListOfOptions is a list of solver options, the same as for lp_demon_setup/6 and eplex_solver_setup/5, except for the collect_from and initial_solve options, which are specific for the demon solvers.

Adding Constraints to a Solver State

Constraints can be added directly to a solver state without posting them to an eplex instance. This is done by:


lp_add_constraints(+Handle, +Constraints, +NewIntegers)

Add new constraints (with possibly new variables) to the solver state represented by Handle The new constraints will be taken into account the next time the solver is run. The constraints will be removed on backtracking.

The constraints are first normalised, and simple constraints filtered out (as discussed in section 11.3.1) before they are added to the external solver (by calling lp_add/3 described below).


lp_add(+Handle, +NewNormConstraints, +NewIntegers)

This adds the constraints (both linear and intergrality) to the external solver represented by Handle. The linear arithmetic constraints must be normalised. Note that it is possible to add trivial constraints, which would be filtered out by the higher level lp_add_constraints/3 using this predicate. Integrality constraints on non-problem variables are filtered out and a warning given.

Running a Solver State Explicitly


lp_solve(+Handle, -Cost)

Apply the external solver's LP or MIP solver to the problem represented by Handle. Precisely which method is used depends on the options given to lp_setup/4. lp_solve/2 fails if there is no solution or succeeds if an optimal solution is found, returning the solution's cost in Cost (unlike with lp_demon_setup/6, Cost gets instantiated to a number). After a success, various solution and status information can be retrieved using lp_get/3 and lp_var_get/4.

When a solver is triggered repeatedly, each invocation will automatically take into account the current variable bounds. The set of constraints considered by the solver is the one given when the solver was created plus any new constraints that were added (lp_add_constraints/3) in the meantime.

If there was an error condition, or limits were exceeded, lp_solve/2 raises an event. See section 11.10 for details.

lp_probe(+Handle, +Objective, -Cost)

Similar to lp_solve/2, but optimize for a different objective function rather than the one that was specified during solver setup. This is the predicate called by eplex_probe/2. The main difference is that eplex_probe/2 will first collect the constraints from the associated eplex instance before calling lp_probe/3.

Accessing the Solver State

In section 11.5.1, we discussed how solver state information can be accessed via the eplex instance. Here are the lower level predicates that directly access this information via the solver state's handle:


lp_get(+Handle, +What, -Value)

Retrieve information about solver state and results. See the reference manual description of lp_get/3 for a detailed description of the available values for What.

For example, it is possible to obtain the solution values from the last successful invocation of the external solver using the following:

    instantiate_solution(Handle) :-
        lp_get(Handle, vars, Vars),
        lp_get(Handle, typed_solution, Values),
        Vars = Values.


lp_var_get(+Handle,+Var, +What, -Value)

Retrieve information about solver state represented by Handle, related to a specific variable Var. Again, see the reference manual for the available parameters.

Changing Solver State Settings

In addition to accessing information from the solver state, some options (a subset of those specified during solver set up) can be changed by:


lp_set(+Handle, +What, +Value)

This primitive can be used to change some of the initial options even after setup. Handle refers to an existing solver state. See the reference manual for details.

Destroying a Solver State


lp_cleanup(+Handle)

Destroy the specified solver state, free all memory, etc. If the solver state is associated with an eplex handle, the solver state is disassociated with the eplex instance. However, unlike eplex_cleanup/0, the outstanding constraints not yet collected by the solver is not removed.

As with eplex_cleanup/0, care should be taken before using this non-logical predicate.

Miscellaneous Predicates


lp_read(+File, +Format, -Handle)

Read a problem from a file and setup a solver for it. Format is lp or mps. The result is a handle similar to the one obtained by lp_setup/4.


normalise_cstrs(+Constraints, -NormConstraints, -NonlinConstr)

where Constraints is a list of terms of the form X =:= Y, X >= Y or X =< Y where X and Y are arithmetic expressions. The linear constraints are returned in normalised form in NormConstraints, the nonlinear ones are returned unchanged in NonlinConstr.


next up previous index
Next: Multiple Solver States Up: EPLEX: The ECLiPSe/CPLEX Interface Previous: Advanced Use of Eplex   Index
Warwick Harvey
2002-05-15