/// <summary> /// Runs the algorithm on the configuration to find old theorems (i.e. those who are true in the configuration /// with the last object removed), the new theorems (i.e. those that use the last object), the invalidated old /// theorems (see <see cref="ITheoremFinder.FindNewTheorems(ContextualPicture, TheoremMap, out Theorem[])"/>, /// and all theorems find via <see cref="ITheoremFinder.FindAllTheorems(ContextualPicture)"/>. /// </summary> /// <param name="configuration">The configuration where we're looking for theorems.</param> /// <returns>The old, new, invalidated all, and all theorems.</returns> private static (TheoremMap oldTheorems, TheoremMap newTheorems, Theorem[] invalidOldTheorems, TheoremMap allTheorems) FindTheorems(Configuration configuration) { // Prepare the kernel var kernel = NinjectUtilities.CreateKernel() // With constructor .AddConstructor() // Look for only some types .AddTheoremFinder(new TheoremFindingSettings(soughtTheoremTypes: new[] { ParallelLines, PerpendicularLines, EqualLineSegments, TangentCircles, LineTangentToCircle, Incidence, ConcurrentLines }, // No exclusion of inside-picture tangencies tangentCirclesTheoremFinderSettings: new TangentCirclesTheoremFinderSettings(excludeTangencyInsidePicture: false), // Exclusion of inside-picture tangencies lineTangentToCircleTheoremFinderSettings: new LineTangentToCircleTheoremFinderSettings(excludeTangencyInsidePicture: true))); // Create the finder var finder = kernel.Get <ITheoremFinder>(); // Create the old configuration, so we can find its theorems var oldConfiguration = new Configuration(configuration.LooseObjectsHolder, // We just don't want to include the last object configuration.ConstructedObjects.Except(new[] { configuration.LastConstructedObject }).ToList()); // Construct the old configuration var oldPictures = kernel.Get <IGeometryConstructor>().ConstructWithUniformLayout(oldConfiguration, numberOfPictures: 5).pictures; // Construct the old contextual picture var oldContextualPicture = new ContextualPicture(oldPictures); // Finally get the old theorems var oldTheorems = finder.FindAllTheorems(oldContextualPicture); // Create the pictures for the current configuration var pictures = kernel.Get <IGeometryConstructor>().ConstructWithUniformLayout(configuration, numberOfPictures: 5).pictures; // Create the contextual picture for the current configuration var contextualPicture = new ContextualPicture(pictures); // Run both algorithms var newTheorems = finder.FindNewTheorems(contextualPicture, oldTheorems, out var invalidOldTheorems); var allTheorems = finder.FindAllTheorems(contextualPicture); // Return everything return(oldTheorems, newTheorems, invalidOldTheorems, allTheorems); }
/// <summary> /// The entry method of the application. /// </summary> /// <param name="arguments">Expects one argument, the path to the directory with outputs.</param> private static void Main(string[] arguments) { // Get the path to the folder with outputs var outputFolder = arguments.FirstOrDefault() // Make aware if it's not been set ?? throw new InvalidOperationException("Expected one argument, the path to the directory with outputs"); // Setup Serilog so it logs to console Log.Logger = new LoggerConfiguration().WriteTo.Console().CreateLogger(); // Log the folder Log.Information("Exploring folder {outputFolder}", outputFolder); // Start timing var stopwatch = Stopwatch.StartNew(); #region Prepare results folder // Create the path to the folder with results var resultsFolder = "Results"; // If it exists, delete it if (Directory.Exists(resultsFolder)) { Directory.Delete(resultsFolder, recursive: true); } // Recreate it Directory.CreateDirectory(resultsFolder); #endregion #region Prepare services // Prepare kernel var kernel = NinjectUtilities.CreateKernel() // That uses Theorem Sorter .AddTheoremSorter() // And Constructor, needed for Theorem Sorter .AddConstructor() // And Ranked Theorem IO stuff .AddRankedTheoremIO(); // We will need to create theorem sorters var sorterFactory = kernel.Get <ITheoremSorterFactory>(); // And ranked theorem writers var writerFactory = kernel.Get <IRankedTheoremJsonLazyWriterFactory>(); // And use a reader var theoremReader = kernel.Get <IRankedTheoremJsonLazyReader>();
/// <summary> /// Runs the algorithm on the configuration to find new and all theorems. /// </summary> /// <param name="configuration">The configuration where we're looking for theorems.</param> /// <param name="instanceFactory">The factory for creating an instance of the finder. If it's null, the default constructor is used.</param> /// <returns>The new and all theorems.</returns> protected (List <Theorem> newTheorems, List <Theorem> allTheorems) FindTheorems(Configuration configuration, Func <T> instanceFactory = null) { // Prepare the kernel with the constructor module var kernel = NinjectUtilities.CreateKernel().AddConstructor(); // Create the pictures var pictures = kernel.Get <IGeometryConstructor>().ConstructWithUniformLayout(configuration, numberOfPictures: 5).pictures; // Create the contextual picture var contextualPicture = new ContextualPicture(pictures); // If the instance factory is specified var finder = instanceFactory != null? // Invoke it instanceFactory() : // Otherwise use reflection to call the parameterless constructor Activator.CreateInstance <T>(); // Run both algorithms return(finder.FindNewTheorems(contextualPicture).ToList(), finder.FindAllTheorems(contextualPicture).ToList()); }
/// <summary> /// Assembles all needed components for the application and performs the <paramref name="applicationCode"/> function. /// <para> /// <list type="number"> /// <item>It builds <see cref="JsonConfiguration"/> using either <paramref name="customConfigurationFilePaths"/>, if they /// are not empty, or files <see cref="DefaultConfigurationFilePath"/> and <see cref="DevConfigurationFilePath"/>.</item> /// <item>Sets up Serilog logging using <see cref="LoggingUtilities.SetupSerilog(JsonConfiguration)"/>.</item> /// <item>Constructs an empty Ninject kernel using <see cref="NinjectUtilities.CreateKernel"/>.</item> /// <item>Runs the <paramref name="applicationCode"/> and logs its exceptions.</item> /// </list> /// </para> /// </summary> /// <param name="customConfigurationFilePaths">The paths to custom configuration files loaded in this order. If no files are /// specified, then the files <see cref="DefaultConfigurationFilePath"/> and <see cref="DevConfigurationFilePath"/> are used.</param> /// <param name="applicationCode">The function performing the actual application code.</param> public static async Task Run(string[] customConfigurationFilePaths, Func <IKernel, JsonConfiguration, Task> applicationCode) { #region Load JsonConfiguration // Prepare the variable for settings JsonConfiguration jsonConfiguration; try { // If the custom files are specified... jsonConfiguration = customConfigurationFilePaths.Length != 0 // Load the configuration from them ? new JsonConfiguration(customConfigurationFilePaths) // Otherwise use the default files : new JsonConfiguration(DefaultConfigurationFilePath, DevConfigurationFilePath); } catch (Exception e) { // Re-throw throw new ConfigurationException($"Cannot set up a JsonConfiguration from arguments: {customConfigurationFilePaths.ToJoinedString()}", e); } #endregion #region Logging try { // Ensure we have logging LoggingUtilities.SetupSerilog(jsonConfiguration); } catch (Exception e) { // Re-throw throw new LoggingException($"Cannot set up Serilog using the configuration loaded from {customConfigurationFilePaths.ToJoinedString()}", e); } #endregion #region Application Code try { // Log start Log.Information("The application has started."); // Log from where we have the configuration from Log.Information("Configuration loaded from files: {files}", jsonConfiguration.LoadedConfigurationFilePaths.ToJoinedString()); // Prepare a stopwatch var stopwatch = Stopwatch.StartNew(); // Execute the application code with a new empty kernel await applicationCode(NinjectUtilities.CreateKernel(), jsonConfiguration); // Log end Log.Information("The application has finished correctly in {time:F2} sec.\n", stopwatch.ElapsedMilliseconds / 1000d); } // Catch for any unhandled exception catch (Exception e) { // Log if there is any Log.Fatal(e, $"An unexpected exception has occurred."); // This is a sad end throw; } #endregion }
/// <summary> /// The entry method of the application. /// </summary> private static void Main() { // Setup simple logger Log.Logger = new LoggerConfiguration().WriteTo.Console().CreateLogger(); // Initialize the kernel _kernel = NinjectUtilities.CreateKernel() // Add the constructor .AddConstructor() // Add the configuration generator that uses fast generation (it does not really matter here) .AddConfigurationGenerator(new GenerationSettings(ConfigurationFilterType.Fast)); // Bind the generator _kernel.Bind <IProblemGenerator>().To <ProblemGenerator.ProblemGenerator>(); // Add an empty failure tracer _kernel.Bind <IGeometryFailureTracer>().To <EmptyGeometryFailureTracer>(); // Add an empty theorem finder _kernel.Bind <ITheoremFinder>().To <EmptyTheoremFinder>(); // Load the construction file _constructions = File.ReadAllLines("constructions.txt") // Each line should be a construction .Select(Parser.ParseConstruction) // Enumerate .ToReadOnlyHashSet(); // Load the template input file _templateInputFile = File.ReadAllText("input_template.txt"); #region Preparing the results folder // Create the path to the folder with inputs var resultsFolder = "Results"; // If the folder exists, clear it if (Directory.Exists(resultsFolder)) { Directory.Delete(resultsFolder, recursive: true); } // Otherwise create it else { Directory.CreateDirectory(resultsFolder); } #endregion // Prepare the stopwatch var stopwatch = Stopwatch.StartNew(); // Prepare the counter of generated inputs var counter = 0; // Go through the all types of generated input files new[] { Triangle_TwoObjects_PlusThreeObjects(), Triangle_FourObjects_OnlyFullySymmetric_PlusTwoObjects(), Triangle_FourObjects_TwoLinesAndTwoPoints_OnlySymmetric_OnlyUsedLines_PlusTwoObjects(), Triangle_FourObjects_ThreeLinesAndOnePoint_OnlySymmetric_OnlyUsedLines_PlusTwoObjects(), Quadrilateral_TwoObjects_PlusTwoObjects() } // Merge the inputs .Flatten() // Handle each generated file .ForEach(input => { // Count the input in counter++; // Log the count, but not too often if (counter % 100 == 0) { Log.Information("{count} files after {time} ms.", counter, stopwatch.ElapsedMilliseconds); } // Prepare the constructions as a single string var constructionString = input.Constructions // For each take the name .Select(construction => construction.Name) // Each on a separate line .ToJoinedString("\n"); // Prepare the formatted configuration by creating a formatter for it var configurationString = new OutputFormatter(input.InitialConfiguration.AllObjects) // Formatting it .FormatConfiguration(input.InitialConfiguration) // Replacing any curly braces in the definitions .Replace("{", "").Replace("}", ""); // Prepare the content by taking the template file var content = _templateInputFile // Replace the constructions .Replace("{Constructions}", constructionString) // Replace the configuration .Replace("{InitialConfiguration}", configurationString) // Replace the iterations .Replace("{Iterations}", input.NumberOfIterations.ToString()) // Replace maximal points .Replace("{MaximalPoints}", input.MaximalNumbersOfObjectsToAdd[Point].ToString()) // Replace maximal lines .Replace("{MaximalLines}", input.MaximalNumbersOfObjectsToAdd[Line].ToString()) // Replace maximal circles .Replace("{MaximalCircles}", input.MaximalNumbersOfObjectsToAdd[Circle].ToString()) // Replace the symmetry generation mode .Replace("{SymmetryGenerationMode}", input.SymmetryGenerationMode.ToString()); // Create the directory where the file goes Directory.CreateDirectory(Path.Combine(resultsFolder, $"input_{counter}")); // Write the content File.WriteAllText(Path.Combine(resultsFolder, $"input_{counter}/input_{counter}.txt"), content); }); // Log how many files have been created Log.Information("Generated {counter} file(s) after {time} ms.", counter, stopwatch.ElapsedMilliseconds); }
/// <summary> /// Gets an instance of the generator. /// </summary> /// <param name="filterType">The type of configuration filter to be used</param> private static IConfigurationGenerator GetGenerator(ConfigurationFilterType filterType) => NinjectUtilities.CreateKernel().AddConfigurationGenerator(new GenerationSettings(filterType)).Get <IConfigurationGenerator>();