NaN erreur : Probleme à 1 million d'euros ... ou presque

ltchris
NaN erreur : Probleme à 1 million d'euros ... ou presque

Bonjour,

Voila je suis physicien, ca fait 4 mois que je me suis mis au Java(car ca fait partie d'un logiciel plus gros deja en java), pour faire un programme pour traiter des données en Génétique.

En résumé, mon programme prend une matrice de distance de n points entre eux (n*n) et grace à celle-ci il place ces n points dans n-1 dimensions.
Mathématiquement la méthode de reconstruction marche y'a pas de problème. Mais qd je met ça dans l'ordi ben ca plante, j'ai une erreur NaN.

J'ai fait un algo de test (ci-dessous), ou je tire alétoirement une matrice (n points dans m dimensions), je calcule les distances entre les points, et je lance mon algo pour retrouver une nouvelle matrice position.
Et j'ai presque à chaque fois (ca depend de la grandeur de n) un NaN. Le NaN est du au calcul de racine carrée d'un nombre négatif. Le probleme c'est que je ne devrais jamais avoir de nombre négatif dans cette racine ! (si on regarde le cote mathématique)

Y'a un truc bizarre qui se passe, peut etre est-ce du a des erreur de calcul typique de java, un truc que je sais pas car je debute. Ca fait un mois que je suis dessus, et ca m'enerve car l'algo en lui meme est simple, mais ça donne cette %è3$** d'erreur !!!
En un mot : Heeelllppppppp ..... :(

class geotest
{
	//  n = nombre de points
	//  m = dimension de l'espace
	static int n =100;
	static int m = n -1;
	
	// Matrice des positions initiales
	public static double[][] positionInit = new double[n][m];
	// Matrice des positions reconstruites par l'algorithme
	public static double[][] position = new double[n][m];
	// Matrice des distances
	public static double[][] distance = new double[n][n];
	// petite methode pour calculer un carre
	static double SQR(double x) { return x * x; }
	
	// Calcul de la distance euclidienne pour la matrice de position
	static double dist(double[][] position, int a, int b)
	{
		double sum = 0.0;
		for (int i = 0; i < m; i++)
		{
			sum = sum + SQR(position[a][i] - position[b][i]);
		}
		return Math.sqrt(sum);
	}

		
	public static void main(String[] args)
	{
		// On crée une matrice triangulaire aléatoire
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < i; j++) positionInit[i][j] = Math.random();	
		}
		
		// On calcul les distances euclidiennes entre les points
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < i; j++)
			{
				distance[i][j] = dist(positionInit,i, j);
				distance[j][i] = dist(positionInit,i, j);
			}
		}
		
		// Le premier point a tout ces coordonnées nulles
		// Le deuxième n'a qu'une seule coordonnée nulle
		position[1][0] = distance[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
			// La norme du vecteur sera sa distance au point 1
			double norme = SQR(distance[0][i]); 

			// On calcul d'abord les n-2 premières coordonnées du point courant
			for (int p = 0; p < i - 1; p++)
			{
				position[i][p] = norme - SQR(distance[p + 1][i])+ SQR(distance[p+1][0]);

				double sumCoord = 0.0;
				for (int j = 0; j <= p - 1; j++) 
				{
					sumCoord += position[i][j] * position[p + 1][j];
				}
				position[i][p] = position[i][p] - 2 * sumCoord;
				position[i][p] = position[i][p] / (2 * position[p + 1][p]);
			}

			// On calcul enfin la dernière coord du point courant en utilisant les coord calculés à l'instant
			double sumSQR=0.0;
			for (int j = 0; j < i - 1; j++)
			{
				sumSQR += SQR(position[i][j]);
			}
			// Le dernier calcul devrait tjs etre vrai car norme > sumSQR (mathematiquement j'entend)
			position[i][i - 1] = 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(position[i][i - 1])==true && zero==0){
				zero++;
				System.out.println(" NaN at i=" + i );
			}
		}
		
	}
	
}
fredericmazue

Quote:
ca fait 4 mois que je me suis mis au Java

Fallait pas...
Quote:
car ca fait partie d'un logiciel plus gros deja en java

Fallait pas non plus...

Quote:
J'ai fait un algo de test (ci-dessous),

C'est que ci-dessous, ce n'est pas un algorithme qu'il y a, mais du code. Code qui, soit dit sans vouloir te peiner, est illisible. Il faudrait au moins respecter les conventions d'écriture. Geotest ou lieu de geotest. whichPoint au lieu de WhichPoint, carre au lieu de SQR (qui ressemble beaucoup trop à sqrt qui plus est), etc.
Ceci étant dit, après y avoir passé un bon moment car piqué par la curiosité, je dois dire que je ne suis pas parvenu à comprendre ce code.
Mais à priori, il n'y a pas "d'erreur de calcul typique de Java."
Je serais assez curieux de voir l'algorithme écrit ici, pour pouvoir voir s'il il a été traduit correctement en Java.
Parce que ce code, je le trouve très bizarre ainsi que ces commentaires. Exemple:

Quote:
On crée une matrice triangulaire aléatoire

Comment ça une matrice triangulaire ? J'ignorais que l'on pouvait faire ça en Java. En Objective Caml oui, mais pas en Java ;)
ltchris

arf ces informaticiens ... jamais content par le code qu'on leur donne :)
(moi je le trouve très lisible (après 1mois passé dedans forcement))
J'imagine bien que pris brut comme ça, ça doit pas le faire !

Bon j'ai un word avec l'algo qui est dispo, je vais virer les infos qui servent a rien, et je met ca sur le forum plus tard.

Merci en tout cas pour avoir passé un peu de tps sur mon probleme.

ltchris

et hop, j'espere que ca t'aidera, ou au moins que ca t'embrouillera pas plus :

En entrer, j’ai une matrice de position positionInit[Nbpoints][Nbpoints-1] (triangulaire aleatoire, dans la pratique cette matrice sera donnée par les experiences) , grace à cette matrice je calcule les distances euclidiennes entre tout les points (methode dist) et donc j’obtiens une matrice de distance distance[Nbpoints][Nbpoints]

C’est sur cette dernière matrice que je vais lancer mon algorithme :
Il consiste à positionner les n points, dont j’ai les distances les uns par rapport aux autres, dans un espace à n-1 dimensions

- Pour le premier point, il faut initialiser ses coordonnées à 0. c’est l’origine de notre espace.
- Pour le deuxième on initialise sa première coordonnée grâce à la valeur de distance[0][1]

Ensuite nous allons lancer l’algorithme pour tout les points, du 3ème au nème. Donc on fera une première boucle for avec i le numéro du point, qui ira de 2 à n-1

    Pour chaque point i, les i-2 premières coordonnées p sont calculées grâce à la formule mathématique suivante. Pour calculer ces coordonnées on aura donc une deuxième boucle for avec p allant de 0 à i-2 :

    [img]http://www.edp6.jussieu.fr/etudiants/becavin/equ1cercle.bmp[/img]
    Dans cette formule l’élèment x^i_p = position[i-1][p-1] (variable position[][] de mon code)
    Et l’élèment d_i_p = distance [i-1][p-1] (variable distance[][] de mon code)

    Une fois la boucle for sur le p terminée, il reste la dernière coordonnée à calculer, en utilisant l’équation suivante :
    [img]http://www.edp6.jussieu.fr/etudiants/becavin/equ2cercle.bmp[/img]

Une fois les n points calculés, on arrête l’algorithme, et on a donc n points avec n-1 dimensions.

edit : merde les images s'affichent pas ?? pas le tps de m'en occuper je dois partir, je met un lien html vers les equations

fredericmazue

Quote:
arf ces informaticiens ... jamais content par le code qu'on leur donne

En effet :)

Quote:
(moi je le trouve très lisible (après 1mois passé dedans forcement))

Quoiqu'on pourrait argumenter qu'une heure devrait suffire .... :twisted:

Quote:
J'imagine bien que pris brut comme ça, ça doit pas le faire !

Ben...
D'ailleurs.. je ne voudrais pas trop remuer le couteau dans la plaie...mais ça ne le fait pas pour toi non plus :)

