/// <inheritdoc/> public void Run(LoadedProblemGeneratorInput input) { #region Prepare readable writers // Prepare the name of readable output files var nameOfReadableFiles = $"{_settings.OutputFilePrefix}{input.Id}.{_settings.FileExtension}"; // If we should write readable output without proofs using var readableOutputWithoutProofsWriter = _settings.WriteReadableOutputWithoutProofs // Prepare the writer for it ? new StreamWriter(new FileStream(Path.Combine(_settings.ReadableOutputWithoutProofsFolder, nameOfReadableFiles), FileMode.Create, FileAccess.Write, FileShare.Read)) // Otherwise null : null; // If we should write readable output with proofs using var readableOutputWithProofsWriter = _settings.WriteReadableOutputWithProofs // Prepare the writer for it ? new StreamWriter(new FileStream(Path.Combine(_settings.ReadableOutputWithProofsFolder, nameOfReadableFiles), FileMode.Create, FileAccess.Write, FileShare.Read)) // Otherwise null : null; // Local function that writes a line to both readable writers, if they are available void WriteLineToBothReadableWriters(string line = "") { // Write to the standard writer readableOutputWithoutProofsWriter?.WriteLine(line); // Write to the writer with proofs readableOutputWithProofsWriter?.WriteLine(line); } #endregion #region Prepare JSON writer // Prepare the name of the JSON output file var jsonOutputFileName = $"{_settings.OutputFilePrefix}{input.Id}.json"; // If we should write the JSON output var jsonOutputWriter = _settings.WriteJsonOutput // Prepare the writer for it ? _factory.Create(Path.Combine(_settings.JsonOutputFolder, jsonOutputFileName)) // Otherwise null : null; #endregion // Call the generation algorithm var(initialTheorems, outputs) = _generator.Generate(input); #region Write constructions // Write the constructions header WriteLineToBothReadableWriters($"Constructions:\n"); // Write all of them input.Constructions.ForEach(construction => WriteLineToBothReadableWriters($" - {construction}")); // An empty line WriteLineToBothReadableWriters(); #endregion #region Write the initial configuration // Prepare the formatter for the initial configuration var initialFormatter = new OutputFormatter(input.InitialConfiguration.AllObjects); // Write it WriteLineToBothReadableWriters("Initial configuration:\n"); WriteLineToBothReadableWriters(initialFormatter.FormatConfiguration(input.InitialConfiguration)); // Write its theorems, if there are any if (initialTheorems.Any()) { WriteLineToBothReadableWriters("\nTheorems:\n"); WriteLineToBothReadableWriters(InitialTheoremsToString(initialFormatter, initialTheorems)); } #endregion #region Write other setup // Write iterations WriteLineToBothReadableWriters($"\nIterations: {input.NumberOfIterations}"); // Write maximal numbers of objects of particular types WriteLineToBothReadableWriters($"{input.MaximalNumbersOfObjectsToAdd.Select(pair => $"MaximalNumberOf{pair.Key}s: {pair.Value}").ToJoinedString("\n")}\n"); // Write whether we're excluding symmetry WriteLineToBothReadableWriters($"SymmetryGenerationMode: {input.SymmetryGenerationMode}"); #endregion // Write results header WriteLineToBothReadableWriters($"Results:"); // Log that we've started Log.Information("Generation has started."); #region Tracking variables // Prepare the number of generated configurations var numberOfGeneratedConfigurations = 0; // Prepare the total number of interesting theorems var numberOfInterestingTheorems = 0; // Prepare the total number of configurations with an interesting theorem var numberOfConfigurationsWithInterestingTheorem = 0; #endregion #region Start stopwatch // Prepare a stopwatch to measure the execution time var stopwatch = new Stopwatch(); // Start it stopwatch.Start(); #endregion // Begin writing of the JSON output file jsonOutputWriter?.BeginWriting(); // Prepare the variable indicating whether we're writing best theorems, // which happens when we want to write them either readable or JSON form var writeBestTheorems = _settings.WriteReadableBestTheorems || _settings.WriteJsonBestTheorems; // Prepare the variable indicating the last time we rewrote the best theorems DateTimeOffset?lastTimeBestTheoremsWereRewritten = null; #region Generation loop // Run the generation foreach (var generatorOutput in outputs) { // Mark the configuration numberOfGeneratedConfigurations++; #region Logging progress // Find out if we should log progress and if yes, do it if (_settings.LogProgress && numberOfGeneratedConfigurations % _settings.ProgressLoggingFrequency == 0) { // Calculate how long on average it takes to generate 'one batch' according to the progress frequency var averageTime = (double)stopwatch.ElapsedMilliseconds / numberOfGeneratedConfigurations * _settings.ProgressLoggingFrequency; // Based on whether we're creating best theorems, write how many of them we have var bestTheoremString = $"{(writeBestTheorems ? $" ({_resolver.AllSorters.Select(pair => pair.sorter.BestTheorems.Count()).Sum()} after global merge)" : "")}"; // Log what we have Log.Information("Generated configurations: {configurations}, after {time} ms, {frequency} in {averageTime:F2} ms on average, with {theorems} theorems{bestTheorems} " + "in {allConfigurations} configurations", numberOfGeneratedConfigurations, stopwatch.ElapsedMilliseconds, _settings.ProgressLoggingFrequency, averageTime, numberOfInterestingTheorems, bestTheoremString, numberOfConfigurationsWithInterestingTheorem); } #endregion // Skip configurations without theorems if (generatorOutput.NewTheorems.AllObjects.Count == 0) { continue; } // Prepare the output of the analyzer GeneratedProblemAnalyzerOutputBase analyzerOutput; #region Analyzer call try { // If we should look for proofs (because we should be writing them or analyze the inner inferences) analyzerOutput = _settings.WriteInferenceRuleUsages || _settings.WriteReadableOutputWithProofs // Then call the analysis that construct them ? (GeneratedProblemAnalyzerOutputBase)_analyzer.AnalyzeWithProofConstruction(generatorOutput, input.SymmetryGenerationMode) // Otherwise we don't need them : _analyzer.AnalyzeWithoutProofConstruction(generatorOutput, input.SymmetryGenerationMode); } catch (Exception e) { // If there is any sort of problem, we should make aware of it. Log.Error(e, "There has been an exception while analyzing the configuration:\n\n{configuration}\n", // Write the problematic configuration new OutputFormatter(generatorOutput.Configuration.AllObjects).FormatConfiguration(generatorOutput.Configuration)); // And move on, we still might get something cool continue; } #endregion // Count in interesting theorems numberOfInterestingTheorems += analyzerOutput.InterestingTheorems.Count; // If this is a configuration with an interesting theorem, count it in if (analyzerOutput.InterestingTheorems.Any()) { numberOfConfigurationsWithInterestingTheorem++; } // Write JSON output jsonOutputWriter?.Write(analyzerOutput.InterestingTheorems); #region Handling best theorems // If we are supposed to be handling best theorems, do so if (writeBestTheorems) { // Take the interesting theorems var theoremsToBeJudged = analyzerOutput.InterestingTheorems // Group by type .GroupBy(rankedTheorem => rankedTheorem.Theorem.Type); try { // Prepare the set of sorters whose content changed var updatedSorterTypes = new HashSet <TheoremType>(); // Mark all interesting theorems analyzerOutput.InterestingTheorems // Grouped by type .GroupBy(rankedTheorem => rankedTheorem.Theorem.Type) // Handle each group .ForEach(group => { // Let the sorter judge the theorems _resolver.GetSorterForType(group.Key).AddTheorems(group, out var localBestTheoremChanged); // If there is any local change, mark it if (localBestTheoremChanged) { updatedSorterTypes.Add(group.Key); } }); // Find out if we should rewrite the best theorems, i.e. it must be allowed var shouldWeRewriteBestTheorems = _settings.WriteBestTheoremsContinuously // And either we haven't done it yet && (lastTimeBestTheoremsWereRewritten == null || // Or the number of seconds that have passed since the last rewrote DateTimeOffset.Now.ToUnixTimeSeconds() - lastTimeBestTheoremsWereRewritten.Value.ToUnixTimeSeconds() // Is more than our specified interval > _settings.BestTheoremsRewrittingIntervalInSeconds); // If we should write best theorems continuously and it is time to it if (shouldWeRewriteBestTheorems) { // Do it RewriteBestTheorems(updatedSorterTypes); // After the update where it was done last time lastTimeBestTheoremsWereRewritten = DateTimeOffset.Now; } } catch (Exception e) { // If there is any sort of problem, we should make aware of it. Log.Error(e, "There has been an exception while sorting theorems of the configuration:\n\n{configuration}\n", // Write the problematic configuration new OutputFormatter(generatorOutput.Configuration.AllObjects).FormatConfiguration(generatorOutput.Configuration)); } } #endregion #region Human-readable output // Prepare a formatter for the generated configuration var formatter = new OutputFormatter(generatorOutput.Configuration.AllObjects); // Prepare the header so we can measure it var header = $"Configuration {numberOfGeneratedConfigurations}"; // Construct the header with dashes var headerWithConfiguration = $"\n{new string('-', header.Length)}\n{header}\n{new string('-', header.Length)}\n\n" + // And the configuration $"{formatter.FormatConfiguration(generatorOutput.Configuration)}"; #region Writing to the writer of readable output without proofs // If there is anything interesting to write if (analyzerOutput.InterestingTheorems.Any()) { // Write the header readableOutputWithoutProofsWriter?.Write(headerWithConfiguration); // Write the analysis results without proofs readableOutputWithoutProofsWriter?.Write(AnalyzerOutputToString(formatter, analyzerOutput, writeProofs: false)); // Flush it readableOutputWithProofsWriter?.Flush(); } #endregion #region Writing to the writer of output with proofs // Write the header readableOutputWithProofsWriter?.Write(headerWithConfiguration); // Write the analysis results with proofs readableOutputWithProofsWriter?.Write(AnalyzerOutputToString(formatter, analyzerOutput, writeProofs: true)); // Flush it readableOutputWithoutProofsWriter?.Flush(); #endregion #endregion #region Inference rule usage statistics // If we should write inference rule usages if (_settings.WriteInferenceRuleUsages) { // Mark the proofs _tracker.MarkProofs(((GeneratedProblemAnalyzerOutputWithProofs)analyzerOutput).TheoremProofs.Values); // Prepare the writer using var inferenceRuleUsageWriter = new StreamWriter(new FileStream(_settings.InferenceRuleUsageFilePath, FileMode.Create, FileAccess.Write, FileShare.Read)); // Rewrite the stats file inferenceRuleUsageWriter.Write(InferenceRuleUsagesToString()); } #endregion } #endregion // Rewrite the best theorems after the generation is finished RewriteBestTheorems(); // Prepare the string explaining the state after merge var afterMergeString = $"{(writeBestTheorems ? $"{_resolver.AllSorters.Select(pair => pair.sorter.BestTheorems.Count()).Sum()}" : "-")}"; // Write end WriteLineToBothReadableWriters("\n------------------------------------------------"); WriteLineToBothReadableWriters($"Generated configurations: {numberOfGeneratedConfigurations}"); WriteLineToBothReadableWriters($"Configurations with an interesting theorem: {numberOfConfigurationsWithInterestingTheorem}"); WriteLineToBothReadableWriters($"Interesting theorems: {numberOfInterestingTheorems}"); WriteLineToBothReadableWriters($"Interesting theorems after global merge: {afterMergeString}"); // Log these stats as well Log.Information("Generated configurations: {count}", numberOfGeneratedConfigurations); Log.Information("Configurations with an interesting theorem: {count}", numberOfConfigurationsWithInterestingTheorem); Log.Information("Interesting theorems: {count}", numberOfInterestingTheorems); Log.Information("Interesting theorems after global merge: {count}", afterMergeString); Log.Information("Run-time: {time} ms", stopwatch.ElapsedMilliseconds); // Close the JSON output writer jsonOutputWriter?.EndWriting(); }
/// <inheritdoc/> public void Run(LoadedProblemGeneratorInput input) { // Prepare the variable holding the number of generated configurations var generatedConfigurations = 0; // Prepare the stopwatch var stopwatch = new Stopwatch(); // Start them stopwatch.Start(); // Run the generation loop foreach (var output in _generator.Generate(input).generationOutputs) { // Switch based on how we calculate the count switch (_settings.CountingMode) { // If we're counting in only the last iteration case CountingMode.LastIteration: // Check if this is the last iteration if (output.Configuration.IterationIndex == input.NumberOfIterations) { // Count it in generatedConfigurations++; } // Otherwise we may move on else { continue; } break; // If we're counting in everything case CountingMode.All: // Do it generatedConfigurations++; break; // Unhandled cases default: throw new ConfigurationGenerationLauncherException($"Unhandled value of {nameof(CountingMode)}: {_settings.CountingMode}"); } // If we're logging and if we should log if (_settings.LogProgress && generatedConfigurations % _settings.GenerationProgresLoggingFrequency == 0) { // Prepare the used memory string var usedMemory = ((double)GC.GetTotalMemory(forceFullCollection: true) / 1000000).ToStringWithDecimalDot(); // Log the number of generated configurations as well as the memory Log.Information("Number of generated configurations: {count}, used memory: {memory} MB", generatedConfigurations, usedMemory); } } // Stop the timing stopwatch.Stop(); // Log the final number and time Log.Information("The total number of generated configurations is {count} in {time} ms.", generatedConfigurations, stopwatch.ElapsedMilliseconds); }