java实现任意矩阵Strassen算法

本例输入为两个任意尺寸的矩阵m * n, n * m,输出为两个矩阵的乘积。计算任意尺寸矩阵相乘时,使用了Strassen算法。程序为自编,经过测试,请放心使用。基本算法是:
1.对于方阵(正方形矩阵),找到最大的l, 使得l = 2 ^ k, k为整数并且l < m。边长为l的方形矩阵则采用Strassen算法,其余部分以及方形矩阵中遗漏的部分用蛮力法。
2.对于非方阵,依照行列相应添加0使其成为方阵。
StrassenMethodTest.java

package matrixalgorithm;

import java.util.Scanner;

public class StrassenMethodTest {

  private StrassenMethod strassenMultiply;

   StrassenMethodTest(){
    strassenMultiply = new StrassenMethod();
  }//end cons

   public static void main(String[] args){
    Scanner input = new Scanner(System.in);
    System.out.println("Input row size of the first matrix: ");
    int arow = input.nextInt();
    System.out.println("Input column size of the first matrix: ");
    int acol = input.nextInt();
    System.out.println("Input row size of the second matrix: ");
    int brow = input.nextInt();
    System.out.println("Input column size of the second matrix: ");
    int bcol = input.nextInt();

    double[][] A = new double[arow][acol];
    double[][] B = new double[brow][bcol];
    double[][] C = new double[arow][bcol];
    System.out.println("Input data for matrix A: ");

    /*In all of the codes later in this project,
    r means row while c means column.
    */
    for (int r = 0; r < arow; r++) {
      for (int c = 0; c < acol; c++) {
        System.out.printf("Data of A[%d][%d]: ", r, c);
        A[r][c] = input.nextDouble();
      }//end inner loop
    }//end loop

    System.out.println("Input data for matrix B: ");
    for (int r = 0; r < brow; r++) {
      for (int c = 0; c < bcol; c++) {
        System.out.printf("Data of A[%d][%d]: ", r, c);
        B[r][c] = input.nextDouble();
      }//end inner loop
    }//end loop

    StrassenMethodTest algorithm = new StrassenMethodTest();
    C = algorithm.multiplyRectMatrix(A, B, arow, acol, brow, bcol);

    //Display the calculation result:
    System.out.println("Result from matrix C: ");
    for (int r = 0; r < arow; r++) {
      for (int c = 0; c < bcol; c++) {
        System.out.printf("Data of C[%d][%d]: %f\n", r, c, C[r][c]);
      }//end inner loop
    }//end outter loop
   }//end main

  //Deal with matrices that are not square:
  public double[][] multiplyRectMatrix(double[][] A, double[][] B,
      int arow, int acol, int brow, int bcol) {
    if (arow != bcol) //Invalid multiplicatio
      return new double[][]{{0}};

    double[][] C = new double[arow][bcol];

    if (arow < acol) {

      double[][] newA = new double[acol][acol];
      double[][] newB = new double[brow][brow];

      int n = acol;

      for (int r = 0; r < acol; r++)
        for (int c = 0; c < acol; c++)
          newA[r][c] = 0.0;

      for (int r = 0; r < brow; r++)
        for (int c = 0; c < brow; c++)
          newB[r][c] = 0.0;

      for (int r = 0; r < arow; r++)
        for (int c = 0; c < acol; c++)
          newA[r][c] = A[r][c];

      for (int r = 0; r < brow; r++)
        for (int c = 0; c < bcol; c++)
          newB[r][c] = B[r][c];

      double[][] C2 = multiplySquareMatrix(newA, newB, n);
      for(int r = 0; r < arow; r++)
        for(int c = 0; c < bcol; c++)
          C[r][c] = C2[r][c];
    }//end if

    else if(arow == acol)
      C = multiplySquareMatrix(A, B, arow);

    else {
      int n = arow;
      double[][] newA = new double[arow][arow];
      double[][] newB = new double[bcol][bcol];

      for (int r = 0; r < arow; r++)
        for (int c = 0; c < arow; c++)
          newA[r][c] = 0.0;

      for (int r = 0; r < bcol; r++)
        for (int c = 0; c < bcol; c++)
          newB[r][c] = 0.0;

      for (int r = 0; r < arow; r++)
        for (int c = 0; c < acol; c++)
          newA[r][c] = A[r][c];

      for (int r = 0; r < brow; r++)
        for (int c = 0; c < bcol; c++)
          newB[r][c] = B[r][c];

      double[][] C2 = multiplySquareMatrix(newA, newB, n);
      for(int r = 0; r < arow; r++)
        for(int c = 0; c < bcol; c++)
          C[r][c] = C2[r][c];
    }//end else

     return C;
   }//end method

