Conversation
- Align strategy with revised edge_list_goal.md - Design unified CPOs (source_id, target_id, edge_value) to work across: - Adjacency list edges - Edge list values - Edgelist views over adjacency lists - Extend CPO resolution from 4-tier to 6-tier for edge_info and tuple support - Add lightweight value-based edge descriptor design for edge lists - Update implementation phases and milestones - Document design decisions with rationale - Update references to actual codebase files
- Add mutual-exclusivity guards for tier 6/7 and noexcept propagation - Require symmetry for target_id/edge_value and clarify edge_list context is no-op - Expand test plan with ambiguity guard cases and descriptor tier checks
- Step-by-step tasks for agent execution - Progress tracking table - Test requirements for each step - Build and run commands - Completion checklist
Step 1.1: Create type trait infrastructure - Define forward declaration of edge_list::edge_descriptor - Implement is_edge_list_descriptor trait (defaults to false_type) - Add is_edge_list_descriptor_v variable template - Specialize trait for edge_descriptor<VId, EV>
Steps 1.2-1.5 implementation: - Added _has_edge_info_member and _is_tuple_like_edge concepts to all three CPOs - Extended source_id CPO with tiers 5-7 (edge_list_descriptor, edge_info_member, tuple_like) - Renamed _descriptor to _adj_list_descriptor for clarity - Updated enum, _Choose(), and operator() with new tier resolution - Created test infrastructure in tests/edge_list/ - All source_id tests passing (23/23) Note: target_id and edge_value await Steps 2.1 and 3.1 for tier extension Test placeholders added for future implementation
Steps 2.1-2.2 implementation: - Renamed _descriptor to _adj_list_descriptor in target_id enum - Added _edge_list_descriptor, _edge_info_member, _tuple_like values - Added _has_edge_list_descriptor concept - Updated _Choose() function with tiers 5-7 and noexcept propagation - Removed edge_descriptor_type constraint from operator() - Updated operator() implementation with new strategy cases - Updated documentation to reflect 7-tier resolution - Enabled all target_id tests - all passing (23/23) Note: source_id and target_id now complete. Only edge_value awaits Step 3.1
Steps 3.1-3.2 implementation: - Renamed _default to _adj_list_descriptor in edge_value enum - Added _edge_list_descriptor, _edge_info_member, _tuple_like values - Added _has_edge_list_descriptor concept - Renamed _has_default to _has_adj_list_descriptor for consistency - Updated _Choose() function with tiers 5-7 and noexcept propagation - Removed edge_descriptor_type constraint from operator() - Updated operator() implementation with new strategy cases - Updated documentation to reflect 7-tier resolution - Enabled all edge_value tests - all passing (23/23) All three CPOs (source_id, target_id, edge_value) now support full 7-tier resolution! Next: Phase 4 - Create edge_list::edge_descriptor type
- Implemented edge_list::edge_descriptor<VId, EV = void> template - Supports void edge values with [[no_unique_address]] optimization - Uses template member functions to avoid forming reference to void - Added detail::empty_value with comparison operators for void case - Implemented constructors for both void and non-void cases - Added deduction guides for CTAD support - Included accessors: source_id(), target_id(), value() - Defaulted comparison operators (==, <=>) - Fixed forward declaration to avoid default parameter redefinition - Created comprehensive test suite with 39 assertions across 16 test cases - Tests cover: construction, traits, CPO integration (Tier 5), noexcept, comparisons - All tests passing (test_edge_list_descriptor) - Updated tests/edge_list/CMakeLists.txt to build new test
- Changed source_id() and target_id() to return const VId& instead of VId - Avoids copying non-trivial types like strings - Maintains optimal performance for all vertex ID types - Added test case for string vertex IDs with static_assert verification - All 42 assertions passing across 17 test cases
- Changed constructors to use forwarding references (V1&&, V2&&, E&&) - Eliminates unnecessary copies during edge_descriptor construction - Enables move semantics when constructing from rvalues - Added std::constructible_from constraints for type safety - Added test case demonstrating move construction from strings - All 45 assertions passing across 18 test cases Performance impact: For std::string vertex IDs, this eliminates 2+ copy operations per edge_descriptor construction, using moves instead.
Major architectural change: edge_descriptor now stores references to data instead of owning copies, making it a true lightweight handle. Changes: - Member variables changed from VId to const VId& (zero-copy references) - Edge value changed from EV to std::reference_wrapper<const EV> - Constructors take const references instead of values - Removed default constructor (descriptor must reference existing data) - Assignment operators deleted (reference semantics) - Custom comparison operators (compare values, not reference addresses) - Added test verifying descriptors reference underlying data - Added test showing changes to referenced data are visible Performance impact: - BEFORE: 2-4 copies per edge_descriptor construction - AFTER: 0 copies - descriptor is pure reference wrapper - Descriptor size: ~3 pointers (24 bytes on 64-bit) - Construction: O(1) trivial reference binding All 60 assertions passing across 18 test cases
- Changed from struct to class for proper encapsulation - Moved member variables to private section - Public interface remains unchanged (constructors, accessors, operators) - All 60 assertions still passing across 18 test cases
Changes to edge_list_strategy.md: - Updated edge_descriptor design documentation - Clarified it's a reference-based lightweight handle - Added key design properties (zero-copy, reference semantics, encapsulation) - Updated code examples to show class with private members - Documented use of const references and std::reference_wrapper Changes to edge_list_plan.md: - Updated Step 4.1 implementation requirements - Added design requirements emphasizing zero-copy and reference semantics - Updated code example to show reference-based implementation - Updated Step 4.3 test requirements to verify reference behavior - Added test cases verifying descriptors reference underlying data
…sts) Phase 5: Update edge_list concepts to use unified CPOs - Updated basic_sourced_edgelist to support ANY vertex ID type (not just integral) - Fixed basic_sourced_index_edgelist to check std::integral on decayed return types - Updated all type aliases to use CPO pattern with declval - Fixed edge_value_t and vertex_id_t to use std::remove_cvref_t for consistency - Fixed edge_value CPO to check tuple size >= 3 before accessing element 2 - Created test_edge_list_concepts.cpp with 14 test cases, 41 assertions Phase 6: Integration and finalization - Updated graph.hpp to include all edge_list headers (traits, descriptor, concepts) - Created test_edge_list_integration.cpp with 16 test cases, 32 assertions - Implemented generic algorithms demonstrating unified CPO interface - Verified support for all edge types: pairs, tuples, edge_info, edge_descriptor - Tested string vertex IDs and mixed edge types in same compilation unit All phases 1-6 complete: 156 assertions across 71 test cases, all passing
…ith unified CPOs Implements full edge_list unification across 6 phases: Phase 1-3: Extended source_id, target_id, edge_value CPOs with tiers 5-7 - Tier 5: edge_list::edge_descriptor support - Tier 6: edge_info struct support - Tier 7: tuple/pair support Phase 4: Created reference-based edge_list::edge_descriptor - Zero-copy construction and access - Proper encapsulation with private members - Support for void and non-void edge values Phase 5: Updated edge_list concepts - basic_sourced_edgelist supports ANY vertex ID type - basic_sourced_index_edgelist requires integral types - Updated type aliases with unified CPO pattern Phase 6: Integration and testing - Updated graph.hpp with all edge_list headers - Comprehensive integration tests Results: 156 assertions across 71 test cases, all passing
- Combined test_edge_list_cpo, test_edge_list_descriptor, test_edge_list_concepts, and test_edge_list_integration into single test_edge_list executable - Reduces build artifacts and simplifies test execution - All 156 assertions across 71 test cases still passing
- Updated all view signatures to use descriptor-based design from Section 8 - Changed vertex_info<V, VV> to use vertex_descriptor (no separate VId) - Changed edge_info<E, EV> to use edge_descriptor (no Sourced bool) - Changed neighbor_info<E, VV> to use edge_descriptor for context - Fixed const correctness for value functions (const vertex_value_t<G>&) - Updated range adaptor closures with proper factory functions - Added complete pipe syntax support for all views - Clarified implementation notes to reflect descriptor access patterns - Added forward reference in Section 2.1 to Section 8 Strategy document is now ready for implementation.
- Created view_plan.md with 24 implementation steps - Phase 0: Info struct refactoring (3 steps) - Phase 1: Foundation - directory structure, search_base, concepts (3 steps) - Phase 2: Basic views - vertexlist, incidence, neighbors, edgelist (5 steps) - Phase 3: DFS views - state, vertices_dfs, edges_dfs, cancel (4 steps) - Phase 4: BFS views - state, vertices_bfs, edges_bfs, depth/size (4 steps) - Phase 5: Topological sort - algorithm, cycle detection (2 steps) - Phase 6: Integration - headers, docs, benchmarks (4 steps) - Each step includes tasks, tests, and acceptance criteria - Progress tracking table at top of document
- Reverted all view signatures to use original info structs - vertex_info<VId, V, VV> retains id, vertex, value members - edge_info<VId, Sourced, E, EV> retains source_id, target_id, edge, value members - neighbor_info<VId, Sourced, V, VV> retains source_id, target_id, target, value members - Removed note about descriptor-based refactoring from Section 2.1 - Original design provides flexibility for copyable vertices/edges - Deleted view_plan.md (will be regenerated with correct design)
- Clarified that VId, V/E, and VV/EV can ALL be void - VId=void suppresses id/source_id/target_id members (useful with descriptors) - V/E=void suppresses vertex/edge/target members (useful for ID-only iteration) - VV/EV=void suppresses value members (when no value function) - Updated usage examples showing different void combinations - vertex_info: 4 specializations (2^3 combinations minus edge cases) - edge_info: 16 specializations (Sourced × 2^3 void combinations) - neighbor_info: 16 specializations (Sourced × 2^3 void combinations) - Preserves flexibility for copyable types and descriptor-based usage - Updated Phase 0 implementation tasks to reflect optional member design
- DFS views (vertices_dfs, edges_dfs, sourced_edges_dfs) yield info structs with VId=void - BFS views (vertices_bfs, edges_bfs, sourced_edges_bfs) yield info structs with VId=void - Topological sort views yield info structs with VId=void - vertices_*: yields vertex_info<void, V, VV> - edges_*: yields edge_info<void, false, E, EV> - sourced_edges_*: yields edge_info<void, true, E, EV> - IDs are accessible via descriptors (v.vertex_id(), e.source_id(), e.target_id(g)) - Reduces redundancy and aligns with descriptor-based architecture
Section 8.1 (vertex_info):
- Note that vertex_info<VId, void, VV> ({id, value}) is useful for external data
- Use cases: graph construction, export/import, serialization, external algorithms
Section 8.2 (edge_info):
- Note that edge_info<VId, true, void, EV> ({source_id, target_id, value}) is useful
- Use cases: graph construction, edge list export/import, CSV/JSON formats
- External algorithms operating on edge triples without graph context
While descriptors eliminate redundancy within graph traversal, ID-based
combinations remain valuable for data exchange and graph initialization.
- Updated problem statement to clarify neighbors view uses edge descriptor internally
- View creates neighbor_info for the target edge
- Edge descriptor provides necessary navigation context
- Also noted external data use case for {source_id, target_id, value} combination
…scriptor - Changed from 'Problem/Solution' to 'Note/Implementation' framing - Clarified that edge_descriptor has source vertex descriptor as member variable - This design naturally provides source context without additional tracking - Updated code example to show vertex_descriptor (not just vertex_id_t) - Source context is built into the descriptor itself, simplifying implementation
- Break down implementation into 7 phases with 30+ discrete steps - Each step has clear goals, files to create/modify, tests, and acceptance criteria - Phase 0: Info struct refactoring (vertex_info, edge_info, neighbor_info) - Phase 1: Foundation (directory structure, search_base, concepts) - Phase 2: Basic views (vertexlist, incidence, neighbors, edgelist) - Phase 3: DFS views (vertices, edges, sourced edges, cancel) - Phase 4: BFS views (vertices, edges, sourced edges, depth/size) - Phase 5: Topological sort views (vertices, edges, cycle detection) - Phase 6: Range adaptors (pipe syntax, chaining) - Phase 7: Integration (master header, docs, benchmarks, edge cases) - Progress tracking checkboxes for each step - Agent-friendly with detailed implementation guidance - Created on feature/views-implementation branch
- Remove incorrect [[no_unique_address]] usage from info struct members - Use proper template specializations to physically omit void members - Add example specializations showing correct approach - Update acceptance criteria to verify physical absence of void members - [[no_unique_address]] is still correctly used in view classes for empty functors
- Add VId=void specializations for vertex_info (4 new, 8 total) - Add VId=void specializations for edge_info (8 new, 16 total) - Add VId=void specializations for neighbor_info (8 new, 16 total) - All void template parameters physically omit corresponding members - Primary pattern: info<void, ..., descriptor, value> for descriptor-based views - External data pattern: info<VId, ..., void, value> for construction/export - Create comprehensive test suite (392 assertions, 27 test cases) - Tests verify all specializations, structured bindings, type traits, and copyability - Fix CMakeLists.txt to properly link test target Implementation notes: - edge_info uses source_id/target_id (vertex IDs), not edge_id - neighbor_info uses source_id/target_id (vertex IDs), not vertex_id - neighbor_info uses 'target' member when VId present, 'vertex' when VId=void - Sourced=true includes source_id, Sourced=false omits it - All tests pass with no warnings Phase 0 complete per view_plan.md steps 0.1-0.3
- Add include/graph/views/ directory for view implementations - tests/views/ infrastructure already completed in Phase 0 - Update view_plan.md to mark Step 1.1 as complete
- Add cancel_search enum for traversal control (continue_search, cancel_branch, cancel_all) - Implement visited_tracker template for DFS/BFS vertex tracking - Support custom allocators for visited storage - Use std::fill for vector<bool> compatibility - Comprehensive test suite: 61 assertions in 6 test cases, all passing - Update view_plan.md to mark Step 1.2 as complete
- Define vertex_value_function concept for vertex value functions (invocable with descriptor, returns non-void) - Define edge_value_function concept for edge value functions (invocable with descriptor, returns non-void) - Define search_view concept for DFS/BFS/topo views (requires cancel(), depth(), size() methods) - Comprehensive test suite: 27 assertions in 4 test cases, all passing - Tests cover valid/invalid types, various return types, mutable/capturing lambdas - Update view_plan.md to mark Step 1.3 as complete - Phase 1 (Foundation) complete
- Yields vertex_info<void, vertex_descriptor, VV> - Value function receives vertex descriptor - Supports structured bindings: [v] and [v, val] - Tests cover iteration, value functions, const correctness - 67 new assertions (547 total views tests)
- Change edge_info<void, true, ...> to edge_info<void, false, ...> - When VId=void, Sourced should be false since there are no separate source_id/target_id members; IDs are accessible via the descriptor - Update vertexlist iterator to store vertex_t<G> directly - Iterator now stores vertex_info for no-VVF variant (returns by ref) - Iterator stores vertex_type for VVF variant (returns by value) - Update related comments in view_strategy.md and view_plan.md
vertexlist view: - Yields vertex_info<void, vertex_descriptor, VV> - Supports optional value function receiving vertex descriptor - Uses vertices() CPO for proper map-based container support - 14 test cases, 83 assertions incidence view: - Yields edge_info<void, false, edge_descriptor, EV> - Iterator stores edge_type directly (not iterator) - Uses edges() CPO for proper container-agnostic iteration - 15 test cases, 84 assertions Both views tested with: - vector<vector<T>> (vov) - map<VId, vector<T>> (mov) - vector<map<VId, EV>> (voem) - map<VId, map<VId, EV>> (moem) Updated documentation: - view_strategy.md: Added Section 7.2 Container Type Coverage - view_plan.md: Steps 2.1 and 2.2 marked complete Total: 647 assertions in 66 test cases, all passing
- Yields edge_info<void, false, edge_t<G>, EV> for each edge - Flattens adjacency list structure into single edge range - Uses vertex descriptors (like vertexlist_view) and edge descriptors (like incidence_view) - edgelist_view<G, void>: Stores edge_info directly, returns const reference - edgelist_view<G, EVF>: Stores edge descriptor, computes value lazily on dereference - Factory functions: edgelist(g) and edgelist(g, evf) - Skips vertices with no edges automatically - Supports map-based containers (vov, voem, mov, moem) - 80 assertions in 15 test cases, all passing
- Add edge_list_edgelist_view<EL, void> and <EL, EVF> specializations - Wraps edge_list ranges, yields edge_info<void, false, edge, EV> - Factory functions: edgelist(el) and edgelist(el, evf) - EVF receives (EL&, edge) to support edge_list CPOs (source_id, target_id) - Remove conflicting namespace edgelist = edge_list; alias - Add 11 new tests (Tests 16-26): pairs, tuples, edge_info, weighted, empty, range concepts, iterators, string VIds, algorithms, deque Test Results: 26 test cases, 128 assertions, all passing
- Create include/graph/views/basic_views.hpp - Includes vertexlist.hpp, incidence.hpp, neighbors.hpp, edgelist.hpp - Single include for all basic (non-search) graph views - Add test_basic_views.cpp to verify header compilation Test Results: 109 test cases, 860 assertions, all passing
…ency_list tests + remove sourced_edges views
- incidence.hpp: Add incidence(g, uid) and incidence(g, uid, evf) convenience overloads
- undirected_adjacency_list.hpp: Add ADL edge_value() overloads for edge_descriptor
- test_incidence.cpp: Add 6 comprehensive undirected_adjacency_list test cases
- Basic iteration, iteration order, range algorithms
- Edge cases (empty, single edge), uid convenience overload
- Dense graph with 10 vertices, 26 edges, 7+ edges per vertex
- view_plan.md: Remove sourced_edges_* steps (3.3, 4.3, 5.3) from Phases 3-5
- Source accessible via edge descriptor's source_id()
- Renumber remaining steps, update Overview and PR summary
Tests: 21 incidence test cases, 278 assertions passing
114 total views test cases, 912 assertions passing
The index_vertex_range concept now correctly checks the underlying iterator type of the vertex container rather than the view's range category. vertex_descriptor_view is always forward_range (synthesizes descriptors on-the-fly), but the underlying container may still support random access. Changes: - Fix index_vertex_range to check vertex_desc::iterator_type - Vector and deque graphs now satisfy index_adjacency_list - DFS views use adj_list::index_adjacency_list constraint directly - Update concept tests to reflect correct behavior Implementation details: - vertices_dfs_view with shared_ptr state for iterator copies - Support for both vertex_id and vertex_descriptor as seed - Value function support with proper structured bindings - Cancel, depth, and size accessors on view All 3931 tests pass.
- Add edges_dfs_view class with void and EVF specializations - Yields edge_info<void, false, edge_descriptor, EV> for tree edges - Tree edges visited in DFS order (back edges not yielded) - Edge descriptor provides source/target access via CPOs - 8 factory functions for vertex_id/descriptor × vvf × allocator - Deduction guides for CTAD support - 14 new test cases covering all edge traversal scenarios All 3931 tests pass.
- Add cancel_branch handling to all DFS advance() methods - cancel_branch: pops current vertex, resets to continue_search - cancel_all: clears entire stack, stops traversal - 9 new test cases covering all cancel modes: - cancel_all stops traversal (vertices and edges) - cancel_branch skips subtree (vertices and edges) - continue_search normal behavior - Cancel state propagates through shared state - cancel_branch at seed vertex - Multiple cancel_branch calls - Cancel with value function Phase 3 (DFS Views) complete. All 3931 tests pass.
Phase 4 Steps 4.1-4.3 Complete Step 4.1: BFS infrastructure + vertices_bfs - Yields vertex_info<void, vertex_descriptor, VV> - Queue-based breadth-first traversal - Accepts both vertex_id and vertex_descriptor as seed - Supports depth(), size(), cancel() accessors - Value function receives vertex descriptor - 13 vertex tests verify level-order traversal Step 4.2: edges_bfs - Yields edge_info<void, false, edge_descriptor, EV> - Edges visited in BFS tree order - Uses edge_queue_entry for iteration state tracking - Proper cancel_branch semantics (skip target vertex) - 9 edge tests verify BFS edge traversal Step 4.3: BFS depth/size accessor tests - 9 comprehensive tests for depth/size tracking - Verifies depth increases by BFS level - Verifies size counts discovered vertices/edges - Tests on various graph topologies (wide, deep, disconnected) - Tests with and without value functions Files: - include/graph/views/bfs.hpp (1068 lines) - tests/views/test_bfs.cpp (718 lines, 31 tests, 113 assertions) All 187 view tests pass (2289 assertions)
…g tests Step 6.2: Range adaptor closures for search views + topological sort - Add vertices_dfs, edges_dfs, vertices_bfs, edges_bfs adaptors - Add vertices_topological_sort, edges_topological_sort adaptors - Support pipe syntax: g | vertices_dfs(seed), g | vertices_topological_sort() - Support value functions and optional allocators - Direct call compatibility: vertices_dfs(g, seed) - All search views chain with std::views adaptors Step 6.3: Comprehensive pipe syntax and chaining tests - Add 12 comprehensive chaining tests - Test multiple transforms, filters, and complex chains - Test integration with std::views::take, drop, transform, filter - Test const correctness with pipes and chains - Test mixing different view types in nested loops - Verify seamless integration with standard library ranges Test Results: 51 test cases, 101 assertions, all passing Phase 5 (Topological Sort) and Phase 6 (Range Adaptors) complete
Step 7.1: Create unified views.hpp header - Add include/graph/views.hpp master header - Includes all view headers (basic_views, dfs, bfs, topological_sort, adaptors) - Comprehensive documentation with usage examples - Add tests/views/test_unified_header.cpp (5 tests, 19 assertions) - Tests verify single-include pattern works correctly - All views accessible through one header Step 7.2: Update graph.hpp integration - Update include/graph/graph.hpp documentation - Views require separate include to avoid circular dependencies - Add tests/views/test_graph_hpp_includes_views.cpp (4 tests, 14 assertions) - Tests verify graph.hpp + views.hpp work together - All basic and search views accessible - Value functions and chaining with std::views work Design: Views not auto-included in graph.hpp due to circular dependency between edge_list.hpp and graph.hpp. Users include both headers: #include <graph/graph.hpp> #include <graph/views.hpp> Test Results: 284 test cases, 2573 assertions, all passing
- Add test_edge_cases.cpp with 32 test cases (3119 assertions) - Test empty graphs and single vertices - Test disconnected graphs and self-loops - Test parallel edges and const graphs - Test alternative containers (deque-based) - Test sparse graphs (non-contiguous IDs) - Test value functions (capturing, mutable, throwing) - Test exception safety - Large graph stress tests (up to 10K vertices) - Iterator stability and view copying tests - Empty range edge cases - All 312 views tests passing (5679 total assertions) - Phase 7 (Integration & Polish) complete
Step 7.3: Comprehensive views documentation - Add docs/views.md (810 lines) - Overview and quick start guide - All 10 views documented with examples - Range adaptor syntax and value functions - Chaining patterns and performance considerations - Best practices and common patterns - Limitations and cross-references Step 7.4: Performance benchmarks - Add benchmark/benchmark_views.cpp (520 lines) - 25 benchmarks covering all view types - Basic views: vertexlist, incidence, neighbors, edgelist - Search views: DFS, BFS, topological sort (vertices and edges) - Comparison benchmarks: view vs manual iteration - Chaining benchmarks: filter, transform, take - Graph type benchmarks: path, complete, random graphs - Complexity analysis: O(N) for basic views, O(V+E) for search - Add benchmark/README.md (197 lines) documenting results - Fix benchmark/benchmark_vertex_access.cpp namespace issue - Update benchmark/CMakeLists.txt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.