Represents a D-connector motif.
See the Motifs enumeration for the definition of a D-connector motif. Note that a D-connector motif includes only its . The AnchorVertices are provided by this class, but they are not actually a part of the motif.

This class is optimized for use by the algorithm that finds D-connector motifs. Because of that, it's possible to create an instance of this class that isn't actually a valid D-connector motif. Specifically, it's up to the caller to populate the SpanVertices collection, which starts out empty, with at least two span vertices.

Inheritance: Motif
示例#1
0
        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);
        }
示例#2
0
        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;
            }
        }
示例#3
0
        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);
    }