Algorithm 网格的最小精确覆盖面积;额外削减

Algorithm 网格的最小精确覆盖面积;额外削减,algorithm,linear-programming,integer-programming,Algorithm,Linear Programming,Integer Programming,这个问题出现在a中,但由于它现在已关闭,因此可以询问它 问题(不是这个问题本身,这只是背景信息)可以这样形象地描述,借用他们自己的形象: 我选择以最佳方式解决它。这可能(对于决策变量)是一个NP完全问题(当然是NP问题,闻起来像是一个精确覆盖问题,虽然我还没有证明一般的精确覆盖问题可以简化为它),但这很好,它只需要在实践中快速,不一定在最坏的情况下。在这个问题的背景下,我对任何近似算法都不感兴趣,除非它们提供切割 有一个明显的ILP模型:生成所有可能的正方形(如果一个正方形只覆盖网格中存在的单

这个问题出现在a中,但由于它现在已关闭,因此可以询问它

问题(不是这个问题本身,这只是背景信息)可以这样形象地描述,借用他们自己的形象:

我选择以最佳方式解决它。这可能(对于决策变量)是一个NP完全问题(当然是NP问题,闻起来像是一个精确覆盖问题,虽然我还没有证明一般的精确覆盖问题可以简化为它),但这很好,它只需要在实践中快速,不一定在最坏的情况下。在这个问题的背景下,我对任何近似算法都不感兴趣,除非它们提供切割

有一个明显的ILP模型:生成所有可能的正方形(如果一个正方形只覆盖网格中存在的单元格,那么它是可能的),为每个正方形引入一个二进制变量
x_i
,指示我们是否使用它,然后

minimize sum x_i

subject to:
1) x_i is an integer
2) 0 ≤ x_i ≤ 1
3) for every cell c
       (sum[j | c ϵ square_j] x_j) = 1
约束3表示每个单元格只覆盖一次。约束1和约束2使x_i成为二进制。最小解给出了原问题的最优解

这个(即忽略约束1)的线性松弛是半正常的,但它做的事情是这样的(这是一个6x6网格,缺少左上角):

这里选择了13个大小为“一半”(目标值为6.5)的正方形(这样你可以更容易地找到它们)

  • 4x4中的1个
  • 3x3中的3个
  • 2x2中的6个
  • 1x1中的第3个
此实例的最佳解决方案的目标值为8,例如:

线性放松有一半不错,但我并不完全满意。间隙有时超过10%,这有时会导致非常缓慢的整数相位

这就是真正的问题所在,是否有额外的限制,我可以添加(懒散地)作为削减,以改进分数解决方案

我已经尝试过这个问题的替代公式来寻找切入点,例如,我们不选择正方形,如果我们选择“左上角”和“右下角”,然后将它们匹配起来,形成覆盖所有单元格的非重叠正方形,会怎么样?然后,在每个“类似反斜杠的对角线”上,必须有匹配数量的左上角和右下角。但这并没有帮助,因为如果我们选择平方,那么不管怎样,这个条件总是正确的,在分数解中也是如此

我还尝试了一些关于重叠的推理,例如,如果两个正方形明显重叠,那么它们的和不能大于1,这可以通过添加重叠区域中完全包含的所有正方形来改进。但这种约束不如所有单元格只覆盖一次的约束那么强大

我尝试过对总面积进行推理(如中所述,总覆盖面积必须等于单元数),但这已经得到了每个单元必须覆盖一次的约束的保证,即从总面积的角度来说明它只允许更多的自由

我也尝试过用平方数(每个平方的面积都是一个平方)和平方数的差来做一些事情,但这也没有带来任何有用的结果。

我用这种方法对类似的问题产生了很好的效果(ITA的;向下滚动)。这里是,这(没有评论)可能只是一个零知识证明,我知道我在说什么。它比一个商业解决方案(我不想说出它的名字)快了几个数量级

关键是分支策略。与其直接在
xi
变量上分支(这可能是您的解算器正在做的),不如在更高级别的决策上分支。我在草莓地使用的一个方法是决定两个细胞是否被同一个正方形覆盖。如果以分数解最为悬而未决的对为目标,那么解决方案的结构似乎设置得相当快


不幸的是,我无法为您提供如何将其编程到现有整数程序解算器的建议。对于草莓地,我选择了定制一切,主要是因为我想这样做,但部分原因是我正在动态生成列,使用累积网格行和网格列总和快速计算矩形。

使用正方形的总面积等于要覆盖的总面积的约束怎么样,除了不重叠的约束之外?这应该比检查双覆盖约束更容易。

动态规划:选择一个单元格(任何单元格都可以),计算覆盖它的所有有效方格(即,仅覆盖当前单元格和网格中的其他单元格)。对于每个这样的正方形,递归地获得剩余区域的最小覆盖值(网格减去正方形),然后从中选择最小值(结果是该值+1)。 为了加快速度,请尝试选择在递归的每个级别中具有最少有效覆盖面积的单元格(从而减少每个级别中的递归调用数)

非常简单。

目标函数值的约束 当目标函数值为非整数时——例如,因为分数解中有奇数个0.5权重的平方——可以“直接在目标函数上”添加一个切分,以迫使其达到下一个更高的整数值:例如。,在您的示例分数解中,对于总目标函数值为6.5的13个平方,每个平方的权重为0.5,您可以添加所有x_i>=7的约束

更全面的削减 这导致了一个更一般的规则,当你有一个分数解,其中一些单元格的子集C被一些非整数总权重w的正方形的子集S“精确覆盖”时,这个规则就会起作用。所谓“完全覆盖”,我的意思是S中的每个正方形都有非零的权重,加在一起为C中的每个单元格提供1的总权重,并且不与C之外的任何单元格重叠。您可以
Sum_{square_i in T}(x_i) + RoundUp(w) * Sum_{square_j in U}(x_j) >= RoundUp(w)
cell(x,y) := min(cell(x,y-1) ?? 0, cell(x-1,y) ?? 0, cell(x-1,y-1) ?? 0) + 1
--+++
+-+++
+++++
FindMinimum[{
  a + b + c + d + e + f + g, 
  (a 1^2 + b 2^2 + c 3^2 + d 4^2 + e 5^2 + f 6^2 + g 7^2) == 119 &&
  a >= 0 && b >= 0 && c >= 0 && d >= 0 && e >= 0 && f >= 0 && g >= 0 &&
  a \[Element] Integers &&
  b \[Element] Integers &&
  c \[Element] Integers &&
  d \[Element] Integers &&
  e \[Element] Integers &&
  f \[Element] Integers &&
  g \[Element] Integers
}, {a,b,c,d,e,f,g}]