# Least Squares Module
This module provides a comprehensive suite of least squares optimization algorithms for different problem types.
## Available Methods
### Standard Least Squares
- `least_squares()`: Basic nonlinear least squares solver
- Levenberg-Marquardt algorithm
- Trust Region Reflective algorithm
- Suitable for well-conditioned problems with clean data
### Robust Least Squares
- `robust_least_squares()`: M-estimators for outlier-resistant regression
- **Huber Loss**: Quadratic for small residuals, linear for large ones
- **Bisquare (Tukey) Loss**: Completely rejects extreme outliers
- **Cauchy Loss**: Very strong outlier protection with slowly decreasing influence
- Uses Iteratively Reweighted Least Squares (IRLS) algorithm
### Weighted Least Squares
- `weighted_least_squares()`: Handles heteroscedastic data (varying variance)
- Allows different importance weights for each data point
- Essential when measurement errors vary across observations
- Uses modified Gauss-Newton algorithm
### Bounded Least Squares
- `bounded_least_squares()`: Box constraints on parameters
- Enforces upper and lower bounds on variables
- Trust region reflective algorithm adapted for bounds
- Useful when parameters have physical constraints
### Separable Least Squares
- `separable_least_squares()`: Variable projection for partially linear models
- Optimizes models of the form: f(x, α, β) = Σ αᵢ φᵢ(x, β)
- Reduces dimensionality by eliminating linear parameters
- Uses VARPRO algorithm for efficient optimization
- Useful for exponential models, Gaussian mixtures, etc.
### Total Least Squares
- `total_least_squares()`: Errors-in-variables regression
- Handles measurement errors in both x and y variables
- Minimizes orthogonal distances to the fitted line
- Supports weighted TLS with known error variances
- Useful for instrument calibration and measurement analysis
## When to Use Each Method
1. **Standard Least Squares**:
- Data is clean (no outliers)
- Measurement errors have constant variance
- No constraints on parameters
2. **Robust Least Squares**:
- Data contains outliers
- Need to minimize influence of anomalous measurements
- Choose loss function based on outlier severity:
- Huber: Moderate outliers
- Bisquare: Strong outliers
- Cauchy: Very strong outliers
3. **Weighted Least Squares**:
- Measurement errors vary across observations
- Some data points are more reliable than others
- Known variance structure in the data
4. **Bounded Least Squares**:
- Parameters must stay within physical limits
- Need to enforce box constraints
- Regularization through bounds
5. **Separable Least Squares**:
- Model is linear in some parameters
- Want to reduce optimization complexity
- Common in curve fitting (exponentials, Gaussians)
6. **Total Least Squares**:
- Both x and y have measurement errors
- Need to minimize perpendicular distances
- Instrument calibration problems
- Error variances are known (for weighted version)
## Example Usage
```rust
use ndarray::{array, Array1};
use scirs2_optimize::least_squares::{
least_squares, robust_least_squares, weighted_least_squares, bounded_least_squares,
Method, HuberLoss
};
// Define residual function for exponential model: y = a * exp(b * x)
fn residual(params: &[f64], data: &[f64]) -> Array1<f64> {
let a = params[0];
let b = params[1];
let n = data.len() / 2;
let x_vals = &data[0..n];
let y_vals = &data[n..];
let mut residuals = Array1::zeros(n);
for i in 0..n {
let predicted = a * (b * x_vals[i]).exp();
residuals[i] = y_vals[i] - predicted;
}
residuals
}
// Standard least squares
let result = least_squares(residual, &x0, Method::LevenbergMarquardt, None, &data, None)?;
// Robust least squares with Huber loss
let loss = HuberLoss::new(1.0);
let result = robust_least_squares(residual, &x0, loss, None, &data, None)?;
// Weighted least squares
let weights = array![1.0, 0.5, 2.0]; // Different weights for each residual
let result = weighted_least_squares(residual, &x0, &weights, None, &data, None)?;
// Bounded least squares
let bounds = Bounds::new(&[(Some(0.0), None), (None, Some(1.0))]);
let result = bounded_least_squares(residual, &x0, Some(bounds), None, &data, None)?;
```
## Implementation Details
All methods support:
- Optional analytical Jacobian (uses finite differences if not provided)
- Configurable convergence criteria
- Maximum iteration limits
- Function evaluation counting
The algorithms are implemented in pure Rust for:
- Memory safety
- Performance
- Cross-platform compatibility