List 为什么clpfd变量被分配到具体化中的实际值?
我正在开发一个(SWI-)Prolog程序,它使用CLP(FD)约束为特定问题找到解决方案。要做到这一点,我恰好需要两个列表的“无位置”重叠。即: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
- 列表
的长度为ALa
- 列表
的长度为BLb
- 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 . . . . . . ---> 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]