用Java计算矩阵的空空间基础

时间:2018-05-20 12:25:14

标签: java matrix

我正在尝试用Java获取Matrix 3x3的null空间(内核)。我尝试过使用Efficient Java Matrix Library(实际上并不需要那个,它只是一个例子。我已经尝试过像apache一样的其他人并获得相同的结果)。

这是我的代码:

public static void main(String[] args) {
    double[][] data = new double[][] {
        {1,2,3},
        {1,2,3},
        {1,2,3}
    };
    SimpleMatrix m = new SimpleMatrix(data);
    SimpleSVD svd = m.svd();
    SimpleMatrix nullSpace = svd.nullSpace();
    nullSpace.print();
}

问题是我得到了Orthonormal并且我想要它的基础

 0,964  0,000 
-0,148 -0,832 
-0,222  0,555 

这里使用Matlab获得的基础:null(M,'r')

-2    -3
 1     0
 0     1

1 个答案:

答案 0 :(得分:0)

所以我自己找到了答案。我注意到MATLAB脚本可以编辑并打开我想要的脚本,然后用Java实现相同的脚本。我会将它发布到可能需要它的每个节点,但请注意这个脚本是原始.m之一的不太好的副本。

我之前使用Apache Matrix Library,另外还有两件事。

  1. 我使用this class that I found navigating into apache test files
  2. 我使用它this function that a guy made in another java question(只是rref函数,但对它进行了一些更改,所以我将在此添加它以及我的内核函数)
  3. 现在代码(我将其大部分放在MatrixFunctions.java中以便主要节省空间):

    <强> MatrixFunctions.java

    //...Some other stuff
        public static double[][] rref(double[][] matrix, List<Integer> pivot) {
            double[][] rref = new double[matrix.length][];
            for (int i = 0; i < matrix.length; i++)
                rref[i] = Arrays.copyOf(matrix[i], matrix[i].length);
    
            int r = 0;
            for (int c = 0; c < rref[0].length && r < rref.length; c++) {
                int j = r;
                for (int i = r + 1; i < rref.length; i++)
                    if (Math.abs(rref[i][c]) > Math.abs(rref[j][c]))
                        j = i;
                if (Math.abs(rref[j][c]) < 0.00001)
                    continue;
    
                //Remember where we pivoted
                pivot.add(j);
    
                double[] temp = rref[j];
                rref[j] = rref[r];
                rref[r] = temp;
    
                double s = 1.0 / rref[r][c];
                for (j = 0; j < rref[0].length; j++)
                    rref[r][j] *= s;
                for (int i = 0; i < rref.length; i++) {
                    if (i != r) {
                        double t = rref[i][c];
                        for (j = 0; j < rref[0].length; j++)
                            rref[i][j] -= t * rref[r][j];
                    }
                }
                r++;
            }
    
            return rref;
        }
    
        public static RealMatrix kernel(RealMatrix A) {
            int m = A.getRowDimension(), n = A.getColumnDimension();
            List<Integer> pivot = new ArrayList<>();
            RealMatrix R = MatrixUtils.createRealMatrix(MatrixFunctions.rref(A.getData(), pivot));
            int r = pivot.size();
            HashMap<Integer, Integer> nopiv = new HashMap<>();
            for (int i = 0; i < n; i++) {
                nopiv.put(i, i+1);
            }
            for (Integer e : pivot) {
                if (nopiv.containsValue(e+1))
                    nopiv.remove(e, e+1);
            }
            //Remove ones contained inside pivot from nopiv
            for (int j = 0; j < r; j++) {
                int index = pivot.get(j);
                if (nopiv.containsValue(index))
                    nopiv.remove(index);
            }
    
            double[][] Z = new double[n][n-r];    
    
            //Add 1(s) in the main diagonal
            if (n > r) {
                double[][] eye = new double[n-r][n-r];
                for (int i = 0; i < eye.length; i++) {
                    for (int j = 0; j < eye[i].length; j++) {
                        if (j==i)
                            eye[i][j] = 1;
                        else
                            eye[i][j] = 0;
                    }
                }
                //Add eye in Z
                Integer[] loc = nopiv.values().toArray(new Integer[nopiv.size()]);
                for (int i = 0; i < loc.length; i++) {
                    int index = loc[i];
                    for (int j = 0; j < Z[0].length; j++) {
                        Z[index-1][j] = eye[i][j];
                    }
                }
    
                if (r > 0) {
                    for (int i = 0; i < r; i++) {
                        int indexi = pivot.get(i);
                        for (int j = 0; j < loc.length; j++) {
                            int indexd = loc[j]-1;
                            Z[indexi][j] = -R.getEntry(i, indexd);
                        }
                    }
                }
            }
    
            return MatrixUtils.createRealMatrix(Z);
        }
    //...NnanananananaBATMAN!!
    

    最后一个主要测试它:

        public static void main(String[] args) {
            double[][] matrix = new double[][] {
                {1,2,3},
                {1,2,3},
                {1,2,3}
            };
            //Calculate
            RealMatrix A = MatrixFunctions.kernel(MatrixUtils.createRealMatrix(matrix));
            System.out.println(A); // displays C formatted appropriately
        }
    

    输出:

    Array2DRowRealMatrix{
     {-2.0,-3.0},
     {1.0,0.0},
     {0.0,1.0}
    }
    

    哪个适合我需要的......

    我用更多的元素测试了这个函数,以确保它工作得很好。但我不能确保它一直都能正常工作,当然它不是最有效的方法。

相关问题