示例#1
0
 public SolutionAgg()
 {
     atomIndices = new IndexList();
     solEq       = null;
     solArea     = -1;
     solType     = SolutionType.UNKNOWN;
 }
示例#2
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);
            }
        }
示例#3
0
 public SolutionAgg()
 {
     atomIndices = new IndexList();
     solEq = null;
     solArea = -1;
     solType = SolutionType.UNKNOWN;
 }
示例#4
0
        public ComplexRegionEquation(ComplexRegionEquation complex) : base()
        {
            target = complex.target;

            expr = complex.expr.Copy();

            thisArea = -1;
        }
        public ComplexRegionEquation(ComplexRegionEquation complex)
            : base()
        {
            target = complex.target;

            expr = complex.expr.Copy();

            thisArea = -1;
        }
示例#6
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();
        }
示例#7
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);
            }
        }
        public ComplexRegionEquation TraceRegionArea(Region thatRegion)
        {
            // Find this region in the hypergraph.
            int startIndex = graph.GetNodeIndex(thatRegion);

            if (startIndex == -1) throw new ArgumentException("Desired region not found in area hypergraph: " + thatRegion);

            // Modifiable region equation: region = region so that we substitute into the RHS.
            ComplexRegionEquation eq = new ComplexRegionEquation(thatRegion, thatRegion);

            // Traverse depth-first to construct all equations.
            bool success = SimpleVisit(startIndex, eq);

            return success ? memoizedSolutions[startIndex] : null;
        }
        //
        // The graph nodes are the powerset of atomic nodes
        //
        private void PrecomputeShapes()
        {
            // Construct each element of the powerset
            for (int r = 0; r < graph.vertices.Count; r++)
            {
                // TODO collect atoms into a shape....



                // Check if we can memoize this directly as a shape
                if (graph.vertices[r].data is ShapeRegion)
                {
                    memoizedSolutions[r] = new ComplexRegionEquation(graph.vertices[r].data, graph.vertices[r].data);
                }
            }
        }
        public ComplexRegionEquation TraceRegionArea(Region thatRegion)
        {
            // Find this region in the hypergraph.
            int startIndex = graph.GetNodeIndex(thatRegion);

            if (startIndex == -1)
            {
                throw new ArgumentException("Desired region not found in area hypergraph: " + thatRegion);
            }

            // Modifiable region equation: region = region so that we substitute into the RHS.
            ComplexRegionEquation eq = new ComplexRegionEquation(thatRegion, thatRegion);

            // Traverse depth-first to construct all equations.
            bool success = SimpleVisit(startIndex, eq);

            return(success ? memoizedSolutions[startIndex] : null);
        }
示例#11
0
        //
        // Depth-First
        //
        public ComplexRegionEquation TraceRegionArea(Region thatRegion)
        {
            // Find this region in the hypergraph.
            int startIndex = graph.GetNodeIndex(thatRegion);

            if (startIndex == -1)
            {
                throw new ArgumentException("Desired region not found in area hypergraph: " + thatRegion);
            }

            // Modifiable region equation: region = region so that we substitute into the RHS.
            ComplexRegionEquation eq = new ComplexRegionEquation(thatRegion, thatRegion);

            bool[] visited = new bool[graph.Size()];

            //    // Precompute any shapes in which we know we can compute the area; this is done in BuildNodes()
            //    memoizedSolutions = new ComplexRegionEquation[graph.Size()];

            // Traverse depth-first to construct all equations.
            bool success = SimpleVisit(startIndex, eq, visited);


            return(success ? memoizedSolutions[startIndex] : null);
        }
示例#12
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);
            }
        }
