AddSpanVertexToPotentialDConnectorMotifs ( IVertex oPotentialSpanVertex, ICollection <IVertex> oDPotentialAnchorVertices, Dictionary <string, DConnectorMotif> oPotentialDConnectorMotifs ) { Debug.Assert(oPotentialSpanVertex != null); Debug.Assert(oDPotentialAnchorVertices != null); Debug.Assert(oDPotentialAnchorVertices.Count >= 2); Debug.Assert(oPotentialDConnectorMotifs != null); // Is there already a DConnectorMotif object for this set of // potential anchor vertices? IOrderedEnumerable <IVertex> oOrderedDPotentialAnchorVertices = oDPotentialAnchorVertices.OrderBy(v => v.ID); string stringKey = string.Join(",", oOrderedDPotentialAnchorVertices.Select(v => v.ID.ToString()).ToArray()); DConnectorMotif oPotentialDConnectorMotif; if (!oPotentialDConnectorMotifs.TryGetValue( stringKey, out oPotentialDConnectorMotif)) { // No. Create one. oPotentialDConnectorMotif = new DConnectorMotif(new List <IVertex>(oDPotentialAnchorVertices)); oPotentialDConnectorMotifs.Add(stringKey, oPotentialDConnectorMotif); } oPotentialDConnectorMotif.SpanVertices.Add(oPotentialSpanVertex); }
AddDConnectorMotif ( HashSet <Motif> currentDConnectorMotifs, Dictionary <IVertex, DConnectorMotif> verticesAlreadyInDConnectorMotifs, DConnectorMotif connectorMotifToAdd) { // Assert that there are no shared anchor and span vertices Debug.Assert(connectorMotifToAdd.SpanVertices.Intersect <IVertex>(connectorMotifToAdd.AnchorVertices).Count <IVertex>() == 0); currentDConnectorMotifs.Add(connectorMotifToAdd); foreach (IVertex oVertex in connectorMotifToAdd.SpanVertices) { // We do not allow overlapping span vertices so we use .Add verticesAlreadyInDConnectorMotifs.Add(oVertex, connectorMotifToAdd); } foreach (IVertex oVertex in connectorMotifToAdd.AnchorVertices) { // We allow overlapping anchor vertices so we use = verticesAlreadyInDConnectorMotifs[oVertex] = connectorMotifToAdd; } }
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); }
TestCollapsedAttributes2() { // Without vertex names and with SpanScale set to a non-default value. IVertex oAnchorVertex1 = new Vertex(); IVertex oAnchorVertex2 = new Vertex(); DConnectorMotif oDConnectorMotif = new DConnectorMotif( new List<IVertex>() {oAnchorVertex1, oAnchorVertex2} ); IVertex oSpanVertex1 = new Vertex(); IVertex oSpanVertex2 = new Vertex(); oDConnectorMotif.SpanVertices.Add(oSpanVertex1); oDConnectorMotif.SpanVertices.Add(oSpanVertex2); oDConnectorMotif.SpanScale = 0.5; String sCollapsedAttributes = oDConnectorMotif.CollapsedAttributes; CollapsedGroupAttributes oCollapsedGroupAttributes = CollapsedGroupAttributes.FromString(sCollapsedAttributes); Assert.AreEqual( CollapsedGroupAttributeValues.DConnectorMotifType, oCollapsedGroupAttributes[CollapsedGroupAttributeKeys.Type] ); Assert.AreEqual( "2", oCollapsedGroupAttributes[ CollapsedGroupAttributeKeys.AnchorVertices] ); Assert.IsFalse( oCollapsedGroupAttributes.ContainsKey( CollapsedGroupAttributeKeys.GetAnchorVertexNameKey(0) ) ); Assert.IsFalse( oCollapsedGroupAttributes.ContainsKey( CollapsedGroupAttributeKeys.GetAnchorVertexNameKey(1) ) ); Assert.AreEqual( "2", oCollapsedGroupAttributes[ CollapsedGroupAttributeKeys.SpanVertices] ); Assert.IsTrue( oCollapsedGroupAttributes.ContainsKey( CollapsedGroupAttributeKeys.SpanScale) ); Assert.AreEqual( "0.5", oCollapsedGroupAttributes[CollapsedGroupAttributeKeys.SpanScale] ); }
TestConstructor() { IVertex oAnchorVertex1 = new Vertex(); IVertex oAnchorVertex2 = new Vertex(); IVertex oAnchorVertex3 = new Vertex(); DConnectorMotif o2ConnectorMotif = new DConnectorMotif( new List<IVertex>(){oAnchorVertex1, oAnchorVertex2}); Assert.AreEqual(oAnchorVertex1, o2ConnectorMotif.AnchorVertices[0]); Assert.AreEqual(oAnchorVertex2, o2ConnectorMotif.AnchorVertices[1]); DConnectorMotif o3ConnectorMotif = new DConnectorMotif( new List<IVertex>(){oAnchorVertex1, oAnchorVertex2, oAnchorVertex3}); Assert.AreEqual(oAnchorVertex1, o3ConnectorMotif.AnchorVertices[0]); Assert.AreEqual(oAnchorVertex2, o3ConnectorMotif.AnchorVertices[1]); Assert.AreEqual(oAnchorVertex3, o3ConnectorMotif.AnchorVertices[2]); Assert.AreEqual(0, o2ConnectorMotif.SpanVertices.Count); Assert.AreEqual(0, o3ConnectorMotif.SpanVertices.Count); Assert.AreEqual(1.0, o3ConnectorMotif.SpanScale); }
TestCollapsedAttributes() { // With vertex names. IVertex oAnchorVertex1 = new Vertex(); IVertex oAnchorVertex2 = new Vertex(); oAnchorVertex1.Name = "Name1"; oAnchorVertex2.Name = "Name2"; DConnectorMotif oDConnectorMotif = new DConnectorMotif( new List<IVertex>(){oAnchorVertex1, oAnchorVertex2} ); IVertex oSpanVertex1 = new Vertex(); IVertex oSpanVertex2 = new Vertex(); oDConnectorMotif.SpanVertices.Add(oSpanVertex1); oDConnectorMotif.SpanVertices.Add(oSpanVertex2); String sCollapsedAttributes = oDConnectorMotif.CollapsedAttributes; CollapsedGroupAttributes oCollapsedGroupAttributes = CollapsedGroupAttributes.FromString(sCollapsedAttributes); Assert.AreEqual( CollapsedGroupAttributeValues.DConnectorMotifType, oCollapsedGroupAttributes[CollapsedGroupAttributeKeys.Type] ); Assert.AreEqual( "2", oCollapsedGroupAttributes[ CollapsedGroupAttributeKeys.AnchorVertices] ); Assert.IsTrue( oCollapsedGroupAttributes.ContainsKey( CollapsedGroupAttributeKeys.GetAnchorVertexNameKey(0) ) ); Assert.IsTrue( oCollapsedGroupAttributes.ContainsKey( CollapsedGroupAttributeKeys.GetAnchorVertexNameKey(1))); Assert.AreEqual( "Name1", oCollapsedGroupAttributes[ CollapsedGroupAttributeKeys.GetAnchorVertexNameKey(0)]); Assert.AreEqual( "Name2", oCollapsedGroupAttributes[ CollapsedGroupAttributeKeys.GetAnchorVertexNameKey(1)]); Assert.AreEqual( "2", oCollapsedGroupAttributes[ CollapsedGroupAttributeKeys.SpanVertices] ); Assert.IsTrue( oCollapsedGroupAttributes.ContainsKey( CollapsedGroupAttributeKeys.SpanScale) ); Assert.AreEqual( "1", oCollapsedGroupAttributes[CollapsedGroupAttributeKeys.SpanScale] ); }
TestAllVertices() { IVertex oAnchorVertex1 = new Vertex(); IVertex oAnchorVertex2 = new Vertex(); DConnectorMotif oDConnectorMotif = new DConnectorMotif( new List<IVertex>() {oAnchorVertex1, oAnchorVertex2} ); IVertex oSpanVertex1 = new Vertex(); IVertex oSpanVertex2 = new Vertex(); oDConnectorMotif.SpanVertices.Add(oSpanVertex1); oDConnectorMotif.SpanVertices.Add(oSpanVertex2); IVertex[] aoVerticesInMotif = oDConnectorMotif.VerticesInMotif; // Note that the anchor vertices aren't actually a part of the motif. Assert.AreEqual(2, aoVerticesInMotif.Length); Assert.AreEqual( oSpanVertex1, aoVerticesInMotif.Single( oVertex => oVertex == oSpanVertex1) ); Assert.AreEqual( oSpanVertex2, aoVerticesInMotif.Single( oVertex => oVertex == oSpanVertex2) ); }
TestSpanVertices() { IVertex oAnchorVertex1 = new Vertex(); IVertex oAnchorVertex2 = new Vertex(); DConnectorMotif oDConnectorMotif = new DConnectorMotif( new List<IVertex>() { oAnchorVertex1, oAnchorVertex2 }); IVertex oSpanVertex1 = new Vertex(); IVertex oSpanVertex2 = new Vertex(); oDConnectorMotif.SpanVertices.Add(oSpanVertex1); oDConnectorMotif.SpanVertices.Add(oSpanVertex2); Assert.AreEqual(2, oDConnectorMotif.SpanVertices.Count); Assert.AreEqual( oSpanVertex1, oDConnectorMotif.SpanVertices[0] ); Assert.AreEqual( oSpanVertex2, oDConnectorMotif.SpanVertices[1] ); }
AddDConnectorMotif ( HashSet<Motif> currentDConnectorMotifs, Dictionary<IVertex, DConnectorMotif> verticesAlreadyInDConnectorMotifs, DConnectorMotif connectorMotifToAdd) { // Assert that there are no shared anchor and span vertices Debug.Assert(connectorMotifToAdd.SpanVertices.Intersect<IVertex>(connectorMotifToAdd.AnchorVertices).Count<IVertex>() == 0); currentDConnectorMotifs.Add(connectorMotifToAdd); foreach (IVertex oVertex in connectorMotifToAdd.SpanVertices) { // We do not allow overlapping span vertices so we use .Add verticesAlreadyInDConnectorMotifs.Add(oVertex, connectorMotifToAdd); } foreach (IVertex oVertex in connectorMotifToAdd.AnchorVertices) { // We allow overlapping anchor vertices so we use = verticesAlreadyInDConnectorMotifs[oVertex] = connectorMotifToAdd; } }
AddSpanVertexToPotentialDConnectorMotifs ( IVertex oPotentialSpanVertex, ICollection<IVertex> oDPotentialAnchorVertices, Dictionary<string, DConnectorMotif> oPotentialDConnectorMotifs ) { Debug.Assert(oPotentialSpanVertex != null); Debug.Assert(oDPotentialAnchorVertices != null); Debug.Assert(oDPotentialAnchorVertices.Count >= 2); Debug.Assert(oPotentialDConnectorMotifs != null); // Is there already a DConnectorMotif object for this set of // potential anchor vertices? IOrderedEnumerable<IVertex> oOrderedDPotentialAnchorVertices = oDPotentialAnchorVertices.OrderBy(v => v.ID); string stringKey = string.Join(",", oOrderedDPotentialAnchorVertices.Select(v => v.ID.ToString()).ToArray()); DConnectorMotif oPotentialDConnectorMotif; if (!oPotentialDConnectorMotifs.TryGetValue( stringKey, out oPotentialDConnectorMotif)) { // No. Create one. oPotentialDConnectorMotif = new DConnectorMotif(new List<IVertex>(oDPotentialAnchorVertices)); oPotentialDConnectorMotifs.Add(stringKey, oPotentialDConnectorMotif); } oPotentialDConnectorMotif.SpanVertices.Add(oPotentialSpanVertex); }