protected ICollection<Motif> FilterDConnectorMotifs
(Dictionary<string, DConnectorMotif> oPotentialDConnectorMotifs)
{
Debug.Assert(oPotentialDConnectorMotifs != null);
HashSet<Motif> currentDConnectorMotifs = new HashSet<Motif>();
Dictionary<IVertex, DConnectorMotif> verticesAlreadyInDConnectorMotifs =
new Dictionary<IVertex, DConnectorMotif>();
// Select only those potential D-connector motifs that have at least
// two span vertices.
foreach (DConnectorMotif potentialMotif in
oPotentialDConnectorMotifs.Values.Where(
oPotentialDConnectorMotif =>
oPotentialDConnectorMotif.SpanVertices.Count >= 2)
)
{
// If any of the motif's span vertices are included in another
// D-connector motif we need to pick the motif to keep
//
// If this weren't done, for example, the following ring of vertices
// would result in two redundant two-connector motifs:
//
// A-B-C-D-A
List<DConnectorMotif> overlappingMotifs =
(from spanVertex in potentialMotif.SpanVertices
where verticesAlreadyInDConnectorMotifs.ContainsKey(spanVertex)
select verticesAlreadyInDConnectorMotifs[spanVertex])
.Distinct<DConnectorMotif>().ToList<DConnectorMotif>();
if (overlappingMotifs.Count > 0)
{
// Our bookkeeping should prevent more than one overlap
Debug.Assert(overlappingMotifs.Count == 1);
DConnectorMotif existingMotif = overlappingMotifs[0];
int potAnchors = potentialMotif.AnchorVertices.Count,
potSpanners = potentialMotif.SpanVertices.Count,
potTotal = potAnchors + potSpanners;
int existAnchors = existingMotif.AnchorVertices.Count,
existSpanners = existingMotif.SpanVertices.Count,
existTotal = existAnchors + existSpanners;
// Potential motif is larger in total size, so we favor it
// -- OR --
// Potential motif is equal in total size and has more spanners, which we favor over more anchors
if (potSpanners > existSpanners ||
(
potSpanners == existSpanners &&
potTotal > existTotal))
{
// Remove the existing motif from the list of motifs and the dictionary entries for its vertices
currentDConnectorMotifs.Remove(existingMotif);
foreach (IVertex existingSpanVertex in existingMotif.SpanVertices)
{
verticesAlreadyInDConnectorMotifs.Remove(existingSpanVertex);
}
foreach (IVertex existingAnchorVertex in existingMotif.AnchorVertices)
{
verticesAlreadyInDConnectorMotifs.Remove(existingAnchorVertex);
}
// Add the potential DConnectorMotif and record its vertices
AddDConnectorMotif(currentDConnectorMotifs, verticesAlreadyInDConnectorMotifs, potentialMotif);
}
else
{
// Potential motif is smaller than the existing one or is the same size with fewer spanners -- do nothing
}
}
// If all of the motifs span vertices are not included in others, add the DConnectorMotif and record its vertices
else
{
AddDConnectorMotif(currentDConnectorMotifs, verticesAlreadyInDConnectorMotifs, potentialMotif);
}
}
return currentDConnectorMotifs;
}