Home > Enterprise >  Reduced Row Echelon Implementation in Java
Reduced Row Echelon Implementation in Java

Time:02-04

Via this code:

import java.util.Arrays;

public class RREFS {

    public static void main(String[] args){

        double[][] rref;
        double[][] matrix;
        matrix=new double[][]{
                new double[]{  8.385956100787163E-8,   0.9103664774626016, 0.41380294430118253,                 0.0, 0.0, 0.0  },
                new double[]{ 2.0779736498353668E-8,  0.22558161873553792, -0.4962795612181877,  0.8383433249008051, 0.0, 0.0  },
                new double[]{ 1.0081125874457642E-7, -0.34690893617920376,  0.7631996595942279,  0.5451426139958772, 0.0, 0.0  },
                new double[]{                   0.0,                  0.0,                 0.0,                 0.0, 1.0, 0.0  },
                new double[]{                   0.0,                  0.0,                 0.0,                 0.0, 0.0, 1.0  }
        };
        rref=RREFS.rref(matrix);
        print(rref);

//      this
//      [ 8.385956100787163E-8,   0.9103664774626016, 0.41380294430118253,                 0.0, 0.0, 0.0]
//      [2.0779736498353668E-8,  0.22558161873553792, -0.4962795612181877,  0.8383433249008051, 0.0, 0.0]
//      [1.0081125874457642E-7, -0.34690893617920376,  0.7631996595942279,  0.5451426139958772, 0.0, 0.0]
//      [                  0.0,                  0.0,                 0.0,                 0.0, 1.0, 0.0]
//      [                  0.0,                  0.0,                 0.0,                 0.0, 0.0, 1.0]

//       produces
//       [1.0, 0.0, 0.0,                 0.0, 0.0, 0.0]
//       [0.0, 1.0, 0.0,                 0.0, 0.0, 0.0]
//       [0.0, 0.0, 1.0, -1.3999999999999997, 0.0, 0.0]
//       [0.0, 0.0, 0.0,                 0.0, 1.0, 0.0]
//       [0.0, 0.0, 0.0,                 0.0, 0.0, 1.0]

//       insteada
//       [1.0, 0.0, 0.0,  1.38165312352941182995E7, 0.0, 0.0]
//       [0.0, 1.0, 0.0,        -0.636363636363636, 0.0, 0.0]
//       [0.0, 0.0, 1.0,                      -1.4, 0.0, 0.0]
//       [0.0, 0.0, 0.0,                         0, 1.0, 0.0]
//       [0.0, 0.0, 0.0,                         0, 0.0, 1.0]
​
    }


    /**
     * Puts a matrix into reduced row echelon form
     *
     * @param matrix input matrix
     *
     * @return 2D result matrix
     */
    public static double[][] rref(double[][] matrix){
        int columnIndex = 0;
        int cursor;

        // number of rows and columns in matrix
        int getRowSize = matrix.length;
        int getColumnSize = matrix[0].length;


        loop:
        for(int rowIndex = 0; rowIndex < getRowSize; rowIndex  ){
            if(getColumnSize <= columnIndex){
                break loop;
            }
            cursor = rowIndex;
            while(matrix[cursor][columnIndex] == 0){
                cursor  ;
                if(getRowSize == cursor){
                    cursor = rowIndex;
                    columnIndex  ;
                    if(getColumnSize == columnIndex){
                        break loop;
                    }
                }

            }

            matrix = rowSwap(matrix, cursor, rowIndex);
            if(matrix[rowIndex][columnIndex] != 0){
                matrix = rowScale(matrix, rowIndex, (1/matrix[rowIndex][columnIndex]));
            }

            for(cursor = 0; cursor < getRowSize; cursor  ){
                if(cursor != rowIndex){
                    matrix = rowAddScale(matrix, rowIndex, cursor,((-1) * matrix[cursor][columnIndex]));
                }
            }columnIndex  ;
        }return matrix;
    }

    /**
     * Swap positions of 2 rows
     *
     * @param matrix matrix before row additon
     * @param rowIndex1 int index of row to swap
     * @param rowIndex2 int index of row to swap
     *
     * @return matrix after row swap
     */
    private static double[][] rowSwap(double[][] matrix, int rowIndex1,
                                      int rowIndex2){
        // number of columns in matrix
        int numColumns = matrix[0].length;

        // holds number to be swapped
        double hold;

        for(int k = 0; k < numColumns; k  ){
            hold = matrix[rowIndex2][k];
            matrix[rowIndex2][k] = matrix[rowIndex1][k];
            matrix[rowIndex1][k] = hold;
        }

        return matrix;
    }

