Exemplo n.º 1
0
        /// <inheritdoc/>
        public bool IsTrueInAllPictures(Pictures pictures, Theorem theorem)
        {
            #region Ensure all inner objects are constructed

            // Go through the inner objects
            var objectsToConstruct = theorem.GetInnerConfigurationObjects()
                                     // And the object needed to construct them
                                     .GetDefiningObjects()
                                     // That are constructible
                                     .OfType <ConstructedConfigurationObject>()
                                     // That are not already constructed
                                     .Where(innerObject => !pictures.First().Contains(innerObject));

            // Construct all of them
            foreach (var constructedObject in objectsToConstruct)
            {
                // Safely perform
                var data = GeneralUtilities.TryExecute(
                    // The construction of the object
                    () => _constructor.Construct(pictures, constructedObject, addToPictures: true),
                    // Ignore any exception in this step (it will be solved in the next one)
                    (InconsistentPicturesException _) => { });

                // If there has been an inconsistency, we're sad and say this theorem is not true
                if (data == null)
                {
                    return(false);
                }

                // If there is an inconstructible object, the same
                if (data.InconstructibleObject != null)
                {
                    return(false);
                }
            }

            #endregion

            // If we got here, all needed objects are constructed. We need the theorem objects
            var theoremObjects = new Dictionary <TheoremObject, Dictionary <Picture, IAnalyticObject> >();

            #region Construct theorem objects

            // Get the inner base theorem objects, i.e. Line / Circle / Point
            // Then we will reconstruct the other i.e., LineSegment later...
            var baseTheoremObjects = theorem.InvolvedObjects
                                     // Each theorem object can bring more of them
                                     .SelectMany(theoremObject => theoremObject switch
            {
                // If the object is already base, we return it
                BaseTheoremObject _ => theoremObject.ToEnumerable(),

                // If we have a line segment, then its inner objects are points
                LineSegmentTheoremObject lineSegment => lineSegment.PointSet,

                // Unhandled cases
                _ => throw new ConstructorException($"Unhandled type of {nameof(TheoremObject)}: {theoremObject.GetType()}")
            })
Exemplo n.º 2
0
        /// <inheritdoc/>
        public (Theorem newTheorem, Configuration newConfiguration)? Simplify(Theorem theorem, Configuration configuration)
        {
            // Prepare the dictionary of replaced theorem objects
            var replacedTheoremObjects = new Dictionary <TheoremObject, TheoremObject>();

            #region Mapping theorem objects

            // We will try to replace each theorem object
            foreach (var theoremObject in theorem.InvolvedObjects)
            {
                // We're going to try to use some simplification rule for it
                foreach (var simplifcationRule in _data.Rules)
                {
                    // If the template simplifiable object has a different type, then we can't do much
                    if (!theoremObject.GetType().Equals(simplifcationRule.SimplifableObject.GetType()))
                    {
                        continue;
                    }

                    // Otherwise switch based on object type
                    switch (theoremObject)
                    {
                    // Point simplification is not handled, let's move on
                    case PointTheoremObject _:
                        continue;

                    // With objects with points (lines / circles) we can try to map those points
                    case TheoremObjectWithPoints objectWithPoints:

                        // If this object doesn't have a point, we can't do much
                        if (!objectWithPoints.DefinedByPoints)
                        {
                            continue;
                        }

                        #region Mapping line / circle

                        // Get the original points
                        var originalPoints = objectWithPoints.PointsList;

                        // Get the template points
                        var templatePoints = (TheoremObjectWithPoints)simplifcationRule.SimplifableObject;

                        // Go through the permutations of template points, each representing
                        // a possible mapping between them and original points
                        foreach (var orderedTemplatePoints in templatePoints.PointsList.Permutations())
                        {
                            #region Trying various mappings

                            // Enumerate them
                            foreach (var mapping in Map(orderedTemplatePoints, originalPoints))
                            {
                                #region Mapping the simplified object

                                // Otherwise we can use it to come up with the new theorem object
                                // First we must include its objects in the mapping (since Remap method requires it)
                                simplifcationRule.SimplifiedObject.GetInnerConfigurationObjects()
                                // Only those that aren't there yet
                                .Where(configurationObject => !mapping.ContainsKey(configurationObject))
                                // They are definitely constructed (loose should have been mapped by now)
                                .Cast <ConstructedConfigurationObject>()
                                // Remap each
                                .Select(constructedObject => (originalObject: constructedObject, mappedObject: new ConstructedConfigurationObject
                                                              (
                                                                  // The construction stays the same
                                                                  construction: constructedObject.Construction,

                                                                  // Map its arguments one by one
                                                                  input: constructedObject.PassedArguments.FlattenedList.Select(innerObject => mapping[innerObject]).ToArray()
                                                              )))
                                // Add them to the mapping
                                .ForEach(pair => mapping.Add(pair.originalObject, pair.mappedObject));

                                // Now we can finally map the simplified object
                                var newTheoremObject = simplifcationRule.SimplifiedObject.Remap(mapping);

                                #endregion

                                #region Checking if the mapping doesn't increase the number of configuration objects

                                // We need to find how many configuration objects we would need if we did the replaced
                                // In order to find out take the theorem objects
                                var neededObjects = theorem.InvolvedObjects
                                                    // Exclude the one to be replaced
                                                    .Except(theoremObject.ToEnumerable())
                                                    // Include the new one
                                                    .Concat(newTheoremObject)
                                                    // Find the inner configuration objects for each theorem object
                                                    .SelectMany(theoremObject => theoremObject.GetInnerConfigurationObjects())
                                                    // Use our helper method to find all the objects needed to define these
                                                    .GetDefiningObjects()
                                                    // And simply take their count
                                                    .Count;

                                // If this replacement would complicate the theorem, we need to keep looking...
                                if (neededObjects > configuration.AllObjects.Count)
                                {
                                    continue;
                                }

                                #endregion

                                // At this point the mapping is okay and we can add the object
                                replacedTheoremObjects.Add(theoremObject, newTheoremObject);

                                // We don't have to look for another one
                                break;
                            }

                            #endregion

                            // If the mapping has been successful, we don't have to look for another one
                            if (replacedTheoremObjects.ContainsKey(theoremObject))
                            {
                                break;
                            }
                        }

                        #endregion

                        break;

                    // Unhandled cases
                    default:
                        throw new TheoremSimplifierException($"Unhandled type of {nameof(TheoremObjectWithPoints)}: {theoremObject.GetType()}");
                    }

                    // If the mapping has been successful, we don't have to look for another one
                    if (replacedTheoremObjects.ContainsKey(theoremObject))
                    {
                        break;
                    }
                }
            }

            #endregion

            #region Constructing the final result

            // If no object has been mapped, then we cannot simplify the theorem
            if (replacedTheoremObjects.IsEmpty())
            {
                return(null);
            }

            // Otherwise we can recreate the theorem
            var newTheorem = new Theorem(theorem.Type, theorem.InvolvedObjects
                                         // Each object is either preserved or taken from the mapping
                                         .Select(theoremObject => replacedTheoremObjects.GetValueOrDefault(theoremObject) ?? theoremObject));

            // Now we need to find the new configuration. We do that by finding
            // the objects that are now unnecessary with respect to the new theorem
            var unnecessaryObjects = newTheorem.GetUnnecessaryObjects(configuration);

            // Now we create the new configuration by copying its objects in their order
            var newConfiguration = new Configuration(configuration.LooseObjectsHolder, configuration.ConstructedObjects
                                                     // With the exclusion of the objects that are now not necessary
                                                     .Except(unnecessaryObjects)
                                                     // And the inclusion the new objects that are taken from the inner objects of the new theorem
                                                     .Concat(newTheorem.GetInnerConfigurationObjects()
                                                     // And are constructed
                                                             .OfType <ConstructedConfigurationObject>()
                                                     // With the exclusion of those that already are there
                                                             .Where(innerObject => !configuration.ConstructedObjectsSet.Contains(innerObject)))
                                                     // They are constructed
                                                     .Cast <ConstructedConfigurationObject>()
                                                     // Now we can enumerate
                                                     .ToArray());

            // Finally we can return the result
            return(newTheorem, newConfiguration);

            #endregion
        }