// // 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 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); } } } }
// // Is this problem (defined by the set of atomic regions) covered / defined by all the root shapes? // public bool IsProblemInteresting(List <Figure> roots, List <AtomicRegion> regions) { SolutionAgg solution = solutions.GetSolutionAgg(this.figureAtoms, regions); List <int>[] coverage = DetermineAtomCoverageOfShapes(roots); return(SolutionCoversRoots(coverage, solution, roots.Count)); }
public override bool Equals(object obj) { SolutionAgg that = obj as SolutionAgg; if (that == null) { return(false); } return(Utilities.EqualOrderedSets(this.atomIndices.orderedIndices, that.atomIndices.orderedIndices)); }
// // Acquire a single solution equation and area value. // public KeyValuePair <ComplexRegionEquation, double> GetSolution(List <Atomizer.AtomicRegion> figureAtoms, List <Atomizer.AtomicRegion> desiredRegions) { IndexList indices = IndexList.AcquireAtomicRegionIndices(figureAtoms, desiredRegions); SolutionAgg solutionAgg = null; if (!solutions.TryGetValue(indices, out solutionAgg)) { throw new ArgumentException("Could not find a solution in the database."); } return(new KeyValuePair <ComplexRegionEquation, double>(solutionAgg.solEq, solutionAgg.solArea)); }
// // Does this one solution cover all root shapes. // private bool SolutionCoversRoots(List <int>[] coverage, SolutionAgg solution, int numShapes) { List <int> shapesCovered = new List <int>(); // Collect all shape-covered indices foreach (int index in solution.atomIndices.orderedIndices) { Utilities.AddUniqueList <int>(shapesCovered, coverage[index]); } // If we covered all indices, the solution covers. return(shapesCovered.Count == numShapes); }
// // Acquire a single solution equation and area value. // public SolutionAgg GetSolutionAgg(List <Atomizer.AtomicRegion> figureAtoms, List <Atomizer.AtomicRegion> desiredRegions) { IndexList indices = IndexList.AcquireAtomicRegionIndices(figureAtoms, desiredRegions); SolutionAgg solutionAgg = null; if (!solutions.TryGetValue(indices, out solutionAgg)) { throw new ArgumentException("Could not find a solution in the database."); } return(solutionAgg); }
// // 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(); }
// // 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 PreprocessShapeHierarchyAreas(KnownMeasurementsAggregator known, TreeNode<Figure> currentRoot) //{ // Figure theFigure = currentRoot.GetData(); // // 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); // } // foreach (TreeNode<Figure> child in currentRoot.Children()) // { // PreprocessShapeHierarchyAreas(known, child); // } //} // // Combine (through addition) any / all set of two equations in which there is no shared atomic region: // (0 1 2) + (5 6) = (0 1 2 5 6) // // worklist-style fixpoint construction // private void ComposeAllRegions() { List <SolutionAgg> worklist = new List <SolutionAgg>(solutions.GetComputableSolutions()); while (worklist.Any()) { SolutionAgg currentSol = worklist[0]; worklist.RemoveAt(0); foreach (SolutionAgg otherSol in solutions.GetSolutions()) { HandleComposition(worklist, currentSol, otherSol); } solutions.AddSolution(currentSol); } }
private void HandleComposition(List <SolutionAgg> worklist, SolutionAgg first, SolutionAgg second) { // Addition of the two regions. SolutionAgg unionSol = HandleUnion(first, second); if (unionSol != null) { AddToWorklist(worklist, unionSol); } else { // Subtraction of the two regions. SolutionAgg diffSol = HandleDifference(first, second); if (diffSol != null) { AddToWorklist(worklist, diffSol); } } }
// // Adds an equation, if it does not exist. // If an equation for the region already exists, take the shortest one or the one that is computable. // private bool AddSolution(Dictionary <IndexList, SolutionAgg> solDictionary, SolutionAgg that) { // // Does this equation NOT exist in the database? // SolutionAgg existentAgg = null; if (!solDictionary.TryGetValue(that.atomIndices, out existentAgg)) { // Add this solution to the database. solDictionary.Add(that.atomIndices, that); return(true); } // // The equation already exists in the database. // return(UpdateSolution(solDictionary, existentAgg, that)); }
private SolutionAgg HandleDifference(SolutionAgg first, SolutionAgg second) { // Can we combine the currentSol with this existent solution? IndexList diffIndices = IndexList.DifferenceIndices(first.atomIndices, second.atomIndices); // Disjoint union not possible. if (diffIndices == null) { return(null); } // // Can combine; create a new solution / equation with addition. // SolutionAgg newSum = new SolutionAgg(); newSum.atomIndices = diffIndices; newSum.solType = first.solType == SolutionAgg.SolutionType.COMPUTABLE && second.solType == SolutionAgg.SolutionType.COMPUTABLE ? SolutionAgg.SolutionType.COMPUTABLE : SolutionAgg.SolutionType.INCOMPUTABLE; if (newSum.solType == SolutionAgg.SolutionType.INCOMPUTABLE) { newSum.solArea = -1; } else { newSum.solArea = first.solArea > second.solArea ? first.solArea - second.solArea : second.solArea - first.solArea; } if (first.atomIndices.Count > second.atomIndices.Count) { newSum.solEq = new ComplexRegionEquation(MakeRegion(diffIndices.orderedIndices), new ComplexRegionEquation.Binary(first.solEq.target, OperationT.SUBTRACTION, second.solEq.target)); } else { newSum.solEq = new ComplexRegionEquation(MakeRegion(diffIndices.orderedIndices), new ComplexRegionEquation.Binary(second.solEq.target, OperationT.SUBTRACTION, first.solEq.target)); } return(newSum); }
// // Given that both the old and new solutions are computable, how to do we prefer one solution over another? // private bool PreferNewComputableSolution(SolutionAgg existent, SolutionAgg newSolution) { bool exisDefShapes = existent.solEq.DefinedByShapes(); bool newDefShapes = newSolution.solEq.DefinedByShapes(); // // Favor a solution consisting of all shapes over the alternative. // if (exisDefShapes && !newDefShapes) { return(false); } if (!exisDefShapes && newDefShapes) { return(true); } // // Favor a shorter solution. // return(existent.solEq.Length > newSolution.solEq.Length); }
// // If the solution is already in the database, update the solution in the database (if needed). // otherwise, add this solution to the worklist. // private void AddToWorklist(List <SolutionAgg> worklist, SolutionAgg solution) { //// Guarantee we may add this to the aorklist for processing. //if (!solutions.Contains(solution)) //{ // worklist.Add(solution); // return; //} // // If the solution is already in the database, update the solution in the database (if needed). // if (solutions.AddSolution(solution)) { // The solution may be in the worklist for processing; update accordingly. int worklistIndex = worklist.IndexOf(solution); if (worklistIndex != -1) { worklist[worklistIndex] = solution; } } }
private SolutionAgg HandleUnion(SolutionAgg first, SolutionAgg second) { // Can we combine the currentSol with this existent solution? IndexList unionIndices = IndexList.UnionIndices(first.atomIndices, second.atomIndices); // Disjoint union not possible. if (unionIndices == null) { return(null); } // // Can combine; create a new solution / equation with addition. // SolutionAgg newSum = new SolutionAgg(); newSum.atomIndices = unionIndices; newSum.solType = first.solType == SolutionAgg.SolutionType.COMPUTABLE && second.solType == SolutionAgg.SolutionType.COMPUTABLE ? SolutionAgg.SolutionType.COMPUTABLE : SolutionAgg.SolutionType.INCOMPUTABLE; newSum.solArea = newSum.solType == SolutionAgg.SolutionType.COMPUTABLE ? first.solArea + second.solArea : -1; newSum.solEq = new ComplexRegionEquation(MakeRegion(unionIndices.orderedIndices), new ComplexRegionEquation.Binary(first.solEq.target, OperationT.ADDITION, second.solEq.target)); return(newSum); }
// // If the solution exists in the root solutions as incomputable, seek a solution from the extended // public bool TryGetValue(IndexList indices, out SolutionAgg solutionAgg) { return solutions.TryGetValue(indices, out solutionAgg); }
// // Given that both the old and new solutions are computable, how to do we prefer one solution over another? // private bool PreferNewComputableSolution(SolutionAgg existent, SolutionAgg newSolution) { bool exisDefShapes = existent.solEq.DefinedByShapes(); bool newDefShapes = newSolution.solEq.DefinedByShapes(); // // Favor a solution consisting of all shapes over the alternative. // if (exisDefShapes && !newDefShapes) return false; if (!exisDefShapes && newDefShapes) return true; // // Favor a shorter solution. // return existent.solEq.Length > newSolution.solEq.Length; }
// // Adds an equation, if it does not exist. // If an equation for the region already exists, take the shortest one or the one that is computable. // private bool AddSolution(Dictionary<IndexList, SolutionAgg> solDictionary, SolutionAgg that) { // // Does this equation NOT exist in the database? // SolutionAgg existentAgg = null; if (!solDictionary.TryGetValue(that.atomIndices, out existentAgg)) { // Add this solution to the database. solDictionary.Add(that.atomIndices, that); return true; } // // The equation already exists in the database. // return UpdateSolution(solDictionary, existentAgg, that); }
// // If the solution is already in the database, update the solution in the database (if needed). // otherwise, add this solution to the worklist. // private void AddToWorklist(List<SolutionAgg> worklist, SolutionAgg solution) { //// Guarantee we may add this to the aorklist for processing. //if (!solutions.Contains(solution)) //{ // worklist.Add(solution); // return; //} // // If the solution is already in the database, update the solution in the database (if needed). // if (solutions.AddSolution(solution)) { // The solution may be in the worklist for processing; update accordingly. int worklistIndex = worklist.IndexOf(solution); if (worklistIndex != -1) { worklist[worklistIndex] = solution; } } }
// // The equation already exists in the database. // private bool UpdateSolution(Dictionary <IndexList, SolutionAgg> solDictionary, SolutionAgg existentAgg, SolutionAgg that) { // Favor a straight-forward calculation of the area (no manipulations to acquire the value). if (existentAgg.IsDirectArea()) { return(false); } // Favor a coomputable equation over incomputable. if (existentAgg.solType == SolutionAgg.SolutionType.INCOMPUTABLE && that.solType == SolutionAgg.SolutionType.COMPUTABLE) { solDictionary[that.atomIndices] = that; return(true); } // Again, favor a computable solution over not. else if (existentAgg.solType == SolutionAgg.SolutionType.COMPUTABLE && that.solType == SolutionAgg.SolutionType.INCOMPUTABLE) { // NO-OP } // The computability is the same for both equations. else if (existentAgg.solType == that.solType || existentAgg.solType == SolutionAgg.SolutionType.UNKNOWN) { if (!Utilities.CompareValues(existentAgg.solArea, that.solArea)) { throw new Exception("Area for region " + existentAgg.atomIndices.ToString() + " was calculated now as (" + existentAgg.solArea + ") AND before (" + that.solArea + ")"); } if (PreferNewComputableSolution(existentAgg, that)) { solDictionary[that.atomIndices] = that; return(true); } } return(false); }
// // Does this one solution cover all root shapes. // private bool SolutionCoversRoots(List<int>[] coverage, SolutionAgg solution, int numShapes) { List<int> shapesCovered = new List<int>(); // Collect all shape-covered indices foreach (int index in solution.atomIndices.orderedIndices) { Utilities.AddUniqueList<int>(shapesCovered, coverage[index]); } // If we covered all indices, the solution covers. return shapesCovered.Count == numShapes; }
// // The equation already exists in the database. // private bool UpdateSolution(Dictionary<IndexList, SolutionAgg> solDictionary, SolutionAgg existentAgg, SolutionAgg that) { // Favor a straight-forward calculation of the area (no manipulations to acquire the value). if (existentAgg.IsDirectArea()) return false; // Favor a coomputable equation over incomputable. if (existentAgg.solType == SolutionAgg.SolutionType.INCOMPUTABLE && that.solType == SolutionAgg.SolutionType.COMPUTABLE) { solDictionary[that.atomIndices] = that; return true; } // Again, favor a computable solution over not. else if (existentAgg.solType == SolutionAgg.SolutionType.COMPUTABLE && that.solType == SolutionAgg.SolutionType.INCOMPUTABLE) { // NO-OP } // The computability is the same for both equations. else if (existentAgg.solType == that.solType || existentAgg.solType == SolutionAgg.SolutionType.UNKNOWN) { if (!Utilities.CompareValues(existentAgg.solArea, that.solArea)) { throw new Exception("Area for region " + existentAgg.atomIndices.ToString() + " was calculated now as (" + existentAgg.solArea + ") AND before (" + that.solArea + ")"); } if (PreferNewComputableSolution(existentAgg, that)) { solDictionary[that.atomIndices] = that; return true; } } return false; }
public bool Contains(SolutionAgg solution) { return(Contains(solution.atomIndices)); }
// // 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); } } }
public bool AddSolution(SolutionAgg that) { return AddSolution(solutions, that); }
public bool Contains(SolutionAgg solution) { return Contains(solution.atomIndices); }
private void HandleComposition(List<SolutionAgg> worklist, SolutionAgg first, SolutionAgg second) { // Addition of the two regions. SolutionAgg unionSol = HandleUnion(first, second); if (unionSol != null) { AddToWorklist(worklist, unionSol); } else { // Subtraction of the two regions. SolutionAgg diffSol = HandleDifference(first, second); if (diffSol != null) AddToWorklist(worklist, diffSol); } }
public bool AddSolution(SolutionAgg that) { return(AddSolution(solutions, that)); }
// // If the solution exists in the root solutions as incomputable, seek a solution from the extended // public bool TryGetValue(IndexList indices, out SolutionAgg solutionAgg) { return(solutions.TryGetValue(indices, out solutionAgg)); }
private SolutionAgg HandleUnion(SolutionAgg first, SolutionAgg second) { // Can we combine the currentSol with this existent solution? IndexList unionIndices = IndexList.UnionIndices(first.atomIndices, second.atomIndices); // Disjoint union not possible. if (unionIndices == null) return null; // // Can combine; create a new solution / equation with addition. // SolutionAgg newSum = new SolutionAgg(); newSum.atomIndices = unionIndices; newSum.solType = first.solType == SolutionAgg.SolutionType.COMPUTABLE && second.solType == SolutionAgg.SolutionType.COMPUTABLE ? SolutionAgg.SolutionType.COMPUTABLE : SolutionAgg.SolutionType.INCOMPUTABLE; newSum.solArea = newSum.solType == SolutionAgg.SolutionType.COMPUTABLE ? first.solArea + second.solArea : -1; newSum.solEq = new ComplexRegionEquation(MakeRegion(unionIndices.orderedIndices), new ComplexRegionEquation.Binary(first.solEq.target, OperationT.ADDITION, second.solEq.target)); return newSum; }
// // 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 SolutionAgg HandleDifference(SolutionAgg first, SolutionAgg second) { // Can we combine the currentSol with this existent solution? IndexList diffIndices = IndexList.DifferenceIndices(first.atomIndices, second.atomIndices); // Disjoint union not possible. if (diffIndices == null) return null; // // Can combine; create a new solution / equation with addition. // SolutionAgg newSum = new SolutionAgg(); newSum.atomIndices = diffIndices; newSum.solType = first.solType == SolutionAgg.SolutionType.COMPUTABLE && second.solType == SolutionAgg.SolutionType.COMPUTABLE ? SolutionAgg.SolutionType.COMPUTABLE : SolutionAgg.SolutionType.INCOMPUTABLE; if (newSum.solType == SolutionAgg.SolutionType.INCOMPUTABLE) { newSum.solArea = -1; } else { newSum.solArea = first.solArea > second.solArea ? first.solArea - second.solArea : second.solArea - first.solArea; } if (first.atomIndices.Count > second.atomIndices.Count) { newSum.solEq = new ComplexRegionEquation(MakeRegion(diffIndices.orderedIndices), new ComplexRegionEquation.Binary(first.solEq.target, OperationT.SUBTRACTION, second.solEq.target)); } else { newSum.solEq = new ComplexRegionEquation(MakeRegion(diffIndices.orderedIndices), new ComplexRegionEquation.Binary(second.solEq.target, OperationT.SUBTRACTION, first.solEq.target)); } return newSum; }
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); } } } }