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.
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:
change maintenant typeAffichage=4 en typeAffichage=3 et tu verra que les distances ne divergent pas.