Mathematical optimization in pure Rust

Overview

CircleCI Build Status Gitter chat

argmin

A pure Rust optimization framework

This crate offers a numerical optimization toolbox/framework written entirely in Rust. It is at the moment potentially very buggy. Please use with care and report any bugs you encounter. This crate is looking for contributors!

Documentation of most recent release

Documentation of master

Design goals

This crate's intention is to be useful to users as well as developers of optimization algorithms, meaning that it should be both easy to apply and easy to implement algorithms. In particular, as a developer of optimization algorithms you should not need to worry about usability features (such as logging, dealing with different types, setters and getters for certain common parameters, counting cost function and gradient evaluations, termination, and so on). Instead you can focus on implementing your algorithm.

  • Easy framework for the implementation of optimization algorithms: Implement a single iteration of your method and let the framework do the rest. This leads to similar interfaces for different solvers, making it easy for users.
  • Pure Rust implementations of a wide range of optimization methods: This avoids the need to compile and interface C/C++/Fortran code.
  • Type-agnostic: Many problems require data structures that go beyond simple vectors to represent the parameters. In argmin, everything is generic: All that needs to be done is implementing certain traits on your data type. For common types, these traits are already implemented.
  • Convenient: Easy and consistent logging of anything that may be important. Log to the terminal, to a file or implement your own observers. Future plans include sending metrics to databases and connecting to big data piplines.
  • Algorithm evaluation: Methods to assess the performance of an algorithm for different parameter settings, problem classes, ...

Since this crate is in a very early stage, so far most points are only partially implemented or remain future plans.

Algorithms

Usage

Add this to your Cargo.toml:

[dependencies]
argmin = "0.4.1"

Optional features (recommended)

There are additional features which can be activated in Cargo.toml:

[dependencies]
argmin = { version = "0.4.1", features = ["ctrlc", "ndarrayl", "nalgebral"] }

These may become default features in the future. Without these features compilation to wasm32-unknown-unkown seems to be possible.

  • ctrlc: Uses the ctrlc crate to properly stop the optimization (and return the current best result) after pressing Ctrl+C.
  • ndarrayl: Support for ndarray, ndarray-linalg and ndarray-rand.
  • nalgebral: Support for nalgebra.

Running the tests

Running the tests requires the ndarrayl and nalgebral features to be enabled

cargo test --features "ndarrayl nalgebral"

Defining a problem

A problem can be defined by implementing the ArgminOp trait which comes with the associated types Param, Output and Hessian. Param is the type of your parameter vector (i.e. the input to your cost function), Output is the type returned by the cost function and Hessian is the type of the Hessian. The trait provides the following methods:

  • apply(&self, p: &Self::Param) -> Result<Self::Output, Error>: Applys the cost function to parameters p of type Self::Param and returns the cost function value.
  • gradient(&self, p: &Self::Param) -> Result<Self::Param, Error>: Computes the gradient at p.
  • hessian(&self, p: &Self::Param) -> Result<Self::Hessian, Error>: Computes the Hessian at p.

The following code snippet shows an example of how to use the Rosenbrock test functions from argmin-testfunctions in argmin:

use argmin::testfunctions::{rosenbrock_2d, rosenbrock_2d_derivative, rosenbrock_2d_hessian};
use argmin::prelude::*;
use serde::{Serialize, Deserialize};

/// First, create a struct for your problem
#[derive(Clone, Default, Serialize, Deserialize)]
struct Rosenbrock {
    a: f64,
    b: f64,
}

/// Implement `ArgminOp` for `Rosenbrock`
impl ArgminOp for Rosenbrock {
    /// Type of the parameter vector
    type Param = Vec<f64>;
    /// Type of the return value computed by the cost function
    type Output = f64;
    /// Type of the Hessian. Can be `()` if not needed.
    type Hessian = Vec<Vec<f64>>;

    /// Apply the cost function to a parameter `p`
    fn apply(&self, p: &Self::Param) -> Result<Self::Output, Error> {
        Ok(rosenbrock_2d(p, self.a, self.b))
    }

    /// Compute the gradient at parameter `p`.
    fn gradient(&self, p: &Self::Param) -> Result<Self::Param, Error> {
        Ok(rosenbrock_2d_derivative(p, self.a, self.b))
    }

    /// Compute the Hessian at parameter `p`.
    fn hessian(&self, p: &Self::Param) -> Result<Self::Hessian, Error> {
        let t = rosenbrock_2d_hessian(p, self.a, self.b);
        Ok(vec![vec![t[0], t[1]], vec![t[2], t[3]]])
    }
}

It is optional to implement any of these methods, as there are default implementations which will return an Err when called. What needs to be implemented is defined by the requirements of the solver that is to be used.

Running a solver

The following example shows how to use the previously shown definition of a problem in a Steepest Descent (Gradient Descent) solver.

use argmin::prelude::*;
use argmin::solver::gradientdescent::SteepestDescent;
use argmin::solver::linesearch::MoreThuenteLineSearch;

// Define cost function (must implement `ArgminOperator`)
let cost = Rosenbrock { a: 1.0, b: 100.0 };

// Define initial parameter vector
let init_param: Vec<f64> = vec![-1.2, 1.0];

// Set up line search
let linesearch = MoreThuenteLineSearch::new();

// Set up solver
let solver = SteepestDescent::new(linesearch);

// Run solver
let res = Executor::new(cost, solver, init_param)
    // Add an observer which will log all iterations to the terminal
    .add_observer(ArgminSlogLogger::term(), ObserverMode::Always)
    // Set maximum iterations to 10
    .max_iters(10)
    // run the solver on the defined problem
    .run()?;

// print result
println!("{}", res);

Observing iterations

Argmin offers an interface to observe the state of the iteration at initialization as well as after every iteration. This includes the parameter vector, gradient, Hessian, iteration number, cost values and many more as well as solver-specific metrics. This interface can be used to implement loggers, send the information to a storage or to plot metrics. Observers need to implment the Observe trait. Argmin ships with a logger based on the slog crate. ArgminSlogLogger::term logs to the terminal and ArgminSlogLogger::file logs to a file in JSON format. Both loggers also come with a *_noblock version which does not block the execution of logging, but may drop some messages if the buffer is full. Parameter vectors can be written to disc using WriteToFile. For each observer it can be defined how often it will observe the progress of the solver. This is indicated via the enum ObserverMode which can be either Always, Never, NewBest (whenever a new best solution is found) or Every(i) which means every ith iteration.

let res = Executor::new(problem, solver, init_param)
    // Add an observer which will log all iterations to the terminal (without blocking)
    .add_observer(ArgminSlogLogger::term_noblock(), ObserverMode::Always)
    // Log to file whenever a new best solution is found
    .add_observer(ArgminSlogLogger::file("solver.log")?, ObserverMode::NewBest)
    // Write parameter vector to `params/param.arg` every 20th iteration
    .add_observer(WriteToFile::new("params", "param"), ObserverMode::Every(20))
    // run the solver on the defined problem
    .run()?;

Checkpoints

The probability of crashes increases with runtime, therefore one may want to save checkpoints in order to be able to resume the optimization after a crash. The CheckpointMode defines how often checkpoints are saved and is either Never (default), Always (every iteration) or Every(u64) (every Nth iteration). It is set via the setter method checkpoint_mode of Executor. In addition, the directory where the checkpoints and a prefix for every file can be set via checkpoint_dir and checkpoint_name, respectively.

The following example shows how the from_checkpoint method can be used to resume from a checkpoint. In case this fails (for instance because the file does not exist, which could mean that this is the first run and there is nothing to resume from), it will resort to creating a new Executor, thus starting from scratch.

let res = Executor::from_checkpoint(".checkpoints/optim.arg")
    .unwrap_or(Executor::new(operator, solver, init_param))
    .max_iters(iters)
    .checkpoint_dir(".checkpoints")
    .checkpoint_name("optim")
    .checkpoint_mode(CheckpointMode::Every(20))
    .run()?;

Implementing an optimization algorithm

In this section we are going to implement the Landweber solver, which essentially is a special form of gradient descent. 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)

In order to implement this using the argmin framework, one first needs to define a struct which holds data specific to the solver. Then, the Solver trait needs to be implemented for the struct. This requires setting the associated constant NAME which gives your solver a name. The next_iter method defines the computations performed in a single iteration of the solver. Via the parameters op and state one has access to the operator (cost function, gradient computation, Hessian, ...) and to the current state of the optimization (parameter vectors, cost function values, iteration number, ...), respectively.

