exonware-xwnode 0.0.1.21__py3-none-any.whl → 0.0.1.23__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 (250) hide show
  1. exonware/__init__.py +8 -1
  2. exonware/xwnode/__init__.py +18 -5
  3. exonware/xwnode/add_strategy_types.py +165 -0
  4. exonware/xwnode/base.py +7 -5
  5. exonware/xwnode/common/__init__.py +1 -1
  6. exonware/xwnode/common/graph/__init__.py +30 -0
  7. exonware/xwnode/common/graph/caching.py +131 -0
  8. exonware/xwnode/common/graph/contracts.py +100 -0
  9. exonware/xwnode/common/graph/errors.py +44 -0
  10. exonware/xwnode/common/graph/indexing.py +260 -0
  11. exonware/xwnode/common/graph/manager.py +568 -0
  12. exonware/xwnode/common/management/__init__.py +3 -5
  13. exonware/xwnode/common/management/manager.py +9 -9
  14. exonware/xwnode/common/management/migration.py +6 -6
  15. exonware/xwnode/common/monitoring/__init__.py +3 -5
  16. exonware/xwnode/common/monitoring/metrics.py +7 -3
  17. exonware/xwnode/common/monitoring/pattern_detector.py +2 -2
  18. exonware/xwnode/common/monitoring/performance_monitor.py +6 -2
  19. exonware/xwnode/common/patterns/__init__.py +3 -5
  20. exonware/xwnode/common/patterns/advisor.py +1 -1
  21. exonware/xwnode/common/patterns/flyweight.py +6 -2
  22. exonware/xwnode/common/patterns/registry.py +203 -184
  23. exonware/xwnode/common/utils/__init__.py +25 -11
  24. exonware/xwnode/common/utils/simple.py +1 -1
  25. exonware/xwnode/config.py +3 -8
  26. exonware/xwnode/contracts.py +4 -105
  27. exonware/xwnode/defs.py +413 -159
  28. exonware/xwnode/edges/strategies/__init__.py +86 -4
  29. exonware/xwnode/edges/strategies/_base_edge.py +2 -2
  30. exonware/xwnode/edges/strategies/adj_list.py +287 -121
  31. exonware/xwnode/edges/strategies/adj_matrix.py +316 -222
  32. exonware/xwnode/edges/strategies/base.py +1 -1
  33. exonware/xwnode/edges/strategies/{edge_bidir_wrapper.py → bidir_wrapper.py} +45 -4
  34. exonware/xwnode/edges/strategies/bitemporal.py +520 -0
  35. exonware/xwnode/edges/strategies/{edge_block_adj_matrix.py → block_adj_matrix.py} +77 -6
  36. exonware/xwnode/edges/strategies/bv_graph.py +664 -0
  37. exonware/xwnode/edges/strategies/compressed_graph.py +217 -0
  38. exonware/xwnode/edges/strategies/{edge_coo.py → coo.py} +46 -4
  39. exonware/xwnode/edges/strategies/{edge_csc.py → csc.py} +45 -4
  40. exonware/xwnode/edges/strategies/{edge_csr.py → csr.py} +94 -12
  41. exonware/xwnode/edges/strategies/{edge_dynamic_adj_list.py → dynamic_adj_list.py} +46 -4
  42. exonware/xwnode/edges/strategies/edge_list.py +168 -0
  43. exonware/xwnode/edges/strategies/edge_property_store.py +2 -2
  44. exonware/xwnode/edges/strategies/euler_tour.py +560 -0
  45. exonware/xwnode/edges/strategies/{edge_flow_network.py → flow_network.py} +2 -2
  46. exonware/xwnode/edges/strategies/graphblas.py +449 -0
  47. exonware/xwnode/edges/strategies/hnsw.py +637 -0
  48. exonware/xwnode/edges/strategies/hop2_labels.py +467 -0
  49. exonware/xwnode/edges/strategies/{edge_hyperedge_set.py → hyperedge_set.py} +2 -2
  50. exonware/xwnode/edges/strategies/incidence_matrix.py +250 -0
  51. exonware/xwnode/edges/strategies/k2_tree.py +613 -0
  52. exonware/xwnode/edges/strategies/link_cut.py +626 -0
  53. exonware/xwnode/edges/strategies/multiplex.py +532 -0
  54. exonware/xwnode/edges/strategies/{edge_neural_graph.py → neural_graph.py} +2 -2
  55. exonware/xwnode/edges/strategies/{edge_octree.py → octree.py} +69 -11
  56. exonware/xwnode/edges/strategies/{edge_quadtree.py → quadtree.py} +66 -10
  57. exonware/xwnode/edges/strategies/roaring_adj.py +438 -0
  58. exonware/xwnode/edges/strategies/{edge_rtree.py → rtree.py} +43 -5
  59. exonware/xwnode/edges/strategies/{edge_temporal_edgeset.py → temporal_edgeset.py} +24 -5
  60. exonware/xwnode/edges/strategies/{edge_tree_graph_basic.py → tree_graph_basic.py} +78 -7
  61. exonware/xwnode/edges/strategies/{edge_weighted_graph.py → weighted_graph.py} +188 -10
  62. exonware/xwnode/errors.py +3 -6
  63. exonware/xwnode/facade.py +20 -20
  64. exonware/xwnode/nodes/strategies/__init__.py +29 -9
  65. exonware/xwnode/nodes/strategies/adjacency_list.py +650 -177
  66. exonware/xwnode/nodes/strategies/aho_corasick.py +358 -183
  67. exonware/xwnode/nodes/strategies/array_list.py +36 -3
  68. exonware/xwnode/nodes/strategies/art.py +581 -0
  69. exonware/xwnode/nodes/strategies/{node_avl_tree.py → avl_tree.py} +77 -6
  70. exonware/xwnode/nodes/strategies/{node_b_plus_tree.py → b_plus_tree.py} +81 -40
  71. exonware/xwnode/nodes/strategies/{node_btree.py → b_tree.py} +79 -9
  72. exonware/xwnode/nodes/strategies/base.py +469 -98
  73. exonware/xwnode/nodes/strategies/{node_bitmap.py → bitmap.py} +12 -12
  74. exonware/xwnode/nodes/strategies/{node_bitset_dynamic.py → bitset_dynamic.py} +11 -11
  75. exonware/xwnode/nodes/strategies/{node_bloom_filter.py → bloom_filter.py} +15 -2
  76. exonware/xwnode/nodes/strategies/bloomier_filter.py +519 -0
  77. exonware/xwnode/nodes/strategies/bw_tree.py +531 -0
  78. exonware/xwnode/nodes/strategies/contracts.py +1 -1
  79. exonware/xwnode/nodes/strategies/{node_count_min_sketch.py → count_min_sketch.py} +3 -2
  80. exonware/xwnode/nodes/strategies/{node_cow_tree.py → cow_tree.py} +135 -13
  81. exonware/xwnode/nodes/strategies/crdt_map.py +629 -0
  82. exonware/xwnode/nodes/strategies/{node_cuckoo_hash.py → cuckoo_hash.py} +2 -2
  83. exonware/xwnode/nodes/strategies/{node_xdata_optimized.py → data_interchange_optimized.py} +21 -4
  84. exonware/xwnode/nodes/strategies/dawg.py +876 -0
  85. exonware/xwnode/nodes/strategies/deque.py +321 -153
  86. exonware/xwnode/nodes/strategies/extendible_hash.py +93 -0
  87. exonware/xwnode/nodes/strategies/{node_fenwick_tree.py → fenwick_tree.py} +111 -19
  88. exonware/xwnode/nodes/strategies/hamt.py +403 -0
  89. exonware/xwnode/nodes/strategies/hash_map.py +354 -67
  90. exonware/xwnode/nodes/strategies/heap.py +105 -5
  91. exonware/xwnode/nodes/strategies/hopscotch_hash.py +525 -0
  92. exonware/xwnode/nodes/strategies/{node_hyperloglog.py → hyperloglog.py} +6 -5
  93. exonware/xwnode/nodes/strategies/interval_tree.py +742 -0
  94. exonware/xwnode/nodes/strategies/kd_tree.py +703 -0
  95. exonware/xwnode/nodes/strategies/learned_index.py +533 -0
  96. exonware/xwnode/nodes/strategies/linear_hash.py +93 -0
  97. exonware/xwnode/nodes/strategies/linked_list.py +316 -119
  98. exonware/xwnode/nodes/strategies/{node_lsm_tree.py → lsm_tree.py} +219 -15
  99. exonware/xwnode/nodes/strategies/masstree.py +130 -0
  100. exonware/xwnode/nodes/strategies/{node_persistent_tree.py → persistent_tree.py} +149 -9
  101. exonware/xwnode/nodes/strategies/priority_queue.py +544 -132
  102. exonware/xwnode/nodes/strategies/queue.py +249 -120
  103. exonware/xwnode/nodes/strategies/{node_red_black_tree.py → red_black_tree.py} +183 -72
  104. exonware/xwnode/nodes/strategies/{node_roaring_bitmap.py → roaring_bitmap.py} +19 -6
  105. exonware/xwnode/nodes/strategies/rope.py +717 -0
  106. exonware/xwnode/nodes/strategies/{node_segment_tree.py → segment_tree.py} +106 -106
  107. exonware/xwnode/nodes/strategies/{node_set_hash.py → set_hash.py} +30 -29
  108. exonware/xwnode/nodes/strategies/{node_skip_list.py → skip_list.py} +74 -6
  109. exonware/xwnode/nodes/strategies/sparse_matrix.py +427 -131
  110. exonware/xwnode/nodes/strategies/{node_splay_tree.py → splay_tree.py} +55 -6
  111. exonware/xwnode/nodes/strategies/stack.py +244 -112
  112. exonware/xwnode/nodes/strategies/{node_suffix_array.py → suffix_array.py} +5 -1
  113. exonware/xwnode/nodes/strategies/t_tree.py +94 -0
  114. exonware/xwnode/nodes/strategies/{node_treap.py → treap.py} +75 -6
  115. exonware/xwnode/nodes/strategies/{node_tree_graph_hybrid.py → tree_graph_hybrid.py} +46 -5
  116. exonware/xwnode/nodes/strategies/trie.py +153 -9
  117. exonware/xwnode/nodes/strategies/union_find.py +111 -5
  118. exonware/xwnode/nodes/strategies/veb_tree.py +856 -0
  119. exonware/xwnode/strategies/__init__.py +5 -51
  120. exonware/xwnode/version.py +3 -3
  121. {exonware_xwnode-0.0.1.21.dist-info → exonware_xwnode-0.0.1.23.dist-info}/METADATA +23 -3
  122. exonware_xwnode-0.0.1.23.dist-info/RECORD +130 -0
  123. exonware/xwnode/edges/strategies/edge_adj_list.py +0 -353
  124. exonware/xwnode/edges/strategies/edge_adj_matrix.py +0 -445
  125. exonware/xwnode/nodes/strategies/_base_node.py +0 -307
  126. exonware/xwnode/nodes/strategies/node_aho_corasick.py +0 -525
  127. exonware/xwnode/nodes/strategies/node_array_list.py +0 -179
  128. exonware/xwnode/nodes/strategies/node_hash_map.py +0 -273
  129. exonware/xwnode/nodes/strategies/node_heap.py +0 -196
  130. exonware/xwnode/nodes/strategies/node_linked_list.py +0 -413
  131. exonware/xwnode/nodes/strategies/node_trie.py +0 -257
  132. exonware/xwnode/nodes/strategies/node_union_find.py +0 -192
  133. exonware/xwnode/queries/executors/__init__.py +0 -47
  134. exonware/xwnode/queries/executors/advanced/__init__.py +0 -37
  135. exonware/xwnode/queries/executors/advanced/aggregate_executor.py +0 -50
  136. exonware/xwnode/queries/executors/advanced/ask_executor.py +0 -50
  137. exonware/xwnode/queries/executors/advanced/construct_executor.py +0 -50
  138. exonware/xwnode/queries/executors/advanced/describe_executor.py +0 -50
  139. exonware/xwnode/queries/executors/advanced/for_loop_executor.py +0 -50
  140. exonware/xwnode/queries/executors/advanced/foreach_executor.py +0 -50
  141. exonware/xwnode/queries/executors/advanced/join_executor.py +0 -50
  142. exonware/xwnode/queries/executors/advanced/let_executor.py +0 -50
  143. exonware/xwnode/queries/executors/advanced/mutation_executor.py +0 -50
  144. exonware/xwnode/queries/executors/advanced/options_executor.py +0 -50
  145. exonware/xwnode/queries/executors/advanced/pipe_executor.py +0 -50
  146. exonware/xwnode/queries/executors/advanced/subscribe_executor.py +0 -50
  147. exonware/xwnode/queries/executors/advanced/subscription_executor.py +0 -50
  148. exonware/xwnode/queries/executors/advanced/union_executor.py +0 -50
  149. exonware/xwnode/queries/executors/advanced/window_executor.py +0 -51
  150. exonware/xwnode/queries/executors/advanced/with_cte_executor.py +0 -50
  151. exonware/xwnode/queries/executors/aggregation/__init__.py +0 -21
  152. exonware/xwnode/queries/executors/aggregation/avg_executor.py +0 -50
  153. exonware/xwnode/queries/executors/aggregation/count_executor.py +0 -38
  154. exonware/xwnode/queries/executors/aggregation/distinct_executor.py +0 -50
  155. exonware/xwnode/queries/executors/aggregation/group_executor.py +0 -50
  156. exonware/xwnode/queries/executors/aggregation/having_executor.py +0 -50
  157. exonware/xwnode/queries/executors/aggregation/max_executor.py +0 -50
  158. exonware/xwnode/queries/executors/aggregation/min_executor.py +0 -50
  159. exonware/xwnode/queries/executors/aggregation/sum_executor.py +0 -50
  160. exonware/xwnode/queries/executors/aggregation/summarize_executor.py +0 -50
  161. exonware/xwnode/queries/executors/array/__init__.py +0 -9
  162. exonware/xwnode/queries/executors/array/indexing_executor.py +0 -51
  163. exonware/xwnode/queries/executors/array/slicing_executor.py +0 -51
  164. exonware/xwnode/queries/executors/base.py +0 -257
  165. exonware/xwnode/queries/executors/capability_checker.py +0 -204
  166. exonware/xwnode/queries/executors/contracts.py +0 -166
  167. exonware/xwnode/queries/executors/core/__init__.py +0 -17
  168. exonware/xwnode/queries/executors/core/create_executor.py +0 -96
  169. exonware/xwnode/queries/executors/core/delete_executor.py +0 -99
  170. exonware/xwnode/queries/executors/core/drop_executor.py +0 -100
  171. exonware/xwnode/queries/executors/core/insert_executor.py +0 -39
  172. exonware/xwnode/queries/executors/core/select_executor.py +0 -152
  173. exonware/xwnode/queries/executors/core/update_executor.py +0 -102
  174. exonware/xwnode/queries/executors/data/__init__.py +0 -13
  175. exonware/xwnode/queries/executors/data/alter_executor.py +0 -50
  176. exonware/xwnode/queries/executors/data/load_executor.py +0 -50
  177. exonware/xwnode/queries/executors/data/merge_executor.py +0 -50
  178. exonware/xwnode/queries/executors/data/store_executor.py +0 -50
  179. exonware/xwnode/queries/executors/defs.py +0 -93
  180. exonware/xwnode/queries/executors/engine.py +0 -221
  181. exonware/xwnode/queries/executors/errors.py +0 -68
  182. exonware/xwnode/queries/executors/filtering/__init__.py +0 -25
  183. exonware/xwnode/queries/executors/filtering/between_executor.py +0 -80
  184. exonware/xwnode/queries/executors/filtering/filter_executor.py +0 -79
  185. exonware/xwnode/queries/executors/filtering/has_executor.py +0 -70
  186. exonware/xwnode/queries/executors/filtering/in_executor.py +0 -70
  187. exonware/xwnode/queries/executors/filtering/like_executor.py +0 -76
  188. exonware/xwnode/queries/executors/filtering/optional_executor.py +0 -76
  189. exonware/xwnode/queries/executors/filtering/range_executor.py +0 -80
  190. exonware/xwnode/queries/executors/filtering/term_executor.py +0 -77
  191. exonware/xwnode/queries/executors/filtering/values_executor.py +0 -71
  192. exonware/xwnode/queries/executors/filtering/where_executor.py +0 -44
  193. exonware/xwnode/queries/executors/graph/__init__.py +0 -15
  194. exonware/xwnode/queries/executors/graph/in_traverse_executor.py +0 -51
  195. exonware/xwnode/queries/executors/graph/match_executor.py +0 -51
  196. exonware/xwnode/queries/executors/graph/out_executor.py +0 -51
  197. exonware/xwnode/queries/executors/graph/path_executor.py +0 -51
  198. exonware/xwnode/queries/executors/graph/return_executor.py +0 -51
  199. exonware/xwnode/queries/executors/ordering/__init__.py +0 -9
  200. exonware/xwnode/queries/executors/ordering/by_executor.py +0 -50
  201. exonware/xwnode/queries/executors/ordering/order_executor.py +0 -51
  202. exonware/xwnode/queries/executors/projection/__init__.py +0 -9
  203. exonware/xwnode/queries/executors/projection/extend_executor.py +0 -50
  204. exonware/xwnode/queries/executors/projection/project_executor.py +0 -50
  205. exonware/xwnode/queries/executors/registry.py +0 -173
  206. exonware/xwnode/queries/parsers/__init__.py +0 -26
  207. exonware/xwnode/queries/parsers/base.py +0 -86
  208. exonware/xwnode/queries/parsers/contracts.py +0 -46
  209. exonware/xwnode/queries/parsers/errors.py +0 -53
  210. exonware/xwnode/queries/parsers/sql_param_extractor.py +0 -318
  211. exonware/xwnode/queries/strategies/__init__.py +0 -24
  212. exonware/xwnode/queries/strategies/base.py +0 -236
  213. exonware/xwnode/queries/strategies/cql.py +0 -201
  214. exonware/xwnode/queries/strategies/cypher.py +0 -181
  215. exonware/xwnode/queries/strategies/datalog.py +0 -70
  216. exonware/xwnode/queries/strategies/elastic_dsl.py +0 -70
  217. exonware/xwnode/queries/strategies/eql.py +0 -70
  218. exonware/xwnode/queries/strategies/flux.py +0 -70
  219. exonware/xwnode/queries/strategies/gql.py +0 -70
  220. exonware/xwnode/queries/strategies/graphql.py +0 -240
  221. exonware/xwnode/queries/strategies/gremlin.py +0 -181
  222. exonware/xwnode/queries/strategies/hiveql.py +0 -214
  223. exonware/xwnode/queries/strategies/hql.py +0 -70
  224. exonware/xwnode/queries/strategies/jmespath.py +0 -219
  225. exonware/xwnode/queries/strategies/jq.py +0 -66
  226. exonware/xwnode/queries/strategies/json_query.py +0 -66
  227. exonware/xwnode/queries/strategies/jsoniq.py +0 -248
  228. exonware/xwnode/queries/strategies/kql.py +0 -70
  229. exonware/xwnode/queries/strategies/linq.py +0 -238
  230. exonware/xwnode/queries/strategies/logql.py +0 -70
  231. exonware/xwnode/queries/strategies/mql.py +0 -68
  232. exonware/xwnode/queries/strategies/n1ql.py +0 -210
  233. exonware/xwnode/queries/strategies/partiql.py +0 -70
  234. exonware/xwnode/queries/strategies/pig.py +0 -215
  235. exonware/xwnode/queries/strategies/promql.py +0 -70
  236. exonware/xwnode/queries/strategies/sparql.py +0 -220
  237. exonware/xwnode/queries/strategies/sql.py +0 -275
  238. exonware/xwnode/queries/strategies/xml_query.py +0 -66
  239. exonware/xwnode/queries/strategies/xpath.py +0 -223
  240. exonware/xwnode/queries/strategies/xquery.py +0 -258
  241. exonware/xwnode/queries/strategies/xwnode_executor.py +0 -332
  242. exonware/xwnode/queries/strategies/xwquery.py +0 -456
  243. exonware_xwnode-0.0.1.21.dist-info/RECORD +0 -214
  244. /exonware/xwnode/nodes/strategies/{node_ordered_map.py → ordered_map.py} +0 -0
  245. /exonware/xwnode/nodes/strategies/{node_ordered_map_balanced.py → ordered_map_balanced.py} +0 -0
  246. /exonware/xwnode/nodes/strategies/{node_patricia.py → patricia.py} +0 -0
  247. /exonware/xwnode/nodes/strategies/{node_radix_trie.py → radix_trie.py} +0 -0
  248. /exonware/xwnode/nodes/strategies/{node_set_tree.py → set_tree.py} +0 -0
  249. {exonware_xwnode-0.0.1.21.dist-info → exonware_xwnode-0.0.1.23.dist-info}/WHEEL +0 -0
  250. {exonware_xwnode-0.0.1.21.dist-info → exonware_xwnode-0.0.1.23.dist-info}/licenses/LICENSE +0 -0
