Next: , Up: Defining Global Constraints   [Contents][Index]


10.9.9.1 The Global Constraint Programming Interface

This section describes a programming interface by means of which new constraints can be written. The interface consists of a set of predicates provided by this library module. Constraints defined in this way can take arbitrary arguments and may use any constraint solving algorithm, provided it makes sense. Reification cannot be expressed in this interface; instead, reification may be achieved by explicitly passing a 0/1-variable to the constraint in question.

Global constraints have state, which may be updated each time the constraint is resumed. The state information may be used e.g. in incremental constraint solving.

The following two predicates are the principal entrypoints for defining and posting new global constraints:

clpfd:dispatch_global(+Constraint, +State0, -State, -Actions)   hook

Tells the solver how to solve constraints of the form Constraint. Defined as a multifile predicate.

When defining a new constraint, a clause of this predicate must be added. Its body defines a constraint solving method and should always succeed determinately. When a global constraint is called or resumed, the solver will call this predicate to deal with the constraint.

Please note: the constraint is identified by its principal functor; there is no provision for having two constraints with the same name in different modules. It is good practice to include a cut in every clause of clpfd:dispatch_global/4.

Please note: During propagation, if the domain of a variable becomes reduced to a single value, then the variable will eventually be bound to that value, but it is undefined exactly when that happens. Therefore, clauses of clpfd:dispatch_global/4 should not use nonvar/1 or integer/1 to check if a variable is fixed. Use e.g. fd_min/1 and fd_max/1 instead.

State0 and State are the old and new state respectively.

The constraint solving method must not wake up suspended goals recursively e.g. by binding variables or posting new constraints; instead, Actions should be unified with a list of requests to the solver. The list of requests is executed as if in the scope of fd_batch/1 so that any newly posted constraints are injected into the ongoing propagation, and not propagated recursively. Each request should be of one of the following forms:

exit

The constraint has become entailed, and ceases to exist.

fail

The constraint has become disentailed, causing the solver to backtrack.

X = V

The solver binds X to V.

X in R

The solver constrains X to be a member of the ConstantRange R (see Syntax of Indexicals).

X in_set S

The solver constrains X to be a member of the FD set S (see FD Set Operations).

call(Goal)

The solver calls the goal or constraint Goal, which should be module prefixed unless it is a built-in predicate or an exported predicate of the clpfd module.

fd_global(:Constraint, +State, +Susp)
fd_global(:Constraint, +State, +Susp, +Options)

where Constraint is a constraint goal, State is its initial state, and Susp is a term encoding how the constraint should wake up in response to domain changes. This predicate posts the constraint.

Susp is a list of F(Var) terms where Var is a variable to suspend on and F is a functor encoding when to wake up:

dom(X)

wake up when the domain of X has changed

min(X)

wake up when the lower bound of X has changed

max(X)

wake up when the upper bound of X has changed

minmax(X)

wake up when the lower or upper bound of X has changed

val(X)

wake up when the lower and upper bounds of X have coincided

Options is a list of zero or more of the following:

source(Term)

By default, the symbolic form computed by copy_term/3, and shown in the answer constraint if clpfd:full_answer holds, equals Constraint, module name expanded. With this option, the symbolic form will instead be Term. In particular, if Term equals true, then the constraint will not appear in the Body argument of copy_term/3. This can be useful if you are posting some redundant (implied) constraint.

idempotent(Boolean)

If true (the default), then the constraint solving method is assumed to be idempotent. That is, in the scope of clpfd:dispatch_global/4, the solver will not check for the resumption conditions for the given constraint, while performing its Actions. If false, then an action may well cause the solver to resume the constraint that produced the action.

If a variable occurs more than once in a global constraint that is being posted, or due to a variable-variable unification, then the solver will no longer trust the constraint solving method to be idempotent.

For an example of usage, see Global Constraint Example.

The following predicate controls operational aspects of the constraint solver:

fd_flag(+FlagName, ?OldValue, ?NewValue)

OldValue is the value of the FD flag FlagName, and the new value of FlagName is set to NewValue. The possible FD flag names and values are:

overflow

Determines the behavior on integer overflow conditions. Possible values:

error

Raises a representation error (the default).

fail

Silently fails.

debug

Controls the visibility of constraint propagation. Possible values are on and off (the default). For internal use by library(fdbg).



Send feedback on this subject.