private static bool HandleSimpleSegmentEquation(KnownMeasurementsAggregator known, SegmentEquation theEq)
        {
            if (theEq.GetAtomicity() != Equation.BOTH_ATOMIC)
            {
                return(false);
            }

            Segment unknownSegment = null;
            double  segmentValue   = -1;

            if (theEq.lhs is NumericValue)
            {
                unknownSegment = theEq.rhs as Segment;
                segmentValue   = (theEq.lhs as NumericValue).DoubleValue;
            }
            else if (theEq.rhs is NumericValue)
            {
                unknownSegment = theEq.lhs as Segment;
                segmentValue   = (theEq.rhs as NumericValue).DoubleValue;
            }
            else
            {
                return(false);
            }

            //
            // (7) Add to the list of knowns
            //
            return(known.AddSegmentLength(unknownSegment, segmentValue));
        }
Example #2
0
        //
        // Get the numeric value of this area.
        //
        public virtual double GetArea(KnownMeasurementsAggregator known)
        {
            // Did we memoize this area?
            if (thisArea > 0)
            {
                return(thisArea);
            }

            // Calculate the area if not memoized.
            double area = 0;

            foreach (Atomizer.AtomicRegion atom in atoms)
            {
                double currArea = atom.GetArea(known);

                if (currArea <= 0)
                {
                    return(-1);
                }

                area += currArea;
            }

            return(area);
        }
        private static bool HandleSimpleArcEquation(KnownMeasurementsAggregator known, ArcEquation theEq)
        {
            if (theEq.GetAtomicity() != Equation.BOTH_ATOMIC)
            {
                return(false);
            }

            Arc    unknownArc = null;
            double measure    = -1;

            if (theEq.lhs is NumericValue)
            {
                unknownArc = theEq.rhs as Arc;
                measure    = (theEq.lhs as NumericValue).DoubleValue;
            }
            else if (theEq.rhs is NumericValue)
            {
                unknownArc = theEq.lhs as Arc;
                measure    = (theEq.rhs as NumericValue).DoubleValue;
            }
            else
            {
                return(false);
            }

            //
            // (7) Add to the list of knowns
            //
            return(known.AddArcMeasureDegree(unknownArc, measure));
        }
Example #4
0
        //
        // Create the actual equation and continue processing recursively.
        //
        private void ProcessShape(Region currOuterRegion, TreeNode <Figure> currShape,
                                  List <TreeNode <Figure> > currHierarchyRoots, ComplexRegionEquation currEquation,
                                  double currArea, KnownMeasurementsAggregator known)
        {
            // Acquire the sub-shape.
            Figure currentFigure = currShape.GetData();

            // See what regions compose the subshape.
            ShapeRegion childShapeRegion = new ShapeRegion(currentFigure);

            // Make a copy of the current outer regions
            Region regionCopy = new Region(currOuterRegion);

            // Remove all regions from the outer region; if successful, recur on the new outer shape.
            if (regionCopy.Remove(childShapeRegion.atoms))
            {
                // Update the equation: copy and modify
                ComplexRegionEquation eqCopy = new ComplexRegionEquation(currEquation);
                eqCopy.AppendSubtraction(childShapeRegion);

                // Compute new area
                double currAreaCopy = currArea;
                if (currAreaCopy > 0)
                {
                    double currShapeArea = currentFigure.GetArea(known);

                    currAreaCopy = currShapeArea < 0 ? -1 : currAreaCopy - currShapeArea;
                }

                // Recur.
                SolveHelper(regionCopy, currHierarchyRoots, eqCopy, currAreaCopy, known);
            }
        }
Example #5
0
        //
        // Recur through all of the shapes to pre-calculate their areas.
        //
        private void PreprocessShapeHierarchyAreas(KnownMeasurementsAggregator known, List <Figure> allFigures)
        {
            foreach (Figure theFigure in allFigures)
            {
                // Acquire the indices of the shape.
                IndexList figIndices = IndexList.AcquireAtomicRegionIndices(figureAtoms, theFigure.atoms);
                figureIndexMap[figIndices] = theFigure;

                double area = theFigure.GetArea(known);

                if (area > 0)
                {
                    ShapeRegion atomRegion = new ShapeRegion(theFigure);

                    SolutionAgg agg = new SolutionAgg();

                    // The equation is the identity equation.
                    agg.solEq       = new ComplexRegionEquation(atomRegion, atomRegion);
                    agg.solType     = SolutionAgg.SolutionType.COMPUTABLE;
                    agg.solArea     = area;
                    agg.atomIndices = IndexList.AcquireAtomicRegionIndices(figureAtoms, theFigure.atoms);

                    // Add this solution to the database.
                    solutions.AddSolution(agg);
                }
            }
        }
Example #6
0
        private void PreprocessAtomAreas(KnownMeasurementsAggregator known)
        {
            //
            // Preprocess any of the shape atoms to see if the area is computable.
            //
            for (int a = 0; a < figureAtoms.Count; a++)
            {
                ShapeAtomicRegion shapeAtom = figureAtoms[a] as ShapeAtomicRegion;
                if (shapeAtom != null)
                {
                    double area = shapeAtom.GetArea(known);

                    if (area > 0)
                    {
                        ShapeRegion atomRegion = new ShapeRegion(shapeAtom.shape);

                        SolutionAgg agg = new SolutionAgg();

                        // The equation is the identity equation.
                        agg.solEq       = new ComplexRegionEquation(atomRegion, atomRegion);
                        agg.solType     = SolutionAgg.SolutionType.COMPUTABLE;
                        agg.solArea     = area;
                        agg.atomIndices = new IndexList(a);

                        // Add this solution to the database.
                        solutions.AddSolution(agg);
                    }
                }
            }
        }
Example #7
0
        private static bool AcquireViaFigures(KnownMeasurementsAggregator known, List<Figure> figures)
        {
            //
            // Split into the types of figures.
            //
            List<Triangle> triangles = new List<Triangle>();
            List<IsoscelesTrapezoid> isoTraps = new List<IsoscelesTrapezoid>();

            foreach (Figure fig in figures)
            {
                if (fig is Triangle) triangles.Add(fig as Triangle);
                if (fig is IsoscelesTrapezoid) isoTraps.Add(fig as IsoscelesTrapezoid);
            }

            //
            // Process each type of figure.
            //
            bool addedKnown = false;

            foreach (Triangle tri in triangles)
            {
                addedKnown = KnownValueAcquisition.HandleTriangle(known, tri) || addedKnown;
            }

            foreach (IsoscelesTrapezoid isoTrap in isoTraps)
            {
                HandleIsoscelesTrapezoid(known, isoTrap);
            }

            return addedKnown;
        }
