Esempio n. 1
0
        public void Test_Quadrilateral_With_Medium_Partial_Symmetry()
        {
            // Prepare the objects
            var A = new LooseConfigurationObject(Point);
            var B = new LooseConfigurationObject(Point);
            var C = new LooseConfigurationObject(Point);
            var D = new LooseConfigurationObject(Point);
            var P = new ConstructedConfigurationObject(Incenter, A, B, D);
            var Q = new ConstructedConfigurationObject(Incenter, C, B, D);

            // Prepare the configuration
            var configuration = Configuration.DeriveFromObjects(Quadrilateral, P, Q);

            // Prepare the theorem
            // NOTE: I did not really try to make it be true in general
            var theorem = new Theorem(PerpendicularLines, new[]
            {
                new LineTheoremObject(P, Q),
                new LineTheoremObject(B, D)
            });

            // Rank
            var rank = new SymmetryRanker().Rank(theorem, configuration, allTheorems: null);

            // Assert
            rank.Rounded().Should().Be((3d / 9).Rounded());
        }
Esempio n. 2
0
        public void Test_Quadrilateral_With_Very_Strong_Partial_Symmetry()
        {
            // Prepare the objects
            var A = new LooseConfigurationObject(Point);
            var B = new LooseConfigurationObject(Point);
            var C = new LooseConfigurationObject(Point);
            var D = new LooseConfigurationObject(Point);
            var P = new ConstructedConfigurationObject(Midpoint, A, B);
            var Q = new ConstructedConfigurationObject(Midpoint, B, C);
            var R = new ConstructedConfigurationObject(Midpoint, C, D);
            var S = new ConstructedConfigurationObject(Midpoint, D, A);

            // Prepare the configuration
            var configuration = Configuration.DeriveFromObjects(Quadrilateral, P, Q, R, S);

            // Prepare the theorem
            // NOTE: I did not really try to make it be true in general
            var theorem = new Theorem(PerpendicularLines, new[]
            {
                new LineTheoremObject(P, R),
                new LineTheoremObject(Q, S)
            });

            // Rank
            var rank = new SymmetryRanker().Rank(theorem, configuration, allTheorems: null);

            // Assert
            rank.Rounded().Should().Be((5d / 9).Rounded());
        }
Esempio n. 3
0
        public void Test_That_Old_Theorem_Invalidation_Happens_With_Concurrent_Lines()
        {
            // Create the objects
            var A = new LooseConfigurationObject(Point);
            var B = new LooseConfigurationObject(Point);
            var C = new LooseConfigurationObject(Point);
            var D = new ConstructedConfigurationObject(Midpoint, B, C);
            var E = new ConstructedConfigurationObject(Midpoint, C, A);
            var F = new ConstructedConfigurationObject(Midpoint, A, B);
            var G = new ConstructedConfigurationObject(Centroid, A, B, C);

            // Create the configuration
            var configuration = Configuration.DeriveFromObjects(Triangle, D, E, F, G);

            // Run
            var(oldTheorems, newTheorems, invalidOldTheorems, allTheorems) = FindTheorems(configuration);

            // Assert that old + new - invalidated = all
            oldTheorems.AllObjects.Concat(newTheorems.AllObjects).Except(invalidOldTheorems).OrderlessEquals(allTheorems.AllObjects).Should().BeTrue();

            // Create the invalidated theorem
            var invalidatedTheorem = new Theorem(ConcurrentLines, new[]
            {
                new LineTheoremObject(A, D),
                new LineTheoremObject(B, E),
                new LineTheoremObject(C, F)
            });

            // Assert it is the only one
            invalidOldTheorems.OrderlessEquals(new[] { invalidatedTheorem });

            // Assert it is indeed old
            oldTheorems.AllObjects.Should().Contain(invalidatedTheorem);
        }
Esempio n. 4
0
        public void Test_Triangle_With_Partial_Symmetry()
        {
            // Prepare the objects
            var A = new LooseConfigurationObject(Point);
            var B = new LooseConfigurationObject(Point);
            var C = new LooseConfigurationObject(Point);
            var M = new ConstructedConfigurationObject(Midpoint, A, B);
            var N = new ConstructedConfigurationObject(Midpoint, A, C);

            // Prepare the configuration
            var configuration = Configuration.DeriveFromObjects(Triangle, A, B, C, M, N);

            // Prepare the theorem
            var theorem = new Theorem(ParallelLines, new[]
            {
                new LineTheoremObject(B, C),
                new LineTheoremObject(M, N)
            });

            // Rank
            var rank = new SymmetryRanker().Rank(theorem, configuration, allTheorems: null);

            // Assert
            rank.Rounded().Should().Be((1d / 3).Rounded());
        }
