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.
- exonware/__init__.py +8 -1
- exonware/xwnode/__init__.py +18 -5
- exonware/xwnode/add_strategy_types.py +165 -0
- exonware/xwnode/base.py +7 -5
- exonware/xwnode/common/__init__.py +1 -1
- exonware/xwnode/common/graph/__init__.py +30 -0
- exonware/xwnode/common/graph/caching.py +131 -0
- exonware/xwnode/common/graph/contracts.py +100 -0
- exonware/xwnode/common/graph/errors.py +44 -0
- exonware/xwnode/common/graph/indexing.py +260 -0
- exonware/xwnode/common/graph/manager.py +568 -0
- exonware/xwnode/common/management/__init__.py +3 -5
- exonware/xwnode/common/management/manager.py +9 -9
- exonware/xwnode/common/management/migration.py +6 -6
- exonware/xwnode/common/monitoring/__init__.py +3 -5
- exonware/xwnode/common/monitoring/metrics.py +7 -3
- exonware/xwnode/common/monitoring/pattern_detector.py +2 -2
- exonware/xwnode/common/monitoring/performance_monitor.py +6 -2
- exonware/xwnode/common/patterns/__init__.py +3 -5
- exonware/xwnode/common/patterns/advisor.py +1 -1
- exonware/xwnode/common/patterns/flyweight.py +6 -2
- exonware/xwnode/common/patterns/registry.py +203 -184
- exonware/xwnode/common/utils/__init__.py +25 -11
- exonware/xwnode/common/utils/simple.py +1 -1
- exonware/xwnode/config.py +3 -8
- exonware/xwnode/contracts.py +4 -105
- exonware/xwnode/defs.py +413 -159
- exonware/xwnode/edges/strategies/__init__.py +86 -4
- exonware/xwnode/edges/strategies/_base_edge.py +2 -2
- exonware/xwnode/edges/strategies/adj_list.py +287 -121
- exonware/xwnode/edges/strategies/adj_matrix.py +316 -222
- exonware/xwnode/edges/strategies/base.py +1 -1
- exonware/xwnode/edges/strategies/{edge_bidir_wrapper.py → bidir_wrapper.py} +45 -4
- exonware/xwnode/edges/strategies/bitemporal.py +520 -0
- exonware/xwnode/edges/strategies/{edge_block_adj_matrix.py → block_adj_matrix.py} +77 -6
- exonware/xwnode/edges/strategies/bv_graph.py +664 -0
- exonware/xwnode/edges/strategies/compressed_graph.py +217 -0
- exonware/xwnode/edges/strategies/{edge_coo.py → coo.py} +46 -4
- exonware/xwnode/edges/strategies/{edge_csc.py → csc.py} +45 -4
- exonware/xwnode/edges/strategies/{edge_csr.py → csr.py} +94 -12
- exonware/xwnode/edges/strategies/{edge_dynamic_adj_list.py → dynamic_adj_list.py} +46 -4
- exonware/xwnode/edges/strategies/edge_list.py +168 -0
- exonware/xwnode/edges/strategies/edge_property_store.py +2 -2
- exonware/xwnode/edges/strategies/euler_tour.py +560 -0
- exonware/xwnode/edges/strategies/{edge_flow_network.py → flow_network.py} +2 -2
- exonware/xwnode/edges/strategies/graphblas.py +449 -0
- exonware/xwnode/edges/strategies/hnsw.py +637 -0
- exonware/xwnode/edges/strategies/hop2_labels.py +467 -0
- exonware/xwnode/edges/strategies/{edge_hyperedge_set.py → hyperedge_set.py} +2 -2
- exonware/xwnode/edges/strategies/incidence_matrix.py +250 -0
- exonware/xwnode/edges/strategies/k2_tree.py +613 -0
- exonware/xwnode/edges/strategies/link_cut.py +626 -0
- exonware/xwnode/edges/strategies/multiplex.py +532 -0
- exonware/xwnode/edges/strategies/{edge_neural_graph.py → neural_graph.py} +2 -2
- exonware/xwnode/edges/strategies/{edge_octree.py → octree.py} +69 -11
- exonware/xwnode/edges/strategies/{edge_quadtree.py → quadtree.py} +66 -10
- exonware/xwnode/edges/strategies/roaring_adj.py +438 -0
- exonware/xwnode/edges/strategies/{edge_rtree.py → rtree.py} +43 -5
- exonware/xwnode/edges/strategies/{edge_temporal_edgeset.py → temporal_edgeset.py} +24 -5
- exonware/xwnode/edges/strategies/{edge_tree_graph_basic.py → tree_graph_basic.py} +78 -7
- exonware/xwnode/edges/strategies/{edge_weighted_graph.py → weighted_graph.py} +188 -10
- exonware/xwnode/errors.py +3 -6
- exonware/xwnode/facade.py +20 -20
- exonware/xwnode/nodes/strategies/__init__.py +29 -9
- exonware/xwnode/nodes/strategies/adjacency_list.py +650 -177
- exonware/xwnode/nodes/strategies/aho_corasick.py +358 -183
- exonware/xwnode/nodes/strategies/array_list.py +36 -3
- exonware/xwnode/nodes/strategies/art.py +581 -0
- exonware/xwnode/nodes/strategies/{node_avl_tree.py → avl_tree.py} +77 -6
- exonware/xwnode/nodes/strategies/{node_b_plus_tree.py → b_plus_tree.py} +81 -40
- exonware/xwnode/nodes/strategies/{node_btree.py → b_tree.py} +79 -9
- exonware/xwnode/nodes/strategies/base.py +469 -98
- exonware/xwnode/nodes/strategies/{node_bitmap.py → bitmap.py} +12 -12
- exonware/xwnode/nodes/strategies/{node_bitset_dynamic.py → bitset_dynamic.py} +11 -11
- exonware/xwnode/nodes/strategies/{node_bloom_filter.py → bloom_filter.py} +15 -2
- exonware/xwnode/nodes/strategies/bloomier_filter.py +519 -0
- exonware/xwnode/nodes/strategies/bw_tree.py +531 -0
- exonware/xwnode/nodes/strategies/contracts.py +1 -1
- exonware/xwnode/nodes/strategies/{node_count_min_sketch.py → count_min_sketch.py} +3 -2
- exonware/xwnode/nodes/strategies/{node_cow_tree.py → cow_tree.py} +135 -13
- exonware/xwnode/nodes/strategies/crdt_map.py +629 -0
- exonware/xwnode/nodes/strategies/{node_cuckoo_hash.py → cuckoo_hash.py} +2 -2
- exonware/xwnode/nodes/strategies/{node_xdata_optimized.py → data_interchange_optimized.py} +21 -4
- exonware/xwnode/nodes/strategies/dawg.py +876 -0
- exonware/xwnode/nodes/strategies/deque.py +321 -153
- exonware/xwnode/nodes/strategies/extendible_hash.py +93 -0
- exonware/xwnode/nodes/strategies/{node_fenwick_tree.py → fenwick_tree.py} +111 -19
- exonware/xwnode/nodes/strategies/hamt.py +403 -0
- exonware/xwnode/nodes/strategies/hash_map.py +354 -67
- exonware/xwnode/nodes/strategies/heap.py +105 -5
- exonware/xwnode/nodes/strategies/hopscotch_hash.py +525 -0
- exonware/xwnode/nodes/strategies/{node_hyperloglog.py → hyperloglog.py} +6 -5
- exonware/xwnode/nodes/strategies/interval_tree.py +742 -0
- exonware/xwnode/nodes/strategies/kd_tree.py +703 -0
- exonware/xwnode/nodes/strategies/learned_index.py +533 -0
- exonware/xwnode/nodes/strategies/linear_hash.py +93 -0
- exonware/xwnode/nodes/strategies/linked_list.py +316 -119
- exonware/xwnode/nodes/strategies/{node_lsm_tree.py → lsm_tree.py} +219 -15
- exonware/xwnode/nodes/strategies/masstree.py +130 -0
- exonware/xwnode/nodes/strategies/{node_persistent_tree.py → persistent_tree.py} +149 -9
- exonware/xwnode/nodes/strategies/priority_queue.py +544 -132
- exonware/xwnode/nodes/strategies/queue.py +249 -120
- exonware/xwnode/nodes/strategies/{node_red_black_tree.py → red_black_tree.py} +183 -72
- exonware/xwnode/nodes/strategies/{node_roaring_bitmap.py → roaring_bitmap.py} +19 -6
- exonware/xwnode/nodes/strategies/rope.py +717 -0
- exonware/xwnode/nodes/strategies/{node_segment_tree.py → segment_tree.py} +106 -106
- exonware/xwnode/nodes/strategies/{node_set_hash.py → set_hash.py} +30 -29
- exonware/xwnode/nodes/strategies/{node_skip_list.py → skip_list.py} +74 -6
- exonware/xwnode/nodes/strategies/sparse_matrix.py +427 -131
- exonware/xwnode/nodes/strategies/{node_splay_tree.py → splay_tree.py} +55 -6
- exonware/xwnode/nodes/strategies/stack.py +244 -112
- exonware/xwnode/nodes/strategies/{node_suffix_array.py → suffix_array.py} +5 -1
- exonware/xwnode/nodes/strategies/t_tree.py +94 -0
- exonware/xwnode/nodes/strategies/{node_treap.py → treap.py} +75 -6
- exonware/xwnode/nodes/strategies/{node_tree_graph_hybrid.py → tree_graph_hybrid.py} +46 -5
- exonware/xwnode/nodes/strategies/trie.py +153 -9
- exonware/xwnode/nodes/strategies/union_find.py +111 -5
- exonware/xwnode/nodes/strategies/veb_tree.py +856 -0
- exonware/xwnode/strategies/__init__.py +5 -51
- exonware/xwnode/version.py +3 -3
- {exonware_xwnode-0.0.1.21.dist-info → exonware_xwnode-0.0.1.23.dist-info}/METADATA +23 -3
- exonware_xwnode-0.0.1.23.dist-info/RECORD +130 -0
- exonware/xwnode/edges/strategies/edge_adj_list.py +0 -353
- exonware/xwnode/edges/strategies/edge_adj_matrix.py +0 -445
- exonware/xwnode/nodes/strategies/_base_node.py +0 -307
- exonware/xwnode/nodes/strategies/node_aho_corasick.py +0 -525
- exonware/xwnode/nodes/strategies/node_array_list.py +0 -179
- exonware/xwnode/nodes/strategies/node_hash_map.py +0 -273
- exonware/xwnode/nodes/strategies/node_heap.py +0 -196
- exonware/xwnode/nodes/strategies/node_linked_list.py +0 -413
- exonware/xwnode/nodes/strategies/node_trie.py +0 -257
- exonware/xwnode/nodes/strategies/node_union_find.py +0 -192
- exonware/xwnode/queries/executors/__init__.py +0 -47
- exonware/xwnode/queries/executors/advanced/__init__.py +0 -37
- exonware/xwnode/queries/executors/advanced/aggregate_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/ask_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/construct_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/describe_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/for_loop_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/foreach_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/join_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/let_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/mutation_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/options_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/pipe_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/subscribe_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/subscription_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/union_executor.py +0 -50
- exonware/xwnode/queries/executors/advanced/window_executor.py +0 -51
- exonware/xwnode/queries/executors/advanced/with_cte_executor.py +0 -50
- exonware/xwnode/queries/executors/aggregation/__init__.py +0 -21
- exonware/xwnode/queries/executors/aggregation/avg_executor.py +0 -50
- exonware/xwnode/queries/executors/aggregation/count_executor.py +0 -38
- exonware/xwnode/queries/executors/aggregation/distinct_executor.py +0 -50
- exonware/xwnode/queries/executors/aggregation/group_executor.py +0 -50
- exonware/xwnode/queries/executors/aggregation/having_executor.py +0 -50
- exonware/xwnode/queries/executors/aggregation/max_executor.py +0 -50
- exonware/xwnode/queries/executors/aggregation/min_executor.py +0 -50
- exonware/xwnode/queries/executors/aggregation/sum_executor.py +0 -50
- exonware/xwnode/queries/executors/aggregation/summarize_executor.py +0 -50
- exonware/xwnode/queries/executors/array/__init__.py +0 -9
- exonware/xwnode/queries/executors/array/indexing_executor.py +0 -51
- exonware/xwnode/queries/executors/array/slicing_executor.py +0 -51
- exonware/xwnode/queries/executors/base.py +0 -257
- exonware/xwnode/queries/executors/capability_checker.py +0 -204
- exonware/xwnode/queries/executors/contracts.py +0 -166
- exonware/xwnode/queries/executors/core/__init__.py +0 -17
- exonware/xwnode/queries/executors/core/create_executor.py +0 -96
- exonware/xwnode/queries/executors/core/delete_executor.py +0 -99
- exonware/xwnode/queries/executors/core/drop_executor.py +0 -100
- exonware/xwnode/queries/executors/core/insert_executor.py +0 -39
- exonware/xwnode/queries/executors/core/select_executor.py +0 -152
- exonware/xwnode/queries/executors/core/update_executor.py +0 -102
- exonware/xwnode/queries/executors/data/__init__.py +0 -13
- exonware/xwnode/queries/executors/data/alter_executor.py +0 -50
- exonware/xwnode/queries/executors/data/load_executor.py +0 -50
- exonware/xwnode/queries/executors/data/merge_executor.py +0 -50
- exonware/xwnode/queries/executors/data/store_executor.py +0 -50
- exonware/xwnode/queries/executors/defs.py +0 -93
- exonware/xwnode/queries/executors/engine.py +0 -221
- exonware/xwnode/queries/executors/errors.py +0 -68
- exonware/xwnode/queries/executors/filtering/__init__.py +0 -25
- exonware/xwnode/queries/executors/filtering/between_executor.py +0 -80
- exonware/xwnode/queries/executors/filtering/filter_executor.py +0 -79
- exonware/xwnode/queries/executors/filtering/has_executor.py +0 -70
- exonware/xwnode/queries/executors/filtering/in_executor.py +0 -70
- exonware/xwnode/queries/executors/filtering/like_executor.py +0 -76
- exonware/xwnode/queries/executors/filtering/optional_executor.py +0 -76
- exonware/xwnode/queries/executors/filtering/range_executor.py +0 -80
- exonware/xwnode/queries/executors/filtering/term_executor.py +0 -77
- exonware/xwnode/queries/executors/filtering/values_executor.py +0 -71
- exonware/xwnode/queries/executors/filtering/where_executor.py +0 -44
- exonware/xwnode/queries/executors/graph/__init__.py +0 -15
- exonware/xwnode/queries/executors/graph/in_traverse_executor.py +0 -51
- exonware/xwnode/queries/executors/graph/match_executor.py +0 -51
- exonware/xwnode/queries/executors/graph/out_executor.py +0 -51
- exonware/xwnode/queries/executors/graph/path_executor.py +0 -51
- exonware/xwnode/queries/executors/graph/return_executor.py +0 -51
- exonware/xwnode/queries/executors/ordering/__init__.py +0 -9
- exonware/xwnode/queries/executors/ordering/by_executor.py +0 -50
- exonware/xwnode/queries/executors/ordering/order_executor.py +0 -51
- exonware/xwnode/queries/executors/projection/__init__.py +0 -9
- exonware/xwnode/queries/executors/projection/extend_executor.py +0 -50
- exonware/xwnode/queries/executors/projection/project_executor.py +0 -50
- exonware/xwnode/queries/executors/registry.py +0 -173
- exonware/xwnode/queries/parsers/__init__.py +0 -26
- exonware/xwnode/queries/parsers/base.py +0 -86
- exonware/xwnode/queries/parsers/contracts.py +0 -46
- exonware/xwnode/queries/parsers/errors.py +0 -53
- exonware/xwnode/queries/parsers/sql_param_extractor.py +0 -318
- exonware/xwnode/queries/strategies/__init__.py +0 -24
- exonware/xwnode/queries/strategies/base.py +0 -236
- exonware/xwnode/queries/strategies/cql.py +0 -201
- exonware/xwnode/queries/strategies/cypher.py +0 -181
- exonware/xwnode/queries/strategies/datalog.py +0 -70
- exonware/xwnode/queries/strategies/elastic_dsl.py +0 -70
- exonware/xwnode/queries/strategies/eql.py +0 -70
- exonware/xwnode/queries/strategies/flux.py +0 -70
- exonware/xwnode/queries/strategies/gql.py +0 -70
- exonware/xwnode/queries/strategies/graphql.py +0 -240
- exonware/xwnode/queries/strategies/gremlin.py +0 -181
- exonware/xwnode/queries/strategies/hiveql.py +0 -214
- exonware/xwnode/queries/strategies/hql.py +0 -70
- exonware/xwnode/queries/strategies/jmespath.py +0 -219
- exonware/xwnode/queries/strategies/jq.py +0 -66
- exonware/xwnode/queries/strategies/json_query.py +0 -66
- exonware/xwnode/queries/strategies/jsoniq.py +0 -248
- exonware/xwnode/queries/strategies/kql.py +0 -70
- exonware/xwnode/queries/strategies/linq.py +0 -238
- exonware/xwnode/queries/strategies/logql.py +0 -70
- exonware/xwnode/queries/strategies/mql.py +0 -68
- exonware/xwnode/queries/strategies/n1ql.py +0 -210
- exonware/xwnode/queries/strategies/partiql.py +0 -70
- exonware/xwnode/queries/strategies/pig.py +0 -215
- exonware/xwnode/queries/strategies/promql.py +0 -70
- exonware/xwnode/queries/strategies/sparql.py +0 -220
- exonware/xwnode/queries/strategies/sql.py +0 -275
- exonware/xwnode/queries/strategies/xml_query.py +0 -66
- exonware/xwnode/queries/strategies/xpath.py +0 -223
- exonware/xwnode/queries/strategies/xquery.py +0 -258
- exonware/xwnode/queries/strategies/xwnode_executor.py +0 -332
- exonware/xwnode/queries/strategies/xwquery.py +0 -456
- exonware_xwnode-0.0.1.21.dist-info/RECORD +0 -214
- /exonware/xwnode/nodes/strategies/{node_ordered_map.py → ordered_map.py} +0 -0
- /exonware/xwnode/nodes/strategies/{node_ordered_map_balanced.py → ordered_map_balanced.py} +0 -0
- /exonware/xwnode/nodes/strategies/{node_patricia.py → patricia.py} +0 -0
- /exonware/xwnode/nodes/strategies/{node_radix_trie.py → radix_trie.py} +0 -0
- /exonware/xwnode/nodes/strategies/{node_set_tree.py → set_tree.py} +0 -0
- {exonware_xwnode-0.0.1.21.dist-info → exonware_xwnode-0.0.1.23.dist-info}/WHEEL +0 -0
- {exonware_xwnode-0.0.1.21.dist-info → exonware_xwnode-0.0.1.23.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,168 @@
|
|
1
|
+
"""
|
2
|
+
#exonware/xwnode/src/exonware/xwnode/edges/strategies/edge_edge_list.py
|
3
|
+
|
4
|
+
Edge List Edge Strategy Implementation
|
5
|
+
|
6
|
+
Company: eXonware.com
|
7
|
+
Author: Eng. Muhammad AlShehri
|
8
|
+
Email: connect@exonware.com
|
9
|
+
Version: 0.0.1.23
|
10
|
+
Generation Date: 11-Oct-2025
|
11
|
+
"""
|
12
|
+
|
13
|
+
from typing import Any, Iterator, Dict, List, Set, Optional
|
14
|
+
from ._base_edge import AEdgeStrategy
|
15
|
+
from ...defs import EdgeMode, EdgeTrait
|
16
|
+
|
17
|
+
|
18
|
+
class EdgeListStrategy(AEdgeStrategy):
|
19
|
+
"""
|
20
|
+
Edge List - Simple list of (source, target) pairs.
|
21
|
+
|
22
|
+
WHY this strategy:
|
23
|
+
- Simplest possible graph representation
|
24
|
+
- Universal file format (SNAP datasets, NetworkX, GraphML)
|
25
|
+
- Minimal memory overhead - just edge tuples
|
26
|
+
- Trivial serialization/deserialization
|
27
|
+
|
28
|
+
WHY this implementation:
|
29
|
+
- Python list of edge dicts for simplicity
|
30
|
+
- Linear storage matches file format exactly
|
31
|
+
- Node set tracking for vertex iteration
|
32
|
+
- No indexing overhead - pure sequential storage
|
33
|
+
|
34
|
+
Time Complexity:
|
35
|
+
- Add Edge: O(1) - append to list
|
36
|
+
- Has Edge: O(E) - linear scan
|
37
|
+
- Get Neighbors: O(E) - scan all edges
|
38
|
+
- Remove Edge: O(E) - linear search and remove
|
39
|
+
- Iteration: O(E) - direct list iteration
|
40
|
+
|
41
|
+
Space Complexity: O(E) - minimal overhead
|
42
|
+
|
43
|
+
Trade-offs:
|
44
|
+
- Advantage: Simplest format, minimal memory, fast I/O
|
45
|
+
- Limitation: Slow for all queries except iteration
|
46
|
+
- Compared to ADJ_LIST: Use only for storage/transport
|
47
|
+
|
48
|
+
Best for:
|
49
|
+
- Graph file I/O (reading/writing edge lists)
|
50
|
+
- Data interchange (network datasets, graph databases)
|
51
|
+
- Initial graph loading (convert to better format after)
|
52
|
+
- Minimal memory scenarios
|
53
|
+
- Streaming edge data collection
|
54
|
+
|
55
|
+
Not recommended for:
|
56
|
+
- Any graph algorithms - convert first
|
57
|
+
- Production queries - too slow
|
58
|
+
- Interactive applications - needs indexing
|
59
|
+
|
60
|
+
Following eXonware Priorities:
|
61
|
+
1. Security: Simple format reduces attack surface
|
62
|
+
2. Usability: Trivial to understand and use
|
63
|
+
3. Maintainability: Minimal code, no complex logic
|
64
|
+
4. Performance: Fast sequential access, slow queries
|
65
|
+
5. Extensibility: Easy to add filters, transformations
|
66
|
+
"""
|
67
|
+
|
68
|
+
def __init__(self, traits: EdgeTrait = EdgeTrait.NONE, **options):
|
69
|
+
super().__init__(EdgeMode.EDGE_LIST, traits, **options)
|
70
|
+
self._edges: List[Dict[str, Any]] = []
|
71
|
+
self._nodes: Set[str] = set()
|
72
|
+
self._edge_id_counter = 0
|
73
|
+
|
74
|
+
def get_supported_traits(self) -> EdgeTrait:
|
75
|
+
return EdgeTrait.SPARSE | EdgeTrait.DIRECTED
|
76
|
+
|
77
|
+
def add_edge(self, source: str, target: str, **properties) -> str:
|
78
|
+
"""Add edge to list."""
|
79
|
+
edge_id = f"edge_{self._edge_id_counter}"
|
80
|
+
self._edge_id_counter += 1
|
81
|
+
|
82
|
+
edge_data = {
|
83
|
+
'id': edge_id,
|
84
|
+
'source': source,
|
85
|
+
'target': target,
|
86
|
+
'properties': properties.copy()
|
87
|
+
}
|
88
|
+
|
89
|
+
self._edges.append(edge_data)
|
90
|
+
self._nodes.add(source)
|
91
|
+
self._nodes.add(target)
|
92
|
+
self._edge_count += 1
|
93
|
+
|
94
|
+
return edge_id
|
95
|
+
|
96
|
+
def remove_edge(self, source: str, target: str, edge_id: Optional[str] = None) -> bool:
|
97
|
+
"""Remove edge from list (O(n) operation)."""
|
98
|
+
removed = False
|
99
|
+
|
100
|
+
if edge_id:
|
101
|
+
self._edges = [e for e in self._edges if e['id'] != edge_id]
|
102
|
+
removed = True
|
103
|
+
else:
|
104
|
+
original_len = len(self._edges)
|
105
|
+
self._edges = [e for e in self._edges
|
106
|
+
if not (e['source'] == source and e['target'] == target)]
|
107
|
+
removed = len(self._edges) < original_len
|
108
|
+
|
109
|
+
if removed:
|
110
|
+
self._edge_count = len(self._edges)
|
111
|
+
|
112
|
+
return removed
|
113
|
+
|
114
|
+
def has_edge(self, source: str, target: str) -> bool:
|
115
|
+
"""Check if edge exists."""
|
116
|
+
return any(e['source'] == source and e['target'] == target for e in self._edges)
|
117
|
+
|
118
|
+
def neighbors(self, node: str) -> Iterator[Any]:
|
119
|
+
"""Get neighbors of node (required by base class)."""
|
120
|
+
return iter(self.get_neighbors(node, "outgoing"))
|
121
|
+
|
122
|
+
def get_neighbors(self, node: str, direction: str = "outgoing") -> List[str]:
|
123
|
+
"""Get neighbors (O(m) where m = total edges)."""
|
124
|
+
neighbors = set()
|
125
|
+
|
126
|
+
for edge in self._edges:
|
127
|
+
if direction == "outgoing" and edge['source'] == node:
|
128
|
+
neighbors.add(edge['target'])
|
129
|
+
elif direction == "incoming" and edge['target'] == node:
|
130
|
+
neighbors.add(edge['source'])
|
131
|
+
elif direction == "both":
|
132
|
+
if edge['source'] == node:
|
133
|
+
neighbors.add(edge['target'])
|
134
|
+
elif edge['target'] == node:
|
135
|
+
neighbors.add(edge['source'])
|
136
|
+
|
137
|
+
return list(neighbors)
|
138
|
+
|
139
|
+
def degree(self, node: str) -> int:
|
140
|
+
"""Get degree of node."""
|
141
|
+
return len(self.get_neighbors(node, "both"))
|
142
|
+
|
143
|
+
def edges(self) -> Iterator[tuple[Any, Any, Dict[str, Any]]]:
|
144
|
+
"""Iterator over edges."""
|
145
|
+
for edge in self._edges:
|
146
|
+
yield (edge['source'], edge['target'], edge['properties'])
|
147
|
+
|
148
|
+
def vertices(self) -> Iterator[Any]:
|
149
|
+
"""Iterator over vertices."""
|
150
|
+
return iter(self._nodes)
|
151
|
+
|
152
|
+
def __len__(self) -> int:
|
153
|
+
"""Get number of edges."""
|
154
|
+
return len(self._edges)
|
155
|
+
|
156
|
+
def to_native(self) -> List[tuple[str, str]]:
|
157
|
+
"""Convert to simple edge list format."""
|
158
|
+
return [(e['source'], e['target']) for e in self._edges]
|
159
|
+
|
160
|
+
def get_backend_info(self) -> Dict[str, Any]:
|
161
|
+
"""Get backend info."""
|
162
|
+
return {
|
163
|
+
'strategy': 'Edge List',
|
164
|
+
'description': 'Simple edge list format',
|
165
|
+
'total_edges': len(self._edges),
|
166
|
+
'total_nodes': len(self._nodes)
|
167
|
+
}
|
168
|
+
|
@@ -8,7 +8,7 @@ edge attribute storage with efficient analytical queries.
|
|
8
8
|
from typing import Any, Iterator, List, Dict, Set, Optional, Tuple, Union
|
9
9
|
from collections import defaultdict
|
10
10
|
import statistics
|
11
|
-
from ._base_edge import
|
11
|
+
from ._base_edge import AEdgeStrategy
|
12
12
|
from ...defs import EdgeMode, EdgeTrait
|
13
13
|
|
14
14
|
|
@@ -143,7 +143,7 @@ class PropertyColumn:
|
|
143
143
|
return len(self.values)
|
144
144
|
|
145
145
|
|
146
|
-
class
|
146
|
+
class EdgePropertyStoreStrategy(AEdgeStrategy):
|
147
147
|
"""
|
148
148
|
Edge Property Store strategy for columnar edge attributes.
|
149
149
|
|