// 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);
        }
Example #2
0
        //
        // Equals checks that for both sides of this equation is the same as one entire side of the other equation
        //
        public override bool Equals(object target)
        {
            AngleEquation thatEquation = target as AngleEquation;

            if (thatEquation == null)
            {
                return(false);
            }

            //
            // Collect all basic terms on the left and right hand sides of both equations.
            //
            List <GroundedClause> thisLHS = lhs.CollectTerms();
            List <GroundedClause> thisRHS = rhs.CollectTerms();

            List <GroundedClause> thatLHS = thatEquation.lhs.CollectTerms();
            List <GroundedClause> thatRHS = thatEquation.rhs.CollectTerms();

            // Check side length counts as a first step.
            if (!((thisLHS.Count == thatLHS.Count && thisRHS.Count == thatRHS.Count) ||
                  (thisLHS.Count == thatRHS.Count && thisLHS.Count == thatLHS.Count)))
            {
                return(false);
            }

            // Seek one side equal to one side and then the other equals the other.
            // Cannot do this easily with a union / set interection set theoretic approach since an equation may have multiple instances of a value
            // In theory, since we always deal with simplified equations, there should not be multiple instances of a particular value.
            // So, this should work.

            // Note operations like multiplication and substraction have been taken into account.
            List <GroundedClause> unionLHS = new List <GroundedClause>(thisLHS);

            Utilities.AddUniqueList(unionLHS, thatLHS);

            List <GroundedClause> unionRHS = new List <GroundedClause>(thisRHS);

            Utilities.AddUniqueList(unionRHS, thatRHS);

            // Exact same sides means the union is the same as each list itself
            if (unionLHS.Count == thisLHS.Count && unionRHS.Count == thisRHS.Count)
            {
                return(true);
            }

            // Check the other combination of sides
            unionLHS = new List <GroundedClause>(thisLHS);
            Utilities.AddUniqueList(unionLHS, thatRHS);

            if (unionLHS.Count != thisLHS.Count)
            {
                return(false);
            }

            unionRHS = new List <GroundedClause>(thisRHS);
            Utilities.AddUniqueList(unionRHS, thatLHS);

            // Exact same sides means the union is the same as each list itself
            return(unionRHS.Count == thisRHS.Count);
        }
        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);
        }
        //
        // 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;
        }