private static List<EdgeAggregator> InstantiateFromAltitude(GroundedClause clause) { List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); if (clause is Intersection) { Intersection inter = clause as Intersection; // We are only interested in straight-angle type intersections if (inter.StandsOnEndpoint()) return newGrounded; if (!inter.IsPerpendicular()) return newGrounded; foreach (Altitude altitude in candidateAltitude) { newGrounded.AddRange(InstantiateFromAltitude(inter, altitude)); } candidateIntersection.Add(inter); } else if (clause is Altitude) { Altitude altitude = clause as Altitude; foreach (Intersection inter in candidateIntersection) { newGrounded.AddRange(InstantiateFromAltitude(inter, altitude)); } candidateAltitude.Add(altitude); } return newGrounded; }
public static void Instantiate(GroundedClause clause) { annotation.active = EngineUIBridge.JustificationSwitch.RIGHT_TRIANGLE_DEFINITION; List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); // // Instantiating FROM a right triangle // Strengthened streng = clause as Strengthened; if (streng == null) return; if (streng.strengthened is RightTriangle) { candidateRight.Add(streng); foreach (Strengthened iso in candidateIsosceles) { InstantiateRightTriangle(streng, iso); } } else if (streng.strengthened is IsoscelesTriangle) { candidateIsosceles.Add(streng); foreach (Strengthened right in candidateRight) { InstantiateRightTriangle(right, streng); } } }
// // This implements forward and Backward instantiation // public static List<EdgeAggregator> Instantiate(GroundedClause clause) { annotation.active = EngineUIBridge.JustificationSwitch.PERPENDICULAR_DEFINITION; // FROM Perpendicular if (clause is Perpendicular) return InstantiateFromPerpendicular(clause, clause as Perpendicular); // TO Perpendicular if (clause is RightAngle || clause is Intersection) return InstantiateToPerpendicular(clause); // Handle Strengthening; may be a Perpendicular (FROM) or Right Angle (TO) Strengthened streng = clause as Strengthened; if (streng != null) { if (streng.strengthened is Perpendicular && !(streng.strengthened is PerpendicularBisector)) { return InstantiateFromPerpendicular(clause, streng.strengthened as Perpendicular); } else if (streng.strengthened is RightAngle) { return InstantiateToPerpendicular(clause); } } return new List<EdgeAggregator>(); }
public static List<EdgeAggregator> InstantiateToPerpendicular(GroundedClause clause) { List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); if (clause is Intersection) { // Since we receive intersections right away in the instantiation process, just store the intersections candidateIntersections.Add(clause as Intersection); } else if (clause is RightAngle) { RightAngle ra = clause as RightAngle; foreach (Intersection inter in candidateIntersections) { newGrounded.AddRange(InstantiateToPerpendicular(inter, ra, clause)); } } else if (clause is Strengthened) { Strengthened streng = clause as Strengthened; // Only intrerested in right angles if (!(streng.strengthened is RightAngle)) return newGrounded; foreach (Intersection inter in candidateIntersections) { newGrounded.AddRange(InstantiateToPerpendicular(inter, streng.strengthened as RightAngle, clause)); } } return newGrounded; }
public static List <GenericInstantiator.EdgeAggregator> Instantiate(GroundedClause gc) { List <GenericInstantiator.EdgeAggregator> newGrounded = new List <GenericInstantiator.EdgeAggregator>(); Segment segment = gc as Segment; if (segment == null) { return(newGrounded); } // Only generate reflexive if this segment is shared if (!segment.isShared()) { return(newGrounded); } GeometricCongruentSegments ccss = new GeometricCongruentSegments(segment, segment); ccss.MakeIntrinsic(); // This is an 'obvious' notion so it should be intrinsic to any figure List <GroundedClause> antecedent = Utilities.MakeList <GroundedClause>(segment); newGrounded.Add(new GenericInstantiator.EdgeAggregator(antecedent, ccss, reflexAnnotation)); return(newGrounded); }
// // Supplementary(Angle(A, B, D), Angle(B, A, C)) // Congruent(Angle(A, B, D), Angle(B, A, C)) -> RightAngle(Angle(A, B, D)) // -> RightAngle(Angle(B, A, C)) // // C D // | | // |____________| // A B // public static List<EdgeAggregator> Instantiate(GroundedClause c) { annotation.active = EngineUIBridge.JustificationSwitch.CONGRUENT_SUPPLEMENTARY_ANGLES_IMPLY_RIGHT_ANGLES; // The list of new grounded clauses if they are deduced List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); if (c is CongruentAngles) { CongruentAngles conAngles = c as CongruentAngles; // We are interested in adjacent angles, not reflexive if (conAngles.IsReflexive()) return newGrounded; foreach (Supplementary suppAngles in candSupplementary) { newGrounded.AddRange(CheckAndGenerateSupplementaryCongruentImplyRightAngles(suppAngles, conAngles)); } candCongruent.Add(conAngles); } else if (c is Supplementary) { Supplementary supplementary = c as Supplementary; foreach (CongruentAngles cc in candCongruent) { newGrounded.AddRange(CheckAndGenerateSupplementaryCongruentImplyRightAngles(supplementary, cc)); } candSupplementary.Add(supplementary); } return newGrounded; }
// // Implements transitivity with Relations (Parallel, Similar) // Relation(A, B), Relation(B, C) -> Relation(A, C) // // Generation of new relations is restricted to the following rules; let G be Geometric and A algebriac // G + G -> A // G + A -> A // A + A -X> A <- Not allowed // public static List<EdgeAggregator> Instantiate(GroundedClause clause) { List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); // Do we have appropriate clauses? if (!(clause is Parallel) && !(clause is SimilarTriangles)) return newGrounded; // Has this clause been generated before? // Since generated clauses will eventually be instantiated as well, this will reach a fixed point and stop. // Uniqueness of clauses needs to be handled by the class calling this if (ClauseHasBeenDeduced(clause)) return newGrounded; // A reflexive expression provides no information of interest or consequence. if (clause.IsReflexive()) return newGrounded; // // Process the clause // if (clause is Parallel) { newGrounded.AddRange(HandleNewParallelRelation(clause as Parallel)); } else if (clause is SimilarTriangles) { newGrounded.AddRange(HandleNewSimilarTrianglesRelation(clause as SimilarTriangles)); } // Add the new clause to the right list for later combining AddToAppropriateList(clause); return newGrounded; }
public static List<EdgeAggregator> Instantiate(GroundedClause clause) { annotation.active = EngineUIBridge.JustificationSwitch.CORRESPONDING_ANGLES_OF_PARALLEL_LINES; List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); if (clause is Parallel) { Parallel parallel = clause as Parallel; for (int i = 0; i < candidateIntersection.Count; i++) { for (int j = i + 1; j < candidateIntersection.Count; j++) { newGrounded.AddRange(InstantiateIntersection(parallel, candidateIntersection[i], candidateIntersection[j])); } } candidateParallel.Add(parallel); } else if (clause is Intersection) { Intersection newInter = clause as Intersection; foreach (Intersection oldInter in candidateIntersection) { foreach (Parallel parallel in candidateParallel) { newGrounded.AddRange(InstantiateIntersection(parallel, newInter, oldInter)); } } candidateIntersection.Add(newInter); } return newGrounded; }
// // A \ / B // \ / // \ / // O \/ X // /\ // / \ // C / \ D // // Intersection(Segment(AD), Segment(BC)) -> 2 * Angle(CXA) = Arc(A, C) + Arc(B, D), // 2 * Angle(BXD) = Arc(A, C) + Arc(B, D), // 2 * Angle(AXB) = Arc(A, B) + Arc(C, D), // 2 * Angle(CXD) = Arc(A, B) + Arc(C, D) // public static List<EdgeAggregator> Instantiate(GroundedClause clause) { annotation.active = EngineUIBridge.JustificationSwitch.TWO_INTERSECTING_CHORDS_ANGLE_MEASURE_HALF_SUM_INTERCEPTED_ARCS; List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); if (clause is Intersection) { Intersection newInter = clause as Intersection; foreach (Circle circle in candidateCircle) { newGrounded.AddRange(InstantiateTheorem(newInter, circle)); } candidateIntersection.Add(newInter); } else if (clause is Circle) { Circle circle = clause as Circle; foreach (Intersection oldInter in candidateIntersection) { newGrounded.AddRange(InstantiateTheorem(oldInter, circle)); } candidateCircle.Add(circle); } return newGrounded; }
public override bool CanBeStrengthenedTo(GroundedClause gc) { Midpoint midpoint = gc as Midpoint; if (midpoint == null) return false; return this.point.StructurallyEquals(midpoint.point) && this.segment.StructurallyEquals(midpoint.segment); }
// B ---------V---------A // \ // \ // \ // C // // Median(Segment(V, C), Triangle(C, A, B)) -> Midpoint(V, Segment(B, A)) // private static List<EdgeAggregator> InstantiateFromMedian(GroundedClause clause) { List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); if (clause is InMiddle && !(clause is Midpoint)) { InMiddle im = clause as InMiddle; foreach (Median median in candidateMedian) { newGrounded.AddRange(InstantiateFromMedian(im, median)); } candidateInMiddle.Add(im); } else if (clause is Median) { Median median = clause as Median; foreach (InMiddle im in candidateInMiddle) { newGrounded.AddRange(InstantiateFromMedian(im, median)); } candidateMedian.Add(median); } return newGrounded; }
public override bool CanBeStrengthenedTo(GroundedClause gc) { Perpendicular perp = gc as Perpendicular; if (perp == null) return false; return intersect.Equals(perp.intersect) && ((lhs.StructurallyEquals(perp.lhs) && rhs.StructurallyEquals(perp.rhs)) || (lhs.StructurallyEquals(perp.rhs) && rhs.StructurallyEquals(perp.lhs))); }
public override bool ContainsClause(GroundedClause clause) { NumericValue clauseValue = clause as NumericValue; if (clauseValue == null) return false; return Utilities.CompareValues(value, clauseValue.value); }
public static List<EdgeAggregator> Instantiate(GroundedClause clause) { annotation.active = EngineUIBridge.JustificationSwitch.TWO_INTERCEPTED_ARCS_HAVE_CONGRUENT_ANGLES; List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); if (clause is Angle) { Angle angle = clause as Angle; foreach (Angle candCongruentAngle in candidateAngles) { newGrounded.AddRange(InstantiateTheorem(angle, candCongruentAngle)); } candidateAngles.Add(angle); } else if (clause is Circle) { Circle circle = clause as Circle; for (int i = 0; i < candidateAngles.Count; ++i) { for (int j = i + 1; j < candidateAngles.Count; ++j) { newGrounded.AddRange(InstantiateTheorem(candidateAngles[i], candidateAngles[j])); } } } return newGrounded; }
public static List <GenericInstantiator.EdgeAggregator> Instantiate(GroundedClause clause) { List <GenericInstantiator.EdgeAggregator> newGrounded = new List <GenericInstantiator.EdgeAggregator>(); if (!(clause is AngleEquation)) { return(newGrounded); } Equation original = clause as Equation; Equation copyEq = (Equation)original.DeepCopy(); FlatEquation flattened = new FlatEquation(copyEq.lhs.CollectTerms(), copyEq.rhs.CollectTerms()); if (flattened.lhsExps.Count == 1 && flattened.rhsExps.Count == 1) { KeyValuePair <int, int> ratio = Utilities.RationalRatio(flattened.lhsExps[0].multiplier, flattened.rhsExps[0].multiplier); if (ratio.Key != -1) { if (ratio.Key <= 2 && ratio.Value <= 2) { AlgebraicProportionalAngles prop = new AlgebraicProportionalAngles((Angle)flattened.lhsExps[0].DeepCopy(), (Angle)flattened.rhsExps[0].DeepCopy()); List <GroundedClause> antecedent = Utilities.MakeList <GroundedClause>(original); newGrounded.Add(new GenericInstantiator.EdgeAggregator(antecedent, prop, atomAnnotation)); } } } return(newGrounded); }
// // EquilateralTriangle(A, B, C) -> Equation(m \angle ABC = 60), // Equation(m \angle BCA = 60), // Equation(m \angle CAB = 60) // public static List<EdgeAggregator> Instantiate(GroundedClause c) { annotation.active = EngineUIBridge.JustificationSwitch.EQUILATERAL_TRIANGLE_HAS_SIXTY_DEGREE_ANGLES; List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); if (!(c is EquilateralTriangle) && !(c is Strengthened)) return newGrounded; EquilateralTriangle eqTri = c as EquilateralTriangle; if (c is Strengthened) { eqTri = (c as Strengthened).strengthened as EquilateralTriangle; } if (eqTri == null) return newGrounded; // EquilateralTriangle(A, B, C) -> List<GroundedClause> antecedent = Utilities.MakeList<GroundedClause>(c); // -> Equation(m \angle ABC = 60), // Equation(m \angle BCA = 60), // Equation(m \angle CAB = 60) GeometricAngleEquation eq1 = new GeometricAngleEquation(eqTri.AngleA, new NumericValue(60)); GeometricAngleEquation eq2 = new GeometricAngleEquation(eqTri.AngleB, new NumericValue(60)); GeometricAngleEquation eq3 = new GeometricAngleEquation(eqTri.AngleC, new NumericValue(60)); newGrounded.Add(new EdgeAggregator(antecedent, eq1, annotation)); newGrounded.Add(new EdgeAggregator(antecedent, eq2, annotation)); newGrounded.Add(new EdgeAggregator(antecedent, eq3, annotation)); return newGrounded; }
private static List<EdgeAggregator> InstantiateToTheorem(Rhombus rhombus, GroundedClause original) { List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); // For hypergraph List<GroundedClause> antecedent = Utilities.MakeList<GroundedClause>(original); // Instantiate this rhombus diagonals ONLY if the original figure has the diagonals drawn. if (rhombus.TopLeftDiagonalIsValid()) { AngleBisector ab1 = new AngleBisector(rhombus.topLeftAngle, rhombus.topLeftBottomRightDiagonal); AngleBisector ab2 = new AngleBisector(rhombus.bottomRightAngle, rhombus.topLeftBottomRightDiagonal); newGrounded.Add(new EdgeAggregator(antecedent, ab1, annotation)); newGrounded.Add(new EdgeAggregator(antecedent, ab2, annotation)); } if (rhombus.BottomRightDiagonalIsValid()) { AngleBisector ab1 = new AngleBisector(rhombus.topRightAngle, rhombus.bottomLeftTopRightDiagonal); AngleBisector ab2 = new AngleBisector(rhombus.bottomLeftAngle, rhombus.bottomLeftTopRightDiagonal); newGrounded.Add(new EdgeAggregator(antecedent, ab1, annotation)); newGrounded.Add(new EdgeAggregator(antecedent, ab2, annotation)); } return newGrounded; }
// // In an attempt to avoid issues, all terms collected are copies of the originals. // public override List <GroundedClause> CollectTerms() { List <GroundedClause> list = new List <GroundedClause>(); if (leftExp is NumericValue && rightExp is NumericValue) { list.Add(new NumericValue((leftExp as NumericValue).DoubleValue * (rightExp as NumericValue).DoubleValue)); return(list); } if (leftExp is NumericValue) { foreach (GroundedClause gc in rightExp.CollectTerms()) { GroundedClause copyGC = gc.DeepCopy(); copyGC.multiplier *= ((NumericValue)leftExp).IntValue; list.Add(copyGC); } } if (rightExp is NumericValue) { foreach (GroundedClause gc in leftExp.CollectTerms()) { GroundedClause copyGC = gc.DeepCopy(); copyGC.multiplier *= ((NumericValue)rightExp).IntValue; list.Add(copyGC); } } return(list); }
// B ____________________ C // / / // / / // / Circle (center) / // / O / // / / // A /___________________/ D // // Circle(O), Quad(A, B, C, D) -> Supplementary(Angle(ABC), Angle(ADC)), Supplementary(Angle(BAD), Angle(BCD)) // public static List<EdgeAggregator> Instantiate(GroundedClause clause) { annotation.active = EngineUIBridge.JustificationSwitch.INSCRIBED_QUADRILATERAL_OPPOSITE_ANGLES_SUPPLEMENTARY; List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); Circle circle = clause as Circle; if (circle == null) return newGrounded; // // For each inscribed quadrilateral, generate accordingly. // foreach (Quadrilateral quad in circle.inscribedPolys[Polygon.QUADRILATERAL_INDEX]) { Supplementary supp1 = new Supplementary(quad.topLeftAngle, quad.bottomRightAngle); Supplementary supp2 = new Supplementary(quad.bottomLeftAngle, quad.topRightAngle); // For hypergraph List<GroundedClause> antecedent = new List<GroundedClause>(); antecedent.Add(circle); antecedent.Add(quad); newGrounded.Add(new EdgeAggregator(antecedent, supp1, annotation)); newGrounded.Add(new EdgeAggregator(antecedent, supp2, annotation)); } return newGrounded; }
// // In order for two triangles to be congruent, we require the following: // RightTriangle(A, B, C) -> Complementary(Angle(B, A, C), Angle(A, C, B)) // A // | \ // | \ // | \ // | \ // |_____\ // B C // public static List<EdgeAggregator> Instantiate(GroundedClause c) { annotation.active = EngineUIBridge.JustificationSwitch.ACUTE_ANGLES_IN_RIGHT_TRIANGLE_ARE_COMPLEMENTARY; List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); if (!(c is Triangle) && !(c is Strengthened)) return newGrounded; if (c is Triangle) { Triangle tri = c as Triangle; if (!(tri is RightTriangle)) { if (!tri.provenRight) return newGrounded; } newGrounded.AddRange(InstantiateRightTriangle(tri, c)); } if (c is Strengthened) { Strengthened streng = c as Strengthened; if (!(streng.strengthened is RightTriangle)) return newGrounded; newGrounded.AddRange(InstantiateRightTriangle(streng.strengthened as RightTriangle, c)); } return newGrounded; }
// / A // / |) // / | ) // / | ) // Q------- O---X---) D // \ | ) // \ | ) // \ |) // \ C // // Inscribed Angle(AQC) -> Angle(AQC) = 2 * Arc(AC) // public static List<EdgeAggregator> Instantiate(GroundedClause clause) { annotation.active = EngineUIBridge.JustificationSwitch.MEASURE_INSCRIBED_ANGLE_EQUAL_HALF_INTERCEPTED_ARC; List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); if (clause is Angle) { Angle angle = clause as Angle; foreach (Circle circle in candidateCircles) { newGrounded.AddRange(InstantiateTheorem(circle, angle)); } candidateAngles.Add(angle); } else if (clause is Circle) { Circle circle = clause as Circle; foreach (Angle angle in candidateAngles) { newGrounded.AddRange(InstantiateTheorem(circle, angle)); } candidateCircles.Add(circle); } return newGrounded; }
// // AngleBisector(SegmentA, D), Angle(C, A, B)) -> 2 m\angle CAD = m \angle CAB, // 2 m\angle BAD = m \angle CAB // // A ________________________B // |\ // | \ // | \ // | \ // | \ // C D // public static List<EdgeAggregator> Instantiate(GroundedClause c) { annotation.active = EngineUIBridge.JustificationSwitch.ANGLE_BISECTOR_THEOREM; List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); if (!(c is AngleBisector)) return newGrounded; AngleBisector angleBisector = c as AngleBisector; KeyValuePair<Angle, Angle> adjacentAngles = angleBisector.GetBisectedAngles(); // Construct 2 m\angle CAD Multiplication product1 = new Multiplication(new NumericValue(2), adjacentAngles.Key); // Construct 2 m\angle BAD Multiplication product2 = new Multiplication(new NumericValue(2), adjacentAngles.Value); // 2X = AB GeometricAngleEquation newEq1 = new GeometricAngleEquation(product1, angleBisector.angle); GeometricAngleEquation newEq2 = new GeometricAngleEquation(product2, angleBisector.angle); // For hypergraph List<GroundedClause> antecedent = Utilities.MakeList<GroundedClause>(angleBisector); newGrounded.Add(new EdgeAggregator(antecedent, newEq1, annotation)); newGrounded.Add(new EdgeAggregator(antecedent, newEq2, annotation)); return newGrounded; }
public static List<EdgeAggregator> InstantiateTheorem(GroundedClause original, IsoscelesTriangle isoTri) { GeometricCongruentAngles newCongSegs = new GeometricCongruentAngles(isoTri.baseAngleOppositeLeg1, isoTri.baseAngleOppositeLeg2); List<GroundedClause> antecedent = Utilities.MakeList<GroundedClause>(original); return Utilities.MakeList<EdgeAggregator>(new EdgeAggregator(antecedent, newCongSegs, annotation)); }
public void AddGeneralPredecessor(GroundedClause gc) { if (gc.clauseId == -1) { Debug.WriteLine("ERROR: id is -1: " + gc.ToString()); } Utilities.AddUnique(generalPredecessors, gc.clauseId); }
public static void Record(GroundedClause clause) { // Record uniquely? For right angles, etc? if (clause is Quadrilateral) { figureQuadrilaterals.Add(clause as Quadrilateral); } }
public static void Record(GroundedClause clause) { // Record uniquely? For right angles, etc? if (clause is Point) { figurePoints.Add(clause as Point); } }
// // Given a list of grounded clauses, get the structurally unique. // public GroundedClause Get(GroundedClause clause) { if (clause is GeometryTutorLib.ConcreteAST.Point) { return GeometryTutorLib.Utilities.GetStructurally<GeometryTutorLib.ConcreteAST.Point>(implied.points, clause as GeometryTutorLib.ConcreteAST.Point); } else if (clause is GeometryTutorLib.ConcreteAST.Segment) { return GeometryTutorLib.Utilities.GetStructurally<GeometryTutorLib.ConcreteAST.Segment>(implied.segments, clause as GeometryTutorLib.ConcreteAST.Segment); } else if (clause is Intersection) { return GeometryTutorLib.Utilities.GetStructurally<Intersection>(implied.ssIntersections, clause as Intersection); } else if (clause is CircleCircleIntersection) { return GeometryTutorLib.Utilities.GetStructurally<CircleCircleIntersection>(implied.ccIntersections, clause as CircleCircleIntersection); } else if (clause is CircleSegmentIntersection) { return GeometryTutorLib.Utilities.GetStructurally<CircleSegmentIntersection>(implied.csIntersections, clause as CircleSegmentIntersection); } else if (clause is Angle) { return GeometryTutorLib.Utilities.GetStructurally<Angle>(implied.angles, clause as Angle); } else if (clause is InMiddle) { return GeometryTutorLib.Utilities.GetStructurally<InMiddle>(implied.inMiddles, clause as InMiddle); } else if (clause is MinorArc) { return GeometryTutorLib.Utilities.GetStructurally<MinorArc>(implied.minorArcs, clause as MinorArc); } else if (clause is Semicircle) { return GeometryTutorLib.Utilities.GetStructurally<Semicircle>(implied.semiCircles, clause as Semicircle); } else if (clause is MajorArc) { return GeometryTutorLib.Utilities.GetStructurally<MajorArc>(implied.majorArcs, clause as MajorArc); } else if (clause is ArcInMiddle) { return GeometryTutorLib.Utilities.GetStructurally<ArcInMiddle>(implied.arcInMiddle, clause as ArcInMiddle); } else if (clause is Triangle) { return GeometryTutorLib.Utilities.GetStructurally<GeometryTutorLib.ConcreteAST.Polygon>(implied.polygons[GeometryTutorLib.ConcreteAST.Polygon.TRIANGLE_INDEX], clause as GeometryTutorLib.ConcreteAST.Polygon); } else if (clause is Quadrilateral) { return GeometryTutorLib.Utilities.GetStructurally<GeometryTutorLib.ConcreteAST.Polygon>(implied.polygons[GeometryTutorLib.ConcreteAST.Polygon.QUADRILATERAL_INDEX], clause as GeometryTutorLib.ConcreteAST.Polygon); } return null; }
// A D // /\ / \ // / \ / \ // / \ / \ // /______\ /_______\ // B C E F // // In order for two triangles to be congruent, we require the following: // Triangle(A, B, C), Triangle(D, E, F), // Congruent(Segment(A, B), Segment(D, E)), // Congruent(Segment(A, C), Angle(D, F)), // Congruent(Segment(B, C), Segment(E, F)) -> Congruent(Triangle(A, B, C), Triangle(D, E, F)), // Congruent(Angle(A, B, C), Angle(D, E, F)), // Congruent(Angle(C, A, B), Angle(F, D, E)), // Congruent(Angle(B, C, A), Angle(E, F, D)), // public static List<EdgeAggregator> Instantiate(GroundedClause clause) { annotation.active = EngineUIBridge.JustificationSwitch.SSS; // The list of new grounded clauses if they are deduced List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); if (clause is CongruentSegments) { CongruentSegments newCss = clause as CongruentSegments; // Check all combinations of triangles to see if they are congruent // This congruence must include the new segment congruence for (int i = 0; i < candidateTriangles.Count - 1; i++) { for (int j = i + 1; j < candidateTriangles.Count; j++) { for (int m = 0; m < candidateSegments.Count - 1; m++) { for (int n = m + 1; n < candidateSegments.Count; n++) { newGrounded.AddRange(InstantiateSSS(candidateTriangles[i], candidateTriangles[j], candidateSegments[m], candidateSegments[n], newCss)); } } } } // Add this segment to the list of possible clauses to unify later candidateSegments.Add(newCss); } // If this is a new triangle, check for triangles which may be congruent to this new triangle else if (clause is Triangle) { Triangle newTriangle = clause as Triangle; // Check all combinations of triangles to see if they are congruent // This congruence must include the new segment congruence foreach (Triangle oldTri in candidateTriangles) { for (int m = 0; m < candidateSegments.Count - 1; m++) { for (int n = m + 1; n < candidateSegments.Count - 1; n++) { for (int p = n + 1; p < candidateSegments.Count - 2; p++) { newGrounded.AddRange(InstantiateSSS(newTriangle, oldTri, candidateSegments[m], candidateSegments[n], candidateSegments[p])); } } } } candidateTriangles.Add(newTriangle); } return newGrounded; }
public override bool Equals(object obj) { GroundedClause that = obj as GroundedClause; if (that == null) { return(false); } return(multiplier == that.multiplier); // && clauseId == that.clauseId; }
// // Midpoint(M, Segment(A, B)) -> 2AM = AB, 2BM = AB A ------------- M ------------- B // public static List<EdgeAggregator> Instantiate(GroundedClause clause) { annotation.active = EngineUIBridge.JustificationSwitch.MIDPOINT_THEOREM; if (clause is Midpoint) return InstantiateMidpointTheorem(clause, clause as Midpoint); if ((clause as Strengthened).strengthened is Midpoint) return InstantiateMidpointTheorem(clause, (clause as Strengthened).strengthened as Midpoint); return new List<EdgeAggregator>(); }
public AngleArcEquation(GroundedClause l, GroundedClause r) : base(l, r) { double sumL = SumSide(l.CollectTerms()); double sumR = SumSide(r.CollectTerms()); if (!Utilities.CompareValues(sumL, sumR)) { throw new ArgumentException("Angle-Arc equation is inaccurate; sums differ: " + l + " " + r); } }
// // This implements forward and Backward instantiation // public static List<EdgeAggregator> Instantiate(GroundedClause clause) { annotation.active = EngineUIBridge.JustificationSwitch.SEGMENT_BISECTOR_DEFINITION; if (clause is SegmentBisector || clause is Strengthened || clause is InMiddle) return InstantiateFromSegmentBisector(clause); if (clause is Intersection || clause is CongruentSegments) return InstantiateToSegmentBisector(clause); return new List<EdgeAggregator>(); }
// // This implements forward and Backward instantiation // Forward is Midpoint -> Congruent Clause // Backward is Congruent -> Midpoint Clause // public static List<EdgeAggregator> Instantiate(GroundedClause c) { annotation.active = EngineUIBridge.JustificationSwitch.ANGLE_BISECTOR_DEFINITION; if (c is AngleBisector) return InstantiateBisector(c as AngleBisector); if (c is CongruentAngles || c is Segment) return InstantiateCongruent(c); return new List<EdgeAggregator>(); }
public AngleEquation(GroundedClause l, GroundedClause r) : base(l, r) { double sumL = SumSide(l.CollectTerms()); double sumR = SumSide(r.CollectTerms()); if (!Utilities.CompareValues(sumL, sumR)) { throw new ArgumentException("Angle equation is inaccurate; sums differ: " + l + " " + r); } }
public override bool ContainsClause(GroundedClause clause) { NumericValue clauseValue = clause as NumericValue; if (clauseValue == null) { return(false); } return(Utilities.CompareValues(value, clauseValue.value)); }
// // This implements forward and Backward instantiation // public static List<EdgeAggregator> Instantiate(GroundedClause clause) { if (clause is Complementary) return InstantiateFromComplementary(clause as Complementary); if (clause is RightAngle || clause is Strengthened || clause is AngleEquation) { return InstantiateToComplementary(clause); } return new List<EdgeAggregator>(); }
public override bool CanBeStrengthenedTo(GroundedClause gc) { Perpendicular perp = gc as Perpendicular; if (perp == null) { return(false); } return(intersect.Equals(perp.intersect) && ((lhs.StructurallyEquals(perp.lhs) && rhs.StructurallyEquals(perp.rhs)) || (lhs.StructurallyEquals(perp.rhs) && rhs.StructurallyEquals(perp.lhs)))); }
public override bool CanBeStrengthenedTo(GroundedClause gc) { Midpoint midpoint = gc as Midpoint; if (midpoint == null) { return(false); } return(this.point.StructurallyEquals(midpoint.point) && this.segment.StructurallyEquals(midpoint.segment)); }
public override bool CanBeStrengthenedTo(GroundedClause gc) { RightAngle ra = gc as RightAngle; if (ra == null) { return(false); } return(this.StructurallyEquals(ra)); }
// // Generate Proportional relationships only if those proportions may be used by a figure (in this case, only triangles) // // Triangle(A, B, C), Triangle(D, E, F), // // Congruent(Segment(A, B), Segment(B, C)), Congruent(Segment(D, E), Segment(E, F)) -> Similar(Triangle(A, B, C), Triangle(D, E, F)), // Proportional(Segment(A, B), Segment(D, E)), // Proportional(Segment(A, B), Segment(E, F)), // Proportional(Segment(B, C), Segment(D, E)), // Proportional(Segment(B, C), Segment(E, F)), // public static List<EdgeAggregator> Instantiate(GroundedClause c) { annotation.active = EngineUIBridge.JustificationSwitch.CONGRUENT_SEGMENTS_IMPLY_PROPORTIONAL_SEGMENTS_DEFINITION; // The list of new grounded clauses if they are deduced List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); if (!(c is Triangle) && !(c is CongruentSegments)) return newGrounded; // If this is a new triangle, check for triangles which may be Similar to this new triangle if (c is Triangle) { Triangle candidateTri = c as Triangle; foreach (Triangle oldTriangle in candidateTriangles) { for (int m = 0; m < candidateCongruentSegments.Count - 1; m++) { for (int n = m + 1; n < candidateCongruentSegments.Count; n++) { newGrounded.AddRange(IfCongruencesApplyToTrianglesGenerate(candidateTri, oldTriangle, candidateCongruentSegments[m], candidateCongruentSegments[n])); } } } // Add this triangle to the list of possible clauses to unify later candidateTriangles.Add(candidateTri); } // // Two sets of congruent segments can lead to proportionality // else if (c is CongruentSegments) { CongruentSegments newCss = c as CongruentSegments; // Avoid reflexive relationships since they will not lead to interesting proportional relationships if (newCss.IsReflexive()) return newGrounded; for (int i = 0; i < candidateTriangles.Count - 1; i++) { for (int j = i + 1; j < candidateTriangles.Count; j++) { foreach (CongruentSegments css in candidateCongruentSegments) { newGrounded.AddRange(IfCongruencesApplyToTrianglesGenerate(candidateTriangles[i], candidateTriangles[j], css, newCss)); } } } candidateCongruentSegments.Add(newCss); } return newGrounded; }
public static List<EdgeAggregator> Instantiate(GroundedClause clause) { annotation.active = EngineUIBridge.JustificationSwitch.CIRCLE_DEFINITION; if (clause is Circle) { return InstantiateFromDefinition(clause as Circle); } return new List<EdgeAggregator>(); }
// // This implements forward and Backward instantiation // public static List<EdgeAggregator> Instantiate(GroundedClause clause) { annotation.active = EngineUIBridge.JustificationSwitch.MEDIAN_DEFINITION; List<EdgeAggregator> newGrounded = new List<EdgeAggregator>(); if (clause is Median || clause is InMiddle) newGrounded.AddRange(InstantiateFromMedian(clause)); if (clause is SegmentBisector || clause is Triangle || clause is Strengthened) newGrounded.AddRange(InstantiateToMedian(clause)); return newGrounded; }
public SegmentEquation(GroundedClause l, GroundedClause r) : base(l, r) { double sumL = SumSide(l.CollectTerms()); double sumR = SumSide(r.CollectTerms()); //if (!Utilities.CompareValues(sumL, sumR)) //{ // throw new ArgumentException("Segment equation is inaccurate; sums differ: " + l + " = " + r); //} if (Utilities.CompareValues(sumL, 0) && Utilities.CompareValues(sumR, 0)) { throw new ArgumentException("Should not have an equation that is 0 = 0: " + this.ToString()); } }
public override List <GroundedClause> CollectTerms() { List <GroundedClause> list = new List <GroundedClause>(); list.AddRange(leftExp.CollectTerms()); foreach (GroundedClause gc in rightExp.CollectTerms()) { GroundedClause copyGC = gc.DeepCopy(); list.Add(copyGC); } return(list); }
public static void Record(GroundedClause clause) { if (clause is MinorArc) { figureMinorArcs.Add(clause as MinorArc); } if (clause is MajorArc) { figureMajorArcs.Add(clause as MajorArc); } if (clause is Semicircle) { figureSemicircles.Add(clause as Semicircle); } }
public static List <GenericInstantiator.EdgeAggregator> InstantiateProportion(GroundedClause clause) { List <GenericInstantiator.EdgeAggregator> newGrounded = new List <GenericInstantiator.EdgeAggregator>(); ProportionalAngles propAngs = clause as ProportionalAngles; if (propAngs == null) { return(newGrounded); } // Do not generate equations based on 'forced' proportions if (propAngs.proportion.Key == -1 || propAngs.proportion.Value == -1) { return(newGrounded); } // Create a product on the left hand side Multiplication productLHS = new Multiplication(new NumericValue(propAngs.proportion.Key), propAngs.smallerAngle.DeepCopy()); // Create a product on the right hand side, if it applies. GroundedClause rhs = propAngs.largerAngle.DeepCopy(); if (propAngs.proportion.Value > 1) { rhs = new Multiplication(new NumericValue(propAngs.proportion.Key), rhs); } // // Create the equation // Equation newEquation = null; if (propAngs is AlgebraicProportionalAngles) { newEquation = new AlgebraicAngleEquation(productLHS, rhs); } else if (propAngs is GeometricProportionalAngles) { newEquation = new GeometricAngleEquation(productLHS, rhs); } List <GroundedClause> antecedent = Utilities.MakeList <GroundedClause>(propAngs); newGrounded.Add(new GenericInstantiator.EdgeAggregator(antecedent, newEquation, defAnnotation)); return(newGrounded); }
//public Equation(GroundedClause l, GroundedClause r, string just) : base() //{ // lhs = l; // rhs = r; // justification = just; //} public override void Substitute(GroundedClause toFind, GroundedClause toSub) { if (lhs.Equals(toFind)) { lhs = toSub.DeepCopy(); } else { lhs.Substitute(toFind, toSub); } if (rhs.Equals(toFind)) { rhs = toSub.DeepCopy(); } else { rhs.Substitute(toFind, toSub); } }
public override void Substitute(GroundedClause toFind, GroundedClause toSub) { if (leftExp.Equals(toFind)) { leftExp = toSub; } else { leftExp.Substitute(toFind, toSub); } if (rightExp.Equals(toFind)) { rightExp = toSub; } else { rightExp.Substitute(toFind, toSub); } }
public static List <GenericInstantiator.EdgeAggregator> Instantiate(GroundedClause pred, GroundedClause c) { List <GenericInstantiator.EdgeAggregator> newGrounded = new List <GenericInstantiator.EdgeAggregator>(); if (c is Angle) { return(newGrounded); } //Angle angle = c as Angle; //if (IsSpecialAngle(angle.measure)) //{ // GeometricAngleEquation angEq = new GeometricAngleEquation(angle, new NumericValue((int)angle.measure), "Given:tbd"); // List<GroundedClause> antecedent = Utilities.MakeList<GroundedClause>(pred); // newClauses.Add(new EdgeAggregator(antecedent, angEq)); //} return(newGrounded); }
// // Generate all corresponding conngruent components. // Ensure vertices correpsond appropriately. // public static List <GenericInstantiator.EdgeAggregator> Instantiate(GroundedClause clause) { List <GenericInstantiator.EdgeAggregator> newGrounded = new List <GenericInstantiator.EdgeAggregator>(); CongruentTriangles conTris = clause as CongruentTriangles; if (conTris == null) { return(newGrounded); } List <Point> orderedTriOnePts = new List <Point>(); List <Point> orderedTriTwoPts = new List <Point>(); if (!conTris.VerifyCongruentTriangles(out orderedTriOnePts, out orderedTriTwoPts)) { return(newGrounded); } return(GenerateCPCTC(conTris, orderedTriOnePts, orderedTriTwoPts)); }
// // Modify the given information to account for redundancy in stated nodes // That is, does given information strengthen a figure node? // private List <ConcreteAST.GroundedClause> DoGivensStrengthenFigure() { List <ConcreteAST.GroundedClause> modifiedGivens = new List <ConcreteAST.GroundedClause>(); ConcreteAST.GroundedClause currentGiven = null; foreach (ConcreteAST.GroundedClause given in givens) { currentGiven = given; foreach (ConcreteAST.GroundedClause component in figure) { if (component.CanBeStrengthenedTo(given)) { currentGiven = new ConcreteAST.Strengthened(component, given); break; } } modifiedGivens.Add(currentGiven); } return(modifiedGivens); }
public GeometricSegmentEquation(GroundedClause l, GroundedClause r) : base(l, r) { }
public override bool ContainsClause(GroundedClause target) { // If a composite node, check accordingly; this will return false if they are atomic return(lhs.ContainsClause(target) || rhs.ContainsClause(target)); }
public Subtraction(GroundedClause l, GroundedClause r) : base(l, r) { }
public Equation(GroundedClause l, GroundedClause r) : base() { lhs = l; rhs = r; }
public AlgebraicSegmentEquation(GroundedClause l, GroundedClause r) : base(l, r) { }
public override bool ContainsClause(GroundedClause target) { return(this.Equals(target)); }
// Acquire the index of the clause in the hypergraph based only on structure public static int StructuralIndex(Hypergraph.Hypergraph <ConcreteAST.GroundedClause, Hypergraph.EdgeAnnotation> graph, ConcreteAST.GroundedClause g) { // // Handle general case // List <Hypergraph.HyperNode <ConcreteAST.GroundedClause, Hypergraph.EdgeAnnotation> > vertices = graph.vertices; for (int v = 0; v < vertices.Count; v++) { if (vertices[v].data.StructurallyEquals(g)) { return(v); } if (vertices[v].data is ConcreteAST.Strengthened) { if ((vertices[v].data as ConcreteAST.Strengthened).strengthened.StructurallyEquals(g)) { return(v); } } } // // Handle strengthening by seeing if the clause is found without a 'strengthening' component // ConcreteAST.Strengthened streng = g as ConcreteAST.Strengthened; if (streng != null) { int index = StructuralIndex(graph, streng.strengthened); if (index != -1) { return(index); } } return(-1); }
public Multiplication(GroundedClause l, GroundedClause r) : base(l, r) { }
public GeometricArcEquation(GroundedClause l, GroundedClause r) : base(l, r) { }