以下是我的问题场景:
我有几千件物品。每个对象都有256个布尔维度(true或false)。我想找到这样的集群
不需要解决方案的最优性,但算法应该很快。
我该如何最好地解决这个问题?你会推荐一种算法吗?
注意:我已经对这个问题采用了暴力方法,但速度很慢。
答案 0 :(得分:2)
您可以将其写为 mixed-integer linear program (MILP) :
您拥有固定数量的群集和对象 每个群集最多可以有256个真实尺寸 如果对象k中的维度i为真,则参数等于1。
您有以下变量:
您有以下约束:
第二个约束是一个棘手的问题,因为它不会感觉是线性的,但实际上你可以线性地写它。 约束可以写成:
目标函数可以是所有的总和,因此您可以最小化所有群集上所有真实维度的总和。
让我解释第二个约束:在右侧,计算集群i内的元素数量,减去维度j设置为1的对象数量。如果所有对象都具有维度j,则该值等于零,否则为正值。
如果评估为零,则 必须等于1,以避免违反约束。如果不是,{{0}}可以是任何(零或一)。这是有效的,因为将出现在目标函数中,这意味着当程序在零或一之间选择时,它将选择零。
一旦你写完这篇文章,你可以使用商业解算器解决它(如果你有一个,他们会给学生免费许可,如果你是一个)或Coin-OR只是命名一个。
提醒一下:解决MILP是一个 NP完全问题。
答案 1 :(得分:0)
所以我决定写下我提出的(理论)解决方案。部分是因为它可能对我有所帮助(见下文有关此内容的更多信息),部分原因是为任何感兴趣的人提供了一个不错的解它是一个线性方程组,人们可以使用Simplex Algorithm来解决。
我想出的约束是:
1)每个对象都在一个集群中
2)每个群集最多有M(常量)对象
3)如果该群集中至少有一个对象将该维度设置为true,则群集的维度为真
我将解释现在如何强制执行约束:
让n个对象和k个集群。我们考虑总和(以下这是一行)
x 1 1 + x 2 1 + x 3 1 + ... + x n 1 + d 1 1 + d 2 1 + d 3 1 + ... + d n 1 +
x 1 2 + x 2 2 + x 3 2 + ... + x n 2 + d 1 2 + d 2 2 + d 3 2 + ... + d n 2 +
...
x 1 k + x 2 k + x 3 k + ... + x n k + d 1 k + d 2 k + d 3 k + ... + d n k功能
,其中
如果对象a是int cluster c,则x a c 为真
如果集群c中的维度b为真,则d b c 为真
由于群集对象总是更好(或至少永远不会有害),我们知道群集的数量是 ceil(对象除以M)。为简单起见,我现在将省略变量,然后编写系数。
1)每个对象都在一个群集中
10 ... 0 0 ... 0 10 ... 0 0 ... 0 10 ... 0 0 ... 0 ... 10 ... 0 0 ... 0 = 1
010 ... 0 0 ... 0 010 ... 0 0 ... 0 010 ... 0 0 ... 0 ... 010 ... 0 0 ... 0 = 1
...
0..01 0 ... 0 0 ... 01 0 ... 0 0 ... 01 0 ... 0 ... 0 ... 01 0 ... 0 = 1
这将强制每个对象只在一个集群中。这可以理论上允许对象与若干簇中的部分(< 1)一起使用。但是因为我们正在寻找最佳解决方案,所以不会发生这种情况。
2)每个群集最多有M个(常量)对象
11 ... 1 0 ... 0 0 ... 0 0 ... 0 0 ... 0 0 ... 0 ... 0 ... 0 0 ... 0 <= M
0 ... 0 0 ... 0 11 ... 1 0 ... 0 0 ... 0 0 ... 0 ... 0 ... 0 0 ... 0 <= M
...
0 ... 0 0 ... 0 0 ... 0 0 ... 0 0 ... 0 0 ... 0 ... 11 ... 1 0 ... 0 <= M
对象的总和不大于M.这个约束应该是明确的。
现在是棘手的部分:
3)如果该群集中至少有一个对象将该维度设置为true,则群集的维度为true
对于每个维度和每个群集,请考虑将此维度设置为true的那些元素(我们也可以考虑假的,但它们并不重要)。我们现在为每个(和每个集群)写一行
0..010 ... 0 -10 ... 0 0 ... 0 0 ... 0 ... 0 ... 0 0 ... 0&lt; = 0
其中1表示此对象的此维度(在此群集中)设置为true,-1表示维度(在本例中为第一个维度)。如果在此群集中设置了对象,则此群集的维度必须为1(1 * 1 -1 * d <= 0),如果未设置,则维度也可以为零(0 * 1) - 1 * d <= 0)。
对于第一个群集中的第二个维度,它将如下所示:
0..010 ... 0 0-10 ... 0 0 ... 0 0 ... 0 ... 0 ... 0 0 ... 0&lt; = 0
以及最后一个集群和最后一个维度
0 ... 0 0 ... 0 0 ... 0 0 ... 0 ... 0..010..0 0 ... 0-1&lt; = 0
现在我们可以简单地最小化x a c 的总和,我们就完成了。
这可能会以更好的方式写下来,但我希望这是可以理解的。
现在问题如下: 我正在使用70个群集,3000个对象和2300个维度。使用上面的方法,这将产生371000个变量(cluster * objects + clusters * dimensions)和1292095行(将行估计为对象+ cluster + dimensions * log(objects)* clusters)
我倾向于认为最佳解决方案不可行。即使您仍然可以优化此处描述的方法,类似的方法也不太可能表现得更好。所以现在我正在寻找好的近似值,欢迎任何解决这个问题的想法。
谢谢:)