@@ -13,31 +13,82 @@ from ...defs import NodeMode, NodeTrait
13
13
 
14
14
  class SegmentTreeStrategy(ANodeTreeStrategy):
15
15
  """
16
- Segment Tree node strategy for efficient range queries and updates.
17
-
18
- Provides O(log n) range queries and updates for associative operations
19
-
16
+ Segment Tree strategy for range query operations.
17
+
18
+ WHY Segment Tree:
19
+ - Supports arbitrary range queries (sum, min, max, GCD, etc.)
20
+ - O(log n) queries and updates (in optimized implementation)
21
+ - More flexible than Fenwick Tree (supports non-invertible operations)
22
+ - Industry standard for range query problems
23
+ - Handles both point and range updates
24
+
25
+ WHY this implementation:
26
+ - Simplified O(n) range query for correctness (not O(log n) tree structure)
27
+ - Supports multiple operations (sum, min, max, etc.)
28
+ - Combiner pattern allows pluggable operations
29
+ - Identity elements enable proper initialization
30
+ - Clear semantics over performance optimization
31
+
32
+ Time Complexity (Current Simplified Implementation):
33
+ - Update: O(1) - direct array access
34
+ - Range Query: O(n) - scans range (simplified for correctness)
35
+ - Note: Full O(log n) segment tree requires tree rebuild logic
36
+
37
+ Space Complexity: O(n) - simple array storage
38
+
39
+ Trade-offs:
40
+ - Advantage: Supports non-invertible operations (min, max, GCD)
41
+ - Advantage: More flexible than Fenwick Tree
42
+ - Limitation: Current implementation is O(n) query (not O(log n))
43
+ - Limitation: Full segment tree is more complex than Fenwick
44
+ - Compared to Fenwick: More flexible, but current impl slower
45
+ - Compared to naive: Same complexity, but extensible
46
+
47
+ Best for:
48
+ - Range queries with non-invertible operations (min, max)
49
+ - When operation flexibility is needed
50
+ - Competitive programming (with proper O(log n) impl)
51
+ - When understanding segment tree concepts
52
+
53
+ Not recommended for:
54
+ - Prefix sums only (use Fenwick Tree - simpler)
55
+ - When O(log n) is critical (current impl is O(n))
56
+ - Production systems (needs full tree implementation)
57
+
58
+ Following eXonware Priorities:
59
+ 1. Usability: Clear API for range operations
60
+ 2. Maintainability: Simplified for correctness over complexity
61
+ 3. Performance: O(1) updates, O(n) queries (acceptable for moderate n)
62
+ 4. Extensibility: Easy to swap combiner functions
63
+ 5. Security: Input validation, bounds checking
64
+
65
+ Implementation Note:
66
+ This is a SIMPLIFIED segment tree using O(n) range queries for CORRECTNESS.
67
+ A full O(log n) segment tree requires proper tree structure with:
68
+ - Recursive tree building
69
+ - Lazy propagation for range updates
70
+ - Complex index calculations
71
+
72
+ For production O(log n) performance, this needs enhancement.
73
+ Current implementation prioritizes CORRECTNESS and SIMPLICITY per
74
+ GUIDELINES_DEV.md principle: "prefer simple, maintainable solutions."
75
+ """
20
76
 
