Initially only the third constraint[eclipse 1]: lib(repair), lib(fd). % libraries needed here yes. [eclipse 2]: fd:([X,Y,Z]::1..3), % the problem variables fd:(Y #\= X) r_conflict_prop confset, % state the constraints fd:(Y #\= Z) r_conflict_prop confset, fd:(Y #= 3) r_conflict_prop confset, [X,Y,Z] tent_set [1,2,3], % set initial assignment [X,Y,Z] tent_get [NewX,NewY,NewZ], % get repaired solution conflict_constraints(confset, Cs), % see the conflicts conflict_vars(Vs). X = X{fd:[1..3], repair:1} Y = 3 Z = Z{fd:[1, 2], repair:3} NewX = 1 NewY = 3 NewZ = 3 Cs = [3 #\= Z{fd:[1, 2], repair:3}] Vs = [Z{fd:[1, 2], repair:3}] Delayed goals: ... yes.

`Y #= 3`

is inconsistent with the
tentative assignment. According to the definition of `Y #= 3`

being propagated, which causes Y to be intantiated to 3
thus rendering the tentative value (2) irrelevant.Now the constraint

`Y #\= Z`

, is in conflict since Y is now 3 and Z has the
tentative value 3 as well. The constraint starts to propagate and removes 3
from the domain of `Z [1..2]`

. As a result Z becomes a conflict variable since its tentative value (3) is no longer in its domain. The

`Y #\= Z`

constraint remains in the
conflict constraint set because Z has no valid tentative assignment.The constraint

`Y #\= X`

is not affected, it neither goes into conflict
nor is its fd-version ever activated.To repair the remaining conflicts and to find actual solutions, the

`repair/0`

predicate described below could be used.The predicate is recursive and terminates when there are no more variables or constraints in conflict.repair(ConflictSet) :- ( conflict_vars([C|_]) -> % label conflict indomain(C), % variables first repair(ConflictSet) ; conflict_constraints(ConflictSet, [C|_]) -> term_variables(C, Vars), % choose one variable in deleteffc(Var,Vars, _), % the conflict constraint Var tent_get Val, (Var = Val ; fd:(Var #\= Val)), repair(ConflictSet) ; % no more conflicts: true % a solution is found. ).

Repair search often finishes without labeling all variables, a solution has been found and a set of tenable variables are still uninstantiated. Thus even after the search is finished, Repair library delayed goals used for monitoring constraints will be present in anticipation of further changes.

To remove them one has to ground these tenable variables to their tentative values.

Note that the example code never changes tentative values. This has the advantage that this is still a complete, monotonic and cycle-free algorithm. However, it is not very realistic when the problem is difficult and the solution is not close enough to the initial tentative assignment. In that case, one would like to exploit the observation that it is often possible to repair some conflict constraints by changing tentative values. During search one would update the tentative values to be as near as pssible to what one wants while maintaining consistency. If the search leads to a failure these changes are of course undone.