Conversation
|
Please add one or more tests (without removing or modifying any existing tests) that fail with the current algorithm but pass with the proposed algorithm. Please add a timeit or similar benchmark that measures the performance difference on a large grid (like 2k items). |
Preserve all 18 existing doctest examples and append frontier exhaustion regressions and controls. Add an optional 2,025-cell benchmark with a documented 89-cell reachable corridor, leaving the production fix unchanged.
|
Addressed in
On free-threaded CPython 3.15.0rc2, five samples of 100 searches each measured:
The best sample was about 2.1% slower; the median was 1.123× the original, with substantial variance. I would not attribute that spread entirely to the guard or generalize it to arbitrary grids. All configured pre-commit hooks passed. The production fix remains unchanged, and independent review verified the preserved examples, regression outcomes, and benchmark setup. Codex assisted with this follow-up. |
Describe your change
Stop the bidirectional A* loop when either frontier is empty. The previous
orcondition allowed another iteration with one empty list, although that iteration unconditionally pops from both frontiers.For example, with
grid = [[0, 1, 0], [1, 1, 0]], start(0, 0), and goal(0, 2), the forward frontier empties first and the original raisesIndexError: pop from empty list. The fixed guard returns the existing start-only no-path result. The mirrored backward-frontier case is also covered. Node matching, heuristics, and the return convention are unchanged.At the maintainer's request, follow-up
74af1de3d89d81cbea6ade9c7000947e4aabef21appends nine doctest examples while preserving all 18 originals. It adds an optional--benchmarkblock in this same file; the production methods and existing demonstration are unchanged by the follow-up.Validation on free-threaded CPython 3.15.0rc2, GIL disabled:
IndexErrorwhen one frontier empties first. Fixed algorithm: 27 passed. Controls cover both frontiers emptying together and a reachable corridor. The global grid is restored afterward.pre-commit run --all-files --show-diff-on-failure: exit 0, all applicable configured hooks passed without modifying files.git diff --checkpassed.Run
python graphs/bidirectional_a_star.py --benchmarkfor the optionaltimeitbenchmark. It uses 2,025 total grid cells but only 89 traversable cells, forming a deterministic staircase path. Grid setup and an exact-path assertion are outside timing; each iteration creates a fresh search object. The original/fixed comparison restores only the originalorguard in a temporary copy, retaining identical benchmark code and inputs. Both versions return the expected 89-cell path. Unreachable baseline cases crash and are tested separately, not included in timing.Five samples of 100 searches each, pinned to CPU 0 at the same nice level, measured milliseconds per search:
orandThe best sample was about 2.1% slower and the median was 1.123× the original, with substantial variance. These are measurements of this specific reachable workload, not an intrinsic guard-overhead estimate, a speedup claim, or 2,025 expanded nodes.
AI assistance was used to prepare this change and follow-up; a separate agent independently reviewed and reproduced the regression evidence.
Checklist
No new file or algorithm is added, and no issue is claimed. All 18 original doctests are preserved and nine examples are appended in response to review. The existing class doctests pass; no new functions are introduced. The personal-authorship attestation remains unchecked.