最小乘法次数与集合覆盖问题

5
我有一个集合I ={P1,P2,…,Pm},以如下方式表示n个I的有限子集,分别为R1、R2、…、Rn:
R1 = {P1,P2}
R2 = {P2,P4}
R3 = {P2,P3,P4}
R4 = {P1,P2,P4}

....

其中Pi表示整数。

对于每个Ri,我想计算其所有元素的乘积。我的目标是通过在Ri(i = 1,2,...,n)之间共享一些公共部分来尽可能少地使用乘法和除法。

例如,如果我可以先计算P2 * P4,那么这个结果可以用于计算R3和R4的所有元素的乘积。

请注意,除法也是允许的。例如,我可以先计算A = P1 * P2 * P3 * P4,然后使用A / P1来计算R3的所有元素的乘积,并使用A / P3来计算R4的所有元素的乘积。

如果我想使用最少的乘法和除法来计算I的每个子集的所有产品,这是否是一个集合覆盖问题?NP完全?顺便说一句,你能否给出一个整数线性规划公式来描述它,就像here中描述的那样。

非常感谢任何建议!

社区编辑:增加假设:

  • 可以使用除法,其成本与乘法相同
  • 给定集合中没有重复元素。例如,R5 = {P1, P1, P1, P2}是不允许的

1
是的,这是允许的。例如,我可以先计算A=P1P2P3*P4,然后使用A/P1来计算R3的所有元素的乘积,并使用A/P3来计算R4的元素乘积。 - John Smith
1
我假设除法算作乘法? - ninjagecko
1
当然可以!把它们看作是每个需要一个flop的操作。 - John Smith
1
在每组中,我们假设没有重复项。 - John Smith
1
你是否将计算最小操作所需的时间视为成本的一部分,还是不在意(例如可预先计算)?您是否假设并行或非并行硬件? - ninjagecko
显示剩余4条评论
3个回答

1

没有分割,这似乎等同于Gary & Johnson中描述的集合计算问题,因此是NP完全问题。

[PO9] 集合计算

实例:有限集合A的子集集合C,正整数J。

问题:是否存在一个序列S = (z_1 <- x_1 U y_1, z_2 <- x_2 U y_2, ..., z_j <- x_j U y_j),其中j <= J个并操作,每个x_i和y_i要么是A中的某个元素{a},要么是z_k(k < i),使得x_i和y_i不相交,1 <= i <= j,并且对于C中的每个子集c都存在某个z_i(1 <= i <= j)与之相同。

您的集合I对应于A,每个R_i对应于C的一个元素,乘法对应于集合并。


在集成计算中,J代表什么与我的问题相对应? - John Smith
J是允许的最大乘法次数。小写字母j是实际乘法次数。将优化问题转化为决策问题是很自然的,通过对要优化的事物施加限制,例如:将“最小化乘法次数”转化为“我能在少于J次乘法中完成吗?” - mhum
"R_i 对应于 C 中的一个元素"? 我认为它应该是 "R_i 中所有元素的乘积对应于 C 中的一个元素"。您能否确认一下?谢谢! - John Smith
是的,这差不多是同样的事情。问题的设置方式并不一定需要区分集合R_i和R_i中所有元素的乘积,因为我们可以选择每个P_i都是不同的质数。 - mhum
谢谢。顺便问一下,您认为Ninjagecko算法的近似比如何? - John Smith

1

首先,您不需要除法

这里不需要除法,它总是会多出一次计算。

如果您需要除法,那么这意味着您已经进行了乘法运算,因此如果您除以一个数,就相当于撤销了您已经完成的工作。

例如,如果您通过将 Pi*Pj*Pk 除以 Pn 来计算 Pi*Pj*Pk,这意味着您已经先计算了 Pi*Pj*Pk*Pn,因此您已经计算了 Pi*Pj*Pk。

