rom.ecsw.custom_nnls

Purpose: Provides a flexible, robust bounded Non-Negative Least Squares (NNLS) solver for computing positive cubature weights in ECSW-based hyperreduction pipelines. Designed to find non-negative weight vectors that satisfy a linear system within per-entry bounds, with precise control over sparsity, convergence criteria, and solver diagnostics.

Summary: Implements an active-set NNLS algorithm supporting per-entry lower and upper bounds on the right-hand side, configurable sparsity constraints (minimum and maximum nonzeros), stall detection, and two convergence criteria (L2 norm or L∞ norm). The NNLSSolver class is the primary entry point for ECSW weight computation, and the NNLS_termination enum selects the stopping condition. This module is a Python adaptation of the libROM NNLS implementation from the LLNL team.

Original C++ Reference: libROM team, LLNL

Python Adaptation: Suparno Bhattacharyya


Classes

Name Description
NNLSSolver Active-set NNLS solver with configurable bounds, sparsity constraints, and convergence criteria.
NNLS_termination Enumeration for selecting the solver termination criterion (L2 or L∞).

NNLSSolver

rom.ecsw.custom_nnls.NNLSSolver(
    const_tol=1e-06,
    min_nnz=1,
    max_nnz=0,
    verbosity=1,
    res_change_termination_tol=1e-10,
    zero_tol=1e-15,
    n_outer=1000,
    n_inner=400,
    criterion=NNLS_termination.LINF,
)

Summary: Solves the bounded non-negative least squares problem: find ( ) such that ( A ), where each entry of ( ) may be constrained to a range ([{},, {}]). The active-set algorithm iteratively adapts the set of active (nonzero) variables while enforcing non-negativity, per-entry bounds, sparsity constraints, and stall detection. Key algorithmic properties include:

  • Active-set method: Dynamically maintains the set of nonzero variables, updating it at each outer iteration to maximize constraint satisfaction.
  • Per-entry bound support: Each right-hand side entry can independently have a lower and upper bound, providing flexible constraint specification beyond simple non-negativity.
  • Dual termination criteria: Convergence can be assessed via the L2 norm (sum-of-squares residual) or the L∞ norm (maximum single constraint violation), selectable via criterion.
  • Stall detection: If the mean residual change over 50 consecutive steps falls below res_change_termination_tol, the solver exits early with a stall flag.
  • Sparsity control: min_nnz and max_nnz allow enforcement of sparse solutions, which is critical for ECSW cubature rules where a minimal element subset is desired.

Parameters

Name Type Description Default
const_tol float Tolerance for constraint violations evaluated under the infinity norm criterion. 1e-06
min_nnz int Minimum number of nonzero entries required in the solution before the solver may terminate. 1
max_nnz int Maximum number of nonzero entries permitted in the solution; 0 imposes no upper limit. 0
verbosity int Console output level: 0 for silent, 1 for summary only, ≥2 for detailed per-iteration diagnostics. 1
res_change_termination_tol float Stall detection threshold; if the mean residual change over 50 steps falls below this value, the solver exits with a stall exit code. 1e-10
zero_tol float Numerical zero threshold; values with absolute magnitude below this are treated as zero to suppress numerical noise. 1e-15
n_outer int Maximum number of active-set (outer) iterations before termination. 1000
n_inner int Maximum number of inner iterations per active-set update step. 400
criterion NNLS_termination Stopping condition: L2 (residual sum-of-squares below threshold) or LINF (maximum constraint violation below const_tol). LINF

Attributes

Name Type Description
const_tol_ float Active constraint violation tolerance.
min_nnz_ int Minimum required number of nonzero solution entries.
max_nnz_ int Maximum permitted number of nonzero solution entries.
verbosity_ int Current output verbosity level.
res_change_termination_tol_ float Stall detection threshold for residual change monitoring.
zero_tol_ float Numerical zero threshold for noise suppression.
n_outer_ int Maximum outer (active-set) iteration count.
n_inner_ int Maximum inner iteration count per active-set step.
d_criterion NNLS_termination Active convergence criterion.

Example

>>> from nnls_solver import NNLSSolver, NNLS_termination
>>> import numpy as np
>>> A = np.random.rand(20, 10)
>>> const_tol_ = 1e-3
>>> lb = b - const_tol_
>>> ub = b + const_tol_
>>> solver = NNLSSolver(const_tol=const_tol_, verbosity=2)
>>> x, flag = solver.solve(A, lb, ub)
>>> print("Exit flag:", flag)

Methods

Name Description
set_verbosity Update the output verbosity level for subsequent solver runs.
solve Solve the bounded non-negative least squares problem using the active-set method.

set_verbosity

rom.ecsw.custom_nnls.NNLSSolver.set_verbosity(verbosity_in)

Summary: Updates the solver’s verbosity level, controlling the volume of diagnostic output printed during subsequent calls to solve. Setting 0 suppresses all output; higher values progressively enable more detailed per-iteration reporting.

Parameters
Name Type Description Default
verbosity_in int New output verbosity level; 0 for silent, 1 for summary, ≥2 for detailed diagnostics. required

solve

rom.ecsw.custom_nnls.NNLSSolver.solve(mat, rhs_lb, rhs_ub)

Summary: Solves the bounded non-negative least squares problem: find ( ) such that ( A ) with ( ) entry-wise. The active-set algorithm iterates over candidate nonzero sets, updating the active variables to progressively reduce constraint violations until the selected termination criterion (L2 or LINF) is satisfied, sparsity limits are met, or a maximum iteration count or stall condition is reached.

Parameters
Name Type Description Default
mat array_like, shape (m, n) System matrix ( A ) for the least squares problem. required
rhs_lb array_like, shape (m,) Per-entry lower bounds on the right-hand side ( ). required
rhs_ub array_like, shape (m,) Per-entry upper bounds on the right-hand side ( ). required
Returns
Name Type Description
final_soln ndarray, shape (n,) Non-negative solution vector ( ).
exit_flag int Solver status code: 0 = converged successfully; 1 = reached maximum iterations; 2 = stalled (residual change below res_change_termination_tol); 3 = failed.

NNLS_termination

rom.ecsw.custom_nnls.NNLS_termination()

Summary: Enumeration for selecting the convergence criterion used by NNLSSolver. Determines how the solver assesses whether the current solution satisfies the constraint tolerance.

Name Type Description
L2 int Terminate when the L2 norm (sum of squared residuals) falls below the constraint tolerance. Corresponds to standard least-squares convergence.
LINF int Terminate when the L∞ norm (largest single constraint violation) falls below const_tol. Stricter than L2—ensures no individual constraint is significantly violated. Default criterion.

Notes

LINF (default) is the more conservative criterion and is recommended for ECSW weight computation where individual constraint violations can produce physically inconsistent cubature rules. L2 may be preferred when a globally small residual is sufficient and isolated violations are acceptable.