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.
- exonware/__init__.py +14 -0
- exonware/xwnode/__init__.py +127 -0
- exonware/xwnode/base.py +676 -0
- exonware/xwnode/config.py +178 -0
- exonware/xwnode/contracts.py +730 -0
- exonware/xwnode/errors.py +503 -0
- exonware/xwnode/facade.py +460 -0
- exonware/xwnode/strategies/__init__.py +158 -0
- exonware/xwnode/strategies/advisor.py +463 -0
- exonware/xwnode/strategies/edges/__init__.py +32 -0
- exonware/xwnode/strategies/edges/adj_list.py +227 -0
- exonware/xwnode/strategies/edges/adj_matrix.py +391 -0
- exonware/xwnode/strategies/edges/base.py +169 -0
- exonware/xwnode/strategies/flyweight.py +328 -0
- exonware/xwnode/strategies/impls/__init__.py +13 -0
- exonware/xwnode/strategies/impls/_base_edge.py +403 -0
- exonware/xwnode/strategies/impls/_base_node.py +307 -0
- exonware/xwnode/strategies/impls/edge_adj_list.py +353 -0
- exonware/xwnode/strategies/impls/edge_adj_matrix.py +445 -0
- exonware/xwnode/strategies/impls/edge_bidir_wrapper.py +455 -0
- exonware/xwnode/strategies/impls/edge_block_adj_matrix.py +539 -0
- exonware/xwnode/strategies/impls/edge_coo.py +533 -0
- exonware/xwnode/strategies/impls/edge_csc.py +447 -0
- exonware/xwnode/strategies/impls/edge_csr.py +492 -0
- exonware/xwnode/strategies/impls/edge_dynamic_adj_list.py +503 -0
- exonware/xwnode/strategies/impls/edge_flow_network.py +555 -0
- exonware/xwnode/strategies/impls/edge_hyperedge_set.py +516 -0
- exonware/xwnode/strategies/impls/edge_neural_graph.py +650 -0
- exonware/xwnode/strategies/impls/edge_octree.py +574 -0
- exonware/xwnode/strategies/impls/edge_property_store.py +655 -0
- exonware/xwnode/strategies/impls/edge_quadtree.py +519 -0
- exonware/xwnode/strategies/impls/edge_rtree.py +820 -0
- exonware/xwnode/strategies/impls/edge_temporal_edgeset.py +558 -0
- exonware/xwnode/strategies/impls/edge_tree_graph_basic.py +271 -0
- exonware/xwnode/strategies/impls/edge_weighted_graph.py +411 -0
- exonware/xwnode/strategies/manager.py +775 -0
- exonware/xwnode/strategies/metrics.py +538 -0
- exonware/xwnode/strategies/migration.py +432 -0
- exonware/xwnode/strategies/nodes/__init__.py +50 -0
- exonware/xwnode/strategies/nodes/_base_node.py +307 -0
- exonware/xwnode/strategies/nodes/adjacency_list.py +267 -0
- exonware/xwnode/strategies/nodes/aho_corasick.py +345 -0
- exonware/xwnode/strategies/nodes/array_list.py +209 -0
- exonware/xwnode/strategies/nodes/base.py +247 -0
- exonware/xwnode/strategies/nodes/deque.py +200 -0
- exonware/xwnode/strategies/nodes/hash_map.py +135 -0
- exonware/xwnode/strategies/nodes/heap.py +307 -0
- exonware/xwnode/strategies/nodes/linked_list.py +232 -0
- exonware/xwnode/strategies/nodes/node_aho_corasick.py +520 -0
- exonware/xwnode/strategies/nodes/node_array_list.py +175 -0
- exonware/xwnode/strategies/nodes/node_avl_tree.py +371 -0
- exonware/xwnode/strategies/nodes/node_b_plus_tree.py +542 -0
- exonware/xwnode/strategies/nodes/node_bitmap.py +420 -0
- exonware/xwnode/strategies/nodes/node_bitset_dynamic.py +513 -0
- exonware/xwnode/strategies/nodes/node_bloom_filter.py +347 -0
- exonware/xwnode/strategies/nodes/node_btree.py +357 -0
- exonware/xwnode/strategies/nodes/node_count_min_sketch.py +470 -0
- exonware/xwnode/strategies/nodes/node_cow_tree.py +473 -0
- exonware/xwnode/strategies/nodes/node_cuckoo_hash.py +392 -0
- exonware/xwnode/strategies/nodes/node_fenwick_tree.py +301 -0
- exonware/xwnode/strategies/nodes/node_hash_map.py +269 -0
- exonware/xwnode/strategies/nodes/node_heap.py +191 -0
- exonware/xwnode/strategies/nodes/node_hyperloglog.py +407 -0
- exonware/xwnode/strategies/nodes/node_linked_list.py +409 -0
- exonware/xwnode/strategies/nodes/node_lsm_tree.py +400 -0
- exonware/xwnode/strategies/nodes/node_ordered_map.py +390 -0
- exonware/xwnode/strategies/nodes/node_ordered_map_balanced.py +565 -0
- exonware/xwnode/strategies/nodes/node_patricia.py +512 -0
- exonware/xwnode/strategies/nodes/node_persistent_tree.py +378 -0
- exonware/xwnode/strategies/nodes/node_radix_trie.py +452 -0
- exonware/xwnode/strategies/nodes/node_red_black_tree.py +497 -0
- exonware/xwnode/strategies/nodes/node_roaring_bitmap.py +570 -0
- exonware/xwnode/strategies/nodes/node_segment_tree.py +289 -0
- exonware/xwnode/strategies/nodes/node_set_hash.py +354 -0
- exonware/xwnode/strategies/nodes/node_set_tree.py +480 -0
- exonware/xwnode/strategies/nodes/node_skip_list.py +316 -0
- exonware/xwnode/strategies/nodes/node_splay_tree.py +393 -0
- exonware/xwnode/strategies/nodes/node_suffix_array.py +487 -0
- exonware/xwnode/strategies/nodes/node_treap.py +387 -0
- exonware/xwnode/strategies/nodes/node_tree_graph_hybrid.py +1434 -0
- exonware/xwnode/strategies/nodes/node_trie.py +252 -0
- exonware/xwnode/strategies/nodes/node_union_find.py +187 -0
- exonware/xwnode/strategies/nodes/node_xdata_optimized.py +369 -0
- exonware/xwnode/strategies/nodes/priority_queue.py +209 -0
- exonware/xwnode/strategies/nodes/queue.py +161 -0
- exonware/xwnode/strategies/nodes/sparse_matrix.py +206 -0
- exonware/xwnode/strategies/nodes/stack.py +152 -0
- exonware/xwnode/strategies/nodes/trie.py +274 -0
- exonware/xwnode/strategies/nodes/union_find.py +283 -0
- exonware/xwnode/strategies/pattern_detector.py +603 -0
- exonware/xwnode/strategies/performance_monitor.py +487 -0
- exonware/xwnode/strategies/queries/__init__.py +24 -0
- exonware/xwnode/strategies/queries/base.py +236 -0
- exonware/xwnode/strategies/queries/cql.py +201 -0
- exonware/xwnode/strategies/queries/cypher.py +181 -0
- exonware/xwnode/strategies/queries/datalog.py +70 -0
- exonware/xwnode/strategies/queries/elastic_dsl.py +70 -0
- exonware/xwnode/strategies/queries/eql.py +70 -0
- exonware/xwnode/strategies/queries/flux.py +70 -0
- exonware/xwnode/strategies/queries/gql.py +70 -0
- exonware/xwnode/strategies/queries/graphql.py +240 -0
- exonware/xwnode/strategies/queries/gremlin.py +181 -0
- exonware/xwnode/strategies/queries/hiveql.py +214 -0
- exonware/xwnode/strategies/queries/hql.py +70 -0
- exonware/xwnode/strategies/queries/jmespath.py +219 -0
- exonware/xwnode/strategies/queries/jq.py +66 -0
- exonware/xwnode/strategies/queries/json_query.py +66 -0
- exonware/xwnode/strategies/queries/jsoniq.py +248 -0
- exonware/xwnode/strategies/queries/kql.py +70 -0
- exonware/xwnode/strategies/queries/linq.py +238 -0
- exonware/xwnode/strategies/queries/logql.py +70 -0
- exonware/xwnode/strategies/queries/mql.py +68 -0
- exonware/xwnode/strategies/queries/n1ql.py +210 -0
- exonware/xwnode/strategies/queries/partiql.py +70 -0
- exonware/xwnode/strategies/queries/pig.py +215 -0
- exonware/xwnode/strategies/queries/promql.py +70 -0
- exonware/xwnode/strategies/queries/sparql.py +220 -0
- exonware/xwnode/strategies/queries/sql.py +275 -0
- exonware/xwnode/strategies/queries/xml_query.py +66 -0
- exonware/xwnode/strategies/queries/xpath.py +223 -0
- exonware/xwnode/strategies/queries/xquery.py +258 -0
- exonware/xwnode/strategies/queries/xwnode_executor.py +332 -0
- exonware/xwnode/strategies/queries/xwquery_strategy.py +424 -0
- exonware/xwnode/strategies/registry.py +604 -0
- exonware/xwnode/strategies/simple.py +273 -0
- exonware/xwnode/strategies/utils.py +532 -0
- exonware/xwnode/types.py +912 -0
- exonware/xwnode/version.py +78 -0
- exonware_xwnode-0.0.1.12.dist-info/METADATA +169 -0
- exonware_xwnode-0.0.1.12.dist-info/RECORD +132 -0
- exonware_xwnode-0.0.1.12.dist-info/WHEEL +4 -0
- exonware_xwnode-0.0.1.12.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,161 @@
|
|
1
|
+
"""
|
2
|
+
Queue Strategy Implementation
|
3
|
+
|
4
|
+
Implements a FIFO (First In, First Out) data structure using Python's deque.
|
5
|
+
|
6
|
+
Company: eXonware.com
|
7
|
+
Author: Eng. Muhammad AlShehri
|
8
|
+
Email: connect@exonware.com
|
9
|
+
Version: 0.0.1.12
|
10
|
+
Generation Date: 07-Sep-2025
|
11
|
+
"""
|
12
|
+
|
13
|
+
from typing import Any, Iterator, Optional, Dict, Union
|
14
|
+
from collections import deque
|
15
|
+
from .base import ANodeLinearStrategy
|
16
|
+
from ...types import NodeMode, NodeTrait
|
17
|
+
|
18
|
+
|
19
|
+
class QueueStrategy(ANodeLinearStrategy):
|
20
|
+
"""
|
21
|
+
Queue node strategy for FIFO (First In, First Out) operations.
|
22
|
+
|
23
|
+
Provides O(1) enqueue and dequeue operations with efficient memory usage
|
24
|
+
for queue-based algorithms and breadth-first search.
|
25
|
+
"""
|
26
|
+
|
27
|
+
def __init__(self):
|
28
|
+
"""Initialize an empty queue."""
|
29
|
+
super().__init__()
|
30
|
+
self._queue: deque = deque()
|
31
|
+
self._mode = NodeMode.QUEUE
|
32
|
+
self._traits = {NodeTrait.FIFO, NodeTrait.FAST_INSERT, NodeTrait.FAST_DELETE}
|
33
|
+
|
34
|
+
def insert(self, key: str, value: Any) -> None:
|
35
|
+
"""Enqueue an item into the queue."""
|
36
|
+
self._queue.append((key, value))
|
37
|
+
self._record_access("enqueue")
|
38
|
+
|
39
|
+
def find(self, key: str) -> Optional[Any]:
|
40
|
+
"""Find an item in the queue (O(n) operation)."""
|
41
|
+
for k, v in self._queue:
|
42
|
+
if k == key:
|
43
|
+
self._record_access("find")
|
44
|
+
return v
|
45
|
+
return None
|
46
|
+
|
47
|
+
def delete(self, key: str) -> bool:
|
48
|
+
"""Remove an item from the queue."""
|
49
|
+
for i, (k, v) in enumerate(self._queue):
|
50
|
+
if k == key:
|
51
|
+
del self._queue[i]
|
52
|
+
self._record_access("delete")
|
53
|
+
return True
|
54
|
+
return False
|
55
|
+
|
56
|
+
def size(self) -> int:
|
57
|
+
"""Get the number of items in the queue."""
|
58
|
+
return len(self._queue)
|
59
|
+
|
60
|
+
def is_empty(self) -> bool:
|
61
|
+
"""Check if the queue is empty."""
|
62
|
+
return len(self._queue) == 0
|
63
|
+
|
64
|
+
def to_native(self) -> Dict[str, Any]:
|
65
|
+
"""Convert queue to native dictionary format."""
|
66
|
+
return dict(self._queue)
|
67
|
+
|
68
|
+
def from_native(self, data: Dict[str, Any]) -> None:
|
69
|
+
"""Load queue from native dictionary format."""
|
70
|
+
self._queue = deque(data.items())
|
71
|
+
|
72
|
+
def enqueue(self, value: Any) -> None:
|
73
|
+
"""Enqueue a value into the queue."""
|
74
|
+
key = f"item_{len(self._queue)}"
|
75
|
+
self.insert(key, value)
|
76
|
+
|
77
|
+
def dequeue(self) -> Optional[Any]:
|
78
|
+
"""Dequeue and return the front item from the queue."""
|
79
|
+
if self.is_empty():
|
80
|
+
return None
|
81
|
+
key, value = self._queue.popleft()
|
82
|
+
self._record_access("dequeue")
|
83
|
+
return value
|
84
|
+
|
85
|
+
def front(self) -> Optional[Any]:
|
86
|
+
"""Get the front item without removing it."""
|
87
|
+
if self.is_empty():
|
88
|
+
return None
|
89
|
+
key, value = self._queue[0]
|
90
|
+
self._record_access("front")
|
91
|
+
return value
|
92
|
+
|
93
|
+
def back(self) -> Optional[Any]:
|
94
|
+
"""Get the back item without removing it."""
|
95
|
+
if self.is_empty():
|
96
|
+
return None
|
97
|
+
key, value = self._queue[-1]
|
98
|
+
self._record_access("back")
|
99
|
+
return value
|
100
|
+
|
101
|
+
def clear(self) -> None:
|
102
|
+
"""Clear all items from the queue."""
|
103
|
+
self._queue.clear()
|
104
|
+
self._record_access("clear")
|
105
|
+
|
106
|
+
def get_at_index(self, index: int) -> Optional[Any]:
|
107
|
+
"""Get item at specific index (0 = front of queue)."""
|
108
|
+
if 0 <= index < len(self._queue):
|
109
|
+
key, value = self._queue[index]
|
110
|
+
self._record_access("get_at_index")
|
111
|
+
return value
|
112
|
+
return None
|
113
|
+
|
114
|
+
def push_front(self, value: Any) -> None:
|
115
|
+
"""Push to front of queue."""
|
116
|
+
self._queue.appendleft((f"item_{len(self._queue)}", value))
|
117
|
+
self._record_access("push_front")
|
118
|
+
|
119
|
+
def push_back(self, value: Any) -> None:
|
120
|
+
"""Push to back of queue."""
|
121
|
+
self.enqueue(value)
|
122
|
+
|
123
|
+
def __iter__(self) -> Iterator[Any]:
|
124
|
+
"""Iterate through queue items (front to back)."""
|
125
|
+
for key, value in self._queue:
|
126
|
+
yield value
|
127
|
+
|
128
|
+
def __repr__(self) -> str:
|
129
|
+
"""String representation of the queue."""
|
130
|
+
return f"QueueStrategy(size={len(self._queue)}, front={self.front()})"
|
131
|
+
|
132
|
+
# Required abstract methods from base classes
|
133
|
+
def pop_front(self) -> Any:
|
134
|
+
"""Remove element from front (same as dequeue for queue)."""
|
135
|
+
return self.dequeue()
|
136
|
+
|
137
|
+
def pop_back(self) -> Any:
|
138
|
+
"""Remove element from back (not applicable for queue)."""
|
139
|
+
raise NotImplementedError("Queue doesn't support pop_back")
|
140
|
+
|
141
|
+
def set_at_index(self, index: int, value: Any) -> None:
|
142
|
+
"""Set element at index (not recommended for queue)."""
|
143
|
+
if 0 <= index < len(self._queue):
|
144
|
+
key, old_value = self._queue[index]
|
145
|
+
self._queue[index] = (key, value)
|
146
|
+
|
147
|
+
def as_linked_list(self):
|
148
|
+
"""Provide LinkedList behavioral view."""
|
149
|
+
return self
|
150
|
+
|
151
|
+
def as_stack(self):
|
152
|
+
"""Provide Stack behavioral view (not recommended)."""
|
153
|
+
raise NotImplementedError("Queue cannot behave as Stack")
|
154
|
+
|
155
|
+
def as_queue(self):
|
156
|
+
"""Provide Queue behavioral view."""
|
157
|
+
return self
|
158
|
+
|
159
|
+
def as_deque(self):
|
160
|
+
"""Provide Deque behavioral view."""
|
161
|
+
return self
|
@@ -0,0 +1,206 @@
|
|
1
|
+
"""
|
2
|
+
Sparse Matrix Strategy Implementation
|
3
|
+
|
4
|
+
Implements a sparse matrix using coordinate format (COO) for memory efficiency.
|
5
|
+
|
6
|
+
Company: eXonware.com
|
7
|
+
Author: Eng. Muhammad AlShehri
|
8
|
+
Email: connect@exonware.com
|
9
|
+
Version: 0.0.1.12
|
10
|
+
Generation Date: 07-Sep-2025
|
11
|
+
"""
|
12
|
+
|
13
|
+
from typing import Any, Iterator, List, Optional, Dict, Union, Tuple
|
14
|
+
from .base import ANodeMatrixStrategy
|
15
|
+
from ...types import NodeMode, NodeTrait
|
16
|
+
|
17
|
+
|
18
|
+
class SparseMatrixStrategy(ANodeMatrixStrategy):
|
19
|
+
"""
|
20
|
+
Sparse Matrix node strategy for memory-efficient matrix operations.
|
21
|
+
|
22
|
+
Uses coordinate format (COO) to store only non-zero elements,
|
23
|
+
providing excellent memory efficiency for sparse matrices.
|
24
|
+
"""
|
25
|
+
|
26
|
+
def __init__(self):
|
27
|
+
"""Initialize an empty sparse matrix."""
|
28
|
+
super().__init__()
|
29
|
+
self._data: List[Tuple[int, int, Any]] = [] # (row, col, value)
|
30
|
+
self._rows = 0
|
31
|
+
self._cols = 0
|
32
|
+
self._mode = NodeMode.SPARSE_MATRIX
|
33
|
+
self._traits = {NodeTrait.SPARSE, NodeTrait.MEMORY_EFFICIENT, NodeTrait.MATRIX_OPS}
|
34
|
+
|
35
|
+
def insert(self, key: str, value: Any) -> None:
|
36
|
+
"""Insert a value using key as coordinate (e.g., '1,2' for row 1, col 2)."""
|
37
|
+
try:
|
38
|
+
row, col = map(int, key.split(','))
|
39
|
+
self.set_at_position(row, col, value)
|
40
|
+
except ValueError:
|
41
|
+
raise ValueError(f"Key must be in format 'row,col', got: {key}")
|
42
|
+
|
43
|
+
def find(self, key: str) -> Optional[Any]:
|
44
|
+
"""Find a value using key as coordinate."""
|
45
|
+
try:
|
46
|
+
row, col = map(int, key.split(','))
|
47
|
+
return self.get_at_position(row, col)
|
48
|
+
except ValueError:
|
49
|
+
return None
|
50
|
+
|
51
|
+
def delete(self, key: str) -> bool:
|
52
|
+
"""Delete a value using key as coordinate."""
|
53
|
+
try:
|
54
|
+
row, col = map(int, key.split(','))
|
55
|
+
return self.set_at_position(row, col, 0) is not None
|
56
|
+
except ValueError:
|
57
|
+
return False
|
58
|
+
|
59
|
+
def size(self) -> int:
|
60
|
+
"""Get the number of non-zero elements."""
|
61
|
+
return len(self._data)
|
62
|
+
|
63
|
+
def to_native(self) -> Dict[str, Any]:
|
64
|
+
"""Convert sparse matrix to native dictionary format."""
|
65
|
+
result = {}
|
66
|
+
for row, col, value in self._data:
|
67
|
+
result[f"{row},{col}"] = value
|
68
|
+
return result
|
69
|
+
|
70
|
+
def from_native(self, data: Dict[str, Any]) -> None:
|
71
|
+
"""Load sparse matrix from native dictionary format."""
|
72
|
+
self._data.clear()
|
73
|
+
for key, value in data.items():
|
74
|
+
try:
|
75
|
+
row, col = map(int, key.split(','))
|
76
|
+
if value != 0: # Only store non-zero values
|
77
|
+
self._data.append((row, col, value))
|
78
|
+
self._rows = max(self._rows, row + 1)
|
79
|
+
self._cols = max(self._cols, col + 1)
|
80
|
+
except ValueError:
|
81
|
+
continue
|
82
|
+
|
83
|
+
def get_dimensions(self) -> Tuple[int, int]:
|
84
|
+
"""Get matrix dimensions (rows, cols)."""
|
85
|
+
return (self._rows, self._cols)
|
86
|
+
|
87
|
+
def get_at_position(self, row: int, col: int) -> Any:
|
88
|
+
"""Get value at specific position."""
|
89
|
+
for r, c, value in self._data:
|
90
|
+
if r == row and c == col:
|
91
|
+
return value
|
92
|
+
return 0 # Default to 0 for sparse matrix
|
93
|
+
|
94
|
+
def set_at_position(self, row: int, col: int, value: Any) -> None:
|
95
|
+
"""Set value at specific position."""
|
96
|
+
# Remove existing entry if it exists
|
97
|
+
self._data = [(r, c, v) for r, c, v in self._data if not (r == row and c == col)]
|
98
|
+
|
99
|
+
# Add new entry if value is not zero
|
100
|
+
if value != 0:
|
101
|
+
self._data.append((row, col, value))
|
102
|
+
|
103
|
+
# Update dimensions
|
104
|
+
self._rows = max(self._rows, row + 1)
|
105
|
+
self._cols = max(self._cols, col + 1)
|
106
|
+
|
107
|
+
def get_row(self, row: int) -> List[Any]:
|
108
|
+
"""Get entire row as list."""
|
109
|
+
result = [0] * self._cols
|
110
|
+
for r, c, value in self._data:
|
111
|
+
if r == row:
|
112
|
+
result[c] = value
|
113
|
+
return result
|
114
|
+
|
115
|
+
def get_column(self, col: int) -> List[Any]:
|
116
|
+
"""Get entire column as list."""
|
117
|
+
result = [0] * self._rows
|
118
|
+
for r, c, value in self._data:
|
119
|
+
if c == col:
|
120
|
+
result[r] = value
|
121
|
+
return result
|
122
|
+
|
123
|
+
def transpose(self) -> 'SparseMatrixStrategy':
|
124
|
+
"""Return transposed matrix."""
|
125
|
+
transposed = SparseMatrixStrategy()
|
126
|
+
for row, col, value in self._data:
|
127
|
+
transposed.set_at_position(col, row, value)
|
128
|
+
return transposed
|
129
|
+
|
130
|
+
def multiply(self, other: 'SparseMatrixStrategy') -> 'SparseMatrixStrategy':
|
131
|
+
"""Multiply with another sparse matrix."""
|
132
|
+
result = SparseMatrixStrategy()
|
133
|
+
other_dict = {}
|
134
|
+
for r, c, v in other._data:
|
135
|
+
other_dict[(r, c)] = v
|
136
|
+
|
137
|
+
for r1, c1, v1 in self._data:
|
138
|
+
for c2 in range(other._cols):
|
139
|
+
if (c1, c2) in other_dict:
|
140
|
+
v2 = other_dict[(c1, c2)]
|
141
|
+
current = result.get_at_position(r1, c2)
|
142
|
+
result.set_at_position(r1, c2, current + v1 * v2)
|
143
|
+
|
144
|
+
return result
|
145
|
+
|
146
|
+
def add(self, other: 'SparseMatrixStrategy') -> 'SparseMatrixStrategy':
|
147
|
+
"""Add another sparse matrix."""
|
148
|
+
result = SparseMatrixStrategy()
|
149
|
+
|
150
|
+
# Add all elements from self
|
151
|
+
for r, c, v in self._data:
|
152
|
+
result.set_at_position(r, c, v)
|
153
|
+
|
154
|
+
# Add all elements from other
|
155
|
+
for r, c, v in other._data:
|
156
|
+
current = result.get_at_position(r, c)
|
157
|
+
result.set_at_position(r, c, current + v)
|
158
|
+
|
159
|
+
return result
|
160
|
+
|
161
|
+
def as_adjacency_matrix(self):
|
162
|
+
"""Convert to adjacency matrix format."""
|
163
|
+
return self
|
164
|
+
|
165
|
+
def as_incidence_matrix(self):
|
166
|
+
"""Convert to incidence matrix format."""
|
167
|
+
return self
|
168
|
+
|
169
|
+
def as_sparse_matrix(self):
|
170
|
+
"""Return self as sparse matrix."""
|
171
|
+
return self
|
172
|
+
|
173
|
+
def density(self) -> float:
|
174
|
+
"""Calculate matrix density (non-zero elements / total elements)."""
|
175
|
+
total_elements = self._rows * self._cols
|
176
|
+
if total_elements == 0:
|
177
|
+
return 0.0
|
178
|
+
return len(self._data) / total_elements
|
179
|
+
|
180
|
+
def clear(self) -> None:
|
181
|
+
"""Clear all elements."""
|
182
|
+
self._data.clear()
|
183
|
+
self._rows = 0
|
184
|
+
self._cols = 0
|
185
|
+
|
186
|
+
def __iter__(self) -> Iterator[Tuple[int, int, Any]]:
|
187
|
+
"""Iterate through non-zero elements."""
|
188
|
+
for row, col, value in self._data:
|
189
|
+
yield (row, col, value)
|
190
|
+
|
191
|
+
def __repr__(self) -> str:
|
192
|
+
"""String representation of the sparse matrix."""
|
193
|
+
return f"SparseMatrixStrategy({self._rows}x{self._cols}, {len(self._data)} non-zero)"
|
194
|
+
|
195
|
+
# Required abstract methods from base classes
|
196
|
+
def as_adjacency_matrix(self):
|
197
|
+
"""Provide Adjacency Matrix behavioral view."""
|
198
|
+
return self
|
199
|
+
|
200
|
+
def as_incidence_matrix(self):
|
201
|
+
"""Provide Incidence Matrix behavioral view."""
|
202
|
+
return self
|
203
|
+
|
204
|
+
def as_sparse_matrix(self):
|
205
|
+
"""Provide Sparse Matrix behavioral view."""
|
206
|
+
return self
|
@@ -0,0 +1,152 @@
|
|
1
|
+
"""
|
2
|
+
Stack Strategy Implementation
|
3
|
+
|
4
|
+
Implements a LIFO (Last In, First Out) data structure using Python's list.
|
5
|
+
|
6
|
+
Company: eXonware.com
|
7
|
+
Author: Eng. Muhammad AlShehri
|
8
|
+
Email: connect@exonware.com
|
9
|
+
Version: 0.0.1.12
|
10
|
+
Generation Date: 07-Sep-2025
|
11
|
+
"""
|
12
|
+
|
13
|
+
from typing import Any, Iterator, List, Optional, Dict, Union
|
14
|
+
from .base import ANodeLinearStrategy
|
15
|
+
from ...types import NodeMode, NodeTrait
|
16
|
+
|
17
|
+
|
18
|
+
class StackStrategy(ANodeLinearStrategy):
|
19
|
+
"""
|
20
|
+
Stack node strategy for LIFO (Last In, First Out) operations.
|
21
|
+
|
22
|
+
Provides O(1) push and pop operations with efficient memory usage
|
23
|
+
for stack-based algorithms and recursive function simulation.
|
24
|
+
"""
|
25
|
+
|
26
|
+
def __init__(self):
|
27
|
+
"""Initialize an empty stack."""
|
28
|
+
super().__init__()
|
29
|
+
self._stack: List[Any] = []
|
30
|
+
self._mode = NodeMode.STACK
|
31
|
+
self._traits = {NodeTrait.LIFO, NodeTrait.FAST_INSERT, NodeTrait.FAST_DELETE}
|
32
|
+
|
33
|
+
def insert(self, key: str, value: Any) -> None:
|
34
|
+
"""Push an item onto the stack."""
|
35
|
+
self._stack.append((key, value))
|
36
|
+
self._record_access("push")
|
37
|
+
|
38
|
+
def find(self, key: str) -> Optional[Any]:
|
39
|
+
"""Find an item in the stack (O(n) operation)."""
|
40
|
+
for k, v in reversed(self._stack):
|
41
|
+
if k == key:
|
42
|
+
self._record_access("find")
|
43
|
+
return v
|
44
|
+
return None
|
45
|
+
|
46
|
+
def delete(self, key: str) -> bool:
|
47
|
+
"""Remove an item from the stack."""
|
48
|
+
for i, (k, v) in enumerate(self._stack):
|
49
|
+
if k == key:
|
50
|
+
self._stack.pop(i)
|
51
|
+
self._record_access("delete")
|
52
|
+
return True
|
53
|
+
return False
|
54
|
+
|
55
|
+
def size(self) -> int:
|
56
|
+
"""Get the number of items in the stack."""
|
57
|
+
return len(self._stack)
|
58
|
+
|
59
|
+
def is_empty(self) -> bool:
|
60
|
+
"""Check if the stack is empty."""
|
61
|
+
return len(self._stack) == 0
|
62
|
+
|
63
|
+
def to_native(self) -> Dict[str, Any]:
|
64
|
+
"""Convert stack to native dictionary format."""
|
65
|
+
return dict(reversed(self._stack))
|
66
|
+
|
67
|
+
def from_native(self, data: Dict[str, Any]) -> None:
|
68
|
+
"""Load stack from native dictionary format."""
|
69
|
+
self._stack = [(k, v) for k, v in data.items()]
|
70
|
+
|
71
|
+
def push(self, value: Any) -> None:
|
72
|
+
"""Push a value onto the stack."""
|
73
|
+
key = f"item_{len(self._stack)}"
|
74
|
+
self.insert(key, value)
|
75
|
+
|
76
|
+
def pop(self) -> Optional[Any]:
|
77
|
+
"""Pop and return the top item from the stack."""
|
78
|
+
if self.is_empty():
|
79
|
+
return None
|
80
|
+
key, value = self._stack.pop()
|
81
|
+
self._record_access("pop")
|
82
|
+
return value
|
83
|
+
|
84
|
+
def peek(self) -> Optional[Any]:
|
85
|
+
"""Peek at the top item without removing it."""
|
86
|
+
if self.is_empty():
|
87
|
+
return None
|
88
|
+
key, value = self._stack[-1]
|
89
|
+
self._record_access("peek")
|
90
|
+
return value
|
91
|
+
|
92
|
+
def clear(self) -> None:
|
93
|
+
"""Clear all items from the stack."""
|
94
|
+
self._stack.clear()
|
95
|
+
self._record_access("clear")
|
96
|
+
|
97
|
+
def get_at_index(self, index: int) -> Optional[Any]:
|
98
|
+
"""Get item at specific index (0 = top of stack)."""
|
99
|
+
if 0 <= index < len(self._stack):
|
100
|
+
key, value = self._stack[-(index + 1)]
|
101
|
+
self._record_access("get_at_index")
|
102
|
+
return value
|
103
|
+
return None
|
104
|
+
|
105
|
+
def push_front(self, value: Any) -> None:
|
106
|
+
"""Push to front (bottom) of stack."""
|
107
|
+
self._stack.insert(0, (f"item_{len(self._stack)}", value))
|
108
|
+
self._record_access("push_front")
|
109
|
+
|
110
|
+
def push_back(self, value: Any) -> None:
|
111
|
+
"""Push to back (top) of stack."""
|
112
|
+
self.push(value)
|
113
|
+
|
114
|
+
def __iter__(self) -> Iterator[Any]:
|
115
|
+
"""Iterate through stack items (top to bottom)."""
|
116
|
+
for key, value in reversed(self._stack):
|
117
|
+
yield value
|
118
|
+
|
119
|
+
def __repr__(self) -> str:
|
120
|
+
"""String representation of the stack."""
|
121
|
+
return f"StackStrategy(size={len(self._stack)}, top={self.peek()})"
|
122
|
+
|
123
|
+
# Required abstract methods from base classes
|
124
|
+
def pop_front(self) -> Any:
|
125
|
+
"""Remove element from front (same as pop for stack)."""
|
126
|
+
return self.pop()
|
127
|
+
|
128
|
+
def pop_back(self) -> Any:
|
129
|
+
"""Remove element from back (not applicable for stack)."""
|
130
|
+
raise NotImplementedError("Stack doesn't support pop_back")
|
131
|
+
|
132
|
+
def set_at_index(self, index: int, value: Any) -> None:
|
133
|
+
"""Set element at index (not recommended for stack)."""
|
134
|
+
if 0 <= index < len(self._stack):
|
135
|
+
key, old_value = self._stack[-(index + 1)]
|
136
|
+
self._stack[-(index + 1)] = (key, value)
|
137
|
+
|
138
|
+
def as_linked_list(self):
|
139
|
+
"""Provide LinkedList behavioral view."""
|
140
|
+
return self
|
141
|
+
|
142
|
+
def as_stack(self):
|
143
|
+
"""Provide Stack behavioral view."""
|
144
|
+
return self
|
145
|
+
|
146
|
+
def as_queue(self):
|
147
|
+
"""Provide Queue behavioral view (not recommended)."""
|
148
|
+
raise NotImplementedError("Stack cannot behave as Queue")
|
149
|
+
|
150
|
+
def as_deque(self):
|
151
|
+
"""Provide Deque behavioral view."""
|
152
|
+
return self
|