  //Deal with matrices that are square matrices.
   public double[][] multiplySquareMatrix(double[][] A2, double[][] B2, int n){

     double[][] C2 = new double[n][n];

     for(int r = 0; r < n; r++)
       for(int c = 0; c < n; c++)
         C2[r][c] = 0;

     if(n == 1){
      C2[0][0] = A2[0][0] * B2[0][0];
      return C2;
     }//end if

     int exp2k = 2;

     while(exp2k <= (n / 2) ){
       exp2k *= 2;
     }//end loop

     if(exp2k == n){
       C2 = strassenMultiply.strassenMultiplyMatrix(A2, B2, n);
       return C2;
     }//end else

     //The "biggest" strassen matrix:
     double[][][] A = new double[6][exp2k][exp2k];
     double[][][] B = new double[6][exp2k][exp2k];
     double[][][] C = new double[6][exp2k][exp2k];

     for(int r = 0; r < exp2k; r++){
       for(int c = 0; c < exp2k; c++){
         A[0][r][c] = A2[r][c];
         B[0][r][c] = B2[r][c];
       }//end inner loop
     }//end outter loop

    C[0] = strassenMultiply.strassenMultiplyMatrix(A[0], B[0], exp2k);

    for(int r = 0; r < exp2k; r++)
      for(int c = 0; c < exp2k; c++)
        C2[r][c] = C[0][r][c];

    int middle = exp2k / 2;

    for(int r = 0; r < middle; r++){
      for(int c = exp2k; c < n; c++){
        A[1][r][c - exp2k] = A2[r][c];
        B[3][r][c - exp2k] = B2[r][c];
      }//end inner loop
    }//end outter loop

    for(int r = exp2k; r < n; r++){
      for(int c = 0; c < middle; c++){
        A[3][r - exp2k][c] = A2[r][c];
        B[1][r - exp2k][c] = B2[r][c];
      }//end inner loop
    }//end outter loop

    for(int r = middle; r < exp2k; r++){
      for(int c = exp2k; c < n; c++){
        A[2][r - middle][c - exp2k] = A2[r][c];
        B[4][r - middle][c - exp2k] = B2[r][c];
      }//end inner loop
    }//end outter loop

    for(int r = exp2k; r < n; r++){
      for(int c = middle; c < n - exp2k + 1; c++){
        A[4][r - exp2k][c - middle] = A2[r][c];
        B[2][r - exp2k][c - middle] = B2[r][c];
      }//end inner loop
    }//end outter loop

    for(int i = 1; i <= 4; i++)
      C[i] = multiplyRectMatrix(A[i], B[i], middle, A[i].length, A[i].length, middle);

    /*
    Calculate the final results of grids in the "biggest 2^k square,
    according to the rules of matrice multiplication.
    */
    for (int row = 0; row < exp2k; row++) {
       for (int col = 0; col < exp2k; col++) {
         for (int k = exp2k; k < n; k++) {
           C2[row][col] += A2[row][k] * B2[k][col];
         }//end loop
       }//end inner loop
     }//end outter loop

    //Use brute force to solve the rest, will be improved later:
    for(int col = exp2k; col < n; col++){
      for(int row = 0; row < n; row++){
        for(int k = 0; k < n; k++)
          C2[row][col] += A2[row][k] * B2[k][row];
      }//end inner loop
    }//end outter loop

    for(int row = exp2k; row < n; row++){
      for(int col = 0; col < exp2k; col++){
        for(int k = 0; k < n; k++)
          C2[row][col] += A2[row][k] * B2[k][row];
      }//end inner loop
    }//end outter loop   

    return C2;
   }//end method

}//end class