use argmin::prelude::*;
use serde::{Deserialize, Serialize};

// Define a struct which holds any parameters/data which are needed during the execution of the
// solver. Note that this does not include parameter vectors, gradients, Hessians, cost
// function values and so on, as those will be handled by the `Executor`.
#[derive(Serialize, Deserialize)]
pub struct Landweber {
    /// omega
    omega: f64,
}

impl Landweber {
    /// Constructor
    pub fn new(omega: f64) -> Self {
        Landweber { omega }
    }
}

impl<O> Solver<O> for Landweber
where
    // `O` always needs to implement `ArgminOp`
    O: ArgminOp,
    // `O::Param` needs to implement `ArgminScaledSub` because of the update formula
    O::Param: ArgminScaledSub<O::Param, f64, O::Param>,
{
    // This gives the solver a name which will be used for logging
    const NAME: &'static str = "Landweber";

    // Defines the computations performed in a single iteration.
    fn next_iter(
        &mut self,
        // This gives access to the operator supplied to the `Executor`. `O` implements
        // `ArgminOp` and `OpWrapper` takes care of counting the calls to the respective
        // functions.
        op: &mut OpWrapper<O>,
        // Current state of the optimization. This gives access to the parameter vector,
        // gradient, Hessian and cost function value of the current, previous and best
        // iteration as well as current iteration number, and many more.
        state: &IterState<O>,
    ) -> Result<ArgminIterData<O>, Error> {
        // First we obtain the current parameter vector from the `state` struct (`x_k`).
        let xk = state.get_param();
        // Then we compute the gradient at `x_k` (`\nabla f(x_k)`)
        let grad = op.gradient(&xk)?;
        // Now subtract `\nabla f(x_k)` scaled by `omega` from `x_k` to compute `x_{k+1}`
        let xkp1 = xk.scaled_sub(&self.omega, &grad);
        // Return new paramter vector which will then be used by the `Executor` to update
        // `state`.
        Ok(ArgminIterData::new().param(xkp1))
    }
}

TODOs

  • More optimization methods
  • Automatic differentiation
  • Parallelization
  • Tests
  • Evaluation on real problems
  • Evaluation framework
  • Documentation & Tutorials
  • C interface
  • Python wrapper
  • Solver and problem definition via a config file

Please open an issue if you want to contribute! Any help is appreciated!

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

License: MIT OR Apache-2.0

