228for (
int fileIndex = 0;
235 string inputFileName =
239 string instanceStem =
240 Path.GetFileNameWithoutExtension(
248 string mathematicalModelPath =
251 $
"{instanceStem}.mathematical-model.txt");
253 string solutionCheckReportPath =
256 $
"{instanceStem}.solution-check.txt");
264 $
"INSTANCE {fileIndex + 1}/{inputFiles.Length}");
281 "1/7 - Lecture de l'instance...");
283 LotSizingInstance instance =
284 LotSizingInstanceXmlSerializer.DeserializeFromFile(
288 $
" OK - {instance.Name} " +
289 $
"({instance.PlanningHorizon} périodes)");
292 "2/7 - Construction du modèle mathématique de diagnostic...");
294 MathematicalModelFormulationRegistry formulationRegistry =
295 StandardLotSizingFormulationRegistryFactory.Create(
298 var modelBuildOptions =
299 new MathematicalModelBuildOptions
301 RequestedFormulationId =
302 StandardLotSizingFormulation.StandardFormulationId,
307 ValidateGeneratedModel =
310 CloneGeneratedModel =
314 var modelBuildService =
315 new MathematicalModelBuildService();
317 MathematicalModelBuildResult modelBuildResult =
318 await modelBuildService.BuildAsync(
323 if (!modelBuildResult.IsSuccessful ||
324 modelBuildResult.Model is
null)
326 throw new InvalidOperationException(
327 "Impossible de construire le modèle mathématique. " +
330 modelBuildResult.Diagnostics));
333 MathematicalModel mathematicalModel =
334 modelBuildResult.Model;
338 mathematicalModelPath);
341 $
" OK - {mathematicalModel.VariableCount} variables, " +
342 $
"{mathematicalModel.EnabledConstraintCount} contraintes.");
345 $
" Dump : {mathematicalModelPath}");
348 $
"3/7 - Solveur demandé : {solverDisplayName}.");
351 "4/7 - Résolution...");
361 StandardLotSizingFormulation.StandardFormulationId,
364 $
"{solverDisplayName} - {instanceStem}",
367 new SolverParameters()
370 SolverRunResult runResult =
371 await
bootstrap.SolverService.SolveAsync(
376 $
"{runResult.SolverName} {runResult.SolverVersion}");
379 $
" Statut : {runResult.TerminationReason}");
382 $
" Durée : {runResult.ElapsedSeconds:F3} s");
384 if (runResult.ObjectiveValue.HasValue)
387 $
" Objectif solveur : " +
388 $
"{runResult.ObjectiveValue.Value:G17}");
391 if (runResult.RecomputedObjectiveValue.HasValue)
394 $
" Objectif recalculé par Solver : " +
395 $
"{runResult.RecomputedObjectiveValue.Value:G17}");
398 $
" Vérification interne Solver : " +
399 $
"{runResult.ObjectiveVerificationStatus}");
401 if (runResult.ObjectiveDifference.HasValue)
404 $
" Écart interne Solver : " +
405 $
"{runResult.ObjectiveDifference.Value:G17}");
409 if (!runResult.HasSolution ||
410 runResult.Solution is
null)
413 runResult.Diagnostics.Count == 0
414 ?
"Aucun diagnostic supplémentaire."
417 runResult.Diagnostics);
419 throw new InvalidOperationException(
420 "Aucune solution exploitable n'a été produite. " +
425 "5/7 - Préparation du résultat candidat...");
428 $
"solver-{runResult.RunId}";
431 LotSizingInstanceFactory.ComputeSupplyChainFingerprint(
432 instance.SupplyChain);
439 $
"{runResult.SolverName} solution",
447 ReportedObjectiveValue =
448 runResult.ObjectiveValue,
454 runResult.TerminationReason ==
455 SolverTerminationReason.Optimal
456 ? OptimalityStatus.ProvenOptimal
457 : OptimalityStatus.NoProof,
463 string.IsNullOrWhiteSpace(
464 runResult.SolverVersion)
465 ? runResult.SolverName
466 : $
"{runResult.SolverName} " +
467 $
"{runResult.SolverVersion}",
470 runResult.CompletedAtUtc ??
476 SupplyChainFingerprint =
480 $
"Termination reason: " +
481 $
"{runResult.TerminationReason}. " +
483 $
"{runResult.ElapsedSeconds:F6} s."
487 $
" OK - candidat {knownResult.ResultId} préparé.");
490 "6/7 - Vérification indépendante de la solution...");
492 LotSizingSolutionVerificationResult verification =
499 SolutionCheckResult checkResult =
500 verification.CheckResult;
506 $
"{inputFileName} / {knownResult.ResultId}",
510 await File.WriteAllTextAsync(
511 solutionCheckReportPath,
514 encoderShouldEmitUTF8Identifier:
false));
518 solutionCheckReportPath);
520 if (!verification.IsValid)
527 Console.Error.WriteLine(
528 " REJET - la solution ne satisfait pas le checker indépendant.");
530 Console.Error.WriteLine(
531 " L'instance n'est pas écrite dans le répertoire résolu " +
532 "et ce résultat n'est pas enregistré comme KnownResult.");
539 instance.AddKnownResult(
542 if (runResult.TerminationReason ==
543 SolverTerminationReason.Optimal ||
544 !instance.HasBestKnownResultId)
546 instance.SetBestKnownResult(
551 " ACCEPTÉ - résultat vérifié et ajouté à l'instance.");
554 "7/7 - Écriture de l'instance résolue...");
556 LotSizingInstanceXmlSerializer.SerializeToFile(
559 validateBeforeSerialization:
true,
560 validateCurrentFingerprint:
true,
564 $
" OK - {outputPath}");
568 catch (System.Exception exception)
575 Console.Error.WriteLine();
576 Console.Error.WriteLine(
577 $
"ÉCHEC TECHNIQUE pour {inputFileName}");
579 Console.Error.WriteLine(
750 SolutionCheckResult result,
754 $
" Checker : {(result.IsValid ? "VALID
" : "INVALID
")}");
757 $
" Structure : {FormatStage(result.StructuralCheckCompleted, result.IsStructurallyValid)}");
760 $
" Domaines : {FormatStage(result.VariableDomainCheckCompleted, result.AreVariableDomainsValid)}");
763 $
" Faisable : {FormatStage(result.FeasibilityCheckCompleted, result.IsFeasible)}");
766 $
" Objectif : {FormatStage(result.ObjectiveCheckCompleted, result.IsObjectiveConsistent)}");
768 if (result.FeasibilityCheckCompleted)
771 $
" Contraintes violées : {result.ViolatedConstraintCount}");
774 $
" Violation maximale : {result.MaximumConstraintViolation:G17}");
777 if (result.ReportedObjectiveValue.HasValue)
780 $
" Objectif reporté solveur : {result.ReportedObjectiveValue.Value:G17}");
783 if (result.RecomputedObjectiveValue.HasValue)
786 $
" Objectif checker : {result.RecomputedObjectiveValue.Value:G17}");
789 if (result.ObjectiveDifference.HasValue)
792 $
" Écart objectif : {result.ObjectiveDifference.Value:G17}");
795 if (result.ObjectiveComparisonTolerance.HasValue)
798 $
" Tolérance comparaison : {result.ObjectiveComparisonTolerance.Value:G17}");
805 SolutionCheckSeverity.Error);
811 SolutionCheckSeverity.Warning);
814 $
" Diagnostics : {errorCount} erreur(s), {warningCount} avertissement(s)");
817 $
" Rapport : {reportPath}");
Writes a complete human-readable representation of a solver-independent mathematical model.
static void Write(MathematicalModel model, string filePath)
Writes the supplied mathematical model to a text file.