CLP 中变量的暂定绑定

Posted

技术标签:

【中文标题】CLP 中变量的暂定绑定【英文标题】:Tentative binding of variables in CLP 【发布时间】:2020-12-26 12:16:02 【问题描述】:

我正在尝试使用 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。然而,我想“撤消”这个(=backtrack)并且只保留有关失败的绑定的信息(F|Fs)。此信息位于谓词 sequence_fail_alternative_rearrange 中,用于创建具有替代值输入的新序列,并且“测试”再次运行,直到 找到了有效的解决方案 - 或者当用完备选方案列表时整个迭代失败。

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

【问题讨论】:

【参考方案1】:

提示: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).

【讨论】:

以上是关于CLP 中变量的暂定绑定的主要内容,如果未能解决你的问题,请参考以下文章

具有内部链接的变量的暂定定义具有不完整的非数组类型:一致的实现显示不同的行为

C中暂定定义背后的基本原理是什么?

描述关于关系排序的整数序列的最一般的高阶约束

如何在 PHP 中绑定 SQL 变量?

OBIEE 和绑定变量

绑定变量选项