package AlgLin;

import java.io.FileNotFoundException;

// La classe Helder étend SysLin
public class Helder extends SysLin {

    // Constructeur de la classe Helder
    public Helder(Matrice matrice, Vecteur secondMembre) throws IrregularSysLinException {
        super(matrice, secondMembre);
    }

    // Méthode pour factoriser la matrice en LDR
    public void factorLDR() {
        int degre = getOrdre();
        Matrice A = getMatriceSystem();

        for (int i = 0; i < degre; i++) {
            for (int j = 0; j < i; j++) {
                // Pour L(ij)
                double sommeL = 0;
                for (int k = 0; k < j; k++) {
                    sommeL += A.getCoef(i, k) * A.getCoef(k, k) * A.getCoef(k, j);
                }
                A.remplacecoef(i, j, (A.getCoef(i, j) - sommeL) / A.getCoef(j, j));
            }

            // Pour D(ii)
            double sommeD = 0;
            for (int k = 0; k < i; k++) {
                sommeD += A.getCoef(i, k) * A.getCoef(k, k) * A.getCoef(k, i);
            }
            A.remplacecoef(i, i, A.getCoef(i, i) - sommeD);

            // Pour R(ij)		
            for (int j = i + 1; j < degre; j++) {
                double sommeR = 0;
                for (int k = 0; k < i; k++) {
                    sommeR += A.getCoef(i, k) * A.getCoef(k, k) * A.getCoef(k, j);
                }
                A.remplacecoef(i, j, (A.getCoef(i, j) - sommeR) / A.getCoef(i, i));
            }
        }
        //System.out.println("A la fin A : \n" + A);
    }
	

    // Méthode pour résoudre le système linéaire
    public Vecteur resolution() throws IrregularSysLinException {
        // Création de matrices et vecteurs temporaires
        Matrice matrice = new Matrice(getOrdre(), getOrdre());
        matrice.recopie(getMatriceSystem()); // on copie la matrice pour eviter de modifier A directement
        factorLDR(); // on transforme A en LDR
        Vecteur x = new Vecteur(getOrdre());
        Vecteur y = new Vecteur(getOrdre());
        Vecteur z = new Vecteur(getOrdre());
        // Création des sous-systèmes L, D, et R
        SysLin L = new SysTriangInfUnite(getMatriceSystem(), getSecondMembre());
        SysLin D = new SysDiagonal(getMatriceSystem(), getSecondMembre());
        SysLin R = new SysTriangSupUnite(getMatriceSystem(), getSecondMembre());

        // on veut resoudre les 3 equations Ly = b, Dz = y, et Rx = z
        try {
            // Résolution du système en trois étapes
            L.setSecondMembre(getSecondMembre());
            y = L.resolution();
            D.setSecondMembre(y);
            z = D.resolution();
            R.setSecondMembre(z);
            x = R.resolution();
        } catch (IrregularSysLinException e) {
            System.out.println("La résolution présente une erreur");
        }
        // Vérification de la norme
        verifierNorme(matrice, getSecondMembre(), x);
        return x;
    }
    
    
	// en supposant que la matrice est deja factorisé en A = LDR
	public Vecteur resolutionPartielle() throws IrregularSysLinException{
		Vecteur x = new Vecteur(getOrdre());
		Vecteur y = new Vecteur(getOrdre());
		Vecteur z = new Vecteur(getOrdre());
		SysLin L = new SysTriangInfUnite(getMatriceSystem(), getSecondMembre());
		SysLin D = new SysDiagonal(getMatriceSystem(), getSecondMembre());
		SysLin R = new SysTriangSupUnite(getMatriceSystem(), getSecondMembre());
		
		try {
			L.setSecondMembre(getSecondMembre());
			y = L.resolution();
			D.setSecondMembre(y); // le résultat y devient le nouveau second membre a ce moment
			z = D.resolution();
			R.setSecondMembre(z);
			x = R.resolution();
		} catch (IrregularSysLinException e) {
			System.out.println("Erreur de résolution");
		}
		return x;
	}

	
	// modifieur du second membre
	public void setSecondMembre(Vecteur newSecondMembre) {
		super.setSecondMembre(newSecondMembre);
	}
	
    // Méthode principale pour tester la classe
    public static void main(String[] args) throws FileNotFoundException {
        // Création de la matrice et du vecteur second membre
        Matrice matrice = new Matrice("matriceTestHelder.txt");
        Vecteur secondMembre = new Vecteur("vecteurTestHelder.txt");
        

        // Affichage de la matrice et du vecteur second membre
        System.out.println("La matrice A : \n" + matrice);
        System.out.println("Le vecteur : \n" + secondMembre);
        System.out.println("Nous supposons résoudre un système Ax = b");
        
        // Copie de la matrice pour éviter les modifications
        Matrice matriceCopie = new Matrice(matrice.nbLigne(), matrice.nbColonne());
        matriceCopie.recopie(matrice);
        
        try {
            // Résolution du système linéaire
            Helder helder = new Helder(matriceCopie, secondMembre);
            Vecteur solution = helder.resolution();
            System.out.println("Solution x de Ax = b : \n" + solution);
        } catch(IrregularSysLinException e) {
            System.out.println(e.getMessage());
        }

        System.out.println("On teste une résolution d’un système A²x = b");
        
        // Copie de la matrice pour éviter les modifications
        Matrice matriceCopie2 = new Matrice(matrice.nbLigne(), matrice.nbColonne());
        matriceCopie2.recopie(matrice);
        
        // Copie du vecteur solution pour résoudre A²x = b
        Matrice matriceCopie3 = new Matrice(matrice.nbLigne(), matrice.nbColonne());
        matriceCopie3.recopie(matrice);
        
        try {
            
            Helder helder = new Helder(matriceCopie2, secondMembre);
            Vecteur solution = helder.resolution();
            Vecteur y = solution;
            Helder helder2 = new Helder(matriceCopie3, y); 
         
            Vecteur solution2 = helder2.resolution();
            System.out.println("Solution de A²x = b : \n" + solution2);
            
            // Vérification de la norme
            helder.verifierNorme(Matrice.produit(matrice, matrice), secondMembre, solution2);
        } catch(IrregularSysLinException e) {
            System.out.println(e.getMessage());
        }
    }
}