Tree networkx 1.8中是否有一个类封装节点添加/删除操作中的树断言

Tree networkx 1.8中是否有一个类封装节点添加/删除操作中的树断言,tree,encapsulation,networkx,directed-graph,Tree,Encapsulation,Networkx,Directed Graph,我现在搜索了一个小时,在一份写得很好的文档(论文引用,而不是一点未记录)中找到了这个琐碎问题的答案(对那些知道的人来说很琐碎)。让我向您展示我目前的发现: networkx.generators.directed包,其中gn\u图始终是一个(定向)树,但不一定封装断言 networkx.balanced_tree显然生成一棵树,但不是任意树,而是一棵平衡树 graph.graph.Tree()看起来很完美,但它来自版本0.37,而不是1.8 无数的生成器和迭代器提供了良好的生成器和iterao

我现在搜索了一个小时,在一份写得很好的文档(论文引用,而不是一点未记录)中找到了这个琐碎问题的答案(对那些知道的人来说很琐碎)。让我向您展示我目前的发现:

  • networkx.generators.directed
    包,其中
    gn\u图
    始终是一个(定向)树,但不一定封装断言
  • networkx.balanced_tree
    显然生成一棵树,但不是任意树,而是一棵平衡树
  • graph.graph.Tree
    ()看起来很完美,但它来自版本0.37,而不是1.8
  • 无数的生成器和迭代器提供了良好的生成器和iteraor,但它们都没有在操作中封装树断言的文档
对于操作中的封装,我指的是在添加或删除边时检查树断言(有向无环图),例如

tree = networkx.tree.Tree()
tree.add_edge(a,b) # ok
tree.add_edge(b,c) # ok
tree.add_edge(b,a) # should raise TreeException("This is a tree, i****")

下面是“Tree”类的一个修改版本(来自networkx-0.37,现已弃用),可用于networkx的现代版本。使用networkx-1.9进行了轻微测试,但不能保证任何一项工作正常;预计会有bug。下载版本


下面是“Tree”类的一个修改版本(来自networkx-0.37,现已弃用),可用于networkx的现代版本。使用networkx-1.9进行了轻微测试,但不能保证任何一项工作正常;预计会有bug。下载版本


下面是“Tree”类的一个修改版本(来自networkx-0.37,现已弃用),可用于networkx的现代版本。使用networkx-1.9进行了轻微测试,但不能保证任何一项工作正常;预计会有bug。下载版本


下面是“Tree”类的一个修改版本(来自networkx-0.37,现已弃用),可用于networkx的现代版本。使用networkx-1.9进行了轻微测试,但不能保证任何一项工作正常;预计会有bug。下载版本


谢谢!我假设您在确保这不是nexworkx 1.9或1.8的一部分之前没有花时间创建它,并且您的(正确)答案暗示了这一点。是吗?我是这篇文章的原始作者之一,我在0.37版之后从networkx中删除了它。据我所知,没有计划重新介绍这门课。非常感谢!我假设您在确保这不是nexworkx 1.9或1.8的一部分之前没有花时间创建它,并且您的(正确)答案暗示了这一点。是吗?我是这篇文章的原始作者之一,我在0.37版之后从networkx中删除了它。据我所知,没有计划重新介绍这门课。非常感谢!我假设您在确保这不是nexworkx 1.9或1.8的一部分之前没有花时间创建它,并且您的(正确)答案暗示了这一点。是吗?我是这篇文章的原始作者之一,我在0.37版之后从networkx中删除了它。据我所知,没有计划重新介绍这门课。非常感谢!我假设您在确保这不是nexworkx 1.9或1.8的一部分之前没有花时间创建它,并且您的(正确)答案暗示了这一点。是吗?我是这篇文章的原始作者之一,我在0.37版之后从networkx中删除了它。据我所知,没有计划重新介绍这门课。
from networkx import Graph
from networkx.exception import NetworkXException, NetworkXError
import networkx.convert as convert

class Tree(Graph):
    """ A free (unrooted) tree."""
    def __init__(self, data=None, **attr):
        Graph.__init__(self, **attr)
        if data is not None:
            convert.to_networkx_graph(data, create_using=self)
            # check if it is a tree.
            if not (G.order() == G.size() + 1 and
                    nx.number_connected_components(G) == 1):
                raise NetworkXError("Data %s is not a tree" % data)
        # load graph attributes (must be after convert)
        self.graph.update(attr)
        self.edge = self.adj

    def add_node(self, n):
        if n in self:
            return  # already in tree
        elif len(self.adj) == 0:
            Graph.add_node(self, n)  # first node
        else:  # not allowed
            raise NetworkXError(
                "adding single node %s not allowed in non-empty tree" % (n))

    def add_nodes_from(self, nbunch):
        for n in nbunch:
            self.add_node(n)

    def remove_node(self, n):
        try:
            if len(self.adj[n]) == 1:  # allowed for leaf node
                Graph.remove_node(self, n)
            else:
                raise NetworkXError(
                    "deleting interior node %s not allowed in tree" % (n))
        except KeyError:  # NetworkXError if n not in self
            raise NetworkXError("node %s not in graph" % n)

    def remove_nodes_from(self, nbunch):
        for n in nbunch:
            self.remove_node(n)

    def add_edge(self, u, v=None):
        if v is None:
            (u, v) = u  # no v given, assume u is an edge tuple
        if self.has_edge(u, v):
            return  # no parallel edges allowed
        elif u in self and v in self:
            raise NetworkXError(
                "adding edge %s-%s not allowed in tree" % (u, v))
        elif u in self or v in self:
            Graph.add_edge(self, u, v)
            return
        elif len(self.adj) == 0:  # first leaf
            Graph.add_edge(self, u, v)
            return
        else:
            raise NetworkXError(
                "adding edge %s-%s not allowed in tree" % (u, v))

    def add_edges_from(self, ebunch):
        for e in ebunch:
            self.add_edge(e)

    def remove_edge(self, u, v=None):
        if v is None:
            (u, v) = u
        if self.degree(u) == 1 or self.degree(v) == 1:  # leaf edge
            Graph.remove_edge(self, u, v)
        else:  # interior edge
            raise NetworkXError(
                "deleting interior edge %s-%s not allowed in tree" % (u, v))
        if self.degree(u) == 0:  # OK to remove remaining isolated node
            Graph.remove_node(self, u)
        if self.degree(v) == 0:  # OK to remove remaining isolated node
            Graph.remove_node(self, v)

    def remove_edges_from(self, ebunch):
        for e in ebunch:
            self.remove_edge(e)

    # leaf notation
    def add_leaf(self, u, v=None):
        self.add_edge(u, v)

    def remove_leaf(self, u, v=None):
        self.remove_edge(u, v)

    def add_leaves_from(self, ebunch):
        for e in ebunch:
            self.add_leaf(e)

    def remove_leaves_from(self, ebunch):
        for e in ebunch:
            self.remove_leaf(e)