I am trying to solve a scheduling problem by using SWI Prolog CLP(FD). When trying to solve larger problems I am applying more advanced labeling strategies, and here it would be beneficial to better understand at what point a program is failing and backtracking. Thus, I like to record what variable-bindings cause a fail and using this information to better adapt my labeling heuristic.
In order to illustrate I have generated an example. I generated a predicate that binds a list of Variables to a sequence of values. I would like to know which part of the sequence makes the solution to become invalid and record these variables in the third argument of the predicate.
vars_assign_fail(_, [], []).
vars_assign_fail([S|Vs], [S|Ss], Fs ) :-
!,
vars_assign_fail(Vs, Ss, Fs).
vars_assign_fail([_|Vs], [S|Ss], [S|Fs]) :-
vars_assign_fail(Vs, Ss, Fs).
I can now test this predicate, using only very simple constraints.
?- length(Vs, 6), As=[1, 2, 6, 9, 11, 3], Vs ins 1..5\/8..22, chain(Vs, #<), vars_assign_fail(Vs, As, Fs).
Vs = [1, 2, _51574, 9, 11, _51592],
As = [1, 2, 6, 9, 11, 3],
Fs = [6, 3],
_51574 in 3..5\/8,
_51592 in 12..22.
It tells me that the values 6 and 3 issue a failure in this program. So I want to use this information to modify my test sequence, making use of a finite number of alternative values. In the end I would like to reach something like the following:
solution_valueSeq_alternatives(Vs, Seq, []) :-
!,
fail.
solution_valueSeq_alternatives(Vs, Seq, Alt) :-
vars_assign_fail(Vs, Seq, []).
solution_valueSeq_alternatives(Vs, Seq, [A|Alt]) :-
vars_assign_fail(Vs, Seq, [F|Fs]),
sequence_fail_alternative_rearrange(Seq, [F|Fs], A, Reseq),
solution_valueSeq_alternatives(Vs, Reseq, Alt).
The problem is that in the third clause vars_assign_fail already partially binds the values of Seq to Vs. I, however, would like to "undo" this (=backtrack) and only keep the information on the bindings that failed (F|Fs). This information is in the predicate sequence_fail_alternative_rearrange consumed in order to create a new sequence with the input of alternative values and the "test" is run again until a valid solution is found - or alternatively the whole iteration fails when running out the list of alternatives.
Can anybody give me advice on how to best implement this in Prolog? Is there a possibility to unbind the variables in Vs again or to only tentatively execute vars_assign_fail? What solution would you recommend?