/// <summary>
        /// Traces that a given contextual picture couldn't be cloned and extended with the new object
        /// already drawn in pictures representing some configuration.
        /// </summary>
        /// <param name="previousContextualPicture">The contextual picture that was correct and failed to add the new object.</param>
        /// <param name="newConfigurationPictures">The pictures holding geometry data of the new object that was added.</param>
        /// <param name="exception">The inner inconsistency exception that caused the issue.</param>
        public void InconstructibleContextualPictureByCloning(ContextualPicture previousContextualPicture, PicturesOfConfiguration newConfigurationPictures, InconsistentPicturesException exception)
        {
            // Prepare the initial information string
            var infoString = $"Undrawable object into a contextual picture.";

            // If logging is allowed, log it with the reference to more detail in the file
            if (_settings.LogFailures)
            {
                Log.Warning("Object generation: {info} See {path} for more detail.", infoString, _settings.FailureFilePath);
            }

            // Prepare the formatter for the configuration
            var formatter = new OutputFormatter(newConfigurationPictures.Configuration.AllObjects);

            // Add the data about how the object can be drawn
            infoString += $"\n\nThe object is the last object of the following defining configuration:\n\n{formatter.FormatConfiguration(newConfigurationPictures.Configuration).Indent(2)}";

            // Add the exception
            infoString += $"\n\nThe details of the exception: {exception.Format(formatter)}\n";

            // Open the stream writer for the file
            using var streamWriter = new StreamWriter(_settings.FailureFilePath, append: true);

            // Write indented message to the file
            streamWriter.WriteLine($"- {infoString.Indent(3).TrimStart()}");
        }
Beispiel #2
0
        /// <inheritdoc/>
        protected override IEnumerable<GeometricObject[]> GetAllOptions(ContextualPicture contextualPicture)
        {
            // Get lines as a list
            var allLines = contextualPicture.AllLines.ToList();

            // Go through all unordered pairs 
            for (var i = 0; i < allLines.Count; i++)
            {
                for (var j = i + 1; j < allLines.Count; j++)
                {
                    // Get the lines for comfort
                    var line1 = allLines[i];
                    var line2 = allLines[j];

                    // If they have a common point, exclude them right away
                    if (line1.CommonPointsWith(line2).Any())
                        continue;

                    // Otherwise go through the remaining lines
                    for (var k = j + 1; k < allLines.Count; k++)
                    {
                        // Get the third line for comfort
                        var line3 = allLines[k];

                        // If it has any common point with our two, skip it
                        if (line3.CommonPointsWith(line1).Any() || line3.CommonPointsWith(line2).Any())
                            continue;

                        // Otherwise return this triple
                        yield return new[] { line1, line2, line3 };
                    }
                }
            }
        }
Beispiel #3
0
 /// <inheritdoc/>
 protected override IEnumerable <GeometricObject[]> GetAllOptions(ContextualPicture contextualPicture)
 {
     // If we are excluding tangencies inside picture, we
     // don't have to consider circles with a common point
     if (_settings.ExcludeTangencyInsidePicture)
     {
         // Combine all circles with themselves
         foreach (var circles in contextualPicture.AllCircles.Subsets(2))
         {
             if (circles[0].CommonPointsWith(circles[1]).IsEmpty())
             {
                 yield return(circles);
             }
         }
     }
     // Otherwise we don't have to consider circles with 2 common points
     else
     {
         // Combine all circles with themselves
         foreach (var circles in contextualPicture.AllCircles.Subsets(2))
         {
             if (circles[0].CommonPointsWith(circles[1]).Count() != 2)
             {
                 yield return(circles);
             }
         }
     }
 }
        /// <inheritdoc/>
        protected override IEnumerable <GeometricObject[]> GetNewOptions(ContextualPicture contextualPicture)
        {
            // Find new lines
            var newLines = contextualPicture.NewLines.ToList();

            // Find old lines
            var oldLines = contextualPicture.OldLines.ToList();

            // Combine the new lines with themselves
            foreach (var(newLine1, newLine2) in newLines.UnorderedPairs())
            {
                yield return new[] { newLine1, newLine2 }
            }
            ;

            // Combine the new lines with the old ones
            foreach (var newLine in newLines)
            {
                foreach (var oldLine in oldLines)
                {
                    yield return new[] { newLine, oldLine }
                }
            }
            ;
        }
