pub trait OuterHessianOperator: Send + Sync {
// Required methods
fn dim(&self) -> usize;
fn matvec(&self, v: &Array1<f64>) -> Result<Array1<f64>, String>;
// Provided methods
fn apply_into(
&self,
v: &Array1<f64>,
out: &mut Array1<f64>,
) -> Result<(), String> { ... }
fn is_cheap_to_materialize(&self) -> bool { ... }
fn materialization_capability(&self) -> OuterHessianMaterialization { ... }
fn mul_mat(
&self,
factor: ArrayView2<'_, f64>,
) -> Result<Array2<f64>, String> { ... }
fn materialize_dense(&self) -> Result<Array2<f64>, String> { ... }
}Expand description
Matrix-free outer Hessian operator.
This is the exact outer Hessian action H_outer * v evaluated at the
current outer point, without requiring dense materialization.
The trait provides four increasingly materialized primitives:
matvec— single column, the only one implementors must provide.mul_mat— multi-column; the default falls back to column-by-columnmatvec. Implementors override this when they can amortize per-Hv-apply overhead (cached factorizations, parallel matvecs) across many right-hand-sides.materialization_capability— an explicit work-model contract that tells ARC whether dense exact materialization is unavailable, cheap repeated-HVP, batched-HVP, or explicit.materialize_dense— the special casemul_mat(I_dim)followed by a symmetric average of the off-diagonals to absorb round-off asymmetry. ARC callers only use this whenmaterialization_capabilityadvertises an exact dense route, preserving the no-numerical-Hessian policy.
Required Methods§
Provided Methods§
Sourcefn apply_into(
&self,
v: &Array1<f64>,
out: &mut Array1<f64>,
) -> Result<(), String>
fn apply_into( &self, v: &Array1<f64>, out: &mut Array1<f64>, ) -> Result<(), String>
Write out <- H * v into a caller-supplied buffer. Default
impl wraps matvec and copies; backends override for a true
zero-alloc inner-CG path. The matrix-free trust-region adapter
(OuterToOptHessianOperator) calls this on every CG step
inside opt::MatrixFreeTrustRegion, so an override compounds:
over a 50-outer-iter × 30-CG-iter solve at n=200 the default
path allocates 1500 transient Array1<f64> of size 200 that
the override eliminates.
Sourcefn is_cheap_to_materialize(&self) -> bool
fn is_cheap_to_materialize(&self) -> bool
Whether probing all basis columns is cheap enough for dense ARC.
The default is deliberately conservative. For operator-backed Duchon,
CTN, survival, or other row-streaming kernels, dim <= 64 does not
imply cheap materialization: each column may trigger a full data pass.
New implementations should prefer overriding
materialization_capability so the
caller can distinguish cheap repeated probes from true batched/explicit
Hessian materialization.
Sourcefn materialization_capability(&self) -> OuterHessianMaterialization
fn materialization_capability(&self) -> OuterHessianMaterialization
Exact dense-materialization capability for this operator.
The default preserves the historical work-model hook: operators that
already opted into cheap probing via
is_cheap_to_materialize are treated
as exact repeated-HVP materializers. Backends that can amortize or avoid
basis probes should override this to return
OuterHessianMaterialization::BatchedHvp or
OuterHessianMaterialization::Explicit.
Sourcefn mul_mat(&self, factor: ArrayView2<'_, f64>) -> Result<Array2<f64>, String>
fn mul_mat(&self, factor: ArrayView2<'_, f64>) -> Result<Array2<f64>, String>
Apply the operator to all m columns of factor, returning a
dim × m matrix whose jth column is H · factor[:, j].
The default implementation runs the per-column matvecs in parallel
over rayon — each matvec is independent and the K×K basis-probe used
by materialize_dense issues exactly dim
such calls. Implementors override when batching is cheaper (cached
factorizations, BLAS-3 kernels). All
materialize_dense callers route through
this method, so an override automatically accelerates any
work-model-approved materialization path used by the planner.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".