public ComplexRegionEquation(Region tar, Region r)
     : base()
 {
     target = tar;
     expr = new Unary(r);
     thisArea = -1;
 }
 public SimpleRegionEquation(Region t,  Region big, OperationT opType, Region small)
     : base()
 {
     target = t;
     bigger = big;
     op = opType;
     smaller = small;
 }
        // Ensures unique addition (no addition if the queue contains the element)
        public void AddToWorklist(Queue<Region> worklist, Region r)
        {
            foreach (Region wr in worklist)
            {
                if (wr.RegionDefinedBy(r.atoms)) return;
            }

            worklist.Enqueue(r);
        }
        public ComplexRegionEquation(Region tar, Expr exp)
            : base()
        {
            target = tar;

            expr = exp;

            thisArea = -1;
        }
        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;
        }
        //
        // 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);
            }
        }
        //
        // 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);
            }
        }
 //
 // Return T / F if we added anything new to the hypergraph
 //
 private bool CreateAddNodesEdges(Region large, Region small, Region atom)
 {
     return(CreateAddNodes(large, small, atom) || CreateAddEdges(large, small, atom));
 }
 public Unary(Region r)
     : base()
 {
     theRegion = r;
 }
 public override Expr Substitute(Region toFind, Expr toSub)
 {
     Expr newLeft = leftExp.Substitute(toFind, toSub);
     Expr newRight = leftExp.Substitute(toFind, toSub);
     return new Binary(newLeft, this.op, newRight);
 }
 public Binary(Region ell, OperationT op, Region r)
     : this(new Unary(ell), op, new Unary(r))
 {
 }
 public void SetTarget(Region targ)
 {
     this.target = targ;
 }
 //
 // Return T / F if we added anything new to the hypergraph
 //
 private bool CreateAddNodesEdges(Region large, Region small, Region atom)
 {
     return CreateAddNodes(large, small, atom) || CreateAddEdges(large, small, atom);
 }
        //
        // Add nodes
        //
        private bool CreateAddNodes(Region large, Region small, Region atom)
        {
            bool addedNode = false;

            if (graph.AddNode(large)) addedNode = true;
            if (graph.AddNode(small)) addedNode = true;
            if (graph.AddNode(atom)) addedNode = true;

            return addedNode;
        }
        //
        // Add edges
        //
        private bool CreateAddEdges(Region large, Region small, Region atom)
        {
            bool addedEdge = false;

            //
            // A = (A \ a) + a
            //
            SimpleRegionEquation sumAnnotation = new SimpleRegionEquation(large, small, OperationT.ADDITION, atom);
            List<Region> sources = new List<Region>();
            sources.Add(small);
            sources.Add(atom);
            if (graph.AddEdge(sources, large, sumAnnotation)) addedEdge = true;

            //
            // (A \ a) = A - a
            //
            SimpleRegionEquation diff1Annotation = new SimpleRegionEquation(small, large, OperationT.SUBTRACTION, atom);
            sources = new List<Region>();
            sources.Add(large);
            sources.Add(atom);
            if (graph.AddEdge(sources, small, diff1Annotation)) addedEdge = true;

            //
            // a = A - (A \ a)
            //
            SimpleRegionEquation diff2Annotation = new SimpleRegionEquation(atom, large, OperationT.SUBTRACTION, small);
            sources = new List<Region>();
            sources.Add(large);
            sources.Add(small);
            if (graph.AddEdge(sources, atom, diff2Annotation)) addedEdge = true;

            return addedEdge;
        }
        //
        // 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;
        }
        //
        // 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);
        }
        //
        // 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));
        }
 public AreaArithmeticOperation(Region l, Region r)
     : base()
 {
     leftExp = l;
     rightExp = r;
 }
