chore: sync project state and current artifacts
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
# Story 4.8: Jacobian-Freezing Optimization
|
||||
|
||||
Status: done
|
||||
|
||||
<!-- Note: Validation is optional. Run validate-create-story for quality check before dev-story. -->
|
||||
|
||||
## Story
|
||||
|
||||
As a performance-critical user,
|
||||
I want to freeze Jacobian updates when approaching the solution,
|
||||
so that CPU time is reduced significantly without losing convergence stability.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
1. **Enable Jacobian Freezing in Configuration**
|
||||
- Given a `NewtonConfig`
|
||||
- When configured with `with_jacobian_freezing(max_frozen_iters)` (and optionally threshold)
|
||||
- Then the solver uses the frozen Jacobian optimization when conditions permit
|
||||
|
||||
2. **Reuse Jacobian Matrix**
|
||||
- Given a system solving with Newton-Raphson
|
||||
- When the freezing condition is met
|
||||
- Then the solver skips calling `traverse_for_jacobian` and reuses the previous `JacobianMatrix`
|
||||
- And speed per iteration improves significantly (up to ~80% target)
|
||||
|
||||
3. **Auto-disable on Residual Increase**
|
||||
- Given the solver is using a frozen Jacobian
|
||||
- When the current iteration's residual is GREATER than the previous iteration's residual
|
||||
- Then freezing is automatically disabled, and the Jacobian is recomputed for the next step
|
||||
|
||||
4. **Backward Compatibility**
|
||||
- Given an existing `NewtonConfig`
|
||||
- When no freezing configuration is provided
|
||||
- Then the solver behaves exactly as before (recomputing Jacobian every step)
|
||||
|
||||
## Tasks / Subtasks
|
||||
|
||||
- [x] Add `JacobianFreezingConfig` to `NewtonConfig`
|
||||
- [x] Add `jacobian_freezing: Option<JacobianFreezingConfig>` field
|
||||
- [x] Add builder method `with_jacobian_freezing()`
|
||||
- [x] Implement Modified Newton logic in `crates/solver/src/solver.rs`
|
||||
- [x] Track frozen iterations counter
|
||||
- [x] Skip Jacobian update when conditions permit (residual decreasing, counter < max)
|
||||
- [x] Force Jacobian update if residual increases
|
||||
- [x] Fix broken test struct literals
|
||||
- [x] Update `crates/solver/tests/*.rs` with `..Default::default()` for `NewtonConfig` where new fields are added (if not using builders)
|
||||
- [x] Add unit/integration tests
|
||||
- [x] Test frozen Jacobian converges correctly
|
||||
- [x] Test auto-recompute on divergence trend
|
||||
|
||||
## Dev Notes
|
||||
|
||||
- Relevant architecture patterns and constraints:
|
||||
- **Zero Allocation**: Do not dynamically allocate new matrices in the hot path. The `JacobianMatrix` should be reused.
|
||||
- **Safety**: No panics allowed.
|
||||
- Source tree components to touch:
|
||||
- `crates/solver/src/solver.rs` (update Newton solver loop)
|
||||
- `crates/solver/tests/newton_raphson.rs` (add integration tests for freezing)
|
||||
- Testing standards summary:
|
||||
- Use `approx::assert_relative_eq!` for floating point assertions.
|
||||
- Run `cargo clippy -- -D warnings` to ensure style compliance.
|
||||
|
||||
### Project Structure Notes
|
||||
|
||||
- Alignment with unified project structure: all changes are safely confined to the `solver` crate. No bindings code required.
|
||||
|
||||
### References
|
||||
|
||||
- [Source: `epics.md` FR19] "Solver can freeze Jacobian calculation to accelerate"
|
||||
- [Source: `epics.md` Story 4.8] "Jacobian-Freezing Optimization"
|
||||
- [Source: `architecture.md` NFR4] "No dynamic allocation in solver loop (pre-calculated allocation only)"
|
||||
|
||||
## Dev Agent Record
|
||||
|
||||
### Agent Model Used
|
||||
|
||||
Antigravity
|
||||
|
||||
### Debug Log References
|
||||
|
||||
### Completion Notes List
|
||||
- Ultimate context engine analysis completed - comprehensive developer guide created
|
||||
- Implemented `JacobianFreezingConfig` struct with `max_frozen_iters` and `threshold` fields
|
||||
- Added `jacobian_freezing: Option<JacobianFreezingConfig>` to `NewtonConfig` with `None` default for backward compatibility
|
||||
- Added `with_jacobian_freezing()` builder method on `NewtonConfig`
|
||||
- Modified Newton-Raphson solve loop: decision logic skips Jacobian assembly when frozen, stores and reuses `JacobianMatrix` via `.clone()`
|
||||
- Implemented auto-disable: sets `force_recompute = true` when residual ratio exceeds `(1.0 - threshold)`, resets frozen counter
|
||||
- Fixed inline struct literal in existing test (`test_with_timeout_preserves_other_fields`)
|
||||
- Exported `JacobianFreezingConfig` from `lib.rs`
|
||||
- Created 12 new integration tests in `jacobian_freezing.rs` covering all ACs
|
||||
- All 151 tests pass (130 unit + 21 integration) + 17 doc-tests; zero regressions
|
||||
- **[AI Code Review Fixes]**: Fixed critical Zero-Allocation architecture violation by pre-allocating `JacobianMatrix` outside the loop and adding in-place `update_from_builder` logic to avoid `clone()`.
|
||||
- **[AI Code Review Fixes]**: Added missing Rustdoc documentation to `JacobianFreezingConfig` public fields.
|
||||
- **[AI Code Review Fixes]**: Fixed integration test file `jacobian_freezing.rs` not being tracked in git natively.
|
||||
|
||||
### File List
|
||||
- `crates/solver/src/solver.rs` (modified — added struct, field, builder, loop logic)
|
||||
- `crates/solver/src/lib.rs` (modified — exported `JacobianFreezingConfig`)
|
||||
- `crates/solver/tests/jacobian_freezing.rs` (new — 12 integration tests)
|
||||
- `_bmad-output/implementation-artifacts/4-8-jacobian-freezing-optimization.md` (modified — status + checkboxes + dev notes)
|
||||
|
||||
## Change Log
|
||||
- 2026-02-19: Implemented Jacobian-Freezing Optimization (Story 4.8) — all ACs satisfied, 12 tests added, zero regressions
|
||||
Reference in New Issue
Block a user