Example #8
0
        public static KnownMeasurementsAggregator Propogate(KnownMeasurementsAggregator known, List<Constraint> constraints)
        {
            List<GroundedClause> congruences = new List<GroundedClause>();
            List<GroundedClause> equations = new List<GroundedClause>();
            List<Figure> figures = new List<Figure>();

            foreach (Constraint constraint in constraints)
            {
                if (constraint is CongruenceConstraint) congruences.Add((constraint as CongruenceConstraint).conConstraint);
                if (constraint is EquationConstraint) equations.Add((constraint as EquationConstraint).eqConstraint);
                if (constraint is FigureConstraint) figures.Add((constraint as FigureConstraint).figConstraint);
            }

            //
            // Fixed-point acquisition of values using congruences and equations.
            //
            bool change = true;
            while(change)
            {
                change = KnownValueAcquisition.AcquireCongruences(known, congruences);

                // Right Triangles, Isosceles Triangles, Isosceles Trapezoids
                change = AcquireViaFigures(known, figures) || change;

                change = KnownValueAcquisition.AcquireViaEquations(known, equations) || change;
            }

            return known;
        }
Example #9
0
        public override double EvaluateArea(KnownMeasurementsAggregator known)
        {
            double leftArea = leftProblem.EvaluateArea(known);
            double rightArea = rightProblem.EvaluateArea(known);

            if (leftArea < 0 || rightArea < 0) return -1;

            return leftArea + rightArea;
        }
        public static bool AcquireCongruences(KnownMeasurementsAggregator known, List <GroundedClause> clauses)
        {
            bool addedKnown = false;

            foreach (GeometryTutorLib.ConcreteAST.GroundedClause clause in clauses)
            {
                GeometryTutorLib.ConcreteAST.CongruentSegments cs = clause as GeometryTutorLib.ConcreteAST.CongruentSegments;
                if (cs != null && !cs.IsReflexive())
                {
                    double length1 = known.GetSegmentLength(cs.cs1);
                    double length2 = known.GetSegmentLength(cs.cs2);

                    if (length1 >= 0 && length2 < 0)
                    {
                        if (known.AddSegmentLength(cs.cs2, length1))
                        {
                            addedKnown = true;
                        }
                    }
                    if (length1 <= 0 && length2 > 0)
                    {
                        if (known.AddSegmentLength(cs.cs1, length2))
                        {
                            addedKnown = true;
                        }
                    }
                    // else: both known
                }

                GeometryTutorLib.ConcreteAST.CongruentAngles cas = clause as GeometryTutorLib.ConcreteAST.CongruentAngles;
                if (cas != null && !cas.IsReflexive())
                {
                    double measure1 = known.GetAngleMeasure(cas.ca1);
                    double measure2 = known.GetAngleMeasure(cas.ca2);

                    if (measure1 >= 0 && measure2 < 0)
                    {
                        if (known.AddAngleMeasureDegree(cas.ca2, measure1))
                        {
                            addedKnown = true;
                        }
                    }
                    if (measure1 <= 0 && measure2 > 0)
                    {
                        if (known.AddAngleMeasureDegree(cas.ca1, measure2))
                        {
                            addedKnown = true;
                        }
                    }
                    // else: both known
                }
            }

            return(addedKnown);
        }
        private static bool HandleRatioEquation(KnownMeasurementsAggregator known, SegmentRatioEquation theEq)
        {
            double topLeft     = known.GetSegmentLength(theEq.lhs.smallerSegment);
            double bottomLeft  = known.GetSegmentLength(theEq.lhs.largerSegment);
            double topRight    = known.GetSegmentLength(theEq.rhs.smallerSegment);
            double bottomRight = known.GetSegmentLength(theEq.rhs.largerSegment);

            int unknown = 0;

            if (topLeft <= 0)
            {
                unknown++;
            }
            if (bottomLeft <= 0)
            {
                unknown++;
            }
            if (topRight <= 0)
            {
                unknown++;
            }
            if (bottomRight <= 0)
            {
                unknown++;
            }
            if (unknown != 1)
            {
                return(false);
            }

            if (topLeft <= 0)
            {
                return(known.AddSegmentLength(theEq.lhs.smallerSegment, (topRight / bottomRight) * bottomLeft));
            }
            else if (bottomLeft <= 0)
            {
                return(known.AddSegmentLength(theEq.lhs.largerSegment, topLeft * (bottomRight / topRight)));
            }
            else if (topRight <= 0)
            {
                return(known.AddSegmentLength(theEq.rhs.smallerSegment, (topLeft / bottomLeft) * bottomRight));
            }
            else if (bottomRight <= 0)
            {
                return(known.AddSegmentLength(theEq.rhs.largerSegment, topRight * (bottomLeft / topLeft)));
            }
            else
            {
                return(false);
            }
        }
Example #12
0
        //
        // Catalyst routine to the recursive solver: returns solution equation and actual area.
        //
        public void SolveAll(KnownMeasurementsAggregator known, List <Figure> allFigures)
        {
            PreprocessAtomAreas(known);
            PreprocessShapeHierarchyAreas(known, allFigures);

            //
            // Using the atomic regions, explore all of the top-most shapes recursively.
            //
            for (int a = 0; a < figureAtoms.Count; a++)
            {
                IndexList   atomIndexList = new IndexList(a);
                SolutionAgg agg           = null;

                solutions.TryGetValue(atomIndexList, out agg);

                if (agg == null)
                {
                    Figure topShape = figureAtoms[a].GetTopMostShape();

                    // Shape Region?
                    ComplexRegionEquation startEq = new ComplexRegionEquation(null, new ShapeRegion(topShape));
                    double outerArea = topShape.GetArea(known);

                    // Invoke the recursive solver using the outermost region and catalyst.
                    //ProcessChildrenShapes(a, new ShapeRegion(topShape), topShape.Hierarchy(),
                    //             new List<TreeNode<Figure>>(),
                    //             startEq, outerArea, known);
                    SolveHelper(new ShapeRegion(topShape),
                                topShape.Hierarchy().Children(),
                                startEq, outerArea, known);
                }
                else if (agg.solType == SolutionAgg.SolutionType.COMPUTABLE)
                {
                    //solutions[atomIndexList] = agg;
                }
                else if (agg.solType == SolutionAgg.SolutionType.INCOMPUTABLE)
                {
                    //solutions[atomIndexList] = agg;
                }
                else if (agg.solType == SolutionAgg.SolutionType.UNKNOWN)
                {
                    //TBD
                }
            }

            //
            // Subtraction of shapes extracts as many atomic regions as possible of the strict atomic regions, now compose those together.
            //
            ComposeAllRegions();
        }