Esempio n. 5
0
        public void Test_That_Simplification_Does_Not_Happen_When_It_Would_Add_More_Objects()
        {
            // Create the objects
            var A = new LooseConfigurationObject(Point);
            var B = new LooseConfigurationObject(Point);
            var C = new LooseConfigurationObject(Point);
            var D = new ConstructedConfigurationObject(Incenter, A, B, C);
            var E = new ConstructedConfigurationObject(PerpendicularProjectionOnLineFromPoints, D, B, C);
            var F = new ConstructedConfigurationObject(PerpendicularProjectionOnLineFromPoints, D, A, C);
            var G = new ConstructedConfigurationObject(PerpendicularProjectionOnLineFromPoints, D, A, B);
            var l = new ConstructedConfigurationObject(ParallelLineToLineFromPoints, A, E, F);

            // Create the configuration
            var configuration = Configuration.DeriveFromObjects(Triangle, A, B, C, l);

            // Create the theorem
            var theorem = new Theorem(ConcurrentLines, new[]
            {
                new LineTheoremObject(C, D),
                new LineTheoremObject(E, G),
                new LineTheoremObject(l)
            });

            // Let it be simplified. Theoretically speaking, CD is the angle bisector and it could be applied,
            // but neither C nor D could be removed from the configuration, i.e. we would have all the objects
            // + angle bisector after applying the rule. We don't want that
            var result = Simplify(theorem, configuration);

            // Assert it couldn't be done
            result.Should().BeNull();
        }
Esempio n. 6
0
        public void Test_That_Old_Theorem_Invalidation_Happens_With_Line_Tangent_To_Circle()
        {
            // Create the objects
            var A = new LooseConfigurationObject(Point);
            var B = new LooseConfigurationObject(Point);
            var C = new LooseConfigurationObject(Point);
            var c = new ConstructedConfigurationObject(Incircle, A, B, C);
            var I = new ConstructedConfigurationObject(Incenter, A, B, C);
            var D = new ConstructedConfigurationObject(PerpendicularProjectionOnLineFromPoints, I, B, C);

            // Create the configuration
            var configuration = Configuration.DeriveFromObjects(Triangle, c, I, D);

            // Run
            var(oldTheorems, newTheorems, invalidOldTheorems, allTheorems) = FindTheorems(configuration);

            // Assert that old + new - invalidated = all
            oldTheorems.AllObjects.Concat(newTheorems.AllObjects).Except(invalidOldTheorems).OrderlessEquals(allTheorems.AllObjects).Should().BeTrue();

            // Create the invalidated theorem
            var invalidatedTheorem = new Theorem(LineTangentToCircle, new TheoremObject[]
            {
                new LineTheoremObject(B, C),
                new CircleTheoremObject(c)
            });

            // Assert it is the only one
            invalidOldTheorems.OrderlessEquals(new[] { invalidatedTheorem });

            // Assert it is indeed old
            oldTheorems.AllObjects.Should().Contain(invalidatedTheorem);
        }
Esempio n. 7
0
        public void Test_Triangle_With_Full_Symmetry()
        {
            // Prepare the objects
            var A = new LooseConfigurationObject(Point);
            var B = new LooseConfigurationObject(Point);
            var C = new LooseConfigurationObject(Point);
            var P = new ConstructedConfigurationObject(Midpoint, B, C);
            var Q = new ConstructedConfigurationObject(Midpoint, C, A);
            var R = new ConstructedConfigurationObject(Midpoint, A, B);

            // Prepare the configuration
            var configuration = Configuration.DeriveFromObjects(Triangle, A, B, C, P, Q, R);

            // Prepare the theorem
            var theorem = new Theorem(ConcurrentLines, new[]
            {
                new LineTheoremObject(A, P),
                new LineTheoremObject(B, Q),
                new LineTheoremObject(C, R)
            });

            // Rank
            var rank = new SymmetryRanker().Rank(theorem, configuration, allTheorems: null);

            // Assert
            rank.Should().Be(1);
        }
Esempio n. 8
0
        public Theorem ParseString(string str)
        {
            Theorem theorem = new Theorem();

            theorem.Body = str;
            var regex = new Regex(@"[\[\(](a,b)[\]\)]");

            foreach (Match match in new Regex(@"[\[\(](a,b)[\]\)]").Matches(theorem.Body))
            {
                theorem.Intervals.Value.Add(match.Value);
            }

            Constants.FEATURES features = new Constants.FEATURES();
            foreach (FieldInfo field in typeof(Constants.FEATURES).GetFields())
            {
                string feature = field.GetValue(features).ToString();

                while (str.Contains(feature))
                {
                    theorem.Features.Value.Add(feature);
                    str = str.Replace(feature, string.Empty);
                }
            }
            return(theorem);
        }
