예제 #1
0
        /// <summary>
        /// Perform a node contraction (also: node identification) on two nodes.
        /// The resulting node will have targetname as name.
        /// The attributes of the endpoints are merged and copied to the target node,
        /// with head attributes taking precedence over tail attributes.
        ///
        /// Both node1 and node2 will be removed from the graph.
        /// Then all the neighbours of both endpoints are attached to the target,
        /// preserving direction and attributes.
        /// The new edges will be added to the root graph.
        /// If the graph is strict, no multiple edges will be added between nodes.
        /// </summary>
        /// <returns>target</returns>
        public Node Contract(Node node1, Node node2, string targetname)
        {
            Node target = MyRootGraph.GetOrAddNode(targetname);

            node1.CopyAttributesTo(target);
            node2.CopyAttributesTo(target);
            Merge(node1, target);
            Merge(node2, target);
            return(target);
        }
예제 #2
0
        /// <summary>
        /// An edge can define a cluster as logical head.
        /// This is used to fake edges to and from clusters by clipping the edge on the borders of the logical head.
        /// </summary>
        public void SetLogicalHead(SubGraph lhead)
        {
            if (!lhead.IsCluster())
            {
                throw new InvalidOperationException("ltail must be a cluster");
            }
            if (!MyRootGraph.IsCompound())
            {
                throw new InvalidOperationException("rootgraph must be compound for lheads/ltails to be used");
            }
            string lheadname = lhead.GetName();

            SafeSetAttribute("lhead", lheadname, "");
        }
예제 #3
0
        /// <summary>
        /// An edge can define a cluster as logical head.
        /// This is used to fake edges to and from clusters by clipping the edge on the borders of the logical head.
        /// </summary>
        public SubGraph LogicalHead()
        {
            if (!MyRootGraph.IsCompound())
            {
                throw new InvalidOperationException("rootgraph must be compound for lheads/ltails to be used");
            }
            string lheadname = GetAttribute("lhead");

            if (lheadname == null)
            {
                return(null);
            }
            return(MyRootGraph.GetSubgraph(lheadname));
        }
예제 #4
0
        /// <summary>
        /// Merge a node into a target node.
        /// Basically, add the neighborhood of the node to the neighborhood of the target.
        /// The merge node will be removed from the graph.
        /// The new edges will be added to the root graph.
        ///
        /// If the graph is strict, no multiple edges will be added between nodes.
        ///
        /// If add_self_loops is true, edges between the merge node and the target node will be
        /// added as self loops to the target node. Self loops that already exist as such are always added.
        /// </summary>
        public void Merge(Node merge, Node target, bool add_self_loops = false)
        {
            // .Edges() won't iterate twice over self loops
            foreach (var e in merge.Edges())
            {
                if (!e.IsBetween(merge, target) || add_self_loops) // Only add self loops if we want that
                {
                    Node newtail    = e.Tail().Equals(merge) ? target : e.Tail();
                    Node newhead    = e.Head().Equals(merge) ? target : e.Head();
                    Edge newedge    = MyRootGraph.GetOrAddEdge(newtail, newhead, e.GetName());
                    int  returncode = e.CopyAttributesTo(newedge);
                    // For some reason this may fail, even when the copying seems to have succeeded.
                    Debug.Assert(returncode == 0);
                }
            }

            // The following will delete all edges connected to merge.
            MyRootGraph.Delete(merge);
        }