Example #13
0
        //
        // Given a shape that owns the atomic region, recur through the resulting atomic region
        //
        // From
        //
        public void SolveHelper(Region currOuterRegion, List <TreeNode <Figure> > currHierarchyRoots,
                                ComplexRegionEquation currEquation, double currArea, KnownMeasurementsAggregator known)
        {
            IndexList currOuterRegionIndices = IndexList.AcquireAtomicRegionIndices(figureAtoms, currOuterRegion.atoms);

            // There is no outer region
            if (currOuterRegionIndices.IsEmpty())
            {
                return;
            }

            //
            // We have reached this point by subtracting shapes, therefore, we have an equation.
            //
            SolutionAgg agg = new SolutionAgg();

            agg.solEq = new ComplexRegionEquation(currEquation);
            agg.solEq.SetTarget(currOuterRegion);
            agg.solType     = currArea < 0 ? SolutionAgg.SolutionType.INCOMPUTABLE : SolutionAgg.SolutionType.COMPUTABLE;
            agg.solArea     = currArea;
            agg.atomIndices = currOuterRegionIndices;

            //
            // Add this solution to the database.
            //
            solutions.AddSolution(agg);

            // Was this equation solving for a single atomic region? If so, leave.
            if (currOuterRegion.IsAtomic())
            {
                return;
            }

            //
            // Recursively explore EACH sub-shape root inside of the outer region.
            //
            foreach (TreeNode <Figure> shapeNode in currHierarchyRoots)
            {
                // A list omitting this shape
                List <TreeNode <Figure> > updatedHierarchy = new List <TreeNode <Figure> >(currHierarchyRoots);
                updatedHierarchy.Remove(shapeNode);

                // Process this shape
                ProcessShape(currOuterRegion, shapeNode, updatedHierarchy, currEquation, currArea, known);

                // Process the children
                ProcessChildrenShapes(currOuterRegion, shapeNode, updatedHierarchy, currEquation, currArea, known);
            }
        }
Example #14
0
        //
        // Process the child's shapes.
        //
        private void ProcessChildrenShapes(Region currOuterRegion, TreeNode <Figure> currShape,
                                           List <TreeNode <Figure> > currHierarchyRoots, ComplexRegionEquation currEquation,
                                           double currArea, KnownMeasurementsAggregator known)
        {
            foreach (TreeNode <Figure> childNode in currShape.Children())
            {
                // A copy of the children minus this shape.
                List <TreeNode <Figure> > childHierarchy = new List <TreeNode <Figure> >(currShape.Children());
                childHierarchy.Remove(childNode);

                // Add the hierarchy to the list of topmost hierarchical shapes.
                childHierarchy.AddRange(currHierarchyRoots);

                ProcessShape(currOuterRegion, childNode, childHierarchy, currEquation, currArea, known);
            }
        }
        //
        // (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.
        //
        public static bool HandleEquation(KnownMeasurementsAggregator known, List <GroundedClause> clauses, Equation theEq)
        {
            if (theEq is AngleEquation)
            {
                return(HandleAngleEquation(known, clauses, theEq as AngleEquation));
            }
            if (theEq is SegmentEquation)
            {
                return(HandleSegmentEquation(known, clauses, theEq as SegmentEquation));
            }
            if (theEq is ArcEquation)
            {
                return(HandleArcEquation(known, clauses, theEq as ArcEquation));
            }

            return(false);
        }
        //
        // Check all equations to see if we can substitute into any.
        //
        public static bool AcquireViaEquations(KnownMeasurementsAggregator known, List<GroundedClause> clauses)
        {
            bool addedKnown = false;

            foreach (GeometryTutorLib.ConcreteAST.GroundedClause clause in clauses)
            {
                if (clause is GeometryTutorLib.ConcreteAST.Equation)
                {
                    if (HandleEquation(known, clauses, clause as Equation)) addedKnown = true;
                }
                else if (clause is GeometryTutorLib.ConcreteAST.SegmentRatioEquation)
                {
                    if (HandleRatioEquation(known, clause as SegmentRatioEquation)) addedKnown = true;
                }
            }

            return addedKnown;
        }
        public static KnownMeasurementsAggregator AcquireAllKnownValues(KnownMeasurementsAggregator known, List<GroundedClause> congsEqs, List<GroundedClause> triangles)
        {
            //
            // Fixed-point acquisition of values using congruences and equations.
            //
            bool change = true;
            while(change)
            {
                change = AcquireCongruences(known, congsEqs);

                // Pythagorean Theorem
                change = AcquireViaTriangles(known, triangles) || change;

                change = AcquireViaEquations(known, congsEqs) || change;
            }

            return known;
        }
        public static KnownMeasurementsAggregator AcquireAllKnownValues(KnownMeasurementsAggregator known, List <GroundedClause> congsEqs, List <GroundedClause> triangles)
        {
            //
            // Fixed-point acquisition of values using congruences and equations.
            //
            bool change = true;

            while (change)
            {
                change = AcquireCongruences(known, congsEqs);

                // Pythagorean Theorem
                change = AcquireViaTriangles(known, triangles) || change;

                change = AcquireViaEquations(known, congsEqs) || change;
            }

            return(known);
        }