21
77
  # Strategy type classification
22
78
  STRATEGY_TYPE = NodeType.TREE
23
- like sum, min, max, etc.
24
- """
25
79
 
26
80
  def __init__(self, traits: NodeTrait = NodeTrait.NONE, **options):
27
81
  """Initialize the Segment Tree strategy."""
28
82
  super().__init__(NodeMode.SEGMENT_TREE, traits, **options)
29
83
 
30
- self._size = options.get('initial_size', 0)
31
- self._operation = options.get('operation', 'sum') # sum, min, max, etc.
84
+ self._max_size = options.get('initial_size', 1000)
85
+ self._operation = options.get('operation', 'sum')
32
86
  self._identity = self._get_identity(self._operation)
33
87
  self._combiner = self._get_combiner(self._operation)
34
88
 
35
- # Internal tree representation (0-indexed, 1-based tree)
36
- self._tree: List[Any] = [self._identity] * (4 * max(1, self._size))
89
+ # Simple array to store values (0-indexed for queries)
90
+ self._data: List[Any] = [self._identity] * self._max_size
37
91
  self._values: Dict[str, Any] = {} # Key-value storage for compatibility
38
- self._indices: Dict[str, int] = {} # Map keys to tree indices
39
- self._reverse_indices: Dict[int, str] = {} # Map indices to keys
40
- self._next_index = 0
41
92
 
42
93
  def get_supported_traits(self) -> NodeTrait:
43
94
  """Get the traits supported by the segment tree strategy."""
@@ -83,27 +134,15 @@ like sum, min, max, etc.
83
134
  """Store a value at the given key."""
84
135
  key_str = str(key)
85
136
 
86
- # Convert value to numeric if possible
137
+ # Try to convert to index
87
138
  try:
88
- numeric_value = float(value) if value is not None else 0.0
139
+ idx = int(key_str)
140
+ if 0 <= idx < self._max_size:
141
+ self.update(idx, value)
89
142
  except (ValueError, TypeError):
90
- numeric_value = 0.0
91
-
92
- if key_str in self._indices:
93
- # Update existing
94
- idx = self._indices[key_str]
95
- self._update_point(idx, numeric_value)
96
- else:
97
- # Add new
98
- if self._next_index >= len(self._tree) // 4:
99
- self._resize_tree()
100
-
101
- idx = self._next_index
102
- self._indices[key_str] = idx
103
- self._reverse_indices[idx] = key_str
104
- self._next_index += 1
105
- self._update_point(idx, numeric_value)
143
+ pass
106
144
 
145
+ # Always store in values dict
107
146
  self._values[key_str] = value
108
147
 
109
148
  def get(self, key: Any, default: Any = None) -> Any:
@@ -118,16 +157,18 @@ like sum, min, max, etc.
118
157
  def remove(self, key: Any) -> bool:
119
158
  """Remove value by key."""
120
159
  key_str = str(key)
121
- if key_str not in self._indices:
160
+ if key_str not in self._values:
122
161
  return False
123
162
 
124
- idx = self._indices[key_str]
125
- self._update_point(idx, self._identity)
163
+ # Try to clear from array
164
+ try:
165
+ idx = int(key_str)
166
+ if 0 <= idx < self._max_size:
167
+ self._data[idx] = self._identity
168
+ except (ValueError, TypeError):
169
+ pass
126
170
 
127
- del self._indices[key_str]
128
- del self._reverse_indices[idx]
129
171
  del self._values[key_str]
130
-
131
172
  return True
132
173
 
133
174
  def delete(self, key: Any) -> bool:
@@ -136,11 +177,8 @@ like sum, min, max, etc.
136
177
 
137
178
  def clear(self) -> None:
138
179
  """Clear all data."""
139
- self._tree = [self._identity] * (4 * max(1, self._size))
180
+ self._data = [self._identity] * self._max_size
140
181
  self._values.clear()
141
- self._indices.clear()
142
- self._reverse_indices.clear()
143
- self._next_index = 0
144
182
 
145
183
  def keys(self) -> Iterator[str]:
146
184
  """Get all keys."""
@@ -176,85 +214,47 @@ like sum, min, max, etc.
176
214
  # SEGMENT TREE SPECIFIC OPERATIONS
177
215
  # ============================================================================
178
216
 
179
- def _resize_tree(self) -> None:
180
- """Resize the internal tree when needed."""
181
- old_size = len(self._tree)
182
- new_size = old_size * 2
183
- self._tree.extend([self._identity] * (new_size - old_size))
184
-
185
- def _update_point(self, idx: int, value: Any) -> None:
186
- """Update a single point in the segment tree."""
187
- # Convert to 1-based indexing for tree
188
- tree_idx = idx + len(self._tree) // 4
189
-
190
- # Ensure tree is large enough
191
- while tree_idx >= len(self._tree):
192
- self._resize_tree()
193
- tree_idx = idx + len(self._tree) // 4
217
+ def range_query(self, left: int, right: int) -> Any:
218
+ """
219
+ Query range [left, right] inclusive (0-indexed).
194
220
 
