private GroupBoundsLeastEnlarged pickNext(IList <IBoundable <IExtents> > entries, ComputationExtents group1Bounds, ComputationExtents group2Bounds, out IBoundable <IExtents> entry) { Double maxArealDifference = -1; GroupBoundsLeastEnlarged group = GroupBoundsLeastEnlarged.Tie; IBoundable <IExtents> nextEntry = null; foreach (IBoundable <IExtents> e in entries) { ComputationExtents bounds = new ComputationExtents(e.Bounds); ComputationExtents group1Join = bounds.Union(group1Bounds); ComputationExtents group2Join = bounds.Union(group2Bounds); Double arealDifferenceGroup1 = Math.Abs( group1Join.Area - group1Bounds.Area); Double arealDifferenceGroup2 = Math.Abs( group2Join.Area - group2Bounds.Area); Double differenceInAreas = Math.Abs(arealDifferenceGroup1 - arealDifferenceGroup2); if (differenceInAreas > maxArealDifference) { maxArealDifference = differenceInAreas; nextEntry = e; if (arealDifferenceGroup1 < arealDifferenceGroup2) { group = GroupBoundsLeastEnlarged.Group1; } else if (arealDifferenceGroup2 < arealDifferenceGroup1) { group = GroupBoundsLeastEnlarged.Group2; } } } entries.Remove(nextEntry); entry = nextEntry; return(group); }
private GroupBoundsLeastEnlarged pickNext(IList <IBoundable <TBounds> > entries, TBounds group1Bounds, TBounds group2Bounds, out TItem entry) { Double maxArealDifference = -1; GroupBoundsLeastEnlarged group = GroupBoundsLeastEnlarged.Tie; TItem nextEntry = default(TItem); foreach (TItem e in entries) { TBounds bounds = (TBounds)e.Bounds.Clone(); TBounds group1Join = (TBounds)bounds.Union(group1Bounds); TBounds group2Join = (TBounds)bounds.Union(group2Bounds); Double arealDifferenceGroup1 = Math.Abs( Area(group1Join) - Area(group1Bounds)); Double arealDifferenceGroup2 = Math.Abs( Area(group2Join) - Area(group2Bounds)); Double differenceInAreas = Math.Abs(arealDifferenceGroup1 - arealDifferenceGroup2); if (differenceInAreas > maxArealDifference) { maxArealDifference = differenceInAreas; nextEntry = e; if (arealDifferenceGroup1 < arealDifferenceGroup2) { group = GroupBoundsLeastEnlarged.Group1; } else if (arealDifferenceGroup2 < arealDifferenceGroup1) { group = GroupBoundsLeastEnlarged.Group2; } } } entries.Remove(nextEntry); entry = nextEntry; return(group); }
private void distribute(IList <IBoundable <IExtents> > entries, IBoundable <IExtents>[] group1, IBoundable <IExtents>[] group2, IndexBalanceHeuristic heuristic, ref Int32 group1Count, ref Int32 group2Count) { // recursion halting case #1 if (entries.Count == 0) { return; } // recursion halting case #2 if (group1Count == heuristic.TargetNodeCount || group2Count == heuristic.TargetNodeCount) { return; } IBoundable <IExtents> entry; ComputationExtents group1Bounds = computeBounds(group1, group1Count); ComputationExtents group2Bounds = computeBounds(group2, group2Count); GroupBoundsLeastEnlarged group = pickNext(entries, group1Bounds, group2Bounds, out entry); switch (group) { case GroupBoundsLeastEnlarged.Group1: group1[group1Count++] = entry; break; case GroupBoundsLeastEnlarged.Group2: group2[group2Count++] = entry; break; case GroupBoundsLeastEnlarged.Tie: Double group1BoundsArea = group1Bounds.Area; Double group2BoundsArea = group2Bounds.Area; if (group1BoundsArea < group2BoundsArea) { group1[group1Count++] = entry; } else if (group2BoundsArea < group1BoundsArea) { group2[group2Count++] = entry; } else if (group1Count < group2Count) { group1[group1Count++] = entry; } else if (group2Count < group1Count) { group2[group2Count++] = entry; } else if (_random.Next(0, 2) == 0) // generates 0 or 1 randomly { group1[group1Count++] = entry; } else { group2[group2Count++] = entry; } break; default: throw new InvalidOperationException("Unknown group."); } distribute(entries, group1, group2, heuristic, ref group1Count, ref group2Count); }