Esempio n. 9
0
        public void Test_Quadrilateral_With_Full_Symmetry()
        {
            // Prepare the objects
            var A = new LooseConfigurationObject(Point);
            var B = new LooseConfigurationObject(Point);
            var C = new LooseConfigurationObject(Point);
            var D = new LooseConfigurationObject(Point);
            var P = new ConstructedConfigurationObject(Incenter, A, B, C);
            var Q = new ConstructedConfigurationObject(Incenter, B, C, D);
            var R = new ConstructedConfigurationObject(Incenter, C, D, A);
            var S = new ConstructedConfigurationObject(Incenter, D, A, B);

            // Prepare the configuration
            var configuration = Configuration.DeriveFromObjects(Quadrilateral, P, Q, R, S);

            // Prepare the theorem
            // NOTE: I did not really try to make it be true in general
            var theorem = new Theorem(ConcyclicPoints, P, Q, R, S);

            // Rank
            var rank = new SymmetryRanker().Rank(theorem, configuration, allTheorems: null);

            // Assert
            rank.Should().Be(1);
        }
Esempio n. 10
0
        public void Test_InferTheoremsFromSymmetry_PartialSymmetry()
        {
            // Draw configuration with medians
            var A   = new LooseConfigurationObject(Point);
            var B   = new LooseConfigurationObject(Point);
            var C   = new LooseConfigurationObject(Point);
            var mAC = new ConstructedConfigurationObject(Midpoint, A, C);
            var mAB = new ConstructedConfigurationObject(Midpoint, A, B);
            var D   = new ConstructedConfigurationObject(PerpendicularProjectionOnLineFromPoints, A, B, C);

            // Create the configuration
            var configuration = Configuration.DeriveFromObjects(Triangle, mAC, mAB, D);

            // Create the theorem
            var theorem = new Theorem(ParallelLines, new[]
            {
                new LineTheoremObject(B, D),
                new LineTheoremObject(mAB, mAC)
            });

            // We can infer one other isomorphic theorem
            theorem.InferTheoremsFromSymmetry(configuration).Should().BeEquivalentTo(new[]
            {
                new Theorem(ParallelLines, new[]
                {
                    new LineTheoremObject(C, D),
                    new LineTheoremObject(mAB, mAC)
                })
            });
        }
Esempio n. 11
0
        private static void Print <T>(Theorem <T> t) where T : class
        {
            Console.WriteLine(t);
            var res = t.Solve();

            Console.WriteLine(res == null ? "none" : res.ToString());
            Console.WriteLine();
        }
Esempio n. 12
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()}")
            })
Esempio n. 13
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));
            })
Esempio n. 14
0
        /// <summary>
        /// Handles an inferred equality theorem by communicating it with the normalization helper and scheduler, and also handling proof
        /// construction is the proof data is provided.
        /// </summary>
        /// <param name="equality">The equality theorem to be handled.</param>
        /// <param name="helper">The normalization helper that verifies and normalizes the theorem.</param>
        /// <param name="scheduler">The scheduler of inference rules used for the new objects and theorems this equality might have brought.</param>
        /// <param name="proofData">Either the data needed to mark the theorem's inference in case it's correct; or null, if we are not constructing proofs.</param>
        /// <param name="isValid">Indicates whether the theorem has been found geometrically valid.</param>
        /// <param name="anyChangeOfNormalVersion">Indicates whether this equality caused any change of the normal version of some object.</param>
        private void HandleEquality(Theorem equality, NormalizationHelper helper, Scheduler scheduler, ProofData proofData, out bool isValid, out bool anyChangeOfNormalVersion)
        {
            // Mark the equality to the helper
            helper.MarkProvedEquality(equality, out var isNew, out isValid, out var result);

            // If it turns out not new or valid, we're done
            if (!isNew || !isValid)
            {
                // No removed objects
                anyChangeOfNormalVersion = false;

                // We're done
                return;
            }

            // If we should construct proof, mark the inference to the proof builder
            proofData?.ProofBuilder.AddImplication(proofData.InferenceData, equality, proofData.Assumptions);

            #region Handling new normalized theorems

            // Go through all of them
            foreach (var(originalTheorem, equalities, normalizedTheorem) in result.NormalizedNewTheorems)
            {
                // If we should construct proof, mark the normalized theorem to the proof builder
                proofData?.ProofBuilder.AddImplication(ReformulatedTheorem, normalizedTheorem, assumptions: equalities.Concat(originalTheorem).ToArray());

                // Let the scheduler know about the new normalized theorem
                scheduler.ScheduleAfterProving(normalizedTheorem);
            }

            #endregion

            // Invalidate theorems
            result.DismissedTheorems.ForEach(scheduler.InvalidateTheorem);

            // Invalidate removed objects
            result.RemovedObjects.ForEach(scheduler.InvalidateObject);

            // Handle changed objects
            result.ChangedObjects.ForEach(changedObject =>
            {
                // First we will invalidate them
                scheduler.InvalidateObject(changedObject);

                // And now schedule for them again as if they were knew because now the results of schedules might be different
                scheduler.ScheduleAfterDiscoveringObject(changedObject);
            });

            // Handle entirely new objects
            result.NewObjects.ForEach(newObject => HandleNewObject(newObject, helper, scheduler, proofData?.ProofBuilder));

            // Set if there has been any change of normal version, which is indicated by removing
            // an object or changing its normal version
            anyChangeOfNormalVersion = result.RemovedObjects.Any() || result.ChangedObjects.Any();
        }