Quote:
j’ai une matrice de position positionInit[Nbpoints][Nbpoints-1] (triangulaire aleatoire,

Je dois être particulièrement obtu ce soir, mais je n'arrive pas à voir en quoi cette matrice rectangulaire est triangulaire :twisted:
Quote:
grace à cette matrice je calcule les distances euclidiennes entre tout les points (methode dist) et donc j’obtiens une matrice de distance distance[Nbpoints][Nbpoints]

Déjà ça je comprends mal. Je veux dire que si tu fais ça, (et tu le fais au tout début du code) c'est comme si il y avait une origine à ton espace Donc je vois pas pourquoi tu (re)définis l'origine de cette espace après

Quote:
C’est sur cette dernière matrice que je vais lancer mon algorithme :
Il consiste à positionner les n points, dont j’ai les distances les uns par rapport aux autres, dans un espace à n-1 dimensions

Ca c'est le but à atteindre, ce n'est pas un algorithme

Quote:
- Pour le premier point, il faut initialiser ses coordonnées à 0. c’est l’origine de notre espace.

Bon ok, quoi que l'intérêt reste pour moi à éclaircir.

Quote:
- Pour le deuxième on initialise sa première coordonnée grâce à la valeur de distance[0][1]

Et la deuxième coordonnée ? Serait elle nulle ? Ca voudrait dire que tu orientes alors ton repère.
Y a pas à dire c'est le changement d'origine le plus tordu que j'ai jamais vu (à moins que je ne comprenne rien, ce qui est à envisager très sérieusement semble-t-il).
Pourquoi ne pas (simplement) retrancher à tous les points les coordonnées du point définissant la nouvelle origine. ?

Et puis il y a ça aussi que je ne comprends pas:

Quote:
dans un espace à n-1 dimensions

Dans un espace à n-1 dimensions, les points devraient avoir n-1 coordonnées non ?
Quote:
Une fois les n points calculés, on arrête l’algorithme, et on a donc n points avec n-1 dimensions.

:?:
je devrais sans doute retourner un peu sur les bancs d'école moi.
ou alors il faut lire "n points avec n-1 distances entre eux" :?:
willbback
Quelques remaniements de code après...

J'ai tracé l'éxécution de ton programme, surtout après avoir enlever toutes les variables et fonctions statics.
Il n'y a pas de dépacement de capacité ou d'autre effet de bord sur les calculs. Les traces de l'éxécution montrent bien que la différence est négative :

norme => 0.6771649337724758
sumSQR => 0.05707986660139994
norme - sumSQR => 0.6200850671710758
norme => 1.0030697128773087
sumSQR => 0.03222925665236757
norme - sumSQR => 0.9708404562249412
norme => 1.6103219051706512
sumSQR => 1.479207586759017
norme - sumSQR => 0.13111431841163412
norme => 0.8206716593165391
sumSQR => 0.8202296274896069
norme - sumSQR => 4.4203182693214327E-4
norme => 2.33203115646992
sumSQR => 1.9012313283131725
norme - sumSQR => 0.43079982815674733
norme => 1.7277038148539423
sumSQR => 1.6565290558001564
norme - sumSQR => 0.0711747590537859
norme => 2.167547453133912
sumSQR => 2.145516661279583
norme - sumSQR => 0.022030791854329212
norme => 1.4767939326954636
sumSQR => 1.4544310947438701
norme - sumSQR => 0.02236283795159344
norme => 4.4729882524182045
sumSQR => 4.472868352812732
norme - sumSQR => 1.1989960547253986E-4
norme => 2.4951891405564304
sumSQR => 2.3602593924517876
norme - sumSQR => 0.13492974810464275
norme => 2.9211583347587533
sumSQR => 2.723605174377494
norme - sumSQR => 0.19755316038125947
norme => 3.5766665973028613
sumSQR => 2.9829678146307725
norme - sumSQR => 0.5936987826720888
norme => 4.49540328150194
sumSQR => 4.40280668680983
norme - sumSQR => 0.09259659469210924
norme => 5.026392701318516
sumSQR => 5.023688623120788
norme - sumSQR => 0.0027040781977278883
norme => 5.393425564372234
sumSQR => 5.185970951912552
norme - sumSQR => 0.20745461245968233
norme => 5.878960472224615
sumSQR => 5.463234841401164
norme - sumSQR => 0.4157256308234514
norme => 7.46242180674296
sumSQR => 7.362336686900056
norme - sumSQR => 0.10008511984290447
norme => 4.5891146021073075
sumSQR => 3.940467161329124
norme - sumSQR => 0.6486474407781837
norme => 5.805762546267093
sumSQR => 5.8047779010762275
norme - sumSQR => 9.846451908659404E-4
norme => 6.863656392523804
sumSQR => 6.862331695598104
norme - sumSQR => 0.0013246969257005858
norme => 7.587026893718924
sumSQR => 7.583958030155845
norme - sumSQR => 0.003068863563078672
norme => 8.00070710308303
sumSQR => 7.932200070631185
norme - sumSQR => 0.06850703245184508
norme => 8.154385201498945
sumSQR => 7.378167978642483
norme - sumSQR => 0.7762172228564621
norme => 8.333522523968602
sumSQR => 7.9045277653578525
norme - sumSQR => 0.42899475861074965
norme => 7.5153325105110875
sumSQR => 7.446802772173845
norme - sumSQR => 0.06852973833724274
norme => 8.043054062695509
sumSQR => 18.870764060930057
norme - sumSQR => -10.827709998234548
 NaN at i=27

Le problème est bien dans le calcul.

fredericmazue

Quote:
surtout après avoir enlever toutes les variables et fonctions statics.

C'est pas du luxe... ;)

Quote:
traces de l'éxécution montrent bien que la différence est négative [...] Le problème est bien dans le calcul

C'est ce que j'avais constaté aussi. Dis je ne voudrais pas mourir idiot... Tu as compris toi ce qu'il veut faire ? Et pourquoi il fait un changement de repère de la façon dont il le fait ? Je n'arrive pas à saisir...

ltchris

sorry de répondre aussi tard (c'était pour laisser un suspens ... que vous trouviez pkoi je voulais faire ce programme).

alors en fait, ce que je vous ai montré est la version de test la plus simple que je puisse donner, donc c'est impossible de comprendre ce que je veux faire avec ce programme en ayant juste cette version.
Je vais donc vous dire ce que je veux faire comme vous êtes curieux.
C'est un sujet de doctorat que je viens de débuter. Il s'agit de prendre les données tirées d'experience de puce à ADN (chercher sur wikipedia pour info). De ces expériences, je tire un tableau de données de n*34000

n représente les différentes types de cellules observées (qu'on appelle condition biologique), et 34000 le nombre de niveau d'expression de gènes qu'on observe.
De cette très grande matrice, on extrait une matrice de n*n comprenant les distances entre les diffèrentes conditions biologiques.
Utilisant cette matrice je veux alors représenter mes n points dans un espace euclidien. Cet espace aura n-1 dimensions pour ne perdre aucune information.

donc dans mon programme finale ce qu'il y aura en entrée sera la matrice de distance. Mon programme de test genère lui meme cette matrice distance en creant aléatoirement une matrice de position (triangulaire car y'a des zero partout sauf sur le triangle inferieur). Mais dans la suite la valeur de cette matrice position n'a aucun interet. il ne faut donc pas comparer les matrices position de depart avec celle de fin, elles n'ont aucun lien. Et dans la pratique finale, elle n'auront meme pas la meme dimension.

Le but est vraiment : representer n points dont j'ai les distances les uns par rapport aux autres dans un espace euclidien.

Pour reparler du bug, j'avais deja vu ouais que norm devenait plus petit que sumCoord vers la fin, mais je n'en ai pas trouvé la raison.

sur d'autres forum on me parle de la precision, et d'utiliser BigDecimal . Je vais tester ca j'ai rien a perdre...

willbback

C'est ce que j'avais constaté aussi. Dis je ne voudrais pas mourir idiot... Tu as compris toi ce qu'il veut faire ? Et pourquoi il fait un changement de repère de la façon dont il le fait ? Je n'arrive pas à saisir...

Moi, je ne suis qu'un bête développeur, je code que ce qui est dans les spécifications. :shock:

Concernant la précision, je veux bien croire qu'il ya un problème de précision, mais reste quand même beaucoup de problème d'algorithmie dans ce "bout de code".

Je suis loin d'être une super tronche en math, donc loin de moi l'idée de critiqué les formules mathématiques. Mais là, l'écart entre les 2 nombres produisants la valeure négative est tout de même proche de 2, ce qui fait beaucoup pour une imprécision de calcul sur un nombre si petit.
De plus, l'ordre de grandeur de chaque nombre devient très vite significatif, j'ai fait des éxecutions en faisant varier le nombre de points. Le problème ne se produit pas toujours au même endroit, et la fréquence est relativement rare en dessous de n=47.

Je pencherais plus sur un problème de donnée.

A au fait, voici le code un peu nettoyé

package test;

class Geotest {
	//  n = nombre de points
	//  m = dimension de l'espace
	private int n = 100;

	private int m = n - 1;

	// Matrice des positions initiales
	public double[][] positionInit = new double[n][m];

	// Matrice des positions reconstruites par l'algorithme
	public double[][] position = new double[n][m];

	// Matrice des distances
	public double[][] distance = new double[n][n];

	// petite methode pour calculer un carre
	double SQR(double x) {
		return x * x;
	}

	// Calcul de la distance euclidienne pour la matrice de position
	double dist(double[][] position, int a, int b) {
		double sum = 0.0;
		for (int i = 0; i < m; i++) {
			sum = sum + SQR(position[a][i] - position[b][i]);
		}
		return Math.sqrt(sum);
	}

	public void executeTest() {
		// On crée une matrice triangulaire aléatoire
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < i; j++)
				positionInit[i][j] = Math.random();
		}

		// On calcul les distances euclidiennes entre les points
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < i; j++) {
				distance[i][j] = dist(positionInit, i, j);
				distance[j][i] = dist(positionInit, i, j);
			}
		}

		// Le premier point a tout ces coordonnées nulles
		// Le deuxième n'a qu'une seule coordonnée nulle
		position[1][0] = distance[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
			// La norme du vecteur sera sa distance au point 1
			double norme = SQR(distance[0][i]);

			// On calcul d'abord les n-2 premières coordonnées du point courant
			for (int p = 0; p < i - 1; p++) {
				position[i][p] = norme - SQR(distance[p + 1][i]) + SQR(distance[p + 1][0]);

				double sumCoord = 0.0;
				for (int j = 0; j <= p - 1; j++) {
					sumCoord += position[i][j] * position[p + 1][j];
				}
				position[i][p] = position[i][p] - 2 * sumCoord;
				position[i][p] = position[i][p] / (2 * position[p + 1][p]);
			}

			// On calcul enfin la dernière coord du point courant en utilisant les coord calculés à
			// l'instant
			double sumSQR = 0.0;
			for (int j = 0; j < i - 1; j++) {
				sumSQR += SQR(position[i][j]);
			}

			// Le dernier calcul devrait tjs etre vrai car norme > sumSQR (mathematiquement j'entend)
			position[i][i - 1] = 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(position[i][i - 1]) == true && zero == 0) {
				zero++;
			}
		}

	}

	public static void main(String[] args) {
		Geotest test = new Geotest();
		test.executeTest();
	}
}
fredericmazue

