Commit graph CultLib/packages/cultmath/tests/CultMath.Tests/BoundedLeastSquaresTests.cs
Author SHA1 Message Date
Meta Vens
08f05dede8 CultMath BoundedLeastSquares: the stopping rule's decisions are traced and pinned; Validate is the one owner of n < 0
The release choice and the pass judgement are internal functions (SelectRelease, JudgePass) and Solve reports each
decision, in order and with the values it compared, to an optional internal ISolveTrace. The tests assert those decisions
with exact equality against the traces the base commit dbcb2a8e produced on the same problems, and call the two functions
directly on states a solve may never reach. Solve's own n < 0 check is deleted (Validate throws the same exception), and the
NonFiniteTarget member doc names the n = 0 case.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 22:24:02 +02:00
Meta Vens
a42d7684fb CultMath tests: the rescaled noise-gate problems converge in a few passes, not four
A rescaled problem takes five passes on its own merits; the assertion is that the solve does not spin to the cap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 19:59:50 +02:00
Meta Vens
300fe188d1 CultMath tests: pin the BLS release stop (bls-stop-pins)
W5 with its columns rotated so every column is the released one; the noise gate across column scales; two small problems
whose release is confirmed by a second pass. Untested at this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 19:47:57 +02:00
Meta Vens
004d8bb78a CultMath BoundedLeastSquares: Validate names the invalid input; Solve's validation has one owner
Adds BoundedLeastSquaresInput and BoundedLeastSquares.Validate (tolerance, bounds, matrix, target; first failure).
Solve calls it and its inline tolerance, bounds and A^T b finiteness checks are deleted. Untested at this commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 19:24:59 +02:00
Meta Vens
dbcb2a8ea8 CultMath BoundedLeastSquares: release on the gradient against its rounding, never by the cost
A bound is released only when its violation exceeds both kktTol and the rounding
bound of its double gradient (Higham gamma_(n+1)); the cost-progress rule now judges
only passes that release nothing, and a release resets fMark. Fixes a cold start
stopping Converged with a violated bound (Soul W5, finding
aetheria-release:finding:cut-thrust-allocator-core.s1.solver-converged-early).
Tests: the W5 problem (cold == re-solve at 1e-12 and 1e-9) and the seed-141 noise
case. Builds; verified on Yggdrasil in the following report.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-10 08:51:18 +02:00
Meta Vens
9df0a82faf CultMath tests: pin the KKT tolerance threshold, both decision sites and the forwarded default
The release flips at 1.05x and 0.95x of the computed relative gradient at four
weights either side of 1e-6; all-free conditioned solves change between the
default and 1e-12; the omitted tolerance releases at 1.1e-6 and not at 0.9e-6.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 20:12:08 +02:00
Meta Vens
3dce41bd57 CultMath tests: the KKT tolerance argument of BoundedLeastSquares
Default and explicit-default are bit-identical; a light term under a heavy row
and an allocator-shaped problem are start-dependent at the default and solved
tight at 1e-12; invalid tolerances leave x untouched; the noise-floor fixtures
stop on progress at 1e-12 and 1e-30 (at most 6 iterations); the tolerance path
allocates nothing; the original ten-parameter signature still exists.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 17:21:10 +02:00
Meta Vens
2ad30fbfcf CultMath tests: pin default BoundedLeastSquares solves to their golden bits
Records status, iteration count and every float bit of x for the A54/B5 fixture,
three seeded random problems and a Duel allocator problem, taken at f7ab6212.
The kktRelativeTolerance cut must keep these literals unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 17:13:33 +02:00
Meta Vens
c8227c6347 cultmath: BoundedLeastSquares tests drive stalled passes to the stall rule
Batches of small boxed problems whose passes end with the KKT test failing and
the cost unmoved (dependent free columns, releases the factor drops, weak-direction
noise-floor problems). They must report Converged, and land within the documented
gap of an exact active-set enumeration. Pins the stall comparison and the cost
scale in Objective, which no test reached before.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 13:14:21 +02:00
Meta Vens
6328f15345 cultmath: BoundedLeastSquares test drives the tolerance below the noise floor
With b along the smallest left singular vector, |A^T b| is tiny, so the KKT
tolerance (1e-6 of it) sits below the gradient's rounding noise at cond(A) >=
1e6 and can never be met. The solver must stop on the progress rule, in at most
six passes, never at the cap. This is the path the progress rule exists for;
the earlier fixtures reached it only by accident.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 10:52:39 +02:00
Meta Vens
854f01e4c7 cultmath: BoundedLeastSquares tests pin the tolerance scale and the zero gradient
Two tolerance behaviours had no observer: the scale taken at the box point
nearest the origin (a 6e-5 release on a 1000-scale problem, in either column
position), and the strict comparisons when the scale and the gradient are both
exactly zero (b = 0 at the origin takes no iteration).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 10:37:27 +02:00
Meta Vens
0a80624930 cultmath: BoundedLeastSquares tests observe the warm-start clamp and the workspace
The full-step clamp repairs an out-of-box start on a free column, so the
warm-start clamp was invisible to the old test (Stryker: five survivors). The
new table runs one column with b beyond the box and a cap of 0, where the
solver returns the clamped start untouched, across finite, infinite and NaN
starts and finite and infinite bounds.

