如何将某个矩阵组合成一个矩阵?

时间:2019-03-25 12:00:41

标签: java matrix multiplication

我正在尝试用分而治之进行矩阵乘法。所以,我想,我已经将分解部分分解成子问题(递归案例和基础案例)。

因此,我有四个象限(左上,左下,右上,右下),并且我正在考虑如何将它们合并到结果矩阵中,我不知道。

我正在使用Java,所以我有matrixA和matrixB,并且有一些索引,例如matrixRowsA,matrixColumnsA,matrixRowsB,matrixColumnsB

通过这种方式,我避免创建新的矩阵以及所有只会增加问题解决成本的东西。

所以基本问题是,如何将4个子矩阵连接为填充子矩阵?

所以方法是调用divideAndConquer:

private static int[][] divideAndConquer(int[][]matrixA, int beginRowsA, int endRowsA, int beginColumnsA,
                                        int endColumnsA, int[][]matrixB, int beginRowsB, int endRowsB,
                                        int beginColumnsB, int endColumnsB)
{
    // Base case
    if(lengthOfBothMatrix()==1)
    {
        return multiplyMatrix(matrixA,matrixB);
    }
    }
    else
    {
        int middleRowsA = obtainMiddleRowsB();
        int middleColumnsA = obtainMiddleColumnsA();
        int middleRowsB = obtainMiddleRowsB();
        int middleColumnsB = obtainMiddleColumnsB();

        int[][] leftSuperiorQuadrant = matrixAddition(divideAndConquer(matrixA, beginRowsA, middleRowsA, beginColumnsA, middleColumnsA, matrixB, beginRowsB,
                middleRowsB, beginColumnsB, middleColumnsB),
                divideAndConquer(matrixA, beginRowsA, middleRowsA, middleColumnsA+1, endColumnsA,
                        matrixB, middleRowsB+1, endRowsB, beginColumnsB, middleColumnsB));
        int[][] leftInferiorQuadrant = matrixAddition(divideAndConquer(matrixA, middleRowsA+1, endRowsA, beginColumnsA, middleColumnsA,
                matrixB, beginRowsB,middleRowsB, beginColumnsB, middleColumnsB),
                divideAndConquer(matrixA, middleRowsA+1, endRowsA, middleColumnsA+1, endColumnsA,
                        matrixB, middleRowsB+1, endRowsB, beginColumnsB, middleColumnsB));

        int[][] rightSuperiorQuadrant = matrixAddition(divideAndConquer(matrixA, beginRowsA, middleRowsA, beginColumnsA, middleColumnsA,
                matrixB, beginRowsB, middleRowsB, middleColumnsB+1, endColumnsB),
                divideAndConquer(matrixA, beginRowsA, middleRowsA, middleColumnsA+1, endColumnsA,
                        matrixB, middleRowsB+1, endRowsB, middleColumnsB+1, endColumnsB));
        int[][] rightInferiorQuadrant =matrixAddition(divideAndConquer(matrixA, middleRowsA+1, endRowsA, beginColumnsA, middleColumnsA,
                matrixB, beginRowsB, middleRowsB, middleColumnsB+1, endColumnsB),
                divideAndConquer(matrixA, middleRowsA+1, endRowsA, middleColumnsA+1, endColumnsA,
                        matrixB, middleRowsB+1, endRowsB, middleColumnsB+1, endColumnsB));

我正在使用两个矩阵进行测试:

1 | 2 | 3 | 4 | 
1 | 2 | 3 | 4 | 
1 | 2 | 3 | 4 | 
1 | 2 | 3 | 4 | 
1 | 2 | 3 | 4 | 
1 | 2 | 3 | 4 | 
1 | 2 | 3 | 4 | 
1 | 2 | 3 | 4 | 

2 个答案:

答案 0 :(得分:1)

首先,您可以使用System.arraycopy()将左矩阵(leftSuperiorQuadrant和leftInferiorQuadrant)和右矩阵(rightSuperiorQuadrant&rightInferiorQuadrant)垂直合并为新列矩阵:

    int leftSuperiorQuadrant [][] = {{1, 2}, {3, 4}};
    int rightSuperiorQuadrant [][] = {{5, 6}, {7, 8}};
    int leftInferiorQuadrant [][] = {{9, 10}, {11, 12}};
    int rightInferiorQuadrant [][] = {{13, 14}, {15, 16}};

    int m_intermediate_left[][] = new int[leftSuperiorQuadrant.length+leftInferiorQuadrant.length][];
    int m_intermediate_right[][] = new int[rightSuperiorQuadrant.length+rightInferiorQuadrant.length][];

    // Concat leftSuperiorQuadrant and leftInferiorQuadrant in column
    System.arraycopy(leftSuperiorQuadrant, 0, m_intermediate_left, 0, leftSuperiorQuadrant.length);
    System.arraycopy(leftInferiorQuadrant, 0, m_intermediate_left, leftSuperiorQuadrant.length, leftInferiorQuadrant.length);

    // Concat rightSuperiorQuadrant and rightInferiorQuadrant in column
    System.arraycopy(rightSuperiorQuadrant, 0, m_intermediate_right, 0, rightSuperiorQuadrant.length);
    System.arraycopy(rightInferiorQuadrant, 0, m_intermediate_right, rightSuperiorQuadrant.length, rightInferiorQuadrant.length);

    System.out.println(Arrays.deepToString(m_intermediate_left));
    System.out.println(Arrays.deepToString(m_intermediate_right));

这将返回:

  

[[1,2],[3,4],[9,10],[11,12]]

1  | 2
3  | 4
9  | 10
11 | 12
  

[[5,6],[7,8],[13,14],[15,16]]

5  | 6   
7  | 8  
13 | 14 
15 | 16

然后,您可以手动水平合并这些结果矩阵:

    int m_final[][] = new int[m_intermediate_left.length][m_intermediate_left[0].length+m_intermediate_right[0].length];

    // For each row of the final matrix
    for(int i = 0; i < m_final.length; i++) {
      // For each column of the final matrix     
      for (int j = 0; j < m_final[0].length; j++) {
        // If j corresponds to the left columns, add left matrix values 
        if (j < m_intermediate_left[0].length) {
            m_final[i][j] = m_intermediate_left[i][j];
        }
        // If j corresponds to the right columns, add the right matrix values
        else {
            m_final[i][j] = m_intermediate_right[i][j - m_intermediate_left[0].length];
        }
      }
    }

    System.out.println(Arrays.deepToString(m_final));

这将返回您的欲望矩阵:

  

[[1、2、5、6],[3、4、7、8],[9、10、13、14],[11、12、15、16]]

1  | 2   | 5  | 6 
3  | 4   | 7  | 8
9  | 10  | 13 | 14
11 | 12  | 15 | 16

请注意,如果您的象限具有不同的大小,它将无法正常工作。

最佳

答案 1 :(得分:1)

我仍然想要:

  • 指出,分而治之中的 division 应该沿着(乘法)算法的“ break”界线;
  • 提及不错的Arrays类。

进行最费力的明智部门很重要。 对于矩阵乘法,将一半拆分似乎更合适:

非常粗略:

A: (3x5)      B: (5x3)    A x B: (3x3)
a a b b b     c c c       ... ac ... bd ...
a a b b b     c c c      
a a b b b     d d d      
              d d d
              d d d

如您所见,您可以将任务分为Aa x Bc和Ab x Bd,然后将结果整洁地合并。

这很复杂,也很容易理解。

另一个技巧是使用更多数学上的 short 名称,以便于阅读。尽管通常应该使用足够长的名称,但是该过程可能需要相反的名称。

int[][] multiply(int[][] a, int[][] b) {
    int rows = a.length;
    int cols = b[0].length;
    int terms = b.length:
    if (terms != a[0].length) {
        throw new IllegalArgumentException(
            "Dimensions do not match: " + a[0].length + " != " + terms);
    }
    int[][] product = new int[rows][cols];
    if (terms < 2) { // Cannot divide
        if (terms == 1) {
            for (int i = 0; i < rows; ++i) {
                for (int j = 0; j < cols; ++j) {
                    product[i][j] = a[i][0] * b[0][j];
                }
            }
        }
    } else {
        int half = terms/2;

        int[][] aLeft = new int[rows][half];
        int[][] bTop = new int[half][cols];
        ... fill using Arrays.copyOfRange ...
        int[][] prodLT = multiply(aLeft, bTop);

        int[][] aRight = new int[rows][terms - half];
        int[][] bBottom = new int[terms - half][cols];
        ... fill using Arrays.copyOfRange ...
        int[][] prodRB = multiply(aRight, bBottom);

        ... add prodLT to prodRB into product
    }
    return product;
}