Python 我有一个递归函数来验证树图,需要一个返回条件

Python 我有一个递归函数来验证树图,需要一个返回条件,python,recursion,networkx,Python,Recursion,Networkx,我有一个树形图。每个节点都有属性“amount”。控制root属性值的规则如下: 根“amount”值是其每个子级的“amount”属性的总和 这将继续到最后一个具有子节点的节点。换句话说,此树的属性不同于求和树,因为根节点不是树中每个节点的总和 下面是一个玩具示例,如图G所示: nodedict = {'apples': {'amount': 5.0}, 'bananas': {'amount': 10.0}, 'tomato': {'amount': 50.0}, 'total_fru

我有一个树形图。每个节点都有属性“amount”。控制root属性值的规则如下:

根“amount”值是其每个子级的“amount”属性的总和

这将继续到最后一个具有子节点的节点。换句话说,此树的属性不同于求和树,因为根节点不是树中每个节点的总和

下面是一个玩具示例,如图G所示:

nodedict = {'apples': {'amount': 5.0},
 'bananas': {'amount': 10.0},
 'tomato': {'amount': 50.0},
 'total_fruits': {'amount': 15.0},
 'total_vegetables': {'amount': 9.0},
 'carrot': {'amount': 3.0},
 'squash': {'amount': 6.0},
 'total_fruits_and_vegetables': {'amount': 74.0}}

edgelist = [('total_fruits', 'apples'),
 ('total_fruits', 'bananas'),
 ('total_fruits_and_vegetables', 'tomato'),
 ('total_fruits_and_vegetables', 'total_fruits'),
 ('total_fruits_and_vegetables', 'total_vegetables'),
 ('total_vegetables', 'carrot'),
 ('total_vegetables', 'squash')]

G = nx.DiGraph(edgelist)
nx.set_node_attributes(G, nodedict)
我编写了一个递归函数来验证树的求和规则。输出表明函数已到达树中的所有节点;但是,我想不出如何使用最终返回语句退出函数

def isLeaf(G, node):
    return G.out_degree(node)==0 and G.in_degree(node)==1


def testParentSumChildren(M, node):
    children = list(G.successors(node))
    vals = []
    for child in children:
        vals.append(G.nodes[child]['amount'])

    sumchildrenval = round(sum(vals), 2)
    parentval = round(G.nodes[node]['amount'], 2)

    # Valid difference between -1 and 1
    if -1.0 <= round(parentval - sumchildrenval, 2) <= 1.0:
        return True
    else:
        print("Not Valid Sum.")


def _validateTree(G, node):
    children = list(G.successors(node))
    if children:
        vals = []
        for child in children:
            if isLeaf(G, child):
                # Prevents recursion on child without children
                print("is leaf %s" % (child, ))
            else:
                # Test parent nodes
                if testParentSumChildren(G, child):
                    print("Valid Sum.")
                    _validateTree(G, child)
                else: 
                    print("Not Valid Sum.")

def validateTree(G, root):
    if _validateTree(G, root):
        return True
    else:
        print("Not Valid Tree.")


validateTree(G, root='total_fruits_and_vegetables')

如果在有效树上运行该函数,
validateTree()
应返回True

要报告最终结果,您可以组合子树和当前节点的验证结果,因此递归过程如下所示: 如何收集和记录结果取决于具体情况,有以下几种选择:

  • 递归地构造结果
  • 使用全局变量进行记录
  • 结果引发异常
  • 示例1

    作为递归构造结果的示例,函数返回一个布尔值,并通过逻辑And组合子级的结果:

    def validate(G, node):
        if isLeaf(G, node): # This is the base case  
            return True
        else:
            # step 1
            validate_results_of_children = [validate(G, child) for child in G.successors(node)]
    
            # step 2
            is_current_node_valid = check_current_node_sum(G, node)
    
            # step 3
            final_result = all(validate_results_of_children) and is_current_node_valid 
    
            return final_result
    
    示例2

    使用全局dict记录无效结果,并添加有关树级别的一些额外信息:

    def validate(G, node, record_dict, tree_level):
        if isLeaf(G, node):  # This is the base case
            pass
        else:
            # step 1
            for child in G.successors(node):
                validate(G, child, record_dict, tree_level + 1)
    
            # step 2
            is_current_node_valid = check_current_node_sum(G, node)
    
            # step 3
            record_dict.setdefault(tree_level, {})
            record_dict[tree_level][node] = is_current_node_valid
    
    record_dict = {}
    validate(G, root, record_dict, tree_level=0)
    
    示例3

    定义自定义异常类并在树无效时引发它: 类TreeNotValidException(异常): 通过

    def validate(G, node):
        if isLeaf(G, node):  # This is the base case
            pass
        else:
            # step 1
            for child in G.successors(node):
                validate(G, child, tree_level + 1)
    
            # step 2
            is_current_node_valid = check_current_node_sum(G, node)
    
            # step 3
            if not is_current_node_valid:
                raise TreeNotValidException("Invalid sum for node : " + node)
    

    杰出的图表是来自出版物还是其他出版物?你已经把这件事讲清楚了好几遍——1。无效结果的记录也是算法的证明,我在尝试时发现了一个挑战。2.
    isLeaf()
    条件具有我所知道的所有递归算法的形式,但在我发布的版本中没有预见到;最后3。我显式地编写了
    for()
    循环,因为我认为这样更容易阅读。列表理解表达式的可读性比我编码时想象的要好得多。这是图形递归的一个很好的基础示例。感谢您提供的图表!:)递归是一个很难理解的问题,也是Python中一个令人担忧的主题。让我补充一下,第二个版本的一个有趣的惯用特性是结果记录在一个dict中,该dict存在于递归调用之外。这消除了我幼稚的键混搭带来的另一个复杂问题——返回值太多。
    def validate(G, node):
        if isLeaf(G, node):  # This is the base case
            pass
        else:
            # step 1
            for child in G.successors(node):
                validate(G, child, tree_level + 1)
    
            # step 2
            is_current_node_valid = check_current_node_sum(G, node)
    
            # step 3
            if not is_current_node_valid:
                raise TreeNotValidException("Invalid sum for node : " + node)