Esempio n. 15
0
        private static void Print <T>(Theorem <T> t) where T : class
        {
            Console.WriteLine(t);
            var startTime = stopwatch.Elapsed;
            var res       = t.Solve();
            var endTime   = stopwatch.Elapsed;

            Console.WriteLine(res == null ? "none" : res.ToString());
            Console.WriteLine($"Time to solve: {endTime - startTime}");
            Console.WriteLine();
        }
Esempio n. 16
0
        /// <inheritdoc/>
        public RankedTheorem Rank(Theorem theorem, Configuration configuration, TheoremMap allTheorems)
        {
            // Prepare the ranking dictionary by applying every ranker
            var rankings = _rankers.Select(ranker => (ranker.RankedAspect, ranking: ranker.Rank(theorem, configuration, allTheorems)))
                           // And wrapping the result to a dictionary together with the coefficient from the settings
                           .ToDictionary(pair => pair.RankedAspect, pair => new RankingData(pair.ranking, _settings.RankingCoefficients[pair.RankedAspect]));

            // Wrap the final ranking in a ranking object
            var ranking = new TheoremRanking(rankings);

            // Now we can return the ranked theorem
            return(new RankedTheorem(theorem, ranking, configuration));
        }
Esempio n. 17
0
 /// <summary>
 /// Initializes a new instance of the <see cref="LoadedInferenceRule"/> class.
 /// </summary>
 /// <param name="declaredObjects">The objects that are referenced in the assumptions and the conclusion.</param>
 /// <param name="assumptionGroups">The assumptions grouped in a way that assumptions in the same group are mutually isomorphic (see <see cref="InferenceRule"/>).</param>
 /// <param name="negativeAssumptions">The assumptions that must be not true in order for inferred theorems to hold.</param>
 /// <param name="conclusion">The conclusion that can be inferred if the assumptions are met.</param>
 /// <param name="relativeFileName">The file name relative to the inference rule folder of the rule.</param>
 /// <param name="number">The ordinal number of the rule in the inference rule file.</param>
 /// <param name="adjustmentMessage">The message indicating whether how the rule has been adjusted by the loader (see <see cref="AdjustmentMessage"/>).</param>
 public LoadedInferenceRule(IReadOnlyList <ConstructedConfigurationObject> declaredObjects,
                            IReadOnlyHashSet <IReadOnlyHashSet <Theorem> > assumptionGroups,
                            IReadOnlyList <Theorem> negativeAssumptions,
                            Theorem conclusion,
                            string relativeFileName,
                            int number,
                            string adjustmentMessage)
     : base(declaredObjects, assumptionGroups, negativeAssumptions, conclusion)
 {
     RelativeFileName  = relativeFileName ?? throw new ArgumentNullException(nameof(relativeFileName));
     Number            = number;
     AdjustmentMessage = adjustmentMessage ?? throw new ArgumentNullException(nameof(adjustmentMessage));
 }