Comments
  • Hide Serialization/Deserialization behind feature gate

    Hide Serialization/Deserialization behind feature gate

    Currently Serialization and Deserialization is implemented for all types which get serialized when creating a checkpoint. It would be convenient if this was optional by hiding it behind a feature gate.

    enhancement help wanted good first issue 
    opened by stefan-k 20
  • Add bulk ArgminOp functions

    Add bulk ArgminOp functions

    Addresses #6

    I considered taking an IntoIterator rather than a slice but rayon can't turn that into a parallel iterator without extra trait requirements.

    We could update ParticleSwarm to use bulk_apply like so, but it requires two extra Vec collects

        p.position = O::Param::min(
            &O::Param::max(&new_position, &self.search_region.0),
            &self.search_region.1,
        );
    }
    
    let new_costs = op.bulk_apply(self.particles.iter().map(|p| p.position.clone().collect()))?;
    
    for (p, new_cost) in self.particles.iter_mut().zip(new_costs) {
        if new_cost < p.best_cost {
            p.best_position = p.position.clone();
    

    If we do it would be good to add a note to the PS example.

    opened by TheIronBorn 17
  • Automatic Differentiation

    Automatic Differentiation

    Automatic Differentiation (AD) generates the derivative of arbitrary order n for an input function and is heavily used in Machine Learning. Perhaps we can implement one behind a feature flag. Some previous attempts are:

    • https://github.com/yati-sagade/autodiff-rust
    • https://github.com/raskr/rust-autograd
    • https://github.com/AtheMathmo/rugrads

    I imagine a rust macro which takes a normal pure function and automatically implements the ArgminOp trait. An overview and starting point can be found here: https://arxiv.org/abs/1502.05767

    opened by bytesnake 16
  • Particle Swarm Optimization -ArgminRandom trait

    Particle Swarm Optimization -ArgminRandom trait

    Hi

    I have an issue whenever I try to instantiate the ParticleSwarm optimizer and set the bounds as f64 as per below: let solver = ParticleSwarm::new((-0.3, 0.3), 40);

    returns the errors: the trait argmin_math::ArgminRandom is not implemented for f64 (even though it seems to be the case).

    I use argmin v0.7.0. Also, the example provided in particleswarm.rs leads to a similar error.

    Thank you in advance, amazing work!

    opened by thibc81 14
  • Unable to compile Nelder-Mead example

    Unable to compile Nelder-Mead example

    Note: I had to switch to building with the nightly toolchain because of issues with ndalgebra v0.26.2 due to "feature resolver isrequired"

    I attempted to compile and run the Nelder-Mead example using the following in my Cargo.toml:

    [dependencies]
    argmin = { version = "0.4.4", features = ["ctrlc", "ndarrayl", "nalgebral"] }
    argmin_testfunctions = "*"
    ndarray = { version = "0.15", features = ["serde"] }
    

    Adding features = ["serde"] was added to eliminate Serialize and Deserialize errors. Now I am getting the following errors:

    error[E0277]: the trait bound `ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>: ArgminAdd<ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>, ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>>` is not satisfied    
      --> src\main.rs:36:30
       |
    36 |           .with_initial_params(vec![
       |  ______________________________^
    37 | |             // array![-2.0, 3.0],
    38 | |             // array![-2.0, -1.0],
    39 | |             // array![2.0, -1.0],
    ...  |
    42 | |             array![2.0, -1.0],
    43 | |         ])
       | |_________^ the trait `ArgminAdd<ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>, ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>>` is not implemented for `ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>`
       |
       = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
    
    error[E0277]: the trait bound `ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>: ArgminSub<ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>, ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>>` is not satisfied
      --> src\main.rs:36:30
       |
    36 |           .with_initial_params(vec![
       |  ______________________________^
    37 | |             // array![-2.0, 3.0],
    38 | |             // array![-2.0, -1.0],
    39 | |             // array![2.0, -1.0],
    ...  |
    42 | |             array![2.0, -1.0],
    43 | |         ])
       | |_________^ the trait `ArgminSub<ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>, ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>>` is not implemented for `ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>`
       |
       = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
    
    error[E0277]: the trait bound `ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>: ArgminMul<_, ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>>` is not satisfied
      --> src\main.rs:36:30
       |
    36 |           .with_initial_params(vec![
       |  ______________________________^
    37 | |             // array![-2.0, 3.0],
    38 | |             // array![-2.0, -1.0],
    39 | |             // array![2.0, -1.0],
    ...  |
    42 | |             array![2.0, -1.0],
    43 | |         ])
       | |_________^ the trait `ArgminMul<_, ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>>` is not implemented for `ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>`
       |
       = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
    
    error[E0277]: the trait bound `ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>: ArgminAdd<ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>, ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>>` is not satisfied
      --> src\main.rs:35:18
       |
    35 |     let solver = NelderMead::new()
       |                  ^^^^^^^^^^^^^^^ the trait `ArgminAdd<ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>, ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>>` is not implemented for `ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>`   
       |
       = note: required by `NelderMead::<P, F>::new`
    
    error[E0277]: the trait bound `ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>: ArgminSub<ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>, ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>>` is not satisfied
      --> src\main.rs:35:18
       |
    35 |     let solver = NelderMead::new()
       |                  ^^^^^^^^^^^^^^^ the trait `ArgminSub<ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>, ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>>` is not implemented for `ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>`   
       |
       = note: required by `NelderMead::<P, F>::new`
    
    error[E0277]: the trait bound `ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>: ArgminMul<_, ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>>` is not satisfied
      --> src\main.rs:35:18
       |
    35 |     let solver = NelderMead::new()
       |                  ^^^^^^^^^^^^^^^ the trait `ArgminMul<_, ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>>` is not implemented for `ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>`
       |
       = note: required by `NelderMead::<P, F>::new`
    
    error[E0599]: the method `sd_tolerance` exists for struct `NelderMead<ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>, _>`, but its trait bounds were not satisfied
        --> src\main.rs:44:10
         |
    44   |           .sd_tolerance(0.0001);
         |            ^^^^^^^^^^^^ private field, not a method
         | 
        ::: C:\Users\Nobody\.cargo\registry\src\github.com-1ecc6299db9ec823\ndarray-0.15.1\src\lib.rs:1276:1
         |
    1276 | / pub struct ArrayBase<S, D>
    1277 | | where
    1278 | |     S: RawData,
    1279 | | {
    ...    |
    1289 | |     strides: D,
    1290 | | }
         | | -
         | | |
         | | doesn't satisfy `_: ArgminAdd<ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>, ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>>`
         | |_doesn't satisfy `_: ArgminMul<_, ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>>`
         |   doesn't satisfy `_: ArgminSub<ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>, ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>>`
         |
         = note: the following trait bounds were not satisfied:
                 `ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>: ArgminAdd<ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>, ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>>`
                 `ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>: ArgminSub<ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>, ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>>`
                 `ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>: ArgminMul<_, ArrayBase<OwnedRepr<{float}>, Dim<[usize; 1]>>>`
    

    Let me know if there is any further information I can provide.

    opened by HeavyMetalGeek 13
  • Condition violated:

    Condition violated: "MoreThuenteLineSearch: Search direction must be a descent direction." while using L-BFGS

    I'm sorry the example is quite big, but isolating a smaller section of the codebase for this is nontrivial.

    Steps to reproduce

    git clone https://github.com/yukarichess/yukari -b logistic-regression
    cd yukari
    xz -d quiescent_positions_with_results.xz
    cargo run --release --example tune
    

    What I expected to see

    e.g. if you uncomment the ArmijoCondition/BacktrackingLineSearch in yukari/src/tune.rs:

    Loading FENs...
    Found 1336010 positions
    0.41249916
    Jul 28 00:41:34.650 INFO L-BFGS, max_iters: 100
    0.41249916
    0.41249916
    0.41249916
    0.41249916
    0.41249916
    0.41249916
    0.41249916
    0.41249916
    0.41249916
    0.41249916
    0.41249916
    0.41249916
    0.41249916
    0.41249916
    0.41249916
    0.41249916
    Jul 28 00:41:47.101 INFO iter: 0, cost: 0.4124991579283057, best_cost: 0.4124991579283057, cost_func_count: 1, grad_func_count: 2, jacobian_func_count: 0, hessian_func_count: 0, modify_func_count: 0, gamma: 1.0, time: 12.4510831
    Jul 28 00:41:48.829 INFO iter: 1, cost: 0.4124991579283057, best_cost: 0.4124991579283057, cost_func_count: 1, grad_func_count: 3, jacobian_func_count: 0, hessian_func_count: 0, modify_func_count: 0, gamma: -16734916.191364305, time: 1.7277031
    ArgminResult:
        param (best): [snipped]
        cost (best):   0.4124991579283057
        iters (best):  1
        iters (total): 2
        termination: No change in cost function value
        time:        Some(16.8272069s)
    

    What I actually see

    Loading FENs...
    Found 1336010 positions
    0.41249916
    Jul 28 00:23:52.412 INFO L-BFGS, max_iters: 100
    0.41249916
    0.41249916
    0.41249916
    0.41249915
    0.41249914
    0.41249908
    0.41249884
    0.41249788
    0.41249421
    0.41248170
    0.41246661
    0.41296339
    0.41265837
    0.41254610
    0.41250183
    0.41248326
    0.41247498
    0.41247106
    0.41246910
    0.41246806
    0.41246748
    0.41246714
    0.41246694
    0.41246682
    0.41246674
    0.41246669
    0.41246666
    0.41246665
    0.41246663
    0.41246663
    0.41246662
    0.41246662
    0.41246662
    0.41246661
    0.41246661
    0.41246661
    0.41246661
    0.41246661
    0.41246661
    0.41246661
    0.41246661
    0.41246661
    0.41246661
    0.41246661
    0.41246661
    0.41246661
    0.41246661
    0.41246661
    0.41246661
    0.41246661
    0.41246661
    0.41246661
    0.41246661
    0.41246661
    0.41246661
    Jul 28 00:26:26.145 INFO iter: 0, cost: 0.41246661320768635, best_cost: 0.41246661320768635, cost_func_count: 1, grad_func_count: 2, jacobian_func_count: 0, hessian_func_count: 0, modify_func_count: 0, gamma: 1.0, time: 153.7329519
    thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Condition violated: "MoreThuenteLineSearch: Search direction must be a descent direction."', yukari/examples/tune.rs:39:17
    note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
    Aborted
    

    I think this means that L-BFGS is going in the wrong direction? I admit to being very new to logistic regression, but this definitely seems like a bug to me.

    opened by yukarichess 11
  • Issues with backtracking line search

    Issues with backtracking line search

    I noticed some points while playing around with LBFGS in combination with backtracking line search and would like to hear your thoughts before submitting a PR.

    • I think it would make sense if the optimizer (e.g. LBFGS in this case) accumulated the cost function, gradient etc. call counts into its own call counts because these are the numbers that are reported to an observer. Currently the reported numbers are misleading because the functions are actually called much more often depending on the line search.
    • Currently the backtracking line search evaluates its condition (in terminate) at iteration zero (i.e. directly after the call to init and before the first call to next_iter) without actually applying the search direction to the current state. This doesn't make any sense to me.
    • The alpha values in backtracking line search are actually "shifted" by one application of rho when passed into the condition. For example in the first iteration (iter == 1) it actually checks the condition with a cost and gradient evaluated at x + alpha * search_direction (where alpha == initial_alpha) but at the same time supplies the value alpha = initial_alpha * rho to the condition. This appears to be inconsistent.

    I'm not sure if these issues apply to other line searches as well. If you agree that these points should be addressed I can submit a PR.

    opened by w1th0utnam3 10
  • Feature Request: BFGS::into_inv_hessian

    Feature Request: BFGS::into_inv_hessian

    Hello, I would like to apply the BFGS method to a non convex problem where a greedy approach works well, requiring multiple phases with a gradually increasing dimension. To avoid resetting the learned inv_hessian matrix each time I would like to extract it from the BFGS solver, extend it to the required dimension so as to reuse learnt curvatures and improve performance in the next phase.

    A method that returns clone of the inv_hession would also work as the Solver trait already imposes this constraint. If you would like a PR I am happy to tackle this after some feedback on the clone vs de-structure options.

    Thanks

    opened by millardjn 8
  • Simulated Annealing: First mutation always gets accepted?

    Simulated Annealing: First mutation always gets accepted?

    Hello, I have encountered a scenario which I don't quite understand.

    I tried to set the initial temperature (in Simulated annealing) to the smallest possible positive number. (See first line of code-block) According to my current understanding, This should basically result in a greedy hill-climbing algorithm, where only better parameters are accepted.

    This isn't fully the case though. The first modification/mutation always seems to get accepted, even though it is way worse.

    Code containing the init_temp:

    let init_temp = f64::MIN_POSITIVE;
    
    let problem = AnnealingStruct {
        evaluator: Arc::new(evaluator.clone()),
        layout_generator: &pm,
    };
    
    // Create new SA solver with some parameters (see docs for details)
    // This essentially just prepares the SA solver. It is not run yet, nor does it know anything about the problem it is about to solve.
    let solver = SimulatedAnnealing::new(init_temp) // 200.0)
        .unwrap()
        // Optional: Define temperature function (defaults to `SATempFunc::TemperatureFast`)
        .temp_func(SATempFunc::Boltzmann)
        /////////////////////////
        // Stopping criteria   //
        /////////////////////////
        // Optional: stop if there was no accepted solution after 1000 iterations
        .stall_accepted(params.stall_accepted);
    
    // Create and run the executor, which will apply the solver to the problem, given a starting point (`init_param`)
    let res = Executor::new(problem, solver, init_layout)
        // Optional: Attach a observer
        .add_observer(ArgminSlogLogger::term(), ObserverMode::Always) //Every(100))
        // Optional: Set maximum number of iterations (defaults to `std::u64::MAX`)
        .max_iters(params.max_iters)
        // Optional: Set target cost function value (defaults to `std::f64::NEG_INFINITY`)
        .run()
        .unwrap();
    

    Log:

    Nov 28 16:53:58.373 INFO Simulated Annealing, max_iters: 10000, initial_temperature: 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022250738585072014, stall_iter_accepted_limit: 1000, stall_iter_best_limit: 18446744073709551615, reanneal_fixed: 18446744073709551615, reanneal_accepted: 18446744073709551615, reanneal_best: 18446744073709551615
    
    Nov 28 16:53:58.528 INFO iter: 0, cost: 269.73266205959345, best_cost: 269.73266205959345, cost_func_count: 1, grad_func_count: 0, jacobian_func_count: 0, hessian_func_count: 0, modify_func_count: 1, t: 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000032101030212800104, new_be: true, acc: true, st_i_be: 0, st_i_ac: 0, ra_i_fi: 1, ra_i_be: 0, ra_i_ac: 0, ra_fi: false, ra_be: false, ra_ac: false, time: 0.154631085
    Nov 28 16:53:58.677 INFO iter: 1, cost: 579.427167261033, best_cost: 269.73266205959345, cost_func_count: 2, grad_func_count: 0, jacobian_func_count: 0, hessian_func_count: 0, modify_func_count: 2, t: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002025349508155188, new_be: false, acc: true, st_i_be: 1, st_i_ac: 0, ra_i_fi: 2, ra_i_be: 1, ra_i_ac: 0, ra_fi: false, ra_be: false, ra_ac: false, time: 0.14926356300000002
    Nov 28 16:53:58.827 INFO iter: 2, cost: 579.427167261033, best_cost: 269.73266205959345, cost_func_count: 3, grad_func_count: 0, jacobian_func_count: 0, hessian_func_count: 0, modify_func_count: 3, t: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001605051510640005, new_be: false, acc: false, st_i_be: 2, st_i_ac: 1, ra_i_fi: 3, ra_i_be: 2, ra_i_ac: 1, ra_fi: false, ra_be: false, ra_ac: false, time: 0.150058625
    Nov 28 16:53:58.977 INFO iter: 3, cost: 576.9572329862979, best_cost: 269.73266205959345, cost_func_count: 4, grad_func_count: 0, jacobian_func_count: 0, hessian_func_count: 0, modify_func_count: 4, t: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001382516120265875, new_be: false, acc: true, st_i_be: 3, st_i_ac: 0, ra_i_fi: 4, ra_i_be: 3, ra_i_ac: 0, ra_fi: false, ra_be: false, ra_ac: false, time: 0.149817584
    .
    .
    .
    Nov 28 17:12:54.538 INFO iter: 7334, cost: 411.77879579661055, best_cost: 269.73266205959345, cost_func_count: 7335, grad_func_count: 0, jacobian_func_count: 0, hessian_func_count: 0, modify_func_count: 7335, t: 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002499928774082615, new_be: false, acc: false, st_i_be: 7334, st_i_ac: 5, ra_i_fi: 7335, ra_i_be: 7334, ra_i_ac: 5, ra_fi: false, ra_be: false, ra_ac: false, time: 0.157413196
    Nov 28 17:12:54.694 INFO iter: 7335, cost: 411.77879579661055, best_cost: 269.73266205959345, cost_func_count: 7336, grad_func_count: 0, jacobian_func_count: 0, hessian_func_count: 0, modify_func_count: 7336, t: 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002499890490262483, new_be: false, acc: false, st_i_be: 7335, st_i_ac: 6, ra_i_fi: 7336, ra_i_be: 7335, ra_i_ac: 6, ra_fi: false, ra_be: false, ra_ac: false, time: 0.15598256600000002
    Nov 28 17:12:54.851 INFO iter: 7336, cost: 411.77879579661055, best_cost: 269.73266205959345, cost_func_count: 7337, grad_func_count: 0, jacobian_func_count: 0, hessian_func_count: 0, modify_func_count: 7337, t: 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002499852212832205, new_be: false, acc: true, st_i_be: 7336, st_i_ac: 0, ra_i_fi: 7337, ra_i_be: 7336, ra_i_ac: 0, ra_fi: false, ra_be: false, ra_ac: false, time: 0.157277205
    Nov 28 17:12:55.007 INFO iter: 7337, cost: 411.77879579661055, best_cost: 269.73266205959345, cost_func_count: 7338, grad_func_count: 0, jacobian_func_count: 0, hessian_func_count: 0, modify_func_count: 7338, t: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000249981394178982, new_be: false, acc: false, st_i_be: 7337, st_i_ac: 1, ra_i_fi: 7338, ra_i_be: 7337, ra_i_ac: 1, ra_fi: false, ra_be: false, ra_ac: false, time: 0.15549885400000002
    
    
    opened by Glitchy-Tozier 8
  • Parallel evaluations of cost function

    Parallel evaluations of cost function

    Some optimization algorithms require several independent cost function evaluations per iteration. Sometimes (actually most of the times in my applications), evaluating the cost function can be costly, and its evaluations dominate the optimization time. When the cost function itself cannot be parallelized, an obvious improvement is to evaluate it at these points in parallel. It could also be desirable to evaluate the cost function and its gradient or hessian in parallel when applicable.

    rayon is the perfect library to allow this kind of things. Would it be okay to add it as a dependency? As a feature? Should we create an option to enable parallel evaluation on demand? We could probably even decide automatically whether it is worth to enable it or not, depending on the duration of the first few evaluations.

    opened by Armavica 8
  • Mention wasm-features in `Readme.md`

    Mention wasm-features in `Readme.md`

    When important features aren't mentioned, this can lead to some confusion

    Therefore, I suggest quickly mentioning them. :) This pull-request adds a mention about WebAssembly and the required features.


    Eventually, it would be handy to have every existing feature described in the Readme.md. Nothing extensive, just a short mention that the feature exists and an overview of what it does.

    opened by Glitchy-Tozier 7
  • Egui observer

    Egui observer

    A simple egui observer which shows the progress of the optimization in plots. Plots can selectively be shown or hidden. This is still very basic and will change substantially until it is ready for merging.

    Feedback is welcome!

    Todos

    • [ ] Turn this into separate crate
    • [ ] Turn all other observers also into dedicated crates. Advantage: The slog_logger feature is not needed anymore.
    • [ ] Think about how to extend the Observe trait.

    Caveats

    • Apparently GUIs need to run in the main thread, which is not possible in this case. I solved this by running the GUI in a separate process using the procspawn crate. Samples are then sent via ipc_channel which unfortunately doesn't work on Windows. Therefore Windows support is not possible until there is a reasonable way to communicate with the process that also works on Windows.
    • I haven't found a way to redraw the GUI only when new data comes in. Either it is redrawn as often as possible (with every call to update) or only when there is "GUI input" such as mouse movements. I'd like to redraw whenever there is new data on the channel.
    • This slows down the optimization substantially, which is probably fine and shouldn't be noticeable for cost functions that aren't super fast to compute. I guess such observers are used only during development/tuning and not "in production", where speed matters.

    Changes outside of the new observer

    • get_float of KVType also works for all other numeric types now by converting those to floats. 64bit integers are first cast to 32bit integers because only those can be converted to floats.
    opened by stefan-k 0
  • Turn examples into crates

    Turn examples into crates

    Currently users are occasionally confused about how to properly add argmin and argmin-math to their dependencies. While it is explained in the book, it is sometimes not the first thing they find. Instead they occasionally start from the examples and use internal features (such as _nalgebral) to make it work. By turning examples into their own crates, each example gets their own Cargo.toml and as such helps users to get started.

    Related issues and PRs: #306, #270, #268

    opened by stefan-k 0
  • `terminate` not called on `Ctrl+C`

    `terminate` not called on `Ctrl+C`

    I've successfully argminified my solver here (thanks again for your work).

    I've used the ability to interrupt the executor using Ctrl+C which indeed ends the current iteration but the terminate method does not seem to be called at the end. As terminate is documented as being called after each iteration somehow I was expecting it to be also called in this case to end gracefully.

    Looking at the executor code, I was wondering if a terminaison reason KeyboardInterrupt could be added to handle this specific case seperately from Aborted.

    Maybe a better option would be to add a final_terminate method called only once at the end of run (as a symetric of init) to allow whatever cleanup is needed. What do you think?

    opened by relf 6
  • Replace `assert!` macros with macros from approx crate

    Replace `assert!` macros with macros from approx crate

    Currently most assertions in the tests use the assert! macro, which is somewhat inconvenient for comparing floats. It would be great if those were replaced with the assert macros of the approx crate.

    good first issue 
    opened by stefan-k 0
  • Update ndarray-linalg requirement from 0.14 to 0.16

    Update ndarray-linalg requirement from 0.14 to 0.16

    Updates the requirements on ndarray-linalg to permit the latest version.

    Release notes

    Sourced from ndarray-linalg's releases.

    0.16.0

    What's Changed

    Breaking changes

    New features

    Bug fixes

    Changes

    Others

    Full Changelog: https://github.com/rust-ndarray/ndarray-linalg/compare/ndarray-linalg-v0.15.0...ndarray-linalg-v0.16.0

    Commits
    • 3e13736 (cargo-release) version 0.16.0
    • a1e63aa (cargo-release) version 0.16.0
    • 0bc1e71 (cargo-release) version 0.16.0-rc.0
    • f903228 (cargo-release) version 0.16.0-rc.0
    • 1539577 Merge pull request #349 from rust-ndarray/lax-tridiagonal
    • 4913818 Merge Tridiagonal_ into Lapack
    • d9c52a2 LuTridiagonalWork
    • 6a35654 RcondTridiagonalWork
    • a8550c2 SolveTridiagonalImpl
    • 17f9fb8 Split definition of tridiagonal matrix
    • Additional commits viewable in compare view

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies rust 
    opened by dependabot[bot] 1
  • [DRAFT] Powell's algorithm

    [DRAFT] Powell's algorithm

    Hi @stefan-k,

    I'm opening this PR to seek some guidance and feedback on my first draft to implement Powell's algorithm (#222).

    Currently, this code is completely untested as I am only trying to gauge whether my attempt on implementing this solver is going in the right direction.

    Here are some questions I have:

    1. Is my approach sensible at all? What can be improved?
    2. AFAIK, Powell's method can also be implemented using Golden-section search or Brent's method. Is there a way to do this generically in argmin or will there have to be different versions of solvers for each variant?
    3. I would appreciate some suggestions on a good test function to write some tests for this solver.

    Thanks!

    opened by Trombach 6
Releases(argmin-math-v0.2.1)
  • argmin-math-v0.2.1(Sep 9, 2022)

    What's Changed

    • Update version in book and make blog post active by @stefan-k in https://github.com/argmin-rs/argmin/pull/254
    • Implement missing math traits for nalgebra by @stefan-k in https://github.com/argmin-rs/argmin/pull/258
    • Release argmin-math v0.2.1 by @stefan-k in https://github.com/argmin-rs/argmin/pull/259

    Full Changelog: https://github.com/argmin-rs/argmin/compare/argmin-math-v0.2.0...argmin-math-v0.2.1

    Source code(tar.gz)
    Source code(zip)
  • argmin-v0.7.0(Aug 28, 2022)

    What's Changed

    • Use alias type names in examples by @vbkaisetsu in https://github.com/argmin-rs/argmin/pull/245
    • Fixed bug in Dogleg method by @stefan-k in https://github.com/argmin-rs/argmin/pull/247
    • Support OWL-QN method (L-BFGS with L1-regularization) by @vbkaisetsu in https://github.com/argmin-rs/argmin/pull/244
    • Fix π(x; y) in OWL-QN by @vbkaisetsu in https://github.com/argmin-rs/argmin/pull/248
    • Make ndarray-linalg dependency in argmin-math optional again by @stefan-k in https://github.com/argmin-rs/argmin/pull/249
    • Fix calculating pseudo-gradient in OWL-QN by @vbkaisetsu in https://github.com/argmin-rs/argmin/pull/250
    • Renamed ArgminNorm to ArgminL2Norm by @stefan-k in https://github.com/argmin-rs/argmin/pull/253
    • Release argmin v0.7.0 and argmin-math v0.2.0 by @stefan-k in https://github.com/argmin-rs/argmin/pull/252

    New Contributors

    • @vbkaisetsu made their first contribution in https://github.com/argmin-rs/argmin/pull/245

    Full Changelog: https://github.com/argmin-rs/argmin/compare/argmin-math-v0.1.0...argmin-v0.7.0

    Source code(tar.gz)
    Source code(zip)
  • argmin-math-v0.2.0(Aug 28, 2022)

    What's Changed

    • Use alias type names in examples by @vbkaisetsu in https://github.com/argmin-rs/argmin/pull/245
    • Fixed bug in Dogleg method by @stefan-k in https://github.com/argmin-rs/argmin/pull/247
    • Support OWL-QN method (L-BFGS with L1-regularization) by @vbkaisetsu in https://github.com/argmin-rs/argmin/pull/244
    • Fix π(x; y) in OWL-QN by @vbkaisetsu in https://github.com/argmin-rs/argmin/pull/248
    • Make ndarray-linalg dependency in argmin-math optional again by @stefan-k in https://github.com/argmin-rs/argmin/pull/249
    • Fix calculating pseudo-gradient in OWL-QN by @vbkaisetsu in https://github.com/argmin-rs/argmin/pull/250
    • Renamed ArgminNorm to ArgminL2Norm by @stefan-k in https://github.com/argmin-rs/argmin/pull/253
    • Release argmin v0.7.0 and argmin-math v0.2.0 by @stefan-k in https://github.com/argmin-rs/argmin/pull/252

    New Contributors

    • @vbkaisetsu made their first contribution in https://github.com/argmin-rs/argmin/pull/245

    Full Changelog: https://github.com/argmin-rs/argmin/compare/argmin-math-v0.1.0...argmin-math-v0.2.0

    Source code(tar.gz)
    Source code(zip)
  • argmin-v0.6.0(Aug 9, 2022)

    What's Changed

    • Fixed minor problems in CHANGELOG.md by @stefan-k in https://github.com/argmin-rs/argmin/pull/237
    • Renamed termination_reason method of State to terminate_with by @stefan-k in https://github.com/argmin-rs/argmin/pull/239
    • Add note about *latest* features in argmin-math docs by @stefan-k in https://github.com/argmin-rs/argmin/pull/240
    • Release argmin v0.6.0 and argmin-math v0.1.0 by @stefan-k in https://github.com/argmin-rs/argmin/pull/241

    Full Changelog: https://github.com/argmin-rs/argmin/compare/argmin-math-v0.1.0-rc.1...argmin-v0.6.0

    Source code(tar.gz)
    Source code(zip)
  • argmin-math-v0.1.0(Aug 9, 2022)

    What's Changed

    • Fixed minor problems in CHANGELOG.md by @stefan-k in https://github.com/argmin-rs/argmin/pull/237
    • Renamed termination_reason method of State to terminate_with by @stefan-k in https://github.com/argmin-rs/argmin/pull/239
    • Add note about *latest* features in argmin-math docs by @stefan-k in https://github.com/argmin-rs/argmin/pull/240
    • Release argmin v0.6.0 and argmin-math v0.1.0 by @stefan-k in https://github.com/argmin-rs/argmin/pull/241

    Full Changelog: https://github.com/argmin-rs/argmin/compare/argmin-math-v0.1.0-rc.1...argmin-math-v0.1.0

    Source code(tar.gz)
    Source code(zip)
  • argmin-v0.6.0-rc.2(Jul 31, 2022)

    Second release candidate for argmin v0.6.0. For details please consult CHANGELOG.md.

    What's Changed

    • Remove unused field in GoldenSectionSearch struct by @stefan-k in https://github.com/argmin-rs/argmin/pull/181
    • Make serde an optional dependency behind feature gate by @stefan-k in https://github.com/argmin-rs/argmin/pull/180
    • Refactoring: Moved math abstractions in new crate, updated documentation, readme and reduced dependencies, updated CI by @stefan-k in https://github.com/argmin-rs/argmin/pull/182
    • Fix #2 by @wfsteiner in https://github.com/argmin-rs/argmin/pull/184
    • Remove optional stdweb dependency (unmaintained) by @stefan-k in https://github.com/argmin-rs/argmin/pull/188
    • Update slog-term, slog-async, slog-json by @stefan-k in https://github.com/argmin-rs/argmin/pull/189
    • Remove ignored packages from dependabot config by @stefan-k in https://github.com/argmin-rs/argmin/pull/190
    • Smaller CI pipline and added cargo audit to CI by @stefan-k in https://github.com/argmin-rs/argmin/pull/191
    • Remove the Default trait bound on TrustRegion and Steihaug impls by @cfunky in https://github.com/argmin-rs/argmin/pull/192
    • Remove Default and other unnecessary trait bounds from solvers by @stefan-k in https://github.com/argmin-rs/argmin/pull/193
    • Make inverse Hessian part of IterState (fixes #185) by @stefan-k in https://github.com/argmin-rs/argmin/pull/186
    • Hessian in DFP and SR1 needs to implement Clone by @stefan-k in https://github.com/argmin-rs/argmin/pull/195
    • Make init_inv_hessian in DFP and SR1 optional to avoid cloning by @stefan-k in https://github.com/argmin-rs/argmin/pull/196
    • More efficient ways of retrieving data from IterState by @stefan-k in https://github.com/argmin-rs/argmin/pull/194
    • Large refactoring of operators, state, observers, checkpointing, documentation, ... by @stefan-k in https://github.com/argmin-rs/argmin/pull/198
    • Cleanup and documentation of State, IterState and LinearProgramState by @stefan-k in https://github.com/argmin-rs/argmin/pull/200
    • Cleanup and improve documentation of ConjugateGradient and NonlinearConjugateGradient by @stefan-k in https://github.com/argmin-rs/argmin/pull/202
    • Brent's optimization method by @Armavica in https://github.com/argmin-rs/argmin/pull/77
    • Cleanup and improve documentation of GaussNewton and GaussNewtonLS by @stefan-k in https://github.com/argmin-rs/argmin/pull/203
    • Rename all with_tol methods to with_tolerance by @stefan-k in https://github.com/argmin-rs/argmin/pull/204
    • Improved documentation of GoldenSectionSearch and added tests by @stefan-k in https://github.com/argmin-rs/argmin/pull/205
    • Improved documentation of SteepestDescent and added doc and unit tests by @stefan-k in https://github.com/argmin-rs/argmin/pull/206
    • argmin_error! and argmin_error_closure! macros for easier error creation by @stefan-k in https://github.com/argmin-rs/argmin/pull/207
    • Code of Conduct by @stefan-k in https://github.com/argmin-rs/argmin/pull/208
    • Cleanup and improve documentation of Landweber, added doc and unit tests by @stefan-k in https://github.com/argmin-rs/argmin/pull/209
    • Cleanup linesearch code by @stefan-k in https://github.com/argmin-rs/argmin/pull/210
    • Added float! macro for more convenient creation of float constants by @stefan-k in https://github.com/argmin-rs/argmin/pull/211
    • Cleanup of NelderMead, documentation and doc and unit tests by @stefan-k in https://github.com/argmin-rs/argmin/pull/212
    • Made ArgminError non_exhaustive by @stefan-k in https://github.com/argmin-rs/argmin/pull/213
    • Improved documentation of checkpointing by @stefan-k in https://github.com/argmin-rs/argmin/pull/214
    • Cleanup and documentation of Newton method. Added doc and unit tests by @stefan-k in https://github.com/argmin-rs/argmin/pull/215
    • Cleanup, documentation, doc and unit tests for PSO, introduce PopulationState by @stefan-k in https://github.com/argmin-rs/argmin/pull/216
    • Add support for nalgebra v0.31.0 by @stefan-k in https://github.com/argmin-rs/argmin/pull/218
    • Parallel/bulk evaluation of problem functions by @stefan-k in https://github.com/argmin-rs/argmin/pull/219
    • Cleanup of Quasi-Newton methods by @stefan-k in https://github.com/argmin-rs/argmin/pull/220
    • Cleanup and improve documentation of SimulatedAnnealing, added doc and unit tests by @stefan-k in https://github.com/argmin-rs/argmin/pull/224
    • Including argmin-math is now only necessary for choosing a backend by @stefan-k in https://github.com/argmin-rs/argmin/pull/228
    • Features ndarrayl and nalgebral are not to be used by users by @stefan-k in https://github.com/argmin-rs/argmin/pull/229
    • Cleanup and improve documentation of trust region method, added doc and unit tests by @stefan-k in https://github.com/argmin-rs/argmin/pull/226
    • Restructure and rewrite documentation and README by @stefan-k in https://github.com/argmin-rs/argmin/pull/230
    • Fix logo URL in Readme by @stefan-k in https://github.com/argmin-rs/argmin/pull/232
    • ignore website files for Languages graph in Github by @stefan-k in https://github.com/argmin-rs/argmin/pull/233
    • Fix link to main branch docs in README by @stefan-k in https://github.com/argmin-rs/argmin/pull/236
    • Release argmin v0.6.0-rc.2 and argmin-math v0.1.0-rc.1 by @stefan-k in https://github.com/argmin-rs/argmin/pull/235

    New Contributors

    • @wfsteiner made their first contribution in https://github.com/argmin-rs/argmin/pull/184
    • @cfunky made their first contribution in https://github.com/argmin-rs/argmin/pull/192
    • @Armavica made their first contribution in https://github.com/argmin-rs/argmin/pull/77

    Full Changelog: https://github.com/argmin-rs/argmin/compare/v0.5.0...argmin-v0.6.0-rc.2

    Source code(tar.gz)
    Source code(zip)
  • argmin-math-v0.1.0-rc.1(Jul 31, 2022)

    The math abstractions were split away from argmin and placed in a separate crate called argmin-math. It also includes implementations of these abstractions for basic Vecs, ndarray and nalgebra. The backends (and their version) can be chosen by the user using the available features.

    Source code(tar.gz)
    Source code(zip)
  • v0.5.1(Feb 16, 2022)

    What's Changed

    • Fixed Bug in HagerZhang line search (#2, #184, @wfsteiner)
    • Removed Default trait bounds on TrustRegion and Steihaug implementations (#187, #192, @cfunky)
    • Inverse Hessians are now part of IterState, therefore the final inverse Hessian can be retrieved after an optimization run (#185, #186, @stefan-k)

    Full Changelog: https://github.com/argmin-rs/argmin/compare/v0.5.0...v0.5.1

    Source code(tar.gz)
    Source code(zip)
  • v0.5.0(Jan 10, 2022)

    What's Changed

    • Make use of slog a feature by @ThatGeoGuy in https://github.com/argmin-rs/argmin/pull/136
    • allow any RNG, improve SA example by @TheIronBorn in https://github.com/argmin-rs/argmin/pull/139
    • Remove unnecessary semi-colon in macro by @CattleProdigy in https://github.com/argmin-rs/argmin/pull/143
    • Correct check for new best parameter by @stefan-k in https://github.com/argmin-rs/argmin/pull/152
    • [fix] simulated anneal always accepts first iter by @dariogoetz in https://github.com/argmin-rs/argmin/pull/153
    • Fix inconsistency between state and alpha value in Backtracking linesearch by @w1th0utnam3 in https://github.com/argmin-rs/argmin/pull/155
    • Fix counting of sub problem function counts by @stefan-k in https://github.com/argmin-rs/argmin/pull/156
    • Update LineSearchCondition trait to use references by @w1th0utnam3 in https://github.com/argmin-rs/argmin/pull/158
    • SA: use correct previous cost, new best needs to be strictly better by @stefan-k in https://github.com/argmin-rs/argmin/pull/159
    • Edition 2021 by @stefan-k in https://github.com/argmin-rs/argmin/pull/160
    • PSO: Corrected documentation, removed Hessian trait bounds by @stefan-k in https://github.com/argmin-rs/argmin/pull/161
    • Update best parameters when previous and current cost are Inf by @stefan-k in https://github.com/argmin-rs/argmin/pull/162
    • Tests for Newton method by @stefan-k in https://github.com/argmin-rs/argmin/pull/163
    • Tests for GaussNewton method and fixed GaussNewton example by @stefan-k in https://github.com/argmin-rs/argmin/pull/164
    • Tests for linesearch conditions by @stefan-k in https://github.com/argmin-rs/argmin/pull/165
    • Remove unsafe code from vec math module by @stefan-k in https://github.com/argmin-rs/argmin/pull/166
    • Tests for backtracking linesearch by @stefan-k in https://github.com/argmin-rs/argmin/pull/168
    • Mention wasm-features in Readme.md by @Glitchy-Tozier in https://github.com/argmin-rs/argmin/pull/167
    • Update nalgebra requirement from 0.29.0 to 0.30.0 by @dependabot in https://github.com/argmin-rs/argmin/pull/169
    • WASM builds in CI by @stefan-k in https://github.com/argmin-rs/argmin/pull/170
    • Indicate required features for each example in Cargo.toml by @stefan-k in https://github.com/argmin-rs/argmin/pull/171
    • Fixed documentation warnings and added doc build to CI by @stefan-k in https://github.com/argmin-rs/argmin/pull/173
    • Remove links to examples in docs by @stefan-k in https://github.com/argmin-rs/argmin/pull/174
    • Automatically deploy docs when pushing to main by @stefan-k in https://github.com/argmin-rs/argmin/pull/176
    • Remove CircleCI and add rustfmt pipeline to Github Actions by @stefan-k in https://github.com/argmin-rs/argmin/pull/178
    • Faster CI by removing unnecessary cargo clean by @stefan-k in https://github.com/argmin-rs/argmin/pull/179
    • Version 0.5.0 by @stefan-k in https://github.com/argmin-rs/argmin/pull/172

    New Contributors

    • @ThatGeoGuy made their first contribution in https://github.com/argmin-rs/argmin/pull/136
    • @TheIronBorn made their first contribution in https://github.com/argmin-rs/argmin/pull/139
    • @dariogoetz made their first contribution in https://github.com/argmin-rs/argmin/pull/153
    • @Glitchy-Tozier made their first contribution in https://github.com/argmin-rs/argmin/pull/167

    Full Changelog: https://github.com/argmin-rs/argmin/compare/v0.4.7...v0.5.0

    Source code(tar.gz)
    Source code(zip)
  • v0.4.7(Jan 6, 2022)

    What's Changed

    • github actions and updated changelog by @stefan-k in https://github.com/argmin-rs/argmin/pull/130
    • Update readme by @stefan-k in https://github.com/argmin-rs/argmin/pull/131
    • Update nalgebra requirement from 0.28.0 to 0.29.0 by @dependabot in https://github.com/argmin-rs/argmin/pull/133
    • version 0.4.7 by @stefan-k in https://github.com/argmin-rs/argmin/pull/134

    Full Changelog: https://github.com/argmin-rs/argmin/compare/v0.4.6...v0.4.7

    Source code(tar.gz)
    Source code(zip)
  • v0.4.6(Jan 6, 2022)

    • updated dependencies (#121, #123, #129, @stefan-k):
      • ndarray 0.15
      • ndarray-linalg 0.14
      • appox 0.5
      • nalgebra 0.28
      • ndarray-rand 0.14
      • num-complex 0.4
      • finitediff 0.1.4

    What's Changed

    • Update approx requirement from 0.4.0 to 0.5.0 by @dependabot in https://github.com/argmin-rs/argmin/pull/121
    • update ndarray, ndarray-linalg, nalgebra, ndarray-rand, num-complex by @stefan-k in https://github.com/argmin-rs/argmin/pull/129

    Full Changelog: https://github.com/argmin-rs/argmin/compare/v0.4.5...v0.4.6

    Source code(tar.gz)
    Source code(zip)
  • v0.4.5(Jan 6, 2022)

  • v0.4.4(Jan 6, 2022)

    What's Changed

    • Performance Enhancements by @sdd in https://github.com/argmin-rs/argmin/pull/112
    • version 0.4.4 by @stefan-k in https://github.com/argmin-rs/argmin/pull/113

    New Contributors

    • @sdd made their first contribution in https://github.com/argmin-rs/argmin/pull/112

    Full Changelog: https://github.com/argmin-rs/argmin/compare/v0.4.3...v0.4.4

    Source code(tar.gz)
    Source code(zip)
  • v0.4.3(Jan 6, 2022)

    What's Changed

    • downgrade ndarray-rand to 0.13 (to match ndarray 0.14), version bump by @stefan-k in https://github.com/argmin-rs/argmin/pull/109

    Full Changelog: https://github.com/argmin-rs/argmin/compare/v0.4.2...v0.4.3

    Source code(tar.gz)
    Source code(zip)
  • v0.4.2(Jan 6, 2022)

    What's Changed

    • Update nalgebra requirement from 0.24.1 to 0.25.0 by @dependabot-preview in https://github.com/argmin-rs/argmin/pull/98
    • Update num requirement from 0.3 to 0.4 by @dependabot-preview in https://github.com/argmin-rs/argmin/pull/100
    • Fix lazy evaluation of gradients in line searches by @w1th0utnam3 in https://github.com/argmin-rs/argmin/pull/101
    • Update ndarray-rand requirement from 0.13.0 to 0.14.0 by @dependabot-preview in https://github.com/argmin-rs/argmin/pull/103
    • Fixed error when using recent nightly compiler by @stefan-k in https://github.com/argmin-rs/argmin/pull/106
    • Update nalgebra requirement from 0.25.0 to 0.26.1 by @dependabot-preview in https://github.com/argmin-rs/argmin/pull/105
    • Version bump 0.4.2 by @stefan-k in https://github.com/argmin-rs/argmin/pull/107

    Full Changelog: https://github.com/argmin-rs/argmin/compare/v0.4.1...v0.4.2

    Source code(tar.gz)
    Source code(zip)
  • v0.4.1(Jan 6, 2022)

    What's Changed

    • bump to version 0.4.0 by @stefan-k in https://github.com/argmin-rs/argmin/pull/97

    Full Changelog: https://github.com/argmin-rs/argmin/compare/v0.4.0...v0.4.1

    Source code(tar.gz)
    Source code(zip)
  • v0.4.0(Jan 6, 2022)

    What's Changed

    • Update gnuplot requirement from 0.0.36 to 0.0.37 by @dependabot-preview in https://github.com/argmin-rs/argmin/pull/64
    • Update num requirement from 0.2 to 0.3 by @dependabot-preview in https://github.com/argmin-rs/argmin/pull/66
    • Update paste requirement from 0.1.5 to 1.0.0 by @dependabot-preview in https://github.com/argmin-rs/argmin/pull/67
    • Add nalgebra support by @Maher4Ever in https://github.com/argmin-rs/argmin/pull/68
    • Update nalgebra requirement from 0.21.1 to 0.22.0 by @dependabot-preview in https://github.com/argmin-rs/argmin/pull/70
    • remove unecessary Default bound on NelderMead by @vadixidav in https://github.com/argmin-rs/argmin/pull/73
    • Update approx requirement from 0.3.2 to 0.4.0 by @dependabot-preview in https://github.com/argmin-rs/argmin/pull/74
    • Update ndarray-rand requirement from 0.11.0 to 0.12.0 by @dependabot-preview in https://github.com/argmin-rs/argmin/pull/79
    • Update ndarray-rand requirement from 0.12.0 to 0.13.0 by @dependabot-preview in https://github.com/argmin-rs/argmin/pull/84
    • Replace std::time with instant to work in wasm environment by @stefan-k in https://github.com/argmin-rs/argmin/pull/88
    • Updated dependendies by @stefan-k in https://github.com/argmin-rs/argmin/pull/96

    New Contributors

    • @Maher4Ever made their first contribution in https://github.com/argmin-rs/argmin/pull/68
    • @vadixidav made their first contribution in https://github.com/argmin-rs/argmin/pull/73

    Full Changelog: https://github.com/argmin-rs/argmin/compare/v0.3.1...v0.4.0

    Source code(tar.gz)
    Source code(zip)
  • v0.3.1(Jan 6, 2022)

    What's Changed

    • MoreThuente: Added error check for NaN or Inf by @MattBurn in https://github.com/argmin-rs/argmin/pull/57
    • Update gnuplot requirement from 0.0.34 to 0.0.35 by @dependabot-preview in https://github.com/argmin-rs/argmin/pull/58
    • Update gnuplot requirement from 0.0.35 to 0.0.36 by @dependabot-preview in https://github.com/argmin-rs/argmin/pull/59
    • remove finitediff from ndarrayl feature by @optozorax in https://github.com/argmin-rs/argmin/pull/61
    • bump to version 0.3.1 by @stefan-k in https://github.com/argmin-rs/argmin/pull/62

    New Contributors

    • @optozorax made their first contribution in https://github.com/argmin-rs/argmin/pull/61

    Full Changelog: https://github.com/argmin-rs/argmin/compare/v0.3.0...v0.3.1

    Source code(tar.gz)
    Source code(zip)
  • v0.3.0(Jan 6, 2022)

    What's Changed

    • Update gnuplot requirement from 0.0.32 to 0.0.33 by @dependabot-preview in https://github.com/argmin-rs/argmin/pull/23
    • Update gnuplot requirement from 0.0.33 to 0.0.34 by @dependabot-preview in https://github.com/argmin-rs/argmin/pull/24
    • Remove work-in-progress from README by @stefan-k in https://github.com/argmin-rs/argmin/pull/27
    • Moved argmin_core crate into core module by @stefan-k in https://github.com/argmin-rs/argmin/pull/30
    • Removed Send and Sync trait bounds from ArgminOp by @stefan-k in https://github.com/argmin-rs/argmin/pull/33
    • No reexport of modcholesky crate by @stefan-k in https://github.com/argmin-rs/argmin/pull/35
    • Removed need for unwrap in cstep MoreThuente LineSearch by @MattBurn in https://github.com/argmin-rs/argmin/pull/38
    • Exposed stopping criterion tolerances to user by @stefan-k in https://github.com/argmin-rs/argmin/pull/37
    • Exposed stopping criterion tolerances of Gauss Newton methods to user by @stefan-k in https://github.com/argmin-rs/argmin/pull/39
    • Exposed stopping criterion tolerance of NewtonCG method to user by @stefan-k in https://github.com/argmin-rs/argmin/pull/40
    • Exposed stopping criterion tolerances of Quasi-Newton methods to user by @stefan-k in https://github.com/argmin-rs/argmin/pull/43
    • Moved from failure to anyhow and thiserror by @stefan-k in https://github.com/argmin-rs/argmin/pull/44
    • Made op and state fields of ArgminResult more accessible by @stefan-k in https://github.com/argmin-rs/argmin/pull/45
    • No reexport of argmin_testfunctions by @stefan-k in https://github.com/argmin-rs/argmin/pull/46
    • Remove Serialize trait bound on ArgminOp by @stefan-k in https://github.com/argmin-rs/argmin/pull/36
    • Remove Clone trait bound from ArgminOp by @stefan-k in https://github.com/argmin-rs/argmin/pull/48
    • Generic floats by @stefan-k in https://github.com/argmin-rs/argmin/pull/50
    • Golden-section search by @nilgoyette in https://github.com/argmin-rs/argmin/pull/49
    • Added Golden-section search to documentation by @stefan-k in https://github.com/argmin-rs/argmin/pull/53
    • Added Golden-section search also to Readme by @stefan-k in https://github.com/argmin-rs/argmin/pull/54
    • Fixed macro documentation in IterState by @stefan-k in https://github.com/argmin-rs/argmin/pull/55
    • Release 0.3.0 by @stefan-k in https://github.com/argmin-rs/argmin/pull/56

    New Contributors

    • @nilgoyette made their first contribution in https://github.com/argmin-rs/argmin/pull/49

    Full Changelog: https://github.com/argmin-rs/argmin/compare/v0.2.6...v0.3.0

    Source code(tar.gz)
    Source code(zip)
  • v0.2.6(Jan 6, 2022)

    What's Changed

    • Brent's method by @xemwebe in https://github.com/argmin-rs/argmin/pull/22

    New Contributors

    • @xemwebe made their first contribution in https://github.com/argmin-rs/argmin/pull/22

    Full Changelog: https://github.com/argmin-rs/argmin/compare/v0.2.5...v0.2.6

    Source code(tar.gz)
    Source code(zip)
  • v0.2.5(Jan 6, 2022)

    What's Changed

    • MAINT Lint with CircleCI by @rth in https://github.com/argmin-rs/argmin/pull/11
    • Add unit tests to check convergence on the Max Entropy problem by @rth in https://github.com/argmin-rs/argmin/pull/13
    • Derive Clone trait for all optimizers by @rth in https://github.com/argmin-rs/argmin/pull/14
    • Update gnuplot requirement from 0.0.27 to 0.0.32 by @dependabot-preview in https://github.com/argmin-rs/argmin/pull/19
    • Update ndarray-linalg requirement from 0.10.0 to 0.11.1 by @dependabot-preview in https://github.com/argmin-rs/argmin/pull/15

    New Contributors

    • @rth made their first contribution in https://github.com/argmin-rs/argmin/pull/11

    Full Changelog: https://github.com/argmin-rs/argmin/compare/v0.2.4...v0.2.5

    Source code(tar.gz)
    Source code(zip)
  • v0.2.4(Jan 6, 2022)

Owner
argmin
Mathematical optimization in pure Rust
argmin
BLAS bindings for Rust

RBLAS Rust bindings and wrappers for BLAS (Basic Linear Algebra Subprograms). Overview RBLAS wraps each external call in a trait with the same name (b

Michael Yang 77 Oct 8, 2022
gmp bindings for rust

Documentation The following functions are intentionally left out of the bindings: gmp_randinit (not thread-safe, obsolete) mpz_random (not thread-safe

Bartłomiej Kamiński 37 Nov 5, 2022
Rust wrapper for ArrayFire

Arrayfire Rust Bindings ArrayFire is a high performance library for parallel computing with an easy-to-use API. It enables users to write scientific c

ArrayFire 696 Dec 30, 2022
Scientific Computing Library in Rust

SciRust Scientific computing library written in Rust programming language. The objective is to design a generic library which can be used as a backbon

In Digits 242 Dec 16, 2022
Statistical computation library for Rust

statrs Current Version: v0.13.0 Should work for both nightly and stable Rust. NOTE: While I will try to maintain backwards compatibility as much as po

Michael Ma 384 Dec 27, 2022
The write-once-run-anywhere GPGPU library for Rust

The old version of Emu (which used macros) is here. Overview Emu is a GPGPU library for Rust with a focus on portability, modularity, and performance.

Caleb Winston 1.5k Dec 30, 2022
a cheat-sheet for mathematical notation in Rust 🦀 code form

math-as-rust ?? Based on math-as-code This is a reference to ease developers into mathematical notation by showing comparisons with Rust code.

Eduardo Pereira 13 Jan 4, 2023
Determine the Unicode class of a mathematical character in Rust.

unicode-math-class Determine the Unicode class of a mathematical character in Rust. Example use unicode_math_class::{class, MathClass}; assert_eq!(cl

Typst 3 Jan 10, 2023
A pure, low-level tensor program representation enabling tensor program optimization via program rewriting

Glenside is a pure, low-level tensor program representation which enables tensor program optimization via program rewriting, using rewriting frameworks such as the egg equality saturation library.

Gus Smith 45 Dec 28, 2022
A simple interpreter for the mathematical random-access machine

Random-access machine runner A simple Rust RAM program runner. Lexer/Parser Program executor Code formatter Web Compiled to WASM to run in the browser

Marcin Wojnarowski 5 Jan 14, 2023
Rust implementation of real-coded GA for solving optimization problems and training of neural networks

revonet Rust implementation of real-coded genetic algorithm for solving optimization problems and training of neural networks. The latter is also know

Yury Tsoy 19 Aug 11, 2022
Collection of Optimization algorithm in Rust

rustimization A rust optimization library which includes L-BFGS-B and Conjugate Gradient algorithm. Documentation The simplest way to use these optimi

Naushad Karim 47 Sep 23, 2022
Rust implementation of real-coded GA for solving optimization problems and training of neural networks

revonet Rust implementation of real-coded genetic algorithm for solving optimization problems and training of neural networks. The latter is also know

Yury Tsoy 19 Aug 11, 2022
Image optimization using Rust and Vips 🦀

Huffman Image optimization using Rust and Libvips. Requirements You must have the following packages installed before getting started Rust Vips pkg-co

ChronicleHQ 4 Nov 3, 2022
Salty and Sweet one-line Rust Runtime Optimization Library

SAS SAS (Salty-And-Sweet) is an one-line Rust runtime optimization library. Features NUMA-aware rayon: numa feature should be enabled If you have 1 NU

UlagBulag 3 Feb 21, 2024
Linearly Constrained Separable Optimization

LCSO (Linearly Constrained Separable Optimization) Authors The original algorithms here were developed by Nicholas Moehle, and this project was author

BlackRock 28 Oct 1, 2022
TP - Optimization of the energy consumption of a Matrix Multiplication

Optimization de la consommation: Multiplication de matrices Nous allons travailler sur la multiplication de matrices denses. C’est un algorithme class

Bynawers 0 Mar 11, 2022
OptFrame is an optimization framework focused in metaheuristic techniques

optframe-rust Welcome to OptFrame project in Rust. What is OptFrame? OptFrame is an optimization framework focused in metaheuristic techniques, develo

OptFrame 4 Jan 30, 2022
A standalone Aleo prover build upon snarkOS and snarkVM, with multi-threading optimization

Aleo Light Prover Introduction A standalone Aleo prover build upon snarkOS and snarkVM, with multi-threading optimization. It's called "light" because

Haruka Ma 91 Dec 29, 2022
A neural network model that can approximate any non-linear function by using the random search algorithm for the optimization of the loss function.

random_search A neural network model that can approximate any non-linear function by using the random search algorithm for the optimization of the los

ph04 2 Apr 1, 2022