Example #19
0
        //
        // Get the numeric value of this area.
        //
        public virtual double GetArea(KnownMeasurementsAggregator known)
        {
            // Did we memoize this area?
            if (thisArea > 0) return thisArea;

            // Calculate the area if not memoized.
            double area = 0;

            foreach (Atomizer.AtomicRegion atom in atoms)
            {
                double currArea = atom.GetArea(known);

                if (currArea <= 0) return -1;

                area += currArea;
            }

            return area;
        }
        public static bool AcquireCongruences(KnownMeasurementsAggregator known, List<GroundedClause> clauses)
        {
            bool addedKnown = false;

            foreach (GeometryTutorLib.ConcreteAST.GroundedClause clause in clauses)
            {
                GeometryTutorLib.ConcreteAST.CongruentSegments cs = clause as GeometryTutorLib.ConcreteAST.CongruentSegments;
                if (cs != null && !cs.IsReflexive())
                {
                    double length1 = known.GetSegmentLength(cs.cs1);
                    double length2 = known.GetSegmentLength(cs.cs2);

                    if (length1 >= 0 && length2 < 0)
                    {
                        if (known.AddSegmentLength(cs.cs2, length1)) addedKnown = true;
                    }
                    if (length1 <= 0 && length2 > 0)
                    {
                        if (known.AddSegmentLength(cs.cs1, length2)) addedKnown = true;
                    }
                    // else: both known
                }

                GeometryTutorLib.ConcreteAST.CongruentAngles cas = clause as GeometryTutorLib.ConcreteAST.CongruentAngles;
                if (cas != null && !cas.IsReflexive())
                {
                    double measure1 = known.GetAngleMeasure(cas.ca1);
                    double measure2 = known.GetAngleMeasure(cas.ca2);

                    if (measure1 >= 0 && measure2 < 0)
                    {
                        if (known.AddAngleMeasureDegree(cas.ca2, measure1)) addedKnown = true;
                    }
                    if (measure1 <= 0 && measure2 > 0)
                    {
                        if (known.AddAngleMeasureDegree(cas.ca1, measure2)) addedKnown = true;
                    }
                    // else: both known
                }
            }

            return addedKnown;
        }
        private static bool AddKnowns(KnownMeasurementsAggregator known, List <KeyValuePair <Segment, double> > pairs)
        {
            if (!pairs.Any())
            {
                return(false);
            }

            bool change = false;

            foreach (KeyValuePair <Segment, double> rightPair in pairs)
            {
                // Do we know this already?
                if (known.GetSegmentLength(rightPair.Key) < 0)
                {
                    change = true;
                    known.AddSegmentLength(rightPair.Key, rightPair.Value);
                }
            }
            return(change);
        }
        private static bool AcquireViaTriangles(KnownMeasurementsAggregator known, List <GroundedClause> triangles)
        {
            bool addedKnown = false;

            foreach (GroundedClause clause in triangles)
            {
                if (clause is Triangle)
                {
                    addedKnown = HandleTriangle(known, clause as Triangle) || addedKnown;
                }
                else if (clause is Strengthened)
                {
                    Strengthened streng = clause as Strengthened;
                    if (streng.strengthened is Triangle)
                    {
                        addedKnown = HandleTriangle(known, streng.strengthened as Triangle) || addedKnown;
                    }
                }
            }

            return(addedKnown);
        }
Example #23
0
        public static KnownMeasurementsAggregator Propogate(KnownMeasurementsAggregator known, List <Constraint> constraints)
        {
            List <GroundedClause> congruences = new List <GroundedClause>();
            List <GroundedClause> equations   = new List <GroundedClause>();
            List <Figure>         figures     = new List <Figure>();

            foreach (Constraint constraint in constraints)
            {
                if (constraint is CongruenceConstraint)
                {
                    congruences.Add((constraint as CongruenceConstraint).conConstraint);
                }
                if (constraint is EquationConstraint)
                {
                    equations.Add((constraint as EquationConstraint).eqConstraint);
                }
                if (constraint is FigureConstraint)
                {
                    figures.Add((constraint as FigureConstraint).figConstraint);
                }
            }

            //
            // Fixed-point acquisition of values using congruences and equations.
            //
            bool change = true;

            while (change)
            {
                change = KnownValueAcquisition.AcquireCongruences(known, congruences);

                // Right Triangles, Isosceles Triangles, Isosceles Trapezoids
                change = AcquireViaFigures(known, figures) || change;

                change = KnownValueAcquisition.AcquireViaEquations(known, equations) || change;
            }

            return(known);
        }
        //
        // A right triangle means we can apply the pythagorean theorem to acquire an unknown.
        //
        public static bool HandleTriangle(KnownMeasurementsAggregator known, Triangle tri)
        {
            if (tri == null)
            {
                return(false);
            }

            KeyValuePair <Segment, double> pair = tri.PythagoreanTheoremApplies(known);

            if (pair.Value > 0)
            {
                // Do we know this already?
                if (known.GetSegmentLength(pair.Key) > 0)
                {
                    return(false);
                }

                // We don't know it, we add it.
                known.AddSegmentLength(pair.Key, pair.Value);
                return(true);
            }
            else
            {
                if (AddKnowns(known, tri.IsoscelesRightApplies(known)))
                {
                    return(true);
                }
                if (AddKnowns(known, tri.CalculateBaseOfIsosceles(known)))
                {
                    return(true);
                }
                if (AddKnowns(known, tri.RightTriangleTrigApplies(known)))
                {
                    return(true);
                }
            }

            return(false);
        }
Example #25
0
        private static bool AcquireViaFigures(KnownMeasurementsAggregator known, List <Figure> figures)
        {
            //
            // Split into the types of figures.
            //
            List <Triangle>           triangles = new List <Triangle>();
            List <IsoscelesTrapezoid> isoTraps  = new List <IsoscelesTrapezoid>();

            foreach (Figure fig in figures)
            {
                if (fig is Triangle)
                {
                    triangles.Add(fig as Triangle);
                }
                if (fig is IsoscelesTrapezoid)
                {
                    isoTraps.Add(fig as IsoscelesTrapezoid);
                }
            }

            //
            // Process each type of figure.
            //
            bool addedKnown = false;

            foreach (Triangle tri in triangles)
            {
                addedKnown = KnownValueAcquisition.HandleTriangle(known, tri) || addedKnown;
            }

            foreach (IsoscelesTrapezoid isoTrap in isoTraps)
            {
                HandleIsoscelesTrapezoid(known, isoTrap);
            }

            return(addedKnown);
        }
        //
        // Check all equations to see if we can substitute into any.
        //
        public static bool AcquireViaEquations(KnownMeasurementsAggregator known, List <GroundedClause> clauses)
        {
            bool addedKnown = false;

            foreach (GeometryTutorLib.ConcreteAST.GroundedClause clause in clauses)
            {
                if (clause is GeometryTutorLib.ConcreteAST.Equation)
                {
                    if (HandleEquation(known, clauses, clause as Equation))
                    {
                        addedKnown = true;
                    }
                }
                else if (clause is GeometryTutorLib.ConcreteAST.SegmentRatioEquation)
                {
                    if (HandleRatioEquation(known, clause as SegmentRatioEquation))
                    {
                        addedKnown = true;
                    }
                }
            }

            return(addedKnown);
        }
Example #27
0
 //
 // An isosceles trapezoid can use an equation to find the height based on the bases and the side lengths.
 //
 public static void HandleIsoscelesTrapezoid(KnownMeasurementsAggregator known, IsoscelesTrapezoid isoTrap)
 {
     isoTrap.CalculateHeight(known);
 }
