Skip to content

Commit

Permalink
Implement Khiops piloting using a json parameter file
Browse files Browse the repository at this point in the history
Reference
- issue #230  Extending Khiops entries with a lightweight json structure for scenarios #230
- #230
  - cette issue contient les specification detaillees de la fonctionnalité, donc on pourra
    extraire la documentation
  - cf. commentaire "Extension du pilotage de Khiops via les scénarios"
  - #230 (comment)

Choix d'implementation principaux
- le fichier de parametre json est lu et traite en entier de facon prealable, avec une taille limitee
- le fichier de commande est traite en flux, ce qui permet de n'avoir aucune limite de taille
- toute ligne de commande peut etre commentee, y compris les lignes du langage de pilotage de type IF ou LOOP
- les lignes d'un fichier de commande template n'ont pas besoin de se terminer par un commentaire
- toute __key__ du fichier de commande doit se trouver dans le fichier json
- toute key du fichier json doit etre utilise dans le fichier de commande
- les __key__ de parametrage json ne peuvent concerner que la partie parametrage utilisateur d'une valeur
- toute erreur ou incoherence dans les fichiers de commande et de parametrage json provoquent une erreur fatale

CommandFile
- methodes publiques
  - ReadInputCommand: refactoring et simplification
  - ReadWriteCommandFiles: pour ecrire le scenario en sortie sans rejouer les commandes
- methodes privees principales de parsing des scenario et de leur langage
  - ResetParser
  - RecodeCurrentLineUsingJsonParameters
  - ParseInputCommand: analyse syntaxique des lignes d'un fichier de commande en entree
  - TokenizeInputCommand
  - GetFirstInputToken
- variables de travail du parser
  - prefixees par parser (ex: nParserState, sParserBlockKey, nParserLineIndex...)
  - maintenues le temps d'une session d'analyse, pour gerer le parser de scenario en flux
- contraintes
  - nMaxLineLength = 500: longueur max d'une ligne de fichier de commande
  - nLoopMaxLineNumber = 1000: Taille max d'un bloc d'instruction IF ou LOOP d'un fichier de commande
- constantes: renommees et etendues pour harmonisation
  - sCommentPrefix
  - sJsonKeyDelimiter
  - sByteJsonKeyPrefix
  - ...

JsonLex.lex
- STRINGERROR: variante de STRINGVALUE dans le cas d'erreur d'encodage utf8
JsonYac.yac
- regles impliquant STRINGERROR pour avoir des erreurs interpretable en cas de STRINGERROR

UIObject: prise en compte de l'option -O, pour les scenarios en sortie sans rejouer les commandes
- ParseMainParameters
- CheckCommandLineOptions

TextService:
- parametrage avance de la conversion de lencodage Json vers un encodage C pas necessairemernet Utf8
  pour le cas des rapport Khiops
  - Set|GetForceUnicodeToAnsi
  - Set|GetForceUtf8ToAnsi
- modifie le comportement de la methode JsonToCString utilisee par le parser de Json
- utilise uniquement dans CCCoclusteringReport

LearningTestTool
- kht_test.py
  - --nop-output-scenario: "create an output scenario nop_output_test.prm in results dir, without replaying commands"
- _kht_families
  - ajout de la famille JsonParameters

Ajout de tests unitaires: test\UnitTests\Norm\results.ref\base_TextService.txt

Ajout de test CI/CD: test\LearningTest\TestKhiops\Standard\JsonSpliceJunction

Batterie de tests LearningTest\TestKhiops\JsonParameters
- une petite cinquantaine de test, les trois-quart concernant la detection des erreurs
  • Loading branch information
marcboulle committed Oct 29, 2024
1 parent 2959070 commit d47673a
Show file tree
Hide file tree
Showing 27 changed files with 2,870 additions and 524 deletions.
3 changes: 2 additions & 1 deletion src/Learning/MODL/MODL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,12 @@ int main(int argc, char** argv)

// Activation de la gestion des signaux via des erreurs, pour afficher des messages d'erreur explicites
// A potentiellement commenter sur certains IDE lors des phases de debuggage
Global::ActivateSignalErrorManagement();
//Global::ActivateSignalErrorManagement();

// Choix du repertoire de lancement pour le debugage sous Windows (a commenter apres fin du debug)
// SetWindowsDebugDir("Standard", "IrisLight");
// SetWindowsDebugDir("Standard", "IrisU2D");
// SetWindowsDebugDir("JsonParameters", "JsonSpliceJunctionAll");

