Skip to content

Commit 8dd4216

Browse files
authored
Feature/vertex id const ref (#6)
* Implement incoming edges Phases 1-3 and rename concepts/aliases for clarity\n\nPhase 1: in_edges CPO, in_degree CPO, outgoing aliases (out_edges,\nout_degree, find_out_edge), type aliases (in_edge_range_t, in_edge_iterator_t,\nin_edge_t, out_edge_range_t, out_edge_iterator_t, out_edge_t).\n\nPhase 2: find_in_edge and contains_in_edge CPOs with 3-tier resolution\n(member/ADL/default). Default tiers delegate to outgoing edge operations\nin reverse direction. Added has_in_degree, has_find_in_edge,\nhas_contains_in_edge traits.\n\nPhase 3: out_edge_range, in_edge_range, bidirectional_adjacency_list,\nindex_bidirectional_adjacency_list concepts. Updated graph.hpp with full\nre-exports for all Phases 1-3 items.\n\nRenamed for directional clarity:\n- vertex_edge_range concept -> out_edge_range\n- in_vertex_edge_range concept -> in_edge_range\n- out_vertex_edge_range_t -> out_edge_range_t\n- in_vertex_edge_range_t -> in_edge_range_t\n- out_vertex_edge_iterator_t -> out_edge_iterator_t\n- in_vertex_edge_iterator_t -> in_edge_iterator_t\n\nAll 4342 tests pass." * Swap primary/alias: out_edges, out_degree, find_out_edge are now primary The explicit directional names (out_edges, out_degree, find_out_edge, out_edge_range_t, out_edge_iterator_t, out_edge_t) are now the primary CPO definitions and type aliases. The shorter names (edges, degree, find_vertex_edge, vertex_edge_range_t, vertex_edge_iterator_t, edge_t) become convenience aliases via inline constexpr auto&. Code changes: - graph_cpo.hpp: swap primary/alias for 3 CPOs + 6 type aliases - adjacency_list_concepts.hpp: use out_edges in concept definitions, fix concept ordering (ordered_vertex_edges after adjacency_list) Documentation updates: - cpo-reference.md, adjacency-lists.md, type-aliases.md, adjacency-list-interface.md, cpo-order.md, coding-guidelines.md - agents/incoming_edges_design.md, incoming_edges_plan.md All 4342 tests pass. * Rename contains_edge -> contains_out_edge (primary), contains_edge is alias Follows the same pattern as out_edges/edges, out_degree/degree, and find_out_edge/find_vertex_edge: the explicit directional name is the primary definition, the shorter name is a convenience alias. - graph_cpo.hpp: contains_out_edge is primary _fn instance, contains_edge is inline constexpr auto& alias - graph.hpp: re-export both contains_out_edge and contains_edge - Updated cpo-reference.md, cpo-order.md All 4342 tests pass. * Rename has_edge(g) CPO to has_edges(g) The plural form better reflects the CPO's semantics: it checks whether the graph has any edges (plural), not a specific edge. Internal dispatch unchanged: the CPO still resolves g.has_edge() member and ADL has_edge(g) customization points on containers. All 4342 tests pass. * Phase 4: undirected_adjacency_list incoming-edge support Add in_edges() ADL friends to base_undirected_adjacency_list that forward to the same edge ranges as edges(), making undirected graphs model bidirectional_adjacency_list at zero cost. in_degree is handled automatically by the CPO default tier (size(in_edges(g, u))). find_in_edge and contains_in_edge also work correctly via their default tiers which delegate to find_vertex_edge/edges with swapped arguments. 10 new test cases covering: - Concept satisfaction (bidirectional + index_bidirectional) - in_edges == edges identity per vertex - in_degree == degree for all vertices - find_in_edge with vertex ids, descriptors, and mixed - contains_in_edge positive and negative cases - Star and triangle graph topologies All 4352 tests pass. * Update Phase 5-6 plan: out_* primary naming for views and adaptors Phase 5 now renames existing incidence.hpp/neighbors.hpp to out_incidence.hpp/out_neighbors.hpp (primary), with thin forwarding headers as aliases. in_incidence.hpp/in_neighbors.hpp are the new incoming-edge views. Phase 6 similarly renames adaptor instances to out_* primary, incidence/neighbors as aliases, then adds in_* adaptor closures. * Update Phase 5 plan: single-header approach for views Keep out_*, in_*, and alias views all in the same incidence.hpp and neighbors.hpp files. No file renames or forwarding headers needed. Mirrors how graph_cpo.hpp keeps out_edges, in_edges, and edges alias together. * Restructure Phases 5-7: edge accessor parameterization Introduce out_edge_accessor / in_edge_accessor in Phase 5 as a single parameterization point. Views (incidence, neighbors) gain an Accessor template parameter defaulting to out_edge_accessor — no class duplication. Phase 7 reuses the same accessor types for BFS/DFS/topo-sort, eliminating the need for a separate edge_accessor.hpp in that phase. * Phase 5: Edge accessor + parameterized incidence/neighbors views Introduce out_edge_accessor and in_edge_accessor as stateless policy structs that bundle edge-range fetching, neighbor-id extraction, and neighbor-vertex access. All four incidence view classes and all four neighbors view classes gain an Accessor template parameter (defaulting to out_edge_accessor) so existing code is source-compatible. New factory functions: - out_incidence / in_incidence / basic_out_incidence / basic_in_incidence - out_neighbors / in_neighbors / basic_out_neighbors / basic_in_neighbors Files changed: - NEW include/graph/views/edge_accessor.hpp - MOD include/graph/views/incidence.hpp (parameterized + factories) - MOD include/graph/views/neighbors.hpp (parameterized + factories) - MOD include/graph/graph.hpp (include edge_accessor.hpp) - NEW tests/views/test_in_incidence.cpp (14 test sections) - NEW tests/views/test_in_neighbors.cpp (14 test sections) - MOD tests/views/CMakeLists.txt (register new tests) All 4352 tests pass (461 views tests, 6238 assertions). * Phase 6: Pipe-syntax adaptors for incoming views + alias renames Add incoming adaptor closures so pipe syntax works for in_edges: g | in_incidence(uid) g | in_incidence(uid, evf) g | in_neighbors(uid) g | in_neighbors(uid, vvf) g | basic_in_incidence(uid) g | basic_in_neighbors(uid) Outgoing adaptors gain explicit out_* names via type aliases: out_incidence_adaptor_fn = incidence_adaptor_fn (etc.) Short names are now inline constexpr references to out_* objects: incidence = out_incidence, neighbors = out_neighbors basic_incidence = basic_out_incidence, basic_neighbors = basic_out_neighbors Files changed: - MOD include/graph/views/adaptors.hpp (8 new adaptor types + instances) - MOD include/graph/views/neighbors.hpp (static_cast fix for Clang) - MOD include/graph/views/edge_accessor.hpp (minor formatting) - MOD tests/views/test_adaptors.cpp (16 new test cases, 25 assertions) All 4352 tests pass on both GCC and Clang. * Phase 8: dynamic_graph bidirectional support with direction tags Complete Phase 8 of incoming edges plan — direction-aware edge_descriptor, in_edges ADL friends, and all CPO fixes for bidirectional dynamic_graph. Direction tag design (Option A): - Added out_edge_tag / in_edge_tag in descriptor.hpp - EdgeDirection 3rd template parameter on edge_descriptor (default out_edge_tag) - is_in_edge / is_out_edge static constexpr members - requires constraints on tag-dependent member functions: - source_id(vertex_data) requires(is_in_edge) - target_id(vertex_data) split into requires(is_in_edge) / requires(is_out_edge) Mirror principle (A1) implementation: - source_id(vertex_data): navigates .in_edges() for actual source (in-edge only) - target_id(vertex_data): trivial return for in-edges, navigates .edges() for out-edges - underlying_value/inner_value: direction-aware container selection Infrastructure changes: - edge_descriptor_view: EdgeDirection parameter, enable_borrowed_range for 3-param - descriptor_traits: all 11 specializations updated, is_in_edge_descriptor trait - edge_cpo.hpp: source_id tier 4 with if constexpr (is_in_edge) + fallback safety - graph_cpo.hpp: _wrap_in_edge helper in _in_edges namespace - dynamic_graph.hpp: in_edges(g,u) ADL friends with in_edge_tag descriptors, direction-aware edge_value ADL friend Bidirectional template parameter (steps 8.1-8.4): - Propagated through all classes, 27 traits files, all test files - dynamic_vertex_bidir_base with conditional in_edges_ storage - load_edges populates both containers when Bidirectional - _has_default_uid CPO fix for in_edges 4391/4391 tests pass on GCC-15 and Clang, zero regressions. * Phase 9: transpose_view + kosaraju bidirectional overload - Add include/graph/views/transpose.hpp: zero-cost bidirectional graph adaptor that swaps edges<->in_edges and target<->source via ADL friends. Documented limitation for forward-iterator containers (CPO tier-1 bypass). - Add kosaraju(G&&, Component&) overload in connected_components.hpp, constrained on index_bidirectional_adjacency_list. Uses manual iterative stack-based DFS with in_edges/source_id for the second pass — works with ALL container types (vov + vol). O(V+E) with no transpose overhead. - Add tests/views/test_transpose.cpp: 9 tests verifying edge/degree swap, double-transpose identity, edge_value forwarding, edge cases. - Add tests/algorithms/test_scc_bidirectional.cpp: 14 tests covering single vertex, cycles, multi-SCC, DAG, self-loops, weighted, disconnected, and agreement with the two-graph overload — tested on both vov and vol. - Update graph.hpp to include transpose.hpp. - Update CMakeLists for both test targets. 4405/4405 tests pass on GCC-15 and Clang." * Phases 7 & 10: Accessor-parameterized search views + documentation Phase 7 — BFS/DFS/topological sort Accessor parameterization: - Add Accessor template param (default out_edge_accessor) to all BFS, DFS, and topological sort view classes and factory functions - Fix in_edge_accessor::neighbor() — was calling adj_list::source() which returns owning vertex for in-edge descriptors; now uses find_vertex(g, source_id(g, e)) for correct resolution - Add 22 new tests in test_reverse_traversal.cpp covering forward and reverse traversal for all search view types Phase 10 — Documentation: - Create docs/user-guide/bidirectional-access.md tutorial guide - Update 11 existing doc files: index, getting-started, views, algorithms, containers, concepts, cpo-reference, type-aliases, adjacency-list-interface, cpo-implementation, README - Add CHANGELOG entry for full bidirectional edge access feature - Document bidirectional_adjacency_list concept, in_edge_* type aliases, Bidirectional template parameter, in_incidence/in_neighbors views, and Accessor parameter on search views 4405/4405 tests passing. * docs: update migration guide and coverage report for bidirectional/undirected support migration-from-v2.md: - Add undirected_adjacency_list section with template signature, complexity table, iterator invalidation rules, usage example, and when-to-use guidance - Add Bidirectional Graphs section covering dynamic_graph<...,true,true,...>, incoming-edge CPO table (in_edges, in_degree, find_in_edge, contains_in_edge, source_id), in_incidence/in_neighbors view table with structured-binding yields, and algorithms note (SCC, reverse BFS/DFS) - Add bidirectional graphs row to Key Changes at a Glance table - Add migration checklist item for predecessor/incoming-edge queries docs/status/coverage.md: - Regenerate from clean build (2026-02-22, 4405 tests, 96.0% line / 91.8% func) - Add edge_accessor.hpp and transpose.hpp (new files in views/) - Update all per-file line and function counts cmake/CodeCoverage.cmake: - Write raw data to coverage_raw.info then filter into coverage.info to avoid overwriting in place - Add --ignore-errors unused to lcov --remove to fix failure with lcov >= 2.x when the /usr/* exclude pattern matches nothing * Minor update to migration guide for v2.1.0 release. * docs: update metrics and implementation matrix (2026-02-23) - Views: 7 → 10 (added in_incidence, in_neighbors, transpose) - Trait combinations: 26 → 27 - Test count: 4261 → 4405 (2026-02-19 → 2026-02-23) - Coverage: 96.0% line / 91.8% function - Connected components row now notes Kosaraju SCC + test_scc_bidirectional.cpp - Removed stale note about README using graph::graph target (already graph::graph3) * refine dynamic_edge_refactor_strategy: comprehensive review fixes\n\n- Add in_edges_type derived alias fallback rule (detected_or_t)\n- Fix Phase 2 sequencing: temporary constructibility dispatch\n- Fix Phase 4c: in_edges_type omission from standard traits\n- Add compile-time safety risk row for fallback aliases\n- Add Definition of Done section\n- Remove stale Sourced=true and uniform-mode references" * add phased implementation plan for dynamic_edge refactor\n\n6-phase plan with precise file/line references, safety mitigations,\ntemporary bridge patterns, and status tracker. Derived from\ndynamic_edge_refactor_strategy.md." * docs: apply final review patches to dynamic_edge_refactor_plan 11 issues identified in deep cross-review of plan vs source code: - 4a.4: CRITICAL — remove dynamic_edge_source from dynamic_out_edge base list after Sourced=false empty spec is deleted; promote surviving Sourced=false specs to primary template (not just 'keep') - 4a.5: drop Sourced arg from dynamic_in_edge's dynamic_edge_value base - 4b.2: call out dynamic_vertex_base internal edge_type/edges_type aliases (L721-722) that also need Sourced removed - 4b.4: add edge_allocator_type audit + in_edge_allocator_type alias for non-uniform bidirectional mode - 4b.6 (new): edge_value direction-aware friend function needs Sourced removed and type-based dispatch check - 4d.1: clarify that all 18 emplace_edge calls across 3 load_edges paths must be audited; Sourced=false branch promoted, Sourced=true deleted - 4g: Phase 4g build gate replaced with example-target build (no library-only CMake target exists) - Overview: add test_dynamic_edge_comparison.cpp to Files of Interest - 5.1.1: warn that Sourced→Bidirectional at position 5 is a semantic change, not just a rename; callers passing true/false must be audited - 5.2: add detailed test_dynamic_edge_comparison.cpp migration steps - Risk table: add row for missing library-only CMake target" * feat: add dynamic_in_edge class and detection-idiom aliases (Phase 1) Purely additive changes to dynamic_graph.hpp (198 insertions, 0 deletions): 1. Forward declaration for dynamic_in_edge<EV,VV,GV,VId,Bidirectional,Traits> (6 params, no Sourced) after the dynamic_edge forward declaration. 2. graph::container::detail namespace with detection-idiom helpers: - detected_or_t<Default, Op, Args...> — returns Op<Args...> if well-formed, otherwise Default (no Boost dependency) - detect_in_edge_type<T> — detects T::in_edge_type - detect_in_edges_type<T> — detects T::in_edges_type 3. dynamic_in_edge_source<EV,VV,GV,VId,Bidirectional,Traits> — temporary unconditional source-id base (no Sourced param). Replaces in Phase 4a. 4. dynamic_in_edge — 2 specializations (EV!=void, EV=void): - Primary: inherits dynamic_in_edge_source + dynamic_edge_value (Sourced=true pass-through). Constructors: (src), (src,val), (src,val&&). operator<=> and operator== compare by source_id. - void specialization: inherits dynamic_in_edge_source only. Constructor: (src). Same comparison operators. 5. In dynamic_graph_base: three new dead aliases (activated in Phase 2): - out_edge_type = edge_type - in_edge_type = detected_or_t<edge_type, detect_in_edge_type, Traits> - in_edges_type = detected_or_t<edges_type, detect_in_edges_type, Traits> - static_assert verifying non-uniform traits define both in_edge_type and in_edges_type if either is defined. 6. std::hash<dynamic_in_edge<...>> — hashes source_id only. Phase 1 gate: cmake --build build/linux-gcc-debug succeeded, 4405/4405 tests passed, zero failures." * feat: wire in_edge_type into bidir vertex base and load_edges (Phase 2) Three changes to dynamic_graph.hpp (all existing tests still pass): 1. dynamic_vertex_bidir_base<..., true>: edges_type (in-edge storage) now derived via detection idiom: detail::detected_or_t<Traits::edges_type, detect_in_edges_type, Traits> Falls back to Traits::edges_type for all 27 standard traits — zero runtime behaviour change. Enables future non-uniform traits to supply a distinct in_edges_type. 2. make_in_edge private helpers in dynamic_graph_base (temporary bridge, removed in Phase 4d). Dispatch based on constructibility: - if InEdge is constructible from (VId, VId [, Val]): legacy path for edge_type when Sourced=true - otherwise: future path for dynamic_in_edge which takes (VId [, Val]) Two overloads: void-EV (no value) and non-void-EV (copy value). 3. All 6 in-edge emplace_edge sites across the 3 load_edges paths changed from edge_type{src, tgt} to make_in_edge(src, tgt) (and analogously for the value-bearing variant). Out-edge construction unchanged. Phase 2 gate: cmake --build build/linux-gcc-debug succeeded, 4405/4405 tests passed, zero failures." * refactor: rename dynamic_edge → dynamic_out_edge with deprecated alias (Phase 3) - Renamed all dynamic_edge class declarations to dynamic_out_edge in dynamic_graph.hpp (80 occurrences: class decls, edge_type aliases, hash specializations) - Added deprecated alias 'using dynamic_edge = dynamic_out_edge<...>' for backward compatibility; will be removed in Phase 4 - Renamed forward declarations and edge_type aliases in all 27 traits headers from dynamic_edge to dynamic_out_edge - test_dynamic_edge_comparison.cpp continues to compile via the alias 4405/4405 tests pass * docs: mark Phase 3 COMPLETE in refactor plan * refactor: remove Sourced from edge classes, collapse dynamic_out_edge 4→2 specs (Phase 4a) Phase 4a of the dynamic_edge refactor plan: - 4a.1: Remove bool Sourced from dynamic_edge_target template params - 4a.2: Remove bool Sourced from dynamic_edge_source, delete empty Sourced=false specialization (now unconditionally stores source_id) - 4a.3: Remove bool Sourced from dynamic_edge_value (both specs) - 4a.4: Collapse dynamic_out_edge from 4 to 2 specializations (keyed on EV only). dynamic_out_edge no longer inherits dynamic_edge_source. - 4a.5: Switch dynamic_in_edge bases from dynamic_in_edge_source to the repurposed dynamic_edge_source; delete dynamic_in_edge_source - 4a.6: Update dynamic_out_edge forward declaration (6 params) - 4a.7: Remove deprecated dynamic_edge alias; collapse 2 hash specs into 1 (hashes target_id only) Does NOT compile yet — vertex/graph classes still reference Sourced. Continues in Phase 4b. * Phase 4b: Remove bool Sourced from vertex and graph classes - dynamic_vertex_bidir_base: Remove Sourced from both specializations; delete static_assert(Sourced, ...) in Bidirectional=true spec - dynamic_vertex_base: Remove Sourced from template params, bidir_base reference, and graph_type/vertex_type/edge_type aliases - dynamic_vertex: Remove Sourced from both specializations (primary and VV=void) including all type aliases and base class references - dynamic_graph_base: Remove Sourced from template params and all type aliases (graph_type, vertex_type, edge_type) - dynamic_graph: Remove Sourced from both specializations (primary and GV=void); remove 'constexpr ... sourced = Sourced' constant - Forward declarations: Remove 'bool Sourced = false' from dynamic_graph and 'bool Sourced' from dynamic_vertex - dynamic_adjacency_graph alias: Remove Traits::sourced - edge_value friend function: Verified no Sourced dependency (uses is_in_edge type trait for direction dispatch) Remaining Sourced references (to be addressed in later phases): - Lines 58-82: traits forward declarations (Phase 4c) - Lines 1311,1406,1444: if constexpr(Sourced) in load_edges (Phase 4d) Does NOT compile yet — traits files still pass Sourced. * Phase 4c: Remove bool Sourced from all 27 traits files - All 27 traits files (vofl, vol, vov, vod, vos, vous, vom, voum, dofl, dol, dov, dod, dos, dous, mofl, mol, mov, mod, mos, mous, mom, uofl, uol, uov, uod, uos, uous): * Remove 'bool Sourced' from forward declarations (6→5 params) * Remove 'bool Sourced = false' from struct template params * Remove 'static constexpr bool sourced = Sourced;' member * Remove Sourced from edge_type/vertex_type/graph_type aliases * Update comments referencing Sourced - dynamic_graph.hpp: Remove 'bool Sourced' from all 9 traits forward declarations (lines 58-82) Remaining Sourced references (Phase 4d): - Lines 1311,1406,1444: if constexpr(Sourced) in load_edges - Line 242: comment in dynamic_edge_source Does NOT compile yet — load_edges still references Sourced. * Phase 4d: Simplify load_edges — remove Sourced branches and make_in_edge - All 3 load_edges paths (associative, sequential-forward, fallback): * Remove if constexpr(Sourced) guards — collapse to unconditional path * Out-edge construction: always edge_type(target_id [, value]) * In-edge construction: direct in_edge_type(source_id [, value]) guarded by if constexpr(Bidirectional) — replaces make_in_edge bridge - Delete make_in_edge helper (2 overloads, added in Phase 2) 27 insertions, 74 deletions. No Sourced references remain in code (only 1 documentation comment at line 242 in dynamic_edge_source). Does NOT compile yet — Phase 4e-4g pending. * Phase 4f/4g: Compile gate — fix examples, verify library headers compile - 4f: Hash specializations already Sourced-free (done in Phase 4a) - 4g: Fixed example files that still used old 7-param dynamic_graph: * dijkstra_clrs_example.cpp: Remove Sourced from dynamic_graph and vol_graph_traits template args * mst_usage_example.cpp: Remove Sourced from dynamic_graph and vov_graph_traits template args - Build verification: dijkstra_example and basic_usage compile cleanly Phase 4 complete. Tests still reference Sourced (Phase 5). * docs: update status tracker — Phase 4a-4g all COMPLETE * Phase 5.1: Update graph_test_types.hpp — remove Sourced, add bidir aliases - All 27 tag structs: rename 'bool Sourced' -> 'bool Bidirectional = false' in template alias, update 5th traits arg to Bidirectional - graph_test_types struct: * Drop 7-param dynamic_graph (Sourced removed) -> 6-param * Remove sourced_void / sourced_int / sourced_all aliases * Add bidir_void / bidir_int / bidir_all aliases (Bidirectional=true) * Update doxygen comments - File header: update 'sourced' -> 'bidirectional' in description * test: update all tests for Sourced removal and add bidir uniform/non-uniform coverage (Phase 5) * chore: update status tracker for Phase 5 completion (5.8 count fix, 5.9 entry) * chore: fix stale dynamic_edge comment in edge_descriptor.hpp (Phase 6.1) * docs: update Doxygen comments in dynamic_graph.hpp — remove Sourced/dynamic_edge refs (Phase 6.2) * docs: fix stale Sourced references in migration-from-v2.md (Phase 6.3) * docs: cleanup Doxygen, update user docs, archive strategy (Phase 6) * chore: record Phase 6.6 commit hash in status tracker * test: add coverage for uncovered dijkstra_shortest_paths.hpp lines (error paths + visitor) * docs: update coverage.md — dijkstra 100% line coverage, overall 96.3% * docs: fix Quick Example in README — add init_shortest_paths, weight fn, and output * Phase 0: Add raw_vertex_id_t, vertex_id_store_t; protect vertex_id_t with remove_cvref_t * Phase 1: descriptor return types to decltype(auto) - vertex_descriptor::vertex_id() returns decltype(auto): random-access returns size_t by value, map returns const Key& via std::get<0> - edge_descriptor::source_id() and target_id() return decltype(auto): parenthesized returns in lambdas to preserve reference semantics - Added static_asserts in test_dynamic_graph_integration.cpp as regression guards - Verified: gcc-debug, gcc-release, clang-debug, clang-release, gcc-asan (all pass) * Phase 2: Concept and trait requires-expressions use const vertex_id_t<G>& - adjacency_list_traits.hpp: 6 trait concepts updated (has_degree_uid_impl, has_find_vertex_impl, has_find_vertex_edge_uvid_impl, has_find_vertex_edge_uidvid_impl, has_find_in_edge_uid_impl, has_find_in_edge_uidvid_impl) - adjacency_list_concepts.hpp: vertex concept updated - Verified: gcc-debug, gcc-release, clang-debug, clang-release, gcc-asan (all pass) * Phase 3: View factory functions and constructors use const vertex_id_t<G>& - incidence.hpp: 12 factory functions (incidence, basic_incidence, out/in variants) - neighbors.hpp: 12 factory functions (neighbors, basic_neighbors, out/in variants) - bfs.hpp: 4 constructors, 5 deduction guides, 12 factory functions - dfs.hpp: 4 constructors, 6 deduction guides, 12 factory functions - transpose.hpp: 2 find_vertex friend functions - topological_sort.hpp, vertexlist.hpp, edgelist.hpp: no vertex_id params (no change) - Verified: gcc-debug, gcc-release, clang-debug, clang-release, gcc-asan (all pass) * Phase 4a: Algorithm parameter signatures use const vertex_id_t<G>& - dijkstra_shortest_paths.hpp: source param + relax_target lambda - bellman_ford_shortest_paths.hpp: source param + relax_target lambda - breadth_first_search.hpp: source param - depth_first_search.hpp: already const& (no change) - topological_sort.hpp: source param + internal dfs_visit - connected_components.hpp: 2 dfs_finish_order lambda params - mis.hpp: seed param - label_propagation, jaccard, tc, mst, articulation_points, biconnected_components: no vertex_id_t function/lambda params (no change) - Verified: gcc-debug, gcc-release, clang-debug, clang-release, gcc-asan (all pass) * Phase 4b: Algorithm internals use vertex_id_store_t<G> with static_assert guards - dijkstra_shortest_paths.hpp: id_type = vertex_id_store_t<G> + static_assert - bellman_ford_shortest_paths.hpp: same - breadth_first_search.hpp: same - depth_first_search.hpp: same - topological_sort.hpp: 3 id_type aliases + added traversal_common.hpp include - All static_asserts verify vertex_id_store_t<G> == vertex_id_t<G> for index_adjacency_list (integral IDs), establishing pattern for future non-integral graph support - Verified: gcc-debug, gcc-release, clang-debug, clang-release, gcc-asan (all pass) * Phase 5: Adaptor/pipe syntax verified — no changes needed - Reviewed all 16 incidence/neighbors direct-call adaptors: explicit vertex_id_t<G>(forward<UID>(uid)) construction is intentional type conversion; resulting prvalue binds correctly to const& parameters - Reviewed all pipe closure structs: store decayed UID/Seed, std::move on pipe invocation; works correctly with const& downstream - Reviewed all BFS/DFS direct-call adaptors: std::forward<Seed>(seed) already perfect-forwards to const& parameters - Updated plan status table - Verified: gcc-debug, gcc-release, clang-debug, clang-release, gcc-asan (all pass) * Phase 6: Update docs, examples, and fix missed prim seed param - Fix mst.hpp prim() seed parameter: vertex_id_t<G> -> const vertex_id_t<G>& (missed in Phase 4a) - Update examples/dijkstra_clrs.hpp seed parameter to const& - Update algorithm doc signatures to const vertex_id_t<G>& convention: bfs.md, bellman_ford.md, dijkstra.md, mis.md, topological_sort.md, mst.md - Update docs/contributing/algorithm-template.md signature example - All 4 presets green (GCC debug/release, Clang debug/release) * vertex_id_const_ref_plan.md completed * Fix static_assert platform portability: check size+signedness not exact type On some platforms uint64_t is unsigned long while on others it's unsigned long long. Check sizeof==8 && is_unsigned instead of is_same_v to avoid false failures in CI.
1 parent 8ab9416 commit 8dd4216

31 files changed

+1617
-167
lines changed

agents/vertex_id_const_ref_plan.md

Lines changed: 675 additions & 0 deletions
Large diffs are not rendered by default.

agents/vertex_id_const_ref_strategy.md

Lines changed: 707 additions & 0 deletions
Large diffs are not rendered by default.

docs/contributing/algorithm-template.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,11 @@ template <adjacency_list G,
9494
class WF = function<range_value_t<Distance>(edge_t<G>)>>
9595
requires /* ... constraints ... */
9696
void algorithm_name(
97-
G&& g, // graph
98-
vertex_id_t<G> source, // starting vertex
99-
Distance& distance, // out: distances
100-
Predecessor& predecessor, // out: predecessors
101-
WF&& weight) // edge weight function
97+
G&& g, // graph
98+
const vertex_id_t<G>& source, // starting vertex
99+
Distance& distance, // out: distances
100+
Predecessor& predecessor, // out: predecessors
101+
WF&& weight) // edge weight function
102102
```
103103
104104
---

docs/user-guide/algorithms/bellman_ford.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ bellman_ford_shortest_paths(G&& g, const Sources& sources,
7575

7676
// Single-source, distances + predecessors
7777
[[nodiscard]] constexpr optional<vertex_id_t<G>>
78-
bellman_ford_shortest_paths(G&& g, vertex_id_t<G> source,
78+
bellman_ford_shortest_paths(G&& g, const vertex_id_t<G>& source,
7979
Distances& distances, Predecessors& predecessors,
8080
WF&& weight,
8181
Visitor&& visitor = empty_visitor(),
@@ -93,7 +93,7 @@ bellman_ford_shortest_distances(G&& g, const Sources& sources,
9393

9494
// Single-source, distances only
9595
[[nodiscard]] constexpr optional<vertex_id_t<G>>
96-
bellman_ford_shortest_distances(G&& g, vertex_id_t<G> source,
96+
bellman_ford_shortest_distances(G&& g, const vertex_id_t<G>& source,
9797
Distances& distances,
9898
WF&& weight,
9999
Visitor&& visitor = empty_visitor(),

docs/user-guide/algorithms/bfs.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ void breadth_first_search(G&& g, const Sources& sources,
6666
Visitor&& visitor = empty_visitor());
6767

6868
// Single-source BFS
69-
void breadth_first_search(G&& g, vertex_id_t<G> source,
69+
void breadth_first_search(G&& g, const vertex_id_t<G>& source,
7070
Visitor&& visitor = empty_visitor());
7171
```
7272

