// // RightAngle(A, B, C), Angle(A, B, X) + Angle(X, B, C) = 90 -> Complementary(Angle(A, B, X), Angle(X, B, C)) // public static List <EdgeAggregator> InstantiateToComplementary(AngleEquation eq, RightAngle ra, GroundedClause original) { List <EdgeAggregator> newGrounded = new List <EdgeAggregator>(); // // Acquire the two angles from the equation // KeyValuePair <int, int> cards = eq.GetCardinalities(); List <GroundedClause> terms = cards.Key == 2 ? eq.lhs.CollectTerms() : eq.rhs.CollectTerms(); List <GroundedClause> singleton = cards.Key == 1 ? eq.lhs.CollectTerms() : eq.rhs.CollectTerms(); Angle angle1 = terms[0] as Angle; Angle angle2 = terms[1] as Angle; // Create the resultant angle to compare to the input right angle Segment shared = angle1.IsAdjacentTo(angle2); if (!ra.HasSegment(angle1.OtherRayEquates(shared)) || !ra.HasSegment(angle2.OtherRayEquates(shared))) { return(newGrounded); } // Success, we have correspondence Complementary comp = new Complementary(angle1, angle2); List <GroundedClause> antecedent = new List <GroundedClause>(); antecedent.Add(original); newGrounded.Add(new EdgeAggregator(antecedent, comp, annotation)); return(newGrounded); }
// Acquire the angle and its measure from the equation private static KeyValuePair <Angle, double> ExtractFromEquation(AngleEquation eq) { NumericValue numeral = null; Angle angle = null; // Split the sides if (eq.lhs is NumericValue) { numeral = eq.lhs as NumericValue; angle = eq.rhs as Angle; } else if (eq.rhs is NumericValue) { numeral = eq.rhs as NumericValue; angle = eq.lhs as Angle; } if (numeral == null || angle == null) { return(new KeyValuePair <Angle, double>(null, 0)); } // The multiplier must be one for: 2mABC = 45, not acceptable; something weird happened anyway if (angle.multiplier != 1) { return(new KeyValuePair <Angle, double>(angle, numeral.DoubleValue * (1.0 / angle.multiplier))); } return(new KeyValuePair <Angle, double>(angle, numeral.DoubleValue)); }
public static List <EdgeAggregator> Instantiate(GroundedClause clause) { annotation.active = EngineUIBridge.JustificationSwitch.ANGLES_OF_EQUAL_MEASUREARE_CONGRUENT; List <EdgeAggregator> newGrounded = new List <EdgeAggregator>(); AngleEquation newAngEq = clause as AngleEquation; if (newAngEq == null) { return(newGrounded); } // One side must be atomic int atomicity = newAngEq.GetAtomicity(); if (atomicity != Equation.BOTH_ATOMIC) { return(newGrounded); } // Split the information into the angle and its measure KeyValuePair <Angle, double> newAngleAndMeasure = ExtractFromEquation(newAngEq); // If splitting failed, we are not interested in the equation if (newAngleAndMeasure.Key == null) { return(newGrounded); } // Can we create any new congruence relationships comparing numeric (deduced angle measure) values? foreach (AngleEquation oldEq in candiateAngleEquations) { KeyValuePair <Angle, double> oldEqAngle = ExtractFromEquation(oldEq); // Avoid generating equivalent angles if (!newAngleAndMeasure.Key.Equates(oldEqAngle.Key)) { // Do the angles have the same measure if (Utilities.CompareValues(newAngleAndMeasure.Value, oldEqAngle.Value)) { AlgebraicCongruentAngles acas = new AlgebraicCongruentAngles(newAngleAndMeasure.Key, oldEqAngle.Key); // For hypergraph construction List <GroundedClause> antecedent = new List <GroundedClause>(); antecedent.Add(newAngEq); antecedent.Add(oldEq); newGrounded.Add(new EdgeAggregator(antecedent, acas, annotation)); } } } // Add to the list for future reference candiateAngleEquations.Add(newAngEq); return(newGrounded); }
public static List <EdgeAggregator> InstantiateToComplementary(GroundedClause clause) { annotation.active = EngineUIBridge.JustificationSwitch.COMPLEMENTARY_DEFINITION; List <EdgeAggregator> newGrounded = new List <EdgeAggregator>(); if (clause is AngleEquation) { AngleEquation eq = clause as AngleEquation; // // Filter only acceptable equations; one side has two values, the other one // // Check basic size of the sides int atomicity = eq.GetAtomicity(); if (atomicity == Equation.BOTH_ATOMIC || atomicity == Equation.NONE_ATOMIC) { return(newGrounded); } // Now check more involved cardinalities of each side KeyValuePair <int, int> cards = eq.GetCardinalities(); if (!(cards.Key == 1 && cards.Value == 2) && !(cards.Key == 2 && cards.Value == 1)) { return(newGrounded); } List <GroundedClause> terms = cards.Key == 2 ? eq.lhs.CollectTerms() : eq.rhs.CollectTerms(); List <GroundedClause> singleton = cards.Key == 1 ? eq.lhs.CollectTerms() : eq.rhs.CollectTerms(); // Coefficients need to be 1 foreach (GroundedClause gc in terms) { if (gc.multiplier != 1) { return(newGrounded); } } // Require the constant to be 90 NumericValue numeral = singleton[0] as NumericValue; if (numeral == null || Utilities.CompareValues(numeral.IntValue, 90)) { return(newGrounded); } // Require adjacent angles Angle angle1 = terms[0] as Angle; Angle angle2 = terms[1] as Angle; if (angle1.IsAdjacentTo(angle2) == null) { return(newGrounded); } foreach (RightAngle ra in candidateRightAngles) { newGrounded.AddRange(InstantiateToComplementary(eq, ra, ra)); } foreach (Strengthened streng in candidateStrengthened) { newGrounded.AddRange(InstantiateToComplementary(eq, streng.strengthened as RightAngle, streng)); } candidateAngleEquations.Add(eq); } else if (clause is RightAngle) { RightAngle newRa = clause as RightAngle; foreach (AngleEquation eq in candidateAngleEquations) { newGrounded.AddRange(InstantiateToComplementary(eq, newRa, newRa)); } candidateRightAngles.Add(newRa); } else if (clause is Strengthened) { Strengthened newStreng = clause as Strengthened; if (!(newStreng.strengthened is RightAngle)) { return(newGrounded); } foreach (AngleEquation eq in candidateAngleEquations) { newGrounded.AddRange(InstantiateToComplementary(eq, newStreng.strengthened as RightAngle, newStreng)); } candidateStrengthened.Add(newStreng); } return(newGrounded); }
public static List <EdgeAggregator> InstantiateToRightAngle(GroundedClause clause) { List <EdgeAggregator> newGrounded = new List <EdgeAggregator>(); if (clause is AngleEquation) { AngleEquation eq = clause as AngleEquation; //Filter for acceptable equations - both sides atomic int atomicity = eq.GetAtomicity(); if (atomicity != Equation.BOTH_ATOMIC) { return(newGrounded); } //Check that the terms equate an angle to a measure List <GroundedClause> lhs = eq.lhs.CollectTerms(); List <GroundedClause> rhs = eq.rhs.CollectTerms(); Angle angle = null; NumericValue value = null; if (lhs[0] is Angle && rhs[0] is NumericValue) { angle = lhs[0] as Angle; value = rhs[0] as NumericValue; } else if (rhs[0] is Angle && lhs[0] is NumericValue) { angle = rhs[0] as Angle; value = lhs[0] as NumericValue; } else { return(newGrounded); } //Verify that the angle is a right angle if (!Utilities.CompareValues(value.DoubleValue, 90.0)) { return(newGrounded); } Strengthened newRightAngle = new Strengthened(angle, new RightAngle(angle)); List <GroundedClause> antecedent = Utilities.MakeList <GroundedClause>(clause); newGrounded.Add(new EdgeAggregator(antecedent, newRightAngle, defAnnotation)); return(newGrounded); } else if (clause is CongruentAngles) { CongruentAngles cas = clause as CongruentAngles; // Not interested in reflexive relationships in this case if (cas.IsReflexive()) { return(newGrounded); } foreach (RightAngle ra in candidateRightAngles) { newGrounded.AddRange(InstantiateToRightAngle(ra, cas, ra)); } foreach (Strengthened streng in candidateStrengthened) { newGrounded.AddRange(InstantiateToRightAngle(streng.strengthened as RightAngle, cas, streng)); } candidateCongruentAngles.Add(clause as CongruentAngles); } else if (clause is RightAngle) { RightAngle ra = clause as RightAngle; foreach (CongruentAngles oldCas in candidateCongruentAngles) { newGrounded.AddRange(InstantiateToRightAngle(ra, oldCas, ra)); } candidateRightAngles.Add(ra); } else if (clause is Strengthened) { Strengthened streng = clause as Strengthened; // Only intrerested in right angles if (!(streng.strengthened is RightAngle)) { return(newGrounded); } foreach (CongruentAngles oldCas in candidateCongruentAngles) { newGrounded.AddRange(InstantiateToRightAngle(streng.strengthened as RightAngle, oldCas, streng)); } candidateStrengthened.Add(streng); } return(newGrounded); }
private static bool HandleSimpleAngleEquation(KnownMeasurementsAggregator known, AngleEquation theEq) { if (theEq.GetAtomicity() != Equation.BOTH_ATOMIC) { return(false); } Angle unknownAngle = null; double angleValue = -1; if (theEq.lhs is NumericValue) { unknownAngle = theEq.rhs as Angle; angleValue = (theEq.lhs as NumericValue).DoubleValue; } else if (theEq.rhs is NumericValue) { unknownAngle = theEq.lhs as Angle; angleValue = (theEq.rhs as NumericValue).DoubleValue; } else { return(false); } // // (7) Add to the list of knowns // return(known.AddAngleMeasureDegree(unknownAngle, angleValue)); }
// // (1) Make a copy // (2) Collect the equation terms. // (3) Are all but one known? // (4) Substitute // (5) Simplify // (6) Acquire the unknown and its value. // (7) Add to the list of knowns. // private static bool HandleAngleEquation(KnownMeasurementsAggregator known, List <GroundedClause> clauses, AngleEquation theEq) { if (theEq.GetAtomicity() == Equation.BOTH_ATOMIC) { return(HandleSimpleAngleEquation(known, theEq)); } // CTA: Verify this calls the correct Equation deep copy mechanism. // (1) Make a copy AngleEquation copy = (AngleEquation)theEq.DeepCopy(); // (2) Collect the equation terms. List <GroundedClause> left = copy.lhs.CollectTerms(); double[] leftVal = new double[left.Count]; List <GroundedClause> right = copy.rhs.CollectTerms(); double[] rightVal = new double[right.Count]; // (3) Are all but one term known? int unknownCount = 0; for (int ell = 0; ell < left.Count; ell++) { if (left[ell] is NumericValue) { leftVal[ell] = (left[ell] as NumericValue).DoubleValue; } else { leftVal[ell] = known.GetAngleMeasure(left[ell] as Angle); if (leftVal[ell] <= 0) { unknownCount++; } } } for (int r = 0; r < right.Count; r++) { if (right[r] is NumericValue) { rightVal[r] = (right[r] as NumericValue).DoubleValue; } else { rightVal[r] = known.GetAngleMeasure(right[r] as Angle); if (rightVal[r] <= 0) { unknownCount++; } } } // We can't solve for more or less than one unknown. if (unknownCount != 1) { return(false); } // // (4) Substitute // for (int ell = 0; ell < left.Count; ell++) { if (leftVal[ell] > 0) { copy.Substitute(left[ell], new NumericValue(leftVal[ell])); } } for (int r = 0; r < right.Count; r++) { if (rightVal[r] > 0) { copy.Substitute(right[r], new NumericValue(rightVal[r])); } } // // (5) Simplify // AngleEquation simplified = (AngleEquation)GenericInstantiator.Simplification.Simplify(copy); return(HandleSimpleAngleEquation(known, simplified)); }