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
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:
J'ai encore limité les essais à N = 4, ce qui est largement suffisant pour y voir clair.
Voir un premier résultat
Ici tout marche bien, ou du moins tout semble.
Voici un second résultat:
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
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