exonware-xwnode 0.0.1.12__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 (132) hide show
  1. exonware/__init__.py +14 -0
  2. exonware/xwnode/__init__.py +127 -0
  3. exonware/xwnode/base.py +676 -0
  4. exonware/xwnode/config.py +178 -0
  5. exonware/xwnode/contracts.py +730 -0
  6. exonware/xwnode/errors.py +503 -0
  7. exonware/xwnode/facade.py +460 -0
  8. exonware/xwnode/strategies/__init__.py +158 -0
  9. exonware/xwnode/strategies/advisor.py +463 -0
  10. exonware/xwnode/strategies/edges/__init__.py +32 -0
  11. exonware/xwnode/strategies/edges/adj_list.py +227 -0
  12. exonware/xwnode/strategies/edges/adj_matrix.py +391 -0
  13. exonware/xwnode/strategies/edges/base.py +169 -0
  14. exonware/xwnode/strategies/flyweight.py +328 -0
  15. exonware/xwnode/strategies/impls/__init__.py +13 -0
  16. exonware/xwnode/strategies/impls/_base_edge.py +403 -0
  17. exonware/xwnode/strategies/impls/_base_node.py +307 -0
  18. exonware/xwnode/strategies/impls/edge_adj_list.py +353 -0
  19. exonware/xwnode/strategies/impls/edge_adj_matrix.py +445 -0
  20. exonware/xwnode/strategies/impls/edge_bidir_wrapper.py +455 -0
  21. exonware/xwnode/strategies/impls/edge_block_adj_matrix.py +539 -0
  22. exonware/xwnode/strategies/impls/edge_coo.py +533 -0
  23. exonware/xwnode/strategies/impls/edge_csc.py +447 -0
  24. exonware/xwnode/strategies/impls/edge_csr.py +492 -0
  25. exonware/xwnode/strategies/impls/edge_dynamic_adj_list.py +503 -0
  26. exonware/xwnode/strategies/impls/edge_flow_network.py +555 -0
  27. exonware/xwnode/strategies/impls/edge_hyperedge_set.py +516 -0
  28. exonware/xwnode/strategies/impls/edge_neural_graph.py +650 -0
  29. exonware/xwnode/strategies/impls/edge_octree.py +574 -0
  30. exonware/xwnode/strategies/impls/edge_property_store.py +655 -0
  31. exonware/xwnode/strategies/impls/edge_quadtree.py +519 -0
  32. exonware/xwnode/strategies/impls/edge_rtree.py +820 -0
  33. exonware/xwnode/strategies/impls/edge_temporal_edgeset.py +558 -0
  34. exonware/xwnode/strategies/impls/edge_tree_graph_basic.py +271 -0
  35. exonware/xwnode/strategies/impls/edge_weighted_graph.py +411 -0
  36. exonware/xwnode/strategies/manager.py +775 -0
  37. exonware/xwnode/strategies/metrics.py +538 -0
  38. exonware/xwnode/strategies/migration.py +432 -0
  39. exonware/xwnode/strategies/nodes/__init__.py +50 -0
  40. exonware/xwnode/strategies/nodes/_base_node.py +307 -0
  41. exonware/xwnode/strategies/nodes/adjacency_list.py +267 -0
  42. exonware/xwnode/strategies/nodes/aho_corasick.py +345 -0
  43. exonware/xwnode/strategies/nodes/array_list.py +209 -0
  44. exonware/xwnode/strategies/nodes/base.py +247 -0
  45. exonware/xwnode/strategies/nodes/deque.py +200 -0
  46. exonware/xwnode/strategies/nodes/hash_map.py +135 -0
  47. exonware/xwnode/strategies/nodes/heap.py +307 -0
  48. exonware/xwnode/strategies/nodes/linked_list.py +232 -0
  49. exonware/xwnode/strategies/nodes/node_aho_corasick.py +520 -0
  50. exonware/xwnode/strategies/nodes/node_array_list.py +175 -0
  51. exonware/xwnode/strategies/nodes/node_avl_tree.py +371 -0
  52. exonware/xwnode/strategies/nodes/node_b_plus_tree.py +542 -0
  53. exonware/xwnode/strategies/nodes/node_bitmap.py +420 -0
  54. exonware/xwnode/strategies/nodes/node_bitset_dynamic.py +513 -0
  55. exonware/xwnode/strategies/nodes/node_bloom_filter.py +347 -0
  56. exonware/xwnode/strategies/nodes/node_btree.py +357 -0
  57. exonware/xwnode/strategies/nodes/node_count_min_sketch.py +470 -0
  58. exonware/xwnode/strategies/nodes/node_cow_tree.py +473 -0
  59. exonware/xwnode/strategies/nodes/node_cuckoo_hash.py +392 -0
  60. exonware/xwnode/strategies/nodes/node_fenwick_tree.py +301 -0
  61. exonware/xwnode/strategies/nodes/node_hash_map.py +269 -0
  62. exonware/xwnode/strategies/nodes/node_heap.py +191 -0
  63. exonware/xwnode/strategies/nodes/node_hyperloglog.py +407 -0
  64. exonware/xwnode/strategies/nodes/node_linked_list.py +409 -0
  65. exonware/xwnode/strategies/nodes/node_lsm_tree.py +400 -0
  66. exonware/xwnode/strategies/nodes/node_ordered_map.py +390 -0
  67. exonware/xwnode/strategies/nodes/node_ordered_map_balanced.py +565 -0
  68. exonware/xwnode/strategies/nodes/node_patricia.py +512 -0
  69. exonware/xwnode/strategies/nodes/node_persistent_tree.py +378 -0
  70. exonware/xwnode/strategies/nodes/node_radix_trie.py +452 -0
  71. exonware/xwnode/strategies/nodes/node_red_black_tree.py +497 -0
  72. exonware/xwnode/strategies/nodes/node_roaring_bitmap.py +570 -0
  73. exonware/xwnode/strategies/nodes/node_segment_tree.py +289 -0
  74. exonware/xwnode/strategies/nodes/node_set_hash.py +354 -0
  75. exonware/xwnode/strategies/nodes/node_set_tree.py +480 -0
  76. exonware/xwnode/strategies/nodes/node_skip_list.py +316 -0
  77. exonware/xwnode/strategies/nodes/node_splay_tree.py +393 -0
  78. exonware/xwnode/strategies/nodes/node_suffix_array.py +487 -0
  79. exonware/xwnode/strategies/nodes/node_treap.py +387 -0
  80. exonware/xwnode/strategies/nodes/node_tree_graph_hybrid.py +1434 -0
  81. exonware/xwnode/strategies/nodes/node_trie.py +252 -0
  82. exonware/xwnode/strategies/nodes/node_union_find.py +187 -0
  83. exonware/xwnode/strategies/nodes/node_xdata_optimized.py +369 -0
  84. exonware/xwnode/strategies/nodes/priority_queue.py +209 -0
  85. exonware/xwnode/strategies/nodes/queue.py +161 -0
  86. exonware/xwnode/strategies/nodes/sparse_matrix.py +206 -0
  87. exonware/xwnode/strategies/nodes/stack.py +152 -0
  88. exonware/xwnode/strategies/nodes/trie.py +274 -0
  89. exonware/xwnode/strategies/nodes/union_find.py +283 -0
  90. exonware/xwnode/strategies/pattern_detector.py +603 -0
  91. exonware/xwnode/strategies/performance_monitor.py +487 -0
  92. exonware/xwnode/strategies/queries/__init__.py +24 -0
  93. exonware/xwnode/strategies/queries/base.py +236 -0
  94. exonware/xwnode/strategies/queries/cql.py +201 -0
  95. exonware/xwnode/strategies/queries/cypher.py +181 -0
  96. exonware/xwnode/strategies/queries/datalog.py +70 -0
  97. exonware/xwnode/strategies/queries/elastic_dsl.py +70 -0
  98. exonware/xwnode/strategies/queries/eql.py +70 -0
  99. exonware/xwnode/strategies/queries/flux.py +70 -0
  100. exonware/xwnode/strategies/queries/gql.py +70 -0
  101. exonware/xwnode/strategies/queries/graphql.py +240 -0
  102. exonware/xwnode/strategies/queries/gremlin.py +181 -0
  103. exonware/xwnode/strategies/queries/hiveql.py +214 -0
  104. exonware/xwnode/strategies/queries/hql.py +70 -0
  105. exonware/xwnode/strategies/queries/jmespath.py +219 -0
  106. exonware/xwnode/strategies/queries/jq.py +66 -0
  107. exonware/xwnode/strategies/queries/json_query.py +66 -0
  108. exonware/xwnode/strategies/queries/jsoniq.py +248 -0
  109. exonware/xwnode/strategies/queries/kql.py +70 -0
  110. exonware/xwnode/strategies/queries/linq.py +238 -0
  111. exonware/xwnode/strategies/queries/logql.py +70 -0
  112. exonware/xwnode/strategies/queries/mql.py +68 -0
  113. exonware/xwnode/strategies/queries/n1ql.py +210 -0
  114. exonware/xwnode/strategies/queries/partiql.py +70 -0
  115. exonware/xwnode/strategies/queries/pig.py +215 -0
  116. exonware/xwnode/strategies/queries/promql.py +70 -0
  117. exonware/xwnode/strategies/queries/sparql.py +220 -0
  118. exonware/xwnode/strategies/queries/sql.py +275 -0
  119. exonware/xwnode/strategies/queries/xml_query.py +66 -0
  120. exonware/xwnode/strategies/queries/xpath.py +223 -0
  121. exonware/xwnode/strategies/queries/xquery.py +258 -0
  122. exonware/xwnode/strategies/queries/xwnode_executor.py +332 -0
  123. exonware/xwnode/strategies/queries/xwquery_strategy.py +424 -0
  124. exonware/xwnode/strategies/registry.py +604 -0
  125. exonware/xwnode/strategies/simple.py +273 -0
  126. exonware/xwnode/strategies/utils.py +532 -0
  127. exonware/xwnode/types.py +912 -0
  128. exonware/xwnode/version.py +78 -0
  129. exonware_xwnode-0.0.1.12.dist-info/METADATA +169 -0
  130. exonware_xwnode-0.0.1.12.dist-info/RECORD +132 -0
  131. exonware_xwnode-0.0.1.12.dist-info/WHEEL +4 -0
  132. exonware_xwnode-0.0.1.12.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,252 @@
