ECLiPSe will first solve the built-in constraints, then user-defined constraints by CHRs then the other goals.
Example, contd.:
[eclipse]: chr(minmax). minmax.chr compiled traceable 106874 bytes in 3.37 seconds minmax.pl compiled traceable 124980 bytes in 1.83 seconds yes. [eclipse]: minimum(X,Y,Z), maximum(X,Y,Z). X = Y = Z = _g496 yes.
Each user-defined constraint is associated with all rules in whose heads it occurs by the CHR compiler. Every time a user-defined constraint goal is added or re-activated, it checks itself the applicability of its associated CHRs by trying each CHR. To try a CHR, one of its heads is matched against the constraint goal. If a CHR has two heads, the constraint store is searched for a ``partner'' constraint that matches the other head. If the matching succeeded, the guard is executed as a test. Otherwise the rule delays and the next rule is tried.
The guard either succeeds, fails or delays. If the guard succeeds, the rule fires. Otherwise the rule delays and the next rule is tried. In the current implementation, a guard succeeds if its execution succeeds without delayed goals and attempts to ``touch'' a global variable (one that occurs in the heads). A variable is touched if it is unified with a term (including other variables), if it gets more constrained by built-in constraints (e.g. finite domains or equations over rationals) or if a goal delays on it (see also the check_guard_bindings option ). Currently, built-in constraints used in a guard act as tests only (see also the section on writing good CHR programs).
If the firing CHR is a simplification rule, the matched constraint goals are removed and the body of the CHR is executed. Similarly for a firing simpagation rule, except that the first head is kept. If the firing CHR is a propagation rule the body of the CHR is executed and the next rule is tried. It is remembered that the propagation rule fired, so it will not fire again (with the same partner constraint) if the constraint goal is re-activated.
If the constraint goal has not been removed and all rules have been tried, it delays until a variable occurring in the constraint is touched. Then the constraint is re-activated and all its rules are tried again.
Example, contd.: The following trace is edited, rules that are tried in vain and redelay have been removed.
[eclipse]: chr_trace. yes. Debugger switched on - creep mode [eclipse]: notrace. % trace only constraints Debugger switched off yes. [eclipse]: minimum(X,Y,Z), maximum(X,Y,Z). ADD (1) minimum(X, Y, Z) TRY (1) minimum(_g218, _g220, _g222) with propagation RULE 'propagation' FIRED ADD (2) leq(_g665, _g601) ADD (3) leq(_g665, Var) ADD (4) maximum(_g601, Var, _g665) TRY (4) maximum(_g601, Var, _g665) with propagation RULE 'propagation' FIRED ADD (5) leq(_g601, _g665) TRY (5) leq(_g601, _g665) (2) leq(_g665, _g601) with antisymmetry RULE 'antisymmetry' FIRED TRY (4) maximum(_g601, Var, _g601) with max_eq RULE 'max_eq' FIRED ADD (6) leq(Var, _g601) TRY (3) leq(_g601, Var) (6) leq(Var, _g601) with antisymmetry RULE 'antisymmetry' FIRED TRY (1) minimum(_g601, _g601, _g601) with min_eq RULE 'min_eq' FIRED ADD (7) leq(_g601, _g601) TRY (7) leq(_g601, _g601) with reflexivity RULE 'reflexivity' FIRED X = Y = Z = _g558 yes.