Umb3rus
Umb3rus

Reputation: 7

Issues with calculating the determinant of a matrix (in Java). It is alwys 0

I want to calculoate the determinant of a given NxN Matrix using the Laplace-Method. I already tried differnt approaches which always return a 0.

The class I used:

package Matrix;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.Scanner;
public class Matrix
{
    double[][] array;

    public static void init(Matrix a,int row , int column)
    {
        a.array = new double [row] [column];
        for (int i = 0; i < row; i++)
        {
            for(int k = 0; k < column; k++)
            {
                a.array[i][k] = 0;
            }
        }
    }

    public static int getNRows(Matrix a)
    {
        return a.array.length;
    }

    public static int getNColumns(Matrix a)
    {
        return a.array[0].length;
    }

    public static void print(Matrix a)
    {
        for(int i = 0; i < getNRows(a);i++ )
        {
            for (int k = 0; k < getNColumns(a); k++)
            {
                System.out.print(a.array[i][k] + "\t");
            }
            System.out.println();
        }
    }
    public static double det(Matrix a)
    {
        double det = 0;
        det = a.array[0][0] * a.array[1][1] * a.array[2][2] + a.array[1][0] * a.array[2][1] * a.array[0][2] + a.array[2][0] * a.array[0][1] * a.array[1][2] - a.array[2][0] * a.array[1][1] * a.array[0][2] - a.array[1][0] * a.array[0][1] * a.array[2][2] - a.array[0][0] * a.array[2][1] * a.array[1][2];
        return det;
    public static Matrix transpose(Matrix a)
    {
        Matrix transposed = new Matrix();
        Matrix.init(transposed, getNRows(a), getNColumns(a));
        for(int i = 0; i < getNRows(a); i++)
        {
            for(int j = 0; j < getNColumns(a); j++)
            {
                transposed.array[j][i] = a.array[i][j];
            }
        }
        return transposed;
    }
    public static Matrix subMatrix(Matrix a, int exclRow, int exclCol)
    {
        Matrix subMatrix = new Matrix();
        Matrix.init(subMatrix, getNRows(a) - 1, getNColumns(a) - 1);
        for(int i = 0; i < getNRows(a) - 1; i++)
        {
            for(int j = 0; j < getNColumns(a) - 1; j++)
            {
                if(i != exclRow && j != exclCol)
                {
                    subMatrix.array[i][j] = a.array[i][j];
                }
            }
        }
        return subMatrix;
    }

    public static Matrix loadMatrix(String filename) throws Exception
    {
        Scanner sc = new Scanner(new BufferedReader(new FileReader(filename)));
        Matrix result = new Matrix();
        int row = 0;
        int col = 0;

        String[] line = sc.nextLine().trim().split("\t");
        row = Integer.parseInt(line[0]);
        col = Integer.parseInt(line[1]);
        init(result, row, col);

        int currentRow = 0;
        while(sc.hasNextLine())
        {
            String[] line2 =sc.nextLine().trim().split("\t");
            for(int i = 0; i < col; i++)
            {
                result.array[currentRow][i] = Double.parseDouble(line2[i]);
            }
            currentRow++;
        }
        return result;
    }

    /*public static double detN(Matrix a)
    {
        int colOfA = getNColumns(a);
        int rowOfA = getNRows(a);
        double value = 1;
        if(colOfA != rowOfA)
        {
            return 0;
        }
        if(colOfA == 1 && rowOfA == 1)
        {
            return a.array[0][0];
        }
        else
        {
            
            for(int row = 0; row < rowOfA; row++)
            {
                value += Math.pow(-1, row) * a.array[row][0] * detN(subMatrix(a, row, 0));
            }
        }
        return value;
    }*/

    public static double detN(Matrix a)
    {
        int colOfA = getNColumns(a);
        int rowOfA = getNRows(a);
        if(colOfA != rowOfA)
        {
            return 0;
        }
        if(rowOfA <= 3)
        {
            return det(a);
        }
        double value = 0;
        for(int row = 0; row < rowOfA; row++)
        {
            if(row % 2 == 0)
            {
                value += a.array[row][0] * detN(subMatrix(a, row, 0));
            }
            else
            {
                value -= a.array[row][0] * detN(subMatrix(a, row, 0));
            }
        }
        return value;
    }
    public static Matrix adjointN(Matrix a)
    {
        int rowOfA = getNRows(a);
        int colOfA = getNColumns(a);

        Matrix ret = new Matrix();
        Matrix.init(ret, rowOfA, colOfA);
        for(int row = 0; row < rowOfA; row++)
        {
            for(int col = 0; col < colOfA; col++)
            {
                ret.array[row][col] = detN(subMatrix(a, row, col));
            }
            ret = transpose(ret);
            return ret;
        }
        return ret;
    }
    public static Matrix inverseN(Matrix a)
    {
        Matrix inverse = new Matrix();
        Matrix.init(inverse, getNRows(a), getNColumns(a));
        double pre = 1/detN(a);
        inverse = adjointN(a);
        for(int i = 0; i < getNRows(a); i++)
        {
            for(int j = 0; j < getNColumns(a); j++)
            {
               inverse.array[j][i] = inverse.array[i][j] * pre;
            }
        }
        return inverse;
    }

}

I have two versions for detN, which both yield the same result.

This isn't the entire class, because there are some functions that don't belong to this particular question

Upvotes: 0

Views: 280

Answers (2)

user15200595
user15200595

Reputation: 21

Here is an approach you could consider(the code is not fully debugged so take with a grain of salt). Finding the determinant is a recursive concept since you are always finding the determinant of a smaller matrix to get the final answer.

//Recursive base function

public static double det(int[][] matrix) {

    if(matrix.length == 2)
        return ((matrix[0][0] * matrix[1][1]) - (matrix[0][1] * matrix[1][0]));

    double determinant = 0;
    int mlength = matrix.length - 1;
    int[][] newM = new int[mlength][mlength];

    for(int i = 0; i < mlength + 1; i++) {
        newM = newMatrix(matrix, i);
        determinant = determinant + (Math.pow(-1, i) * matrix[0][i]) * det(newM);
    }

    return determinant;
}

//Format smaller matrix to use in further iteration of above det(int[][]) function

public static int[][] newMatrix(int[][] m, int column) {

    int length = m.length - 1;

    int[][] newMat = new int[length][length];

    for(int i = 1; i < m.length; i++) {
        for(int j = 0; j < column; j++)
            newMat[i - 1][j] = m[i][j];
        for(int k = column + 1; k < m.length; k++)
            newMat[i - 1][k - 1] = m[i][k];
    }

    return newMat;
}

You can adapt to however your Matrix class works.

Upvotes: 1

user14971157
user14971157

Reputation:

subMatrix is not really excluding the given row and column - it is just making them zero (not copying) and removing the last row and column...

Printing the matrix will help debug that.


one way: use additional indices for the destination matrix (the sub matrix). Only increment this if a value is really copied. Example:
sub.array[k++][l++] = a.array[i][j] inside the if
loop over original matrix


Alternative: if one index is greater than or equal to the index that must be skipped, add 1 to the reading index:

var k = (i>=exclRow) ? i+1 : i;
var l = (j>=exclCol) ? j+1 : j;
sub.array[i][j = a.array[k][l];

code not intended to be complete, just ideas how to solve the problem

Upvotes: 0

Related Questions