我有一组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}
答案 0 :(得分:1)
首先,您不需要分工
此处不需要除法,它将永远是一个额外的计算。
如果你需要分割它意味着你已经进行了多重植入,因此如果你分开就撤消你已经完成的工作。
例如,如果通过将Pi * Pj * Pk * Pn除以Pn来计算Pi * Pj * Pk,则意味着您之前计算了Pi * Pj * Pk * Pn,因此您之前计算了Pi * Pj * Pk。
(我假设你的所有号码都是素数)
我的解决方案
我有一个想法,没有考虑分裂的可能性。
您可以开始使用您的Ri构建suffix tree。
然后乘法的数量将是树中边的数量。
示例:
使用您的示例后缀树将是:
P2
/ \
P4 P1
/ \
P3 P1
你得到4次乘法:
M1=P1*P2
M2=P2*P4
M3=M2*P1
M4=M2*P3
查找最小乘法数相当于构建具有最小边数的后缀树。
希望这可以提供帮助。
答案 1 :(得分:1)
考虑元素R i 的图形,没有边缘。我们现在允许自己添加如下边缘:
例如,我们可以绘制边R 1 →R 3 ,成本乘以R 1 / R 3 = P3 * P4 / P1
对所有节点执行此操作,因此您具有| R | 2 边缘。
现在,如果仅使用了中间结果,则可以使用最小生成树算法来解决此问题。我相信MST算法的边数非常接近线性(逆Ackermann的一个因子,比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
,然后除以P i ,得到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
的过程中记住P1*P2*P3*P4
和P1*P2*P3*P4*P5
。然后我们可以免费获得R5
(而R4
通过另一种方式只需一次乘法,不幸的是成本与以前相同),将总费用从9降低到8.这导致我们猜测在很长一段时间后,使用任意边缘执行http://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm也可能产生最佳解决方案。
无论如何,我们如何将这样的系统整合到我们的解决方案中?我们无法添加节点,因为这会弄乱MST算法。对于每个边缘,乘以或除以临时表达式E不会使某些P具有超过幂p(例如对于p = 2,我们允许中间的临时表达式创建像P1 * P4^2 / P3
这样的产品但是不允许像{{1}这样的东西我们在边缘上执行乘法和除法,并创建两个新边。 (我们可能不止一次或在将来的日期这样做。)我们也对边缘的所有子集执行此操作,我们将如上所述进行记忆。如果使用MST算法,这种方法的成本是边数增加很多,所以也许(| R | + #newedges) 2 =(| R | ^ | P |) 2 可能在更糟糕的情况下,显着增加了找到最佳答案所需的时间。
(旁注:您可能也可以将关于格子的数学应用于此问题,因为您可以将每个集合视为位向量,它们共同构成格子的基础。)
答案 2 :(得分:1)
没有分歧,这似乎等同于Gary & Johnson中描述的问题ENSEMBLE COMPUTATION,因此NP-complete。
[PO9] ENSEMBLE COMPUTATION
实例:a的子集的集合C. 有限集A,正整数J.
问题:是否有序列S = (z_1&lt; - x_1 U y_1,z_2&lt; - x_2 U y_2,...,z_j&lt; - x_j U y_j)j&lt; = J 联合运算,其中每个x_i和y_i对于A中的某个a是{a} 或某些k的z_k < i,使得x_i和y_i是不相交的,1&lt; = i&lt; = j,并且对于C中的每个子集c,存在一些z_i,1 <= i &lt; = j,这与C相同。
你的集合I对应于A,每个R_i对应于C的元素,乘法对应于集合。