22 dimensions, parent_coords
25 Stage III invariant in 2D and 3D:
26 If a parent has a full set of mixed children and a dominant subtree that
27 differs from the parent subtree and improves split pressure, parent is promoted.
30 name=f
"pytest-tree-stage-iii-promote-{dimensions}d", max_level=2, dimensions=dimensions
37 assert tree._tree_arrays[parent_level][parent_coords] == (1, 0)
40 total_children = len(children)
41 dominant_count = total_children // 2 + 1
42 parent_count = total_children - dominant_count - 1
48 for coords
in children[:dominant_count]:
49 tree._tree_arrays[child_level][coords] = (1, 2)
50 for coords
in children[dominant_count:dominant_count + parent_count]:
51 tree._tree_arrays[child_level][coords] = (1, 0)
52 tree._tree_arrays[child_level][children[-1]] = (1, 1)
55 split_strategy._optimize_hierarchy(tree)
58 assert tree._tree_arrays[parent_level][parent_coords] == (1, 2)
61@pytest.mark.parametrize(
62 "dimensions,parent_coords",
69 dimensions, parent_coords
72 Stage III safety invariant in 2D and 3D:
73 Parent ownership is never moved backward to a smaller subtree id.
76 name=f
"pytest-tree-stage-iii-backward-{dimensions}d", max_level=2, dimensions=dimensions
83 tree._tree_arrays[parent_level][parent_coords] = (1, 2)
86 total_children = len(children)
87 dominant_count = total_children // 2 + 1
88 parent_count = total_children - dominant_count - 1
91 for coords
in children[:dominant_count]:
92 tree._tree_arrays[child_level][coords] = (1, 0)
93 for coords
in children[dominant_count:dominant_count + parent_count]:
94 tree._tree_arrays[child_level][coords] = (1, 2)
95 tree._tree_arrays[child_level][children[-1]] = (1, 1)
98 split_strategy._optimize_hierarchy(tree)
101 assert tree._tree_arrays[parent_level][parent_coords] == (1, 2)
104@pytest.mark.parametrize(
105 "dimensions,parent_coords",
112 dimensions, parent_coords
115 Stage III safety invariant in 2D and 3D:
116 No promotion occurs unless all 3^d children of a parent exist.
119 name=f
"pytest-tree-stage-iii-incomplete-{dimensions}d", max_level=2, dimensions=dimensions
125 assert tree._tree_arrays[parent_level][parent_coords] == (1, 0)
128 total_children = len(children)
129 dominant_count = total_children // 2 + 1
130 parent_count = total_children - dominant_count - 1
133 for coords
in children[:dominant_count]:
134 tree._tree_arrays[child_level][coords] = (1, 2)
135 for coords
in children[dominant_count:dominant_count + parent_count]:
136 tree._tree_arrays[child_level][coords] = (1, 0)
137 tree._tree_arrays[child_level][children[-1]] = (1, 1)
140 tree._tree_arrays[child_level][children[0]] = (0, 0)
143 split_strategy._optimize_hierarchy(tree)
146 assert tree._tree_arrays[parent_level][parent_coords] == (1, 0)
149@pytest.mark.parametrize(
150 "dimensions,parent_coords",
157 dimensions, parent_coords
160 Stage III relaxed mode in 2D and 3D:
161 If full-child-set gating is disabled, mixed partial child sets can still
162 promote a parent to the dominant subtree.
165 name=f
"pytest-tree-stage-iii-incomplete-allowed-{dimensions}d", max_level=2, dimensions=dimensions
171 assert tree._tree_arrays[parent_level][parent_coords] == (1, 0)
174 total_children = len(children)
175 dominant_count = total_children // 2 + 1
176 parent_count = total_children - dominant_count - 1
179 for coords
in children[:dominant_count]:
180 tree._tree_arrays[child_level][coords] = (1, 2)
181 for coords
in children[dominant_count:dominant_count + parent_count]:
182 tree._tree_arrays[child_level][coords] = (1, 0)
183 tree._tree_arrays[child_level][children[-1]] = (1, 1)
186 tree._tree_arrays[child_level][children[0]] = (0, 0)
189 split_strategy._optimize_hierarchy(tree, require_all_children=
False)
192 assert tree._tree_arrays[parent_level][parent_coords] == (1, 2)
195@pytest.mark.parametrize("dimensions", [2, 3])
198 Stage III invariant in 2D and 3D:
199 Optimisation modifies only subtree ids, never node existence flags (weights).
202 name=f
"pytest-tree-stage-iii-weights-{dimensions}d", max_level=2, dimensions=dimensions
206 parent_coords = (0, 0)
if dimensions == 2
else (0, 0, 0)
209 total_children = len(children)
210 dominant_count = total_children // 2 + 1
211 parent_count = total_children - dominant_count - 1
212 for coords
in children[:dominant_count]:
213 tree._tree_arrays[child_level][coords] = (1, 2)
214 for coords
in children[dominant_count:dominant_count + parent_count]:
215 tree._tree_arrays[child_level][coords] = (1, 0)
216 tree._tree_arrays[child_level][children[-1]] = (1, 1)
220 for level
in range(tree._max_level):
221 size = 3 ** (level + 1)
223 for a
in range(size):
224 for b
in range(size):
225 weight, _ = tree._tree_arrays[level][a][b]
226 weights_before[(level, a, b)] = weight
228 for a
in range(size):
229 for b
in range(size):
230 for c
in range(size):
231 weight, _ = tree._tree_arrays[level][a][b][c]
232 weights_before[(level, a, b, c)] = weight
235 split_strategy._optimize_hierarchy(tree)
238 for coords, weight_before
in weights_before.items():
241 weight_after, _ = tree._tree_arrays[level][a][b]
243 level, a, b, c = coords
244 weight_after, _ = tree._tree_arrays[level][a][b][c]
246 assert weight_after == weight_before, (
247 f
"Node {coords} weight changed from {weight_before} to {weight_after}"