Skip to content

feat: add TNC solver and parameter transforms - #129

Merged
jolars merged 3 commits into
jolars:mainfrom
fhenskens:feat/tnc-parameter-transforms
Nov 4, 2026
Merged

jolars merged 3 commits into
jolars:mainfrom
fhenskens:feat/tnc-parameter-transforms

Conversation

@fhenskens

@fhenskens fhenskens commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Adds finite-box truncated Newton through Basin's existing solver and executor interfaces, with limited-memory BFGS preconditioned CG, feasible gradient-difference Hessian-vector products, and explicit exact products. The solver supports all four dense backends with both scalar precisions, typed callback errors, and exact checkpoints.

Adds an explicit ParameterTransform adapter for linear and logarithmic physical parameters. Gradients and Hessian-vector products include the full chain rule. TNC uses the supplied coordinates; normalization remains an opt-in problem transformation.

Includes runnable rustdoc examples, backend and edge-case tests, f32 integration coverage, the solver catalogue entry, and a developer note describing the original implementation in sisyfuzz and the changes for Basin. The browser visualizer is not extended.

Logarithmic transforms use relative log/exponential formulas to preserve narrow physical intervals. Chain-rule products combine scales when partial products would overflow or underflow, including exact Hessian-vector products. Regression tests cover the reported f32 failures and extreme ranges on every dense backend. Packaged notices retain sisyfuzz's source/version, copyright, and Apache-2.0 provenance and record the author's contribution under Basin's dual-license terms.

Validation:

  • All three Rust formatting checks, strict rustdoc, Basin all-target/all-feature clippy, and both WASM builds pass.
  • The focused TNC, transform, and f32 suites pass: 45 tests with nalgebra, ndarray, faer, problems, parallel, and serde enabled.
  • The routine pure-Rust suite passes 2,741 tests with solver::newuoa::driver::tests::chained_rosenbrock_6d excluded. That test also fails in a clean archive of the base commit with the same objective value, confirming an existing failure on this Windows environment.
  • cargo package --list --allow-dirty --offline confirms that the adapted modules and the copyright and license notices are included.
  • Workspace clippy could not complete locally because the competitor reference build requires libclang.
  • All four web checks were attempted. Formatting and lint require the missing biome executable; the build requires wasm-pack. Svelte checking also encounters an existing Windows path issue in the mdsvex layout configuration and missing generated WASM bindings.

No new dependencies or executor semantics are introduced. The default Wolfe search uses bounded trial steps but does not guarantee strong-Wolfe conditions at every accepted step; TNC validates feasibility, finite data, and nonincreasing accepted cost.

@jolars jolars left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! This looks good to me. Just a couple of notes that GPT 6.1 sol found when I reviewed the changes. Can you have a look?

Comment on lines +213 to +214
ParameterScale::Logarithmic => {
(value.ln() - a.ln()) / self.widths[i]

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For accepted f32 bounds [100_000_000, 100_001_000], subtracting rounded absolute logarithms loses substantial coordinate precision. encode([100_000_496]) produces [0.4], which decodes to [100_000_408]; the decoder's coarse steps prevent a quadratic centered at the original point from reaching its representable minimum. Use stable relative-log and relative-exponential formulas throughout the mapping, and cover this case in the required f32 round-trip tests.

Comment on lines +267 to +268
ParameterScale::Logarithmic => {
physical.get_scalar(i) * self.widths[i]

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With accepted f32 bounds [1e30, 1e38], this intermediate product can overflow even when the transformed gradient is finite. For f(x) = -ln(x) at unit coordinate 0.99, the correct normalized derivative is approximately -18.42, but gradient() returns -inf, causing TNC to terminate with failure at iteration zero. Apply the chain-rule factors without first materializing the overflowing Jacobian, and add a high-range case to the f32 round-trip coverage.

Comment on lines +55 to +57
/// Adapted from the independent Rust implementation in
/// [`sisyfuzz` 0.1.0](https://docs.rs/crate/sisyfuzz/0.1.0/source/src/tnc.rs)
/// to Basin's [`Solver`] lifecycle and shared line searches.

@jolars jolars Nov 3, 2026 •

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The published sisyfuzz 0.1.0 LICENSE includes Copyright 2026 Frans Henskens, but that attribution is absent from the new module and crates/basin/COPYRIGHT. Please add a source/version, copyright, and license entry for the adapted code to the crate's packaged notices. Basin's README already provides dual-license contribution terms for this author-submitted PR; documenting that alongside the upstream Apache-2.0 provenance would make the licensing of this port clear.

@fhenskens

Copy link
Copy Markdown
Contributor Author

It was right. Fixed upstream too. Thanks for that!

@fhenskens
fhenskens requested a review from jolars November 4, 2026 05:01

@jolars jolars left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thanks!

@jolars
jolars merged commit ac7ea46 into jolars:main Nov 4, 2026
@jolars jolars mentioned this pull request Nov 4, 2026
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.

2 participants