    /**
     * Adds 2 rows together row2 = row2   row1
     *
     * @param matrix matrix before row additon
     * @param rowIndex1 int index of row to be added
     * @param rowIndex2 int index or row that row1 is added to
     *
     * @return matrix after row addition
     */
    private static double[][] rowAdd(double[][] matrix, int rowIndex1,
                                     int rowIndex2){
        // number of columns in matrix
        int numColumns = matrix[0].length;

        for(int k = 0; k < numColumns; k  ){
            matrix[rowIndex2][k]  = matrix[rowIndex1][k];
        }

        return matrix;
    }

    /**
     * Multiplies a row by a scalar
     *
     * @param matrix matrix before row additon
     * @param rowIndex int index of row to be scaled
     * @param scalar double to scale row by
     *
     * @return matrix after row scaling
     */
    private static double[][] rowScale(double[][] matrix, int rowIndex,
                                       double scalar){
        // number of columns in matrix
        int numColumns = matrix[0].length;

        for(int k = 0; k < numColumns; k  ){
            matrix[rowIndex][k] *= scalar;
        }

        return matrix;
    }

    /**
     * Adds a row by the scalar of another row
     * row2 = row2   (row1 * scalar)
     * @param matrix matrix before row additon
     * @param rowIndex1 int index of row to be added
     * @param rowIndex2 int index or row that row1 is added to
     * @param scalar double to scale row by
     *
     * @return matrix after row addition
     */
    private static double[][] rowAddScale(double[][] matrix, int rowIndex1,
                                          int rowIndex2, double scalar){
        // number of columns in matrix
        int numColumns = matrix[0].length;

        for(int k = 0; k < numColumns; k  ){
            matrix[rowIndex2][k]  = (matrix[rowIndex1][k] * scalar);
        }

        return matrix;
    }

    public static void print(double[][] matrix) {
        print("",matrix);
    }
    public static void print(String message, double[][] matrix) {
        System.out.println(message);
        for (int i = 0; i < matrix.length; i  ) {
            System.out.println(Arrays.toString(matrix[i]));
        }System.out.println();
    }
}

I am trying to build a custom rref calculator thus I have edie-zhou's implementation asper.

It works with every simple matrix I have tested so far, However the result of

 [ 8.385956100787163E-8,   0.9103664774626016, 0.41380294430118253,                 0.0, 0.0, 0.0]
 [2.0779736498353668E-8,  0.22558161873553792, -0.4962795612181877,  0.8383433249008051, 0.0, 0.0]
 [1.0081125874457642E-7, -0.34690893617920376,  0.7631996595942279,  0.5451426139958772, 0.0, 0.0]
 [                  0.0,                  0.0,                 0.0,                 0.0, 1.0, 0.0]
 [                  0.0,                  0.0,                 0.0,                 0.0, 0.0, 1.0]

is this

[1.0, 0.0, 0.0,                 0.0, 0.0, 0.0]
[0.0, 1.0, 0.0,                 0.0, 0.0, 0.0]
[0.0, 0.0, 1.0, -1.3999999999999997, 0.0, 0.0]
[0.0, 0.0, 0.0,                 0.0, 1.0, 0.0]
[0.0, 0.0, 0.0,                 0.0, 0.0, 1.0]

instead of

[1.0, 0.0, 0.0,  1.38165312352941182995E7, 0.0, 0.0]
[0.0, 1.0, 0.0,        -0.636363636363636, 0.0, 0.0]
[0.0, 0.0, 1.0,                      -1.4, 0.0, 0.0]
[0.0, 0.0, 0.0,                         0, 1.0, 0.0]
[0.0, 0.0, 0.0,                         0, 0.0, 1.0]

according to this online calculator and some others I tested, please what seems to be the problem with the code.

CodePudding user response:

You may actually have a "do not compare floats for equality" problem in there. If I do:

public static boolean isZero(double foo) {
    // demonstration only, replace with less silly implementation
    return Math.abs(foo)<0.0000001;
}

  ...
  while(isZero(matrix[cursor][columnIndex])){
  //instead of
  while(matrix[cursor][columnIndex] == 0){

I get

[1.0, 0.0, 0.0, 1.3816531235294117E7, 0.0, 0.0]
[0.0, 1.0, 0.0, -0.6363636363636362, 0.0, 0.0]
[0.0, 0.0, 1.0, -1.3999999999999997, 0.0, 0.0]
[0.0, 0.0, 0.0, 0.0, 1.0, 0.0]
[0.0, 0.0, 0.0, 0.0, 0.0, 1.0]

which is the result you wanted I believe.

More discussion e.g. in How should I do floating point comparison?

  • Related