Ajouter un commentaire

ltchris

lance ce joli code, et le secret sur la divergence tu comprendra! Pour le point situé juste avant le NaN je calcule les différences entre ce qu'on trouve et ce qu'on aurait du avoir, et tu vois que les erreur sont de plus en plus grande:

class Geotest {
    final int NB_POINTS = 50;
    // type Matrice de départ :  0 = c'est nous qui la créons ;  1 = aléatoire ; 2=on la lit dans un fichier
    final int typeMat = 1;
    /* typeAffichage : 
     *  0 = on affiche toutes les étapes de calcul
     *  1 = on affiche juste résultats
     *  2 = on affiche juste quand y'a du NaN
     *  3 = difference entre somme des distance init et finale
     *  4 = on affiche difference entre matrice position depart et matrice position finale   */
    public int typeAffichage = 4;
    
    int quelLigne=9;
    
    
    
    //  n = nombre de points
    //  m = dimension de l'espace
    private int n = NB_POINTS;
   
    private int m = NB_POINTS - 1;
    
    // Matrice des positions initiales
    public double[][] coordonneesInitiales = new double[n][m];
                                     
    // Matrice des positions reconstruites par l'algorithme
    public double[][] coordonnees = new double[n][m];
   
    // Matrice des distances
    public double[][] distances = new double[n][n];
    
    // vecteur pour controle de division par zero
    // zeroPos[0]=position en i ; zeroPos[1]=position en j ; zeroPos[2] = valeur de coord
    public double[] zeroPos = { -1,-1,-1};
   
    // petite methode pour calculer un carre
    double carre(double x) {
        return x * x;
    }
   
    // Calcul de la distance euclidienne pour la matrice de position
    double dist(double[][] coords, int a, int b) {
        double sum = 0;
        for (int i = 0; i < m; i++) {
            sum = sum + carre(coords[a][i] - coords[b][i]);
        }
        return Math.sqrt(sum);
    }
   
    public void creationMatrice(int type){
    	if(typeAffichage==0) System.out.println("Matrice Initiale");
    	switch(type) {
    	case 0 : 
    		// ON cree nous même la matrice
    			double[][] temp =  
    			{
    			        { 0.0, 0.0, 0.0 } ,
    			        { 2.0, 0.0, 0.0 },
    			        { 7.0, 0.0, 0.0 },
    			        { 0.0, 1.0, 2.0 } 
    			};
    			for(int i=0;i<n;i++){
    				if(typeAffichage==0) System.out.print(i + "=>   ");
    				for(int j=0;j<m;j++){
    					coordonneesInitiales[i][j]= temp[i][j]; 
    					if(typeAffichage==0) System.out.print(coordonneesInitiales[i][j] + " ");
    				}
    				if(typeAffichage==0) System.out.println();
    			}
    			break;
 		
       	case 1 :
       		// On crée une matrice triangulaire aléatoire
       		for (int i = 0; i < n; i++) {
       			if(typeAffichage==0) System.out.print(i + "=>   ");
    			for (int j = 0; j < i; j++) {
    				coordonneesInitiales[i][j] = (Math.random()*0.1);
    				if(typeAffichage==0) System.out.print(coordonneesInitiales[i][j] + " ");
    			}
    			if(typeAffichage==0) System.out.println();
    		}
       		break;
    	}
    }
    
