Skip to content

Commit 5085c60

Browse files
authored
Edge desc (#23)
* docs: document index-only vertex descriptor aliases and constraints - vertex-patterns.md: add index_only_vertex/container_backed_vertex to Foundation Concepts table; add note to Storage Concepts about direct_vertex_type covering both container and index-only iterators; add requires notes to inner_value/underlying_value in Member Functions; add new Index-Only Aliases section with usage example - concepts.md: add index_only_vertex and container_backed_vertex to Descriptor Concepts table - archive/descriptor.md: add index-only iterator category to vertex descriptor spec * refactor: remove index storage path from edge_descriptor; simplify vertices(g) edge_descriptor always stores EdgeIter directly — edges always have physical containers, so the conditional_t<random_access_iterator<EdgeIter>, size_t, EdgeIter> dual-storage path was unnecessary overhead. This eliminates 38 if constexpr branches across 6 files (~380 lines removed). compressed_graph: vertices(g) now returns iota_view<size_t,size_t>(0, n), which the vertices CPO wraps automatically via _wrap_if_needed. The empty-graph special case is no longer needed. vertex_descriptor_view: CTAD deduction guides updated to use std::ranges::iterator_t<> so they work with views (e.g. iota_view) that lack Container::iterator/const_iterator nested types. edge_descriptor_view: Fixed forward_list compatibility — removed spurious sized_range constraint from container constructor, changed if to if constexpr so std::ranges::size() is not compiled for non-sized ranges. Tests: Rewrote test_edge_descriptor.cpp and test_descriptor_traits.cpp for iterator-based storage. Updated test_compressed_graph_cpo.cpp (21 call sites replaced). Fixed pre-existing ODR violation in test_source_id_cpo.cpp (namespace rename to avoid CustomEdge collision). Fixed test_edge_value_cpo.cpp custom graph structs to dereference iterators. Fixed unused vertex_data parameters. * docs: update documentation for edge_descriptor iterator-only storage - CHANGELOG: add entries for edge_descriptor simplification, vertices(g) iota_view, CTAD guide update, and edge_descriptor_view forward_list fix - vertex-patterns.md: CTAD guides now show std::ranges::iterator_t<> - adjacency-list-interface.md: edge_descriptor wraps iterator (not index) - edge-value-concepts.md: target_id() always dereferences stored iterator - adjacency-lists.md: fix edge_descriptor template parameter names - archive/descriptor.md: spec updated for iterator-only edge storage - bgl2_comparison_result.md: updated code sample and size comparison - archive/edge_map_analysis.md: updated code sample * Update BGL2 comparison query and results with expanded selectors, design features, and algorithm inventory
1 parent 7645a19 commit 5085c60

20 files changed

Lines changed: 851 additions & 1734 deletions

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@
1515
- 456 new algorithm tests for sparse graph types (4343 → 4799)
1616

1717
### Changed
18+
- **`edge_descriptor` simplified to iterator-only storage** — removed the `conditional_t<random_access_iterator, size_t, EdgeIter>` dual-storage path; edges always store the iterator directly since edges always have physical containers. Eliminates 38 `if constexpr` branches across 6 files (~500 lines removed).
19+
- **`compressed_graph::vertices(g)` returns `iota_view`** — simplified to `std::ranges::iota_view<size_t, size_t>(0, num_vertices())`, which the `vertices` CPO wraps automatically via `_wrap_if_needed`.
20+
- **`vertex_descriptor_view` CTAD deduction guides** — updated from `Container::iterator`/`const_iterator` to `std::ranges::iterator_t<>` for compatibility with views like `iota_view`.
21+
- **`edge_descriptor_view` forward_list compatibility** — fixed constructor to use `if constexpr` for `sized_range` check so `std::ranges::size()` is not compiled for non-sized ranges like `forward_list`.
1822
- All algorithms relaxed from `index_adjacency_list<G>` to `adjacency_list<G>`
1923
- Algorithm internal arrays use `make_vertex_property_map` (vector or unordered_map depending on graph type)
2024
- User-facing `Distances`, `Predecessors`, `Weight`, `Component`, `Label` parameters accept vertex property maps

agents/bgl2_comparison_query.md

Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,31 +12,82 @@ BGL2 now supports 10 container selectors defined in `container_selectors.hpp`:
1212
| `vecS` | `std::vector` | O(1) random access, index-based descriptors |
1313
| `listS` | `std::list` | O(1) insertion/removal, stable iterator-based descriptors |
1414
| `setS` | `std::set` | O(log n), ordered unique elements, stable iterators |
15-
| `mapS` | `std::set` (for edges) | O(log n), key-value storage, prevents parallel edges |
15+
| `mapS` | `std::set` (for edges) | O(log n), prevents parallel edges, stable iterators |
1616
| `multisetS` | `std::multiset` | O(log n), ordered with duplicates allowed |
1717
| `multimapS` | `std::multiset` (for edges) | O(log n), duplicate keys allowed |
18-
| `hash_setS` | `std::unordered_set` | O(1) average, hash-based unique |
19-
| `hash_mapS` | `std::unordered_set` (for edges) | O(1) average, hash-based |
20-
| `hash_multisetS` | `std::unordered_multiset` | O(1) average, duplicates allowed |
21-
| `hash_multimapS` | `std::unordered_multiset` (for edges) | O(1) average, duplicate keys |
18+
| `hash_setS` | `std::unordered_set` | O(1) average, hash-based unique, **unstable iterators** |
19+
| `hash_mapS` | `std::unordered_set` (for edges) | O(1) average, hash-based, **unstable iterators** |
20+
| `hash_multisetS` | `std::unordered_multiset` | O(1) average, duplicates allowed, **unstable iterators** |
21+
| `hash_multimapS` | `std::unordered_multiset` (for edges) | O(1) average, duplicate keys, **unstable iterators** |
22+
23+
> **Note on "map" selectors:** Despite having "map" in their names, `mapS`/`multimapS`/`hash_mapS`/`hash_multimapS` all map to **set** containers (not `std::map`). The "map" name reflects the vertex→edge *mapping semantic*, not the container type. The uniqueness/ordering behavior of the underlying set provides the desired parallel-edge control.
2224
2325
The `adjacency_list.hpp` provides implementations for:
2426
- **Vertex list selectors:** `vecS` (index-based), `listS` (iterator-based), `setS` (iterator-based)
2527
- **Out-edge list selectors:** All 10 selectors work for edge containers
2628

2729
**Key BGL2 Design Features:**
28-
- Selector concepts: `ContainerSelector`, `SequenceSelector`, `AssociativeSelector`, `UnorderedSelector`
29-
- Selector traits: `is_random_access`, `has_stable_iterators`, `is_ordered`, `is_unique`
30+
- Selector concepts: `ContainerSelector`, `SequenceSelector`, `AssociativeSelector`, `UnorderedSelector`, `StableIteratorSelector`, `RandomAccessSelector`
31+
- Selector traits (per-selector `static constexpr bool`): `is_random_access`, `has_stable_iterators`, `is_ordered`, `is_unique`
3032
- `container_gen<Selector, ValueType>` maps selectors to container types
3133
- `parallel_edge_category_for<OutEdgeListS>` determines if parallel edges are allowed (based on `is_unique`)
3234

35+
**BGL2 Additional Graph Containers:**
36+
- `adjacency_matrix.hpp` — dense adjacency matrix representation (fixed vertex count, O(V²) space, O(1) edge lookup)
37+
- `compressed_sparse_row_graph.hpp` — CSR (compressed sparse row) graph (static, cache-efficient)
38+
- `grid_graph.hpp` — N-dimensional implicit grid graph (O(1) space, used in image processing / scientific computing)
39+
40+
**BGL2 Additional Design Features:**
41+
- `strong_descriptor.hpp` — type-safe `descriptor<Tag>` wrapper preventing vertex/edge descriptor mix-ups at compile time
42+
- `validation.hpp``validate_graph()` framework checking dangling edges, self-loops, parallel edges, bidirectional consistency, etc.
43+
- `algorithm_params.hpp` / `algorithm_result.hpp` — named parameter structs (C++20 designated initializers) and rich result types (e.g., `dijkstra_result` with `path_to()`, `is_reachable()`)
44+
- `visitor_callbacks.hpp` — 9-event BFS/DFS callback structs with `null_callback` defaults and single-event wrappers
45+
- `composable_algorithms.hpp` — range adaptors: `find_components()`, `find_distances_from()`, `find_k_core()`, `find_neighbors()`, `find_common_neighbors()`, `degree_distribution()`
46+
- `parallel_algorithms.hpp``parallel_bfs()` (level-synchronous), `parallel_connected_components()` (Shiloach-Vishkin), `parallel_for_each_vertex/edge()`
47+
- `coroutine_traverse.hpp` — lazy coroutine-based BFS/DFS: `bfs_traverse()`, `dfs_traverse()`, multi-source and all-components variants
48+
- `MutableGraph` concept — individual `add_vertex()`, `remove_vertex()`, `add_edge()`, `remove_edge()`
49+
50+
**Graph-v3 Key Design Features (for comparison context):**
51+
- Concept-based CPO design — any type satisfying graph concepts works with algorithms (no adaptor class needed). A `vector<vector<int>>` or user-defined container works directly.
52+
- Trait-based container configuration (27 trait combinations: `vov`, `vofl`, `mol`, `dov`, etc.) vs BGL2's selector-based approach
53+
- 3 graph containers: `dynamic_graph` (mutable adjacency list), `compressed_graph` (CSR), `undirected_adjacency_list` (dual-list with O(1) edge removal from both endpoints)
54+
- `edge_list` module — standalone edge list support for `pair<T,T>`, `tuple<T,T,EV,...>`, and `edge_data` structs
55+
- Edge descriptors always store the edge iterator directly (no conditional `size_t`/iterator storage)
56+
- Vertex descriptors use `size_t` for index-based graphs, iterator otherwise
57+
- 13 view headers — lazy range adaptors including traversal views (`vertices_dfs()`, `edges_bfs()`, `vertices_topological_sort()`) and pipe syntax (`g | vertexlist() | ...`)
58+
- `dynamic_graph` mutations are batch-oriented (`load_edges()`, `load_vertices()`) — no individual `add_vertex()` / `remove_vertex()` / `add_edge()` / `remove_edge()`
59+
- `vertex_property_map<G, T>``vector<T>` for index graphs, `unordered_map<VId, T>` for mapped graphs, with `container_value_fn()` wrapping for algorithm compatibility
60+
- Visitor-based algorithms: BFS/DFS support `on_discover_vertex`, `on_examine_edge`, `on_tree_edge`, `on_back_edge`, etc.
61+
62+
**Algorithm Inventory:**
63+
64+
| Algorithm | BGL2 | Graph-v3 |
65+
|-----------|------|----------|
66+
| BFS |||
67+
| DFS | ✅ (edge classification) | ✅ (edge classification) |
68+
| Dijkstra shortest paths || ✅ (multi-source) |
69+
| Bellman-Ford shortest paths | ✅ (negative cycle detection) | ✅ (negative cycle detection) |
70+
| Topological sort || ✅ (full-graph, single-source, multi-source) |
71+
| Connected components || ✅ (DFS-based + afforest) |
72+
| MST (Kruskal + Prim) | ✅ (separate headers) | ✅ (combined mst.hpp, includes in-place Kruskal) |
73+
| Strongly connected components | ✅ (Tarjan) | ✅ (Kosaraju, 2 overloads: transpose or bidirectional) |
74+
| Triangle counting || ✅ (undirected + directed) |
75+
| Articulation points || ✅ (iterative Hopcroft-Tarjan) |
76+
| Biconnected components || ✅ (Hopcroft-Tarjan with edge stack) |
77+
| Jaccard similarity || ✅ (per-edge coefficient) |
78+
| Label propagation || ✅ (community detection) |
79+
| Maximum independent set || ✅ (greedy) |
80+
| Composable algorithms | ✅ (k-core, degree dist, etc.) ||
81+
| Coroutine traversal | ✅ (lazy BFS/DFS generators) ||
82+
| Parallel algorithms | ✅ (parallel BFS, parallel CC) ||
83+
3384
Compare and contrast BGL2 with the current library (graph-v3), making sure that the following topics are covered:
3485
- The differences between the vertex and edge descriptors.
3586
- The ability to adapt to pre-existing graph data structures.
3687
- Strengths and weaknesses in the capabilities of each library.
3788
- Container flexibility: BGL2's selector-based approach vs graph-v3's trait-based approach.
3889
- Other areas of interest in the design and flexibility for the libraries.
3990

40-
Algorithms have not been implemented for graph-v3 and is a known limitation.
91+
Compare and contrast the algorithms implemented in each library.
4192

42-
Output the result to `agents/bgl2_comparison_result.md`.
93+
Replace the contents of `agents/bgl2_comparison_result.md` with the result.

0 commit comments

Comments
 (0)