List 为什么clpfd变量被分配到具体化中的实际值?

List 为什么clpfd变量被分配到具体化中的实际值?,list,prolog,swi-prolog,clpfd,List,Prolog,Swi Prolog,Clpfd,我正在开发一个(SWI-)Prolog程序,它使用CLP(FD)约束为特定问题找到解决方案。要做到这一点,我恰好需要两个列表的“无位置”重叠。即: 列表La的长度为A 列表Lb的长度为B A>B 未定位的重叠列表是La+Lb,其中元素以逐个方式添加 但是,我需要Lb具有可变偏移量(即,对于La+Lb添加,每个列表的第一个元素不在相同的位置。但是,列表Lb始终在La的宽度范围内。例如: BeLa=[0,1,1,1,1,0,1,1,1]和Lb=[1,2,2] 可能的情况1 (Lb) 1 2 2

我正在开发一个(SWI-)Prolog程序,它使用CLP(FD)约束为特定问题找到解决方案。要做到这一点,我恰好需要两个列表的“无位置”重叠。即:

  • 列表
    La
    的长度为A
  • 列表
    Lb
    的长度为B
  • A>B
  • 未定位的重叠列表是
    La+Lb
    ,其中元素以逐个方式添加
但是,我需要
Lb
具有可变偏移量(即,对于
La+Lb
添加,每个列表的第一个元素不在相同的位置。但是,列表
Lb
始终在
La
的宽度范围内。例如:

Be
La=[0,1,1,1,1,0,1,1,1]
Lb=[1,2,2]

可能的情况1

(Lb) 1 2 2 . . . . . . ---> offset = 0
(La) 0 1 1 1 1 0 1 1 1
( +) 1 3 3 1 1 0 1 1 1   
可能的情况2

(Lb) . . . 1 2 2 . . . ---> offset = 3
(La) 0 1 1 1 1 0 1 1 1
( +) 0 1 1 2 3 2 1 1 1   
可能的情况3

(Lb) . . . . . 1 2 2 . ---> offset = 5
(La) 0 1 1 1 1 0 1 1 1
( +) 0 1 1 1 1 1 3 3 1   
我想将
偏移量
定义为一个clpfd变量,其中有一个特定的域与之关联。为了计算
La+Lb
,我编写了谓词
overlap/6
,如下所示:

overlap([],[],_,_,_,[]) :- !.
overlap([],_, _,_,_,[]) :- !.
overlap(A, [],_,_,_, A) :- !.
overlap(A, _,Os,_,_, A) :- length(A,L), L =< Os, !.
overlap([A|As],[B|Bs],0,Os,S,[A|Ls]) :-  % Os is the actual Offset 
    A #= B #<== S #= Os,                 % S is a clpfd variable
    overlap(As,Bs,0,Os,S,Ls),!.
overlap([A|As],Bs,Acc,Os,S,[A|Ls]) :-
    Acc > 0,
    Acc0 is Acc-1,
    overlap(As,Bs,Acc0,Os,S,Ls),!.
或:


如果存在与起始位置
S
的重叠,我们期望约束的结合,以便覆盖所有重叠位置。例如:

:- use_module(library(clpfd)).

overlap_at(As, Bs, S, ABs) :-
        length(As, L),
        L1 #= L - 1,
        S in 0..L1,
        overlap_at_(As, Bs, S, 0, ABs).

overlap_at_([], _, _, _, []).
overlap_at_([A|As], Bs, S, N0, [AB|ABs]) :-
        overlap_here(Bs, [A|As], [AB|ABs], Conj),
        S #= N0 #==> Conj,
        S #> N0 #==> AB #= A,
        N1 #= N0 + 1,
        overlap_at_(As, Bs, S, N1, ABs).

overlap_here(_, [], _, 1) :- !.
overlap_here([], _, _, 1).
overlap_here([B|Bs], [A|As], [AB|ABs], (AB #= A + B #/\ Rest)) :-
        overlap_here(Bs, As, ABs, Rest).
注意我是如何在这里/4中描述连词的

示例查询:

?- overlap_at([0,1,1,1,1,0,1,1,1], [1,2,2], 3, ABs).
ABs = [0, 1, 1, 2, 3, 2, _G909, _G912, _G915],
_G909 in inf..sup,
_G912 in inf..sup,
_G915 in inf..sup.
这为您提供了一个很好的解决方案:所有元素(包括重叠)都会根据需要实例化。第三个参数当然也可以是一个变量:例如Try

?- overlap_at([0,1,1,1,1,0,1,1,1], [1,2,2], S, ABs), 
   indomain(S), writeln(ABs), false.
这会产生如下结果:

[1,3,3,_,_,_,_,_,_]
[0,2,3,3,_,_,_,_,_]
[0,1,2,3,3,_,_,_,_]
[0,1,1,2,3,2,_,_,_]
[0,1,1,1,2,2,3,_,_]
[0,1,1,1,1,1,3,3,_]
[0,1,1,1,1,0,2,3,3]
[0,1,1,1,1,0,1,2,3]
[0,1,1,1,1,0,1,1,2]

我把剩下的留作练习:不受重叠影响的尾随位置需要与
A
的元素相等。此外,您可能需要进一步限制重叠的可能位置,我一直比较笼统。

约束和!不要聚集在一起。试着先说明何时应该使用您的定义cceed和它应该失败的时间。事实上,它应该总是成功的…
只是为了削减(剩下的)不需要的解决方案。你说“它应该总是成功”。不,绝对不是,否则
会重叠(,,,,,,,,,,,,,,).
将是一个完美的实现!对。当:
La
Lb
是任意长度的列表,它们的长度为
a>=B
,偏移量绑定到实际数字(
=0
)和
S
(最终偏移量)时,应该会成功没有绑定到一个数字,但有一个有界的和众所周知的域。这就是你的意思吗?(我编辑了这个问题,顺便说一下)给出具体的例子!这真的很有帮助。非常感谢!这对我来说非常棒。我在这里使用了
overlap_([],[a | As],[AB | ABs],(AB#=a#/\Rest)):-overlap_这里([],As,ABs,Rest)也考虑那些不受重叠影响的元素。
?- overlap_at([0,1,1,1,1,0,1,1,1], [1,2,2], S, ABs), 
   indomain(S), writeln(ABs), false.
[1,3,3,_,_,_,_,_,_]
[0,2,3,3,_,_,_,_,_]
[0,1,2,3,3,_,_,_,_]
[0,1,1,2,3,2,_,_,_]
[0,1,1,1,2,2,3,_,_]
[0,1,1,1,1,1,3,3,_]
[0,1,1,1,1,0,2,3,3]
[0,1,1,1,1,0,1,2,3]
[0,1,1,1,1,0,1,1,2]