使用 CLP 获取间隔

Getting intervals with CLP

我想在序言环境中获取可变域的非中断间隔。

例如,我有一个变量 X,它被限制在其域中取一些值。假设 X 有一个 初始域 [0..20] 并且它被限制为(不)具有 589 作为值.所以 X 有新域 [0..4, 6, 7, 10..20]。我想在这个域中获得非中断间隔作为列表 [[0..4], [6,7], [10..20]]

SWI-Prolog中,当我运行以下目标时使用clpfd库:

X in 0..20, X #\= 5, X #\= 8, X #\= 9.

答案是:

X in 0..4\/6..7\/10..20.

到目前为止一切顺利。但我不知道如何将这个域作为间隔列表获取。有办法吗?


也欢迎使用其他 Prolog 实现及其各自的 CLP/FD 库的解决方案。

使用fd_dom/2,可以获得变量的定义域。然后 DCG rule 可用于解析形式为 L1..U1\/L2..U2\/... 的域。

SWI-Prolog 手册 (link) 中给出了将域作为整数列表获取域的示例 DCG 规则。稍加修改就可以用来获取间隔:

dom_intervals(Dom, Intervals) :- phrase(dom_intervals1(Dom), Intervals).

dom_intervals1(I)           -->  {integer(I)}, [I].
dom_intervals1(L..U)        --> [L..U].
dom_intervals1(D1 \/ D2)    --> dom_intervals1(D1), dom_intervals1(D2).

终于可以使用这个查询了:

X in 0..20, X #\= 5, X #\= 8, X #\= 9, fd_dom(X, D), dom_intervals(D, Intervals).


虽然在 YAP-prolog manual 中没有提到 clpfd,但也可以用 YAP-prolog 做同样的事情。