Beispiel #5
0
        /// <inheritdoc/>
        protected override IEnumerable <GeometricObject[]> GetNewOptions(ContextualPicture contextualPicture)
        {
            // Find new circles.
            var newCircles = contextualPicture.NewCircles.ToList();

            // Find old circles.
            var oldCircles = contextualPicture.OldCircles.ToList();

            // If we are excluding tangencies inside picture, we
            // don't have to consider circles with a common point
            if (_settings.ExcludeTangencyInsidePicture)
            {
                // Combine the new circles with themselves
                foreach (var circles in newCircles.Subsets(2))
                {
                    if (circles[0].CommonPointsWith(circles[1]).IsEmpty())
                    {
                        yield return(circles);
                    }
                }

                // Combine the new circles with the old ones
                foreach (var newCircle in newCircles)
                {
                    foreach (var oldCircle in oldCircles)
                    {
                        if (newCircle.CommonPointsWith(oldCircle).IsEmpty())
                        {
                            yield return new[] { newCircle, oldCircle }
                        }
                    }
                }
                ;
            }
            // Otherwise we don't have to consider circles with 2 common points
            else
            {
                // Combine the new circles with themselves
                foreach (var circles in newCircles.Subsets(2))
                {
                    if (circles[0].CommonPointsWith(circles[1]).Count() != 2)
                    {
                        yield return(circles);
                    }
                }

                // Combine the new circles with the old ones
                foreach (var newCircle in newCircles)
                {
                    foreach (var oldCircle in oldCircles)
                    {
                        if (newCircle.CommonPointsWith(oldCircle).Count() != 2)
                        {
                            yield return new[] { newCircle, oldCircle }
                        }
                    }
                }
                ;
            }
        }
Beispiel #6
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ProblemGeneratorOutput"/> class.
 /// </summary>
 /// <param name="configuration">The generated configuration.</param>
 /// <param name="contextualPicture">The contextual picture where the configuration is drawn.</param>
 /// <param name="oldTheorems">The found theorems for the configurations that don't use the last object of the configuration.</param>
 /// <param name="newTheorems">The found theorems for the configurations that use the last object of the configuration.</param>
 public ProblemGeneratorOutput(GeneratedConfiguration configuration, ContextualPicture contextualPicture, TheoremMap oldTheorems, TheoremMap newTheorems)
 {
     Configuration     = configuration ?? throw new ArgumentNullException(nameof(configuration));
     ContextualPicture = contextualPicture ?? throw new ArgumentNullException(nameof(contextualPicture));
     OldTheorems       = oldTheorems ?? throw new ArgumentNullException(nameof(oldTheorems));
     NewTheorems       = newTheorems ?? throw new ArgumentNullException(nameof(newTheorems));
 }
 /// <inheritdoc/>
 public override IEnumerable <Theorem> FindNewTheorems(ContextualPicture contextualPicture)
 // Take new options
 => GetNewOptions(contextualPicture)
 // That represent a true theorem
 .Where(objects => RepresentsTrueTheorem(contextualPicture, objects))
 // Cast each to theorems
 .SelectMany(ToTheorems);
Beispiel #8
0
        /// <inheritdoc/>
        public TheoremMap FindNewTheorems(ContextualPicture contextualPicture, TheoremMap oldTheorems, out Theorem[] invalidOldTheorems)
        {
            // Set no invalid theorems
            invalidOldTheorems = Array.Empty <Theorem>();

            // Return an empty theorem map
            return(new TheoremMap());
        }
