User defined constraints

## 3.4 User defined constraints

- Modifying variable domains
- The IC attribute

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.