// Parametrage des logs memoires depuis les variables d'environnement, pris en compte dans KWLearningProject
// KhiopsMemStatsLogFileName, KhiopsMemStatsLogFrequency, KhiopsMemStatsLogToCollect
Expand Down
37 changes: 24 additions & 13 deletions src/Learning/MODL_Coclustering/CCCoclusteringReport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ boolean CCCoclusteringReport::ReadGenericReport(const ALString& sFileName, CCHie
boolean bOk;
int nFileFormat;
ALString sKhiopsEncoding;
boolean bForceAnsi;
boolean bForceUnicodeToAnsi;
boolean bForceUtf8ToAnsi;

require(sFileName != "");
require(coclusteringDataGrid != NULL);
Expand All @@ -69,27 +70,27 @@ boolean CCCoclusteringReport::ReadGenericReport(const ALString& sFileName, CCHie
// ansi
if (sKhiopsEncoding == "")
{
bForceAnsi = false;
bForceUnicodeToAnsi = false;
AddWarning("The \"khiops_encoding\" field is missing in the read coclustering file. "
"The coclustering file is deprecated, and may raise encoding problems "
"in case of mixed ansi and utf8 chars "
": see the Khiops guide for more information.");
}
else if (sKhiopsEncoding == "ascii" or sKhiopsEncoding == "utf8")
bForceAnsi = false;
bForceUnicodeToAnsi = false;
else if (sKhiopsEncoding == "ansi" or sKhiopsEncoding == "mixed_ansi_utf8")
bForceAnsi = true;
bForceUnicodeToAnsi = true;
else if (sKhiopsEncoding == "colliding_ansi_utf8")
{
bForceAnsi = false;
bForceUnicodeToAnsi = true;
AddWarning("The \"khiops_encoding\" field is \"" + sKhiopsEncoding +
"\" in the read coclustering file. "
"This may raise encoding problems if the file has been modified outside of Khiops "
": see the Khiops guide for more information.");
}
else
{
bForceAnsi = false;
bForceUnicodeToAnsi = false;
AddWarning(
"The value of the \"khiops_encoding\" field is \"" + sKhiopsEncoding +
"\" in the read coclustering file. "
Expand All @@ -98,10 +99,15 @@ boolean CCCoclusteringReport::ReadGenericReport(const ALString& sFileName, CCHie
": see the Khiops guide for more information.");
}

// Parametrage de l'encodage ansi pour les caracteres Utf8
bForceUtf8ToAnsi = sKhiopsEncoding == "ansi" or sKhiopsEncoding == "mixed_ansi_utf8";

// Lecture du fichier en parametrant le json tokeniser correctement
JSONTokenizer::SetForceAnsi(bForceAnsi);
JSONTokenizer::SetForceUnicodeToAnsi(bForceUnicodeToAnsi);
JSONTokenizer::SetForceUtf8ToAnsi(bForceUtf8ToAnsi);
bOk = ReadJSONReport(sFileName, coclusteringDataGrid);
JSONTokenizer::SetForceAnsi(false);
JSONTokenizer::SetForceUnicodeToAnsi(false);
JSONTokenizer::SetForceUtf8ToAnsi(false);
}
return bOk;
}
Expand All @@ -116,7 +122,8 @@ boolean CCCoclusteringReport::ReadGenericReportHeader(const ALString& sFileName,
boolean bOk;
int nFileFormat;
ALString sKhiopsEncoding;
boolean bForceAnsi;
boolean bForceUnicodeToAnsi;
boolean bForceUtf8ToAnsi;

require(sFileName != "");
require(coclusteringDataGrid != NULL);
Expand All @@ -134,12 +141,16 @@ boolean CCCoclusteringReport::ReadGenericReportHeader(const ALString& sFileName,
{
// Analyse du type d'encodage pour determiner si on doit recoder les caracteres utf8 du fichier json en
// ansi Pas de message pour cette lecture rapide
bForceAnsi = (sKhiopsEncoding == "ansi" or sKhiopsEncoding == "mixed_ansi_utf8");
bForceUnicodeToAnsi = (sKhiopsEncoding == "ansi" or sKhiopsEncoding == "mixed_ansi_utf8" or
sKhiopsEncoding == "colliding_ansi_utf8");
bForceUtf8ToAnsi = (sKhiopsEncoding == "ansi" or sKhiopsEncoding == "mixed_ansi_utf8");

// Lecture de l'entete du fichier en parametrant le json tokeniser correctement
JSONTokenizer::SetForceAnsi(bForceAnsi);
JSONTokenizer::SetForceUnicodeToAnsi(bForceUnicodeToAnsi);
JSONTokenizer::SetForceUtf8ToAnsi(bForceUtf8ToAnsi);
bOk = ReadJSONReportHeader(sFileName, coclusteringDataGrid, nInstanceNumber, nCellNumber);
JSONTokenizer::SetForceAnsi(false);
JSONTokenizer::SetForceUnicodeToAnsi(false);
JSONTokenizer::SetForceUtf8ToAnsi(false);
}
return bOk;
}
Expand Down Expand Up @@ -371,7 +382,7 @@ int CCCoclusteringReport::DetectFileFormatAndEncoding(const ALString& sFileName,

// Message d'erreur si pas de format reconnu
if (nFileFormat == None)
AddError("Format of file " + sFileName + " should either " +
AddError("Format of file " + sFileName + " should be either " +
CCCoclusteringReport::GetJSONReportSuffix() + " or " +
CCCoclusteringReport::GetKhcReportSuffix());

Expand Down
6 changes: 3 additions & 3 deletions src/Learning/MODL_Coclustering/MODL_Coclustering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ int main(int argc, char** argv)
Global::ActivateSignalErrorManagement();

// Choix du repertoire de lancement pour le debugage sous Windows (a commenter apres fin du debug)
//SetWindowsDebugDir("y_CoclusteringIV_Standard", "IrisLight");
//SetWindowsDebugDir("y_CoclusteringIV_Standard", "Iris");
//SetWindowsDebugDir("Standard", "Iris");
// SetWindowsDebugDir("y_CoclusteringIV_Standard", "IrisLight");
// SetWindowsDebugDir("y_CoclusteringIV_Standard", "Iris");
// SetWindowsDebugDir("Standard", "Iris");

// Point d'arret sur l'allocation d'un bloc memoire
// MemSetAllocIndexExit(30406);
Expand Down
Loading

0 comments on commit d47673a

Please sign in to comment.