StrassenMethod.java

package matrixalgorithm;

import java.util.Scanner;

public class StrassenMethod {

  private double[][][][] A = new double[2][2][][];
  private double[][][][] B = new double[2][2][][];
  private double[][][][] C = new double[2][2][][];

  /*//Codes for testing this class:
    public static void main(String[] args) {
    Scanner input = new Scanner(System.in);
    System.out.println("Input size of the matrix: ");
    int n = input.nextInt();

    double[][] A = new double[n][n];
    double[][] B = new double[n][n];
    double[][] C = new double[n][n];
    System.out.println("Input data for matrix A: ");
    for (int r = 0; r < n; r++) {
      for (int c = 0; c < n; c++) {
        System.out.printf("Data of A[%d][%d]: ", r, c);
        A[r][c] = input.nextDouble();
      }//end inner loop
    }//end loop

    System.out.println("Input data for matrix B: ");
    for (int r = 0; r < n; r++) {
      for (int c = 0; c < n; c++) {
        System.out.printf("Data of A[%d][%d]: ", r, c);
        B[r][c] = input.nextDouble();
      }//end inner loop
    }//end loop

    StrassenMethod algorithm = new StrassenMethod();
    C = algorithm.strassenMultiplyMatrix(A, B, n);

    System.out.println("Result from matrix C: ");
    for (int r = 0; r < n; r++) {
      for (int c = 0; c < n; c++) {
        System.out.printf("Data of C[%d][%d]: %f\n", r, c, C[r][c]);
      }//end inner loop
    }//end outter loop

  }//end main*/

   public double[][] strassenMultiplyMatrix(double[][] A2, double B2[][], int n){
    double[][] C2 = new double[n][n];
    //Initialize the matrix:
    for(int rowIndex = 0; rowIndex < n; rowIndex++)
      for(int colIndex = 0; colIndex < n; colIndex++)
        C2[rowIndex][colIndex] = 0.0;

    if(n == 1)
      C2[0][0] = A2[0][0] * B2[0][0];
    //"Slice matrices into 2 * 2 parts:
    else{
      double[][][][] A = new double[2][2][n / 2][n / 2];
      double[][][][] B = new double[2][2][n / 2][n / 2];
      double[][][][] C = new double[2][2][n / 2][n / 2];

      for(int r = 0; r < n / 2; r++){
        for(int c = 0; c < n / 2; c++){
          A[0][0][r][c] = A2[r][c];
          A[0][1][r][c] = A2[r][n / 2 + c];
          A[1][0][r][c] = A2[n / 2 + r][c];
          A[1][1][r][c] = A2[n / 2 + r][n / 2 + c];

          B[0][0][r][c] = B2[r][c];
          B[0][1][r][c] = B2[r][n / 2 + c];
          B[1][0][r][c] = B2[n / 2 + r][c];
          B[1][1][r][c] = B2[n / 2 + r][n / 2 + c];
        }//end loop
      }//end loop

      n = n / 2;

      double[][][] S = new double[10][n][n];
      S[0] = minusMatrix(B[0][1], B[1][1], n);
      S[1] = addMatrix(A[0][0], A[0][1], n);
      S[2] = addMatrix(A[1][0], A[1][1], n);
      S[3] = minusMatrix(B[1][0], B[0][0], n);
      S[4] = addMatrix(A[0][0], A[1][1], n);
      S[5] = addMatrix(B[0][0], B[1][1], n);
      S[6] = minusMatrix(A[0][1], A[1][1], n);
      S[7] = addMatrix(B[1][0], B[1][1], n);
      S[8] = minusMatrix(A[0][0], A[1][0], n);
      S[9] = addMatrix(B[0][0], B[0][1], n);

      double[][][] P = new double[7][n][n];
      P[0] = strassenMultiplyMatrix(A[0][0], S[0], n);
      P[1] = strassenMultiplyMatrix(S[1], B[1][1], n);
      P[2] = strassenMultiplyMatrix(S[2], B[0][0], n);
      P[3] = strassenMultiplyMatrix(A[1][1], S[3], n);
      P[4] = strassenMultiplyMatrix(S[4], S[5], n);
      P[5] = strassenMultiplyMatrix(S[6], S[7], n);
      P[6] = strassenMultiplyMatrix(S[8], S[9], n);

      C[0][0] = addMatrix(minusMatrix(addMatrix(P[4], P[3], n), P[1], n), P[5], n);
      C[0][1] = addMatrix(P[0], P[1], n);
      C[1][0] = addMatrix(P[2], P[3], n);
      C[1][1] = minusMatrix(minusMatrix(addMatrix(P[4], P[0], n), P[2], n), P[6], n);

      n *= 2;

       for(int r = 0; r < n / 2; r++){
        for(int c = 0; c < n / 2; c++){
          C2[r][c] = C[0][0][r][c];
          C2[r][n / 2 + c] = C[0][1][r][c];
          C2[n / 2 + r][c] = C[1][0][r][c];
          C2[n / 2 + r][n / 2 + c] = C[1][1][r][c];
        }//end inner loop
      }//end outter loop
    }//end else     

    return C2;
  }//end method