Example #20
0
 public AreaAddition(Region l, Region r)
     : base(l, r)
 {
 }
        //
        // Look at all nodes in the graph. If we can combine this atomic region with any region, add edges and nodes.
        //
        private void RegionComposition(Region currAtomRegion, List<ShapeRegion> shapeRegions, Queue<Region> worklist)
        {
            AtomicRegion atom = currAtomRegion.atoms[0];

            // Look at all nodes in the graph
            int graphSize = graph.Size();
            for (int n = 0; n < graphSize; n++)
            {
                Region node = graph.vertices[n].data;

                // If the region in the graph does NOT have this atom, perform construction.
                if (!node.HasAtom(atom))
                {
                    // Make the sum-set of atoms.
                    List<AtomicRegion> sumAtoms = new List<AtomicRegion>(node.atoms);
                    sumAtoms.Add(atom);

                    // Construct the shape: Shape = atoms + atom
                    Region sumRegion = GetShapeRegion(shapeRegions, sumAtoms);
                    if (sumRegion == null) sumRegion = new Region(sumAtoms);

                    // Add to the worklist if we have added something new.
                    if (CreateAddNodesEdges(sumRegion, node, currAtomRegion))
                    {
                        // Add the smaller regions to the worklist.
                        worklist.Enqueue(sumRegion);
                    }
                }
            }
        }
 public void Substitute(Region toFind, Expr toSub)
 {
     expr.Substitute(toFind, toSub);
 }
        //
        // Take the curr region and deconstruct it into all its atoms to place in the hypergraph.
        //
        private void RegionDecomposition(Region currRegion, List<ShapeRegion> shapeRegions, Queue<Region> worklist)
        {
            for (int a = 0; a < currRegion.atoms.Count; a++)
            {
                AtomicRegion currAtom = currRegion.atoms[a];

                if (currAtom is ShapeAtomicRegion)
                {
                    // Make the difference-set of atoms.
                    List<AtomicRegion> diffSet = new List<AtomicRegion>(currRegion.atoms);
                    diffSet.RemoveAt(a);

                    // Deconstruct the shape: Shape = atoms \ atom
                    Region diffRegion = GetShapeRegion(shapeRegions, diffSet);
                    if (diffRegion == null) diffRegion = new Region(diffSet);

                    Region atomRegion = GetShapeRegion(shapeRegions, Utilities.MakeList<AtomicRegion>(currAtom));
                    if (atomRegion == null) atomRegion = new Region(currAtom);

                    // Add to the worklist if we have added something new.
                    if (CreateAddNodesEdges(currRegion, diffRegion, atomRegion))
                    {
                        // Add the smaller regions to the worklist.
                        AddToWorklist(worklist, diffRegion);

                        // They can't be broken down, but they can be constructed.
                        AddToWorklist(worklist, atomRegion);
                    }
                }
            }
        }
Example #24
0
 public AreaSubtraction(Region l, Region r) : base(l, r)
 {
 }
 public override Expr Substitute(Region toFind, Expr toSub)
 {
     return theRegion.Equals(toFind) ? toSub : this;
 }
 public abstract Expr Substitute(Region toFind, Expr toSub);
 public void AppendSubtraction(Region r)
 {
     this.expr = new Binary(this.expr, OperationT.SUBTRACTION, new Unary(r));
 }
 public Unary(Unary e)
     : base()
 {
     theRegion = e.theRegion;
 }
        //
        // There is one addition edge and two subtraction edges per set of 3 nodes.
        // Build the edges top-down from complete set of atoms down to singletons.
        //
        private void BuildEdges(List<Atomizer.AtomicRegion> atoms, bool[] marked)
        {
            // We don't want edges connecting a singleton region to an 'empty' region.
            if (atoms.Count == 1) return;

            // The node for this set of list of atoms.
            Region atomsRegion = new Region(atoms);

            // Check to see if we have already visited this node and constructed the edges.
            int nodeIndex = graph.GetNodeIndex(atomsRegion);
            if (marked[nodeIndex]) return;

            foreach (Atomizer.AtomicRegion atom in atoms)
            {
                List<Atomizer.AtomicRegion> atomsMinusAtom = new List<Atomizer.AtomicRegion>(atoms);
                atomsMinusAtom.Remove(atom);

                Region aMinus1Region = new Region(atomsMinusAtom);
                Region atomRegion = new Region(atom);

                //
                // A = (A \ a) + a
                //
                SimpleRegionEquation sumAnnotation = new SimpleRegionEquation(atomsRegion, aMinus1Region, OperationT.ADDITION, atomRegion);
                List<Region> sources = new List<Region>();
                sources.Add(aMinus1Region);
                sources.Add(atomRegion);
                graph.AddEdge(sources, atomsRegion, sumAnnotation);

                //
                // (A \ a) = A - a
                //
                SimpleRegionEquation diff1Annotation = new SimpleRegionEquation(aMinus1Region, atomsRegion, OperationT.SUBTRACTION, atomRegion);
                sources = new List<Region>();
                sources.Add(atomsRegion);
                sources.Add(atomRegion);
                graph.AddEdge(sources, aMinus1Region, diff1Annotation);

                //
                // a = A - (A \ a)
                //
                SimpleRegionEquation diff2Annotation = new SimpleRegionEquation(atomRegion, atomsRegion, OperationT.SUBTRACTION, aMinus1Region);
                sources = new List<Region>();
                sources.Add(atomsRegion);
                sources.Add(aMinus1Region);
                graph.AddEdge(sources, atomRegion, diff2Annotation);

                //
                // Recursive call to construct edges with A \ a
                //
                BuildEdges(atomsMinusAtom, marked);
            }

            Debug.WriteLine(graph.EdgeCount());
            marked[nodeIndex] = true;
        }
        //
        // 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);
        }
        //
        // 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 #32
0
 public AreaSubtraction(Region l, Region r)
     : base(l, r)
 {
 }
Example #33
0
 //        public List<Point> ownedPoints { get; protected set; }
 public Region(Region that)
     : this(that.atoms)
 {
 }