1
+ """
2
+ Trie Node Strategy Implementation
3
+
4
+ This module implements the TRIE strategy for efficient string prefix operations.
5
+ """
6
+
7
+ from typing import Any, Iterator, Dict, List, Optional
8
+ from .base import ANodeTreeStrategy
9
+ from ...types import NodeMode, NodeTrait
10
+ from ..utils import (
11
+ TrieNode,
12
+ safe_to_native_conversion,
13
+ create_basic_metrics,
14
+ create_basic_backend_info,
15
+ create_size_tracker,
16
+ create_access_tracker,
17
+ update_size_tracker,
18
+ record_access,
19
+ get_access_metrics
20
+ )
21
+
22
+
23
+ class TrieStrategy(ANodeTreeStrategy):
24
+ """
25
+ Trie node strategy for efficient string prefix operations.
26
+
27
+ Optimized for prefix matching, autocomplete, and string searching.
28
+ """
29
+
30
+ def __init__(self, traits: NodeTrait = NodeTrait.NONE, **options):
31
+ """Initialize the trie strategy."""
32
+ super().__init__(NodeMode.TRIE, traits, **options)
33
+ self._root = TrieNode()
34
+ self._size_tracker = create_size_tracker()
35
+ self._access_tracker = create_access_tracker()
36
+
37
+ def get_supported_traits(self) -> NodeTrait:
38
+ """Get the traits supported by the trie strategy."""
39
+ return (NodeTrait.ORDERED | NodeTrait.HIERARCHICAL | NodeTrait.INDEXED)
40
+
41
+ # ============================================================================
42
+ # CORE OPERATIONS
43
+ # ============================================================================
44
+
45
+ def put(self, key: Any, value: Any = None) -> None:
46
+ """Store a key-value pair (key should be string-like)."""
47
+ word = str(key)
48
+ node = self._root
49
+
50
+ # Traverse/create path
51
+ for char in word:
52
+ if char not in node.children:
53
+ node.children[char] = TrieNode()
54
+ node = node.children[char]
55
+
56
+ # Mark end and store value
57
+ if not node.is_end_word:
58
+ update_size_tracker(self._size_tracker, 1)
59
+ node.is_end_word = True
60
+ node.value = value
61
+ record_access(self._access_tracker, 'put_count')
62
+
63
+ def get(self, key: Any, default: Any = None) -> Any:
64
+ """Retrieve a value by key."""
65
+ word = str(key)
66
+ node = self._find_node(word)
67
+ record_access(self._access_tracker, 'get_count')
68
+ if node and node.is_end_word:
69
+ return node.value
70
+ return default
71
+
72
+ def has(self, key: Any) -> bool:
73
+ """Check if key exists."""
74
+ word = str(key)
75
+ node = self._find_node(word)
76
+ return node is not None and node.is_end_word
77
+
78
+ def remove(self, key: Any) -> bool:
79
+ """Remove a key-value pair."""
80
+ word = str(key)
81
+ result = self._remove_recursive(self._root, word, 0)
82
+ if result:
83
+ update_size_tracker(self._size_tracker, -1)
84
+ record_access(self._access_tracker, 'delete_count')
85
+ return result
86
+
87
+ def delete(self, key: Any) -> bool:
88
+ """Remove a key-value pair (alias for remove)."""
89
+ return self.remove(key)
90
+
91
+ def clear(self) -> None:
92
+ """Clear all data."""
93
+ self._root = TrieNode()
94
+ self._size_tracker['size'] = 0
95
+
96
+ def keys(self) -> Iterator[str]:
97
+ """Get all keys."""
98
+ return iter(self._collect_words())
99
+
100
+ def values(self) -> Iterator[Any]:
101
+ """Get all values."""
102
+ words = self._collect_words()
103
+ for word in words:
104
+ node = self._find_node(word)
105
+ if node:
106
+ yield node.value
107
+
108
+ def items(self) -> Iterator[tuple[str, Any]]:
109
+ """Get all key-value pairs."""
110
+ words = self._collect_words()
111
+ for word in words:
112
+ node = self._find_node(word)
113
+ if node:
114
+ yield (word, node.value)
115
+
116
+ def __len__(self) -> int:
117
+ """Get the number of items."""
118
+ return self._size_tracker['size']
119
+
120
+ def to_native(self) -> Dict[str, Any]:
121
+ """Convert to native Python dictionary."""
122
+ result = {}
123
+ for word in self._collect_words():
124
+ node = self._find_node(word)
125
+ if node:
126
+ result[word] = safe_to_native_conversion(node.value)
127
+ return result
128
+
129
+ @property
130
+ def is_list(self) -> bool:
131
+ """This is not a list strategy."""
132
+ return False
133
+
134
+ @property
135
+ def is_dict(self) -> bool:
136
+ """This behaves like a dict with string keys."""
137
+ return True
138
+
139
+ # ============================================================================
140
+ # TRIE-SPECIFIC OPERATIONS
141
+ # ============================================================================
142
+
143
+ def starts_with(self, prefix: str) -> List[str]:
144
+ """Get all keys that start with the given prefix."""
145
+ node = self._find_node(prefix)
146
+ if not node:
147
+ return []
148
+
149
+ words = []
150
+ self._collect_words_from_node(node, prefix, words)
151
+ return words
152
+
153
+ def longest_common_prefix(self) -> str:
154
+ """Find the longest common prefix of all stored keys."""
155
+ if not self._root.children:
156
+ return ""
157
+
158
+ prefix = ""
159
+ node = self._root
160
+
161
+ while len(node.children) == 1 and not node.is_end_word:
162
+ char = next(iter(node.children.keys()))
163
+ prefix += char
164
+ node = node.children[char]
165
+
166
+ return prefix
167
+
168
+ def get_all_prefixes(self, word: str) -> List[str]:
169
+ """Get all prefixes of the given word that exist in the trie."""
170
+ prefixes = []
171
+ node = self._root
172
+
173
+ for i, char in enumerate(word):
174
+ if char not in node.children:
175
+ break
176
+ node = node.children[char]
177
+ if node.is_end_word:
178
+ prefixes.append(word[:i+1])
179
+
180
+ return prefixes
181
+
182
+ # ============================================================================
183
+ # HELPER METHODS
184
+ # ============================================================================
185
+
186
+ def _find_node(self, word: str) -> Optional[TrieNode]:
187
+ """Find the node corresponding to the given word."""
188
+ node = self._root
189
+ for char in word:
190
+ if char not in node.children:
191
+ return None
192
+ node = node.children[char]
193
+ return node
194
+
195
+ def _remove_recursive(self, node: TrieNode, word: str, index: int) -> bool:
196
+ """Recursively remove a word from the trie."""
197
+ if index == len(word):
198
+ if node.is_end_word:
199
+ node.is_end_word = False
200
+ node.value = None
201
+ return True
202
+ return False
203
+
204
+ char = word[index]
205
+ if char not in node.children:
206
+ return False
207
+
208
+ child = node.children[char]
209
+ should_delete_child = self._remove_recursive(child, word, index + 1)
210
+
211
+ if should_delete_child and not child.is_end_word and not child.children:
212
+ del node.children[char]
213
+
214
+ return should_delete_child
215
+
216
+ def _collect_words(self) -> List[str]:
217
+ """Collect all words stored in the trie."""
218
+ words = []
219
+ self._collect_words_from_node(self._root, "", words)
220
+ return words
221
+
222
+ def _collect_words_from_node(self, node: TrieNode, prefix: str, words: List[str]) -> None:
223
+ """Collect all words from a given node."""
224
+ if node.is_end_word:
225
+ words.append(prefix)
226
+
227
+ for char, child in node.children.items():
228
+ self._collect_words_from_node(child, prefix + char, words)
229
+
230
+ # ============================================================================
231
+ # PERFORMANCE CHARACTERISTICS
232
+ # ============================================================================
233
+
234
+ def backend_info(self) -> Dict[str, Any]:
235
+ """Get backend implementation info."""
236
+ return create_basic_backend_info(
237
+ 'TRIE',
238
+ 'TrieNode tree',
239
+ complexity={
240
+ 'get': 'O(m) where m is key length',
241
+ 'put': 'O(m) where m is key length',
242
+ 'has': 'O(m) where m is key length',
243
+ 'starts_with': 'O(m + k) where m is prefix length, k is number of matches'
244
+ }
245
+ )
246
+
247
+ def metrics(self) -> Dict[str, Any]:
248
+ """Get performance metrics."""
249
+ base_metrics = create_basic_metrics('TRIE', self._size_tracker['size'])
250
+ access_metrics = get_access_metrics(self._access_tracker)
251
+ base_metrics.update(access_metrics)
252
+ return base_metrics
@@ -0,0 +1,187 @@
1
+ """
2
+ Union-Find Node Strategy Implementation
3
+
4
+ This module implements the UNION_FIND strategy for efficient set operations.
5
+ """
6
+
7
+ from typing import Any, Iterator, Dict, List, Set
8
+ from .base import ANodeGraphStrategy
9
+ from ...types import NodeMode, NodeTrait
10
+ from ..utils import (
11
+ UnionFind,
12
+ safe_to_native_conversion,
13
+ create_basic_metrics,
14
+ create_basic_backend_info,
15
+ create_size_tracker,
16
+ create_access_tracker,
17
+ update_size_tracker,
18
+ record_access,
19
+ get_access_metrics
20
+ )
21
+
22
+
23
+ class UnionFindStrategy(ANodeGraphStrategy):
24
+ """
25
+ Union-Find node strategy for efficient set operations.
26
+
27
+ Optimized for union, find, and connected operations on disjoint sets.
28
+ """
29
+
30
+ def __init__(self, traits: NodeTrait = NodeTrait.NONE, **options):
31
+ """Initialize the union-find strategy."""
32
+ super().__init__(NodeMode.UNION_FIND, traits, **options)
33
+ self._union_find = UnionFind()
34
+ self._size_tracker = create_size_tracker()
35
+ self._access_tracker = create_access_tracker()
36
+
37
+ def get_supported_traits(self) -> NodeTrait:
38
+ """Get the traits supported by the union-find strategy."""
39
+ return (NodeTrait.SET_OPERATIONS | NodeTrait.HIERARCHICAL)
40
+
41
+ # ============================================================================
42
+ # CORE OPERATIONS
43
+ # ============================================================================
44
+
45
+ def put(self, key: Any, value: Any = None) -> None:
46
+ """Store a key-value pair (creates a new set)."""
47
+ str_key = str(key)
48
+ if str_key not in self._union_find.parent:
49
+ update_size_tracker(self._size_tracker, 1)
50
+ self._union_find.make_set(str_key, value)
51
+ record_access(self._access_tracker, 'put_count')
52
+
53
+ def get(self, key: Any, default: Any = None) -> Any:
54
+ """Retrieve a value by key."""
55
+ str_key = str(key)
56
+ record_access(self._access_tracker, 'get_count')
57
+ return self._union_find.values.get(str_key, default)
58
+
59
+ def has(self, key: Any) -> bool:
60
+ """Check if key exists."""
61
+ return str(key) in self._union_find.parent
62
+
63
+ def remove(self, key: Any) -> bool:
64
+ """Remove a key-value pair."""
65
+ str_key = str(key)
66
+ if str_key in self._union_find.parent:
67
+ # Remove from all data structures
68
+ del self._union_find.parent[str_key]
69
+ if str_key in self._union_find.rank:
70
+ del self._union_find.rank[str_key]
71
+ if str_key in self._union_find.values:
72
+ del self._union_find.values[str_key]
73
+ update_size_tracker(self._size_tracker, -1)
74
+ record_access(self._access_tracker, 'delete_count')
75
+ return True
76
+ return False
77
+
78
+ def delete(self, key: Any) -> bool:
79
+ """Remove a key-value pair (alias for remove)."""
80
+ return self.remove(key)
81
+
82
+ def clear(self) -> None:
83
+ """Clear all data."""
84
+ self._union_find = UnionFind()
85
+ self._size_tracker['size'] = 0
86
+
87
+ def keys(self) -> Iterator[str]:
88
+ """Get all keys."""
89
+ return iter(self._union_find.parent.keys())
90
+
91
+ def values(self) -> Iterator[Any]:
92
+ """Get all values."""
93
+ return iter(self._union_find.values.values())
94
+
95
+ def items(self) -> Iterator[tuple[str, Any]]:
96
+ """Get all key-value pairs."""
97
+ return iter(self._union_find.values.items())
98
+
99
+ def __len__(self) -> int:
100
+ """Get the number of items."""
101
+ return self._size_tracker['size']
102
+
103
+ def to_native(self) -> Dict[str, Any]:
104
+ """Convert to native Python dict with set structure info."""
105
+ result = {}
106
+ for key in self._union_find.parent.keys():
107
+ result[key] = {
108
+ 'value': safe_to_native_conversion(self._union_find.values.get(key)),
109
+ 'root': self._union_find.find(key),
110
+ 'set_id': self._union_find.find(key)
111
+ }
112
+ return result
113
+
114
+ @property
115
+ def is_list(self) -> bool:
116
+ """This is not a list strategy."""
117
+ return False
118
+
119
+ @property
120
+ def is_dict(self) -> bool:
121
+ """This behaves like a dict but with set semantics."""
122
+ return True
123
+
124
+ # ============================================================================
125
+ # UNION-FIND SPECIFIC OPERATIONS
126
+ # ============================================================================
127
+
128
+ def make_set(self, element: str, value: Any = None) -> None:
129
+ """Create a new set containing only the given element."""
130
+ if element not in self._union_find.parent:
131
+ update_size_tracker(self._size_tracker, 1)
132
+ self._union_find.make_set(element, value)
133
+
134
+ def find(self, element: str) -> str:
135
+ """Find the root of the set containing element (with path compression)."""
136
+ return self._union_find.find(element)
137
+
138
+ def union(self, element1: str, element2: str) -> bool:
139
+ """Union the sets containing element1 and element2."""
140
+ return self._union_find.union(element1, element2)
141
+
142
+ def connected(self, element1: str, element2: str) -> bool:
143
+ """Check if two elements are in the same set."""
144
+ return self._union_find.connected(element1, element2)
145
+
146
+ def get_set_members(self, element: str) -> Set[str]:
147
+ """Get all members of the set containing the given element."""
148
+ return self._union_find.get_set_members(element)
149
+
150
+ def get_all_sets(self) -> List[Set[str]]:
151
+ """Get all disjoint sets."""
152
+ return self._union_find.get_all_sets()
153
+
154
+ def get_set_count(self) -> int:
155
+ """Get the number of disjoint sets."""
156
+ return self._union_find.get_set_count()
157
+
158
+ def get_set_size(self, element: str) -> int:
159
+ """Get the size of the set containing the given element."""
160
+ return self._union_find.get_set_size(element)
161
+
162
+ # ============================================================================
163
+ # PERFORMANCE CHARACTERISTICS
164
+ # ============================================================================
165
+
166
+ def backend_info(self) -> Dict[str, Any]:
167
+ """Get backend implementation info."""
168
+ return create_basic_backend_info(
169
+ 'UNION_FIND',
170
+ 'UnionFind with path compression and union by rank',
171
+ complexity={
172
+ 'find': 'O(α(n)) amortized where α is inverse Ackermann',
173
+ 'union': 'O(α(n)) amortized where α is inverse Ackermann',
174
+ 'connected': 'O(α(n)) amortized where α is inverse Ackermann'
175
+ }
176
+ )
177
+
178
+ def metrics(self) -> Dict[str, Any]:
179
+ """Get performance metrics."""
180
+ base_metrics = create_basic_metrics('UNION_FIND', self._size_tracker['size'])
181
+ access_metrics = get_access_metrics(self._access_tracker)
182
+ base_metrics.update(access_metrics)
183
+ base_metrics.update({
184
+ 'set_count': self._union_find.get_set_count(),
185
+ 'avg_set_size': self._size_tracker['size'] / max(1, self._union_find.get_set_count())
186
+ })
187
+ return base_metrics