Esempio n. 18
0
        /// <summary>
        /// Handles an inferred theorem by communicating it with the normalization helper and scheduler, and also handling proof
        /// construction is the proof data is provided.
        /// </summary>
        /// <param name="theorem">The theorem to be handled.</param>
        /// <param name="helper">The normalization helper that verifies and normalizes the theorem.</param>
        /// <param name="scheduler">The scheduler of inference rules used for the theorem if it is correct.</param>
        /// <param name="proofData">Either the data needed to mark the theorem's inference in case it's correct; or null, if we are not constructing proofs.</param>
        /// <param name="isValid">Indicates whether the theorem has been found geometrically valid.</param>
        private void HandleNonequality(Theorem theorem, NormalizationHelper helper, Scheduler scheduler, ProofData proofData, out bool isValid)
        {
            // Mark the theorem to the helper
            helper.MarkProvedNonequality(theorem, out var isNew, out isValid, out var normalizedTheorem, out var equalities);

            // If it turns out not new or valid, we're done
            if (!isNew || !isValid)
            {
                return;
            }

            #region Handle proof construction

            // Mark the original theorem
            proofData?.ProofBuilder.AddImplication(proofData.InferenceData, theorem, proofData.Assumptions);

            // If any normalization happened
            if (equalities.Any())
            {
                // Mark the normalized theorem too
                proofData?.ProofBuilder.AddImplication(ReformulatedTheorem, normalizedTheorem, assumptions: equalities.Concat(theorem).ToArray());
            }

            #endregion

            // Let the scheduler know
            scheduler.ScheduleAfterProving(normalizedTheorem);

            #region Inference from symmetry

            // If the theorem use an object that is not part of the original configuration,
            // then we will not do any symmetry inference. If it could prove a new theorem,
            // then this new theorem would be inferable conventionally
            if (!normalizedTheorem.GetInnerConfigurationObjects().All(helper.Configuration.AllObjects.Contains))
            {
                return;
            }

            // Otherwise try to infer new theorems using this one
            foreach (var inferredTheorem in normalizedTheorem.InferTheoremsFromSymmetry(helper.Configuration))
            {
                // If it can be done, make sure the proof builder knows it
                proofData?.ProofBuilder.AddImplication(InferableFromSymmetry, inferredTheorem, assumptions: new[] { normalizedTheorem });

                // Call this method to handle this new inferred theorem, without caring if it is valid (it should be logically)
                HandleNonequality(inferredTheorem, helper, scheduler, proofData, isValid: out var _);
            }

            #endregion
        }
