domingo, 7 de abril de 2019

Classe em Java para um Sistema Linear


Classe em Java para um Sistema Linear

Exercício

Crie uma classe em Java que recebe em seu construtor uma matriz que represente um sistema linear de $n\leq 4$ incógnitas e implemente pelo menos os seguintes métodos:

matriz: Imprime o sistema em forma de matriz;
resultado: Imprime a solução do sistema;
equacao: Imprime a equação do sistema.

A matriz de entrada possui $n$ linhas e $n+1$ colunas, esta contendo as constantes das equações.

In [1]:
public class SistemaLinear{

    int n;
    double[][] mat;
    double[][] invertida;
    double[][] resultado;
    char []var = {'x', 'y', 'z', 'w'};

    public SistemaLinear(double [][]mat){
    
        this.n = mat.length;
        
        this.mat = new double[n][n+1];
        invertida = new double[n][n];
        
        //Copie a matriz
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n+1; j++)
                this.mat[i][j] = mat[i][j];

        invertida = inverta(mat);
        this.resultado = new double[n][1];
        
        for (int i = 0; i < n; i++) 
            for (int j = 0; j < 1; j++) 
                for (int k = 0; k < n; k++)
                    resultado[i][j] = resultado[i][j] + invertida[i][k] * mat[k][n];
    
    }
    
    public void matriz(){

        for(int i=0; i<n; i++){
            System.out.print("|");
            for(int j=0; j<n; j++)
                System.out.print(" "+mat[i][j]);
            
            System.out.print(" | "+(i==n/2?"x":" ")+" |"+ var[i]+"|");
            System.out.print(" "+(i==n/2?"=":" ")+" |"+ mat[i][n]+"|");
            System.out.println();
        }
    }
    
    public void equacao(){
        
        int i=0;
        System.out.print("("+round(resultado[i][0],5)+")"+var[i]);
        for(i++; i<n; i++)
            System.out.print(" + ("+round(resultado[i][0],5)+")"+var[i]);
        
        System.out.println(" = 0");

    }

    public void inverso(){
        for (int i=0; i<n; ++i){
            for (int j=0; j<n; ++j)
                System.out.print(invertida[i][j]+"  ");
            
            System.out.println();
        }
    }
    
    public void resultado(){
        for(int i=0; i<n; i++)
            System.out.println(var[i]+" = "+round(resultado[i][0],5));
    }
 
 
    public static double[][] inverta(double[][] a_){
    
        int n = a_.length;
        double a[][] = new double[n][n];
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                a[i][j] = a_[i][j];
        
        double x[][] = new double[n][n];
        double b[][] = new double[n][n];
        int index[] = new int[n];
        for (int i=0; i<n; ++i) 
            b[i][i] = 1;
 
        //Transform the matrix into an upper triangle
        gaussian(a, index);
 
        //Update the matrix b[i][j] with the ratios stored
        for (int i=0; i<n-1; ++i)
            for (int j=i+1; j<n; ++j)
                for (int k=0; k<n; ++k)
                    b[index[j]][k] -= a[index[j]][i]*b[index[i]][k];
 
        //Perform backward substitutions
        for(int i=0; i<n; ++i){
        
            x[n-1][i] = b[index[n-1]][i]/a[index[n-1]][n-1];
            for (int j=n-2; j>=0; --j){
            
                x[j][i] = b[index[j]][i];
                for (int k=j+1; k<n; ++k) 
                    x[j][i] -= a[index[j]][k]*x[k][i];
                
                x[j][i] /= a[index[j]][j];
            }
            
        }
        return x;
        
    }
    
    //Method to carry out the partial-pivoting Gaussian
    //elimination.  Here index[] stores pivoting order.
    public static void gaussian(double a[][], int index[]){
    
        int n = index.length;
        double c[] = new double[n];
 
        //Initialize the index
        for (int i=0; i<n; ++i) 
            index[i] = i;
 
        //Find the rescaling factors, one from each row
        for (int i=0; i<n; ++i){
        
            double c1 = 0;
            for (int j=0; j<n; ++j){
            
                double c0 = Math.abs(a[i][j]);
                if (c0 > c1) c1 = c0;
                
            }
            c[i] = c1;
        }
 
        //Search the pivoting element from each column
        int k = 0;
        for (int j=0; j<n-1; ++j){
        
            double pi1 = 0;
            for (int i=j; i<n; ++i){
                double pi0 = Math.abs(a[index[i]][j]);
                pi0 /= c[index[i]];
                if (pi0 > pi1){
                    pi1 = pi0;
                    k = i;
                }
            }
 
            //Interchange rows according to the pivoting order
            int itmp = index[j];
            index[j] = index[k];
            index[k] = itmp;
            for (int i=j+1; i<n; ++i){
            
                double pj = a[index[i]][j]/a[index[j]][j];
 
                //Record pivoting ratios below the diagonal
                a[index[i]][j] = pj;
 
                //Modify other elements accordingly
                for (int l=j+1; l<n; ++l)
                    a[index[i]][l] -= pj*a[index[j]][l];
            }
        }
    }
    
    //Para deixar o resultado para apenas duas casas decimais:
    public static double round(double valor, int casas) {
        if (casas < 0) throw new IllegalArgumentException();

        long fator = (long) Math.pow(10, casas);
        valor *= fator;
        return (double) Math.round(valor) / fator;
    }
    
}

//Utilização
double[][] equacao = {{1, 2, 3, 5}, 
                      {5, 3, 1, 7},
                      {1, 2, 2, 4}};

SistemaLinear eq = new SistemaLinear(equacao);
eq.matriz();
eq.resultado();
eq.equacao();
| 1.0 2.0 3.0 |   |x|   |5.0|
| 5.0 3.0 1.0 | x |y| = |7.0|
| 1.0 2.0 2.0 |   |z|   |4.0|
x = 0.85714
y = 0.57143
z = 1.0
(0.85714)x + (0.57143)y + (1.0)z = 0