Quote:
matrice de position (triangulaire car y'a des zero partout sauf sur le triangle inferieur).

Sauf que c'est une matrice rectangulaire. (arf ces programmeurs... oui je sais ... ;) )

Quote:
sur d'autres forum on me parle de la precision

Faut pas écouter ce qu'on dit sur les autres forum ;)
wilbback wrote:
Mais là, l'écart entre les 2 nombres produisants la valeure négative est tout de même proche de 2, ce qui fait beaucoup pour une imprécision de calcul sur un nombre si petit.

wilbback a tout à fait raison à mon humble avis. J'ai moi même hier regardé brièvement sous deboggueur et j'ai vu des valeurs négatives de 0.2 ce qui est de même beaucoup pour une imprécision. Et même beaucoup trop vu le peu de calculs effectués sur les nombres. Le problème de précision ne me parait pas vraisemblable.

En tous cas mon ampéropifomètre à ondultions synthétiques vibro-quantiques me suggère que les calculs pourraient bien être faux.

Du moins mon expérience d'informaticien (arf) me fait penser que c'est plus probable qu'un erreur de précision.

ltchris

Cool, un joli code tout propre d'informaticien :)

Malheureusement vous confirmez, ce que je pensais depuis le debut. Avec des resultats avec aussi peu de chiffre avant la virgule (1 , 2 max) il me parait bizarre que des erreurs de precision apparaissent.
Et les calculs je l'es ai verifié 20 fois ... (d'ou les presque 1mois de recherche de bug=verif calcul + verif divergence quelconque + c quoi ce bordel putain)

Je sens que je vais essayer de faire totalement différement mon truc, car ca fait chié !

Merci bcp en tout cas pour l'aide, si vous voyez quelque chose d'autre prevenez moi ...

willbback
Une petite dernière....

Décidément, mon patron va finir par me virer à force de jouer avec ce merveilleux algorithme.
Voici le code que j'ai mis en place

package test;

class Geotest {
	//  n = nombre de points
	//  m = dimension de l'espace
	private int n = 10;

	private int m = n - 1;

	// Matrice des positions initiales
	public double[][] positionInit = new double[n][m];

	// Matrice des positions reconstruites par l'algorithme
	public double[][] position = new double[n][m];

	// Matrice des distances
	public double[][] distance = new double[n][n];

	// petite methode pour calculer un carre
	double SQR(double x) {
		return x * x;
	}

