Prolog ECLiPSe CLP难题:完美的矩形拟合

Prolog ECLiPSe CLP难题:完美的矩形拟合,prolog,constraint-programming,eclipse-clp,Prolog,Constraint Programming,Eclipse Clp,我正在做一个叫做“盒子除法”的拼图。本质上,它是一种基于给定线索的完美矩形拟合。这些规则是: 某些网格单元包含数字(这是已知的输入数据) 任务是将网格区域划分为满足以下约束的矩形房间:每个房间正好包含一个数字,房间的总面积等于其中的数字 例如。: 有解决方案: +-----------+ | 4 . | 2 | | . . | . | |------+----+ | . 3 . | +-----------+ 我已经编写了约束和一个小的有限域解算器,它有效地为我提供了每个提

我正在做一个叫做“盒子除法”的拼图。本质上,它是一种基于给定线索的完美矩形拟合。这些规则是:

  • 某些网格单元包含数字(这是已知的输入数据)
  • 任务是将网格区域划分为满足以下约束的矩形房间:每个房间正好包含一个数字,房间的总面积等于其中的数字
例如。: 有解决方案:

+-----------+
| 4  . | 2  |
| .  . | .  |
|------+----+
| .   3  .  |
+-----------+
我已经编写了约束和一个小的有限域解算器,它有效地为我提供了每个提示的所有可能的矩形位置,如下所示(坐标从(1,1)开始,从左上到右下移动):

随后,我尝试编写自己的解算器,该解算器基于检查重叠约束(即,如果两个矩形水平重叠,则它们不应垂直重叠,反之亦然)。它适用于小型谜题,但是,由于广泛的约束检查,我的两次尝试都没有成功地扩展到大于~15x15的谜题

因此,我们的目标是找到一个可以扩展到更大谜题的模型,如果可能的话,可以使用ECLiPSe内置的search/6,并且能够轻松地试验不同的搜索启发法

有什么想法/想法吗?提前谢谢

注意:我正在使用integer IC域库(=lib(IC))

编辑如果有人对运行时结果感兴趣,它们现在都可以在不到半秒钟内求解)

问题输入数据:

语法:问题(ID、宽度、高度、提示)(提示是三元组:(I、J、Value))

