Suppose we have a tree and each node can have multiple children while the children can have more children etc.
Take this tree as an example:
- Node 1
- Node 1.1
- Node 1.2
- Node 1.2.1
- Node 1.2.1.1
- Node 1.2.1.2
- Node 1.2.2
- Node 1.3
- Node 1.3.1
Node 1 has a depth = 0 (root)
Node 1.1, 1.2, 1.3 has depth = 1 and so on
For each node I want to calculate the maximum depth it can reach. For example, Node 1 max. depth is 3 (the tree goes as deep as node 1.2.1.1). While Node 1.3 max depth = 1 (the subtree reaches as deep as node 1.3.1)
Now what I could do is to create a function, that takes a subtree and counts to the deepest node, and returns the depth value. But this would require calling that function for each and every node which seems very inefficient to me.
I want to create the tree and compute the max depths in one go.
I'm keeping the code very simple as there are a lot of other operations my function contains (such as generating new children as I'm building the tree from scratch, but I left these parts out for simplicity). But basically, I'm going through the tree like this:
def create_behavior_tree(depth, max_depth, behavior_tree)
for child in behavior_tree.children:
if depth > max_depth:
max_depth = depth
if len(child) > 0: # Expanding node
max_depth = create_behavior_tree(depth + 1, max_depth, child)
child.max_depth = max_depth # problem: stores the values in "reverse"
else: # Single node without children
child.max_depth = depth
create_behavior_tree(1, 0, Tree)
However, when I do that, I can not reach the newest max_depth value for the outer node, it can only be reached within the innermost node (since this is recursion). So this would compute: Node 1 max depth = 0, Node 1.2 max depth = 1, Node 1.2.1 max depth = 2 etc. It's actually in reverse.
So, perhaps I need to use global variables here?
EDIT – A more detailed version of my function
def create_behavior_tree(depth, behavior_tree, children, max_tree_depth, node_count):
if depth <= max_tree_depth:
for child in children:
# add behavior node
if type(child) == Behaviour:
behavior_tree.add_children([child])
node_count += 1 # counting total nodes in tree
# add composite node
if type(child) == Composite:
# replace by behavior node (reached max tree depth)
if depth == max_tree_depth:
node = create_behaviour_node()
behavior_tree.add_children([node])
node_count += 1
else:
behavior_tree.add_children([child])
node_count += 1
# further expand behavior tree
children = create_random_children(size=3)
_, node_count = create_behavior_tree(depth + 1, node, children, max_tree_depth, node_count)
return behavior_tree, node_count
random_children = create_random_children(size=3) # Create 3 random children
root = py_trees.composites.Selector("Selector")
create_behavior_tree(1, root, random_children, 5, 0)