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()); }
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()); }
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); }
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()); }
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(); }
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); }
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); }
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); }
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); }
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) }) }); }
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(); }
/// <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()}") })
/// <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)); })
/// <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(); }
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(); }
/// <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)); }
/// <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)); }
/// <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 }
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); } }
/// <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(); }
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); }
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); }
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); }
/// <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); }
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; }
/// <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))); }
/// <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}"), }; }
/// <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; }
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); }
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) }), }); }