15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,1,1,1,1,1,1,3,(3,(1,1,(1,1,1,1,1,15,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,(1,1,3,(1,1,1,1,1,1,1,1,1,1,1,(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 14,6),(6,15,8)]

15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,(1,1,1,1,1,3,(7,3,3,(7,3,(7,3,3,(3,3,3,(7,3,1,3,(1,1,1,1,1,1,1,1,3,1,3,(3,3,3,3,3,(13,3,4,4,4,4,4,4,4,4,3,(1,1,1,1,1,1,1,1,6,1,6,6,6,6,6,6,6,7,7,2,2,(7,7,7,7,7,2,7,7,7,7,7,7,7,2,(7,7,7,2,(7,7,2,(4,7,7,7,7,7,7,7,2,(4,7,7,2,(4,2,(4 14,26),(15,14,2)]

20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,[,(,(2,1,1,1,1,1,1,1,1,1,1,(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,(1,2,(1,2,2,2,(1,2,2,(1,2,2,(1,2,2,2,(1,2,2,2,2,2,(5,2,2,(5,2,(5,2,2,(5,2,2,(5,2,2,2,2,(5,2,2,(5,2,2,(5,2,2,(5,2,2,(5,2,2,2,(5,2,2,2,(5,2,(5,2,2,2,20,3)]

20,20,20,20,20,20,20,20,20,(,(3,1,1,1,2,(8,1,1,1,1,(2,2,2,(4,2,(4,2,4,2,(4,2,3,(4,2,(4,2,2,(2,2,2,(2,2,2,(2,2,2,(2,2,2,2,(2,2,2,2,(4,2,(4,2,(4,2,(4,2,(4,2,(4,4,2,(4,2,(4,2,(4,2,2,(4,4,2,4,4,4,2,(4,4,4,2,(4,4,4,4,4,2,(4,4,4,4,2,(4,4,4,2,(4,4,4,4,4,4,4,(4,4,4,4,4,4,4,4,(4,4,(4,(4,4,4,10,3)、(11,10,45)、(15,12,28)、(19,12,2)、(20,12,2)、(5,13,2)、(8,13,3),(15,13,40)、(6,14,2)、(9,14,12)、(3,15,14)、(5,15,4)、(6,15,6)、(18,15,18)、(3,16,2)、(4,16,6)、(5,18,3)、(14,18,15)、(17,18,2)、(3,19,2)、(5,19,4)、(10,19,2)、(2,20,6)、(5,20,3)、(6,20,2)、(8,20,3)、(16,20,2)、(17,20,2)、(20,6))

5,1,10,(15,1,1,(17,1,1,8,(17,1,1,8,(17,1,1,8,(1,(24,1,1,2,(13,1,1,2,(14,2,(14,2,2,(14,1,2,(1,1,1,1,1,1,1,1,1,(1,1,1,1,1,(14,1,1,1,1,(14,2,2,(14,2,2,2,(14,2,(14,2,(14,2,(14,2,2,(14,2,(14,2,2,2,2,(14,2,2,(14,2,(14,2,(14,2,2,2,(14,2,2,2,2,(3,2,(3,2,(3,2,(3,2,(3,2,2,2,(3,2,(3,2,(3,2,(3,2,(3,2,(3,2,2,(3,2,(3 11,3)、(2,12,2)、(4,12,5)、(10,12,4)、(22,12,2)、(23,12,3),(24,12,6),(6,13,15),(19,13,2),(21,13,2),(2,14,2),(5,14,28),(17,14,3),(20,14,3),(22,14,2),(18,15,3),(21,15,5),(7,16,7),(12,16,3),(15,16,3),(16,16,2),(9,17,2),(11,17,2),(17,17,3),(20,17,16),(7,18,12),(8,18,2),(9,18,3),(12,18,4),(13,18,9),(19,18,12),(24,18,2),(25,18,3),(1,19,2),(5,19,9),(11,19,2),(3,20,2),(5,20,5),(9,20,2),(20,20,7),(7,21,24),(18,22,6),(20,22,3),(21,22,10),(4,23,6),(5,23,3),(7,23,9),(10,23,12),(16,23,24),(17,23,4),(24,23,5),(1,24,2),(18,24,8),(25,24,2),(2,25,4),(17,25,11))


你可以用有限域约束来描述整个问题,然后用标准的搜索程序来解决。不需要预先计算单个矩形放置的列表

如果这是家庭作业,让我给出一些建议

rect_contains_point(rect(I,J,K,L), point(PI,PJ)) :-
    I #=< PI, PI #=< K,
    J #=< PJ, PJ #=< L.
这与您在网站上的中找到的方法相同

编辑 感谢您提供问题实例。我可以在不到1.5秒的时间内解决所有问题,也可以解决今天的30x40难题

有趣的是,使用最简单的标记策略
input\u order
可以获得最好的性能。对于具有简单几何结构的此类问题,通常最好根据变量在几何体中的“邻接关系”来标记变量,在这里简单地使用行顺序就可以了

然而,特别是对于干扰简单结构的附加约束的问题,这种方法可能无法充分扩展。因此,人们已经开发了专门的放置/打包约束,请参见例如或。后者也可在ECLiPSe via中获得

附言
正如@SeekAndDestroy所报告的,标签策略
miniminate
(选择其域中当前值最小的变量)提供了更好的结果。此外,使用
library(gfd)
而不是
library(ic)
提供了进一步的加速。我在ECLiPSe网站上添加了一些示例。

感谢您的评论。事实上,很荣幸收到您的答复,因为我已经阅读了您的一些作品并从中获得了灵感。ECLiPSe clp确实是一个了不起的系统!主题:我刚刚实现了您在wh中建议的模型方法我不预先计算可能的矩形和角坐标,这是一个非常成功的改进,给出了更简单的重叠约束
% Syntax: rectangle(X,Y,Width,Height,HintValue)
[
  [rectangle(1, 1, 2, 2, 4)],
  [rectangle(2, 1, 2, 1, 2), rectangle(3, 1, 1, 2, 2)],
  [rectangle(1, 3, 3, 1, 3), rectangle(2, 1, 1, 3, 3)]
]
rect_contains_point(rect(I,J,K,L), point(PI,PJ)) :-
    I #=< PI, PI #=< K,
    J #=< PJ, PJ #=< L.
no_overlap(rect(I1,J1,K1,L1), rect(I2,J2,K2,L2)) :-
    K1#<I2 or K2#<I1 or L1#<J2 or L2#<J1.