2013-07-25 61 views
2

我試圖找到一個算法(不是一個matlab命令)枚舉所有可能的NxM矩陣與約束在每個單元格(或0)中只有正整數和固定的總和爲每個行和列(這些是算法的參數)。枚舉具有固定行和列總和的矩陣組合

例: 枚舉與行中的所有的2x3矩陣總計2,1和列總計0,1,2:

| 0 0 2 | = 2 
| 0 1 0 | = 1 
    0 1 2 

| 0 1 1 | = 2 
| 0 0 1 | = 1 
    0 1 2 

這是一個相當簡單的例子,但作爲N和M增加,以及總和,可能有很多的可能性。


編輯1

,我可能有一個有效的安排,以啓動算法:

matrix = new Matrix(N, M) // NxM matrix filled with 0s 
FOR i FROM 0 TO matrix.rows().count() 
    FOR j FROM 0 TO matrix.columns().count() 
    a = target_row_sum[i] - matrix.rows[i].sum() 
    b = target_column_sum[j] - matrix.columns[j].sum() 
    matrix[i, j] = min(a, b) 
    END FOR 
END FOR 

target_row_sum [I]是在第i行預期的總和。

在上面的例子中給出了第二種安排。


編輯2: (基於j_random_hacker's last statement

設M是任意矩陣驗證在給定條件(行和列總和固定的正或空單元格的值)。 (a,b,c,d)在M中的4個單元格值,其中(a,b)和(c,d)在同一行上,並且(a,c)和(b,d)同一列。 設Xa爲包含a的單元格的行號,Ya爲列號。

實施例:

| 1 a b | 
| 1 2 3 | 
| 1 c d | 
-> Xa = 0, Ya = 1 
-> Xb = 0, Yb = 2 
-> Xc = 2, Yc = 1 
-> Xd = 2, Yd = 2 

下面是一個算法,得到的所有組合驗證的初始條件,使只有A,B,C和D變化:

// A matrix array containing a single element, M 
// It will be filled with all possible combinations 
matrices = [M] 

I = min(a, d) 
J = min(b, c) 
FOR i FROM 1 TO I 
    tmp_matrix = M 
    tmp_matrix[Xa, Ya] = a - i 
    tmp_matrix[Xb, Yb] = b + i 
    tmp_matrix[Xc, Yc] = c - i 
    tmp_matrix[Xd, Yd] = d + i 
    matrices.add(tmp_matrix) 
END FOR 
FOR j FROM 1 TO J 
    tmp_matrix = M 
    tmp_matrix[Xa, Ya] = a + j 
    tmp_matrix[Xb, Yb] = b - j 
    tmp_matrix[Xc, Yc] = c + j 
    tmp_matrix[Xd, Yd] = d - j 
    matrices.add(tmp_matrix) 
END FOR 

應該然後可以找到矩陣值的所有可能組合:

  1. 將算法應用於每個位置的第一個矩陣4組細胞;
  2. 遞歸應用算法在前一次迭代獲得的每個子矩陣上,對於每個可能的4個單元組,除了父執行中已經使用的任何組以外;

遞歸深度應該是(N*(N-1)/2)*(M*(M-1)/2),每次執行導致((N*(N-1)/2)*(M*(M-1)/2) - depth)*(I+J+1)子矩陣。但是這會產生很多重複的矩陣,所以這可能會被優化。

回答

0

對於NXM矩陣,您有NXM未知數和N + M個方程。將隨機數放到左上(N-1)X(M-1)子矩陣中,除了(N-1,M-1)元素。現在,您可以輕鬆地找到其餘N + M元素的封閉格式。

更多細節:有總T = N * M個元素

有R =(N-1)+(M-1)-1隨機填寫元件。

剩餘未知數的數目:T-S = N * M - (N-1)×(M-1)+1 = N + M

+0

我剛剛編輯的問題包括一個額外的約束:單元格值必須是正整數或空整數,否則會有無數的安排,您的命題確實是唯一有效的答案。 –

1

你需要這個計算Fisher's exact test?因爲這需要你在做什麼,並且基於那個頁面,看起來通常會有大量的解決方案,所以如果你想要每個解決方案的話,你可能無法比暴力遞歸枚舉更好。 OTOH似乎蒙特卡羅近似值被一些軟件成功使用,而不是全面的枚舉。

我問了一個similar question,這可能會有所幫助。雖然這個問題涉及保留每行和每列字母的頻率而不是和,但是可以將一些結果翻譯出來。例如。如果您發現有數字的任何子矩陣(對未不一定相鄰行對未不一定相鄰列的)

xy 
yx 

然後,你可以重新排列這些到

yx 
xy 

無需更改任何一行或列總和。但是:

  • mhum's answer證明通常將有有效的矩陣不能通過任何這樣的2x2交換序列達到。這可以通過拍攝他的3x3矩陣和映射A -> 1,B -> 2,C -> 4來看出,並且注意到,因爲沒有元素在一行或一列中出現超過一次,所以原始矩陣中的頻率保持等同於新矩陣中的和保存。 但是...
  • someone's answer鏈接到一個數學證明,它實際上會爲基質,其條目是剛剛0或1

更一般地,如果您有任何小矩陣工作

ab 
cd 

其中(不必是唯一的)最小值爲d,那麼您可以用任何d + 1矩陣代替它

ef 
gh 

其中h = d-i,g = c + i,f = b + i且e = a-i,對於任何整數0 < = i < = d。

+0

事實上,我需要這種算法對大數據樣本進行Fisher's Exact測試(但是相對較低的細胞值,因此排除了任何漸進測試,如Chi²測試)。 我還需要另一個問題的算法,更實用,涉及許多賣方(每個賣方都有一組可變物品的可用物品)和買方試圖找到最佳配置,給定一組物品以不同數量購買(最低成本,包括每個賣家和每種物品的固定費用和可變費用......) - 但我會看看蒙特卡羅測試。 –

+0

如果行和列總和很低,則可以通過依次確定每行(例如)如何將不可區分的「大理石」分配給「箱」(其中行中的每個單元是箱並且行總數告訴你你有多少個彈珠。有(n + r-1)個選擇(r-1)種方式將r彈子分佈在n行的單個行上;將每行獲得的結果乘以一起,以獲得配置數量的鬆散上限(鬆散的,因爲某些分佈將被列總和取消)。 –