Example #28
0
        //
        // We have a set of constraints associated with the figure.
        // Also associated is a set of variables in which constraints are defined.
        // 1) Randomly choose one of the variables that defines the area formula, define it by its coordinate-based value.
        // 2) Push it through the constant propagator.
        // 3) From the list of variables, remove which of them that are now known.
        // 4) Repeat until the list of variables is empty.
        //
        public KnownMeasurementsAggregator AcquireKnowns()
        {
            // Acquire all unknown variables required to calculate the area.
            List<Segment> unknownAreaVars = this.GetAreaVariables();

            // The constraints for this problem.
            List<Constraint> constraints = this.GetConstraints();

            // The values we must state to the user in order to solve the problem.
            List<Segment> assumptions = new List<Segment>();

            //
            // Loop until all variables are known.
            //
            KnownMeasurementsAggregator known = new KnownMeasurementsAggregator();
            while (unknownAreaVars.Any())
            {
                // Acquire a new assumption.
                Segment newAssumption = unknownAreaVars[0];

                // remove that assumption since it is now known; add as an assumption.
                unknownAreaVars.RemoveAt(0);
                assumptions.Add(newAssumption);

                // Set this value as known with its intrinsic (corrdinate-based) length.
                known.AddSegmentLength(newAssumption, newAssumption.Length);

                // Propagate the new information through the constraints.
                ConstantPropagator.Propogate(known, constraints);

                // Check if any of the unknown variables are now known through constant propagation.
                unknownAreaVars = AcquireCurrentUnknowns(known, unknownAreaVars);
            }

            //
            // Create the known object.
            //
            KnownMeasurementsAggregator trueAssumptions = new KnownMeasurementsAggregator();
            foreach (Segment seg in assumptions)
            {
                trueAssumptions.AddSegmentLength(seg, seg.Length);
            }

            return trueAssumptions;
        }
Example #29
0
 public abstract double EvaluateArea(KnownMeasurementsAggregator known);
        //
        // Create the actual equation and continue processing recursively.
        //
        private void ProcessShape(Region currOuterRegion, TreeNode<Figure> currShape,
                                 List<TreeNode<Figure>> currHierarchyRoots, ComplexRegionEquation currEquation,
                                 double currArea, KnownMeasurementsAggregator known)
        {
            // Acquire the sub-shape.
            Figure currentFigure = currShape.GetData();

            // See what regions compose the subshape.
            ShapeRegion childShapeRegion = new ShapeRegion(currentFigure);

            // Make a copy of the current outer regions
            Region regionCopy = new Region(currOuterRegion);

            // Remove all regions from the outer region; if successful, recur on the new outer shape.
            if (regionCopy.Remove(childShapeRegion.atoms))
            {
                // Update the equation: copy and modify
                ComplexRegionEquation eqCopy = new ComplexRegionEquation(currEquation);
                eqCopy.AppendSubtraction(childShapeRegion);

                // Compute new area
                double currAreaCopy = currArea;
                if (currAreaCopy > 0)
                {
                    double currShapeArea = currentFigure.GetArea(known);

                    currAreaCopy = currShapeArea < 0 ? -1 : currAreaCopy - currShapeArea;
                }

                // Recur.
                SolveHelper(regionCopy, currHierarchyRoots, eqCopy, currAreaCopy, known);
            }
        }
        private static bool HandleSimpleSegmentEquation(KnownMeasurementsAggregator known, SegmentEquation theEq)
        {
            if (theEq.GetAtomicity() != Equation.BOTH_ATOMIC) return false;

            Segment unknownSegment = null;
            double segmentValue = -1;
            if (theEq.lhs is NumericValue)
            {
                unknownSegment = theEq.rhs as Segment;
                segmentValue = (theEq.lhs as NumericValue).DoubleValue;
            }
            else if (theEq.rhs is NumericValue)
            {
                unknownSegment = theEq.lhs as Segment;
                segmentValue = (theEq.rhs as NumericValue).DoubleValue;
            }
            else return false;

            //
            // (7) Add to the list of knowns
            //
            return known.AddSegmentLength(unknownSegment, segmentValue);
        }
        //
        // (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 HandleSegmentEquation(KnownMeasurementsAggregator known, List <GroundedClause> clauses, SegmentEquation theEq)
        {
            if (theEq.GetAtomicity() == Equation.BOTH_ATOMIC)
            {
                return(HandleSimpleSegmentEquation(known, theEq));
            }

            // CTA: Verify this calls the correct Equation deep copy mechanism.
            // (1) Make a copy
            SegmentEquation copy = (SegmentEquation)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.GetSegmentLength(left[ell] as Segment);
                    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.GetSegmentLength(right[r] as Segment);
                    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
            //
            SegmentEquation simplified = (SegmentEquation)GenericInstantiator.Simplification.Simplify(copy);

            return(HandleSimpleSegmentEquation(known, simplified));
        }
        private static bool HandleRatioEquation(KnownMeasurementsAggregator known, SegmentRatioEquation theEq)
        {
            double topLeft = known.GetSegmentLength(theEq.lhs.smallerSegment);
            double bottomLeft = known.GetSegmentLength(theEq.lhs.largerSegment);
            double topRight = known.GetSegmentLength(theEq.rhs.smallerSegment);
            double bottomRight = known.GetSegmentLength(theEq.rhs.largerSegment);

            int unknown = 0;
            if (topLeft <= 0) unknown++;
            if (bottomLeft <= 0) unknown++;
            if (topRight <= 0) unknown++;
            if (bottomRight <= 0) unknown++;
            if (unknown != 1) return false;

            if (topLeft <= 0)
            {
                return known.AddSegmentLength(theEq.lhs.smallerSegment, (topRight / bottomRight) * bottomLeft);
            }
            else if (bottomLeft <= 0)
            {
                return known.AddSegmentLength(theEq.lhs.largerSegment, topLeft * (bottomRight / topRight));
            }
            else if (topRight <= 0)
            {
                return known.AddSegmentLength(theEq.rhs.smallerSegment, (topLeft / bottomLeft) * bottomRight);
            }
            else if (bottomRight <= 0)
            {
                return known.AddSegmentLength(theEq.rhs.largerSegment, topRight * (bottomLeft / topLeft));
            }
            else return false;
        }
        //
        // Dynamic Programming Style Solution Construction; equation and actual area.
        //
        public KeyValuePair <ComplexRegionEquation, double> Solve(List <Atomizer.AtomicRegion> atoms, KnownMeasurementsAggregator known)
        {
            // Construct the memoization data structure.
            if (memoizedSolutions == null)
            {
                memoizedSolutions = new ComplexRegionEquation[graph.Size()];
            }

            // The region for which we will construct an equation.
            Region desired = new Region(atoms);

            // Determine if this region is actually in the hypergraph.
            int startIndex = graph.GetNodeIndex(desired);

            if (startIndex == -1)
            {
                throw new ArgumentException("Desired region not found in area hypergraph: " + desired);
            }
            // For marking if we have visited the given node already
            bool[] visited = new bool[graph.Size()];

            // Traverse dymanically to construct all equations.
            return(DynamicVisit(startIndex, visited, known));
        }
        //
        // A right triangle means we can apply the pythagorean theorem to acquire an unknown.
        //
        public static bool HandleTriangle(KnownMeasurementsAggregator known, Triangle tri)
        {
            if (tri == null) return false;

            KeyValuePair<Segment, double> pair = tri.PythagoreanTheoremApplies(known);

            if (pair.Value > 0)
            {
                // Do we know this already?
                if (known.GetSegmentLength(pair.Key) > 0) return false;

                // We don't know it, we add it.
                known.AddSegmentLength(pair.Key, pair.Value);
                return true;
            }
            else
            {
                if (AddKnowns(known, tri.IsoscelesRightApplies(known))) return true;
                if (AddKnowns(known, tri.CalculateBaseOfIsosceles(known))) return true;
                if (AddKnowns(known, tri.RightTriangleTrigApplies(known))) return true;
            }

            return false;
        }