Beispiel #9
0
        /// <inheritdoc/>
        public override bool ValidateOldTheorem(ContextualPicture contextualPicture, Theorem oldTheorem)
        {
            // If we don't care whether the intersection point is outside or inside of the picture,
            // then there is no reason to say a theorem is invalid
            if (!ExpectAnyExternalIntersection)
            {
                return(true);
            }

            // Otherwise it might have happened that the new point is the one where the old theorem
            // stated an intersection theorem. We need to check this. Let's take the new point
            var newPoint = contextualPicture.NewPoints.FirstOrDefault();

            // If the last object hasn't been a point, then nothing as explained could have happened
            if (newPoint == null)
            {
                return(true);
            }

            // Otherwise we need to check whether the old theorem doesn't state that some objects
            // have an intersection point equal to the new point
            return(oldTheorem.InvolvedObjects
                   // We know the objects are with points
                   .Cast <TheoremObjectWithPoints>()
                   // For each we will find the corresponding geometric object definable by points
                   .Select(objectWithPoints =>
            {
                // If the object is defined explicitly, then we simply ask the picture to do the job
                if (objectWithPoints.DefinedByExplicitObject)
                {
                    return (DefinableByPoints)contextualPicture.GetGeometricObject(objectWithPoints.ConfigurationObject);
                }

                // Otherwise we need to find the inner points
                var innerPoints = objectWithPoints.Points
                                  // As geometric objects
                                  .Select(contextualPicture.GetGeometricObject)
                                  // They are points
                                  .Cast <PointObject>()
                                  // Enumerate
                                  .ToArray();

                // Base on the type of object we will take all lines / circles passing through the first point
                return (objectWithPoints switch
                {
                    // If we have a line, take lines
                    LineTheoremObject _ => innerPoints[0].Lines.Cast <DefinableByPoints>(),

                    // If we have a circle, take circles
                    CircleTheoremObject _ => innerPoints[0].Circles,

                    // Unhandled cases
                    _ => throw new TheoremFinderException($"Unhandled type of {nameof(TheoremObjectWithPoints)}: {objectWithPoints.GetType()}")
                })
                // Take the first line or circle that contains all the points
                .First(lineOrCircle => lineOrCircle.ContainsAll(innerPoints));
            })
 /// <inheritdoc/>
 public override IEnumerable <Theorem> FindAllTheorems(ContextualPicture contextualPicture)
 // Take all lines
 => contextualPicture.AllLines
 // That have at least three points
 .Where(line => line.Points.Count >= 3)
 // For each take all triples of its points
 .SelectMany(line => line.Points.Subsets(3))
 // Get the configuration objects
 .Select(points => points.Select(point => point.ConfigurationObject).ToArray())
 // Each of these triples makes a theorem
 .Select(points => new Theorem(Type, points));
 /// <inheritdoc/>
 protected override IEnumerable <GeometricObject[]> GetAllOptions(ContextualPicture contextualPicture)
 {
     // Get all points
     return(contextualPicture.AllPoints.ToList()
            // And all its pairs
            .UnorderedPairs().ToList()
            // And all pairs of these pairs
            .UnorderedPairs()
            // Each represents 4 points
            .Select(points => new[] { points.Item1.Item1, points.Item1.Item2, points.Item2.Item1, points.Item2.Item2 }));
 }
Beispiel #12
0
 /// <inheritdoc/>
 public override IEnumerable <Theorem> FindAllTheorems(ContextualPicture contextualPicture)
 // Take all circles
 => contextualPicture.AllCircles
 // That have at least four points
 .Where(circle => circle.Points.Count >= 4)
 // For each take all quadruples of its points
 .SelectMany(circle => circle.Points.Subsets(4))
 // Get the configuration objects
 .Select(points => points.Select(point => point.ConfigurationObject).ToArray())
 // Each of these quadruples makes a theorem
 .Select(points => new Theorem(Type, points));
Beispiel #13
0
        /// <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);
        }
 /// <inheritdoc/>
 public override IEnumerable <Theorem> FindAllTheorems(ContextualPicture contextualPicture)
 // Take all objects
 => contextualPicture.Pictures.Configuration.AllObjects
 // That are explicit lines / circles
 .Where(configurationObject => configurationObject.ObjectType == Line || configurationObject.ObjectType == Circle)
 // For each found the corresponding geometric object
 .Select(contextualPicture.GetGeometricObject)
 // We know they have points
 .Cast <DefinableByPoints>()
 // We can now access its points
 .SelectMany(geometricObject => geometricObject.Points
             // Every one of them makes an incidence
             .Select(point => new Theorem(Type, geometricObject.ConfigurationObject, point.ConfigurationObject)));
        /// <inheritdoc/>
        protected override IEnumerable <GeometricObject[]> GetNewOptions(ContextualPicture contextualPicture)
        {
            // Find new points
            var newPoints = contextualPicture.NewPoints.ToList();

            // Find old points
            var oldPoints = contextualPicture.OldPoints.ToList();

            #region Getting new line segments

            // Prepare the list of new line segments
            var newLineSegments = new List <(PointObject, PointObject)>();

            // Combine the new points with themselves
            foreach (var pairOfPoints in newPoints.UnorderedPairs())
            {
                newLineSegments.Add(pairOfPoints);
            }

            // Combine the new points with the old ones
            foreach (var newPoint in newPoints)
            {
                foreach (var oldPoint in oldPoints)
                {
                    newLineSegments.Add((newPoint, oldPoint));
                }
            }

            #endregion

            // Get the old line segments
            var oldLineSegments = oldPoints.UnorderedPairs().ToList();

            // Combine the new line segments with themselves
            foreach (var((point1, point2), (point3, point4)) in newLineSegments.UnorderedPairs())
            {
                yield return new[] { point1, point2, point3, point4 }
            }
            ;

            // Combine the new line segments with the old ones
            foreach (var(point1, point2) in newLineSegments)
            {
                foreach (var(point3, point4) in oldLineSegments)
                {
                    yield return new[] { point1, point2, point3, point4 }
                }
            }
            ;
        }
Beispiel #16
0
        /// <inheritdoc/>
        public TheoremMap FindNewTheorems(ContextualPicture contextualPicture, TheoremMap oldTheorems, out Theorem[] invalidOldTheorems)
        {
            // Find invalid theorems first by taking the old theorems
            invalidOldTheorems = oldTheorems
                                 // For each [type, theorems] pair
                                 .SelectMany(pair =>
            {
                // Find the right theorem finder
                var finder = _finders.First(finder => finder.Type == pair.Key);

                // And for every theorem answer the question whether it is no longer valid
                return(pair.Value.Where(oldTheorem => !finder.ValidateOldTheorem(contextualPicture, oldTheorem)));
            })
                                 // Enumerate
                                 .ToArray();

            // Reuse all the finders to find the theorems that are geometrically new in the configuration
            var uniqueNewTheorems = _finders.SelectMany(finder => finder.FindNewTheorems(contextualPicture));

            // We still need to find the new theorems that are not new, due to geometric properties
            // such as collinearity or concyclity, but can now be stated using the new object
            // For that we are going to take every old theorem
            var redefinedNewTheorems = oldTheorems.AllObjects
                                       // That is valid
                                       .Except(invalidOldTheorems)
                                       // And return possibly new versions of it
                                       .SelectMany(theorem =>
                                       // If we have an incidence, we don't want to do anything
                                       // (it's not needed to state that A lies on line AB)
                                                   theorem.Type == TheoremType.Incidence ? Enumerable.Empty <Theorem>() :
                                       // Otherwise for each theorem we take its objects
                                                   theorem.InvolvedObjects
                                       // Find the possible definition changes for each
                                       // (this includes the option of not changing the definition at all)
                                                   .Select(theoremObject => FindDefinitionChangeOptions(theoremObject, contextualPicture))
                                       // Combine these definitions in every possible way
                                                   .Combine()
                                       // For every option create a new theorem
                                                   .Select(objects => new Theorem(theorem.Type, objects)))
                                       // We might have gotten even old theorems (when all the definition option changes were
                                       // 'no change'. Also we might have gotten duplicates. This call will solve both problems
                                       .Except(oldTheorems.AllObjects);

            // Concatenate these two types of theorems and wrap the result in a map (which will enumerate it)
            return(new TheoremMap(uniqueNewTheorems.Concat(redefinedNewTheorems)));
        }
        /// <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());
        }
