Пример #1
0
        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);
        }
Пример #2
0
        //
        // Check for (basically) atomic equations involving one unknown and constants otherwise.
        //
        private static FlatEquation SimplifyForMultipliersAndConstants(FlatEquation inEq)
        {
            if (inEq.lhsExps.Count != 1 || inEq.rhsExps.Count != 1) return inEq;

            //
            // Figure out what we're looking at.
            //
            NumericValue value = null;
            GroundedClause unknown = null;
            if (inEq.lhsExps[0] is NumericValue)
            {
                value = inEq.lhsExps[0] as NumericValue;
                unknown = inEq.rhsExps[0];
            }
            else if (inEq.rhsExps[0] is NumericValue)
            {
                value = inEq.rhsExps[0] as NumericValue;
                unknown = inEq.lhsExps[0];
            }
            // Not the type of equation we were looking for.
            else return inEq;

            //
            // Divide both sides to simplify.
            //
            if (unknown.multiplier != 1)
            {
                NumericValue newValue = new NumericValue(value.DoubleValue / unknown.multiplier);

                // reset the multiplier
                unknown.multiplier = 1;

                return new FlatEquation(Utilities.MakeList<GroundedClause>(unknown), Utilities.MakeList<GroundedClause>(newValue));
            }

            // Nothing happened so return original
            return inEq;
        }
Пример #3
0
        //
        // Returns a positive constant on the LHS or RHS as appropriate.
        //
        private static KeyValuePair<double, double> HandleConstants(FlatEquation eq)
        {
            double lhs = CollectConstants(eq.lhsExps);
            double rhs = CollectConstants(eq.rhsExps);

            double simpLeft = lhs > rhs ? lhs - rhs : 0;
            double simpRight = rhs > lhs ? rhs - lhs : 0;

            return new KeyValuePair<double, double>(simpLeft, simpRight);
        }
Пример #4
0
        //private static readonly string NAME = "Simplification";
        //
        // Given an equation, simplify algebraically using the following notions:
        //     A + A = B  -> 2A = B
        //     A + B = B + C -> A = C
        //     A + B = 2B + C -> A = B + C
        //
        public static Equation Simplify(Equation original)
        {
            // Do we have an equation?
            if (original == null) throw new ArgumentException();

            // Is the equation 0 = 0? This should be allowed at it indicates a tautology
            if (original.lhs.Equals(new NumericValue(0)) && original.rhs.Equals(new NumericValue(0)))
            {
                throw new ArgumentException("Should not have an equation that is 0 = 0: " + original.ToString());
            }

            //
            // Ideally, flattening would:
            // Remove all subtractions -> adding a negative instead
            // Distribute subtraction or multiplication over addition
            //
            // Flatten the equation so that each side is a sum of atomic expressions
            Equation copyEq = (Equation)original.DeepCopy();
            FlatEquation flattened = new FlatEquation(copyEq.lhs.CollectTerms(), copyEq.rhs.CollectTerms());

            //Debug.WriteLine("Equation prior to simplification: " + flattened.ToString());

            // Combine terms only on each side (do not cross =)
            FlatEquation combined = CombineLikeTerms(flattened);

            //Debug.WriteLine("Equation after like terms combined on both sides: " + combined);

            // Combine terms across the equal sign
            FlatEquation across = CombineLikeTermsAcrossEqual(combined);

             //Debug.WriteLine("Equation after simplifying both sides: " + across);

            FlatEquation constSimplify = SimplifyForMultipliersAndConstants(across);

            //
            // Inflate the equation
            //
            Equation inflated = null;
            GroundedClause singleLeftExp = InflateEntireSide(constSimplify.lhsExps);
            GroundedClause singleRightExp = InflateEntireSide(constSimplify.rhsExps);
            if (original is AlgebraicSegmentEquation)
            {
                inflated = new AlgebraicSegmentEquation(singleLeftExp, singleRightExp);
            }
            else if (original is GeometricSegmentEquation)
            {
                inflated = new GeometricSegmentEquation(singleLeftExp, singleRightExp);
            }
            else if (original is AlgebraicAngleEquation)
            {
                inflated = new AlgebraicAngleEquation(singleLeftExp, singleRightExp);
            }
            else if (original is GeometricAngleEquation)
            {
                inflated = new GeometricAngleEquation(singleLeftExp, singleRightExp);
            }
            else if (original is AlgebraicArcEquation)
            {
                inflated = new AlgebraicArcEquation(singleLeftExp, singleRightExp);
            }
            else if (original is GeometricArcEquation)
            {
                inflated = new GeometricArcEquation(singleLeftExp, singleRightExp);
            }
            else if (original is AlgebraicAngleArcEquation)
            {
                inflated = new AlgebraicAngleArcEquation(singleLeftExp, singleRightExp);
            }
            else if (original is GeometricAngleArcEquation)
            {
                inflated = new GeometricAngleArcEquation(singleLeftExp, singleRightExp);
            }

            // If simplifying didn't do anything, return the original equation
            if (inflated.Equals(original))
            {
                return original;
            }

            //
            // 0 = 0 should not be allowable.
            //
            if (inflated.lhs.Equals(new NumericValue(0)) && inflated.rhs.Equals(new NumericValue(0)))
            {
                return null;
            }

            return inflated;
        }
