3.4 User defined constraints
The library ic_kernel provides a
number of facilities useful for implementing IC constraints or otherwise
extending the facilities provided by the standard IC library.
While the ic_kernel library
exposes the structure of the IC attribute to the programmer (see below),
accessing it directly is strongly discouraged (if for no other reason,
the internals of IC may continue to evolve).
For accessing information about a variable and its domain, use the
predicates described earlier in section 3.2.7 “Variable query
predicates”.
For modifying a variable, it is particularly important to go through the
access predicates, in order to make sure that the internal state remains
consistent, that appropriate constraints are scheduled for execution as a
result of the change, etc.
The predicates available for modifying a variable are discussed in the next
section.
3.4.1 Modifying variable domains
When using IC variables in normal code, one would typically use the
$\=
, $=<
and $>=
family of constraints to (resp.)
remove a value, reduce the upper bound or increase the lower bound of a
variable.
While these constraints are good for normal CSP solving, they have a
number of properties which may be less desirable when writing new
constraints. In particular, they may leave unwanted delayed goals
behind and may perform extra propagation before returning (it may be
desirable to perform all required bound updates before allowing further
propagation to occur).
To give the constraint writer more control over such matters, special
predicates exist in the ic_kernel
module which allow direct modification of the domain without the waking of
goals (they are scheduled for execution but not actually executed).
These predicates generally accept an IC variable, a non-IC variable (which
will be constrained to make it a real IC variable) or a number.
Full details on these predicates can be found in the reference manual; they
are listed here for completeness. Note that with the exception of
impose_bounds/3 none of
the goals call wake/0, so
the programmer is free to do so at a convenient time.
-
impose_min/2
-
Set the lowerbound.
- impose_max/2
-
Set the upperbound.
- impose_bounds/3
-
Sets both upper and lower bounds.
- exclude/2
-
Excludes an integer from an integral variable.
- exclude_range/3
-
Excludes a range of integers from an integral variable.
- set_var_type/2
-
Makes the variable be of the given type.
- set_vars_type/2
-
Like set_var_type, but works for lists and submatrices of variables as well.
3.4.2 The IC attribute
The IC attribute is a meta-term which is attached to all variables which
take part in IC constraints.
ic_kernel defines the IC
attribute as a structure of the following form:
ic{var_type:Type,
lo:Lo,
hi:Hi,
bitmap:Bitmap,
min:SuspMin,
max:SuspMax,
hole:SuspHole,
type:SuspType
}
This structure holds:
-
var_type
- The type of the variable. This defaults to 'real' but may
become 'integer' after an explicit call to integers/1, by being
included in an integer constraint (e.g. #=) or by inferences made
during constraint propagation.
- lo
- The lower bound of the variable's domain, as a float.
- hi
- The lower bound of the variable's domain, as a float.
- bitmap
- Where relevant, a bitmap representation of the integer domain;
where not relevant it holds the atom
undefined
.
- min
- Suspension list of goals to be woken on lower bound changes.
- max
- Suspension list of goals to be woken on upper bound changes.
- hole
- Suspension list of goals to be woken when a value is removed
from the middle of a domain. Such removals only happen for integer
variables whose domain is finite.
- type
- Suspension list of goals to be woken when a variable's type
becomes more constrained, i.e. when a variable goes from being real to
being integer.
The suspension list names can be used in
suspend/3 and
related predicates to denote an appropriate waking condition.
The attribute of a domain variable can be accessed with the predicate
get_ic_attr/2.
As noted above, direct access and manipulation of the attribute is
discouraged; use the access predicates instead.