Prolog ECLiPSe CLP:缓慢的组合发生/3约束行为

Prolog ECLiPSe CLP:缓慢的组合发生/3约束行为,prolog,constraints,constraint-programming,eclipse-clp,Prolog,Constraints,Constraint Programming,Eclipse Clp,作为一个更大问题的子集,我尝试为NxN板(包含N²单元)编写以下两个约束条件: 每一行/列正好包含由预定义提示给出的整数K的N次出现 2x2块(板上的任何位置)包含的整数K不超过1次 在电路板上,有几个单元已经预先填充好了,对于本SO问题中的约束应忽略不计,因此我们使用整数2表示这些单元,并对未知单元进行建模,使其具有二进制布尔值的有限域: model(Board,N,Hints) :- dim(Board,[N,N]), ( foreach(Row-Col,Hints),

作为一个更大问题的子集,我尝试为NxN板(包含N²单元)编写以下两个约束条件:

  • 每一行/列正好包含由预定义提示给出的整数K的N次出现
  • 2x2块(板上的任何位置)包含的整数K不超过1次
在电路板上,有几个单元已经预先填充好了,对于本SO问题中的约束应忽略不计,因此我们使用整数2表示这些单元,并对未知单元进行建模,使其具有二进制布尔值的有限域:

model(Board,N,Hints) :-
    dim(Board,[N,N]),
    ( foreach(Row-Col,Hints), param(Board)
    do
      2 is Board[Row,Col]
    ),
    ( multifor([I,J],1,N), param(Board)
    do
      Cell is Board[I,J],
      ( var(Cell) -> Cell :: 0..1 ; true )
    ).
代码中的约束分别为:

hint_constraints(Board,N,RowHints,ColHints) :-
    ( for(I,1,N), foreach(RH,RowHints), foreach(CH,ColHints), param(Board,N)
    do
      Row is Board[I,1..N],
      Col is Board[1..N,I],
      ic_global:occurrences(1,Row,RH),           % Here, K=1 and N=RH
      ic_global:occurrences(1,Col,CH)            % Here, K=1 and N=CH
    ).

block_constraints(Board,N) :-
    ( multifor([I,J],1,(N-1)), param(Board)
    do
      Block is Board[I..I+1,J..J+1],
      flatten(Block,BlockFlat),
      Sum #:: [0,1],
      ic_global:occurrences(1,BlockFlat,Sum)     % Here, K=1
    ).
对于简单的谜题执行:

solve(BT) :-
    puzzle(N,_,RowHints,ColHints,Hints),
    model(N,RowHints,ColHints,Hints,Board),
    hint_constraints(Board,N,RowHints,ColHints),
    block_constraints(Board,N),
    once search(Board,0,most_constrained,indomain_max,complete,[backtrack(BT)]).
对于8x8难题,几乎可以立即找到第一个解决方案:

?- solve(BT).
   [](0, 0, 0, 0, 0, 0, 1, 2)
   [](2, 1, 0, 2, 1, 0, 0, 2)
   [](0, 0, 0, 0, 0, 0, 1, 0)
   [](0, 0, 0, 1, 0, 0, 0, 0)
   [](1, 0, 0, 0, 2, 0, 0, 0)
   [](2, 2, 1, 0, 1, 2, 1, 2)
   [](1, 2, 0, 2, 0, 0, 2, 0)
   [](0, 0, 0, 0, 1, 0, 0, 1)

   BT = 0
   Yes (0.01s cpu)
但是,对于20x20实例,我让它运行了大约5分钟,没有得到任何结果

为了调查一个约束是否会比另一个约束成本更高,我分别运行了这两个约束:

当我们使用提示约束/4而不是块约束/2时,我们得到:

?- solve(BT).
   [](1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0)
   [](1, 1, 2, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 2, 0)
   [](2, 1, 1, 1, 2, 1, 1, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0)
   [](1, 1, 0, 0, 0, 0, 0, 2, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 2)
   [](1, 0, 1, 1, 1, 2, 1, 1, 2, 1, 0, 0, 0, 0, 2, 2, 0, 0, 2, 0)
   [](2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0)
   [](2, 0, 0, 0, 1, 2, 1, 1, 1, 1, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0)
   [](1, 0, 0, 0, 2, 1, 1, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0)
   [](2, 0, 0, 0, 1, 1, 0, 1, 1, 2, 1, 0, 2, 0, 2, 0, 2, 0, 0, 2)
   [](2, 0, 0, 0, 1, 0, 2, 1, 0, 1, 1, 0, 0, 0, 0, 0, 2, 0, 2, 0)
   [](0, 0, 0, 0, 2, 0, 2, 0, 0, 1, 2, 1, 2, 1, 1, 0, 0, 1, 0, 2)
   [](0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 2, 0, 0)
   [](0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 1, 1, 1, 0, 1, 0, 2, 0, 0)
   [](2, 0, 0, 0, 2, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1)
   [](0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0, 1, 0, 1, 0, 1)
   [](0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 2, 2, 2, 1)
   [](0, 2, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 1, 1, 1)
   [](0, 0, 2, 0, 0, 0, 0, 0, 2, 2, 0, 2, 0, 1, 0, 0, 1, 2, 1, 1)
   [](2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2)
   [](0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 2, 2, 0, 1, 2, 1, 1, 1, 2, 1)

   BT = 0
   Yes (0.04s cpu)
并可以验证是否满足所有行/列引用。另一方面,当我们使用块约束/2而不是提示约束/2时:

?- solve(BT).
   [](0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0)
   [](0, 1, 2, 1, 0, 2, 1, 2, 1, 0, 1, 0, 1, 2, 1, 0, 1, 2, 2, 0)
   [](2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0)
   [](0, 1, 0, 1, 0, 1, 0, 2, 2, 1, 2, 1, 0, 1, 0, 1, 0, 0, 2, 2)
   [](0, 0, 0, 0, 0, 2, 0, 1, 2, 0, 0, 0, 0, 0, 2, 2, 0, 1, 2, 1)
   [](2, 1, 0, 1, 0, 1, 0, 0, 0, 1, 2, 1, 0, 1, 2, 1, 0, 0, 0, 0)
   [](2, 0, 0, 0, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 1)
   [](0, 1, 0, 1, 2, 1, 0, 0, 0, 2, 1, 0, 1, 0, 2, 1, 0, 2, 0, 0)
   [](2, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 2, 0, 2, 0, 2, 1, 0, 2)
   [](2, 1, 0, 1, 0, 1, 2, 0, 0, 1, 0, 1, 0, 1, 0, 1, 2, 0, 2, 1)
   [](0, 0, 0, 0, 2, 0, 2, 1, 0, 0, 2, 0, 2, 0, 0, 0, 0, 1, 0, 2)
   [](0, 1, 0, 1, 2, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 2, 0, 0)
   [](0, 0, 0, 0, 0, 2, 0, 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 1, 0)
   [](2, 1, 0, 1, 2, 2, 0, 0, 0, 2, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0)
   [](0, 0, 2, 0, 0, 1, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 1, 0)
   [](0, 1, 0, 1, 0, 2, 0, 0, 0, 1, 0, 1, 2, 1, 0, 1, 2, 2, 2, 0)
   [](0, 2, 0, 0, 2, 1, 2, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 1)
   [](0, 1, 2, 1, 0, 0, 0, 0, 2, 2, 1, 2, 1, 0, 1, 0, 0, 2, 0, 0)
   [](2, 0, 0, 0, 0, 2, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 2)
   [](0, 1, 2, 1, 0, 0, 0, 0, 2, 0, 2, 2, 1, 0, 2, 0, 0, 0, 2, 0)

   BT = 0
   Yes (0.01s cpu)
我们可以再次验证2x2块约束是否成功保持。不幸的是,当同时使用这两个约束时,程序似乎无法在5分钟内完成任何地方。我对这种行为感到有点困惑,因为这两个约束分别运行得非常快。虽然我知道必须在内部进行大量检查,以确保在整个过程中仍然满足块约束的同时,每个行/列都存在正确的引用,但这需要5分钟以上的时间,这一事实让我认为我编写块约束的方式肯定出了问题

有人知道如何优化我的块引用约束的实现吗

提前谢谢

拼图实例

拼图(8,简单,[1,2,1,1,1,3,1,2], [2,1,1,1,3,0,3,1], [1-8,2-1,2-4,2-8,5-5,6-1,6-2,6-6,6-8,7-2,7-4,7-7])

拼图(20,中等,[5,2,6,2,7,1,6,3,5,4,5,3,4,2,4,3,5,4,4,5], [5,4,3,3,6,3,4,5,2,4,4,4,2,7,1,5,3,6,3,6], [1-6, 1-15, 2-3, 2-6, 2-8, 2-14, 2-18, 2-19, 3-1, 3-5, 3-11, 4-8, 4-9, 4-11, 4-19, 4-20, 5-6, 5-9, 5-15, 5-16, 5-19, 6-1, 6-11, 6-15, 7-1, 7-6, 7-15, 8-5, 8-10, 8-15, 8-18, 9-1, 9-10, 9-13, 9-15, 9-17, 9-20, 10-1, 10-7, 10-17, 10-19, 11-5, 11-7, 11-11, 11-13, 11-20, 12-5, 12-18, 13-6, 13-11, 13-18, 14-1, 14-5, 14-6, 14-10, 15-3, 15-12, 16-6, 16-13, 16-17, 16-18, 16-19, 17-2、17-5、17-7、17-15、18-3、18-9、18-10、18-12、18-18、19-1、19-6、19-20、20-3、20-9、20-11、20-12、20-15、20-19])


为什么你认为,如果A+B可以以可分离的方式快速计算,那么约束A和B的组合可以快速计算(最坏情况的例子:以一个np难问题为例,移除一些类型的约束->现在它可以在多项式时间内求解)?如果您的约束是正确的,那么很可能存在很多有效的解决方案(绝对和相对数量),回溯类型搜索可以快速找到一个。但考虑到这两种类型的约束,可能会以对数方式减少解的数量,因此搜索将变得非常缓慢。测试和分析一个较小的实例!我明白您的意思,并且理解两个约束的单独行为并没有说明它们的组合行为以及这可能如何反映运行时间。然而,我觉得这不应该是一个很难解决的问题,因为它只是一个更大的逻辑谜题的子集,目前仍然包含多个解决方案。注:我已经修改了我的答案,包括一个较小的谜题实例的结果,这个谜题不构成任何问题。谜题暗示了一些NP难问题。你的拼图实例有名字吗?您是否只有这些给定的实例?通常,一个生成器可以生成不同大小的实例以进行调试和分析。我试图解决的原始难题称为,但我决定不在这个问题中包含所有谜题的信息/规则,因为这已经是一篇相当长的文章,不需要额外的信息来理解这个问题。目前我只准备了这两个输入格式的实例。为什么你认为,如果A+B可以以可分离的方式快速计算,那么约束A和B的组合可以快速计算(最坏情况的例子:以np难问题为例,删除某些类型的约束->现在它可以在多项式时间内求解)?如果您的约束是正确的,那么很可能存在很多有效的解决方案(绝对和相对数量),回溯类型搜索可以快速找到一个。但考虑到这两种类型的约束,可能会以对数方式减少解的数量,因此搜索将变得非常缓慢。测试和分析一个较小的实例!我明白您的意思,并且理解两个约束的单独行为并没有说明它们的组合行为以及这可能如何反映运行时间。然而,我觉得这不应该是一个很难解决的问题,因为它只是一个更大的逻辑谜题的子集,目前仍然包含多个解决方案。注:我已经修改了我的答案,包括一个较小的谜题实例的结果,这个谜题不构成任何问题。谜题暗示了一些NP难问题。你的拼图实例有名字吗?您是否只有这些给定的实例?通常,我们从一个生成器开始,它能够生成不同大小的实例以进行调试和分析。我试图解决的原始谜题被称为,但我决定不在这个问题中包含所有谜题的信息/规则,因为它是alr