ENH: Eigen-backed Levenberg-Marquardt; remove netlib MINPACK#6460
ENH: Eigen-backed Levenberg-Marquardt; remove netlib MINPACK#6460hjmjohnson wants to merge 3 commits into
Conversation
|
Downstream validation (Plastimatch): the Eigen L-M migration + netlib-MINPACK deletion builds and runs correctly in Plastimatch (radiotherapy registration), a real consumer with a direct Why Plastimatch is a meaningful target
Direct vnl_levenberg_marquardt runtime coverage (now executing)Plastimatch ships (First real compilation of Full test results — 579/579, 0 failed, 0 skippedBuilt against this branch's ITK ( No tests reported Not Run / Skipped / Disabled. The ITK-registration family ran with real timings on synthetic phantoms and matched committed baselines (
|
dzenanz
left a comment
There was a problem hiding this comment.
Looks good on a quick glance.
This comment was marked as resolved.
This comment was marked as resolved.
02a837c to
e6313ef
Compare
Add a curated subset of Eigen's unsupported modules to the vendored itkeigen tree to enable an Eigen-backed Levenberg-Marquardt path for the VNL->Eigen numerics migration (ITKv7 direction, InsightSoftwareConsortium#6403; Eigen3 third-party design, InsightSoftwareConsortium#6230): - unsupported/Eigen/NonLinearOptimization (MINPACK lmdif/lmder port + HybridNonLinearSolver), the algorithm-identical counterpart to vnl_levenberg_marquardt. - unsupported/Eigen/LevenbergMarquardt (newer sparse-capable reimplementation, DenseFunctor/SparseFunctor + QRSolver interface). - unsupported/Eigen/NumericalDiff (shared forward/central-difference Jacobian helper required by both). Register the new paths in UpdateFromUpstream.sh so the next Eigen re-sync preserves them, and install the unsupported/Eigen header tree alongside Eigen/ (COPYING.MINPACK was already in the vendored license set). The two umbrella headers are mutually exclusive within a single translation unit (both define Eigen::LevenbergMarquardt); consumers include one per TU.
…mizer Back itk::LevenbergMarquardtOptimizer with the MINPACK-port Levenberg-Marquardt from Eigen's unsupported NonLinearOptimization module (vendored under ThirdParty/Eigen3) as part of the VNL->Eigen numerics migration (InsightSoftwareConsortium#6403, InsightSoftwareConsortium#6230). ITKv6 uses the Eigen engine exclusively. - itkEigenLevenbergMarquardtEngine: a narrow, Eigen-free interface (raw-pointer residual/Jacobian callbacks) delegating to Eigen; no Eigen type appears in the header. The engine ftol mirrors vnl_nonlinear_minimizer's fixed default so the residual stopping criterion matches the historical behavior. - The optimizer drives the engine through the same MultipleValuedVnlCostFunctionAdaptor, so cost-function evaluation and parameter scaling are unchanged. Public API is unchanged; GetOptimizer() and InternalOptimizerType are retained behind itkLegacyMacro (GetOptimizer() now returns nullptr). - A GoogleTest covers Rosenbrock (with/without analytic Jacobian) and a linear least-squares fit; the legacy test drives the optimizer through its own API. A conditioning sweep showed the Eigen and netlib MINPACK engines are numerically equivalent (residuals agree to machine precision on every converged problem) while Eigen is faster.
Replace the vendored netlib MINPACK lmdif/lmder engine behind vnl_levenberg_marquardt with Eigen's MINPACK-port Levenberg-Marquardt (unsupported/Eigen/NonLinearOptimization), and delete the now-unused netlib minpack sources. Both are ports of MINPACK lmdif/lmder, so the result is numerically equivalent; vnl_algo test_levenberg_marquardt passes unchanged. The public vnl_levenberg_marquardt API is preserved verbatim (minimize / minimize_using_gradient / minimize_without_gradient, the MINPACK info return codes, num_iterations/num_evaluations, start/end RMS error, diagnose_outcome, and get_JtJ via the R factor and permutation repopulated from the Eigen solve). Downstream direct callers such as Plastimatch's ransac SphereParametersEstimator compile and run unchanged. vnl_levenberg_marquardt was the sole consumer of the netlib minpack routines (dpmpar/enorm/fdjac2/lmder/lmder1/lmdif/lmpar/qrfac/qrsolv), so they are removed from v3p/netlib and its build, and the includes dropped from v3p_netlib_prototypes.h. This is an ITK-vendored-only divergence from upstream VXL. The re-backing requires Eigen, which standalone VXL does not have; and the netlib deletion cannot stand alone in VXL because vnl_levenberg_marquardt there is still netlib-backed (deletion and re-backing are coupled). Neither half is therefore upstreamable to the vxl extraction fork, so UpdateFromUpstream must re-apply the whole change on each VXL/Eigen re-sync. Refs: ITKv7 numerics direction InsightSoftwareConsortium#6403, Eigen3 third-party design InsightSoftwareConsortium#6230.
e6313ef to
0208b00
Compare
Migrates the Levenberg-Marquardt path from the vendored netlib MINPACK to Eigen's MINPACK-port Levenberg-Marquardt (
unsupported/Eigen/NonLinearOptimization), part of the ITKv7 VNL→Eigen numerics direction (#6403, #6230).itk::LevenbergMarquardtOptimizeris now Eigen-backed,vnl_levenberg_marquardtis auto-routed to the same Eigen engine with its public API unchanged, and the now-unused netlibminpack/sources are deleted.Both engines are MINPACK
lmdif/lmderports, so the result is numerically equivalent (residuals agree to machine precision on every converged problem) while Eigen is faster.Note
Direct downstream callers of
vnl_levenberg_marquardtare unaffected. The public header is unchanged; the only direct consumer found across the build forest — Plastimatch's RANSACSphereParametersEstimator(SlicerRT) — compiles, links, and runs unchanged against this branch (verified locally).Important
This is an ITK-vendored-only divergence from upstream VXL:
itkvnl_algogains a header-only Eigen3 dependency that cannot be carried to standalone VXL (which has no Eigen), and the netlib deletion cannot stand alone in VXL either.UpdateFromUpstreammust re-apply the whole change on each VXL/Eigen re-sync. No change is pushed to the vxl extraction fork.What changed (3 commits)
NonLinearOptimization,LevenbergMarquardt,NumericalDiffunderitkeigen/unsupported/, registered inUpdateFromUpstream.sh, with install rules. Verified MPL2-clean (compiles underEIGEN_MPL2_ONLY, which CI enables).itk::LevenbergMarquardtOptimizer— a narrow, Eigen-free engine interface (itkEigenLevenbergMarquardtEngine, raw-pointer residual/Jacobian callbacks; no Eigen in the header per ENH: Master tracking — Eigen3 third-party design for ITK 6.x #6230) driven through the existingMultipleValuedVnlCostFunctionAdaptor.GetOptimizer()/InternalOptimizerTyperetained behinditkLegacyMacro(GetOptimizer()returnsnullptr). New GoogleTest (Rosenbrock ±Jacobian, linear least-squares); legacy test drives the optimizer through its own API.vnl_levenberg_marquardton Eigen; remove netlib MINPACK — public API preserved verbatim (minimize*, MINPACK return codes, iteration/eval counts, start/end RMS,diagnose_outcome,get_JtJvia the R-factor + permutation from the Eigen solve). Deletes the 9 netlibminpack/routines (sole consumer wasvnl_levenberg_marquardt).Performance / accuracy gate
Conditioning sweep (exponential-sum least squares; single-threaded, Release, median of N reps), Eigen vs netlib through the same optimizer:
Validated locally: full ITK build (0 failures), all 24
vnl_algotests,vnl_algo_test_levenberg_marquardt, the ITK optimizer GoogleTest + legacy test, and the Plastimatch-usage compile/link/run.