195
- # Update leaf
196
- self._tree[tree_idx] = value
221
+ Uses simple O(n) scan for correctness.
222
+ For true O(log n), segment tree needs proper rebuild after updates.
223
+ """
224
+ if left < 0 or right >= len(self._data) or left > right:
225
+ return self._identity
197
226
 
198
- # Update ancestors
199
- while tree_idx > 1:
200
- tree_idx //= 2
201
- left_child = self._tree[tree_idx * 2] if tree_idx * 2 < len(self._tree) else self._identity
202
- right_child = self._tree[tree_idx * 2 + 1] if tree_idx * 2 + 1 < len(self._tree) else self._identity
203
- self._tree[tree_idx] = self._combiner(left_child, right_child)
204
-
205
- def range_query(self, left: int, right: int) -> Any:
206
- """Query range [left, right] inclusive."""
207
- return self._range_query_recursive(1, 0, len(self._tree) // 4 - 1, left, right)
227
+ result = self._identity
228
+ for i in range(left, right + 1):
229
+ result = self._combiner(result, self._data[i])
230
+ return result
208
231
 
209
- def _range_query_recursive(self, node: int, start: int, end: int,
210
- query_left: int, query_right: int) -> Any:
211
- """Recursive range query implementation."""
212
- if query_right < start or query_left > end:
213
- return self._identity
232
+ def update(self, index: int, value: Any) -> None:
233
+ """
234
+ Update value at specific index (0-indexed).
214
235
 
