簡體   English   中英

有效的方法來進行求和

[英]efficient methods to do summation

是否有任何有效的技術可以進行以下求和?

給定有限集A,其包含n個整數A = {X1,X2,...,Xn} ,其中Xi是整數。 現在 N個子集,由A1,A2,...,一個表示。 我們想要計算每個子集的總和。 有一些有效的技術嗎?

(注意, n通常大於A的所有子集的平均大小。)

例如,如果A = {1,2,3,4,5,6,7,9}A1 = {1,3,4,5}A2 = {2,3,4} ,則A3 = .. 。 一種計算A1A2總和的簡單方法需要5個Flops來添加:

總和(A1)= 1 + 3 + 4 + 5 = 13

總和(A2)= 2 + 3 + 4 = 9

...

現在,如果首先計算3 + 4,然后記錄其結果7,我們只需要3個Flops進行添加:

總和(A1)= 1 + 7 + 5 = 13

總和(A2)= 2 + 7 = 9

...

廣義案例怎么樣? 有沒有有效的方法來加速計算? 謝謝!

假設'addition'不僅僅是一個ADD操作,而是一些涉及兩個整數操作數的非常密集的函數,那么一個明顯的方法是緩存結果。

您可以通過合適的數據結構來實現這一點,例如包含由兩個操作數組成的鍵的鍵值字典以及作為值的答案。

但是當你在問題中指定C時,最簡單的方法是nn整數數組,其中x + y的解存儲在array[x][y]

然后,您可以重復遍歷子集,並為每對操作數檢查數組中的適當位置。 如果沒有值,則必須計算它並將其放入數組中。 然后,該值將替換子集中的兩個操作數,並進行迭代。

如果操作是可交換的,則應在查找數組之前對操作數進行排序(即,使得第一個索引始終是兩個操作數中的最小值),因為這將最大化“高速緩存”命中。

對於某些子集選擇,有一些方法可以加快計算速度,如果你不介意做一些(可能很昂貴的)預計算,但並不是所有人都可以。 例如,假設您的子集是{1,2},{2,3},{3,4},{4,5},...,{n-1,n},{n,1}; 那么天真的方法每個子集使用一個算術運算,你顯然不能做得更好。 另一方面,如果您的子集是{1},{1,2},{1,2,3},{1,2,3,4},...,{1,2,...,那么你可以用n-1算術運算得到,而天真的方法則要糟糕得多。

這是進行預計算的一種方法。 它並不總能找到最佳結果。 對於每對子集,將轉換成本定義為min(對稱差異的大小,Y-1的大小)。 (X和Y的對稱差異是X或Y中的事物集合,但不是兩者。)因此,轉移成本是計算Y元素總和所需的算術運算數,給定總和X的。 將空集添加到子集列表中,並使用Edmonds算法(http://en.wikipedia.org/wiki/Edmonds%27_algorithm)或更快但更復雜的變體之一計算最小成本定向生成樹那個主題。 現在確保當生成樹有一個邊X - > Y時,你在Y之前計算X.(這是一個“拓撲排序”,可以有效地完成。)

例如,當你有{1,2},{3,4},{1,2,3,4},{5,6},{7,8},{5,6時,這將給出明顯不理想的結果,7,8}。 在使用上面的過程確定您的操作順序之后,您可以執行優化過程,在這里您可以找到更便宜的方法來評估已經計算出的總和的每個集合的總和,這可能會在實踐中給出相當不錯的結果。

我懷疑,但沒有試圖證明,找到一組給定子集的最佳程序是NP難或更差。 (它當然是可計算的 ;你可能做的一組可能的計算是有限的。但是,從它的表面來看,它可能非常昂貴;可能你可能會跟蹤大約2 ^ n個部分總和,添加任何一個它們在每個步驟中對任何其他步驟,並且具有高達大約n ^ 2步,對於超級天真的成本(2 ^ 2n)^(n ^ 2)= 2 ^(2n ^ 3)操作來嘗試每種可能性。 )

常見的優化技術是預先計算中間結果。 在您的情況下,您可以使用A 2個加數預先計算所有總和,並將它們存儲在查找表中。 這將導致|A|*|A+1|/2表條目,其中|A| A的基數。

為了計算Ai的元素總和,你:

  • 查找Ai的前兩個元素的總和並將它們保存在tmp中
  • 在Ai中有一個元素x:
  • 查找tmp和x的總和

要從您的示例計算A1 = {1,3,4,5}的元素總和,請執行以下操作:

  • lookup(1,3)= 4
  • lookup(4,4)= 8
  • lookup(8,5)= 13

注意,計算任何給定Ai的總和不需要求和,因為在預先計算查找表時已經進行了所有工作。

如果將查找表存儲在哈希表中,則lookup()位於O(1)中。


可能優化此方法:

  • 在計算求和結果的同時構造查找表; 因此,您只計算實際需要的那些總和。 您的查找表現在是一個緩存。
  • 如果您的加法操作是可交換的,則可以通過僅存儲較小的加數首先出現的那些求和來節省一半的高速緩存大小。 然后修改lookup()使lookup(a,b) = lookup(b,a)如果a > b

如果假設求和是耗時的動作,你可以找到每對子集的LCS (通過假設它們按照注釋中的提及進行排序,或者如果它們沒有排序排序),之后計算最大長度的LCS總和(在所有LCS上)成對),然后用相關數字替換它在相關數組中的值,更新它們的LCS並繼續這種方式,直到沒有多個數字的LCS。 當然這不是最佳的,但它比天真的算法(總和的數量更少)更好。 但是,您可以進行回溯以找到最佳解決方案。

例如,您的樣本輸入:

A1={1,3,4,5} , A2={2,3,4}

LCS (A_1,A_2) = {3,4} ==>7 ==>replace it:

A1={1,5,7}, A2={2,7} ==> LCS = {7}, maximum LCS length is `1`, so calculate sums.

你仍然可以通過兩個隨機數的計算總和來改進它,然后再次采用LCS,......

沒有。 沒有高效的技術。

因為它是NP完全問題。 而這種問題沒有有效的解決方案

為什么NP完全?
我們可以使用算法來解決集合覆蓋問題 ,只需在集合中添加額外的集合,包含所有元素。

示例:我們有多組元素
A1 = {1,2},A2 = {2,3},A3 = {3,4}我們想解決集合覆蓋問題。

我們添加到這個集合中,包含所有元素的數字集合A4 = {1,2,3,4}

我們使用約翰史密斯正在尋求的algorhitm,我們檢查解決方案A4代表whit。 我們解決了NP-Complete問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM