2012-03-02 99 views
4

我正在尋找C中的Strassen's Algorithm的實現,並且我在最後發現了這個代碼。如何使用此C代碼使用Strassen算法來乘兩個矩陣?

要使用multiply功能:

void multiply(int n, matrix a, matrix b, matrix c, matrix d); 

,它乘兩個矩陣ab並提出在c結果(d是一箇中介矩陣)。矩陣ab應具有以下類型:

typedef union _matrix 
{ 
    double **d; 
    union _matrix **p; 
} *matrix; 

我已動態分配四個矩陣abcd(雙打的二維陣列),並分配其地址字段_matrix.d

#include "strassen.h" 

#define SIZE 50 

int main(int argc, char *argv[]) 
{ 
    double ** matA, ** matB, ** matC, ** matD; 
    union _matrix ma, mb, mc, md; 
    int i = 0, j = 0, n; 

    matA = (double **) malloc(sizeof(double *) * SIZE); 
    for (i = 0; i < SIZE; i++) 
     matA[i] = (double *) malloc(sizeof(double) * SIZE); 
    // Do the same for matB, matC, matD. 

    ma.d = matA; 
    mb.d = matB; 
    mc.d = matC; 
    md.d = matD; 

    // Initialize matC and matD to 0. 

    // Read n. 

    // Read matA and matB. 

    multiply(n, &ma, &mb, &mc, &md); 
    return 0; 
} 

此代碼成功編譯,但與n>BREAK崩潰。

strassen.c:

#include "strassen.h" 

/* c = a * b */ 
void multiply(int n, matrix a, matrix b, matrix c, matrix d) 
{ 
    if (n <= BREAK) { 
     double sum, **p = a->d, **q = b->d, **r = c->d; 
     int i, j, k; 

     for (i = 0; i < n; i++) 
     for (j = 0; j < n; j++) { 
      for (sum = 0., k = 0; k < n; k++) 
       sum += p[i][k] * q[k][j]; 
      r[i][j] = sum; 
     } 
    } else { 
     n /= 2; 
     sub(n, a12, a22, d11); 
     add(n, b21, b22, d12); 
     multiply(n, d11, d12, c11, d21); 
     sub(n, a21, a11, d11); 
     add(n, b11, b12, d12); 
     multiply(n, d11, d12, c22, d21); 
     add(n, a11, a12, d11); 
     multiply(n, d11, b22, c12, d12); 
     sub(n, c11, c12, c11); 
     sub(n, b21, b11, d11); 
     multiply(n, a22, d11, c21, d12); 
     add(n, c21, c11, c11); 
     sub(n, b12, b22, d11); 
     multiply(n, a11, d11, d12, d21); 
     add(n, d12, c12, c12); 
     add(n, d12, c22, c22); 
     add(n, a21, a22, d11); 
     multiply(n, d11, b11, d12, d21); 
     add(n, d12, c21, c21); 
     sub(n, c22, d12, c22); 
     add(n, a11, a22, d11); 
     add(n, b11, b22, d12); 
     multiply(n, d11, d12, d21, d22); 
     add(n, d21, c11, c11); 
     add(n, d21, c22, c22); 
    } 
} 

/* c = a + b */ 
void add(int n, matrix a, matrix b, matrix c) 
{ 
    if (n <= BREAK) { 
     double **p = a->d, **q = b->d, **r = c->d; 
     int i, j; 

     for (i = 0; i < n; i++) 
      for (j = 0; j < n; j++) 
       r[i][j] = p[i][j] + q[i][j]; 
    } else { 
     n /= 2; 
     add(n, a11, b11, c11); 
     add(n, a12, b12, c12); 
     add(n, a21, b21, c21); 
     add(n, a22, b22, c22); 
    } 
} 

/* c = a - b */ 
void sub(int n, matrix a, matrix b, matrix c) 
{ 
    if (n <= BREAK) { 
     double **p = a->d, **q = b->d, **r = c->d; 
     int i, j; 

     for (i = 0; i < n; i++) 
      for (j = 0; j < n; j++) 
       r[i][j] = p[i][j] - q[i][j]; 
    } else { 
     n /= 2; 
     sub(n, a11, b11, c11); 
     sub(n, a12, b12, c12); 
     sub(n, a21, b21, c21); 
     sub(n, a22, b22, c22); 
    } 
} 