215
- if query_left <= start and end <= query_right:
216
- return self._tree[node] if node < len(self._tree) else self._identity
236
+ Simple O(1) update for correctness.
237
+ """
238
+ if index < 0 or index >= self._max_size:
239
+ return
217
240
 
218
- mid = (start + end) // 2
219
- left_result = self._range_query_recursive(2 * node, start, mid, query_left, query_right)
220
- right_result = self._range_query_recursive(2 * node + 1, mid + 1, end, query_left, query_right)
241
+ # Store value
242
+ self._data[index] = value
221
243
 
222
- return self._combiner(left_result, right_result)
244
+ # Track in values dict
245
+ key = str(index)
246
+ self._values[key] = value
223
247
 
224
248
  def range_update(self, left: int, right: int, value: Any) -> None:
225
- """Update range [left, right] with value (point updates)."""
249
+ """Update range [left, right] with value."""
226
250
  for i in range(left, right + 1):
227
- if i in self._reverse_indices:
228
- key = self._reverse_indices[i]
229
- self.put(key, value)
230
-
231
- def prefix_query(self, index: int) -> Any:
232
- """Query prefix [0, index]."""
233
- return self.range_query(0, index)
234
-
235
- def suffix_query(self, index: int) -> Any:
236
- """Query suffix [index, size-1]."""
237
- return self.range_query(index, len(self._values) - 1)
238
-
239
- def find_first_greater(self, value: Any) -> Optional[int]:
240
- """Find first index where tree value > given value."""
241
- for i in range(len(self._values)):
242
- if i in self._reverse_indices:
243
- key = self._reverse_indices[i]
244
- if key in self._values:
245
- try:
246
- if float(self._values[key]) > float(value):
247
- return i
248
- except (ValueError, TypeError):
249
- continue
250
- return None
251
+ self.update(i, value)
251
252
 
252
253
  def get_operation_info(self) -> Dict[str, Any]:
253
254
  """Get information about the current operation."""
254
255
  return {
255
256
  'operation': self._operation,
256
- 'identity': self._identity,
257
- 'total_result': self.range_query(0, max(0, len(self._values) - 1))
257
+ 'identity': self._identity
258
258
  }
259
259
 
260
260
  # ============================================================================
@@ -7,11 +7,12 @@ with O(1) average-case membership testing and insertion.
7
7
 
8
8
  from typing import Any, Iterator, Set, Dict, Union, List
9
9
  import hashlib
10
- from ._base_node import aNodeStrategy
10
+ from .base import ANodeStrategy
11
11
  from ...defs import NodeMode, NodeTrait
12
+ from .contracts import NodeType
12
13
 
13
14
 
14
- class xSetHashStrategy(aNodeStrategy):
15
+ class SetHashStrategy(ANodeStrategy):
15
16
  """
