A Bounds-Consistent IC constraint

## 14.6 A Bounds-Consistent IC constraint

To show the basic ideas, we will simply reimplement a constraint that already exists in the ic solver, the inequality constraint. We want a constraint ge/2 that takes two ic variables (or numbers) and constrains the first to be greater or equal to the second.
The behaviour should be to maintain bounds-consistency: If we have a goal `ge(X,Y)`, where the domain of `X is X{1..5}` and the domain of `Y is Y{3..7}`, we would like the domains to be updated such that the upper bound of Y gets reduced to 5, and the lower bound of X gets increased to 3. The following code achieves this:

>     ge(X, Y) :-
>             get_bounds(X, _, XH),
>             get_bounds(Y, YL, _),
>             ( var(X),var(Y) ->
>                 suspend(ge(X,Y), 0, [X->ic:max, Y->ic:min])
>             ;
>                 true
>             ),
>             X #>= YL,    % impose new bounds
>             Y #=< XH.

We have used a single primitive from the low-level interface of the ic library: get_bounds/3, which extracts the current domain bounds from a variable. Further, we have used the information that the library implements trigger conditions called min and max, which cause a goal to wake up when the lower/upper bound on an ic variable changes.
Note that we suspend a new instance of the `ge(X,Y)` goal before we impose the new bounds on the variables. This is important when the constraint is to be used together with other constraints of higher priority: imposing a bound may immediately wake and execute such a higher-priority constraint. The higher-priority constraint may then in turn change one of the bounds that ought to wake ge/2 again. This only works if ge/2 has already been (re-)suspended at that time.