pub struct Corrector { /* private fields */ }Expand description
Corrector for applying robust loss functions via residual and Jacobian adjustment.
This struct holds the precomputed scaling factors needed to transform a robust loss problem into an equivalent reweighted least squares problem. It is instantiated once per residual block during each iteration of the optimizer.
§Fields
sqrt_rho1: √(ρ’(s)) - Square root of the first derivative, used for residual scalingresidual_scaling: √(ρ’(s)) - Same as sqrt_rho1, stored separately for clarityalpha_sq_norm: α² = ρ’‘(s) / ρ’(s) - Ratio of second to first derivative, used for Jacobian correction
where s = ||r||² is the squared norm of the residual.
Implementations§
Source§impl Corrector
impl Corrector
Sourcepub fn new(loss_function: &dyn LossFunction, sq_norm: f64) -> Self
pub fn new(loss_function: &dyn LossFunction, sq_norm: f64) -> Self
Create a new Corrector by evaluating the loss function at the given squared norm.
§Arguments
loss_function- The robust loss function ρ(s)sq_norm- The squared norm of the residual:s = ||r||²
§Returns
A Corrector instance with precomputed scaling factors
§Example
use apex_solver::core::corrector::Corrector;
use apex_solver::core::loss_functions::{LossFunction, HuberLoss};
use nalgebra::DVector;
let loss = HuberLoss::new(1.0)?;
let residual = DVector::from_vec(vec![1.0, 2.0, 3.0]);
let squared_norm = residual.dot(&residual); // 14.0
let corrector = Corrector::new(&loss, squared_norm);
// corrector is now ready to apply correctionsSourcepub fn correct_jacobian(
&self,
residual: &DVector<f64>,
jacobian: &mut DMatrix<f64>,
)
pub fn correct_jacobian( &self, residual: &DVector<f64>, jacobian: &mut DMatrix<f64>, )
Apply correction to the Jacobian matrix.
Transforms the Jacobian J into J̃ according to the Ceres Solver corrector algorithm:
J̃ = √(ρ'(s)) · (J - α²·r·r^T·J)where:
√(ρ'(s))scales the Jacobian by the loss function weightαis computed by solving the quadratic equation: 0.5·α² - α - (ρ’‘/ρ’)·s = 0- The subtractive term
α²·r·r^T·Jis a rank-1 curvature correction
§Arguments
residual- The original residual vectorrjacobian- Mutable reference to the Jacobian matrix (modified in-place)
§Implementation Notes
The correction is applied in-place for efficiency. The algorithm:
- Scales all Jacobian entries by
√(ρ'(s)) - Adds the outer product correction:
α · (J^T r) · r^T / ||r||
§Example
use apex_solver::core::corrector::Corrector;
use apex_solver::core::loss_functions::{LossFunction, HuberLoss};
use nalgebra::{DVector, DMatrix};
let loss = HuberLoss::new(1.0)?;
let residual = DVector::from_vec(vec![2.0, 1.0]);
let squared_norm = residual.dot(&residual);
let corrector = Corrector::new(&loss, squared_norm);
let mut jacobian = DMatrix::from_row_slice(2, 3, &[
1.0, 0.0, 1.0,
0.0, 1.0, 1.0,
]);
corrector.correct_jacobian(&residual, &mut jacobian);
// jacobian is now corrected to account for the robust lossSourcepub fn correct_residuals(&self, residual: &mut DVector<f64>)
pub fn correct_residuals(&self, residual: &mut DVector<f64>)
Apply correction to the residual vector.
Transforms the residual r into r̃ by scaling:
r̃ = √(ρ'(s)) · rThis ensures that ||r̃||² ≈ ρ(||r||²), i.e., the squared norm of the corrected
residual approximates the robust cost.
§Arguments
residual- Mutable reference to the residual vector (modified in-place)
§Example
use apex_solver::core::corrector::Corrector;
use apex_solver::core::loss_functions::{LossFunction, HuberLoss};
use nalgebra::DVector;
let loss = HuberLoss::new(1.0)?;
let mut residual = DVector::from_vec(vec![2.0, 3.0, 1.0]);
let squared_norm = residual.dot(&residual);
let corrector = Corrector::new(&loss, squared_norm);
corrector.correct_residuals(&mut residual);
// Outlier residuals are scaled downTrait Implementations§
Auto Trait Implementations§
impl Freeze for Corrector
impl RefUnwindSafe for Corrector
impl Send for Corrector
impl Sync for Corrector
impl Unpin for Corrector
impl UnwindSafe for Corrector
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> DistributionExt for Twhere
T: ?Sized,
impl<T> DistributionExt for Twhere
T: ?Sized,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.