(我假设您所有的数字都是质数

我的解决方案

我有一个想法,不考虑除法的可能性。

您可以使用您的 Ri 开始构建后缀树

然后,乘法的次数就是树中边的数量。

例如:

使用您的示例,后缀树如下:

       P2
      / \
     P4 P1
    / \ 
   P3 P1

您将获得4个乘法:

M1=P1*P2

M2=P2*P4

M3=M2*P1

M4=M2*P3

寻找最小乘法次数等价于构建具有最少边数的后缀树。
希望这能有所帮助。

我应该解释一下-1: “例如,如果你通过将PiPjPk除以Pn来计算PiPjPk,这意味着你之前已经计算过PiPjPkPn,因此你之前已经计算过PiPjPk。” 这并不意味着你之前已经计算过PiPj*Pk。它意味着你之前已经计算过Pi*Pj*Pk*Pn的一个因子。例如:Pi*PjPk*Pn。这并不是说除法不是必要的,只是上述内容并不是一个证明。 - ninjagecko
@ninjagecko,谢谢您的评论。我会尝试更新我的证明。我很确定在这里不需要除法(除非你有反例)。后缀树对我来说似乎是一种有趣的方法。 - Ricky Bobby
@RickyBobby,这里对质数的假设是否意味着Pi是原子的,不能分解为两个因数的乘积? - John Smith
@JohnSmith,是的,这意味着Pi不能分解为2 Pk和Pj的乘积。例如,如果R1={60}和R2={2,3,5},则可以通过只进行一次除法计算R2中元素的乘积:60/2,而不是进行2个乘法运算:235。假设这些数字不都是质数会给您的问题增加很多复杂性。 - Ricky Bobby
@RickyBobby,如何用最少的边构建后缀树?有参考资料吗? - John Smith

1
考虑你的元素Ri的无边图。我们现在允许自己按以下方式添加边:
  • 在Ra→Rb之间添加一条有向边,并注明商Rb/Ra。
例如,我们可以画出一个边缘R1→R3,其成本为乘以R1/R3=P3*P4/P1。
对于所有节点都执行此操作,因此您有|R|²个边缘。

如果你使用中间结果,你可以使用最小生成树算法来解决这个问题。我相信最小生成树算法在边的数量上非常接近线性(因子是反阿克曼函数,增长比log(log(log(...log(n)...)))慢);甚至可能存在基于边数的随机线性时间算法,例如http://www.akira.ruc.dk/~keld/teaching/algoritmedesign_f04/Artikler/07/Karger95.pdf。因此,这个基本算法将花费| R | 2时间。

然而,如果你只使用中间结果,你会失去真正最优解,因为我们可以用从空气中汲取出来的“临时”的表达式来实现更好的性能。例如,你可以考虑以下情景:

R1 = {P2, P3, P4, P5}
R2 = {P1, P3, P4, P5}
R3 = {P1, P2, P4, P5}
R4 = {P1, P2, P3, P5}
R5 = {P1, P2, P3, P4}

最优解是计算P1*P2*P3*P4*P5,然后除以Pi,共需9次操作。而上述方法只会执行类似于R1=P2*P3*P4*P5的操作,然后每次执行一次乘法和除法来进行R1→R2、R2→R3、R3→R4、R4→R5的操作,共需11次操作。(如果我们没有除法,我们也需要9次操作:b=P1*P2 c=b*P3 r5=c*P4 r4=c*P5, d=P4*P5, r3=b*d, e=P3*d, r1=e*P2, r2=e*P1。虽然我认为可能会出现必须使用除法的情况,但我找不到这种情况;如果我找不到这种情况,那么这实际上可能是一个简单的多项式时间问题。)
我将这种方法称为“即兴表达”方法。如果我们选择计算即兴表达(在开始时只有一次沉没成本),这将减少所有未来计算的成本,以遍历边缘如果我们选择使用它(因为可能有选择使用多少即兴表达的选择)。
这就带我们来到一个非常小的侧面注释:
Theorem:
  You should have at least one intermediate expression of each 
  length up to the maximum size of any R.
Proof (induction):
  To build up a product of size N, you will need to do 
  have a product of size N-1.

注意到这个定理后,我们发现之前的想法略有偏差。在计算P1*P2*P3*P4*P5的过程中,最优解是记住P1*P2*P3P1*P2*P3*P4。然后我们可以免费得到R5(通过另一种方式只需一次乘法即可获得R4,不幸的是与之前一样的代价),将总成本从9降至8。这使我们猜测,使用任意边执行http://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm也可能产生最优解,但需要很长时间。
无论如何,我们如何将这样的系统纳入我们的解决方案中?我们不能添加一个节点,因为那会破坏MST算法。对于每个边,其中通过临时表达式E乘或除不会使某些P具有超过幂p(例如,对于p = 2,我们允许创建像P1 * P4 ^ 2 / P3 这样的中间临时表达式,但不允许像P2 ^ 3 这样的东西),我们在该边上执行该乘法和除法,并创建两个新边。(我们可能会多次执行此操作,或在以后的日期执行此操作。)我们还对所有边缘子集执行此操作,就像上面所述的记忆化一样。如果您使用MST算法,则此方法的成本是边数大大增加,因此可能(| R | +#newedges) 2 =(| R | ^ | P |) 2 ,在最坏情况下显着增加了找到最佳答案所需的时间。

因此,作为一个猜测,更一般的问题似乎是NP难的;如果这不是情况,请有人发表意见。然而,您可以使用启发式算法来猜测有用的即兴表达式。例如,如果您看到R的“大”子集具有“共同P的高密度”,则可以生成所有共同P的乘积的tricknode。如果您对您的Rs子集中看到的所有“大/密集的共同Ps块”都这样做,然后运行MST,您可能会得到稍微更好的答案,而无需进行更一般的搜索。您甚至可以运行算法来帮助检测这些块,例如分层聚类算法。

(旁注:您还可以将格论的数学应用于此问题,因为您可以将每个集合视为位向量,它们一起形成格的基础。)


我应该对我的答案进行评论:经过一些实验,我无法找到贪心算法似乎不能在没有除法的情况下给出最优结果的情况。贪心算法如下:[...] - ninjagecko
保留产品缓存。按以下方式建立新产品:考虑从缓存中的每个产品到每个R的所有“路径”。考虑路径中每个术语如何减少问题规模(例如,考虑ab->abc->abcd:通过将abcd替换为x0,ab*c替换为x1,重新计算成本,并在所有路径之间进行比较来重写每个R)。替换每个R。这是我在答案中提到的“启发式”的详细说明。 - ninjagecko
非常好的建议!只是想知道MST方法是否接近最优? - John Smith

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接