Skip to content

Release v0.16.0: Elastic Feasibility + Parity Quick Wins - #40

Merged
sipemu merged 27 commits into
mainfrom
release/v0.16.0
Aug 12, 2026
Merged

Release v0.16.0: Elastic Feasibility + Parity Quick Wins#40
sipemu merged 27 commits into
mainfrom
release/v0.16.0

Conversation

@sipemu

@sipemu sipemu commented Aug 12, 2026

Copy link
Copy Markdown
Owner

Release v0.16.0 — Elastic Feasibility + Parity Quick Wins

Second implementation milestone from the v0.14.0 audit backlog. All additive and non-breaking (minor bump 0.15.00.16.0); no new dependencies. Milestone audit passed (4/4 requirements, cross-phase integration clean); full suite 2663 tests green across all feature configs; clippy --all-targets --all-features clean.

Performance / feasibility

  • PERF-03 — Opt-in banded elastic alignment. New non-breaking karcher_mean_with_band, elastic_self_distance_matrix_with_band, elastic_cross_distance_matrix_with_band (band_frac: Option<f64>), re-exported at the crate root. None = exact unbanded (existing behavior preserved); Some(0.1) ≈ 4–6× faster, making previously-infeasible large grids (N=500, M=200) tractable. Existing signatures untouched. (audit: PERF-ELASTIC-BAND, P1)

New capabilities (scikit-fda parity)

  • FEAT-03 — Missing-value imputation. impute_missing_values(data, argvals, method) -> Result<FdMatrix, FdarError> + ImputationMethod { Linear, Mean, Constant(f64) }; NaN detection, all-NaN + zero-column guards, boundary extension. (PREP-03)
  • FEAT-04 — Composable extrapolation policy. ExtrapolationPolicy { Boundary, Exception, Fill(f64), Periodic } threaded non-breakingly through both interpolation paths via fdata_interpolate_with_policy and spline_interpolate_with_policy. (REPR-03)
  • FEAT-05 — Functional scoring metrics. New scoring.rs: functional_mae/mse/mape/msle/explained_variance(y_true, y_pred, argvals) -> Result<f64, FdarError>, Simpson-integrated with domain guards (MAPE zero-denominator, MSLE log domain). (MISC-04)

Quality

  • Adversarial review + verify loop caught and fixed 2 real critical edge-case bugs pre-merge (Periodic zero-length-domain NaN → now errors; explained_variance false perfect-fit → relative guard) plus a coverage gap (spline_interpolate_with_policy).
  • 16 new public API items, all re-exported at the crate root; no breaking changes.

After merge

  • Tag v0.16.0 on the merge commit → release.yml publishes fdars-core 0.16.0 to crates.io.
  • R bindings (fdars-r / CRAN) are a separate release track.

Full changelog: v0.15.0...release/v0.16.0

🤖 Generated with Claude Code

sipemu and others added 27 commits August 11, 2026 21:10
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…c (user decision)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…pers

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…nce tests

- Add karcher_mean_with_band(…, band_frac: Option<f64>) in karcher.rs delegating to karcher_mean_impl via unwrap_or(0.0)
- Export karcher_mean_with_band and karcher_mean_banded from alignment/mod.rs and lib.rs crate root
- Add test_karcher_mean_with_band_none_matches_exact: None path identical to karcher_mean within 1e-15
- Add test_karcher_mean_with_band_wide_matches_unbanded: Some(0.99) matches within 1e-12 at m=30
…t re-exports

- Add elastic_self_distance_matrix_with_band and elastic_cross_distance_matrix_with_band in pairwise.rs using .and_then(|f| band_radius(f, m)) (avoids clippy::map_flatten)
- Export both _with_band functions and the existing _banded variants from alignment/mod.rs and lib.rs crate root
- Add 4 equivalence tests: None path identical within 1e-15, Some(0.99) matches within 1e-12 for both self and cross variants
…it_hotpaths for large grids

