// // 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); }
// // 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; }
// // 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)); }