Example #36
0
 public override double GetArea(KnownMeasurementsAggregator known)
 {
     return shape.GetArea(known);
 }
Example #37
0
 //
 // An isosceles trapezoid can use an equation to find the height based on the bases and the side lengths.
 //
 public static void HandleIsoscelesTrapezoid(KnownMeasurementsAggregator known, IsoscelesTrapezoid isoTrap)
 {
     isoTrap.CalculateHeight(known);
 }
Example #38
0
        //
        // Filter the list of unknowns by any new information.
        //
        private List<Segment> AcquireCurrentUnknowns(KnownMeasurementsAggregator known, List<Segment> unknowns)
        {
            List<Segment> newUnknowns = new List<Segment>();

            foreach (Segment unknown in unknowns)
            {
                if (known.GetSegmentLength(unknown) < 0) newUnknowns.Add(unknown);
            }

            return newUnknowns;
        }
        //
        // (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 HandleSegmentEquation(KnownMeasurementsAggregator known, List<GroundedClause> clauses, SegmentEquation theEq)
        {
            if (theEq.GetAtomicity() == Equation.BOTH_ATOMIC) return HandleSimpleSegmentEquation(known, theEq);

            // CTA: Verify this calls the correct Equation deep copy mechanism.
            // (1) Make a copy
            SegmentEquation copy = (SegmentEquation)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.GetSegmentLength(left[ell] as Segment);
                    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.GetSegmentLength(right[r] as Segment);
                    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
            //
            SegmentEquation simplified = (SegmentEquation)GenericInstantiator.Simplification.Simplify(copy);

            return HandleSimpleSegmentEquation(known, simplified);
        }
        //
        // Graph traversal to find shapes and thus the resulting equation (solution).
        //
        // Dynamic Programming: return the first solution found (which will be the shortest)
        //
        private KeyValuePair<ComplexRegionEquation, double> DynamicVisit(int startIndex, bool[] visited, KnownMeasurementsAggregator known)
        {
            // The actual Region object for this node.
            Region thisRegion = graph.vertices[startIndex].data;

            // Cut off search if we've been here before.
            if (visited[startIndex]) return new KeyValuePair<ComplexRegionEquation,double>(memoizedSolutions[startIndex], thisRegion.GetKnownArea());

            // We've been here now.
            visited[startIndex] = true;

            //
            // Can we compute the area of this node directly?
            //
            double area = thisRegion.GetArea(known);
            if (area > 0)
            {
                thisRegion.SetKnownArea(area);
                memoizedSolutions[startIndex] = new ComplexRegionEquation(thisRegion, thisRegion);
                return new KeyValuePair<ComplexRegionEquation,double>(memoizedSolutions[startIndex], thisRegion.GetKnownArea());
            }

            //
            // Does any of the edges satisfy this equation? Investigate dynamically.
            //
            // Complex equation resulting from each outgoing edge.
            ComplexRegionEquation shortestEq = null;
            area = 0;
            foreach (Hypergraph.HyperEdge<SimpleRegionEquation> edge in graph.vertices[startIndex].targetEdges)
            {
                KeyValuePair<ComplexRegionEquation, double> src1Eq = DynamicVisit(edge.sourceNodes[0], visited, known);
                KeyValuePair<ComplexRegionEquation, double> src2Eq = DynamicVisit(edge.sourceNodes[1], visited, known);

                // Success, we found a valid area expression for edge.
                if (src1Eq.Key != null && src2Eq.Key != null)
                {
                    // Create a copy of the anootation for a simple region equation for this edge.
                    SimpleRegionEquation simpleEdgeEq = new SimpleRegionEquation(edge.annotation);

                    //
                    // Make one complex equation performing substitutions.
                    //
                    ComplexRegionEquation complexEdgeEq = new ComplexRegionEquation(simpleEdgeEq);
                    complexEdgeEq.Substitute(src1Eq.Key.target, src1Eq.Key.expr);
                    complexEdgeEq.Substitute(src2Eq.Key.target, src2Eq.Key.expr);

                    // Pick the shortest equation possible.
                    if (shortestEq == null) shortestEq = complexEdgeEq;
                    else if (shortestEq.Length > complexEdgeEq.Length) shortestEq = complexEdgeEq;

                    if (edge.annotation.op == OperationT.ADDITION)
                    {
                        area = src1Eq.Value + src2Eq.Value;
                    }
                    else if (edge.annotation.op == OperationT.SUBTRACTION)
                    {
                        area = src1Eq.Value - src2Eq.Value;
                    }
                }
            }

            //if (shortestEq != null)
            //{
            //    thisRegion.SetKnownArea(area);
            //    memoizedSolutions[startIndex] = new ComplexRegionEquation(thisRegion, thisRegion);
            //    return new KeyValuePair<ComplexRegionEquation, double>(memoizedSolutions[startIndex], area);
            //}

            memoizedSolutions[startIndex] = shortestEq;

            return new KeyValuePair<ComplexRegionEquation, double>(memoizedSolutions[startIndex], area);
        }