Workspace junk (including NaN doubles) is now checked on random boxed problems
that release bounds and use the tolerance, with bit-identical x and equal
iteration counts.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 09:44:04 +02:00
Meta Vens
4072fce0e7 cultmath: BoundedLeastSquares drops the refinement step it cannot observe
Stryker left the refinement step (removed, negated, or subtracted) unobserved,
and it is unobservable for a reason: refinement with a same-precision residual
does not improve forward error, and Cholesky is backward stable, so the
residual the KKT test reads is already at rounding level. Measured on n=24
problems at cond(A) 1e3..1e6, the solver with and without the step gives the
same iteration counts and the same x error against a Gram-Schmidt QR
reference (both limited by cond(A^T A) * eps).

The refinement pass, its dp buffer and the scratch vector are deleted;
WorkspaceLength returns to 4n^2 + 15n. The doc states where the normal
equations stop being optimal (cost gap below 1e-6 |b|^2 through cond(A) 3e5,
about 2e-5 at 1e6, independent of the scale of A) and that a ridge row beyond
that is the caller's policy.

status is now initialised: the unassigned local made Stryker discard every
mutant inside Solve as a compile error, so 255 mutants were never measured.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 09:29:06 +02:00
Meta Vens
6982adfaaf cultmath: BoundedLeastSquares tests pin iteration counts and the b = 0 start
- n=24 fully free problems at cond 1e2/1e3/1e4, and A x 1e6 with unscaled
  bounds, converge in at most two iterations (a regression to cap-spinning
  fails on the count, not on a clock).
- b = 0 from a far start reaches the optimum instead of the start.
- Warm-start clamp table, free duplicate column gets no step, parallel columns
  at absolute scales 1e3 and 1e-3, near-singular free sets confirm once and
  stop, near-collinear optimum at A x 1e6, and zero allocation on the invalid,
  converged and cap paths (first and second call).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 05:36:50 +02:00
Meta Vens
8b1a1ffde0 cultmath: near-collinear test uses generators that reproduce the gap on the old solver
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 03:44:57 +02:00
Meta Vens
6f8cb642ff cultmath: InvalidInput status and Soul tests (red on the old solver)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 03:43:32 +02:00
Meta Vens
986711c9d5 cultmath: tests for Stryker survivors (dirty workspace, exact caps, spans, near-duplicates)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 03:19:28 +02:00
Meta Vens
32fb7c1503 cultmath: FISTA reference keeps the random KKT test fast
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 02:52:51 +02:00
Meta Vens
c65777b400 cultmath: stop the projected-gradient reference once it stops moving
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 02:33:51 +02:00
Meta Vens
5382b81036 cultmath: widen fixed-column fixture so no other column blocks
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 02:14:39 +02:00
Meta Vens
eec1e40c25 cultmath: pin that a fixed column is never released
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 01:38:56 +02:00
Meta Vens
60c3d6fb0d cultmath: BoundedLeastSquares primal active-set solver
Dense small bounded LS, zero allocation, caller workspace, C#-only.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 01:33:08 +02:00