docs/user-guide/algorithms/dijkstra.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ constexpr void dijkstra_shortest_paths(G&& g, const Sources& sources,
7777
Combine&& combine = plus<>{});
7878

7979
// Single-source, distances + predecessors
80-
constexpr void dijkstra_shortest_paths(G&& g, vertex_id_t<G> source,
80+
constexpr void dijkstra_shortest_paths(G&& g, const vertex_id_t<G>& source,
8181
Distances& distances, Predecessors& predecessors,
8282
WF&& weight = /* default returns 1 */,
8383
Visitor&& visitor = empty_visitor(),
@@ -93,7 +93,7 @@ constexpr void dijkstra_shortest_distances(G&& g, const Sources& sources,
9393
Combine&& combine = plus<>{});
9494

9595
// Single-source, distances only
96-
constexpr void dijkstra_shortest_distances(G&& g, vertex_id_t<G> source,
96+
constexpr void dijkstra_shortest_distances(G&& g, const vertex_id_t<G>& source,
9797
Distances& distances,
9898
WF&& weight = /* default returns 1 */,
9999
Visitor&& visitor = empty_visitor(),

docs/user-guide/algorithms/mis.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ remaining unmarked vertices in order.
6767

6868
```cpp
6969
size_t maximal_independent_set(G&& g, OutputIterator mis,
70-
vertex_id_t<G> seed = 0);
70+
const vertex_id_t<G>& seed = 0);
7171
```
7272
7373
**Returns** the number of vertices in the MIS. Selected vertex IDs are written

docs/user-guide/algorithms/mst.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,12 @@ lightest edge crossing the cut between tree and non-tree vertices.
109109
```cpp
110110
// Simple: uses default weight function from edge values
111111
auto prim(G&& g, Predecessors& predecessors, Weights& weights,
112-
vertex_id_t<G> seed = 0);
112+
const vertex_id_t<G>& seed = 0);
113113
114114
// Full: custom comparator, initial distance, and weight function
115115
auto prim(G&& g, Predecessors& predecessors, Weights& weights,
116116
Compare compare, range_value_t<Weights> init_dist,
117-
WF weight_fn, vertex_id_t<G> seed = 0);
117+
WF weight_fn, const vertex_id_t<G>& seed = 0);
118118
```
119119

120120
**Returns** the total MST weight.

docs/user-guide/algorithms/topological_sort.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ Three overloads cover different use cases:
7373
bool topological_sort(const G& g, OutputIterator result);
7474

7575
// Single-source topological sort
76-
bool topological_sort(const G& g, vertex_id_t<G> source, OutputIterator result);
76+
bool topological_sort(const G& g, const vertex_id_t<G>& source, OutputIterator result);
7777

7878
// Multi-source topological sort
7979
bool topological_sort(const G& g, const Sources& sources, OutputIterator result);

examples/dijkstra_clrs.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ requires forward_range<vertex_range_t<G>> && //
8787
convertible_to<vertex_id_t<G>, range_value_t<Predecessor>> && //
8888
edge_weight_function<G, WF>
8989
void dijkstra_clrs(
90-
G&& g, // graph
91-
vertex_id_t<G> seed, // starting vertex_id
90+
G&& g, // graph
91+
const vertex_id_t<G>& seed, // starting vertex_id
9292
Distance& distance, // out: distance[uid] of uid from seed
9393
Predecessor& predecessor, // out: predecessor[uid] of uid in path
9494
WF&& weight = [](const auto&,

0 commit comments

Comments
 (0)