strassen.h:

#define BREAK 8 

typedef union _matrix { 
    double **d; 
    union _matrix **p; 
} *matrix; 

/* Notational shorthand to access submatrices for matrices named a, b, c, d */ 

#define a11 a->p[0] 
#define a12 a->p[1] 
#define a21 a->p[2] 
#define a22 a->p[3] 
#define b11 b->p[0] 
#define b12 b->p[1] 
#define b21 b->p[2] 
#define b22 b->p[3] 
#define c11 c->p[0] 
#define c12 c->p[1] 
#define c21 c->p[2] 
#define c22 c->p[3] 
#define d11 d->p[0] 
#define d12 d->p[1] 
#define d21 d->p[2] 
#define d22 d->p[3] 

我的問題是如何使用功能multiply(如何實現矩陣)。

strassen.h

strassen.c

+4

不要在C中使用'malloc()'來返回返回值。 – 2012-03-02 19:24:29

+3

請不要傾銷這麼大的代碼塊,而是要清楚地解釋問題所在!並告訴你所嘗試的以及你懷疑的是什麼?您當前版本的問題可能會讓人發癢 – 2012-03-02 19:27:14

+2

'n'未初始化在您的'main'中 – pezcode 2012-03-07 02:55:55

回答

3

Atom said一樣,您需要爲兩個矩陣正確初始化matrix.p。所有的

1)首先,你的matrixunion所以p實質上成爲d解釋爲_matrix **它沒有意義在這裏 - 這就是爲什麼它崩潰。相反,您可能需要製作matrix a struct
最後,p根據定義是一個子矩陣數組,因此它應該是struct _matrix *(並且需要時您需要malloc實際數組)或struct _matrix[4](這是不可能的:))。

typedef struct _matrix 
{ 
    double **d; 
    struct _matrix *p; 
} *matrix; 

2)現在,讓我們來看看p應該是什麼。

      │ 
A.d -> d1 -> a[1,1] a[1,2]│a[1,3] a[1,4] 
     d2 -> a[2,1] a[2,2]│a[2,3] a[2,4] 
      ───────────────────────────── 
     d3 -> a[3,1] a[3,2]│a[3,3] a[3,4] 
     d4 -> a[4,1] a[4,2]│a[4,3] a[4,4] 
          │ 

pmatrix結構的數組!的特點是使d的這些結構的指向內部一個 以這樣的方式(p[k].d)[i][j]是各子矩陣的元素:

p[0].d -> p01 -> a[1,1] p[1].d -> p11 -> a[1,3] 
      p02 -> a[2,1]    p12 -> a[2,3] 

p[2].d -> p21 -> a[3,1] p[3].d -> p31 -> a[3,3] 
      p22 -> a[4,1]    p32 -> a[4,3] 

你現在可以推斷算法初始化p方形一任意均勻大小的

何時初始化它呢? ;)

+0

我認爲,根據上述定義,作者想要爲矩陣引入分層存儲。假設你有一個8×8的矩陣,BREAK的值是2,你首先分配p來表示4個子矩陣,而這個p將代表4個矩陣d。所以你分配1 + 4倍的P和16倍的D。 否則爲什麼有人想要分而治之地添加矩陣? – zapstar 2015-05-31 09:45:36

2

當n> BREAK,矩陣乘法算法使用分層矩陣表示(該字段的union _matrixp,而非字段d)。

當分配內存和初始化矩陣ab時,您需要調整分層表示的代碼。

+0

問題是我沒有弄清楚如何做到這一點,我已經使用標準的動態分配爲二維數組,但代碼崩潰時,它涉及到n>休息,謝謝 – obo 2012-03-08 05:34:34

+0

你的意思是「two」而不是「tow」? – 2012-03-08 07:19:59

2

嗯,我不太確定你發佈的代碼有什麼問題,但是我想指出一下剛剛在英特爾編程比賽中使用的Strassen算法的實現:http://software.intel.com/file/21818。也許你可以在那裏找到一些有用的提示。

+0

這是僅有鏈接的答案的問題。您的鏈接不再指向Strassen算法的實現 - 僅僅是某種分形的圖片...... – NoseKnowsAll 2017-04-22 20:49:17