Beispiel #18
0
        /// <inheritdoc/>
        public override IEnumerable <Theorem> FindNewTheorems(ContextualPicture contextualPicture)
        {
            // Take the new point
            var point = contextualPicture.NewPoints.FirstOrDefault();

            // If there's none, we can't do more
            if (point == null)
            {
                return(Enumerable.Empty <Theorem>());
            }

            // Otherwise take its circles
            return(point.Circles
                   // That have at least 4 points
                   .Where(circle => circle.Points.Count >= 4)
                   // For each take all triples of its points distinct from our point + append our point
                   .SelectMany(circle => circle.Points.Where(_point => _point != point).Subsets(3).Select(subset => subset.Concat(point)))
                   // Get the configuration objects
                   .Select(points => points.Select(point => point.ConfigurationObject).ToArray())
                   // Each of these quadruples makes a theorem
                   .Select(points => new Theorem(Type, points)));
        }
        /// <inheritdoc/>
        public override IEnumerable <Theorem> FindNewTheorems(ContextualPicture contextualPicture)
        {
            // Get the last object of the configuration
            var lastConfigurationObject = contextualPicture.Pictures.Configuration.LastConstructedObject;

            // Distinguish cases bases on its type
            switch (lastConfigurationObject.ObjectType)
            {
            // If we have a point
            case Point:

                // We find its geometric version
                var geometricPoint = (PointObject)contextualPicture.GetGeometricObject(lastConfigurationObject);

                // Take all circles and lines
                return(geometricPoint.Lines.Cast <DefinableByPoints>().Concat(geometricPoint.Circles)
                       // That are defined explicitly
                       .Where(lineCircle => lineCircle.ConfigurationObject != null)
                       // Each makes a valid incidence
                       .Select(lineCircle => new Theorem(Type, lineCircle.ConfigurationObject, lastConfigurationObject)));

            // If we have a line or circle
            case Line:
            case Circle:

                // We find its geometric version
                var geometricLineCircle = (DefinableByPoints)contextualPicture.GetGeometricObject(lastConfigurationObject);

                // Take its points
                return(geometricLineCircle.Points
                       // Each makes a valid incidence theorem
                       .Select(point => new Theorem(Type, point.ConfigurationObject, lastConfigurationObject)));

            // Unhandled cases
            default:
                throw new TheoremFinderException($"Unhandled value of {nameof(ConfigurationObjectType)}: {lastConfigurationObject.ObjectType}");
            }
        }
 /// <inheritdoc/>
 protected override IEnumerable <GeometricObject[]> GetAllOptions(ContextualPicture contextualPicture)
 {
     // If we are excluding tangencies inside picture, we
     // don't have to consider lines and circles with a common point
     if (_settings.ExcludeTangencyInsidePicture)
     {
         // Combine the new lines with all the circles
         foreach (var line in contextualPicture.AllLines)
         {
             foreach (var circle in contextualPicture.AllCircles)
             {
                 if (line.CommonPointsWith(circle).IsEmpty())
                 {
                     yield return new GeometricObject[] { line, circle }
                 }
             }
         }
         ;
     }
     // Otherwise we don't have to consider lines and circles with 2 common points
     else
     {
         // Combine the new lines with all the circles
         foreach (var line in contextualPicture.AllLines)
         {
             foreach (var circle in contextualPicture.AllCircles)
             {
                 if (line.CommonPointsWith(circle).Count() != 2)
                 {
                     yield return new GeometricObject[] { line, circle }
                 }
             }
         }
         ;
     }
 }