    public void executeTest() {
       
    	creationMatrice(typeMat);
       
        // On calcul les distances euclidiennes entre les points
    	if(typeAffichage==0) System.out.println("Matrice distance");
        for (int i = 0; i < n; i++) {
            //System.out.print(i + "=>   ");
            for (int j = 0; j < m; j++) {
                distances[i][j] = dist(coordonneesInitiales, i, j);
                distances[j][i] = dist(coordonneesInitiales, i, j);
                if(typeAffichage==0) System.out.print(distances[i][j] + " ");
              
            }
            if(typeAffichage==0) System.out.println();
        }
       
        
        if(typeAffichage==0) System.out.println("Matrice Résultat (intermediaire)");
        if(typeAffichage==0) System.out.print("1=>   ");
        // Le premier point a tout ces coordonnées nulles
        // Le deuxième n'a qu'une seule coordonnée nulle
        coordonnees[1][0] = distances[1][0];
        if(typeAffichage==0) System.out.println(coordonneesInitiales[1][0] + " ");
       
        /* On lance notre algorithme pour trouver les coordonnées des points 3 à n */
        double zero = 0;
        for (int WichPoint = 2; WichPoint < n; WichPoint++) {
            int i = WichPoint; // je met i juste pour simplifier le code, et Wichpoint pour comprendre de
            // quoi je parle
            if(typeAffichage==0) System.out.print(i + "=>   ");
            // La norme du vecteur sera sa distance au point 1
            double norme = carre(distances[0][i]);
           
            // On calcul d'abord les n-2 premières coordonnées du point courant
            for (int p = 0; p < i - 1; p++) {
                coordonnees[i][p] = norme - carre(distances[p + 1][i]) + carre(distances[p + 1][0]);
                if(typeAffichage==0) System.out.print("p=" + p + "  norme-d²=" + coordonnees[i][p]);
                double sumCoord = 0;
                for (int k = 0; k <= p - 1; k++) {
                    sumCoord += coordonnees[i][k] * coordonnees[p + 1][k];
                    
                }
                if(typeAffichage==0) System.out.print("  sumCoord=" + sumCoord + " ");
                coordonnees[i][p] = coordonnees[i][p] - 2 * sumCoord;
                coordonnees[i][p] = coordonnees[i][p] / (2 * coordonnees[p + 1][p]);
                // on controle la divergence en soustrayant ou additionnant une erreur qui pourrait apparaitre
                
                if(typeAffichage==0) System.out.print("  x=" + coordonnees[i][p] + " ");
                if(typeAffichage==0) System.out.println();
            }
            if(typeAffichage==0) System.out.println();
            // On calcul enfin la dernière coord du point courant en utilisant les coord calculés à
            // l'instant
            double sumSQR = 0;
            for (int j = 0; j < i - 1; j++) {
                sumSQR += carre(coordonnees[i][j]);
            }
           
            // Le dernier calcul devrait tjs etre vrai car norme > sumSQR (mathematiquement j'entend)
            coordonnees[i][i - 1] = Math.sqrt(norme - sumSQR);
            if(i%2==0) coordonnees[i][i - 1]=coordonnees[i][i - 1]-Math.pow(10,-17);
            else coordonnees[i][i - 1]=coordonnees[i][i - 1]+Math.pow(10,-17);
            // on test si un des résultats s'approche de zero = controle division par zero
            if(Math.abs(coordonnees[i][i-1])<0.0000001){
            	System.out.println(" petit resultat= " + coordonnees[i][i-1]);
            	zeroPos[0]=i;
            	zeroPos[1]=i-1;
            	zeroPos[2]=coordonnees[i][i-1];
            }
            // Or y'a du NaN ???? donc norme < sumSQR et c pas normal !!!
           
            // On test le dernier calcul voir quand apparait ce NaN
            if (Double.isNaN(coordonnees[i][i - 1]) == true && zero == 0) {
                zero++;
                quelLigne=i-1;
                System.out.println("Nan a " + i);
                System.out.println("  Position du zero : i=" + zeroPos[0] + " j=" + zeroPos[1] + " coord="+ zeroPos[2]);
                if(typeAffichage==0) typeAffichage=2; // on chg la valeur pour arreter l'affichage au NaN
            }
        }
        if(typeAffichage==1) System.out.println("Matrice resultat");
        for (int i = 0; i < n; i++) {
        	if(typeAffichage==1) System.out.print(i + "=>   ");
            for (int j = 0; j < i; j++) {
            	if(typeAffichage==1) System.out.print(coordonnees[i][j] + " ");            	
            }
            if(typeAffichage==1) System.out.println();
        }
        
        
        // sommme des distances
        if(typeAffichage==3){
        	for(int i=0;i<quelLigne;i++){
            	double sumInit=0;
            	double sumFinale=0;
            	 System.out.print(i + "=>   ");
            	for(int j=0;j<i;j++){
            		sumInit+=distances[i][j];
            		sumFinale+=dist(coordonnees,i,j);
            	}
            	if(typeAffichage==3) System.out.println(" erreur somme des distances= " + (sumInit-sumFinale));
            }
        }
        
        // difference de coordonnées
        if(typeAffichage==4){
        	for(int j=0;j<quelLigne-1;j++){
        		System.out.print("j="+j+" erreur="+ (coordonneesInitiales[quelLigne-1][j]-coordonnees[quelLigne-1][j]));
        		System.out.println();
        	}
        }
                
    } 
   
    public static void main(String[] args) {
        Geotest test = new Geotest();
        test.executeTest();
    }    
} 

change maintenant typeAffichage=4 en typeAffichage=3 et tu verra que les distances ne divergent pas.

Filtered HTML

Plain text

CAPTCHA
Cette question permet de vérifier que vous n'êtes pas un robot spammeur :-)
 H  H  PPPP   FFFF  X   X  L    
H H P P F X X L
HHHH PPPP FFF X L
H H P F X X L
H H P F X X LLLL