In figures 2.1 and 2.3.1, above, we showed a
map colouring problem and its
solution.
The domains associated with the countries were *red, green* and
*blue*.
These were declared as finite domains, with the usual syntax:
*X :: [red, green, blue]*.

The problem could have been modelled using numbers to represent colours, so there is no extra power in allowing symbolic finite domains as well as numeric ones. However when developing ECLiPSe programs for real problems, it is a very great help to use meaningful names so as to distinguish different types of finite domain variables. In particular it is crucial during debugging!

figure illustrates the basic constraints on finite domain variables, and predicates for accessing and searching these domains.

[eclipse 1]: lib(fd). * fd loaded [eclipse 2]: X::[a,b,c]. * X = X{[a, b, c]} * yes. [eclipse 3]: X::[a, 3.1, 7]. * X = X{[3.0999999, 7, a]} * yes. [eclipse 4]: X::[a,b,c], dom(X,List). * X = X{[a, b, c]} * List = [a, b, c] * yes. [eclipse 5]: X::[a,b,c], Y::[b,c,d], X#=Y. * X = X{[b, c]} * Y = X{[b, c]} * yes. [eclipse 6]: X::[a,b,c], X##b. * X = X{[a, c]} * yes. [eclipse 7]: X::[a,b,c], indomain(X). * X = a More? (;) * X = b More? (;) * X = c * yes. [eclipse 8]: [X,Y,Z]::[a,b,c], X##Y, Y##Z, X##Z, labeling([X,Y,Z]). * X = a * Y = b * Z = c More? (;) * X = a * Y = c * Z = b More? (;) * yes. [eclipse 9]: [X,Z]::[a,b,c], Y::[a,c], deleteff(Var,[X,Y,Z],Rest), indomain(Var). * X = X{[a, b, c]} * Y = a * Z = Z{[a, b, c]} * Rest = [X{[a, b, c]}, Z{[a, b, c]}] * Var = a More? (;) * yes.Using Symbolic Finite Domains

The second query
associates a symbolic finite domain with the variable *X*.
In response ECLiPSe prints out the variable name and its newly assigned
domain.
The fact that the variable has an associated domain does not require
any changes in other parts of the program, where *X* may be treated as
an ordinary variable.

Query 3 shows that symbolic domains can include values of different types.

Query 4 shows the use of the *dom* predicate to retrieve the
domain associated with a variable.

Queries 5 and 6 illustrate the equality and disequality constraints,
and their effects on the domains of the variables involved.
Finite domain constraints use a special syntax to make
explicit which constraint library is to handle the constraint, for
example it uses `#=`

instead of `=`

.

Queries 7, 8 and 9 illustrate search. Strictly one would not expect search predicates to belong to a constraint library, but in fact search and constraint propagation are closely connected.

Query 7 shows the *indomain* predicate instantiating a domain
variable *X* to a value in its domain.
ECLiPSe asks if more answers are required, and when the user does indeed
ask for more, another value from the domain of *X* is chosen, and *X*
is instantiated to that value instead.
When the user asks for more again, *X* is instantiated to the third
and last value in its domain, and this time ECLiPSe doesn't offer the
user any further choices, but simply outputs *yes*.

Query 8 illustrates the built-in finite domain *labeling*
predicate.
This predicate simply invokes *indomain* on each variable in turn
in its argument.
In this case it calls *indomain* first on *X*, then *Y* and then
*Z*.
However the variables are constrained to take different values by
three disequality constraints, and only those labelings that satisfy
the constraints are admitted. Consequently this query has six
different answers, though the user stops asking for more after the
second answer.

Query 9 illustrates a heuristic based on the *fail first*
principle.
In choosing the next decision to make, when solving a problem, it is
often best to make the choice with the fewest alternatives first.
The predicate *deleteff* selects a variable from a set of
variables which has the fewest alternatives: i.e. the smallest finite
domain.
In the example there are three variables, *X*, *Y* and *Z*
representing three decisions, *deleteff* picks out *Y* because it
has the smallest domain, and then *indomain* selects a value for
*Y*.
The third argument of *deleteff* is an output argument:
*Rest* returns the remaining variables after the selected one has
been removed. These are the decisions yet to be made.

Wed Sep 3 18:07:19 BST 1997