Skip to content

perf: use vector-backed bookkeeping for A* search - #468

Open
HarshitR2004 wants to merge 1 commit into
bobluppes:mainfrom
HarshitR2004:perf/a-star-dense-storage
Open

HarshitR2004 wants to merge 1 commit into
bobluppes:mainfrom
HarshitR2004:perf/a-star-dense-storage

Conversation

@HarshitR2004

Copy link
Copy Markdown

Summary

A* currently maintains two hash maps for discovered vertices, storing the accumulated path cost twice and allocating individual map entries during traversal. This change replaces them with one lazily grown std::vector<std::optional<path_vertex<WEIGHT_T>>>, indexed by vertex ID.

Addresses the A* storage conversion requested in #463.

Implementation

  • Store the accumulated cost and predecessor in a single path record; empty slots represent undiscovered vertices.
  • Reconstruct the resulting path directly within A*, preserving true edge-weight totals independently of the heuristic.
  • Preserve heuristic ordering, negative-weight errors, and existing behavior for absent vertices and trivial paths. Handle invalid start IDs before allocating indexed storage.
  • Retain the map-based reconstruct_path() helper because bfs_shortest_path and dijkstra_shortest_path still use it on current main.
  • Update the storage documentation and add dataset-free grid benchmarks.

The public API remains unchanged.

Validation

Verified on Linux x86_64 with GCC 13.3.0:

  • Full Debug suite: 828 tests passed.
  • Behavior preservation: all 112 focused A* tests also passed against the original implementation.
  • Independent correctness checks: 3,456 source/target queries matched a Floyd–Warshall oracle, with returned paths checked against their actual edge weights.
  • Edge cases: deleted-vertex gaps, improved routes to discovered vertices, zero-weight cycles, disconnected targets, and absent IDs at SIZE_MAX.
  • Sanitizers: 112 focused tests passed under AddressSanitizer and UndefinedBehaviorSanitizer. Leak detection was disabled because LeakSanitizer could not inspect processes in this container.
  • The Release Graaf_perf target, clang-format 15.0.7 checks, and git diff --check passed.

Performance

Median CPU times across five repetitions, with a 0.15-second minimum per repetition. Graph construction is excluded; both versions use identical benchmarks compiled with -O3 -DNDEBUG.

Grid Heuristic Before After Speedup
32×32 Zero 0.293 ms 0.116 ms 2.52×
32×32 Manhattan 0.173 ms 0.045 ms 3.81×
128×128 Zero 6.700 ms 3.653 ms 1.83×
128×128 Manhattan 2.365 ms 1.726 ms 1.37×

These measurements describe the tested synthetic grids; results may differ for other workloads.

Tradeoff

Vector storage scales with the largest discovered vertex ID plus one. Graphs with many gaps from deleted vertices can therefore require more bookkeeping memory than the previous maps. This follows the graph’s existing dense-storage model.

AI coding assistance was used partially for implementation, testing, and local validation.

@github-actions

Copy link
Copy Markdown
Contributor

Hi there! Thank you for creating your first pull-request on the Graaf library :)

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant