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; }
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); } } } }
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); } }
// public List<Point> ownedPoints { get; protected set; } public Region(Region that) : this(that.atoms) { }