Java inverse matrix calculation

后端 未结 11 1168
难免孤独
难免孤独 2020-12-03 07:58

I\'m trying to calculate the inverse matrix in Java.

I\'m following the adjoint method (first calculation of the adjoint matrix, then transpose this matrix and fina

相关标签:
11条回答
  • 2020-12-03 08:34

    I would recommend using Apache Commons Math 2.0 for this. JAMA is a dead project. ACM 2.0 actually took linear algebra from JAMA and developed it further.

    0 讨论(0)
  • 2020-12-03 08:40

    Matrix inversion is computationally very intensive. As duffymo answered LU is a good algorithm, and there are other variants (QR, for instance).

    Unfortunately you can't get rid of the heavy calculations... and maybe the bottelneck is the getSubmatrix method if you are not using an optimized library.

    Also, special matrix structures (band-matricity, symmetry, diagonality, sparsity) have a great impact in performance if considered in the calculations. Your mileage may vary...

    0 讨论(0)
  • 2020-12-03 08:45

    You NEVER want to compute an inverse matrix this way. Ok, computation of the inverse itself is to be avoided, as it is almost always better to use a factorization such as an LU.

    Computation of the determinant using recursive computations is a numerically obscene thing to do. It turns out that a better choice is to use an LU factorization to compute a determinant. But, if you are going to bother to compute LU factors, then why would you possibly want to compute the inverse? You have already done the difficult work by computing the LU factors.

    Once you have LU factors, you can use them to do back and forward substitution.

    As far as a 19x19 matrix being big, it is not even close to what I'd think of as big.

    0 讨论(0)
  • Exponentially? No, I believe matrix inversion is O(N^3).

    I would recommend using LU decomposition to solve a matrix equation. You don't have to solve for the determinant when you use it.

    Better yet, look into a package to help you. JAMA comes to mind.

    12x12 or 19x19 are not large matricies. It's common to solve problems with tens or hundreds of thousands of degrees of freedom.

    Here's a working example of how to use JAMA. You have to have the JAMA JAR in your CLASSPATH when you compile and run:

    package linearalgebra;
    
    import Jama.LUDecomposition;
    import Jama.Matrix;
    
    public class JamaDemo
    {
        public static void main(String[] args)
        {
            double [][] values = {{1, 1, 2}, {2, 4, -3}, {3, 6, -5}};  // each array is a row in the matrix
            double [] rhs = { 9, 1, 0 }; // rhs vector
            double [] answer = { 1, 2, 3 }; // this is the answer that you should get.
    
            Matrix a = new Matrix(values);
            a.print(10, 2);
            LUDecomposition luDecomposition = new LUDecomposition(a);
            luDecomposition.getL().print(10, 2); // lower matrix
            luDecomposition.getU().print(10, 2); // upper matrix
    
            Matrix b = new Matrix(rhs, rhs.length);
            Matrix x = luDecomposition.solve(b); // solve Ax = b for the unknown vector x
            x.print(10, 2); // print the solution
            Matrix residual = a.times(x).minus(b); // calculate the residual error
            double rnorm = residual.normInf(); // get the max error (yes, it's very small)
            System.out.println("residual: " + rnorm);
        }
    }
    

    Here's the same problem solved using Apache Commons Math, per quant_dev's recommendation:

    package linearalgebra;
    
    import org.apache.commons.math.linear.Array2DRowRealMatrix;
    import org.apache.commons.math.linear.ArrayRealVector;
    import org.apache.commons.math.linear.DecompositionSolver;
    import org.apache.commons.math.linear.LUDecompositionImpl;
    import org.apache.commons.math.linear.RealMatrix;
    import org.apache.commons.math.linear.RealVector;
    
    public class LinearAlgebraDemo
    {
        public static void main(String[] args)
        {
            double [][] values = {{1, 1, 2}, {2, 4, -3}, {3, 6, -5}};
            double [] rhs = { 9, 1, 0 };
    
            RealMatrix a = new Array2DRowRealMatrix(values);
            System.out.println("a matrix: " + a);
            DecompositionSolver solver = new LUDecompositionImpl(a).getSolver();
    
            RealVector b = new ArrayRealVector(rhs);
            RealVector x = solver.solve(b);
            System.out.println("solution x: " + x);;
            RealVector residual = a.operate(x).subtract(b);
            double rnorm = residual.getLInfNorm();
            System.out.println("residual: " + rnorm);
        }
    }
    

    Adapt these to your situation.

    0 讨论(0)
  • 2020-12-03 08:52

    Since ACM library has updated over the years, here is the implementation conforming to latest definition for matrix inversion.

    import org.apache.commons.math3.linear.Array2DRowRealMatrix;
    import org.apache.commons.math3.linear.ArrayRealVector;
    import org.apache.commons.math3.linear.DecompositionSolver;
    import org.apache.commons.math3.linear.LUDecomposition;
    import org.apache.commons.math3.linear.RealMatrix;
    import org.apache.commons.math3.linear.RealVector;
    
    public class LinearAlgebraDemo
    {
        public static void main(String[] args)
        {
            double [][] values = {{1, 1, 2}, {2, 4, -3}, {3, 6, -5}};
            double [][] rhs = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
    
            // Solving AB = I for given A
            RealMatrix A = new Array2DRowRealMatrix(values);
            System.out.println("Input A: " + A);
            DecompositionSolver solver = new LUDecomposition(A).getSolver();
    
            RealMatrix I = new Array2DRowRealMatrix(rhs);
            RealMatrix B = solver.solve(I);
            System.out.println("Inverse B: " + B);
        }
    }
    
    0 讨论(0)
  • 2020-12-03 08:53

    Your algorithm to compute a determinant is indeed exponential. The basic problem is that you are computing from the definition, and the straight definition leads to an exponential amount of subdeterminants to compute. You really need to transform the matrix first before computing either its determinant or its inverse. (I thought of explaining about dynamic programming, but this problem cannot be solved by dynamic programming as the number of subproblems is exponential too.)

    LU decomposition, as recommended by others, is a good choice. If you are new to matrix calculation, you might also want to look at Gaussian elimination to compute determinants and inverses, as that might be a bit easier to comprehend at first.

    And one thing to remember in matrix inversion is numerical stability, since you are dealing with floating point numbers. All the good algorithm include permutations of rows and/or columns to choose the suitable pivots, as they are called. At least in Gaussian elimination, you want to, at each step, to permute the columns so that the element largest in absolute value is chosen as the pivot, as this is the stablest choice.

    0 讨论(0)
提交回复
热议问题