Esempio n. 19
0
        private void btnConfirm_Click(object sender, EventArgs e)
        {
            Theorem theorem = tcc.ParseString(txtTeorema.Text);

            theorem.Id = currentTheorem.Id;
            if (tcc.CheckTheorem(theorem))
            {
                MessageBox.Show("Esatto", "Esatto", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            else
            {
                MessageBox.Show("Sbagliato", "Sbagliato", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
        }
Esempio n. 20
0
        /// <summary>
        /// Initializes a new instance of the <see cref="InferenceRule"/> class.
        /// </summary>
        /// <param name="declaredObjects">The objects that are referenced in the assumptions and the conclusion.</param>
        /// <param name="assumptionGroups">The assumptions grouped in a way that assumptions in the same group are mutually isomorphic (see <see cref="InferenceRule"/>).</param>
        /// <param name="negativeAssumptions">The assumptions that must be not true in order for inferred theorems to hold.</param>
        /// <param name="conclusion">The conclusion that can be inferred if the assumptions are met.</param>
        public InferenceRule(IReadOnlyList <ConstructedConfigurationObject> declaredObjects,
                             IReadOnlyHashSet <IReadOnlyHashSet <Theorem> > assumptionGroups,
                             IReadOnlyList <Theorem> negativeAssumptions,
                             Theorem conclusion)
        {
            DeclaredObjects     = declaredObjects ?? throw new ArgumentNullException(nameof(declaredObjects));
            AssumptionGroups    = assumptionGroups ?? throw new ArgumentNullException(nameof(assumptionGroups));
            NegativeAssumptions = negativeAssumptions ?? throw new ArgumentNullException(nameof(negativeAssumptions));
            Conclusion          = conclusion ?? throw new ArgumentNullException(nameof(conclusion));

            // Find the number of needed construction by taking the declared objects
            NeededConstructionTypes = declaredObjects
                                      // Grouping them by their construction
                                      .GroupBy(template => template.Construction)
                                      // And counting the number of objects in each group
                                      .ToDictionary(group => group.Key, group => group.Count());

            // Find the number of needed assumption types by taking flattened assumptions
            NeededAssumptionTypes = assumptionGroups.Flatten()
                                    // Grouping them by their type
                                    .GroupBy(group => group.Type)
                                    // And counting the number of objects in each group
                                    .ToDictionary(group => group.Key, group => group.Count());

            // Find the explicit objects mappable to implicit ones by taking the assumptions
            ExplicitObjectsMappableToImplicitOnes = AssumptionGroups.Flatten()
                                                    // And the conclusion
                                                    .Concat(Conclusion)
                                                    // Take their inner objects
                                                    .SelectMany(templateTheorem => templateTheorem.InvolvedObjects)
                                                    // That are distinct
                                                    .Distinct()
                                                    // And are objects with points
                                                    .OfType <TheoremObjectWithPoints>()
                                                    // And are defined explicitly
                                                    .Where(templateObject => templateObject.DefinedByExplicitObject
                                                    // And their explicit object is loose
                                                           && templateObject.ConfigurationObject is LooseConfigurationObject
                                                    // And there is no assumption
                                                           && !AssumptionGroups.Flatten()
                                                    // Or conclusion
                                                           .Concat(Conclusion)
                                                    // That is incidence
                                                           .Any(templateTheorem => templateTheorem.Type == TheoremType.Incidence
                                                    // And contains this object
                                                                && templateTheorem.InvolvedObjects.Contains(templateObject)))
                                                    // Enumerate
                                                    .ToReadOnlyHashSet();
        }
Esempio n. 21
0
        public void Test_More_Medians_Defined_Via_Midpoints()
        {
            // Create the objects
            var A = new LooseConfigurationObject(Point);
            var B = new LooseConfigurationObject(Point);
            var C = new LooseConfigurationObject(Point);
            var P = new ConstructedConfigurationObject(Midpoint, A, B);
            var Q = new ConstructedConfigurationObject(Midpoint, B, C);
            var R = new ConstructedConfigurationObject(Midpoint, C, A);

            // Create the configuration
            var configuration = Configuration.DeriveFromObjects(Triangle, A, B, C, P, Q, R);

            // Create the theorem
            var theorem = new Theorem(ConcurrentLines, new[]
            {
                new LineTheoremObject(C, P),
                new LineTheoremObject(A, Q),
                new LineTheoremObject(B, R)
            });

            // Let it be simplified
            var result = Simplify(theorem, configuration);

            // Assert there is some result
            result.Should().NotBeNull();

            // Create the new objects
            var Amedian = new ConstructedConfigurationObject(Median, A, B, C);
            var Bmedian = new ConstructedConfigurationObject(Median, B, A, C);
            var Cmedian = new ConstructedConfigurationObject(Median, C, A, B);

            // Create the new configuration
            var newConfiguration = Configuration.DeriveFromObjects(Triangle, A, B, C, Amedian, Bmedian, Cmedian);

            // Create the new theorem
            var newTheorem = new Theorem(ConcurrentLines, new[]
            {
                new LineTheoremObject(Amedian),
                new LineTheoremObject(Bmedian),
                new LineTheoremObject(Cmedian)
            });

            // Assert
            result.Value.newConfiguration.Should().Be(newConfiguration);
            result.Value.newTheorem.Should().Be(newTheorem);
        }
Esempio n. 22
0
        public void Test_Median_Defined_Via_Midpoint_And_Parallelogram_Point()
        {
            // Create the objects
            var A       = new LooseConfigurationObject(Point);
            var B       = new LooseConfigurationObject(Point);
            var C       = new LooseConfigurationObject(Point);
            var Bmedian = new ConstructedConfigurationObject(Median, B, A, C);
            var Cmedian = new ConstructedConfigurationObject(Median, C, A, B);
            var M       = new ConstructedConfigurationObject(Midpoint, B, C);
            var N       = new ConstructedConfigurationObject(ParallelogramPoint, A, B, C);

            // Create the configuration
            var configuration = Configuration.DeriveFromObjects(Triangle, A, B, C, Bmedian, Cmedian, M, N);

            // Create the theorem
            var theorem = new Theorem(ConcurrentLines, new[]
            {
                new LineTheoremObject(Bmedian),
                new LineTheoremObject(Cmedian),
                new LineTheoremObject(M, N)
            });

            // Let it be simplified
            var result = Simplify(theorem, configuration);

            // Assert there is some result
            result.Should().NotBeNull();

            // Create the new objects
            var Nmedian = new ConstructedConfigurationObject(Median, N, B, C);

            // Create the new configuration
            var newConfiguration = Configuration.DeriveFromObjects(Triangle, A, B, C, Nmedian, Bmedian, Cmedian);

            // Create the new theorem
            var newTheorem = new Theorem(ConcurrentLines, new[]
            {
                new LineTheoremObject(Nmedian),
                new LineTheoremObject(Bmedian),
                new LineTheoremObject(Cmedian)
            });

            // Assert
            result.Value.newConfiguration.Should().Be(newConfiguration);
            result.Value.newTheorem.Should().Be(newTheorem);
        }
Esempio n. 23
0
        public void Test_Nine_Point_Circle()
        {
            // Create the objects
            var A        = new LooseConfigurationObject(Point);
            var B        = new LooseConfigurationObject(Point);
            var C        = new LooseConfigurationObject(Point);
            var P        = new ConstructedConfigurationObject(Midpoint, A, B);
            var Q        = new ConstructedConfigurationObject(Midpoint, B, C);
            var R        = new ConstructedConfigurationObject(Midpoint, C, A);
            var incircle = new ConstructedConfigurationObject(Incircle, A, B, C);

            // Create the configuration
            var configuration = Configuration.DeriveFromObjects(Triangle, incircle, P, Q, R);

            // Create the theorem
            var theorem = new Theorem(TangentCircles, new[]
            {
                new CircleTheoremObject(incircle),
                new CircleTheoremObject(P, Q, R)
            });

            // Let it be simplified
            var result = Simplify(theorem, configuration);

            // Assert there is some result
            result.Should().NotBeNull();

            // Create the new objects
            var ninePointCircle = new ConstructedConfigurationObject(NinePointCircle, A, B, C);

            // Create the new configuration
            var newConfiguration = Configuration.DeriveFromObjects(Triangle, ninePointCircle, incircle);

            // Create the new theorem
            var newTheorem = new Theorem(TangentCircles, new[]
            {
                new CircleTheoremObject(incircle),
                new CircleTheoremObject(ninePointCircle)
            });

            // Assert
            result.Value.newConfiguration.Should().Be(newConfiguration);
            result.Value.newTheorem.Should().Be(newTheorem);
        }
Esempio n. 24
0
        /// <inheritdoc/>
        public override double Rank(Theorem theorem, Configuration configuration, TheoremMap allTheorems)
        {
            // Find the number of possible symmetry mappings of loose objects
            var allSymmetryMappingsCount = configuration.LooseObjectsHolder.GetSymmetricMappings().Count();

            // If there is no symmetry mapping for the layout, then 0 seems
            // like a good ranking
            if (allSymmetryMappingsCount == 0)
            {
                return(0);
            }

            // Otherwise find the number of actual symmetry mappings that
            // preserve both configuration and theorem
            var validSymmetryMappingsCount = theorem.GetSymmetryMappings(configuration).Count();

            // The symmetry ranking is the percentage of valid mappings
            return((double)validSymmetryMappingsCount / allSymmetryMappingsCount);
        }
Esempio n. 25
0
        private void btnStart_Click(object sender, EventArgs e)
        {
            try
            {
                tcc = new TheoremsChecker(txtSource.Text);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Errore caricamento file teoremi", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            lblTeorema.Enabled = true;
            txtTeorema.Enabled = true;
            btnConfirm.Enabled = true;

            currentTheorem  = tcc.GetRndTheorem();
            lblTeorema.Text = currentTheorem.Name;
        }
Esempio n. 26
0
        /// <inheritdoc/>
        public override double Rank(Theorem theorem, Configuration configuration, TheoremMap allTheorems)
        {
            // Pull the number of constructed objects for comfort
            var n = configuration.ConstructedObjects.Count;

            // If there is at most 1 constructed object, let the level be 1
            // This should practically not happen, because we are supposed to be ranking
            // actual interesting problems...
            if (n <= 1)
            {
                return(1);
            }

            // Otherwise calculate the levels of objects
            var levels = configuration.CalculateObjectLevels();

            // And apply the formula from the documentations, i.e. 1 - 6[(l1^2+...+ln^2) - n] / [n(n-1)(2n+5)]
            return(1 - 6d * (levels.Values.Select(level => level * level).Sum() - n) / (n * (n - 1) * (2 * n + 5)));
        }
Esempio n. 27
0
        /// <summary>
        /// Initializes a new instance of the <see cref="AnalyticTheorem"/> class.
        /// </summary>
        /// <param name="theorem">The theorem that should be drawn analytically.</param>
        /// <param name="picture">The picture where the inner objects of the theorem are drawn.</param>
        public AnalyticTheorem(Theorem theorem, Picture picture)
        {
            // Set the type
            _type = theorem.Type;

            // Set the content by switching on the type
            _content = _type switch
            {
                // These types can be compared as object sets
                TheoremType.CollinearPoints or
                TheoremType.ConcyclicPoints or
                TheoremType.ConcurrentLines or
                TheoremType.ParallelLines or
                TheoremType.PerpendicularLines or
                TheoremType.TangentCircles or
                TheoremType.LineTangentToCircle or
                TheoremType.Incidence =>
                // Take the inner objects
                theorem.InvolvedObjects
                // We know they are base
                .Cast <BaseTheoremObject>()
                // And therefore constructible
                .Select(picture.Construct)
                // Enumerate them to a read-only hash set
                .ToReadOnlyHashSet(),

                // In this case we have two line segment objects
                TheoremType.EqualLineSegments =>
                // Take the inner objects
                theorem.InvolvedObjects
                // We know they are line segments
                .Cast <LineSegmentTheoremObject>()
                // From each create their point set
                .Select(segment => segment.PointSet.Select(picture.Construct).ToReadOnlyHashSet())
                // Enumerate them to a read-only hash set
                .ToReadOnlyHashSet(),

                // Unhandled cases
                _ => throw new TheoremSorterException($"Unhandled value of {nameof(TheoremType)}: {_type}"),
            };
        }
Esempio n. 28
0
        /// <inheritdoc/>
        public void MarkInvalidInferrence(Configuration configuration, Theorem invalidConclusion, InferenceRule inferenceRule, Theorem[] negativeAssumptions, Theorem[] possitiveAssumptions)
        {
            // Prepare the file path for the rule with the name of the rule
            var filePath = Path.Combine(_settings.InvalidInferenceFolder, $"{inferenceRule.ToString().Replace(Path.DirectorySeparatorChar, '_')}.{_settings.FileExtension}");

            // If adding this inference would reach the maximal number of written inferences, we're done
            if (_invalidInferencesPerFile.GetValueOrDefault(filePath) + 1 > _settings.MaximalNumberOfInvalidInferencesPerFile)
            {
                return;
            }

            // Otherwise create or get the file in the invalid inference folder
            using var writer = new StreamWriter(filePath, append: true);

            // Prepare the formatter of the configuration
            var formatter = new OutputFormatter(configuration.AllObjects);

            // Write the configuration
            writer.WriteLine(formatter.FormatConfiguration(configuration));

            // An empty line
            writer.WriteLine();

            // Write the incorrect theorem
            writer.WriteLine($" {formatter.FormatTheorem(invalidConclusion)}");

            // Write its assumptions
            possitiveAssumptions.ForEach(assumption => writer.WriteLine($"  - {formatter.FormatTheorem(assumption)}"));

            // As well as negative ones
            negativeAssumptions.ForEach(assumption => writer.WriteLine($"  ! {formatter.FormatTheorem(assumption)}"));

            // Separator
            writer.WriteLine("--------------------------------------------------\n");

            // Mark that we've used this inference
            _invalidInferencesPerFile[filePath] = _invalidInferencesPerFile.GetValueOrDefault(filePath) + 1;
        }
Esempio n. 29
0
        public bool CheckTheorem(Theorem Theorem)
        {
            Theorem xmlTheorem = getTheoremById(Theorem.Id);

            for (int i = 0; i < xmlTheorem.Intervals.Value.Count; i++)
            {
                if (!xmlTheorem.Intervals.Value[i].Equals(Theorem.Intervals.Value[i]))
                {
                    return(false);
                }
            }
            for (int i = 0; i < xmlTheorem.Features.Value.Count; i++)
            {
                if (!xmlTheorem.Features.Value[i].Equals(Theorem.Features.Value[i]))
                {
                    return(false);
                }
            }
            if (textDiff(xmlTheorem.Body, Theorem.Body) > 75)
            {
                return(false);
            }
            return(true);
        }
Esempio n. 30
0
        public void Test_InferTheoremsFromSymmetry_FullSymmetry()
        {
            // Draw configuration with medians
            var A = new LooseConfigurationObject(Point);
            var B = new LooseConfigurationObject(Point);
            var C = new LooseConfigurationObject(Point);
            var D = new ConstructedConfigurationObject(Midpoint, A, B);
            var E = new ConstructedConfigurationObject(Midpoint, B, C);
            var F = new ConstructedConfigurationObject(Midpoint, A, C);

            // Create the configuration
            var configuration = Configuration.DeriveFromObjects(Triangle, D, E, F);

            // Create the theorem
            var theorem = new Theorem(ParallelLines, new[]
            {
                new LineTheoremObject(A, C),
                new LineTheoremObject(D, E)
            });

            // We can infer two other theorems from symmetry
            theorem.InferTheoremsFromSymmetry(configuration).Should().BeEquivalentTo(new[]
            {
                new Theorem(ParallelLines, new[]
                {
                    new LineTheoremObject(A, B),
                    new LineTheoremObject(E, F)
                }),

                new Theorem(ParallelLines, new[]
                {
                    new LineTheoremObject(B, C),
                    new LineTheoremObject(D, F)
                }),
            });
        }