Architecture

In this part, the generic architecture of tree value will be introduced. You can try to understand its core ideas by reading this page.

Like that in numpy and pytorch, tree value’s data layer and logic layer are separated with each other. The data layer is called Tree and the logic layer is called TreeValue. One or more tree values may be pointed to one tree, they share the same memory. In order to support the tree-to-tree operations (tree-to-value or value-to-value are special cases of tree-to-tree) ,func_treelize are provided to transform a common value-based function to a tree-based function.

The core architecture is like this:

../../_images/architecture.puml.svg

Tree

Tree class is the data layer of the TreeValue. The relation with Tree and TreeValue is similar to that of torch.Tensor and torch.Buffer. Actually, there can be multiple TreeValue nodes pointed at the same Tree node, they will share the same memory and when one the them are modified, the other TreeValue pointed at the same position will be effected all at a time.

Here is a example with the usage of the same memories.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
from treevalue import TreeValue

if __name__ == '__main__':
    t1 = TreeValue({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}})
    t2 = TreeValue(t1)  # use the same memory with t1

    print("Initial t1:")
    print(t1)
    print("Initial t2:")
    print(t2)
    print()

    t1.a, t1.x.c = 7, 5  # only t1 is updated in code
    print("Updated t1:")
    print(t1)
    print("Updated t2:")
    print(t2)
    print()

The output is like the following, you can see the memory address of t1 and t2 are the same, when t1 is updated, t2 will be changed together.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Initial t1:
<TreeValue 0x7f488f4b6b20>
├── 'a' --> 1
├── 'b' --> 2
└── 'x' --> <TreeValue 0x7f488f513ee0>
    ├── 'c' --> 3
    └── 'd' --> 4

Initial t2:
<TreeValue 0x7f488f4b6b20>
├── 'a' --> 1
├── 'b' --> 2
└── 'x' --> <TreeValue 0x7f488f513ee0>
    ├── 'c' --> 3
    └── 'd' --> 4


Updated t1:
<TreeValue 0x7f488f4b6b20>
├── 'a' --> 7
├── 'b' --> 2
└── 'x' --> <TreeValue 0x7f488f513ee0>
    ├── 'c' --> 5
    └── 'd' --> 4

Updated t2:
<TreeValue 0x7f488f4b6b20>
├── 'a' --> 7
├── 'b' --> 2
└── 'x' --> <TreeValue 0x7f488f513ee0>
    ├── 'c' --> 5
    └── 'd' --> 4

For contributor, you can get the tree instance inside of a TreeValue instance, by using _detach() method, like the following code.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from treevalue import TreeValue

if __name__ == '__main__':
    t1 = TreeValue({'a': 1, 'b': 2, 'x': {'c': 3, 'd': 4}})
    storage = t1._detach()  # tree is the data tree
    data = storage.detach()

    print('t1:')
    print(t1)

    print('tree storage:')
    print(storage)

    print('data:')
    print(data)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
t1:
<TreeValue 0x7fc2e3eb6b20>
├── 'a' --> 1
├── 'b' --> 2
└── 'x' --> <TreeValue 0x7fc2e3f13ee0>
    ├── 'c' --> 3
    └── 'd' --> 4

tree storage:
<TreeStorage at 0x7fc2e3eb6b20, keys: ('a', 'b', 'x')>
data:
{'a': 1, 'b': 2, 'x': <TreeStorage at 0x7fc2e3f13ee0, keys: ('c', 'd')>}

For further information, take a look at API documentation of BaseTree.

TreeValue

The TreeValue is the logic layer, all the operations and calculations are performed on this layer.

There are 2 primitive TreeValue classes in this project, which are called TreeValue and FastTreeValue. In class TreeValue, only the least necessary features are implemented, while the common and frequently-used features are all implement in the FastTreeValue, which inherits from TreeValue.

When coding, if you need to define a kind of tree which has the common convenient features, just implement class FastTreeValue or use function general_tree_value is okay. But if you need to define your own operations from an empty template, just inherit the raw TreeValue class.

For further information of TreeValue, take a look at:

func_treelize

Function func_treelize is the core feature of this project, almost all the convenient calculations and operations are based on this function.

For further information of func_treelize, take a look at the following pages and their source code implements: