CLP 中变量的临时绑定

时间:2020-12-26 12:16:02

标签: prolog backtracking

我正在尝试使用 SWI Prolog CLP(FD) 解决调度问题。在尝试解决更大的问题时,我正在应用更高级的标记策略,在这里更好地了解程序在什么时候失败和回溯将是有益的。因此,我喜欢记录哪些变量绑定会导致失败,并使用这些信息来更好地适应我的标签启发式方法。
为了说明,我生成了一个例子。我生成了一个将变量列表绑定到值序列的谓词。我想知道序列的哪一部分使解决方案无效并将这些变量记录在谓词的第三个参数中。

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).

我现在可以测试这个谓词,只使用非常简单的约束。

?- 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.

它告诉我值 6 和 3 导致此程序失败。所以我想使用这些信息来修改我的测试序列,利用有限数量的替代值。最后,我想达到以下目标:

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). 

问题是在第三个子句中 vars_assign_fail 已经部分地将 Seq 的值绑定到 Vs。但是,我想“撤消”此操作(=回溯)并仅保留有关失败的绑定的信息(F|Fs)。此信息位于谓词 sequence_fail_alternative_rearrange 中,以创建具有替代值输入的新序列,并再次运行“测试”,直到 找到了有效的解决方案 - 或者在用完备选方案列表时整个迭代失败。

有人可以就如何在 Prolog 中最好地实现这一点给我建议吗?是否有可能再次解除 Vs 中的变量绑定或暂时执行 vars_assign_fail?您会推荐什么解决方案?

1 个答案:

答案 0 :(得分:2)

提示:not 谓词可以应用两次(双重否定),您只关心 Goal 是成功还是失败以及任何绑定都将被丢弃。检查Why double negation doesn't bind in Prolog。 在 vars_assign_fail/3 的第二个子句中使用它,例如:

vars_assign_fail(_, [], []).
vars_assign_fail([V|Vs], [S|Ss], Fs ) :-
    \+ \+ V=S, 
    !,
    vars_assign_fail(Vs, Ss, Fs).
vars_assign_fail([_|Vs], [S|Ss], [S|Fs]) :-
    vars_assign_fail(Vs, Ss, Fs).