   //Add two matrices according to matrix addition.
   private double[][] addMatrix(double[][] A, double[][] B, int n){
    double C[][] = new double[n][n];

    for(int r = 0; r < n; r++)
      for(int c = 0; c < n; c++)
        C[r][c] = A[r][c] + B[r][c];

    return C;
  }//end method 

   //Substract two matrices according to matrix addition.
   private double[][] minusMatrix(double[][] A, double[][] B, int n){
    double C[][] = new double[n][n];

    for(int r = 0; r < n; r++)
      for(int c = 0; c < n; c++)
        C[r][c] = A[r][c] - B[r][c];

    return C;
  }//end method

}//end class

希望本文所述对大家学习java程序设计有所帮助。

(0)

相关推荐

  • 详解Java数据结构和算法(有序数组和二分查找)

    一.概述 有序数组中常常用到二分查找,能提高查找的速度.今天,我们用顺序查找和二分查找实现数组的增删改查. 二.有序数组的优缺点 优点:查找速度比无序数组快多了 缺点:插入时要按排序方式把后面的数据进行移动 三.有序数组和无序数组共同优缺点 删除数据时必须把后面的数据向前移动来填补删除项的漏洞 四.代码实现 public class OrderArray { private int nElemes; //记录数组长度 private long[] a; /** * 构造函数里面初始化数组 赋值默

  • java 二维数组矩阵乘法的实现方法

    复制代码 代码如下: public interface IMatrixMultiple {     public int[][] mmltiple(int[][]a ,int [][]b); } ?public class MatrixMultiple implements IMatrixMultiple { @Override    public int[][] mmltiple(int[][] a, int[][] b) {         int [][] result = new int

  • 简单讲解奇偶排序算法及在Java数组中的实现

    奇偶排序是一个比较有个性的排序,基本思路是奇数列排一趟序,偶数列排一趟序,再奇数排,再偶数排,直到全部有序 举例吧, 待排数组 [6 2 4 1 5 9] 第一次比较奇数列,奇数列与它的邻居偶数列比较,如6和2比,4和1比,5和9比 [6 2 4 1 5 9] 交换后变成 [2 6 1 4 5 9] 第二次比较偶数列,即6和1比,5和5比 [2 6 1 4 5 9] 交换后变成 [2 1 6 4 5 9] 第三趟又是奇数列,选择的是2,6,5分别与它们的邻居列比较 [2 1 6 4 5 9] 交

  • java数据结构与算法之双向循环队列的数组实现方法

    本文实例讲述了java数据结构与算法之双向循环队列的数组实现方法.分享给大家供大家参考,具体如下: 需要说明的是此算法我并没有测试过,这里给出的相当于伪代码的算法思想,所以只能用来作为参考! package source; public class Deque { private int maxSize; private int left; private int right; private int nItems; private long[] myDeque; //constructor p

  • java字符串相似度算法

    本文实例讲述了java字符串相似度算法.分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: public class Levenshtein {     private int compare(String str, String target) {         int d[][]; // 矩阵         int n = str.length();         int m = target.length();         int i; // 遍历str的      

  • java实现的n*n矩阵求值及求逆矩阵算法示例

    本文实例讲述了java实现的n*n矩阵求值及求逆矩阵算法.分享给大家供大家参考,具体如下: 先来看看运行结果: java版的写出来了,用的跟c语言相同的算法,然后看看能不能以后加个框做成程序: import java.math.*; import java.util.*; import java.text.*; public class matrix { static int map1[][]=new int [110][110]; static int just[][]=new int [11

  • java 矩阵乘法的mapreduce程序实现

    java 矩阵乘法的mapreduce程序实现 map函数:对于矩阵M中的每个元素m(ij),产生一系列的key-value对<(i,k),(M,j,m(ij))> 其中k=1,2.....知道矩阵N的总列数;对于矩阵N中的每个元素n(jk),产生一系列的key-value对<(i , k) , (N , j ,n(jk)>, 其中i=1,2.......直到i=1,2.......直到矩阵M的总列数. map package com.cb.matrix; import stati

  • Java中打乱一个数组的2种公平算法分享

    公平算法,打乱数组 这是前几天面试的时候遇见的一道题目,看到这个题首先想到了洗牌程序: 方法一:洗牌程序原理 在java.util包中的Collections类中的 shuffle方法,现在手工实现以下代码如下: package test.ms; import java.util.Random; public class Redistribute2 { public static void main(String[] args) { //define the array int[] s = {1

  • Java实现的求逆矩阵算法示例

    本文实例讲述了Java实现的求逆矩阵算法.分享给大家供大家参考,具体如下: package demo; public class MatrixInverse { public static double Det(double [][]Matrix,int N)//计算n阶行列式(N=n-1) { int T0; int T1; int T2; double Num; int Cha; double [][] B; if(N>0) { Cha=0; B=new double[N][N]; Num=

  • Java对数组实现选择排序算法的实例详解

    一. 算法描述     选择排序:比如在一个长度为N的无序数组中,在第一趟遍历N个数据,找出其中最小的数值与第一个元素交换,第二趟遍历剩下的N-1个数据,找出其中最小的数值与第二个元素交换......第N-1趟遍历剩下的2个数据,找出其中最小的数值与第N-1个元素交换,至此选择排序完成. 以下面5个无序的数据为例: 56 12 80 91 20(文中仅细化了第一趟的选择过程) 第1趟:12 56 80 91 20 第2趟:12 20 80 91 56 第3趟:12 20 56 91 80 第4趟

  • 图解程序员必须掌握的Java常用8大排序算法

    这篇文章主要介绍了Java如何实现八个常用的排序算法:插入排序.冒泡排序.选择排序.希尔排序 .快速排序.归并排序.堆排序和LST基数排序,分享给大家一起学习. 分类 1)插入排序(直接插入排序.希尔排序) 2)交换排序(冒泡排序.快速排序) 3)选择排序(直接选择排序.堆排序) 4)归并排序 5)分配排序(基数排序) 所需辅助空间最多:归并排序 所需辅助空间最少:堆排序 平均速度最快:快速排序 不稳定:快速排序,希尔排序,堆排序. 先来看看8种排序之间的关系: 1.直接插入排序 (1)基本思想

随机推荐