Ajouter un commentaire

fredericmazue

Bon, j'ai regardé un peu et je pense pouvoir aider.
J'ai repris le code de willbback (merci à lui :) )

Je me suis permis de renommer quelques variables pour la clarté. renommer aussi un j en k pour que ça colle mieux à la formule mathématique donnée dans le lien, etc.
Mais c'est du détail. Voici le code toutefois:

package test;

class Geotest {
    final int NB_POINTS = 4;
    //  n = nombre de points
    //  m = dimension de l'espace
    private int n = NB_POINTS;
    
    private int m = NB_POINTS - 1;
    
    public double[][] coordonneesInitiales = new double[n][m];
                                      
    // Matrice des positions initiales
    
    
    // Matrice des positions reconstruites par l'algorithme
    public double[][] coordonnees = new double[n][m];
    
    // Matrice des distances
    public double[][] distances = new double[n][n];
    
    // 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 executeTest() {
        
        // On crée une matrice triangulaire aléatoire
       
        System.out.println("Matrice Initiale");
        for (int i = 0; i < n; i++) {
            System.out.print(i + "=>   ");
            for (int j = 0; j < i; j++) {
                coordonneesInitiales[i][j] = (int)(Math.random() * 10);
                System.out.print(coordonneesInitiales[i][j] + " ");
            }
            System.out.println();
        }
         
        
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<m; j++)
              System.out.print(coordonneesInitiales[i][j] + " ");
            System.out.println();
        }
        
        
        // On calcul les distances euclidiennes entre les points
        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);
                System.out.print(distances[i][j] + " ");
            }
            System.out.println();
        }
        
        System.out.println("Matrice Résultat (intermediaire)");
        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];
        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
            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]);
                
                double sumCoord = 0;
                for (int k = 0; k <= p - 1; k++) {
                    sumCoord += coordonnees[i][k] * coordonnees[p + 1][k];
                }
                coordonnees[i][p] = coordonnees[i][p] - 2 * sumCoord;
                coordonnees[i][p] = coordonnees[i][p] / (2 * coordonnees[p + 1][p]);
                System.out.print(coordonnees[i][p] + " ");
            }
            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] = (float)Math.sqrt(norme - sumSQR);
            // 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++;
                System.out.println("Nan a " + i);
            }
        }
        System.out.println("Matrice resultat");
        for (int i = 0; i < n; i++) {
            System.out.print(i + "=>   ");
            for (int j = 0; j < i; j++) {
                System.out.print(coordonnees[i][j] + " ");
            }
            System.out.println();
        }
        
    }
    
    public static void main(String[] args) {
        Geotest test = new Geotest();
        test.executeTest();
    }
}

J'ai encore limité les essais à N = 4, ce qui est largement suffisant pour y voir clair.

Voir un premier résultat

0=>   
1=>   1.0 
2=>   9.0 4.0 
3=>   5.0 5.0 2.0 
0.0 0.0 0.0 
1.0 0.0 0.0 
9.0 4.0 0.0 
5.0 5.0 2.0 
Matrice distance
0=>   0.0 1.0 9.848857801796104 
1=>   1.0 0.0 8.94427190999916 
2=>   9.848857801796104 8.94427190999916 0.0 
3=>   7.3484692283495345 6.708203932499369 4.58257569495584 
Matrice Résultat (intermediaire)
1=>   1.0 
2=>   8.999999999999986 
3=>   4.9999999999999964 5.000000000000025 
Matrice resultat
0=>   
1=>   1.0 
2=>   8.999999999999986 4.0 
3=>   4.9999999999999964 5.000000000000025 2.0 

Ici tout marche bien, ou du moins tout semble.

Voici un second résultat:

Matrice Initiale
0=>   
1=>   7.0 
2=>   1.0 0.0 
3=>   7.0 6.0 5.0 
0.0 0.0 0.0 
7.0 0.0 0.0 
1.0 0.0 0.0 
7.0 6.0 5.0 
Matrice distance
0=>   0.0 7.0 1.0 
1=>   7.0 0.0 6.0 
2=>   1.0 6.0 0.0 
3=>   10.488088481701515 7.810249675906654 9.848857801796104 
Matrice Résultat (intermediaire)
1=>   7.0 
2=>   1.0 
3=>   7.0 Infinity 
Nan a 3
Matrice resultat
0=>   
1=>   7.0 
2=>   1.0 0.0 
3=>   7.0 Infinity NaN 
 