示例#13
0
        //
        // 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));
        }
        //
        // Depth-First
        //
        public ComplexRegionEquation TraceRegionArea(Region thatRegion)
        {
            // Find this region in the hypergraph.
            int startIndex = graph.GetNodeIndex(thatRegion);

            if (startIndex == -1) throw new ArgumentException("Desired region not found in area hypergraph: " + thatRegion);

            // Modifiable region equation: region = region so that we substitute into the RHS.
            ComplexRegionEquation eq = new ComplexRegionEquation(thatRegion, thatRegion);

            bool[] visited = new bool[graph.Size()];

            //    // Precompute any shapes in which we know we can compute the area; this is done in BuildNodes()
            //    memoizedSolutions = new ComplexRegionEquation[graph.Size()];

            // Traverse depth-first to construct all equations.
            bool success = SimpleVisit(startIndex, eq, visited);

            return success ? memoizedSolutions[startIndex] : null;
        }
示例#15
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);
            }
        }
        //
        // 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);
        }
        //
        // Graph traversal to find shapes and thus the resulting equation (solution).
        //
        // Depth first: construct along the way
        // Find only the SHORTEST equation (based on the number of regions involved in the equation).
        //
        private bool SimpleVisit(int regionIndex, ComplexRegionEquation currentEq, bool[] visited)
        {
            //
            // Deal with memoizing: keep the shortest equation for this particular region (@ regionIndex)
            //
            if (visited[regionIndex]) return true;

            // We have now visited this node.
            visited[regionIndex] = true;

            // Is this partitcular region a shape?
            // If so, save the basis equation in memozied.
            if (graph.vertices[regionIndex].data is ShapeRegion) return true;

            // For all hyperedges leaving this node, follow the edge sources
            foreach (Hypergraph.HyperEdge<SimpleRegionEquation> edge in graph.vertices[regionIndex].targetEdges)
            {
                // Will contain two equations representing expressions for the source node
                ComplexRegionEquation[] edgeEqs = new ComplexRegionEquation[edge.sourceNodes.Count];

                // For actively substituting into.
                ComplexRegionEquation currentEqCopy = new ComplexRegionEquation(currentEq);

                // Area can be calcualted either directly or using the GeoTutor deductive engine.
                bool canCalcArea = true;
                for (int e = 0; e < edge.sourceNodes.Count; e++)
                {
                    // If we have already visited this node, we already have an equation for it; use it.
                    if (visited[edge.sourceNodes[e]])
                    {
                        // Check if we cannot calculate the region area.
                        if (memoizedSolutions[edge.sourceNodes[e]] == null)
                        {
                            canCalcArea = false;
                            break;
                        }

                        // Otherwise, we use the memoized version of this region equation for this source node.
                        edgeEqs[e] = memoizedSolutions[edge.sourceNodes[e]];
                    }
                    // We don't have a memoized version; calculate it.
                    else
                    {
                        // Create an equation: region = region so that we substitute into the RHS.
                        Region srcRegion = graph.vertices[edge.sourceNodes[e]].data;
                        edgeEqs[e] = new ComplexRegionEquation(srcRegion, srcRegion);

                        // This source node is not a shape: we can't directly calculate its area.
                        if (!SimpleVisit(edge.sourceNodes[e], edgeEqs[e], visited))
                        {
                            canCalcArea = false;
                            break;
                        }
                    }
                }

                //
                // If we have a successful search from this edge, create the corresponding region equation.
                //
                if (canCalcArea)
                {
                    // We can substitute the annotation along the edge into the edge's target region (expression).

                                             // to find (val)
                    currentEqCopy.Substitute(graph.vertices[edge.targetNode].data,
                                             // to sub (for val)
                                             new ComplexRegionEquation.Binary(edgeEqs[0].expr,
                                                                              edge.annotation.op,
                                                                              edgeEqs[0].expr));
                    // Choose the shortest solution for this region
                    if (currentEq.Length > currentEqCopy.Length)
                    {
                        currentEq = currentEqCopy;
                    }
                }
            }

            // Did we find a solution?
            if (currentEq.Length == int.MaxValue) return false;

            // Success; save the solution.
            memoizedSolutions[regionIndex] = currentEq;

            return true;
        }