Beispiel #21
0
 /// <inheritdoc/>
 public override bool ValidateOldTheorem(ContextualPicture contextualPicture, Theorem oldTheorem)
 // No restrictions
 => true;
Beispiel #22
0
 /// <inheritdoc/>
 public abstract IEnumerable <Theorem> FindNewTheorems(ContextualPicture contextualPicture);
Beispiel #23
0
 /// <inheritdoc/>
 public abstract bool ValidateOldTheorem(ContextualPicture contextualPicture, Theorem oldTheorem);
 /// <inheritdoc/>
 protected override bool RepresentsTrueTheorem(ContextualPicture contextualPicture, GeometricObject[] objects)
 // Return if the theorem is true in all pictures
 => contextualPicture.Pictures.All(picture =>
                                   // To find out if it's true in the given one we use our abstract method
                                   IsTrue(objects.Select(geometricObject => contextualPicture.GetAnalyticObject(geometricObject, picture)).ToArray()));
 /// <inheritdoc/>
 protected override IEnumerable <GeometricObject[]> GetAllOptions(ContextualPicture contextualPicture)
 // Get all pairs of lines
 => contextualPicture.AllLines.Subsets(2);
Beispiel #26
0
        /// <inheritdoc/>
        protected override IEnumerable<GeometricObject[]> GetNewOptions(ContextualPicture contextualPicture)
        {
            // Find new lines
            var newLines = contextualPicture.NewLines.ToList();

            // Find old lines
            var oldLines = contextualPicture.OldLines.ToList();

            #region Three new lines

            // Go through all unordered pairs 
            for (var i = 0; i < newLines.Count; i++)
            {
                for (var j = i + 1; j < newLines.Count; j++)
                {
                    // Get the lines for comfort
                    var line1 = newLines[i];
                    var line2 = newLines[j];

                    // If they have a common point, exclude them right away
                    if (line1.CommonPointsWith(line2).Any())
                        continue;

                    // Otherwise go through the remaining lines
                    for (var k = j + 1; k < newLines.Count; k++)
                    {
                        // Get the third line for comfort
                        var line3 = newLines[k];

                        // If it has any common point with our two, skip it
                        if (line3.CommonPointsWith(line1).Any() || line3.CommonPointsWith(line2).Any())
                            continue;

                        // Otherwise return this triple
                        yield return new[] { line1, line2, line3 };
                    }
                }
            }

            #endregion

            #region Two new lines, one old

            // Take new line pairs and combine them with the old ones
            foreach (var (newLine1, newLine2) in newLines.UnorderedPairs())
                if (newLine1.CommonPointsWith(newLine2).IsEmpty())
                    foreach (var oldLine in oldLines)
                        if (oldLine.CommonPointsWith(newLine1).IsEmpty() && oldLine.CommonPointsWith(newLine2).IsEmpty())
                            yield return new[] { newLine1, newLine2, oldLine };

            #endregion

            #region One new line, two old

            // Take old line pairs and combine them with the new ones
            foreach (var (oldLine1, oldLine2) in oldLines.UnorderedPairs())
                if (oldLine1.CommonPointsWith(oldLine2).IsEmpty())
                    foreach (var newLine in newLines)
                        if (newLine.CommonPointsWith(oldLine1).IsEmpty() && newLine.CommonPointsWith(oldLine2).IsEmpty())
                            yield return new[] { oldLine1, oldLine2, newLine };

            #endregion
        }
