/// <summary> /// Converts given theorems to a string, optionally with their proofs. /// </summary> /// <param name="formatter">The formatter of the configuration where the theorems hold.</param> /// <param name="analyzerOutput">The analyzer output to be converted to a string.</param> /// <param name="writeProofs">Indicates whether we should format theorem proofs.</param> /// <returns>The string representing the analyzer output.</returns> private static string AnalyzerOutputToString(OutputFormatter formatter, GeneratedProblemAnalyzerOutputBase analyzerOutput, bool writeProofs) { // Prepare the result var result = ""; // Prepare a local theorem index var localTheoremIndex = 1; #region Theorem proofs // If we should write proofs and there are any if (writeProofs) { // Get them var proofs = ((GeneratedProblemAnalyzerOutputWithProofs)analyzerOutput).TheoremProofs; // If there are any if (proofs.Any()) { // Add the header result += $"\n\nProved theorems:\n\n"; // Append theorem proofs by taking them result += proofs // Sorting by the statement of the proved theorem .OrderBy(pair => formatter.FormatTheorem(pair.Key)) // Write proof for each with a local id .Select(pair => $" {localTheoremIndex}. {formatter.FormatTheoremProof(pair.Value, tag: $"{localTheoremIndex++}.")}")
/// <summary> /// The entry method of the application. /// </summary> /// <param name="arguments">The three arguments: /// <list type="number"> /// <item>Path to the inference rule folder.</item> /// <item>The extension of the inference rule files.</item> /// <item>Path to the object introduction rule file.</item> /// </list> /// </param> private static async Task Main(string[] arguments) { #region Kernel preparation // Prepare the settings for the inference rule provider var inferenceRuleProviderSettings = new InferenceRuleProviderSettings(ruleFolderPath: arguments[0], fileExtension: arguments[1]); // Prepare the settings for the object introduction rule provider var objectIntroductionRuleProviderSettings = new ObjectIntroductionRuleProviderSettings(filePath: arguments[2]); // Prepare the kernel var kernel = Infrastructure.NinjectUtilities.CreateKernel() // That constructors configurations .AddConstructor() // That can find theorems .AddTheoremFinder(new TheoremFindingSettings ( // Look for theorems of any type soughtTheoremTypes: Enum.GetValues(typeof(TheoremType)).Cast <TheoremType>() // Except for the EqualObjects that don't have a finder .Except(TheoremType.EqualObjects.ToEnumerable()) // Enumerate .ToArray(), // Exclude in-picture tangencies new TangentCirclesTheoremFinderSettings(excludeTangencyInsidePicture: true), new LineTangentToCircleTheoremFinderSettings(excludeTangencyInsidePicture: true) )) // That can prove theorems .AddTheoremProver(new TheoremProvingSettings ( // Use the provider to find the inference rules new InferenceRuleManagerData(await new InferenceRuleProvider.InferenceRuleProvider(inferenceRuleProviderSettings).GetInferenceRulesAsync()), // Use the provider to find the object introduction rules new ObjectIntroducerData(await new ObjectIntroductionRuleProvider.ObjectIntroductionRuleProvider(objectIntroductionRuleProviderSettings).GetObjectIntroductionRulesAsync()), // Setup the prover new TheoremProverSettings ( // We will be strict and don't assume simplifiable theorems assumeThatSimplifiableTheoremsAreTrue: false, // We will find trivial theorems for all objects findTrivialTheoremsOnlyForLastObject: false ) )); #endregion #region Tests // Take the tests new[] { PerpendicularBisectorsAreConcurrent(), IncenterAndTangentLine(), Midpoints(), Parallelogram(), HiddenExcenter(), HiddenMidpoint(), LineTangentToCircle(), ConcurrencyViaObjectIntroduction(), SimpleLineSegments() } // Perform each .ForEach(configuration => { #region Finding theorems // Prepare 3 pictures in which the configuration is drawn var pictures = kernel.Get <IGeometryConstructor>().ConstructWithUniformLayout(configuration, numberOfPictures: 3).pictures; // Prepare a contextual picture var contextualPicture = new ContextualPicture(pictures); // Find all theorems var theorems = kernel.Get <ITheoremFinder>().FindAllTheorems(contextualPicture); #endregion #region Writing theorems // Prepare the formatter of all the output var formatter = new OutputFormatter(configuration.AllObjects); // Prepare a local function that converts given theorems to a string string TheoremString(IEnumerable <Theorem> theorems) => // If there are no theorems theorems.IsEmpty() // Then return an indication of it ? "nothing" // Otherwise format each theorem : theorems.Select(formatter.FormatTheorem) // Order alphabetically .Ordered() // Add the index .Select((theoremString, index) => $"[{index + 1}] {theoremString}") // Make each on a separate line .ToJoinedString("\n"); // Write the configuration and theorems Console.WriteLine($"\nConfiguration:\n\n{formatter.FormatConfiguration(configuration).Indent(2)}\n"); Console.WriteLine($"Theorems:\n\n{TheoremString(theorems.AllObjects).Indent(2)}\n"); #endregion #region Proving theorems // Prepare a timer var totalTime = new Stopwatch(); // Start it totalTime.Start(); // Perform the theorem finding with proofs, without any assumed theorems var proverOutput = kernel.Get <ITheoremProver>().ProveTheoremsAndConstructProofs(new TheoremMap(), theorems, contextualPicture); // Stop the timer totalTime.Stop(); #endregion #region Writing results // Get the proofs var proofString = proverOutput // Sort by the statement .OrderBy(pair => formatter.FormatTheorem(pair.Key)) // Format each .Select(pair => formatter.FormatTheoremProof(pair.Value)) // Trim .Select(proofString => proofString.Trim()) // Make an empty line between each .ToJoinedString("\n\n"); // Write it Console.WriteLine(proofString); // Write the unproven theorems too Console.WriteLine($"\nUnproved:\n\n{TheoremString(theorems.AllObjects.Except(proverOutput.Keys)).Indent(2)}\n"); // Report time Console.WriteLine($"Total time: {totalTime.ElapsedMilliseconds}"); Console.WriteLine("----------------------------------------------"); #endregion }); #endregion }