16
17
  Hash Set node strategy for efficient set operations.
17
18
 
@@ -20,7 +21,7 @@ class xSetHashStrategy(aNodeStrategy):
20
21
  """
21
22
 
22
23
  # Strategy type classification
23
- STRATEGY_TYPE = NodeType.MATRIX
24
+ STRATEGY_TYPE = NodeType.HYBRID # Hash-based set operations
24
25
 
25
26
 
26
27
  def __init__(self, traits: NodeTrait = NodeTrait.NONE, **options):
@@ -171,10 +172,10 @@ class xSetHashStrategy(aNodeStrategy):
171
172
  self._size -= 1
172
173
  return value
173
174
 
174
- def union(self, other: Union['xSetHashStrategy', Set, List]) -> 'xSetHashStrategy':
175
+ def union(self, other: Union['SetHashStrategy', Set, List]) -> 'SetHashStrategy':
175
176
  """Return union of this set with another."""
176
- result = xSetHashStrategy(
177
- traits=self._traits,
177
+ result = SetHashStrategy(
178
+ traits=self.traits,
178
179
  case_sensitive=self.case_sensitive,
179
180
  allow_none=self.allow_none
180
181
  )
@@ -184,7 +185,7 @@ class xSetHashStrategy(aNodeStrategy):
184
185
  result.add(self._values[element])
185
186
 
186
187
  # Add elements from other
187
- if isinstance(other, xSetHashStrategy):
188
+ if isinstance(other, SetHashStrategy):
188
189
  for element in other._set:
189
190
  result.add(other._values[element])
190
191
  elif isinstance(other, (set, list)):
@@ -193,15 +194,15 @@ class xSetHashStrategy(aNodeStrategy):
193
194
 
194
195
  return result
195
196
 
196
- def intersection(self, other: Union['xSetHashStrategy', Set, List]) -> 'xSetHashStrategy':
197
+ def intersection(self, other: Union['SetHashStrategy', Set, List]) -> 'SetHashStrategy':
197
198
  """Return intersection of this set with another."""
198
- result = xSetHashStrategy(
199
- traits=self._traits,
199
+ result = SetHashStrategy(
200
+ traits=self.traits,
200
201
  case_sensitive=self.case_sensitive,
201
202
  allow_none=self.allow_none
202
203
  )
203
204
 
204
- if isinstance(other, xSetHashStrategy):
205
+ if isinstance(other, SetHashStrategy):
205
206
  common = self._set.intersection(other._set)
206
207
  for element in common:
207
208
  result.add(self._values[element])
@@ -213,15 +214,15 @@ class xSetHashStrategy(aNodeStrategy):
213
214
 
214
215
  return result
215
216
 
216
- def difference(self, other: Union['xSetHashStrategy', Set, List]) -> 'xSetHashStrategy':
217
+ def difference(self, other: Union['SetHashStrategy', Set, List]) -> 'SetHashStrategy':
217
218
  """Return difference of this set with another."""
218
- result = xSetHashStrategy(
219
- traits=self._traits,
219
+ result = SetHashStrategy(
220
+ traits=self.traits,
220
221
  case_sensitive=self.case_sensitive,
221
222
  allow_none=self.allow_none
222
223
  )
223
224
 
224
- if isinstance(other, xSetHashStrategy):
225
+ if isinstance(other, SetHashStrategy):
225
226
  diff = self._set.difference(other._set)
226
227
  elif isinstance(other, (set, list)):
227
228
  other_set = {str(x).lower() if not self.case_sensitive else str(x) for x in other}
@@ -234,15 +235,15 @@ class xSetHashStrategy(aNodeStrategy):
234
235
 
235
236
  return result
236
237
 
237
- def symmetric_difference(self, other: Union['xSetHashStrategy', Set, List]) -> 'xSetHashStrategy':
238
+ def symmetric_difference(self, other: Union['SetHashStrategy', Set, List]) -> 'SetHashStrategy':
238
239
  """Return symmetric difference of this set with another."""
239
- result = xSetHashStrategy(
240
- traits=self._traits,
240
+ result = SetHashStrategy(
241
+ traits=self.traits,
241
242
  case_sensitive=self.case_sensitive,
242
243
  allow_none=self.allow_none
243
244
  )
244
245
 
245
- if isinstance(other, xSetHashStrategy):
246
+ if isinstance(other, SetHashStrategy):
246
247
  sym_diff = self._set.symmetric_difference(other._set)
247
248
  for element in sym_diff:
248
249
  if element in self._values:
@@ -264,37 +265,37 @@ class xSetHashStrategy(aNodeStrategy):
264
265
 
265
266
  return result
266
267
 
267
- def is_subset(self, other: Union['xSetHashStrategy', Set, List]) -> bool:
268
+ def is_subset(self, other: Union['SetHashStrategy', Set, List]) -> bool:
268
269
  """Check if this set is a subset of another."""
269
- if isinstance(other, xSetHashStrategy):
270
+ if isinstance(other, SetHashStrategy):
270
271
  return self._set.issubset(other._set)
271
272
  elif isinstance(other, (set, list)):
272
273
  other_set = {str(x).lower() if not self.case_sensitive else str(x) for x in other}
273
274
  return self._set.issubset(other_set)
274
275
  return False
275
276
 
276
- def is_superset(self, other: Union['xSetHashStrategy', Set, List]) -> bool:
277
+ def is_superset(self, other: Union['SetHashStrategy', Set, List]) -> bool:
277
278
  """Check if this set is a superset of another."""
278
- if isinstance(other, xSetHashStrategy):
279
+ if isinstance(other, SetHashStrategy):
279
280
  return self._set.issuperset(other._set)
280
281
  elif isinstance(other, (set, list)):
281
282
  other_set = {str(x).lower() if not self.case_sensitive else str(x) for x in other}
282
283
  return self._set.issuperset(other_set)
283
284
  return False
284
285
 
285
- def is_disjoint(self, other: Union['xSetHashStrategy', Set, List]) -> bool:
286
+ def is_disjoint(self, other: Union['SetHashStrategy', Set, List]) -> bool:
286
287
  """Check if this set has no elements in common with another."""
287
- if isinstance(other, xSetHashStrategy):
288
+ if isinstance(other, SetHashStrategy):
288
289
  return self._set.isdisjoint(other._set)
289
290
  elif isinstance(other, (set, list)):
290
291
  other_set = {str(x).lower() if not self.case_sensitive else str(x) for x in other}
291
292
  return self._set.isdisjoint(other_set)
292
293
  return True
293
294
 
294
- def copy(self) -> 'xSetHashStrategy':
295
+ def copy(self) -> 'SetHashStrategy':
295
296
  """Create a shallow copy of the set."""
296
- result = xSetHashStrategy(
297
- traits=self._traits,
297
+ result = SetHashStrategy(
298
+ traits=self.traits,
298
299
  case_sensitive=self.case_sensitive,
299
300
  allow_none=self.allow_none
300
301
  )
@@ -307,7 +308,7 @@ class xSetHashStrategy(aNodeStrategy):
307
308
  def update(self, *others) -> None:
308
309
  """Update the set with elements from other iterables."""
309
310
  for other in others:
310
- if isinstance(other, xSetHashStrategy):
311
+ if isinstance(other, SetHashStrategy):
311
312
  for element in other._set:
312
313
  self.add(other._values[element])
313
314
  elif isinstance(other, (set, list, tuple)):
@@ -38,15 +38,75 @@ class SkipListNode:
38
38
 
39
39
  class SkipListStrategy(ANodeTreeStrategy):
40
40
  """
