argmin/solver/landweber/mod.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
// Copyright 2018-2020 argmin developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
//! Landweber iteration
//!
//! [Landweber](struct.Landweber.html)
//!
//! # References
//!
//! [0] Landweber, L. (1951): An iteration formula for Fredholm integral equations of the first
//! kind. Amer. J. Math. 73, 615–624
//! [1] https://en.wikipedia.org/wiki/Landweber_iteration
use crate::prelude::*;
use serde::{Deserialize, Serialize};
/// The Landweber iteration is a solver for ill-posed linear inverse problems.
///
/// In iteration `k`, the new parameter vector `x_{k+1}` is calculated from the previous parameter
/// vector `x_k` and the gradient at `x_k` according to the following update rule:
///
/// `x_{k+1} = x_k - omega * \nabla f(x_k)`
///
/// [Example](https://github.com/argmin-rs/argmin/blob/master/examples/landweber.rs)
///
/// # References
///
/// [0] Landweber, L. (1951): An iteration formula for Fredholm integral equations of the first
/// kind. Amer. J. Math. 73, 615–624
/// [1] https://en.wikipedia.org/wiki/Landweber_iteration
#[derive(Clone, Serialize, Deserialize)]
pub struct Landweber<F> {
/// omega
omega: F,
}
impl<F> Landweber<F> {
/// Constructor
pub fn new(omega: F) -> Self {
Landweber { omega }
}
}
impl<O, F> Solver<O> for Landweber<F>
where
O: ArgminOp<Float = F>,
O::Param: ArgminScaledSub<O::Param, O::Float, O::Param>,
F: ArgminFloat,
{
const NAME: &'static str = "Landweber";
fn next_iter(
&mut self,
op: &mut OpWrapper<O>,
state: &IterState<O>,
) -> Result<ArgminIterData<O>, Error> {
let param = state.get_param();
let grad = op.gradient(¶m)?;
let new_param = param.scaled_sub(&self.omega, &grad);
Ok(ArgminIterData::new().param(new_param))
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test_trait_impl;
test_trait_impl!(landweber, Landweber<f64>);
}