- Add bench_karcher_mean_with_band group comparing None (exact) vs Some(0.1) (banded) at n=20/m=50
- Register bench group in criterion_group! alongside existing bench groups
- Doc comment directs readers to audit_hotpaths.rs bench_p3_karcher_banded for N=500/M=200 cells
- Add 12-01-SUMMARY.md with full execution record, 3 task commits, 6 tests, 1 bench
- Update STATE.md with session, decisions, and metrics for plan 01
- Update ROADMAP.md progress for phase 12
- Mark PERF-03 complete in REQUIREMENTS.md
… tests

WR-01: The _with_band doc comments claimed band_frac=0.99 gives full-warp
coverage "at m >= 10". The correct bound is m < 200 (band_radius(0.99, m) =
ceil(0.99*m) >= m-1 iff 0.01*m < 2). Replace the incorrect threshold with the
m-agnostic phrasing in all three doc-comment blocks: karcher.rs and both
pairwise.rs functions.

IN-02: Add three tests asserting that Some(0.0) — the documented
"treated as unbanded" sentinel — produces results element-wise identical
to the exact unbanded path within 1e-15, mirroring the existing None tests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… metrics

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
All three FEAT-03/04/05 implementation sites verified in-source.
No new dependencies required.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ing metrics

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…licy (FEAT-04)

- Add ExtrapolationPolicy enum with Boundary, Exception, Fill(f64), Periodic variants
- Add fdata_interpolate_with_policy wrapping existing linear_interp / cubic_hermite_interp
- Periodic uses guarded-modulo ((t-t_min)%L+L)%L to handle t < t_min correctly
- Exception policy returns Err(InvalidParameter) for out-of-range query points
- Dimension guard: argvals.len() != data.ncols() -> Err(InvalidDimension)
- In-range queries identical to fdata_interpolate (verified by test)
- Re-export ExtrapolationPolicy and fdata_interpolate_with_policy from lib.rs
- 6 inline tests: boundary, exception, fill, periodic, in-range equivalence, dim guard
- Add ImputationMethod enum with Linear, Mean, Constant(f64) variants
- Add impute_missing_values fn operating per-curve on FdMatrix rows
- Linear strategy uses linear_interp between nearest non-NaN neighbors
- Leading/trailing NaN use boundary extension (nearest valid value) for Linear
- All-NaN curve returns Err(InvalidParameter); argvals mismatch Err(InvalidDimension)
- NaN detection uses is_nan() (not ==) per IEEE-754 requirement
- Re-export ImputationMethod and impute_missing_values from lib.rs
- 6 inline tests: linear (hand-computed), mean, constant, all-NaN, boundary NaN, dim guard
…impute_missing_values

- 13-01-SUMMARY.md: documents both features, deviations (double #[must_use] auto-fix), self-check
- STATE.md: advance plan counter, record metrics, session continuity
…T-05)

- New fdars-core/src/scoring.rs module with five functional scoring metrics
- functional_mae: integrated |y_true - y_pred| via Simpson's rule, averaged over curves
- functional_mse: integrated (y_true - y_pred)^2 via Simpson's rule, averaged over curves
- Private validate_shapes helper shared across all five metrics
- Shape guards: y_pred shape mismatch -> InvalidDimension{parameter:y_pred}
- Argvals length mismatch -> InvalidDimension{parameter:argvals}
- Degenerate guard: n==0 || m<2 -> InvalidDimension{parameter:data}
- pub mod scoring; declared in lib.rs adjacent to utility modules
- All five names re-exported at crate root (pub use scoring::{...})
- Inline tests: constant-error hand-computed, multi-curve average, shape mismatch errors
…se/mape/msle/explained_variance

- 13-02-SUMMARY.md: full plan execution summary with test results, threat mitigations, deviation notes
- STATE.md: Phase 13 Plan 02 complete; both plans done; phase complete
- ROADMAP.md: Phase 13 marked complete (2/2 plans), phase checkbox checked
- CR-01 (helpers.rs): guard domain_len <= 0 before Periodic extrapolation
  branch; x % 0.0 = NaN (IEEE 754) would silently propagate to interpolated
  output -- now returns InvalidParameter("argvals") for degenerate domains