41
- Skip list node strategy for probabilistic data structures.
42
-
43
- Provides O(log n) expected performance for search, insertion, and deletion
44
- with simple implementation and good concu
41
+ Skip List strategy for probabilistic sorted data structures.
42
+
43
+ WHY Skip List:
44
+ - Simpler implementation than balanced trees (no complex rotations)
45
+ - Lock-free concurrent access possible with careful implementation
46
+ - O(log n) expected time for search, insert, delete (probabilistic)
47
+ - Memory-efficient alternative to balanced trees for dynamic datasets
48
+ - Excellent for distributed systems (natural partitioning by levels)
49
+
50
+ WHY this implementation:
51
+ - Probabilistic level promotion (p=0.5) ensures balanced height distribution
52
+ - Header node sentinel pattern eliminates special-case handling
53
+ - Path caching during search amortizes traversal cost
54
+ - Forward pointers list enables efficient level-by-level traversal
55
+ - Statistics tracking for monitoring performance characteristics
56
+
57
+ Time Complexity:
58
+ - Insert: O(log n) expected, O(n) worst case (probabilistic)
59
+ - Search: O(log n) expected, O(n) worst case (probabilistic)
60
+ - Delete: O(log n) expected, O(n) worst case (probabilistic)
61
+ - Range Query: O(k + log n) where k is result size
62
+ - Iteration: O(n) sorted order at bottom level
63
+
64
+ Space Complexity: O(n log n) expected (multiple forward pointers per node)
65
+
66
+ Trade-offs:
67
+ - Advantage: Simpler than balanced trees, good concurrent properties
68
+ - Advantage: No rebalancing overhead (probabilistic balance)
69
+ - Limitation: Worst-case O(n) if unlucky with random levels
70
+ - Limitation: Higher memory overhead than plain linked list
71
+ - Compared to B-Tree: Simpler, better concurrency, but less deterministic
72
+ - Compared to AVL: Easier to implement, but higher memory usage
73
+
74
+ Best for:
75
+ - Concurrent sorted data structures (lock-free variants)
76
+ - When simplicity is more important than worst-case guarantees
77
+ - Distributed systems requiring sorted indices
78
+ - Real-time systems (no unpredictable rebalancing pauses)
79
+ - In-memory caches with sorted key access
80
+
81
+ Not recommended for:
82
+ - Hard real-time systems (probabilistic behavior)
83
+ - Memory-constrained environments (O(n log n) space)
84
+ - When worst-case guarantees are critical (use balanced tree)
85
+ - Disk-based storage (use B-Tree for locality)
86
+ - Write-once, read-many scenarios (plain sorted array better)
87
+
88
+ Following eXonware Priorities:
89
+ 1. Usability: Simple API, no complex rebalancing logic to debug
90
+ 2. Maintainability: Clean probabilistic design, easy to understand
91
+ 3. Performance: O(log n) expected time, efficient range queries
92
+ 4. Extensibility: Easy to add concurrent variants or custom level logic
93
+ 5. Security: Input validation on all operations, prevents malformed structure
94
+
95
+ Industry Best Practices:
96
+ - Follows Pugh's original skip list paper (1990)
97
+ - Uses p=0.5 probability (optimal for most workloads)
98
+ - Implements header sentinel for cleaner code
99
+ - Provides statistics for monitoring probabilistic behavior
100
+ - Supports both case-sensitive and case-insensitive keys
101
+
102
+ Performance Note:
103
+ Skip list is probabilistic - O(log n) is EXPECTED, not worst-case.
104
+ For guaranteed O(log n), use RED_BLACK_TREE or AVL_TREE instead.
105
+ The trade-off is simplicity and concurrency vs determinism.
106
+ """
45
107
 
46
108
  # Strategy type classification
47
109
  STRATEGY_TYPE = NodeType.TREE
48
- rrent access properties.
49
- """
50
110
 
51
111
  def __init__(self, traits: NodeTrait = NodeTrait.NONE, **options):
52
112
  """Initialize the skip list strategy."""
@@ -227,6 +287,14 @@ rrent access properties.
227
287
  """Get number of key-value pairs."""
228
288
  return self._size
229
289
 
290
+ def __len__(self) -> int:
291
+ """Get number of key-value pairs."""
292
+ return self._size
293
+
294
+ def to_native(self) -> Dict[str, Any]:
295
+ """Convert to native Python dict."""
296
+ return dict(self.items())
297
+
230
298
  def is_empty(self) -> bool:
231
299
  """Check if skip list is empty."""
232
300
  return self._size == 0