Beispiel #27
0
        /// <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
        }
Beispiel #28
0
 /// <inheritdoc/>
 public TheoremMap FindAllTheorems(ContextualPicture contextualPicture)
 // Simply reuse all the finders and wrap the theorems in a map (which will enumerate it)
 => new TheoremMap(_finders.SelectMany(finder => finder.FindAllTheorems(contextualPicture)));
Beispiel #29
0
        /// <summary>
        /// Finds all options for changing the definition of a given old theorem object based on the new (last)
        /// configuration object, which might have geometric properties related to this old object (for example,
        /// if the new object is a point and the old one is a line/circle, then it might lie on it). This includes
        /// even an option of not changing the definition at all, i.e. returning the original old object.
        /// </summary>
        /// <param name="oldTheoremObject">The old theorem object for which we're looking for definition change options.</param>
        /// <param name="contextualPicture">The contextual picture that represents the configuration.</param>
        /// <returns>The enumeration of all possible definition changes, including no change.</returns>
        private static IEnumerable <TheoremObject> FindDefinitionChangeOptions(TheoremObject oldTheoremObject, ContextualPicture contextualPicture)
        {
            // Find the new object of the configuration
            var newConfigurationObject = contextualPicture.Pictures.Configuration.LastConstructedObject;

            // Find its geometric version
            var newGeometricObject = contextualPicture.GetGeometricObject(newConfigurationObject);

            // Switch based on the type of old object
            switch (oldTheoremObject)
            {
            // If we have a point or line segment (internally consisting of points...)
            case PointTheoremObject _:
            case LineSegmentTheoremObject _:

                // Then there is no way to find a new definition of the object,
                // i.e. we return the 'no change of definition' option
                return(new[] { oldTheoremObject });

            // If we have an object with points...
            case TheoremObjectWithPoints objectWithPoints:

                #region Find its geometric version

                // We're going to find the corresponding geometric version
                DefinableByPoints geometricObjectWithPoints = default;

                // If our object is defined explicitly
                if (objectWithPoints.DefinedByExplicitObject)
                {
                    // Use the internal configuration object to get the definition directly
                    geometricObjectWithPoints = (DefinableByPoints)contextualPicture.GetGeometricObject(objectWithPoints.ConfigurationObject);
                }

                // Otherwise it's defined by points
                else
                {
                    // Get the points corresponding to its points
                    var geometricPoints = objectWithPoints.Points
                                          // For each find the geometric point
                                          .Select(contextualPicture.GetGeometricObject)
                                          // We know they're points
                                          .Cast <PointObject>()
                                          // Enumerate
                                          .ToArray();

                    // Find the right object based on the type of the theorem object with points
                    geometricObjectWithPoints = (objectWithPoints switch
                    {
                        // Looking for the line that contains our points
                        // It certainly passes through the first point
                        LineTheoremObject _ => geometricPoints[0].Lines.First(line => line.ContainsAll(geometricPoints)) as DefinableByPoints,

                        // Looking for the circle that contains our points
                        // It certainly passes through the first point
                        CircleTheoremObject _ => geometricPoints[0].Circles.First(circle => circle.ContainsAll(geometricPoints)),

                        // Unhandled cases
                        _ => throw new TheoremFinderException($"Unhandled type of {nameof(TheoremObjectWithPoints)}: {objectWithPoints.GetType()}")
                    });
                }
 /// <inheritdoc/>
 public void InconstructibleContextualPictureByCloning(ContextualPicture previousContextualPicture, PicturesOfConfiguration newConfigurationPictures, InconsistentPicturesException exception)
 {
 }