Example #41
0
 public override double EvaluateArea(KnownMeasurementsAggregator known)
 {
     return figure.GetArea(known);
 }
        //
        // (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.
        //
        public static bool HandleEquation(KnownMeasurementsAggregator known, List<GroundedClause> clauses, Equation theEq)
        {
            if (theEq is AngleEquation) return HandleAngleEquation(known, clauses, theEq as AngleEquation);
            if (theEq is SegmentEquation) return HandleSegmentEquation(known, clauses, theEq as SegmentEquation);
            if (theEq is ArcEquation) return HandleArcEquation(known, clauses, theEq as ArcEquation);

            return false;
        }
        //
        // Dynamic Programming Style Solution Construction; equation and actual area.
        //
        public KeyValuePair<ComplexRegionEquation, double> Solve(List<Atomizer.AtomicRegion> atoms, KnownMeasurementsAggregator known)
        {
            // Construct the memoization data structure.
            if (memoizedSolutions == null) memoizedSolutions = new ComplexRegionEquation[graph.Size()];

            // The region for which we will construct an equation.
            Region desired = new Region(atoms);

            // Determine if this region is actually in the hypergraph.
            int startIndex = graph.GetNodeIndex(desired);

            if (startIndex == -1)
            {
                throw new ArgumentException("Desired region not found in area hypergraph: " + desired);
            }
            // For marking if we have visited the given node already
            bool[] visited = new bool[graph.Size()];

            // Traverse dymanically to construct all equations.
            return DynamicVisit(startIndex, visited, known);
        }
        private static bool AcquireViaTriangles(KnownMeasurementsAggregator known, List<GroundedClause> triangles)
        {
            bool addedKnown = false;

            foreach (GroundedClause clause in triangles)
            {
                if (clause is Triangle)
                {
                    addedKnown = HandleTriangle(known, clause as Triangle) || addedKnown;
                }
                else if (clause is Strengthened)
                {
                    Strengthened streng = clause as Strengthened;
                    if (streng.strengthened is Triangle)
                    {
                        addedKnown = HandleTriangle(known, streng.strengthened as Triangle) || addedKnown;
                    }
                }
            }

            return addedKnown;
        }
        //
        // Catalyst routine to the recursive solver: returns solution equation and actual area.
        //
        public void SolveAll(KnownMeasurementsAggregator known, List<Figure> allFigures)
        {
            PreprocessAtomAreas(known);
            PreprocessShapeHierarchyAreas(known, allFigures);

            //
            // Using the atomic regions, explore all of the top-most shapes recursively.
            //
            for (int a = 0; a < figureAtoms.Count; a++)
            {
                IndexList atomIndexList = new IndexList(a);
                SolutionAgg agg = null;

                solutions.TryGetValue(atomIndexList, out agg);

                if (agg == null)
                {
                    Figure topShape = figureAtoms[a].GetTopMostShape();

                    // Shape Region?
                    ComplexRegionEquation startEq = new ComplexRegionEquation(null, new ShapeRegion(topShape));
                    double outerArea = topShape.GetArea(known);

                    // Invoke the recursive solver using the outermost region and catalyst.
                    //ProcessChildrenShapes(a, new ShapeRegion(topShape), topShape.Hierarchy(),
                    //             new List<TreeNode<Figure>>(),
                    //             startEq, outerArea, known);
                    SolveHelper(new ShapeRegion(topShape),
                                topShape.Hierarchy().Children(),
                                startEq, outerArea, known);
                }
                else if (agg.solType == SolutionAgg.SolutionType.COMPUTABLE)
                {
                    //solutions[atomIndexList] = agg;
                }
                else if (agg.solType == SolutionAgg.SolutionType.INCOMPUTABLE)
                {
                    //solutions[atomIndexList] = agg;
                }
                else if (agg.solType == SolutionAgg.SolutionType.UNKNOWN)
                {
                    //TBD
                }
            }

            //
            // Subtraction of shapes extracts as many atomic regions as possible of the strict atomic regions, now compose those together.
            //
            ComposeAllRegions();
        }
        private static bool AddKnowns(KnownMeasurementsAggregator known, List<KeyValuePair<Segment, double>> pairs)
        {
            if (!pairs.Any()) return false;

            bool change = false;
            foreach (KeyValuePair<Segment, double> rightPair in pairs)
            {
                // Do we know this already?
                if (known.GetSegmentLength(rightPair.Key) < 0)
                {
                    change = true;
                    known.AddSegmentLength(rightPair.Key, rightPair.Value);
                }
            }
            return change;
        }
        //
        // Given a shape that owns the atomic region, recur through the resulting atomic region
        //
        // From
        //
        public void SolveHelper(Region currOuterRegion, List<TreeNode<Figure>> currHierarchyRoots,
                                ComplexRegionEquation currEquation, double currArea, KnownMeasurementsAggregator known)
        {
            IndexList currOuterRegionIndices = IndexList.AcquireAtomicRegionIndices(figureAtoms, currOuterRegion.atoms);

            // There is no outer region
            if (currOuterRegionIndices.IsEmpty()) return;

            //
            // We have reached this point by subtracting shapes, therefore, we have an equation.
            //
            SolutionAgg agg = new SolutionAgg();

            agg.solEq = new ComplexRegionEquation(currEquation);
            agg.solEq.SetTarget(currOuterRegion);
            agg.solType = currArea < 0 ? SolutionAgg.SolutionType.INCOMPUTABLE : SolutionAgg.SolutionType.COMPUTABLE;
            agg.solArea = currArea;
            agg.atomIndices = currOuterRegionIndices;

            //
            // Add this solution to the database.
            //
            solutions.AddSolution(agg);

            // Was this equation solving for a single atomic region? If so, leave.
            if (currOuterRegion.IsAtomic()) return;

            //
            // Recursively explore EACH sub-shape root inside of the outer region.
            //
            foreach (TreeNode<Figure> shapeNode in currHierarchyRoots)
            {
                // A list omitting this shape
                List<TreeNode<Figure>> updatedHierarchy = new List<TreeNode<Figure>>(currHierarchyRoots);
                updatedHierarchy.Remove(shapeNode);

                // Process this shape
                ProcessShape(currOuterRegion, shapeNode, updatedHierarchy, currEquation, currArea, known);

                // Process the children
                ProcessChildrenShapes(currOuterRegion, shapeNode, updatedHierarchy, currEquation, currArea, known);
            }
        }
        private void PreprocessAtomAreas(KnownMeasurementsAggregator known)
        {
            //
            // Preprocess any of the shape atoms to see if the area is computable.
            //
            for (int a = 0; a < figureAtoms.Count; a++)
            {
                ShapeAtomicRegion shapeAtom = figureAtoms[a] as ShapeAtomicRegion;
                if (shapeAtom != null)
                {
                    double area = shapeAtom.GetArea(known);

                    if (area > 0)
                    {
                        ShapeRegion atomRegion = new ShapeRegion(shapeAtom.shape);

                        SolutionAgg agg = new SolutionAgg();

                        // The equation is the identity equation.
                        agg.solEq = new ComplexRegionEquation(atomRegion, atomRegion);
                        agg.solType = SolutionAgg.SolutionType.COMPUTABLE;
                        agg.solArea = area;
                        agg.atomIndices = new IndexList(a);

                        // Add this solution to the database.
                        solutions.AddSolution(agg);
                    }
                }
            }
        }
        //
        // Recur through all of the shapes to pre-calculate their areas.
        //
        private void PreprocessShapeHierarchyAreas(KnownMeasurementsAggregator known, List<Figure> allFigures)
        {
            foreach (Figure theFigure in allFigures)
            {
                // Acquire the indices of the shape.
                IndexList figIndices = IndexList.AcquireAtomicRegionIndices(figureAtoms, theFigure.atoms);
                figureIndexMap[figIndices] = theFigure;

                double area = theFigure.GetArea(known);

                if (area > 0)
                {
                    ShapeRegion atomRegion = new ShapeRegion(theFigure);

                    SolutionAgg agg = new SolutionAgg();

                    // The equation is the identity equation.
                    agg.solEq = new ComplexRegionEquation(atomRegion, atomRegion);
                    agg.solType = SolutionAgg.SolutionType.COMPUTABLE;
                    agg.solArea = area;
                    agg.atomIndices = IndexList.AcquireAtomicRegionIndices(figureAtoms, theFigure.atoms);

                    // Add this solution to the database.
                    solutions.AddSolution(agg);
                }
            }
        }
        private static bool HandleSimpleArcEquation(KnownMeasurementsAggregator known, ArcEquation theEq)
        {
            if (theEq.GetAtomicity() != Equation.BOTH_ATOMIC) return false;

            Arc unknownArc = null;
            double measure = -1;
            if (theEq.lhs is NumericValue)
            {
                unknownArc = theEq.rhs as Arc;
                measure = (theEq.lhs as NumericValue).DoubleValue;
            }
            else if (theEq.rhs is NumericValue)
            {
                unknownArc = theEq.lhs as Arc;
                measure = (theEq.rhs as NumericValue).DoubleValue;
            }
            else return false;

            //
            // (7) Add to the list of knowns
            //
            return known.AddArcMeasureDegree(unknownArc, measure);
        }
        //
        // Process the child's shapes.
        //
        private void ProcessChildrenShapes(Region currOuterRegion, TreeNode<Figure> currShape,
                                           List<TreeNode<Figure>> currHierarchyRoots, ComplexRegionEquation currEquation,
                                           double currArea, KnownMeasurementsAggregator known)
        {
            foreach (TreeNode<Figure> childNode in currShape.Children())
            {
                // A copy of the children minus this shape.
                List<TreeNode<Figure>> childHierarchy = new List<TreeNode<Figure>>(currShape.Children());
                childHierarchy.Remove(childNode);

                // Add the hierarchy to the list of topmost hierarchical shapes.
                childHierarchy.AddRange(currHierarchyRoots);

                ProcessShape(currOuterRegion, childNode, childHierarchy, currEquation, currArea, known);
            }
        }