示例#18
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);
            }
        }
        //
        // The graph nodes are the powerset of atomic nodes
        //
        private void PrecomputeShapes()
        {
            // Construct each element of the powerset
            for (int r = 0; r < graph.vertices.Count; r++)
            {
                // TODO collect atoms into a shape....

                // Check if we can memoize this directly as a shape
                if (graph.vertices[r].data is ShapeRegion)
                {
                    memoizedSolutions[r] = new ComplexRegionEquation(graph.vertices[r].data, graph.vertices[r].data);
                }
            }
        }
示例#20
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();
        }
        //
        // Graph traversal to find shapes and thus the resulting equation (solution).
        //
        // Depth first: construct along the way
        // Find only the SHORTEST equation (based on the number of regions involved in the equation).
        //
        private bool SimpleVisit(int regionIndex, ComplexRegionEquation currentEq)
        {
            //
            // Deal with memoizing: keep the shortest equation for this particular region (@ regionIndex)
            //
            if (visited[regionIndex])
            {
                return(true);
            }

            // We have now visited this node.
            visited[regionIndex] = true;

            // Is this partitcular region a shape?
            // If so, save the basis equation in memozied.
            if (graph.vertices[regionIndex].data is ShapeRegion)
            {
                return(true);
            }

            // For all hyperedges leaving this node, follow the edge sources
            foreach (Hypergraph.HyperEdge <SimpleRegionEquation> edge in graph.vertices[regionIndex].targetEdges)
            {
                // Will contain two equations representing expressions for the source node
                ComplexRegionEquation[] edgeEqs = new ComplexRegionEquation[edge.sourceNodes.Count];

                // For actively substituting into.
                ComplexRegionEquation currentEqCopy = new ComplexRegionEquation(currentEq);

                // Area can be calcualted either directly or using the GeoTutor deductive engine.
                bool canCalcArea = true;
                for (int e = 0; e < edge.sourceNodes.Count; e++)
                {
                    // If we have already visited this node, we already have an equation for it; use it.
                    if (visited[edge.sourceNodes[e]])
                    {
                        // Check if we cannot calculate the region area.
                        if (memoizedSolutions[edge.sourceNodes[e]] == null)
                        {
                            canCalcArea = false;
                            break;
                        }

                        // Otherwise, we use the memoized version of this region equation for this source node.
                        edgeEqs[e] = memoizedSolutions[edge.sourceNodes[e]];
                    }
                    // We don't have a memoized version; calculate it.
                    else
                    {
                        // Create an equation: region = region so that we substitute into the RHS.
                        Region srcRegion = graph.vertices[edge.sourceNodes[e]].data;
                        edgeEqs[e] = new ComplexRegionEquation(srcRegion, srcRegion);

                        // This source node is not a shape: we can't directly calculate its area.
                        if (!SimpleVisit(edge.sourceNodes[e], edgeEqs[e]))
                        {
                            canCalcArea = false;
                            break;
                        }
                    }
                }

                //
                // If we have a successful search from this edge, create the corresponding region equation.
                //
                if (canCalcArea)
                {
                    // We can substitute the annotation along the edge into the edge's target region (expression).

                    // to find (val)
                    currentEqCopy.Substitute(graph.vertices[edge.targetNode].data,
                                             // to sub (for val)
                                             new ComplexRegionEquation.Binary(edgeEqs[0].expr,
                                                                              edge.annotation.op,
                                                                              edgeEqs[0].expr));
                    // Choose the shortest solution for this region
                    if (currentEq.Length > currentEqCopy.Length)
                    {
                        currentEq = currentEqCopy;
                    }
                }
            }

            // Did we find a solution?
            if (currentEq.Length == int.MaxValue)
            {
                return(false);
            }

            // Success; save the solution.
            memoizedSolutions[regionIndex] = currentEq;

            return(true);
        }
示例#22
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);
            }
        }