From f75a9a50a90be33102d7a3b59d1c0ac92fd526c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Boull=C3=A9?= Date: Thu, 21 Dec 2023 14:19:41 +0100 Subject: [PATCH] fix instability in coclustering optimization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Les resultats d'optimisation du coclustering sont instables d'un OS à l'autre Non critique pour les utilisateurs, mais critique pour la reproductibilite des jeux de test, dans tous les cas de cocluseing et d'analyse bivariee. Report du commit "fix instability in coclustering optimization" dans la branche V11 Impact dans fonction KWDGMPartMergeCompare de KWDataGridMerger.cpp - stabilisation de la methode de comparaison pour ordonner les fusions lors de l'optimisation d'un coclustering --- .../KWDataPreparation/KWDataGridMerger.cpp | 60 ++++++++++++++++--- 1 file changed, 52 insertions(+), 8 deletions(-) diff --git a/src/Learning/KWDataPreparation/KWDataGridMerger.cpp b/src/Learning/KWDataPreparation/KWDataGridMerger.cpp index 6dc5af9d1..0ebea710b 100644 --- a/src/Learning/KWDataPreparation/KWDataGridMerger.cpp +++ b/src/Learning/KWDataPreparation/KWDataGridMerger.cpp @@ -1959,13 +1959,19 @@ const ALString KWDGMPartMerge::GetObjectLabel() const int KWDGMPartMergeCompare(const void* elem1, const void* elem2) { - // On utilise Epsilon=0 en escomptant le resultat du Diff est reproductible si les operandes sont les memes + // On utilise Epsilon=0 en escomptant que le resultat du Diff est reproductible si les operandes sont les memes // Pour Epsilon > 0, on court le risque d'avoir diff(PM1,PM2) < Epsilon et diff(PM2,PM3) < Epsilon, // mais diff(PM1,PM3) >= Epsilon (ce bug (avec consequence desatreuse dans une SortedList) est deja arrive) const double dEpsilon = 0; + int nCompare; KWDGMPartMerge* partMerge1; KWDGMPartMerge* partMerge2; double dDiff; + ALString sFirstPartLabel1; + ALString sSecondPartLabel1; + ALString sFirstPartLabel2; + ALString sSecondPartLabel2; + ALString sSwapPartLabel; require(elem1 != NULL); require(elem2 != NULL); @@ -1977,15 +1983,53 @@ int KWDGMPartMergeCompare(const void* elem1, const void* elem2) assert(partMerge2->Check()); // Calcul de la difference + nCompare = 0; dDiff = partMerge1->GetMergeCost() - partMerge2->GetMergeCost(); if (dDiff > dEpsilon) - return 1; + nCompare = 1; else if (dDiff < -dEpsilon) - return -1; - // Si egalite, on renvoie 0 + nCompare = -1; + + // Si egalite, on compare sur les nom de des attributs, puis sur celui des parties // On ne peut se baser sur le nombre de cellules des fusions, qui varie a cout egal, - // ce qui empeche les optimisation poussees visant a ne reevaluer que les - // fusions impactees - else - return 0; + // ce qui empeche les optimisation poussees visant a ne reevaluer que les fusions impactees + if (nCompare == 0) + { + // On se base d'abord sur le libelle de l'attribut + // (on pourrait avoir des attribut differents ayant meme libelle de partie) + assert(partMerge1->GetPart1()->GetAttribute() == partMerge1->GetPart2()->GetAttribute()); + assert(partMerge2->GetPart1()->GetAttribute() == partMerge2->GetPart2()->GetAttribute()); + nCompare = partMerge1->GetPart1()->GetAttribute()->GetAttributeName().Compare( + partMerge2->GetPart1()->GetAttribute()->GetAttributeName()); + + // On se base ensuite sur le libelle du plus petit des deux libelles de partie + if (nCompare == 0) + { + // Collecte des libelles de parties pour le Merge 1 + sFirstPartLabel1 = partMerge1->GetPart1()->GetObjectLabel(); + sSecondPartLabel1 = partMerge1->GetPart2()->GetObjectLabel(); + if (sFirstPartLabel1 > sSecondPartLabel1) + { + sSwapPartLabel = sSecondPartLabel1; + sSecondPartLabel1 = sFirstPartLabel1; + sFirstPartLabel1 = sSwapPartLabel; + } + + // Collecte des libelles de parties pour le Merge 2 + sFirstPartLabel2 = partMerge2->GetPart1()->GetObjectLabel(); + sSecondPartLabel2 = partMerge2->GetPart2()->GetObjectLabel(); + if (sFirstPartLabel2 > sSecondPartLabel2) + { + sSwapPartLabel = sSecondPartLabel2; + sSecondPartLabel2 = sFirstPartLabel2; + sFirstPartLabel2 = sSwapPartLabel; + } + + // Comparaison des libelles + nCompare = sFirstPartLabel1.Compare(sFirstPartLabel2); + if (nCompare == 0) + nCompare = sSecondPartLabel1.Compare(sSecondPartLabel2); + } + } + return nCompare; }