Java: cree un duplicado de una matriz sin convertirlo en una referencia

He escrito una serie de operaciones matriciales en las que tomo una matriz flotante bidimensional, la trato como una matriz y realizo operaciones matriciales en ella para adquirir una inversa. Mi problema ha sido que, aunque la matriz que estoy usando con los métodos de la clase no es parte de la clase, cada vez que ejecuto el método con la matriz como parámetro, la matriz en sí también se modifica.

Primero describiré cómo obtuve el inverso de mi matriz y luego mostraré la salida.

Los pasos para tomar el inverso de una matriz son los siguientes:

  1. Obtenga la matriz de cofactor (es decir, cree una matriz de matrices menores de la matriz original y luego niegue cualquier otra entrada. Si C = Matriz de cofactores, M = Matriz de menores, i es la fila actual, y j es la columna actual, entonces C [i] [j] = M [i] [j] * (-1) ^ (i + j)
  2. Convierta la matriz de cofactor en la matriz adjunta (también conocida como adjunta) transponiendo (reemplazando fila, entrada de columna por su columna análoga, entrada de fila y viceversa) la matriz de cofactor. Si C = Matriz de cofactores, A = Matriz adyuvante, i es la fila actual y j es la columna actual, entonces A [i] [j] = C [j] [i]
  3. Finalmente, tome uno de los determinantes de la matriz original y multiplique la matriz adjunta por ese valor. Si I = Matriz inversa, A = Matriz adyuvante y D = Determinante, entonces I = (1 / D) * A
  4. Para probar si realmente ha adquirido la matriz inversa de una matriz, se puede multiplicar la matriz original por su inversa para obtener la matriz de identidad. Si I = Inversa, O = Matriz original e id = Matriz de identidad, entonces O * I = id

Ahora presentaré el código donde implemento estas operaciones. En aras de la concisión, no describiré cómo obtener la Matriz de Menores o el Determinante, pero el problema que he estado encontrando se hará evidente de todos modos.

public class MatrixOperations {
    //Note: this method works fine. There are no problems.
    public float determinant(float [][] a)
    {
        float [][] temp_mat;
        float res = 0;
        //assuming a square matrix
        /*If it's a 2X2, then use the formula for a determinant of
        2X2 matrices.*/
        if(a.length == 2)
        {
            return a[0][0]*a[1][1]-a[0][1]*a[1][0];
        }
        /*Otherwise do the determinant formula recursively until your
        determinant is made up of 2X2 matrix determinants and scalar products*/
        else
        {
            temp_mat = new float[a.length-1][a.length-1];
            int placej = 0;
            int placei = 0;
            for(int k = 0; k<a.length;k++)
            {
                for(int j = 0; j<a.length; j++)
                {
                    for(int i = 1; i < a.length; i++)
                    {
                        placei = i-1;

                        if(j != k)
                        {
                            if(j < k)
                            {
                                temp_mat[placei][j] = a[i][j];
                            }
                            else if(j > k)
                            {
                                if (i == 1){
                                    placej = j-1;
                                }
                                temp_mat[placei][placej] = a[i][j];
                            }
                        }
                    }
                }

                res+=a[0][k]*determinant(temp_mat)*(int)Math.pow(-1, k);
            }
            return res;
        }
    }
    //Note: this method also works fine
    //Scalar product method
    public float[][] mul(float[][] m, float r)
    {
        float[][] res = new float[m.length][m.length];

        for(int i = 0; i < m.length; i++)
        {
            for(int j = 0; j < m.length; j++)
            {
                res[i][j]= m[i][j]*r;
            }
        }

        return res;

    }
    //Note: This method also works fine
    public float[][] mul(float[][] m,float[][] n)
    {
        float[][] res = new float[m.length][m.length];

        for(int i = 0; i < m.length; i++)
        {
            for(int j = 0; j < m.length; j++)
            {
                for(int k = 0; k < m.length; k++)
                {
                    res[i][j] += m[i][k]*m[k][i];
                }
            }
        }

        return res;

    }
    //The method for creating a matrix of minors
    //Here I start having problems
    public float[][] minor(float [][] m)
    {
        float [][] minor_mat = new float [m.length][m.length];
        //If the matrix is greater than a 2X2, use this to generate a matrix of minors
        if(m.length > 2)
        {
            float [][] current_minor = new float [m.length-1][m.length-1];
            int placei = 0;
            int placej = 0;
            for(int i = 0; i < m.length; i++)
            {
                for(int j = 0; j < m.length; j++)
                {
                    for(int k = 0; k < m.length; k++)
                    {
                        for(int l = 0; l < m.length; l++)
                        {
                            if(i != k && j != l)
                            {
                                if(k<i)
                                    placei = k;
                                else if(k>i)
                                    placei = k-1;
                                if(l<j)
                                    placej = l;
                                else if(l>j)
                                    placej = l-1;

                                current_minor[placei][placej] = m[k][l];
                            }
                        }
                    }
                    minor_mat[i][j] = this.determinant(current_minor);
                }
            }
        }
        //otherwise use the definition for 2X2 matrix of minors
        else
        {
            //even though minor_mat is using m.clone() rather than m, when I return the result, m has still been modified for some reason.
            minor_mat = m.clone()
            float temp;
            temp = minor_mat[0][0];
            minor_mat[0][0] = minor_mat[1][1];
            minor_mat[1][1] = temp;
            temp = minor_mat[0][1];
            minor_mat[0][1] = minor_mat[1][0];
            minor_mat[1][0] = temp;
        }
        return minor_mat;
    }
    //the same problem occurs here as it did in the minor method
    //m appears to get modified even though I only use m.clone()
    public float[][] cofactor(float [][] m)
    {
        float[][] res = m.clone();
        res = this.minor(res)
        for(int i = 0; i < m.length; i++)
        {
            for(int j = 0; j < m.length; j++)
            {
                res[i][j] = res[i][j]*(int)Math.pow(-1, i + j);
            }
        }
        return res;
    }

    //The following transpose, adjugate, and inverse methods have the same problem        

    public float[][] transpose(float[][] m)
    {
        float[][] res = new float[m.length][m.length];
        float temp = 0;
        for(int i = 0; i < m.length; i++)
        {
            for(int j = 0; j < m.length; j++)
            {
                temp = m[i][j];
                res[i][j] = m[j][i];
                res[j][i] = temp;       
            }
        }
        return res;
    }
    public float[][] adjugate(float[][] m)
    {
        float[][] res = this.transpose(this.cofactor(m));
        return res;
    }
    public float[][] inverse(float[][] m)
    {
        float[][] res = this.mul(this.adjugate(m), (1/this.determinant(m)));
        return res;
    }
    //print out the matrix in square form
    public void matrixprint(float [][] m)
    {
        for(int i = 0; i < m.length; i++)
        {
            System.out.println("");
            for(int j = 0; j < m[i].length; j++){
                System.out.print(m[i][j] + " ");
            }
        }
        System.out.println("\n");
    }
}

Ahora la clase principal y el método principal que crea una instancia de la clase MatrixOperations y usa sus métodos en una matriz 2X2.

public class Main {

    public static void main(String[] args) {
        MatrixOperations mo = new MatrixOperations();

        //Create a 2X2 matrix called "matrix" and set its elements
        //Then perform each step on "matrix" and finally test if you have acquired the correct inverse

        float [][] matrix = new float[2][2];
        matrix[0][0] = 2;
        matrix [0][1] = 5;
        matrix [1][0] = 4;
        matrix [1][1] = 3;

        System.out.println("Matrix = ");
        mo.matrixprint(matrix);
        System.out.println("Minor = ");
        mo.matrixprint(mo.minor(matrix));
        System.out.println("Matrix = ");
        mo.matrixprint(matrix);
        System.out.println("Cofactor = ");
        mo.matrixprint(mo.cofactor(matrix));
        System.out.println("Matrix = ");
        mo.matrixprint(matrix);
        System.out.println("Adjugate = ");
        mo.matrixprint(mo.adjugate(matrix));
        System.out.println("Matrix = ");
        mo.matrixprint(matrix);
        System.out.println("Determinant = ");
        System.out.println(mo.determinant(matrix));
        System.out.println("Matrix = ");
        mo.matrixprint(matrix);
        System.out.println("Inverse = ");
        mo.matrixprint(mo.inverse(matrix));
        System.out.println("Matrix = ");
        mo.matrixprint(matrix);
        System.out.println("Identity = ");
        mo.matrixprint(mo.mul(mo.inverse(matrix), matrix));

    }

}

Ahora verá que cuando muestro el resultado, cada vez que uso un método en "matriz" y reimprimo "matriz", la "matriz" en sí misma se ha modificado, aunque mis métodos solo usan una copia de "matriz" y no " matriz "en sí misma.

Salida:

Matrix = 

2.0 5.0 
4.0 3.0 

Minor = 

3.0 4.0 
5.0 2.0 

Matrix = 

3.0 4.0 
5.0 2.0 

Cofactor = 

3.0 -4.0 
-5.0 2.0 

Matrix = 

3.0 -4.0 
-5.0 2.0 

Adjugate = 

3.0 5.0 
4.0 2.0 

Matrix = 

3.0 4.0 
5.0 2.0 

Determinant = 
-14.0
Matrix = 

3.0 4.0 
5.0 2.0 

Inverse = 

-0.21428573 0.35714287 
0.2857143 -0.14285715 

Matrix = 

3.0 -4.0 
-5.0 2.0 

Identity = 

0.1479592 0.1479592 
0.12244898 0.12244898

Cualquier ayuda / explicación de por qué sucede esto sería apreciada.

Respuesta 1

Esta línea hace un clon superficial;

float[][] res = m.clone();

Esto copia la resmatriz de referencias a las matrices. pero ninguno de los arreglos resapunta a. Lo más probable es que lo que querías es

float[][] res = new float[m.length][];
for (int i = 0; i < m.length; i++)
    res[i] = m[i].clone();
Respuesta: 2

Es porque estás pasando referencias de matrixobjetos en los métodos de MatrixOperationsclase. No es una copia del matrixobjeto.

De Java doc :

Los parámetros de tipo de datos de referencia, como los objetos, también se pasan a los métodos por valor. Esto significa que cuando el método regresa, la referencia pasada aún hace referencia al mismo objeto que antes.

Respuesta: 3

Estoy trabajando en un problema en el que estoy un poco confundido. La pregunta dice: imagina que eres un general de la Fuerza Aérea Británica durante la Segunda Guerra Mundial. Te quedan 100 aviones para defender el Reino Unido. Con cada ...

Estoy implementando el algoritmo de búsqueda A * de este pseudo en el artículo de Wikipedia: función A * (inicio, objetivo) conjunto cerrado: = el conjunto vacío // El conjunto de nodos ya evaluados. OpenSet: = ...

Intentando crear 1 interfaz y 2 clases concretas dentro de una clase padre. Esto calificará las clases adjuntas para ser clases internas. clase pública Test2 {interfaz A {público ...

Estoy teniendo el siguiente problema. He implementado un procesamiento de canalización y, a veces, tengo que liberar recursos como, por ejemplo, Archivos. Al mismo tiempo, mi tubería es asíncrona, así que ...