Skip to content

Commit 7db942f

Browse files
authored
Mapped (#9)
* agents: archive completed planning documents * refactor: simplify index_vertex_range, add underlying_iterator alias to vertex_descriptor_view - index_vertex_range now checks std::integral<vertex_range_t<G>::storage_type> instead of digging through vertex_desc::iterator_type — reflects the true semantic intent (vertices addressable by integral index) - Add underlying_iterator = VertexIter alias on vertex_descriptor_view for direct access to the underlying container iterator type * docs: add map-based container strategy and implementation plan - map_container_strategy.md: design strategy with concepts, vertex_map, algorithm generalization patterns, and settled design decisions - map_container_plan.md: phased implementation plan (10 phases, 55 sub-phases) with review gates and progress tracking table * chore: snapshot index-only algorithm implementations for reference Copy all 14 algorithm .hpp files to include/graph/algorithm/index/ as byte-identical reference snapshots before map-based generalization. This directory is a temporary review aid and not part of the public API. * feat: add mapped_adjacency_list concepts and vertex_map infrastructure - Add hashable_vertex_id, mapped_vertex_range, mapped_adjacency_list, mapped_bidirectional_adjacency_list concepts to adjacency_list_concepts.hpp (mutually exclusive with index_vertex_range) - Create vertex_map.hpp: vertex_map<G,T> type alias (vector for index, unordered_map for mapped), make_vertex_map (eager+lazy), vertex_map_contains, vertex_map_get (no-insertion read with default fallback) - Add is_null_range_v<T> trait to traversal_common.hpp - Create map_graph_fixtures.hpp with sparse-ID graph factories - Add test_vertex_map.cpp (13 tests) and test_mapped_concepts.cpp (11 tests) - All 4367 tests pass (4343 existing + 24 new) * refactor: rename vertex_map to vertex_property_map, add vertex_property_map_for concept - Rename vertex_map.hpp → vertex_property_map.hpp, test_vertex_map.cpp → test_vertex_property_map.cpp - Rename all identifiers: vertex_map → vertex_property_map, make_vertex_map → make_vertex_property_map, vertex_map_contains → vertex_property_map_contains, vertex_map_get → vertex_property_map_get, vertex_map_value_t → vertex_property_map_value_t - Add vertex_property_map_for<M, G> concept: requires m[uid] subscript access with vertex_id_t<G>, replacing forward_range on Dijkstra's Distances and Predecessors template parameters - Dijkstra requires clause now uses vertex_property_map_for<Distances, G> and (is_null_range_v<Predecessors> || vertex_property_map_for<Predecessors, G>) - Add BFS and Dijkstra sparse/string-VId tests - All 4445 tests pass * feat: generalize BFS, DFS, topological_sort for mapped graphs - Relax concept: index_adjacency_list → adjacency_list for all three traversal algorithms (BFS was done earlier, DFS and topo_sort in this commit) - Replace std::vector<Color/bool> with lazy vertex_property_map: index graphs get value-initialized vector, mapped graphs get empty reserved map with absent-key defaults via vertex_property_map_get - Remove vertex_id_store_t static_asserts, simplify to vertex_id_t<G> - Hoist topo_sort Color enum to detail::TopoColor (shared across functions) - Add 36 sparse DFS tests (6 cases × 6 SPARSE_VERTEX_TYPES) - Add 36 sparse topological_sort tests (6 cases × 6 SPARSE_VERTEX_TYPES) - Add cycle_graph fixture to map_graph_fixtures.hpp - All 4517 tests pass (35 original topo + 36 new sparse topo, 29 original DFS + 36 new sparse DFS) * feat: generalize init_shortest_paths for mapped graphs Add graph-parameterized init_shortest_paths overloads that accept const G& as the first parameter, enabling correct initialization for both index-based (vector) and map-based (unordered_map) containers. - Index graphs: identical fill/iota behavior to legacy overloads - Mapped graphs (empty): populate all vertices from vertexlist(g) - Mapped graphs (pre-populated): fill existing entries - _null_range_type predecessors skipped via is_null_range_v Phase 3 of map_container_plan. * feat: generalize bellman_ford for mapped graphs Generalize bellman_ford_shortest_paths, bellman_ford_shortest_distances, and find_negative_cycle to work with both index and map-based graph types. - Relax concept from index_adjacency_list to adjacency_list - Replace random_access_range with vertex_property_map_for constraints - Remove static_cast<size_t> — use direct operator[] access - Gate size checks with index_vertex_range (index graphs only) - Add overflow guard in relax_target (d_u == infinite → skip) - find_negative_cycle: const-correct map access via .at() - 42 new sparse graph tests (7 test cases × 6 map-based types) Phase 4.3-4.5 of map_container_plan. * perf: use vertex descriptors in component and Dijkstra algorithms - connected_components, kosaraju: store vertex_t<G> (8-byte descriptors) on stacks/vectors instead of vertex_id_t<G>, eliminating string copies for map-based graphs and removing find_vertex on pop via views::incidence(g, descriptor) - dijkstra_shortest_paths: priority queue stores vertex_t<G> instead of vertex_id_t<G>, eliminating string copies on push and find_vertex on pop/incidence/visitor callbacks; one find_vertex per neighbor push remains (unavoidable: target_id returns vertex_id_t<G>) - Remove store_vertex_id helper from traversal_common.hpp - Add sparse vertex tests for connected_components and afforest * docs: update map_container_plan.md — Phase 5 + descriptor optimization complete * feat: generalize jaccard, mis, triangle_count, label_propagation for mapped graphs - jaccard_coefficient: adjacency_list concept, vertex_property_map for neighbor sets, descriptor-based incidence in Phase 2 - maximal_independent_set: adjacency_list concept, vertex_property_map for removed tracking, find_vertex for seed validation - triangle_count: adjacency_list concept, vertices(g) iteration replacing index loop - label_propagation: adjacency_list concept, vertex_property_map_for constraint on Label parameter, vertex iteration for order vector (both overloads) - Added sparse TEMPLATE_TEST_CASE tests for all four algorithms (96 new tests) - All 4709 tests pass * docs: mark Phase 6 complete in map_container_plan.md * feat: generalize articulation_points, biconnected_components for mapped graphs - Relax concept from index_adjacency_list to adjacency_list - Replace internal vector<T> arrays with vertex_property_map (3-5 per algo) - Replace broken static_cast<vid_t>(N) parent sentinel with std::optional<vid_t> - Store edge iterators on DFS stack for O(1) resume (was O(degree) re-scan) - Use edges(g, uid) + target_id(g, *it) CPOs instead of internal view members - Iterate via views::basic_vertexlist(g) instead of vertices(g) + vertex_id() - Add 30 sparse TEMPLATE_TEST_CASE tests per algorithm (5 topologies x 6 types) - All 4769 tests pass * feat: generalize prim MST for mapped graphs - Relax prim() from index_adjacency_list to adjacency_list concept - Predecessor/Weight params: random_access_range -> vertex_property_map_for - Internal distance array uses make_vertex_property_map (vector or map) - Validation: if constexpr index_vertex_range for size checks, find_vertex for mapped - Total weight loop uses basic_vertexlist instead of index loop - Kruskal unchanged: edge-list-centric API already handles sparse integral IDs - Add 30 sparse prim tests (5 cases x 6 SPARSE_VERTEX_TYPES) - 4799 tests pass * chore: update docs for mapped graph algorithm support - CHANGELOG: document mapped graph features, 456 new tests (4343 -> 4799) - algorithms.md: update overview for adjacency_list (index + mapped) - algorithms.md: add map-based graph usage example with vertex_property_map - concepts.md: update hierarchy with mapped_vertex_range, mapped_adjacency_list - concepts.md: correct adjacency_list definition (no longer requires index_vertex_range) * docs: update algorithm docs for adjacency_list + vertex_property_map - Relax graph concept from index_adjacency_list to adjacency_list in all algorithm pages (bfs, dfs, topological_sort, dijkstra, bellman_ford, connected_components, mst, jaccard, mis, triangle_count, label_propagation, articulation_points, biconnected_components) - Update parameter tables: distances/predecessors/component/label/weights now document vertex_property_map_for constraint and make_vertex_property_map usage - Update preconditions: replace 'sized to num_vertices(g)' with 'must satisfy vertex_property_map_for' - Add mapped_adjacency_list to Graph concepts table in adjacency-lists.md - Add Section 5 'Vertex Property Maps' to adjacency-lists.md covering the type alias, factory functions, access helpers, concept, and type trait - Update adjacency-lists.md: all algorithms accept adjacency_list, not just index_adjacency_list fix: vertex_property_map_contains bounds-checks uid for index graphs - Change vector branch from unconditional 'return true' to 'return static_cast<size_t>(uid) < std::ranges::size(m)' - Update test: rename 'always true' case to 'bounds check', add out-of-range assertions - Update doxygen comment and docs table entry * refactor: remove legacy init_shortest_paths overloads, require graph param - Remove the two graph-unaware overloads of init_shortest_paths (no G param). They only worked for index graphs (random_access_range) and broke silently for mapped containers. - Add requires clauses to both graph-aware overloads: adjacency_list<G> && vertex_property_map_for<Distances, G> and (vertex_property_map_for<Predecessors, G> || is_null_range_v<Predecessors>) for the three-arg form. - Update all 27 call sites in test_dijkstra_shortest_paths.cpp and test_bellman_ford_shortest_paths.cpp to pass g as first argument. * Add uniform property access goal and strategy docs Adds agents/uniform_prop_goal.md describing the design intent for uniform property access in graph algorithms, and agents/uniform_prop_strategy.md with the implementation strategy: new vertex_property_function / vertex_arithmetic_property_function concepts, null_vertex_property_fn sentinel, function-object overloads of init_shortest_paths, and the algorithm parameter changes for dijkstra, bellman_ford, and mst.
1 parent f8cd92b commit 7db942f

80 files changed

Lines changed: 11598 additions & 761 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,23 @@
22

33
## [Unreleased]
44

5+
### Added
6+
- **Mapped (sparse) graph algorithm support** — all 14 algorithms now accept `adjacency_list<G>` (both index and map-based containers)
7+
- `mapped_vertex_range`, `mapped_adjacency_list`, `mapped_bidirectional_adjacency_list` concepts
8+
- `vertex_property_map<G, T>` type alias and `make_vertex_property_map` factory (vector for index graphs, unordered_map for mapped)
9+
- `vertex_property_map_for<M, G>` concept for algorithm parameter constraints
10+
- `vertex_property_map_value_t<Container>` trait for extracting per-vertex value types
11+
- `is_sparse_vertex_container_v<G>` trait for compile-time graph type dispatch
12+
- Map-based graph test fixtures (`map_graph_fixtures.hpp`) with sparse vertex IDs
13+
- 456 new algorithm tests for sparse graph types (4343 → 4799)
14+
15+
### Changed
16+
- All algorithms relaxed from `index_adjacency_list<G>` to `adjacency_list<G>`
17+
- Algorithm internal arrays use `make_vertex_property_map` (vector or unordered_map depending on graph type)
18+
- User-facing `Distances`, `Predecessors`, `Weight`, `Component`, `Label` parameters accept vertex property maps
19+
- Index-based for-loops replaced with `views::basic_vertexlist(g)` iteration
20+
- Validation uses `if constexpr (index_vertex_range<G>)` for size checks, `find_vertex` for mapped graphs
21+
522
---
623

724
## [0.5.0] - 2026-03-01 *(Initial Beta)*
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)