如何将整数(解)列表转换为连续区间列表

问题描述 投票:0回答:1

我使用CLP(FD)和SWI-Prolog编写了一个CSP程序。

有些约束看起来像

Xi mod N #= 0
,所以我必须为每个变量Xi调用
res(Xi,Li)
(与
res(X,L) :- setof(X, indomain(X), L)
)来进行回溯并获得有效解决方案列表。如果我不这样做,我就会得到剩余目标。

现在在同一个调用中,我想将 Xi 的解决方案列表转换为连续间隔列表。 我怎样才能做到这一点 ?是否有任何现有谓词可以做到这一点?

我尝试使用

fd_dom(Li,Di), dom_intervals(Di,Ii)
但没有成功,因为 Li 需要是原子的,而不是列表。

dom_intervals 定义如下,请参阅使用 CLP 获取间隔

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

我还尝试在

member(Xtmpi, Li)
之前调用
fd_dom(Xtmpi,Di), dom_intervals(Di,Ii)
,但是
member
枚举结果,因此我得到了单例列表。

预先感谢您的想法。

prolog clpfd
1个回答
0
投票

生成完整序列然后再次将其压缩回来似乎有点浪费,但我没有找到一种方法来解析 fd_domain 而不这样做,所以这里有一个数字到连续范围的语法。

用途:

?- phrase(ranges(Rs), [2, 4,5,6, 10, 22,23,24,25,26,27,28,29,30]).
Rs = [2, 4-6, 10, 22-30]

代码:

:- use_module(library(dcg/basics)).

ranges([R|Rs]) -->          % a list of ranges:
    [A], range(A,B),        % a number A begins a range from A to B,
    {(A=B -> R=A ; R=A-B)}, % output single values as 2, ranges as 2-9
    ranges(Rs).             % then more ranges up to ...

ranges([])     --> eos.     % ... end of stream.


range(A,Z) -->       % a range continues if:
    {succ(A,B)},     % the next number should be B,
    [B],             % and yes, B is next in the list,
    range(B,Z).      % and the range continues from B..end.
 
range(A,A), [C] -->  % a range ends if:
    {succ(A,B)},     % the next number should be B
    [C], {dif(B,C)}. % the next number is C, which is different.
    
range(A,A) --> eos.  % or a range ends at the end of stream.
© www.soinside.com 2019 - 2024. All rights reserved.