	// Calcul de la distance euclidienne pour la matrice de position
	double dist(double[][] position, int a, int b) {
		double sum = 0;
		for (int i = 0; i < m; i++) {
			sum = sum + SQR(position[a][i] - position[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++) {
				positionInit[i][j] = (int)(Math.random() * 10);
				System.out.print(positionInit[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 < i; j++) {
				distance[i][j] = dist(positionInit, i, j);
				distance[j][i] = dist(positionInit, i, j);
				System.out.print(distance[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
		position[1][0] = distance[1][0];
		System.out.println(position[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 = SQR(distance[0][i]);

			// On calcul d'abord les n-2 premières coordonnées du point courant
			for (int p = 0; p < i - 1; p++) {
				position[i][p] = norme - SQR(distance[p + 1][i]) + SQR(distance[p + 1][0]);

				double sumCoord = 0;
				for (int j = 0; j <= p - 1; j++) {
					sumCoord += position[i][j] * position[p + 1][j];
				}
				position[i][p] = position[i][p] - 2 * sumCoord;
				position[i][p] = position[i][p] / (2 * position[p + 1][p]);
				System.out.print(position[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 += SQR(position[i][j]);
			}

			// Le dernier calcul devrait tjs etre vrai car norme > sumSQR (mathematiquement j'entend)
			position[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(position[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(position[i][j] + " ");
			}
			System.out.println();
		}


	}

	public static void main(String[] args) {
		Geotest test = new Geotest();
		test.executeTest();
	}
}

J'ai fait plusieurs éxécutions avec n=10 pour ne pas faire trop apparaître de résultat.
J'ai transformé l'affectation aléatoire pour donner un nombre entier compris entre 0 et 9 afin de limiter l'influence d'une imprécision de calcul.
J'ai fait également afficher les différentes matrices produites (avec un joli effet de mise en page pour bien tout voir :lol: )
Voici le résultat :

Matrice Initiale
0=>	
1=>	3.0 
2=>	0.0 0.0 
3=>	1.0 3.0 1.0 
4=>	9.0 7.0 3.0 5.0 
5=>	1.0 2.0 5.0 9.0 0.0 
6=>	3.0 3.0 7.0 9.0 6.0 3.0 
7=>	5.0 0.0 4.0 4.0 6.0 0.0 2.0 
8=>	9.0 3.0 6.0 7.0 6.0 2.0 3.0 4.0 
9=>	6.0 4.0 9.0 7.0 3.0 1.0 1.0 5.0 1.0 
Matrice distance
0=>	
1=>	3.0 
2=>	0.0 3.0 
3=>	3.3166247903554 3.7416573867739413 3.3166247903554 
4=>	12.806248474865697 10.908712114635714 12.806248474865697 10.44030650891055 
5=>	10.535653752852738 10.677078252031311 10.535653752852738 9.899494936611665 10.44030650891055 
6=>	13.892443989449804 13.564659966250536 13.892443989449804 12.884098726725126 11.357816691600547 7.3484692283495345 
7=>	9.848857801796104 8.717797887081348 9.848857801796104 9.486832980505138 10.344080432788601 9.273618495495704 7.745966692414834 
8=>	15.491933384829668 13.96424004376894 15.491933384829668 14.247806848775006 9.695359714832659 11.61895003862225 8.18535277187245 7.681145747868608 
9=>	14.798648586948742 13.856406460551018 14.798648586948742 13.2664991614216 9.746794344808963 9.273618495495704 7.615773105863909 9.38083151964686 5.916079783099616 
Matrice Résultat (intermediaire)
1=>	3.0 
2=>	0.0 
3=>	1.0 NaN 
Nan a 3
4=>	9.000000000000002 NaN NaN 
5=>	0.9999999999999977 NaN NaN NaN 
6=>	2.999999999999995 NaN NaN NaN NaN 
7=>	4.999999999999996 NaN NaN NaN NaN NaN 
8=>	9.000000000000005 NaN NaN NaN NaN NaN NaN 
9=>	6.000000000000004 NaN NaN NaN NaN NaN NaN NaN 
Matrice resultat
0=>	
1=>	3.0 
2=>	0.0 0.0 
3=>	1.0 NaN NaN 
4=>	9.000000000000002 NaN NaN NaN 
5=>	0.9999999999999977 NaN NaN NaN NaN 
6=>	2.999999999999995 NaN NaN NaN NaN NaN 
7=>	4.999999999999996 NaN NaN NaN NaN NaN NaN 
8=>	9.000000000000005 NaN NaN NaN NaN NaN NaN NaN 
9=>	6.000000000000004 NaN NaN NaN NaN NaN NaN NaN NaN 

La lecture de se résultat montre que :

    le test du NaN ne reporte pas toutes les erreurs
    le NaN se trouve gentiellement réparti après le 2ème colonne de la matrice

Quote:

Et les calculs je l'es ai verifié 20 fois ... (d'ou les presque 1mois de recherche de bug=verif calcul + verif divergence quelconque + c quoi ce bordel putain)

Je pense qu'il est peut-être nécessaire de revérifier l'algorithme d'implémentation. Un petit problème de déplacement dans la Matrice peut-être ?

Quote:

Pour reparler du bug, j'avais deja vu ouais que norm devenait plus petit que sumCoord vers la fin, mais je n'en ai pas trouvé la raison.

sur d'autres forum on me parle de la precision, et d'utiliser BigDecimal . Je vais tester ca j'ai rien a perdre...

Juste pour info, Math.sqrt fonctionne qu'avec des doubles, donc la précision restera égale à l'imprécision des doubles, quoi que tu fasses

fredericmazue

On voit aussi (matrice intermédiaire et résultat) des valeurs proches de 0 ou 1 systématiquement ce que ne me parait pas normal.

L'algorithme semble donc bien faux. A l'expérience je voterais pour une subtile confusion d'indice entre indices des formules mathématiques et indices d'accès aux valeurs des matrices.

Le challenge est intéressant. Dès que j'ai un moment j'essaie d'y voir clair, maintenant que j'ai enfin saisi le problème à résoudre (ca a été dur...)

ltchris

ben le probleme d'indice ca été ce que j'ai essayé de résoudre en premier. Et si il y en avait tjs un, ne pensiez vous pas que ca donnerai un resultat faux des le debut ?

si le challenge vous interesse, peut etre pouvez vous essayer de reprendre depuis le debut, il suffit de vous posez la question :

comment, si j'ai des distances entre des points, representer ces points dans un espace à n-1 dimensions, un espace euclidien ou en calculant la distance entre ces points j'aurai exactement la matrice de distance de depart ?

fredericmazue

Quote:
ben le probleme d'indice ca été ce que j'ai essayé de résoudre en premier. Et si il y en avait tjs un, ne pensiez vous pas que ca donnerai un resultat faux des le debut ?

Je me doute bien que vous y avez pensé.

A propos de résultat faux, la première chose que je vais faire est d'essayer votre code sur 4 points (constants plutôt qu'aléatoires pour commencer), donc (si je comprends bien) dans un espace à trois dimensions que je peux me représenter dans ma petite tête obtue. Je ferai d'abord les calculs à la main et vérifierai dans un premier temps que le code donne le même résultat.
Vous l'avez fait ce test ?

ltchris

yep!
avec qu'il y est le NaN je verifie que le calcul est exact à 10^-17 pres , soit la precisiondu double. Je vois mal comment pourrai y avoir un probleme d'indice.

fredericmazue

Quote:
Je vois mal comment pourrai y avoir un probleme d'indice.

Je vois mal le rapport, Si Nan il y a, problème quelque part il y a.
Faut dire ausis que j'ai du mal à comprendre votre phrase. "Nan il y a" et "calcul exact" Comment ça ?

De toutes façons ça sera soit ça soit que les formules mathématiques sont fausses. Bon bien sûr elles sont peut être mal transcrites, mais après un mois de vérif ça semble peu probable.

Itchris wrote:
Mathématiquement la méthode de reconstruction marche y'a pas de problème

Arf ces scientifiques, tous pareils :twisted:

Désolé je n'ai pas pu me retenir :oops:

willbback
Piste des indices....

ltchris wrote:
yep!
avec qu'il y est le NaN je verifie que le calcul est exact à 10^-17 pres , soit la precisiondu double. Je vois mal comment pourrai y avoir un probleme d'indice.

Etant super nul en math, je n'oserais pas faire de remarque sur les formules. Concernant le parcours de tableaux à l'aide d'indice, ça je connais (débordement de pile, etc...).

J'ai pris votre algorithme, j'ai remplacé les types primitifs double des tableau en objet Double. Et là, petite surprise, ça ne marche plus du tout car j'ai un superbe et tant redouté "java.lang.NullPointerException".
Ce qui signifie tout simplement l'accès a une valeur non initialisée dans le tableau (ce phénomène ne se produit pas avec les types primitifs car la valeur par défaut est 0 en java).
Effectivement, vos indices de parcours ne dépassent pas la limite de votre tableau, ça c'est géré, en revanche, la matrice étant triangulaire inférieure, le calcul de distance (puisque c'est de là qu'intervient l'erreur java) accède à la partie supérieure de la matrice (celle remplit de 0).

J'espère que ce point va vous aider. Si vous avez besoin de plus de détail "java" pour reproduire l'erreur, je vous soumettrais mon code transformé, mais il n'est pas un exemple à suivre pour les développements, c'est juste pour la validation des indices dans votre cas.

Bon courage

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

fredericmazue

Un petit complément:

Finalement il y a bien un facétie de Java à laquelle tu ne t'attendais peut être pas. En effet

int i = 1/0

lève une exception DivisionByZeroException

tandis que

double d = 1.0/0.0

ne la lève pas et affecte Infinity à d, alors que tu t'attendais peut être à une levée d'exception.

arf ce Java :twisted: Non j'exagère :) Beaucoup de langages font comme lui.

willbback
Je crois que je vais avoir le droit à la moitié du Million

fredericmazue wrote:

double d = 1.0/0.0

ne la lève pas et affecte Infinity à d, alors que tu t'attendais peut être à une levée d'exception.

arf ce Java :twisted: Non j'exagère :) Beaucoup de langages font comme lui.

C'est déjà pas cool comme ça.
J'avais remarqué le risque de division par zéro, mais dans tous mes essais, je n'ai jamais vu "Infinity" dans les resultats affichés.
Je viens donc de refaire les essais avec ton code légèrement modifié.

class Geotest {
	final int NB_POINTS = 40;

	// 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];

	// 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

		for (int i = 0; i < n; i++) {
			for (int j = 0; j < i; j++) {
				coordonneesInitiales[i][j] = Math.random();
				if (coordonneesInitiales[i][j] == 0) {
					System.out.println("********  coordonneesInitiales[i][j] ["
							+ i + "][" + j + "] == 0 ********");
				}
			}
		}

		printMatrice("Matrice Initiale Complète", coordonneesInitiales);

		// On calcul les distances euclidiennes entre les points
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				distances[i][j] = dist(coordonneesInitiales, i, j);
				distances[j][i] = dist(coordonneesInitiales, i, j);
			}
		}
		printMatrice("Matrice distance", distances);

		// 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];

		/*
		 * 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
			// La norme du vecteur sera sa distance au point 1
			double norme = carre(distances[0][i]);
			if (norme == 0) {
				System.out.println("********  norme [0][" + i + "] == 0 ********");
			}

			// 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;
				if (coordonnees[p + 1][p] == 0) {
					System.out.println("********  coordonnees[p + 1][p] ["
							+ (p + 1) + "][" + p + "] == 0 ********");
				}
				coordonnees[i][p] = coordonnees[i][p]
						/ (2 * coordonnees[p + 1][p]);
			}
			// 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)
			if ((norme - sumSQR) <= 0) {
				System.out.println("********  (norme - sumSQR) <= 0 "+ (norme - sumSQR) + "********");
			}
			coordonnees[i][i - 1] = 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);
			}
		}
		printMatrice("Matrice resultat", coordonnees);
		System.out.println("Nombre NaN :" + zero);
	}

	private void printMatrice(String legende, double[][] matrice) {
		System.out.println(legende);
		for (int i = 0; i < n; i++) {
			System.out.print(i + "|	");
			for (int j = 0; j < m; j++) {
				System.out.print(matrice[i][j] + "	");
			}
			System.out.println();
		}
	}

	public static void main(String[] args) {
		Geotest test = new Geotest();
		test.executeTest();
	}
}

J'ai eu un ensemble de valeurs à NaN sans pour autant avoir un Infinity. En français dans le texte, j'ai bien eu une valeur négative passée à la fonction racine carré (sqrt) sans pour autant avoir des valeurs à 0 dans les coordonnées.
Il existe donc 2 bugs :
_ Quand les coordonnées sont égales à 0
_ Quand les valeurs sont très petites, la somme "sumSQR" est supérieur à la "norme".
Lors d'un précédent post, j'ai évoqué le problème de la fonction "dist" qui accède à des valeurs dans la partie supérieur de la matrice triangulaire, donc des valeurs à 0.
Il est très probable que si les valeurs sont suffisament petites, le fait de "louper" une valeur dans le calcul de la distance fait que la "sumSQR".
Je continu donc à soutenir que la fonction "dist" a un problème d'indice.

Et pour fredericmazue, le meilleur langage qui existe est celui que chacun maîtrise le mieux (dicton de consultant) :lol:

fredericmazue

Quote:
J'ai eu un ensemble de valeurs à NaN sans pour autant avoir un Infinity

J'ai pas lu ton code. (pas beaucoup le temps ce matin.) Mais je garantis que le mien a bien des Infinity et qu'il y a bien division par zéro.

Quote:
Il existe donc 2 bugs :
_ Quand les coordonnées sont égales à 0
_ Quand les valeurs sont très petites,

C'est aussi mon avis.
Je pense que ça devrait pouvoir se régler en testant ces conditions. Si on tombe dessus, alors on suspend le calcul, on translate d'un vecteur bien senti tous les points déjà calculés, et on reprend le calcul.

Quote:
Je continu donc à soutenir que la fonction "dist" a un problème d'indice.

C'est possible. Je n'ai pas appronfondi la question. Si j'ai le temps j'essaierai de voir ce soir.
Je n'ai pas regardé non plus hier, car nous avons posté quasiment en même temps hier et je n'avais pas encore lu ton post en postant le mien.

Quote:
Et pour fredericmazue, le meilleur langage qui existe est celui que chacun maîtrise le mieux

Le meilleur langage est celui qui convient le mieux au travail à faire. Dicton de non consultant :lol:
Et dans la grande majorité des cas (sauf applet bien sûr :twisted:) ça n'est pas Java ;) :lol:
fredericmazue

Quote:
J'avais remarqué le risque de division par zéro, mais dans tous mes essais, je n'ai jamais vu "Infinity"

Ca parait quand même incroyable que tu n'ais pas Infinity. Comme j'étais fatigué l'autre soir, j'ai vérifié ce matin ce que j'ai dit plus haut et ca fait bien comme j'ai dit.

J'ai aussi essayé ce matin

    public double[][] coordonneesInitiales = 
                                      
    { 
        { 0.0, 0.0, 0.0 } ,
        { 2.0, 0.0, 0.0 },
        { 7.0, 0.0, 0.0 },
        { 0.0, 1.0, 2.0 }
    };

qui donne

0.0 0.0 0.0 
2.0 0.0 0.0 
7.0 0.0 0.0 
0.0 1.0 2.0 
Matrice distance
0=>   0.0 2.0 7.0 
1=>   2.0 0.0 5.0 
2=>   7.0 5.0 0.0 
3=>   2.23606797749979 3.0 7.3484692283495345 
Matrice Résultat (intermediaire)
1=>   2.0 
2=>   7.0 
3=>   2.220446049250313E-16 -Infinity 
Nan a 3
Matrice resultat
0=>   
1=>   2.0 
2=>   7.0 0.0 
3=>   2.220446049250313E-16 -Infinity NaN 

Sur JVM 1.6.0_02-b06
Quelle JVM tu as ?
Non non on se marre pas, les JVM sont pleines de surprises...

willbback

fredericmazue wrote:
Ca parait quand même incroyable que tu n'ais pas Infinity.

Je parlais de mes essais à moi (avec le Math.random). Avec ton code, j'ai bien "infinity", peut importe la JVM (1.4 et 1.5 avec des brouettes derrière).

C'est pour celà que j'ai réécrit le code en gardant le Math.random. J'ai ajouté un contrôle sur l'affectation d'une valeur à 0 par le Math.random et un test s'il y a une division par 0. Or mon joli message pleins de "****" ne s'affiche pas et pourtant j'ai des NaN en sortie.
Donc, la division par 0 n'est pas la seule explication.
Le phénomène du NaN ne semble pas apparaître si on multiplie par 10 le Math.random, ce qui faisait soupçonner l'imprésion de calcul. Mais lors que l'on fait affiché la différence entre "norme" et "sumSQR", il y a plus de 1 et nom pas un chiffre type -0,0000000001 par exemple. Il y a donc un réel écart entre les 2 nombres.
On peut me répondre par " c'est normal, celà correspond à la somme des incertitudes cumulées dans sumSQR". C'est effectivement une possibilité, mais la variable norme suit le même principe. Et pourquoi, lorsque que l'on affecte la matrice par des valeurs croissantes, nous n'avons plus le même problème avec par exemple (Math.sqrt(i*j+1))/100.
Et il y a le phénomène de lecture de la partie supérieure de la matrice, remplit de 0. Dans le cas d'un très petit nombre, le fait de manquer d'une valeur peut entraîner suffisament d'écart pour que sumSQR soit supérieur à norme.
Je pense que je vais arrêter là, car nous n'avons plus vu notre ami à la matrice :cry: donc, je ne sais pas si les recherches servent à quelques choses, ou nous sommes en train de nous livrer une bataille d'algorithme juste pour le plaisir, et je ne voudrais pas lancer de Troll sur la qualité des langages et encore moins Java, car je suis payé suffisament cher pour défendre ce langage auprès de mes clients par ma société (Ah! le vil prestataire que voilà) 8) .
Si j'ai encore le courrage, je tenterais bien une double exécution du programme avec les mêmes valeurs, la première fois affectée directement, la seconde fois trié par ordre croissant et voir éventuellement avec un ordre décroissant, juste pour voir si la croissance des coordonnées a une influence sur le problème de calcul. Il est aussi possible de remplir la matrice avec la plus petite valeur double possible afin de voir comment le phénomène se produit. Bref un peu d'expérimentation. Mais comme notre ami ne semble plus s'intéresser au problème, je vais retourner à mon laborieu travail ..... en Java

ltchris

votre ami à la matrice est toujours la :) et lis vos post avec interet.
De mon cote j'ai trouvé d'autres comportements bizarre, qui me laisse soupconner que effectivement y'aurai un probleme du cote du calcul de distance (qui pourtant est le calcul le plus simple que le calcul scientifique puisse admettre).
J'ai fait d'autres trucs ces deux derniers jours, mais la je m'y remet, et ce soir j'aurai trouvé !!! (a moi mon million d'euros :D )

fredericmazue

Quote:
y'aurai un probleme du cote du calcul de distance

Il y a aussi le problème de la division par 0, bien réel, et vu plusieurs fois par mes petits yeux porcins.

ltchris

ouaip aussi. De manière generale c'est la partie division qui peut foutre la merde apparement!

ltchris

Putain mais c ca !!!!

J'ai relu les messages que vous avez posté. l'histoire du zero au depart je prenais ca comme quelque chose qui arrive parfois si on prend une matrice particulière.Mais en fait y'a bien un gros probleme mathematique derriere!
J'ai considérais quand j'ai fait mon algo que j'aurai jamais de position nulle, sur la diagonale de ma matrice, or je peux en avoir. Je suis entrain de voir pkoi ca fait ca au niveau des math !

fredericmazue

Quote:
J'ai relu les messages que vous avez posté. l'histoire du zero au depart je prenais ca comme quelque chose qui arrive parfois si on prend une matrice particulière.Mais en fait y'a bien un gros probleme mathematique derriere!

On arrête pas de te le dire :lol:

Itchris wrote:
Mathématiquement la méthode de reconstruction marche y'a pas de problème.

Lol :lol:
Arf.... si tu vois ce que je veux dire ;)

Bon tu dois être content que le problème se débloque.

Bon, je répète ma question: pour le million d'Euro, où dois je facturer ? ;)

ltchris

sauf que la question ne se debloque pas totalement !
effectivement qd y'a des zeros ca peut pas marcher. Et Mathématiquement ca ne remet pas en cause mes calculs, ca correspond au cas ou mon systeme linéaire n'est pas solvable (car en fait c un systeme linéaire qu'on resous depuis le debut) car le determinant de la matrice positionfinale est nulle. Cas que j'avais mis de cote, avec toute mon arrogance de jeune loup !

Mais le lien entre "y'a des zeros", et "y'a du NaN" et pas encore acquis, car y'a du NaN sans que j'ai des zeros.

Donc le probleme reste, mais on avance .... Merci à vous ...
Je regarde encore un peu le truc jusqu'a 19h, et pour le reste on verra Lundi !
bon weekend à tous

L'homme à la matrice

fredericmazue

Quote:
effectivement qd y'a des zeros ca peut pas marcher.

Je veux donc mon million d'Euro.

Quote:
avec toute mon arrogance de jeune loup !

Arf... ;)

Quote:
Mais le lien entre "y'a des zeros", et "y'a du NaN" et pas encore acquis, car y'a du NaN sans que j'ai des zeros.

Je dirais, toujours avec l'aide de mon ampéro-pifomètre, que le problème est le même.
N'y aurait-il pas du NaN quand il y a du "presque zéro", des valeurs très petites quoi. D'ailleurs willbback te l'a suggéré dans un de ses posts je crois.

ltchris

et bien non le probleme est pas résolu donc pas de million d'euros :o (comment se sortir de cette situation ? ... changer le nom du post ? non ca va se voir ! .... je suis dans la merde :cry: )

Quote:
Je dirais, toujours avec l'aide de mon ampéro-pifomètre, que le problème est le même.
N'y aurait-il pas du NaN quand il y a du "presque zéro", des valeurs très petites quoi. D'ailleurs willbback te l'a suggéré dans un de ses posts je crois.

Alors : oui ! mais non !
Car j'ai des matrices ou on divise par des nombres pas du tout petit, et on a du nan quand meme !

ltchris

par exemple cette matrice :

>>
>> Position init :
>> 0.099
>> 0.065 0.292
>> 0.478 0.612 0.059
>> 0.748 0.791 0.885 0.244
>> 0.35 0.306 0.032 0.114 0.367
>> 0.132 0.077 0.876 0.079 0.15 0.87
>> 0.963 0.061 0.335 0.75 0.966 0.878 0.998
>> 0.166 0.547 0.288 0.3 0.759 0.557 0.919 0.756
>> 0.017 0.842 0.067 0.895 0.68 0.137 0.921 0.91 0.547
>>
>> Distances :
>>
>> 0.099
>> 0.299 0.294
>> 0.779 0.722 0.526
>> 1.424 1.375 1.248 0.92
>> 0.604 0.553 0.48 0.508 1.128
>> 1.256 1.249 1.266 1.363 1.302 1.272
>> 2.075 2.031 2.058 1.969 1.959 1.749 1.759
>> 1.674 1.667 1.597 1.596 1.749 1.439 1.582 1.342
>> 1.993 1.994 1.889 1.877 2.022 1.761 2.171 1.834 1.009

ou y'a du NaN à 3.

On ne fait jamais de division par un nombre petit mais on a du NaN !

ltchris

Bon weekend, faut vraiment que je parte!

Merci encore pour toute vos contribution !!!

et Bonne année ...

fredericmazue

Pour qu'on parle bien tous de la même chose, peut tu poster, fut il horrible ;) le code avec lequel tu travailles maintenant, si tu as fait des changement par rapport au tout premier code que tu as posté.

Parce que là je viens d'essayer ta matrice avec ton premier code et elle fait pas de Nan sauf erreur de ma part.... :shock:

willbback
Pareil sur mon poste...

Effectivement, avec le dernier code posté (le mien en l'occurence) la matrice ne présente pas de NaN. Nous avons donc un écart de code avec toi.
La seul remarque que je peux faire, c'est que cette matrice est carrée et non plus n*m comme indiqué par

           final int NB_POINTS = 9;
	   private int n = NB_POINTS;

	   private int m = NB_POINTS - 1;

	   // Matrice des positions initiales
	   public double[][] coordonneesInitiales = new double[n][m];

La définition de m n'est peut-être pas bonne dans ton algorithme.

Résultat avec m=NB_POINTS - 1

Matrice Initiale Complète
0|   0.099   0.0   0.0   0.0   0.0   0.0   0.0   0.0   
1|   0.065   0.292   0.0   0.0   0.0   0.0   0.0   0.0   
2|   0.478   0.612   0.059   0.0   0.0   0.0   0.0   0.0   
3|   0.748   0.791   0.885   0.244   0.0   0.0   0.0   0.0   
4|   0.35   0.306   0.032   0.114   0.367   0.0   0.0   0.0   
5|   0.132   0.077   0.876   0.079   0.15   0.87   0.0   0.0   
6|   0.963   0.061   0.335   0.75   0.966   0.878   0.998   0.0   
7|   0.166   0.547   0.288   0.3   0.759   0.557   0.919   0.756   
8|   0.017   0.842   0.067   0.895   0.68   0.137   0.921   0.91   
Matrice distance
0|   0.0   0.2939727878562912   0.7222644944893802   1.374642862710166   0.552581215750228   1.24901361081455   2.0310061545943183   1.6670539883279125   
1|   0.2939727878562912   0.0   0.5257851272145304   1.2482992429702104   0.47971866755422393   1.266385012545553   2.057798338030236   1.5970588592785178   
2|   0.7222644944893802   0.5257851272145304   0.0   0.9201918278272201   0.5083640427882365   1.363477539235612   1.969148546961351   1.595755933719189   
3|   1.374642862710166   1.2482992429702104   0.9201918278272201   0.0   1.1281963481593087   1.3022895223413264   1.9590061255646956   1.749351879982984   
4|   0.552581215750228   0.47971866755422393   0.5083640427882365   1.1281963481593087   0.0   1.2718156312925235   1.7486531960340221   1.4394717781186266   
5|   1.24901361081455   1.266385012545553   1.363477539235612   1.3022895223413264   1.2718156312925235   0.0   1.759449629855882   1.581640920057394   
6|   2.0310061545943183   2.057798338030236   1.969148546961351   1.9590061255646956   1.7486531960340221   1.759449629855882   0.0   1.3415591675360428   
7|   1.6670539883279125   1.5970588592785178   1.595755933719189   1.749351879982984   1.4394717781186266   1.581640920057394   1.3415591675360428   0.0   
8|   1.9179968717388463   1.807713472871185   1.79555562431243   1.9461235829206738   1.674051970519434   2.1007896134549027   1.7500377138793324   0.8476160687481095   
Matrice resultat
0|   0.0   0.0   0.0   0.0   0.0   0.0   0.0   0.0   
1|   0.2939727878562912   0.0   0.0   0.0   0.0   0.0   0.0   0.0   
2|   0.5640590110709848   0.4511135467148184   0.0   0.0   0.0   0.0   0.0   0.0   
3|   0.7106304006006282   0.845553235494761   0.8183441572385862   0.0   0.0   0.0   0.0   0.0   
4|   0.2749166022792148   0.28644631519585045   0.02873032815495471   0.38326223208931004   0.0   0.0   0.0   0.0   
5|   0.07266658984246778   0.15589590626950392   0.8473239749681973   0.09120659782029286   0.8967577549635228   0.0   0.0   0.0   
6|   -0.039336974297272766   0.9016385736644148   0.43262071765637694   1.1125176690221803   0.768253031155888   1.138164098810563   0.0   0.0   
7|   0.5355801846426934   0.1663664752428089   0.34578205869891643   0.7862465808992009   0.5455242010622685   0.8608568453856572   0.829532989969456   0.0   
8|   0.8458333909516604   0.02455934664270381   0.3282700085960744   0.8918283358684781   -0.013458714498495766   1.1051221730801026   0.7882142842439311   0.4656155299457704   
Nombre NaN :0.0

Résultat avec m=NB_POINTS

Matrice Initiale Complète
0|   0.099   0.0   0.0   0.0   0.0   0.0   0.0   0.0   0.0   
1|   0.065   0.292   0.0   0.0   0.0   0.0   0.0   0.0   0.0   
2|   0.478   0.612   0.059   0.0   0.0   0.0   0.0   0.0   0.0   
3|   0.748   0.791   0.885   0.244   0.0   0.0   0.0   0.0   0.0   
4|   0.35   0.306   0.032   0.114   0.367   0.0   0.0   0.0   0.0   
5|   0.132   0.077   0.876   0.079   0.15   0.87   0.0   0.0   0.0   
6|   0.963   0.061   0.335   0.75   0.966   0.878   0.998   0.0   0.0   
7|   0.166   0.547   0.288   0.3   0.759   0.557   0.919   0.756   0.0   
8|   0.017   0.842   0.067   0.895   0.68   0.137   0.921   0.91   0.547   
Matrice distance
0|   0.0   0.2939727878562912   0.7222644944893802   1.374642862710166   0.552581215750228   1.24901361081455   2.0310061545943183   1.6670539883279125   1.9944726119954619   
1|   0.2939727878562912   0.0   0.5257851272145304   1.2482992429702104   0.47971866755422393   1.266385012545553   2.057798338030236   1.5970588592785178   1.8886601070600288   
2|   0.7222644944893802   0.5257851272145304   0.0   0.9201918278272201   0.5083640427882365   1.363477539235612   1.969148546961351   1.595755933719189   1.8770266380635094   
3|   1.374642862710166   1.2482992429702104   0.9201918278272201   0.0   1.1281963481593087   1.3022895223413264   1.9590061255646956   1.749351879982984   2.0215355549680547   
4|   0.552581215750228   0.47971866755422393   0.5083640427882365   1.1281963481593087   0.0   1.2718156312925235   1.7486531960340221   1.4394717781186266   1.7611527474923918   
5|   1.24901361081455   1.266385012545553   1.363477539235612   1.3022895223413264   1.2718156312925235   0.0   1.759449629855882   1.581640920057394   2.170835323095697   
6|   2.0310061545943183   2.057798338030236   1.969148546961351   1.9590061255646956   1.7486531960340221   1.759449629855882   0.0   1.3415591675360428   1.833532383133715   
7|   1.6670539883279125   1.5970588592785178   1.595755933719189   1.749351879982984   1.4394717781186266   1.581640920057394   1.3415591675360428   0.0   1.0087923473143519   
8|   1.9944726119954619   1.8886601070600288   1.8770266380635094   2.0215355549680547   1.7611527474923918   2.170835323095697   1.833532383133715   1.0087923473143519   0.0   
Matrice resultat
0|   0.0   0.0   0.0   0.0   0.0   0.0   0.0   0.0   0.0   
1|   0.2939727878562912   0.0   0.0   0.0   0.0   0.0   0.0   0.0   0.0   
2|   0.5640590110709848   0.4511135467148184   0.0   0.0   0.0   0.0   0.0   0.0   0.0   
3|   0.7106304006006282   0.845553235494761   0.8183441572385862   0.0   0.0   0.0   0.0   0.0   0.0   
4|   0.2749166022792148   0.28644631519585045   0.02873032815495471   0.38326223208931004   0.0   0.0   0.0   0.0   0.0   
5|   0.07266658984246778   0.15589590626950392   0.8473239749681973   0.09120659782029286   0.8967577549635228   0.0   0.0   0.0   0.0   
6|   -0.039336974297272766   0.9016385736644148   0.43262071765637694   1.1125176690221803   0.768253031155888   1.138164098810563   0.0   0.0   0.0   
7|   0.5355801846426934   0.1663664752428089   0.34578205869891643   0.7862465808992009   0.5455242010622685   0.8608568453856572   0.829532989969456   0.0   0.0   
8|   0.8458333909516619   0.024559346642701103   0.3282700085960759   0.8918283358684784   -0.013458714498497065   1.105122173080105   0.7882142842439279   0.7183361481414366   0.0   
Nombre NaN :0.0

Le parcours dans le 2ème cas est complet pour la matrice, ce qui n'est pas le cas dans m=n-1
fredericmazue

Quote:
Nous avons donc un écart de code avec toi.

Qu'est-ce que tu racontes ?

d'un côté (code d'origine)

   //  n = nombre de points 
   //  m = dimension de l'espace 
   static int n =  100; 
   static int m = n-1;

et mon code

    final int NB_POINTS = 100;
    //  n = nombre de points
    //  m = dimension de l'espace
    private int n = NB_POINTS;
    
    private int m = NB_POINTS - 1;

C'est bien la même chose non ? :lol:
C'est juste que mon code est plus lisible à mon goût.

Entre outre mon code marche très bien parce qu'avec "une matrice qui va bien" il restitue convenablement les coordonnées des points comme je l'ai dit dans un post précédent

Par contre quand j'ai dit dans mon post précédent ne pas obtenir de NaN avec la dernière matrice de Itchris, ce n'était pas avec mon code, mais avec le sien, celui qu'il a posté en tout début. :twisted:
Et je maintiens qu'il n'est pas exclu que ces différences viennent de JVM différentes sous des OS différents. Là je suis sous Windows. Peut être Itchris est sous Linux. Les différences de calculs entre JVM avec des (très) petits nombres ça c'est déjà vu. Pourquoi est-ce que je parle de petits nombres ? Parce que si on a vu le problème de la division par zéro. En informatique, il faut se préoccuper de la division par "presque zéro". Tu as contasté qu'avec des "grand nombres" dans la matrice ça allait mieux, et je l'ai constaté aussi. Avec des grands nombres sans coordonnés nulles le code de Itchris (ou le mien puisque c'est le même ré-écrit) fonctionne très bien. Par exemple pour cette matrice

    public double[][] coordonneesInitiales =
    {
        { 0.0, 0.0, 0.0 } ,
        { 9.0, 0.0, 0.0 }, 
        { 4.0, 5.0, 0.0 },
        { 7.0, 1.0, 3.0} 
    };

Par contre avec de très petits nombres, donc des divisions par presque zéro, rien n'est garanti. d'ailleurs quand j'aurais une minute, je vais essayer exactement les mêmes calculs que ceux faits jusque là avec une autre version de JVM et sous Linux, juste pour voir :)

fredericmazue

Je viens de faire un essai avec la même version de JVM sous Linux et sous exactement la même architecture matérielle et je n'ai pas vu de différence dans les résultats. MAIS le code de Itchris avec sa dernière matrice ne me donne pas non plus de NaN....

willbback

fredericmazue wrote:

Qu'est-ce que tu racontes ?

d'un côté (code d'origine)

   //  n = nombre de points 
   //  m = dimension de l'espace 
   static int n =  100; 
   static int m = n-1;

et mon code

    final int NB_POINTS = 100;
    //  n = nombre de points
    //  m = dimension de l'espace
    private int n = NB_POINTS;
    
    private int m = NB_POINTS - 1;

C'est par rapport au code de ltchris. La matrice qu'il présente dans ses résultats est carré et non plus n*m. Je pense donc que nous (toi et moi) n'avons plus la dernière version du code sur lequel il travail . C'est juste une constatation tirée de son dernier poste.
Et effectivement avec les valeurs postées par ltchris, je n'ai pas de NaN non plus. Je suis donc en parfait accord avec tes dires :wink:

J'essaye de reprendre les formules qu'il a posté précédement mais j'ai quelques problèmes d'interprétation. Le calcul de la distance est fait en colonne dans la matrice, les calculs suivants sont fait en ligne. Je suis donc un peut surpris de la progession "cahotique" des indices. Mais ce n'est qu'une intuition mal placée de développeur.

Par exemple la norme est calculée par norme= carre(distances[0][i]), ce qui indique une variation de colonne dans la matrice, les coordonnées sont calculés par coordonnees[i][p] = norme - carre(distances[p + 1][i]) carre(distances[p + 1][0]), qui effectue une variation mélangée colonne et ligne. Mon instinct me dicte plutôt une ligne du type
coordonnees[p][i] = norme - carre(distances[p + 1][i]) + carre(distances[p + 1][0]). Avec un inquiétude sur p + 1. Lors d'une boucle sur p, il est rare d'essayé d'aller voir l'item suivant. Bref, je me pose bien des questions.....
Ou alors, il essaye d'inversé la matrice, et là le parcours n'est pas bon non plus. Mais vu que je ne comprends toujours pas la finalité du "bidule", j'ai du mal.
Il serait peut-être temps de poser le problème en terme plus simple, sans grande théorie mathématique, du genre : je calcul la distante entre le début de la colonne de la matrice initiale jusqu'à un point donné avec la formule ...

fredericmazue

Quote:
Et effectivement avec les valeurs postées par ltchris, je n'ai pas de NaN non plus. Je suis donc en parfait accord avec tes dires

Ah ok, je ne t'avais pas bien lu :oops:
Alors pour cette histoire de NaN ici et pas là et aussi ce que je dis à propos des JVM: Je sais bien que j'ai comme une petite tendance à troller sur Java, une sorte de réflexe quoi, et certains peuvent penser que du coup je délire un peu.
J'invite ceux qui penseraient ça à lire l'article "How Java’s Floating-Point Hurts Everyone Everywhere" que l'on peut trouver à http://www.cs.berkeley.edu/~wkahan/JAVAhurt.pdf
Et l'article n'a pas été écrit pas des truffes :)

Arf... Java :lol:

willbback
Les bigDecimal (ou maux)

Je viens de passer le code de double vers BigDecimal et................. Nous avons toujours des problèmes de NaN. Bref, quand les nombres sont trop petits y a un gros problème....

ltchris

et ben vous chomez pas le weekend!
bonjour,

Ma matrice effectivement n'affiche pas de NaN, car en fait je me suis melangé, je vous en ai donné une qui donne du NaN si on calcul avec peu de precision. Oubliez cette matrice.

Concernant la dimension m = n-1 c'est bien ca qu'il faut avoir.
La matrice de position de depart peut avoir la dimension qu'on vut, t'en que y'a n lignes c'est bon. Il faut juste regler la boucle for dans le calcul de distance pour ne pas aller trop loin dans cette matrice position.
Ce qui ne changera jamais c'est que la matrice position finale est n*n-1, car c'est n points en dimension n-1.

concernant le code qu'on utilise, je me suis mis au dernier qui a été posté sur ce post, ca ne change rien de toute facon car il fait la même chose que le mien, mais est mieux ecrit.
Je l'ai juste modifié au niveau des affichages qu'il effectue.
En gros j'ai deux entier de choix : un pour selectionner si on veut donner la matrice ou si on la veut aleatoire
et l'autre pour dire quelles types d'informations on affiche.
Ah oui puis j'y ai rajouté un test de division par zero. Qui nous permet de verifier qu'on a du NaN sans avoir de division par zero. ( a verifier en tirant une matrice aleatoire)

voila ce que ca donne :

class Geotest {
    final int NB_POINTS = 100;
    // type Matrice de départ :  0 = c'est nous qui la créons ;  1 = aléatoire
    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    */  
    public int typeAffichage = 0;
    
    
    
    //  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()*10);
    				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]);
                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] = (float)Math.sqrt(norme - sumSQR);
            // 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++;
                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();
        }
       
    } 
   
    public static void main(String[] args) {
        Geotest test = new Geotest();
        test.executeTest();
    }
} 
fredericmazue

Quote:
Qui nous permet de verifier qu'on a du NaN sans avoir de division par zero.

Et par presque zéro ?
ltchris

Math.abs(coordonnees[i][p])<0.0000001

c'est le test que j'effectue
donc presque zero est parfaitement englobé dans ce test

ltchris

oups !
mon test etait mal placé, il faut tester le calcul de la dernière coordonnée. J'edit mon code posté juste avant!

edit : hop c fait!

toujours pas de "presque zero"

fredericmazue

Hum... On a pas la même notion du presque. .0000001 c'est gros ça ;)
Et puis moi surtout j'aurais testé coordonnees[p + 1][p] et juste avant de faire la division

fredericmazue

Laissons tomber les "petits"
Je viens de faire quelues essais aves des matrices contenant des nombres microscopiques et je n'ai pas vu de problème.

fredericmazue

Je dirais même plus, avec des matrices sans zéros mal placés, je n'arrive pas à avoir de Nan.

ltchris

Ben justement 0.000001 c'est gros, et meme avec ca, je rentre jamais dans le if. donc on est vraiment loin du "presque zero" a chaque fois.

en fait je me suis trompé au debut d'ecrire le code, le vrai test c'est (j'ai édité le gros code depuis):
if(Math.abs(coordonnees[i-1])<0.0000001){
Car les divisions se font tjs avec ces élèments. Ca ne sert a rien de tester autre chose.

Pour resumer notre probleme :

- on a parfois des nombres petites, donc il faut faire un test de "nombre petit" : j'en fait mon affaire
- on a du naN meme quand y'a pas de division petite.

statistiquement sur des matrices aleatoires le NaN est plus proche quand on passe de double à float (testé), et si on prend des nombres plus grand dans la matrice aléatoire (testé).

y'a donc bien une idée de precision et de divergence, mais ce n'est pas du à de la division par zero dans la majorité des cas !

Le million d'euros[i]congratulations est toujours en jeu ...

ltchris

fredericmazue wrote:
Je dirais même plus, avec des matrices sans zéros mal placés, je n'arrive pas à avoir de Nan.

Ca j'avais remaqué, mais la question est :
n'as-t'on pas du tout de NaN ? ou alors se produit'il trop loin pour qu'on l'observe ?

fredericmazue

Quote:
Ca ne sert a rien de tester autre chose

Ok

Quote:
sur des matrices aleatoires le NaN est plus proche quand on passe de float à double (testé),

Qu'est-ce que quoi comment ?? :shock:

Tu veux dire que quand par exemple tu as des nombre qui se balladent de E-37 à E-38 (passage de float à double si ma mémoire est bonne) tu as du NaN ?
Bon je n'ai peut être pas compris ce que tu veux dire, mais ça ne semble pas faire de sens ce que tu dis, parce que les nombres sont tous doubles dans ton code et normalement la JVM va les coder sur 8 octets tout le temps. Et non pas une fois 4 une fois 8. C'est du Java, mais quand même ;)

Tu aurais une matrice toute prête qu'il n'y aurait qu'à copier-coller dans le code ? Je voudrais bien voir ça de mes petits yeux porcins je dois dire.

Pages