exonware-xwnode 0.0.1.22__py3-none-any.whl → 0.0.1.24__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (249) hide show
  1. exonware/__init__.py +1 -1
  2. exonware/xwnode/__init__.py +18 -5
  3. exonware/xwnode/add_strategy_types.py +165 -0
  4. exonware/xwnode/common/__init__.py +1 -1
  5. exonware/xwnode/common/graph/__init__.py +30 -0
  6. exonware/xwnode/common/graph/caching.py +131 -0
  7. exonware/xwnode/common/graph/contracts.py +100 -0
  8. exonware/xwnode/common/graph/errors.py +44 -0
  9. exonware/xwnode/common/graph/indexing.py +260 -0
  10. exonware/xwnode/common/graph/manager.py +568 -0
  11. exonware/xwnode/common/management/__init__.py +3 -5
  12. exonware/xwnode/common/management/manager.py +2 -2
  13. exonware/xwnode/common/management/migration.py +3 -3
  14. exonware/xwnode/common/monitoring/__init__.py +3 -5
  15. exonware/xwnode/common/monitoring/metrics.py +6 -2
  16. exonware/xwnode/common/monitoring/pattern_detector.py +1 -1
  17. exonware/xwnode/common/monitoring/performance_monitor.py +5 -1
  18. exonware/xwnode/common/patterns/__init__.py +3 -5
  19. exonware/xwnode/common/patterns/flyweight.py +5 -1
  20. exonware/xwnode/common/patterns/registry.py +202 -183
  21. exonware/xwnode/common/utils/__init__.py +25 -11
  22. exonware/xwnode/common/utils/simple.py +1 -1
  23. exonware/xwnode/config.py +3 -8
  24. exonware/xwnode/contracts.py +4 -105
  25. exonware/xwnode/defs.py +413 -159
  26. exonware/xwnode/edges/strategies/__init__.py +86 -4
  27. exonware/xwnode/edges/strategies/_base_edge.py +2 -2
  28. exonware/xwnode/edges/strategies/adj_list.py +287 -121
  29. exonware/xwnode/edges/strategies/adj_matrix.py +316 -222
  30. exonware/xwnode/edges/strategies/base.py +1 -1
  31. exonware/xwnode/edges/strategies/{edge_bidir_wrapper.py → bidir_wrapper.py} +45 -4
  32. exonware/xwnode/edges/strategies/bitemporal.py +520 -0
  33. exonware/xwnode/edges/strategies/{edge_block_adj_matrix.py → block_adj_matrix.py} +77 -6
  34. exonware/xwnode/edges/strategies/bv_graph.py +664 -0
  35. exonware/xwnode/edges/strategies/compressed_graph.py +217 -0
  36. exonware/xwnode/edges/strategies/{edge_coo.py → coo.py} +46 -4
  37. exonware/xwnode/edges/strategies/{edge_csc.py → csc.py} +45 -4
  38. exonware/xwnode/edges/strategies/{edge_csr.py → csr.py} +94 -12
  39. exonware/xwnode/edges/strategies/{edge_dynamic_adj_list.py → dynamic_adj_list.py} +46 -4
  40. exonware/xwnode/edges/strategies/edge_list.py +168 -0
  41. exonware/xwnode/edges/strategies/edge_property_store.py +2 -2
  42. exonware/xwnode/edges/strategies/euler_tour.py +560 -0
  43. exonware/xwnode/edges/strategies/{edge_flow_network.py → flow_network.py} +2 -2
  44. exonware/xwnode/edges/strategies/graphblas.py +449 -0
  45. exonware/xwnode/edges/strategies/hnsw.py +637 -0
  46. exonware/xwnode/edges/strategies/hop2_labels.py +467 -0
  47. exonware/xwnode/edges/strategies/{edge_hyperedge_set.py → hyperedge_set.py} +2 -2
  48. exonware/xwnode/edges/strategies/incidence_matrix.py +250 -0
  49. exonware/xwnode/edges/strategies/k2_tree.py +613 -0
  50. exonware/xwnode/edges/strategies/link_cut.py +626 -0
  51. exonware/xwnode/edges/strategies/multiplex.py +532 -0
  52. exonware/xwnode/edges/strategies/{edge_neural_graph.py → neural_graph.py} +2 -2
  53. exonware/xwnode/edges/strategies/{edge_octree.py → octree.py} +69 -11
  54. exonware/xwnode/edges/strategies/{edge_quadtree.py → quadtree.py} +66 -10
  55. exonware/xwnode/edges/strategies/roaring_adj.py +438 -0
  56. exonware/xwnode/edges/strategies/{edge_rtree.py → rtree.py} +43 -5
  57. exonware/xwnode/edges/strategies/{edge_temporal_edgeset.py → temporal_edgeset.py} +24 -5
  58. exonware/xwnode/edges/strategies/{edge_tree_graph_basic.py → tree_graph_basic.py} +78 -7
  59. exonware/xwnode/edges/strategies/{edge_weighted_graph.py → weighted_graph.py} +188 -10
  60. exonware/xwnode/errors.py +3 -6
  61. exonware/xwnode/facade.py +20 -20
  62. exonware/xwnode/nodes/strategies/__init__.py +29 -9
  63. exonware/xwnode/nodes/strategies/adjacency_list.py +650 -177
  64. exonware/xwnode/nodes/strategies/aho_corasick.py +358 -183
  65. exonware/xwnode/nodes/strategies/array_list.py +36 -3
  66. exonware/xwnode/nodes/strategies/art.py +581 -0
  67. exonware/xwnode/nodes/strategies/{node_avl_tree.py → avl_tree.py} +77 -6
  68. exonware/xwnode/nodes/strategies/{node_b_plus_tree.py → b_plus_tree.py} +81 -40
  69. exonware/xwnode/nodes/strategies/{node_btree.py → b_tree.py} +79 -9
  70. exonware/xwnode/nodes/strategies/base.py +469 -98
  71. exonware/xwnode/nodes/strategies/{node_bitmap.py → bitmap.py} +12 -12
  72. exonware/xwnode/nodes/strategies/{node_bitset_dynamic.py → bitset_dynamic.py} +11 -11
  73. exonware/xwnode/nodes/strategies/{node_bloom_filter.py → bloom_filter.py} +15 -2
  74. exonware/xwnode/nodes/strategies/bloomier_filter.py +519 -0
  75. exonware/xwnode/nodes/strategies/bw_tree.py +531 -0
  76. exonware/xwnode/nodes/strategies/contracts.py +1 -1
  77. exonware/xwnode/nodes/strategies/{node_count_min_sketch.py → count_min_sketch.py} +3 -2
  78. exonware/xwnode/nodes/strategies/{node_cow_tree.py → cow_tree.py} +135 -13
  79. exonware/xwnode/nodes/strategies/crdt_map.py +629 -0
  80. exonware/xwnode/nodes/strategies/{node_cuckoo_hash.py → cuckoo_hash.py} +2 -2
  81. exonware/xwnode/nodes/strategies/{node_xdata_optimized.py → data_interchange_optimized.py} +21 -4
  82. exonware/xwnode/nodes/strategies/dawg.py +876 -0
  83. exonware/xwnode/nodes/strategies/deque.py +321 -153
  84. exonware/xwnode/nodes/strategies/extendible_hash.py +93 -0
  85. exonware/xwnode/nodes/strategies/{node_fenwick_tree.py → fenwick_tree.py} +111 -19
  86. exonware/xwnode/nodes/strategies/hamt.py +403 -0
  87. exonware/xwnode/nodes/strategies/hash_map.py +354 -67
  88. exonware/xwnode/nodes/strategies/heap.py +105 -5
  89. exonware/xwnode/nodes/strategies/hopscotch_hash.py +525 -0
  90. exonware/xwnode/nodes/strategies/{node_hyperloglog.py → hyperloglog.py} +6 -5
  91. exonware/xwnode/nodes/strategies/interval_tree.py +742 -0
  92. exonware/xwnode/nodes/strategies/kd_tree.py +703 -0
  93. exonware/xwnode/nodes/strategies/learned_index.py +533 -0
  94. exonware/xwnode/nodes/strategies/linear_hash.py +93 -0
  95. exonware/xwnode/nodes/strategies/linked_list.py +316 -119
  96. exonware/xwnode/nodes/strategies/{node_lsm_tree.py → lsm_tree.py} +219 -15
  97. exonware/xwnode/nodes/strategies/masstree.py +130 -0
  98. exonware/xwnode/nodes/strategies/{node_persistent_tree.py → persistent_tree.py} +149 -9
  99. exonware/xwnode/nodes/strategies/priority_queue.py +544 -132
  100. exonware/xwnode/nodes/strategies/queue.py +249 -120
  101. exonware/xwnode/nodes/strategies/{node_red_black_tree.py → red_black_tree.py} +183 -72
  102. exonware/xwnode/nodes/strategies/{node_roaring_bitmap.py → roaring_bitmap.py} +19 -6
  103. exonware/xwnode/nodes/strategies/rope.py +717 -0
  104. exonware/xwnode/nodes/strategies/{node_segment_tree.py → segment_tree.py} +106 -106
  105. exonware/xwnode/nodes/strategies/{node_set_hash.py → set_hash.py} +30 -29
  106. exonware/xwnode/nodes/strategies/{node_skip_list.py → skip_list.py} +74 -6
  107. exonware/xwnode/nodes/strategies/sparse_matrix.py +427 -131
  108. exonware/xwnode/nodes/strategies/{node_splay_tree.py → splay_tree.py} +55 -6
  109. exonware/xwnode/nodes/strategies/stack.py +244 -112
  110. exonware/xwnode/nodes/strategies/{node_suffix_array.py → suffix_array.py} +5 -1
  111. exonware/xwnode/nodes/strategies/t_tree.py +94 -0
  112. exonware/xwnode/nodes/strategies/{node_treap.py → treap.py} +75 -6
  113. exonware/xwnode/nodes/strategies/{node_tree_graph_hybrid.py → tree_graph_hybrid.py} +46 -5
  114. exonware/xwnode/nodes/strategies/trie.py +153 -9
  115. exonware/xwnode/nodes/strategies/union_find.py +111 -5
  116. exonware/xwnode/nodes/strategies/veb_tree.py +856 -0
  117. exonware/xwnode/strategies/__init__.py +5 -51
  118. exonware/xwnode/version.py +3 -3
  119. exonware_xwnode-0.0.1.24.dist-info/METADATA +900 -0
  120. exonware_xwnode-0.0.1.24.dist-info/RECORD +130 -0
  121. exonware/xwnode/edges/strategies/edge_adj_list.py +0 -353
  122. exonware/xwnode/edges/strategies/edge_adj_matrix.py +0 -445
  123. exonware/xwnode/nodes/strategies/_base_node.py +0 -307
  124. exonware/xwnode/nodes/strategies/node_aho_corasick.py +0 -525
  125. exonware/xwnode/nodes/strategies/node_array_list.py +0 -179
  126. exonware/xwnode/nodes/strategies/node_hash_map.py +0 -273
  127. exonware/xwnode/nodes/strategies/node_heap.py +0 -196
  128. exonware/xwnode/nodes/strategies/node_linked_list.py +0 -413
  129. exonware/xwnode/nodes/strategies/node_trie.py +0 -257
  130. exonware/xwnode/nodes/strategies/node_union_find.py +0 -192
  131. exonware/xwnode/queries/executors/__init__.py +0 -47
  132. exonware/xwnode/queries/executors/advanced/__init__.py +0 -37
  133. exonware/xwnode/queries/executors/advanced/aggregate_executor.py +0 -50
  134. exonware/xwnode/queries/executors/advanced/ask_executor.py +0 -50
  135. exonware/xwnode/queries/executors/advanced/construct_executor.py +0 -50
  136. exonware/xwnode/queries/executors/advanced/describe_executor.py +0 -50
  137. exonware/xwnode/queries/executors/advanced/for_loop_executor.py +0 -50
  138. exonware/xwnode/queries/executors/advanced/foreach_executor.py +0 -50
  139. exonware/xwnode/queries/executors/advanced/join_executor.py +0 -50
  140. exonware/xwnode/queries/executors/advanced/let_executor.py +0 -50
  141. exonware/xwnode/queries/executors/advanced/mutation_executor.py +0 -50
  142. exonware/xwnode/queries/executors/advanced/options_executor.py +0 -50
  143. exonware/xwnode/queries/executors/advanced/pipe_executor.py +0 -50
  144. exonware/xwnode/queries/executors/advanced/subscribe_executor.py +0 -50
  145. exonware/xwnode/queries/executors/advanced/subscription_executor.py +0 -50
  146. exonware/xwnode/queries/executors/advanced/union_executor.py +0 -50
  147. exonware/xwnode/queries/executors/advanced/window_executor.py +0 -51
  148. exonware/xwnode/queries/executors/advanced/with_cte_executor.py +0 -50
  149. exonware/xwnode/queries/executors/aggregation/__init__.py +0 -21
  150. exonware/xwnode/queries/executors/aggregation/avg_executor.py +0 -50
  151. exonware/xwnode/queries/executors/aggregation/count_executor.py +0 -38
  152. exonware/xwnode/queries/executors/aggregation/distinct_executor.py +0 -50
  153. exonware/xwnode/queries/executors/aggregation/group_executor.py +0 -50
  154. exonware/xwnode/queries/executors/aggregation/having_executor.py +0 -50
  155. exonware/xwnode/queries/executors/aggregation/max_executor.py +0 -50
  156. exonware/xwnode/queries/executors/aggregation/min_executor.py +0 -50
  157. exonware/xwnode/queries/executors/aggregation/sum_executor.py +0 -50
  158. exonware/xwnode/queries/executors/aggregation/summarize_executor.py +0 -50
  159. exonware/xwnode/queries/executors/array/__init__.py +0 -9
  160. exonware/xwnode/queries/executors/array/indexing_executor.py +0 -51
  161. exonware/xwnode/queries/executors/array/slicing_executor.py +0 -51
  162. exonware/xwnode/queries/executors/base.py +0 -257
  163. exonware/xwnode/queries/executors/capability_checker.py +0 -204
  164. exonware/xwnode/queries/executors/contracts.py +0 -166
  165. exonware/xwnode/queries/executors/core/__init__.py +0 -17
  166. exonware/xwnode/queries/executors/core/create_executor.py +0 -96
  167. exonware/xwnode/queries/executors/core/delete_executor.py +0 -99
  168. exonware/xwnode/queries/executors/core/drop_executor.py +0 -100
  169. exonware/xwnode/queries/executors/core/insert_executor.py +0 -39
  170. exonware/xwnode/queries/executors/core/select_executor.py +0 -152
  171. exonware/xwnode/queries/executors/core/update_executor.py +0 -102
  172. exonware/xwnode/queries/executors/data/__init__.py +0 -13
  173. exonware/xwnode/queries/executors/data/alter_executor.py +0 -50
  174. exonware/xwnode/queries/executors/data/load_executor.py +0 -50
  175. exonware/xwnode/queries/executors/data/merge_executor.py +0 -50
  176. exonware/xwnode/queries/executors/data/store_executor.py +0 -50
  177. exonware/xwnode/queries/executors/defs.py +0 -93
  178. exonware/xwnode/queries/executors/engine.py +0 -221
  179. exonware/xwnode/queries/executors/errors.py +0 -68
  180. exonware/xwnode/queries/executors/filtering/__init__.py +0 -25
  181. exonware/xwnode/queries/executors/filtering/between_executor.py +0 -80
  182. exonware/xwnode/queries/executors/filtering/filter_executor.py +0 -79
  183. exonware/xwnode/queries/executors/filtering/has_executor.py +0 -70
  184. exonware/xwnode/queries/executors/filtering/in_executor.py +0 -70
  185. exonware/xwnode/queries/executors/filtering/like_executor.py +0 -76
  186. exonware/xwnode/queries/executors/filtering/optional_executor.py +0 -76
  187. exonware/xwnode/queries/executors/filtering/range_executor.py +0 -80
  188. exonware/xwnode/queries/executors/filtering/term_executor.py +0 -77
  189. exonware/xwnode/queries/executors/filtering/values_executor.py +0 -71
  190. exonware/xwnode/queries/executors/filtering/where_executor.py +0 -44
  191. exonware/xwnode/queries/executors/graph/__init__.py +0 -15
  192. exonware/xwnode/queries/executors/graph/in_traverse_executor.py +0 -51
  193. exonware/xwnode/queries/executors/graph/match_executor.py +0 -51
  194. exonware/xwnode/queries/executors/graph/out_executor.py +0 -51
  195. exonware/xwnode/queries/executors/graph/path_executor.py +0 -51
  196. exonware/xwnode/queries/executors/graph/return_executor.py +0 -51
  197. exonware/xwnode/queries/executors/ordering/__init__.py +0 -9
  198. exonware/xwnode/queries/executors/ordering/by_executor.py +0 -50
  199. exonware/xwnode/queries/executors/ordering/order_executor.py +0 -51
  200. exonware/xwnode/queries/executors/projection/__init__.py +0 -9
  201. exonware/xwnode/queries/executors/projection/extend_executor.py +0 -50
  202. exonware/xwnode/queries/executors/projection/project_executor.py +0 -50
  203. exonware/xwnode/queries/executors/registry.py +0 -173
  204. exonware/xwnode/queries/parsers/__init__.py +0 -26
  205. exonware/xwnode/queries/parsers/base.py +0 -86
  206. exonware/xwnode/queries/parsers/contracts.py +0 -46
  207. exonware/xwnode/queries/parsers/errors.py +0 -53
  208. exonware/xwnode/queries/parsers/sql_param_extractor.py +0 -318
  209. exonware/xwnode/queries/strategies/__init__.py +0 -24
  210. exonware/xwnode/queries/strategies/base.py +0 -236
  211. exonware/xwnode/queries/strategies/cql.py +0 -201
  212. exonware/xwnode/queries/strategies/cypher.py +0 -181
  213. exonware/xwnode/queries/strategies/datalog.py +0 -70
  214. exonware/xwnode/queries/strategies/elastic_dsl.py +0 -70
  215. exonware/xwnode/queries/strategies/eql.py +0 -70
  216. exonware/xwnode/queries/strategies/flux.py +0 -70
  217. exonware/xwnode/queries/strategies/gql.py +0 -70
  218. exonware/xwnode/queries/strategies/graphql.py +0 -240
  219. exonware/xwnode/queries/strategies/gremlin.py +0 -181
  220. exonware/xwnode/queries/strategies/hiveql.py +0 -214
  221. exonware/xwnode/queries/strategies/hql.py +0 -70
  222. exonware/xwnode/queries/strategies/jmespath.py +0 -219
  223. exonware/xwnode/queries/strategies/jq.py +0 -66
  224. exonware/xwnode/queries/strategies/json_query.py +0 -66
  225. exonware/xwnode/queries/strategies/jsoniq.py +0 -248
  226. exonware/xwnode/queries/strategies/kql.py +0 -70
  227. exonware/xwnode/queries/strategies/linq.py +0 -238
  228. exonware/xwnode/queries/strategies/logql.py +0 -70
  229. exonware/xwnode/queries/strategies/mql.py +0 -68
  230. exonware/xwnode/queries/strategies/n1ql.py +0 -210
  231. exonware/xwnode/queries/strategies/partiql.py +0 -70
  232. exonware/xwnode/queries/strategies/pig.py +0 -215
  233. exonware/xwnode/queries/strategies/promql.py +0 -70
  234. exonware/xwnode/queries/strategies/sparql.py +0 -220
  235. exonware/xwnode/queries/strategies/sql.py +0 -275
  236. exonware/xwnode/queries/strategies/xml_query.py +0 -66
  237. exonware/xwnode/queries/strategies/xpath.py +0 -223
  238. exonware/xwnode/queries/strategies/xquery.py +0 -258
  239. exonware/xwnode/queries/strategies/xwnode_executor.py +0 -332
  240. exonware/xwnode/queries/strategies/xwquery.py +0 -456
  241. exonware_xwnode-0.0.1.22.dist-info/METADATA +0 -168
  242. exonware_xwnode-0.0.1.22.dist-info/RECORD +0 -214
  243. /exonware/xwnode/nodes/strategies/{node_ordered_map.py → ordered_map.py} +0 -0
  244. /exonware/xwnode/nodes/strategies/{node_ordered_map_balanced.py → ordered_map_balanced.py} +0 -0
  245. /exonware/xwnode/nodes/strategies/{node_patricia.py → patricia.py} +0 -0
  246. /exonware/xwnode/nodes/strategies/{node_radix_trie.py → radix_trie.py} +0 -0
  247. /exonware/xwnode/nodes/strategies/{node_set_tree.py → set_tree.py} +0 -0
  248. {exonware_xwnode-0.0.1.22.dist-info → exonware_xwnode-0.0.1.24.dist-info}/WHEEL +0 -0
  249. {exonware_xwnode-0.0.1.22.dist-info → exonware_xwnode-0.0.1.24.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,856 @@
1
+ """
2
+ #exonware/xwnode/src/exonware/xwnode/nodes/strategies/veb_tree.py
3
+
4
+ van Emde Boas Tree Node Strategy Implementation
5
+
6
+ This module implements the VEB_TREE strategy for O(log log U) operations
7
+ on fixed-universe integer keys.
8
+
9
+ Company: eXonware.com
10
+ Author: Eng. Muhammad AlShehri
11
+ Email: connect@exonware.com
12
+ Version: 0.0.1.24
13
+ Generation Date: 12-Oct-2025
14
+ """
15
+
16
+ import math
17
+ from typing import Any, Iterator, List, Dict, Optional, Set
18
+ from .base import ANodeTreeStrategy
19
+ from .contracts import NodeType
20
+ from ...defs import NodeMode, NodeTrait
21
+ from ...errors import XWNodeError, XWNodeValueError
22
+
23
+
24
+ class VebNode:
25
+ """
26
+ Node in the van Emde Boas tree structure.
27
+
28
+ WHY recursive structure:
29
+ - Enables O(log log U) time complexity through universe splitting
30
+ - Each cluster handles √U elements recursively
31
+ - Summary structure provides constant-time minimum/maximum
32
+ """
33
+
34
+ def __init__(self, universe_size: int):
35
+ """
36
+ Initialize vEB node.
37
+
38
+ Args:
39
+ universe_size: Size of universe (must be power of 2)
40
+ """
41
+ self.universe_size = universe_size
42
+ self.min = None
43
+ self.max = None
44
+
45
+ # Base case: universe size 2
46
+ if universe_size <= 2:
47
+ self.summary = None
48
+ self.clusters = None
49
+ else:
50
+ # Recursive case - for power of 2, use exact sqrt
51
+ # For universe_size = 2^k, sqrt = 2^(k/2)
52
+ lower_sqrt = 1 << (universe_size.bit_length() // 2) # Power of 2 sqrt
53
+ upper_sqrt = (universe_size + lower_sqrt - 1) // lower_sqrt # Ceiling division
54
+
55
+ # Summary structure for non-empty clusters
56
+ self.summary = VebNode(upper_sqrt)
57
+
58
+ # Array of cluster nodes (one per possible cluster)
59
+ self.clusters = [None] * upper_sqrt
60
+
61
+ def is_empty(self) -> bool:
62
+ """Check if tree is empty."""
63
+ return self.min is None
64
+
65
+ def high(self, x: int) -> int:
66
+ """Get high-order bits (cluster index)."""
67
+ lower_sqrt = 1 << (self.universe_size.bit_length() // 2)
68
+ return x // lower_sqrt
69
+
70
+ def low(self, x: int) -> int:
71
+ """Get low-order bits (position in cluster)."""
72
+ lower_sqrt = 1 << (self.universe_size.bit_length() // 2)
73
+ return x % lower_sqrt
74
+
75
+ def index(self, high: int, low: int) -> int:
76
+ """Combine high and low to get original index."""
77
+ lower_sqrt = 1 << (self.universe_size.bit_length() // 2)
78
+ return high * lower_sqrt + low
79
+
80
+
81
+ class VebTreeStrategy(ANodeTreeStrategy):
82
+ """
83
+ van Emde Boas Tree strategy for O(log log U) integer operations.
84
+
85
+ WHY van Emde Boas Tree:
86
+ - Asymptotically faster than balanced BSTs: O(log log U) vs O(log n)
87
+ - Predictable performance for fixed-universe integers
88
+ - Excellent for routing tables, IP address lookups, priority queues
89
+ - Constant-time min/max queries through summary caching
90
+ - Ideal for small-universe scenarios (16-bit, 32-bit integers)
91
+
92
+ WHY this implementation:
93
+ - Recursive cluster decomposition enables logarithmic speedup
94
+ - Min/max caching at each level for O(1) extreme queries
95
+ - Summary structure enables fast successor/predecessor
96
+ - Lazy cluster initialization saves memory for sparse data
97
+ - Direct indexing eliminates pointer indirection overhead
98
+
99
+ Time Complexity:
100
+ - Insert: O(log log U) where U is universe size
101
+ - Delete: O(log log U)
102
+ - Search: O(log log U)
103
+ - Min/Max: O(1) through caching
104
+ - Successor: O(log log U)
105
+ - Predecessor: O(log log U)
106
+
107
+ Space Complexity: O(U) worst case, O(n) for n elements with lazy allocation
108
+
109
+ Trade-offs:
110
+ - Advantage: Faster than BST for small universes (log log U << log n)
111
+ - Advantage: Constant-time min/max queries
112
+ - Advantage: Excellent for dense integer keys
113
+ - Limitation: High space overhead O(U) for sparse data
114
+ - Limitation: Universe size must be power of 2
115
+ - Limitation: Integer keys only (no strings, floats)
116
+ - Compared to HashMap: Better ordered operations, worse space
117
+ - Compared to B-Tree: Faster for small universes, worse for large
118
+
119
+ Best for:
120
+ - Routing tables with IP addresses (32-bit universe)
121
+ - Priority queues with small integer priorities
122
+ - Network switches and routers
123
+ - Small-universe integer key-value stores
124
+ - Real-time systems requiring predictable performance
125
+ - Dense integer key distributions
126
+
127
+ Not recommended for:
128
+ - Large universes (2^64) - excessive memory
129
+ - Sparse data (few elements, large universe)
130
+ - String or floating-point keys
131
+ - Dynamic universe size requirements
132
+ - Memory-constrained environments
133
+ - Non-integer key types
134
+
135
+ Following eXonware Priorities:
136
+ 1. Security: Validates universe bounds, prevents overflow attacks
137
+ 2. Usability: Simple API for integer operations, clear errors
138
+ 3. Maintainability: Clean recursive structure, well-documented
139
+ 4. Performance: O(log log U) operations, optimal for use case
140
+ 5. Extensibility: Easy to add weighted variants or range queries
141
+
142
+ Industry Best Practices:
143
+ - Follows van Emde Boas original paper (1975)
144
+ - Implements lazy cluster allocation for memory efficiency
145
+ - Uses power-of-2 universe sizes for optimal splitting
146
+ - Provides min/max caching for constant-time queries
147
+ - Supports both membership and key-value storage
148
+ """
149
+
150
+ # Tree node type for classification
151
+ STRATEGY_TYPE: NodeType = NodeType.TREE
152
+
153
+ def __init__(self, mode: NodeMode = NodeMode.VEB_TREE,
154
+ traits: NodeTrait = NodeTrait.NONE,
155
+ universe_size: int = 65536, **options):
156
+ """
157
+ Initialize van Emde Boas tree strategy.
158
+
159
+ Args:
160
+ mode: Node mode (VEB_TREE)
161
+ traits: Node traits
162
+ universe_size: Maximum key value (must be power of 2)
163
+ **options: Additional options
164
+
165
+ Raises:
166
+ XWNodeValueError: If universe_size is not power of 2
167
+ """
168
+ # Validate universe size is power of 2
169
+ if universe_size <= 0 or (universe_size & (universe_size - 1)) != 0:
170
+ raise XWNodeValueError(
171
+ f"Universe size must be a power of 2, got {universe_size}"
172
+ )
173
+
174
+ super().__init__(mode, traits, **options)
175
+
176
+ self.universe_size = universe_size
177
+ self._root = VebNode(universe_size)
178
+ self._values: Dict[int, Any] = {} # Store actual values
179
+ self._size = 0
180
+
181
+ def get_supported_traits(self) -> NodeTrait:
182
+ """Get supported traits."""
183
+ return NodeTrait.ORDERED | NodeTrait.INDEXED | NodeTrait.FAST_INSERT | NodeTrait.FAST_DELETE
184
+
185
+ # ============================================================================
186
+ # CORE VEB OPERATIONS
187
+ # ============================================================================
188
+
189
+ def _veb_insert(self, node: VebNode, x: int) -> None:
190
+ """
191
+ Insert element into vEB tree.
192
+
193
+ Args:
194
+ node: Current vEB node
195
+ x: Integer key to insert
196
+ """
197
+ # Security: Validate bounds
198
+ if x < 0 or x >= node.universe_size:
199
+ raise XWNodeValueError(
200
+ f"Key {x} out of bounds [0, {node.universe_size})"
201
+ )
202
+
203
+ # Empty tree case
204
+ if node.is_empty():
205
+ node.min = node.max = x
206
+ return
207
+
208
+ # Ensure x is not already min or max
209
+ if x == node.min or x == node.max:
210
+ return # Already present
211
+
212
+ # Swap to ensure min is minimum
213
+ if x < node.min:
214
+ x, node.min = node.min, x
215
+
216
+ # Base case
217
+ if node.universe_size == 2:
218
+ node.max = max(x, node.max) if node.max is not None else x
219
+ return
220
+
221
+ # Recursive case
222
+ high = node.high(x)
223
+ low = node.low(x)
224
+
225
+ # Lazy cluster creation
226
+ if node.clusters[high] is None:
227
+ lower_sqrt = 1 << (node.universe_size.bit_length() // 2)
228
+ node.clusters[high] = VebNode(lower_sqrt)
229
+
230
+ # If cluster is empty, update summary
231
+ if node.clusters[high].is_empty():
232
+ self._veb_insert(node.summary, high)
233
+
234
+ # Insert into cluster
235
+ self._veb_insert(node.clusters[high], low)
236
+
237
+ # Update max if necessary
238
+ if x > node.max:
239
+ node.max = x
240
+
241
+ def _veb_delete(self, node: VebNode, x: int) -> bool:
242
+ """
243
+ Delete element from vEB tree.
244
+
245
+ Args:
246
+ node: Current vEB node
247
+ x: Integer key to delete
248
+
249
+ Returns:
250
+ True if deleted, False if not found
251
+ """
252
+ # Security: Validate bounds
253
+ if x < 0 or x >= node.universe_size:
254
+ return False
255
+
256
+ # Element not in tree
257
+ if node.is_empty() or x < node.min or x > node.max:
258
+ return False
259
+
260
+ # Single element case
261
+ if node.min == node.max:
262
+ if x == node.min:
263
+ node.min = node.max = None
264
+ return True
265
+ return False
266
+
267
+ # Base case: universe size 2
268
+ if node.universe_size == 2:
269
+ if x == 0:
270
+ node.min = 1
271
+ else:
272
+ node.max = 0
273
+ return True
274
+
275
+ # Recursive case
276
+ # If deleting min, replace with successor
277
+ if x == node.min:
278
+ first_cluster = node.summary.min
279
+ if first_cluster is None:
280
+ # No other elements
281
+ node.min = node.max
282
+ return True
283
+
284
+ x = node.index(first_cluster, node.clusters[first_cluster].min)
285
+ node.min = x
286
+
287
+ # Delete from appropriate cluster
288
+ high = node.high(x)
289
+ low = node.low(x)
290
+
291
+ if node.clusters[high] is None:
292
+ return False
293
+
294
+ deleted = self._veb_delete(node.clusters[high], low)
295
+
296
+ if not deleted:
297
+ return False
298
+
299
+ # Update summary if cluster becomes empty
300
+ if node.clusters[high].is_empty():
301
+ self._veb_delete(node.summary, high)
302
+
303
+ # Update max if we deleted it
304
+ if x == node.max:
305
+ if node.summary.is_empty():
306
+ node.max = node.min
307
+ else:
308
+ max_cluster = node.summary.max
309
+ node.max = node.index(max_cluster, node.clusters[max_cluster].max)
310
+ elif x == node.max:
311
+ # Update max within same cluster
312
+ node.max = node.index(high, node.clusters[high].max)
313
+
314
+ return True
315
+
316
+ def _veb_member(self, node: VebNode, x: int) -> bool:
317
+ """
318
+ Check membership in vEB tree.
319
+
320
+ Args:
321
+ node: Current vEB node
322
+ x: Integer key to check
323
+
324
+ Returns:
325
+ True if present, False otherwise
326
+ """
327
+ # Security: Validate bounds
328
+ if x < 0 or x >= node.universe_size:
329
+ return False
330
+
331
+ # Check cached min/max
332
+ if x == node.min or x == node.max:
333
+ return True
334
+
335
+ # Empty or out of range
336
+ if node.is_empty() or x < node.min or x > node.max:
337
+ return False
338
+
339
+ # Base case
340
+ if node.universe_size == 2:
341
+ return False
342
+
343
+ # Recursive case
344
+ high = node.high(x)
345
+ low = node.low(x)
346
+
347
+ if node.clusters[high] is None:
348
+ return False
349
+
350
+ return self._veb_member(node.clusters[high], low)
351
+
352
+ def _veb_successor(self, node: VebNode, x: int) -> Optional[int]:
353
+ """
354
+ Find successor of x (smallest element > x).
355
+
356
+ Args:
357
+ node: Current vEB node
358
+ x: Integer key
359
+
360
+ Returns:
361
+ Successor key or None if no successor exists
362
+ """
363
+ # Security: Validate bounds
364
+ if x < 0 or x >= node.universe_size:
365
+ return None
366
+
367
+ # Base case
368
+ if node.universe_size == 2:
369
+ if x == 0 and node.max == 1:
370
+ return 1
371
+ return None
372
+
373
+ # If x < min, min is successor
374
+ if not node.is_empty() and x < node.min:
375
+ return node.min
376
+
377
+ # Check within same cluster
378
+ high = node.high(x)
379
+ low = node.low(x)
380
+
381
+ if node.clusters[high] is not None and not node.clusters[high].is_empty():
382
+ if low < node.clusters[high].max:
383
+ offset = self._veb_successor(node.clusters[high], low)
384
+ if offset is not None:
385
+ return node.index(high, offset)
386
+
387
+ # Find next non-empty cluster
388
+ succ_cluster = self._veb_successor(node.summary, high)
389
+ if succ_cluster is None:
390
+ return None
391
+
392
+ if node.clusters[succ_cluster] is None:
393
+ return None
394
+
395
+ offset = node.clusters[succ_cluster].min
396
+ return node.index(succ_cluster, offset)
397
+
398
+ def _veb_predecessor(self, node: VebNode, x: int) -> Optional[int]:
399
+ """
400
+ Find predecessor of x (largest element < x).
401
+
402
+ Args:
403
+ node: Current vEB node
404
+ x: Integer key
405
+
406
+ Returns:
407
+ Predecessor key or None if no predecessor exists
408
+ """
409
+ # Security: Validate bounds
410
+ if x < 0 or x >= node.universe_size:
411
+ return None
412
+
413
+ # Base case
414
+ if node.universe_size == 2:
415
+ if x == 1 and node.min == 0:
416
+ return 0
417
+ return None
418
+
419
+ # If x > max, max is predecessor
420
+ if not node.is_empty() and x > node.max:
421
+ return node.max
422
+
423
+ # Check within same cluster
424
+ high = node.high(x)
425
+ low = node.low(x)
426
+
427
+ if node.clusters[high] is not None and not node.clusters[high].is_empty():
428
+ if low > node.clusters[high].min:
429
+ offset = self._veb_predecessor(node.clusters[high], low)
430
+ if offset is not None:
431
+ return node.index(high, offset)
432
+
433
+ # Find previous non-empty cluster
434
+ pred_cluster = self._veb_predecessor(node.summary, high)
435
+ if pred_cluster is None:
436
+ # Check if min is predecessor
437
+ if not node.is_empty() and x > node.min:
438
+ return node.min
439
+ return None
440
+
441
+ if node.clusters[pred_cluster] is None:
442
+ return None
443
+
444
+ offset = node.clusters[pred_cluster].max
445
+ return node.index(pred_cluster, offset)
446
+
447
+ # ============================================================================
448
+ # STRATEGY INTERFACE IMPLEMENTATION
449
+ # ============================================================================
450
+
451
+ def put(self, key: Any, value: Any = None) -> None:
452
+ """
453
+ Store key-value pair.
454
+
455
+ Args:
456
+ key: Integer key (0 to universe_size-1)
457
+ value: Associated value
458
+
459
+ Raises:
460
+ XWNodeValueError: If key is not an integer or out of bounds
461
+ """
462
+ # Security: Type validation
463
+ if not isinstance(key, int):
464
+ raise XWNodeValueError(
465
+ f"vEB tree requires integer keys, got {type(key).__name__}"
466
+ )
467
+
468
+ # Security: Bounds validation
469
+ if key < 0 or key >= self.universe_size:
470
+ raise XWNodeValueError(
471
+ f"Key {key} out of universe bounds [0, {self.universe_size})"
472
+ )
473
+
474
+ # Insert into vEB structure
475
+ was_present = self._veb_member(self._root, key)
476
+ self._veb_insert(self._root, key)
477
+
478
+ # Store value
479
+ self._values[key] = value
480
+
481
+ if not was_present:
482
+ self._size += 1
483
+
484
+ def get(self, key: Any, default: Any = None) -> Any:
485
+ """
486
+ Retrieve value by key.
487
+
488
+ Args:
489
+ key: Integer key
490
+ default: Default value if not found
491
+
492
+ Returns:
493
+ Value or default
494
+ """
495
+ # Type check
496
+ if not isinstance(key, int):
497
+ return default
498
+
499
+ # Bounds check
500
+ if key < 0 or key >= self.universe_size:
501
+ return default
502
+
503
+ # Check membership
504
+ if not self._veb_member(self._root, key):
505
+ return default
506
+
507
+ return self._values.get(key, default)
508
+
509
+ def has(self, key: Any) -> bool:
510
+ """
511
+ Check if key exists.
512
+
513
+ Args:
514
+ key: Integer key
515
+
516
+ Returns:
517
+ True if exists, False otherwise
518
+ """
519
+ if not isinstance(key, int):
520
+ return False
521
+
522
+ if key < 0 or key >= self.universe_size:
523
+ return False
524
+
525
+ return self._veb_member(self._root, key)
526
+
527
+ def delete(self, key: Any) -> bool:
528
+ """
529
+ Remove key-value pair.
530
+
531
+ Args:
532
+ key: Integer key
533
+
534
+ Returns:
535
+ True if deleted, False if not found
536
+ """
537
+ if not isinstance(key, int):
538
+ return False
539
+
540
+ if key < 0 or key >= self.universe_size:
541
+ return False
542
+
543
+ # Delete from vEB structure
544
+ deleted = self._veb_delete(self._root, key)
545
+
546
+ if deleted:
547
+ if key in self._values:
548
+ del self._values[key]
549
+ self._size -= 1
550
+
551
+ return deleted
552
+
553
+ def keys(self) -> Iterator[Any]:
554
+ """
555
+ Get iterator over all keys in sorted order.
556
+
557
+ Returns:
558
+ Iterator of keys
559
+ """
560
+ if self._root.is_empty():
561
+ return
562
+
563
+ # Start with minimum
564
+ current = self._root.min
565
+ while current is not None:
566
+ yield current
567
+ current = self._veb_successor(self._root, current)
568
+
569
+ def values(self) -> Iterator[Any]:
570
+ """
571
+ Get iterator over all values in key-sorted order.
572
+
573
+ Returns:
574
+ Iterator of values
575
+ """
576
+ for key in self.keys():
577
+ yield self._values.get(key)
578
+
579
+ def items(self) -> Iterator[tuple[Any, Any]]:
580
+ """
581
+ Get iterator over all key-value pairs in sorted order.
582
+
583
+ Returns:
584
+ Iterator of (key, value) tuples
585
+ """
586
+ for key in self.keys():
587
+ yield (key, self._values.get(key))
588
+
589
+ def __len__(self) -> int:
590
+ """Get number of elements."""
591
+ return self._size
592
+
593
+ def to_native(self) -> Any:
594
+ """
595
+ Convert to native Python dict.
596
+
597
+ Returns:
598
+ Dictionary representation
599
+ """
600
+ return dict(self.items())
601
+
602
+ # ============================================================================
603
+ # VEB-SPECIFIC OPERATIONS
604
+ # ============================================================================
605
+
606
+ def get_min(self) -> Optional[int]:
607
+ """
608
+ Get minimum key in O(1) time.
609
+
610
+ Returns:
611
+ Minimum key or None if empty
612
+ """
613
+ return self._root.min
614
+
615
+ def get_max(self) -> Optional[int]:
616
+ """
617
+ Get maximum key in O(1) time.
618
+
619
+ Returns:
620
+ Maximum key or None if empty
621
+ """
622
+ return self._root.max
623
+
624
+ def successor(self, key: int) -> Optional[int]:
625
+ """
626
+ Find successor of key (smallest key > given key).
627
+
628
+ Args:
629
+ key: Integer key
630
+
631
+ Returns:
632
+ Successor key or None
633
+
634
+ Raises:
635
+ XWNodeValueError: If key is invalid
636
+ """
637
+ if not isinstance(key, int):
638
+ raise XWNodeValueError(f"vEB tree requires integer keys")
639
+
640
+ if key < 0 or key >= self.universe_size:
641
+ raise XWNodeValueError(
642
+ f"Key {key} out of universe bounds [0, {self.universe_size})"
643
+ )
644
+
645
+ return self._veb_successor(self._root, key)
646
+
647
+ def predecessor(self, key: int) -> Optional[int]:
648
+ """
649
+ Find predecessor of key (largest key < given key).
650
+
651
+ Args:
652
+ key: Integer key
653
+
654
+ Returns:
655
+ Predecessor key or None
656
+
657
+ Raises:
658
+ XWNodeValueError: If key is invalid
659
+ """
660
+ if not isinstance(key, int):
661
+ raise XWNodeValueError(f"vEB tree requires integer keys")
662
+
663
+ if key < 0 or key >= self.universe_size:
664
+ raise XWNodeValueError(
665
+ f"Key {key} out of universe bounds [0, {self.universe_size})"
666
+ )
667
+
668
+ return self._veb_predecessor(self._root, key)
669
+
670
+ def range_query(self, low: int, high: int) -> List[tuple[int, Any]]:
671
+ """
672
+ Find all keys in range [low, high].
673
+
674
+ Args:
675
+ low: Lower bound (inclusive)
676
+ high: Upper bound (inclusive)
677
+
678
+ Returns:
679
+ List of (key, value) pairs in range
680
+
681
+ Raises:
682
+ XWNodeValueError: If bounds are invalid
683
+ """
684
+ # Security: Validate inputs
685
+ if not isinstance(low, int) or not isinstance(high, int):
686
+ raise XWNodeValueError("Range bounds must be integers")
687
+
688
+ if low < 0 or high >= self.universe_size or low > high:
689
+ raise XWNodeValueError(
690
+ f"Invalid range [{low}, {high}] for universe [0, {self.universe_size})"
691
+ )
692
+
693
+ result = []
694
+
695
+ # Find first key >= low
696
+ if self._veb_member(self._root, low):
697
+ current = low
698
+ else:
699
+ current = self._veb_successor(self._root, low)
700
+
701
+ # Collect all keys up to high
702
+ while current is not None and current <= high:
703
+ result.append((current, self._values.get(current)))
704
+ current = self._veb_successor(self._root, current)
705
+
706
+ return result
707
+
708
+ # ============================================================================
709
+ # PERFORMANCE METHODS
710
+ # ============================================================================
711
+
712
+ def get_depth(self) -> int:
713
+ """
714
+ Get tree depth.
715
+
716
+ Returns:
717
+ Depth of recursion (log log U)
718
+ """
719
+ depth = 0
720
+ u = self.universe_size
721
+ while u > 2:
722
+ u = int(math.sqrt(u))
723
+ depth += 1
724
+ return depth
725
+
726
+ def get_memory_usage(self) -> Dict[str, Any]:
727
+ """
728
+ Estimate memory usage.
729
+
730
+ Returns:
731
+ Memory usage statistics
732
+ """
733
+ def count_nodes(node: VebNode) -> int:
734
+ """Recursively count allocated nodes."""
735
+ if node is None:
736
+ return 0
737
+
738
+ count = 1
739
+ if node.summary is not None:
740
+ count += count_nodes(node.summary)
741
+
742
+ if node.clusters is not None:
743
+ for cluster in node.clusters:
744
+ if cluster is not None:
745
+ count += count_nodes(cluster)
746
+
747
+ return count
748
+
749
+ node_count = count_nodes(self._root)
750
+
751
+ return {
752
+ 'allocated_nodes': node_count,
753
+ 'universe_size': self.universe_size,
754
+ 'stored_values': len(self._values),
755
+ 'depth': self.get_depth(),
756
+ 'memory_efficiency': len(self._values) / max(node_count, 1)
757
+ }
758
+
759
+ # ============================================================================
760
+ # ADDITIONAL HELPER METHODS
761
+ # ============================================================================
762
+
763
+ def clear(self) -> None:
764
+ """Clear all elements."""
765
+ self._root = VebNode(self.universe_size)
766
+ self._values.clear()
767
+ self._size = 0
768
+
769
+ def is_empty(self) -> bool:
770
+ """Check if tree is empty."""
771
+ return self._root.is_empty()
772
+
773
+ def size(self) -> int:
774
+ """Get number of elements."""
775
+ return self._size
776
+
777
+ def get_mode(self) -> NodeMode:
778
+ """Get strategy mode."""
779
+ return self.mode
780
+
781
+ def get_traits(self) -> NodeTrait:
782
+ """Get strategy traits."""
783
+ return self.traits
784
+
785
+ # ============================================================================
786
+ # COMPATIBILITY METHODS
787
+ # ============================================================================
788
+
789
+ def find(self, key: Any) -> Optional[Any]:
790
+ """
791
+ Find value by key (alias for get).
792
+
793
+ Args:
794
+ key: Integer key
795
+
796
+ Returns:
797
+ Value or None
798
+ """
799
+ return self.get(key)
800
+
801
+ def insert(self, key: Any, value: Any = None) -> None:
802
+ """
803
+ Insert key-value pair (alias for put).
804
+
805
+ Args:
806
+ key: Integer key
807
+ value: Associated value
808
+ """
809
+ self.put(key, value)
810
+
811
+ def __str__(self) -> str:
812
+ """String representation."""
813
+ return f"VebTreeStrategy(universe={self.universe_size}, size={self._size}, depth={self.get_depth()})"
814
+
815
+ def __repr__(self) -> str:
816
+ """Detailed representation."""
817
+ return (f"VebTreeStrategy(mode={self.mode.name}, universe={self.universe_size}, "
818
+ f"size={self._size}, traits={self.traits})")
819
+
820
+ # ============================================================================
821
+ # FACTORY METHOD
822
+ # ============================================================================
823
+
824
+ @classmethod
825
+ def create_from_data(cls, data: Any, universe_size: int = 65536) -> 'VebTreeStrategy':
826
+ """
827
+ Create vEB tree from data.
828
+
829
+ Args:
830
+ data: Dictionary with integer keys
831
+ universe_size: Maximum key value
832
+
833
+ Returns:
834
+ New VebTreeStrategy instance
835
+
836
+ Raises:
837
+ XWNodeValueError: If data contains non-integer keys
838
+ """
839
+ instance = cls(universe_size=universe_size)
840
+
841
+ if isinstance(data, dict):
842
+ for key, value in data.items():
843
+ if not isinstance(key, int):
844
+ raise XWNodeValueError(
845
+ f"vEB tree requires integer keys, found {type(key).__name__}"
846
+ )
847
+ instance.put(key, value)
848
+ elif isinstance(data, (list, tuple)):
849
+ for i, value in enumerate(data):
850
+ instance.put(i, value)
851
+ else:
852
+ # Store scalar as single element
853
+ instance.put(0, data)
854
+
855
+ return instance
856
+