Example #52
0
 public override double GetArea(KnownMeasurementsAggregator known)
 {
     return(shape.GetArea(known));
 }
        //
        // Graph traversal to find shapes and thus the resulting equation (solution).
        //
        // Dynamic Programming: return the first solution found (which will be the shortest)
        //
        private KeyValuePair <ComplexRegionEquation, double> DynamicVisit(int startIndex, bool[] visited, KnownMeasurementsAggregator known)
        {
            // The actual Region object for this node.
            Region thisRegion = graph.vertices[startIndex].data;

            // Cut off search if we've been here before.
            if (visited[startIndex])
            {
                return(new KeyValuePair <ComplexRegionEquation, double>(memoizedSolutions[startIndex], thisRegion.GetKnownArea()));
            }

            // We've been here now.
            visited[startIndex] = true;

            //
            // Can we compute the area of this node directly?
            //
            double area = thisRegion.GetArea(known);

            if (area > 0)
            {
                thisRegion.SetKnownArea(area);
                memoizedSolutions[startIndex] = new ComplexRegionEquation(thisRegion, thisRegion);
                return(new KeyValuePair <ComplexRegionEquation, double>(memoizedSolutions[startIndex], thisRegion.GetKnownArea()));
            }

            //
            // Does any of the edges satisfy this equation? Investigate dynamically.
            //
            // Complex equation resulting from each outgoing edge.
            ComplexRegionEquation shortestEq = null;

            area = 0;
            foreach (Hypergraph.HyperEdge <SimpleRegionEquation> edge in graph.vertices[startIndex].targetEdges)
            {
                KeyValuePair <ComplexRegionEquation, double> src1Eq = DynamicVisit(edge.sourceNodes[0], visited, known);
                KeyValuePair <ComplexRegionEquation, double> src2Eq = DynamicVisit(edge.sourceNodes[1], visited, known);

                // Success, we found a valid area expression for edge.
                if (src1Eq.Key != null && src2Eq.Key != null)
                {
                    // Create a copy of the anootation for a simple region equation for this edge.
                    SimpleRegionEquation simpleEdgeEq = new SimpleRegionEquation(edge.annotation);

                    //
                    // Make one complex equation performing substitutions.
                    //
                    ComplexRegionEquation complexEdgeEq = new ComplexRegionEquation(simpleEdgeEq);
                    complexEdgeEq.Substitute(src1Eq.Key.target, src1Eq.Key.expr);
                    complexEdgeEq.Substitute(src2Eq.Key.target, src2Eq.Key.expr);

                    // Pick the shortest equation possible.
                    if (shortestEq == null)
                    {
                        shortestEq = complexEdgeEq;
                    }
                    else if (shortestEq.Length > complexEdgeEq.Length)
                    {
                        shortestEq = complexEdgeEq;
                    }

                    if (edge.annotation.op == OperationT.ADDITION)
                    {
                        area = src1Eq.Value + src2Eq.Value;
                    }
                    else if (edge.annotation.op == OperationT.SUBTRACTION)
                    {
                        area = src1Eq.Value - src2Eq.Value;
                    }
                }
            }

            //if (shortestEq != null)
            //{
            //    thisRegion.SetKnownArea(area);
            //    memoizedSolutions[startIndex] = new ComplexRegionEquation(thisRegion, thisRegion);
            //    return new KeyValuePair<ComplexRegionEquation, double>(memoizedSolutions[startIndex], area);
            //}

            memoizedSolutions[startIndex] = shortestEq;

            return(new KeyValuePair <ComplexRegionEquation, double>(memoizedSolutions[startIndex], area));
        }