Пример #5
0
        private static FlatEquation CombineLikeTermsAcrossEqual(FlatEquation eq)
        {
            // The new simplified side of the equation
            List<GroundedClause> leftSimp = new List<GroundedClause>();
            List<GroundedClause> rightSimp = new List<GroundedClause>();

            // The resultant constant values on the left / right sides
            KeyValuePair<double, double> constantPair = HandleConstants(eq);

            bool[] rightCheckedExp = new bool[eq.rhsExps.Count];
            foreach (GroundedClause lExp in eq.lhsExps)
            {
                if (!(lExp is NumericValue))
                {
                    int rightExpIndex = StructuralIndex(eq.rhsExps, lExp);

                    //
                    // Left expression has like term on the right?
                    //
                    // it doesn't have a like term
                    if (rightExpIndex == -1)
                    {
                        leftSimp.Add(lExp);
                    }
                    //
                    // Expression has like term on the right
                    //
                    else
                    {
                        rightCheckedExp[rightExpIndex] = true;
                        GroundedClause rExp = eq.rhsExps[rightExpIndex];
                        GroundedClause copyExp = lExp.DeepCopy();

                        // Seek to keep positive values for the resultant, simplified expression
                        if (lExp.multiplier - rExp.multiplier > 0)
                        {
                            copyExp.multiplier = lExp.multiplier - rExp.multiplier;
                            leftSimp.Add(copyExp);
                        }
                        else if (rExp.multiplier - lExp.multiplier > 0)
                        {
                            copyExp.multiplier = rExp.multiplier - lExp.multiplier;
                            rightSimp.Add(copyExp);
                        }
                        else // Cancelation of the terms
                        {
                        }
                    }
                }
            }

            // Pick up all the expressions on the right hand side which were not like terms of those on the left
            for (int i = 0; i < eq.rhsExps.Count; i++)
            {
                if (!rightCheckedExp[i] && !(eq.rhsExps[i] is NumericValue))
                {
                    rightSimp.Add(eq.rhsExps[i]);
                }
            }

            //
            // Add back the constant to the correct side
            //
            if (constantPair.Key != 0) leftSimp.Add(new NumericValue(constantPair.Key));
            if (constantPair.Value != 0) rightSimp.Add(new NumericValue(constantPair.Value));

            //
            // Now check coefficients: both sides all have coefficients that evenly divide the other side.
            //
            if (leftSimp.Any() && rightSimp.Any())
            {
                // Calculate the gcd
                int gcd = leftSimp[0].multiplier;
                for (int i = 1; i < leftSimp.Count; i++)
                {
                    gcd = Utilities.GCD(gcd, leftSimp[i].multiplier);
                }
                foreach (GroundedClause rExp in rightSimp)
                {
                    gcd = Utilities.GCD(gcd, rExp.multiplier);
                }

                if (gcd != 1)
                {
                    // Divide all expressions by the gcd
                    foreach (GroundedClause lExp in leftSimp)
                    {
                        lExp.multiplier /= gcd;
                    }
                    foreach (GroundedClause rExp in rightSimp)
                    {
                        rExp.multiplier /= gcd;
                    }
                }
            }

            // Check for extreme case in which one side has no elements; in this case, add a zero
            if (!leftSimp.Any()) leftSimp.Add(new NumericValue(0));
            if (!rightSimp.Any()) rightSimp.Add(new NumericValue(0));

            return new FlatEquation(leftSimp, rightSimp);
        }
Пример #6
0
 private static FlatEquation CombineLikeTerms(FlatEquation eq)
 {
     return new FlatEquation(CombineSideLikeTerms(eq.lhsExps), CombineSideLikeTerms(eq.rhsExps));
 }
Пример #7
0
        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;
        }