Là c'est beaucoup plus amusant .... et instructif. :twisted:

Il y a du Nan d'accord, mais surtout de l'Infinity. Et on comprends tout de suite.
Quand on a des coordonnées (autres que la première) nulles, cela provoque une division par zéro ici

coordonnees[i][p] = coordonnees[i][p] / (2 * coordonnees[p + 1][p]);

Quand coordonnées [p+1][p] vaut zéro :twisted:
Le Nan n'est qu'un corollaire de ça

Voci un code tout cuit avec cet exemple pour le vérifier

package test;

class Geotest {
    final int NB_POINTS = 4;
    //  n = nombre de points
    //  m = dimension de l'espace
    private int n = NB_POINTS;
    
    private int m = NB_POINTS - 1;
    
    //public double[][] coordonneesInitiales = new double[n][m];
                                      
    // Matrice des positions initiales
    
    public double[][] coordonneesInitiales = 
                                      
    { 
        { 0.0, 0.0, 0.0 } ,
        { 7.0, 0.0, 0.0 },
        { 1.0, 0.0, 0.0 },
        { 7.0, 6.0, 5.0 }
    };
    
    
    // Matrice des positions reconstruites par l'algorithme
    public double[][] coordonnees = new double[n][m];
    
    // Matrice des distances
    public double[][] distances = new double[n][n];
    
    // 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 executeTest() {
        
        // On crée une matrice triangulaire aléatoire
        /*
        System.out.println("Matrice Initiale");
        for (int i = 0; i < n; i++) {
            System.out.print(i + "=>   ");
            for (int j = 0; j < i; j++) {
                coordonneesInitiales[i][j] = (int)(Math.random() * 10);
                System.out.print(coordonneesInitiales[i][j] + " ");
            }
            System.out.println();
        }
         */
        
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<m; j++)
              System.out.print(coordonneesInitiales[i][j] + " ");
            System.out.println();
        }
        
        
        // On calcul les distances euclidiennes entre les points
        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);
                System.out.print(distances[i][j] + " ");
            }
            System.out.println();
        }
        
        System.out.println("Matrice Résultat (intermediaire)");
        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];
        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
            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]);
                
                double sumCoord = 0;
                for (int k = 0; k <= p - 1; k++) {
                    sumCoord += coordonnees[i][k] * coordonnees[p + 1][k];
                }
                coordonnees[i][p] = coordonnees[i][p] - 2 * sumCoord;
                coordonnees[i][p] = coordonnees[i][p] / (2 * coordonnees[p + 1][p]);
                System.out.print(coordonnees[i][p] + " ");
            }
            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] = (float)Math.sqrt(norme - sumSQR);
            // 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++;
                System.out.println("Nan a " + i);
            }
        }
        System.out.println("Matrice resultat");
        for (int i = 0; i < n; i++) {
            System.out.print(i + "=>   ");
            for (int j = 0; j < i; j++) {
                System.out.print(coordonnees[i][j] + " ");
            }
            System.out.println();
        }
        
    }
    
    public static void main(String[] args) {
        Geotest test = new Geotest();
        test.executeTest();
    }
}

Division par zéro....

arf ces scientifiques :twisted:

Désolé je n'ai pas pu me retenir. :oops:
Mais au delà de la taquinerie, j'espère très sincèrement que ça t'aidera :)

Au fait pour le million d'Euro, où dois je facturer ? :D

Filtered HTML

Plain text

CAPTCHA
Cette question permet de vérifier que vous n'êtes pas un robot spammeur :-)
 Y   Y  X   X  V     V  W     W   AA  
Y Y X X V V W W A A
Y X V V W W W AAAA
Y X X V V W W W A A
Y X X V W W A A