- CR-02 (scoring.rs): replace absolute ss_res < NUMERICAL_EPS inner guard
  with relative ss_res <= ss_tot * (1 + 1e-6); old code returned 1.0 even
  when ss_res > ss_tot (both below epsilon), wrongly claiming perfect fit
- WR-01 (helpers.rs): add explicit m == 0 guard in impute_missing_values;
  without it a zero-column matrix was misreported as "curve 0 all-NaN"
- IN-01 (scoring.rs): remove redundant inner #[cfg(test)] on use statement
  inside the already-gated #[cfg(test)] mod tests block

Tests added: test_extrapolation_periodic_zero_length_domain_errors,
test_impute_zero_columns_errors, test_explained_variance_constant_true_perturbed_pred
Close VERIFICATION gap: ROADMAP SC#2 requires ExtrapolationPolicy to thread
through both the linear/cubic path AND spline_interpolate. The linear path
was covered by fdata_interpolate_with_policy in the original phase; this
commit adds the matching spline wrapper.

- New public fn spline_interpolate_with_policy(data, argvals, query_points,
  order, policy: ExtrapolationPolicy) -> Result<FdMatrix, FdarError>
- Reuses the same SVD pseudoinverse / B-spline machinery as spline_interpolate
- Policy semantics:
    Boundary: clamp OOB query to t_min/t_max before spline eval
    Exception: return InvalidParameter on first OOB query
    Fill(v): set OOB cells to constant v; in-range cells use spline
    Periodic: wrap OOB query modulo domain length (same guard as CR-01)
- Periodic zero-length-domain guard mirrors fdata_interpolate_with_policy
- Re-exported at crate root in lib.rs next to spline_interpolate
- 6 inline tests covering all four policy variants + zero-domain guard +
  in-range equivalence check
…xes applied

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Elastic Feasibility + Parity Quick Wins — 2 phases, 4 requirements
(PERF-03, FEAT-03/04/05), milestone audit passed. ROADMAP collapsed,
REQUIREMENTS + phases archived to milestones/v0.16.0-*. Fresh
REQUIREMENTS.md created at next milestone.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Release the v0.16.0 milestone (Elastic Feasibility + Parity Quick Wins):
opt-in banded elastic alignment, missing-value imputation, ExtrapolationPolicy,
and functional scoring metrics. Additive, non-breaking — minor bump from 0.15.0.
README install pins updated 0.15 -> 0.16. Also applies rustfmt to a
spline_interpolate_with_policy test in helpers.rs (was not fmt-clean).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sipemu
sipemu merged commit e35876a into main Aug 12, 2026
9 checks passed
@sipemu
sipemu deleted the release/v0.16.0 branch August 12, 2026 07:20
@codecov

codecov Bot commented Aug 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.53488% with 47 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.20%. Comparing base (e55156c) to head (d378209).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
fdars-core/src/helpers.rs 92.30% 40 Missing ⚠️
fdars-core/src/scoring.rs 97.70% 7 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main      #40      +/-   ##
==========================================
+ Coverage   89.09%   89.20%   +0.10%     
==========================================
  Files         200      201       +1     
  Lines       44616    45476     +860     
==========================================
+ Hits        39752    40565     +813     
- Misses       4864     4911      +47     
Flag Coverage Δ
rust 89.20% <94.53%> (+0.10%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
fdars-core/src/alignment/karcher.rs 99.68% <100.00%> (+0.01%) ⬆️
fdars-core/src/alignment/mod.rs 98.64% <ø> (ø)
fdars-core/src/alignment/pairwise.rs 93.88% <100.00%> (+0.37%) ⬆️
fdars-core/src/scoring.rs 97.70% <97.70%> (ø)
fdars-core/src/helpers.rs 88.52% <92.30%> (+2.91%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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