18 Build the adaptive 2D tree described by the tree3_stage*_fine_first_bfs.dot
21 The tree starts with a **single root node on Level 0** and then embeds the
22 1D ternary structure in the first row of deeper 2D levels (all cells outside
26 Level 0 (3x3): (0,0)=Root (single node)
27 Level 1 (9x9): (0,0)=L1A (0,1)=L1B (0,2)=L1C
28 Level 2 (27x27): (0,0)=L2A1 (0,1)=L2A2 (0,2)=L2A3 [childless leaf]
29 (0,3)=L2B1 (0,4)=L2B2 (0,5)=L2B3 [childless leaf]
30 (0,6)=L2C1 (0,7)=L2C2 (0,8)=L2C3
31 Level 3 (81x81): (0,0-2)=L3A1* (0,3-5)=L3A2*
32 (0,6-8)=weight=0 [L2A3 has no children]
33 (0,9-11)=L3B1* (0,12-14)=L3B2*
34 (0,15-17)=weight=0 [L2B3 has no children]
35 (0,18-20)=L3C1* (0,21-23)=L3C2* (0,24-26)=L3C3*
37 Total leaves initially (all in subtree 0):
38 21 finest-level leaves + 2 childless level-1 leaves = 23
40 The tree uses 4 total subtrees in the tests below.
42 tree = Tree(
"tree3-adaptive", 2, (0.0, 0.0), (1.0, 1.0))
46 for level
in range(4):
47 size = 3 ** (level + 1)
48 arr = np.empty((size, size), dtype=object)
52 tree._tree_arrays.append(arr)
55 tree._tree_arrays[0][0][0] = (1, 0)
58 tree._tree_arrays[1][0][0] = (1, 0)
59 tree._tree_arrays[1][0][1] = (1, 0)
60 tree._tree_arrays[1][0][2] = (1, 0)
65 tree._tree_arrays[2][0][col] = (1, 0)
70 active_level2_cols = list(range(0, 6)) + list(range(9, 15)) + list(range(18, 27))
71 for col
in active_level2_cols:
72 tree._tree_arrays[3][0][col] = (1, 0)
74 tree._subtree_count = 1
75 tree.update_split_pattern()
82 Build a 2D variant where each depicted node in the tree3 diagram is
83 represented by all rows with respect to its parent (3 cells in 2D), while
84 Level 0 still starts from a single root node.
86 Representation rule in 2D:
87 - For each conceptual parent-child edge, one conceptual child node is
88 represented as a vertical stripe of 3 cells in the parent's 3x3 child
90 - Conceptual child indices 0,1,2 map to local child columns 0,1,2.
92 This means all represented non-leaf parents have all 9 children present,
93 which allows Stage III to optimise mixed parents at Level 1.
95 tree = Tree(
"tree3-all-rows", 2, (0.0, 0.0), (1.0, 1.0))
99 for level
in range(4):
100 size = 3 ** (level + 1)
101 arr = np.empty((size, size), dtype=object)
102 for a
in range(size):
103 for b
in range(size):
105 tree._tree_arrays.append(arr)
107 def _fill_child_stripes(parent_level: int, parent_coords: tuple[int, int], child_cols: tuple[int, ...]):
108 """Fill 3-row stripes for selected conceptual child columns."""
109 child_level = parent_level + 1
110 parent_a, parent_b = parent_coords
111 base_a = 3 * parent_a
112 base_b = 3 * parent_b
113 for local_col
in child_cols:
114 for local_row
in range(3):
115 a = base_a + local_row
116 b = base_b + local_col
117 tree._tree_arrays[child_level][a][b] = (1, 0)
120 tree._tree_arrays[0][0][0] = (1, 0)
123 _fill_child_stripes(parent_level=0, parent_coords=(0, 0), child_cols=(0, 1, 2))
128 if tree._tree_arrays[1][a][b][0] == 1:
129 _fill_child_stripes(parent_level=1, parent_coords=(a, b), child_cols=(0, 1, 2))
138 if tree._tree_arrays[2][a][b][0] != 1:
141 parent_group = b // 3
144 is_childless = parent_group
in (0, 1)
and local_index == 2
146 _fill_child_stripes(parent_level=2, parent_coords=(a, b), child_cols=(0, 1, 2))
148 tree._subtree_count = 1
149 tree.update_split_pattern()
156 Build the 2D sparse tree used by ``visualise_tree_split_example3.png``.
158 The tree has 10 leaves in total and is arranged as a single branch that is
159 refined twice on the left-most child path:
161 - 4 finest-level leaves on the deepest branch
162 - 3 level-2 leaves on the middle branch
163 - 3 level-1 leaves directly under the root
165 This is the example that splits best into subtrees 4-3-3.
167 tree = Tree(
"visualise-tree-split-example3", 2, (0.0, 0.0), (1.0, 1.0))
171 for level
in range(4):
172 size = 3 ** (level + 1)
173 arr = np.empty((size, size), dtype=object)
174 for a
in range(size):
175 for b
in range(size):
177 tree._tree_arrays.append(arr)
179 def _add_branch(level: int, a: int, b: int) ->
None:
180 """Create one refined node and its four corner children."""
181 tree._tree_arrays[level][a][b] = (1, 0)
185 next_level = level + 1
188 child_coords = [(base_a + da, base_b + db)
for da
in (0, 2)
for db
in (0, 2)]
190 for child_a, child_b
in child_coords:
191 tree._tree_arrays[next_level][child_a][child_b] = (1, 0)
194 _add_branch(next_level, child_coords[0][0], child_coords[0][1])
198 tree._subtree_count = 1
199 tree.update_split_pattern()
206 Build a 2D tree where Stage III can promote a mixed parent.
208 The returned parent coordinates identify the level-0 parent whose children
209 are configured with a dominant subtree assignment.
215 parent_coords = (0, 0)
218 tree._tree_arrays[parent_level][parent_coords] = (1, 0)
222 for a
in range(3 * parent_coords[0], 3 * parent_coords[0] + 3)
223 for b
in range(3 * parent_coords[1], 3 * parent_coords[1] + 3)
227 for coords
in children[:5]:
228 tree._tree_arrays[child_level][coords] = (1, 2)
229 for coords
in children[5:8]:
230 tree._tree_arrays[child_level][coords] = (1, 0)
231 tree._tree_arrays[child_level][children[8]] = (1, 1)
233 return tree, parent_coords