【发布时间】:2016-05-22 08:18:09
【问题描述】:
我正在尝试在 EclipsE Prolog 中编写 Shikaku 求解器。 我的约束定义如下:
solve(Problemname):-
writeln("Start shikaku."),
problem(Problemname, Width, Height, Hints),
shikaku(Width, Height, Hints).
shikaku(Width, Height, Hints):-
length(Hints, HintCount),
array_list(HintsArray, Hints),
% Prepare the matrix and assign an ID to every Hint (from 1 to HintCount)
dim(Matrix, [Width, Height]),
Matrix[1..Width,1..Height] :: 1..HintCount,
%flatten_array(Matrix,FlattenedMatrix),
(for(ID,1,HintCount), foreach((HintX, HintY, HintNumber), Hints), param(Width, Height, Matrix, HintsArray) do
(
occurrences(ID, Matrix, HintNumber),
L :: 1..Width, R :: 1..Width,
T :: 1..Height, B :: 1..Height,
% Hint coordinates are inside the rectangle.
L #=< HintX,
R #>= HintX,
T #=< HintY,
B #>= HintY,
DeltaX #= R-L+1,
DeltaY #= B-T+1,
HintNumber #= DeltaX * DeltaY,
Matrix[L..R,T..B] :: ID..ID
%writematrix(Submatrix, DeltaX, DeltaY, HintsArray),
%flatten(Submatrix, FlatSubmatrix),
%array_list(FlatSubmatrixArray, FlatSubmatrix),
% Cell count in rectangle must equal HintNumber
%length(FlatSubmatrix, HintNumber),
% All cells in rectangle must have ID as value
%FlatSubmatrixArray[1..HintNumber] :: ID
)
),
% Start searching
labeling(Matrix),
writematrix(Matrix, Width, Height, HintsArray).
writematrix(Matrix, Width, Height, HintsArray):-
writeln("Writing as classic view:"),
(for(I, 1, Height), param(Matrix, Width, HintsArray) do
write("["),
Row is Matrix[I],
(for(J, 1, Width), param(Row, HintsArray) do
ID is Row[J],
(_,_,Val) is HintsArray[ID],
write(" "),
write(Val),
write(" ")
),
writeln("]")
).
cmets 中的行应该检查从 L..R - T..B 出发的子矩阵是否只包含等于 ID 的元素。如何做到这一点?
运行此命令会导致“_3264{1 .. 3} =
edit1:完整代码
edit2 似乎 Eclipse 无法减少 LR/TB 变量的域以应用实例化。这是一个正确的假设吗?如果是这样,这将如何解决?
【问题讨论】:
-
啊哈,问题可能在于您访问 Matrix 以获得 L..R、T..B 的子集,但这些变量可能并不总是在输入代码行时被接地。您不能为具有域的数组子集指定范围。一种可能是在设置 LRTB 变量的域之后,但在将 ID..ID 域设置为 Matrix 子集之前执行搜索。
-
如何做到这一点? :)
-
使用 ECLiPSe 的内置搜索/6,就像您在调用 labeling/1 时所做的那样。只是,不是在循环之后调用它,而是在 L..R 和 T..B 的域实例之间的循环内调用它,但在 Matrix[L..R,T..B] :: ID 行之前..ID。
-
好吧,它运行 :D 虽然它应该返回一个解决方案,但它确实是。
-
太棒了:D!现在问题已经暴露,您可以调整程序。我想这可以归结为:要么您事先设置所有 LRTB 变量的所有约束,但还没有使用它们来访问循环内的 Matrix,或者您像现在一样在循环内执行搜索并且可以保持矩阵呼叫那里。但是,请注意,在循环内调用 search 将需要为不同的解决方案创建不同的选择点,这可能会在处理大型域时减慢执行速度。始终尝试尽可能/需要约束您的模型,以避免不必要的搜索。
标签: prolog clpfd constraint-programming eclipse-clp