/// <summary> /// Finds all pairs of blocks with non-empty intersection and merges them. Iterated until no overlapping pairs remain. /// </summary> /// <param name="semipartition">The semipartition to be processed.</param> /// <returns>The resulting partition.</returns> public static Partition <T> MergeOverlappingBlocks(Semipartition <T> semipartition) { HashSet <HashSet <T> > blocks = new HashSet <HashSet <T> >(); foreach (HashSet <T> block in semipartition.blocks) { HashSet <T> newBlock = new HashSet <T>(); foreach (T element in block) { newBlock.Add(element); } blocks.Add(newBlock); } int N = semipartition.blocks.Count; int newIndexStart = N; List <T> inoverlaps = new List <T>(); for (int i = 0; i < N; i++) { for (int j = i + 1; j < N; j++) { if (blocks.ElementAt(i).Overlaps(blocks.ElementAt(j))) { HashSet <T> newBlock = new HashSet <T>(); newBlock.UnionWith(blocks.ElementAt(i)); newBlock.UnionWith(blocks.ElementAt(j)); foreach (T element in newBlock) { if (!inoverlaps.Contains(element)) { inoverlaps.Add(element); } } // remove the higher-number block first blocks.Remove(blocks.ElementAt(j)); blocks.Remove(blocks.ElementAt(i)); blocks.Add(newBlock); // i stays the same (but is decremented here to do so), N is decremented by 1 N--; i--; break; } } } Partition <T> partition = new Partition <T>(); foreach (HashSet <T> block in blocks) { partition.AddBlock(block); } return(partition); }
/// <summary> /// Places the union of all the blocks in the argument into a single block. Removes all the initial blocks, /// retaining only the merged block. /// </summary> /// <param name="semipartition">The semipartition to be processed.</param> public static void MergeAllBlocks(Semipartition <T> semipartition) { semipartition.assignments = new Dictionary <T, List <HashSet <T> > >(); semipartition.blocks = new HashSet <HashSet <T> >(); HashSet <T> block = new HashSet <T>(); foreach (T element in semipartition.elements) { block.Add(element); semipartition.assignments.Add(element, new List <HashSet <T> >() { block }); } semipartition.blocks.Add(block); }
/// <summary> /// Finds the nonoverlapping blocks and places them into a partition /// places the remaining overlapping blocks into a semipartition /// </summary> /// <param name="semipartition">The semipartition to be processed.</param> /// <returns>A tuple containing a semipartition and a partition. The two have no elements in common, and /// every element in the original semipartition is in one or the other item of the tuple.</returns> public static Tuple <Semipartition <T>, Partition <T> > Decompose(Semipartition <T> semipartition) { Semipartition <T> newSemipartition = new Semipartition <T>(); Partition <T> partition = new Partition <T>(); List <HashSet <T> > overlaps = new List <HashSet <T> >(); foreach (HashSet <T> block1 in semipartition.blocks) { foreach (HashSet <T> block2 in semipartition.blocks) { if (block1 == block2) { break; } if (block2.Overlaps(block1)) { if (!overlaps.Contains(block1)) { overlaps.Add(block1); } if (!overlaps.Contains(block2)) { overlaps.Add(block2); } } } } foreach (HashSet <T> block in semipartition.blocks) { if (overlaps.Contains(block)) { newSemipartition.AddBlock(block); } else { partition.AddBlock(block); } } return(new Tuple <Semipartition <T>, Partition <T> >(newSemipartition, partition)); }
/// <summary> /// Checks to see if any pair of blocks has non-null intersection. /// </summary> /// <param name="semipartition">The semipartition to be examined.</param> /// <returns>True if any pair of blocks has non-null intersection. False otherwise.</returns> public static bool ContainsOverlappingBlocks(Semipartition <T> semipartition) { foreach (HashSet <T> block1 in semipartition) { foreach (HashSet <T> block2 in semipartition) { if (block1 == block2) { break; } if (block1.Overlaps(block2)) { return(true); } } } return(false); }
/// <summary> /// Removes from the partition any blocks completely contained within another block. /// </summary> /// <param name="semipartition">The semipartition to process.</param> public static void PurgeSubblocks(Semipartition <T> semipartition) { List <HashSet <T> > toRemove = new List <HashSet <T> >(); foreach (HashSet <T> block1 in semipartition.blocks) { foreach (HashSet <T> block2 in semipartition.blocks) { if (block1 == block2) { continue; } if (block1.IsSubsetOf(block2)) { if (!toRemove.Contains(block1) && !toRemove.Contains(block2)) { toRemove.Add(block1); } break; } } } foreach (HashSet <T> block in toRemove) { foreach (T element in block) { if (semipartition.assignments[element].Contains(block)) { semipartition.assignments[element].Remove(block); } } semipartition.blocks.Remove(block); } }