peroxide 0.11.5

Rust numeric library contains linear algebra, numerical analysis, statistics and machine learning tools with R, MATLAB, Python like macros
Documentation
# Peroxide

[![On crates.io](https://img.shields.io/crates/v/peroxide.svg)](https://crates.io/crates/peroxide)
[![On docs.rs](https://docs.rs/peroxide/badge.svg)](https://docs.rs/peroxide/)
![maintenance](https://img.shields.io/badge/maintenance-actively--developed-brightgreen.svg)

Pure Rust numeric library contains linear algebra, numerical analysis, statistics and machine learning tools with R, MATLAB, Python like macros.

## Latest README version

Corresponding to `0.11.2`.

## Pre-requisite

* Python module : `matplotlib` for plotting

## Install

* Add next line to your `cargo.toml`
```toml
peroxide = "0.11"
```

## Module Structure

- __src__
  - [lib.rs]src/lib.rs : `mod` and `re-export`
  - __macros__ : Macro files
    - [matlab_macro.rs]src/macros/matlab_macro.rs : MATLAB like macro
    - [mod.rs]src/macros/mod.rs
    - [r_macro.rs]src/macros/r_macro.rs : R like macro
  - __ml__ : For machine learning (*Beta*)
      - [mod.rs]src/ml/mod.rs
      - [reg.rs]src/ml/reg.rs : Regression tools
  - __numerical__ : To do numerical things
    - [bdf.rs]src/numerical/bdf.rs : Backward Differentiation Formula
    - [gauss_legendre.rs]src/numerical/gauss_legendre.rs : Gauss-Legendre 4th order
    - [interp.rs]src/numerical/interp.rs : Interpolation
    - [mod.rs]src/numerical/mod.rs
    - [newton.rs]src/numerical/newton.rs : Newton's Method
    - [ode.rs]src/grave/ode.rs : Merge all ODE algorithm to one module
    - [spline.rs]src/numerical/spline.rs : Natural Spline
    - [utils.rs]src/numerical/utils.rs : Utils to do numerical things (e.g. jacobian)
  - __operation__ : To define general operations
    - [extra_ops.rs]src/operation/extra_ops.rs : Missing operations & Real Trait
    - [mut_ops.rs]src/operation/mut_ops.rs : Mutable operations
    - [mod.rs]src/operation/mod.rs
  - __special__ : Wrapper for `special` crate
    - [mod.rs]src/special/mod.rs
    - [function.rs]src/special/function.rs : Special functions
  - __statistics__ : Statistical Tools
    - [mod.rs]src/statistics/mod.rs
    - [dist.rs]src/statistics/dist.rs : Probability distributions
    - [ops.rs]src/statistics/ops.rs : Some probabilistic operations
    - [rand.rs]src/statistics/rand.rs : Wrapper for `rand` crate
    - [stat.rs]src/statistics/stat.rs : Statistical tools
  - __structure__ : Fundamental data structures
    - [dataframe.rs]src/structure/dataframe.rs : Not yet implemented
    - [dual.rs]src/structure/dual.rs : Dual number system for automatic differentiation
    - [hyper_dual.rs]src/structure/hyper_dual.rs : Hyper dual number system for automatic differentiation
    - [matrix.rs]src/structure/matrix.rs : Matrix
    - [multinomial.rs]src/structure/multinomial.rs : For multinomial (*Beta*)
    - [mod.rs]src/structure/mod.rs
    - [polynomial.rs]src/structure/polynomial.rs : Polynomial
    - [vector.rs]src/structure/vector.rs : Extra tools for `Vec<f64>`
  - __util__
    - [mod.rs]src/util/mod.rs
    - [api.rs]src/util/api.rs : Matrix constructor for various language style 
    - [non_macro.rs]src/util/non_macro.rs : Primordial version of macros
    - [pickle.rs]src/util/pickle.rs : To handle `pickle` data structure
    - [plot.rs]src/util/plot.rs : To draw plot (using `pyo3`)
    - [print.rs]src/util/print.rs : To print conveniently
    - [useful.rs]src/util/useful.rs : Useful utils to implement library
    - [writer.rs]src/util/writer.rs : More convenient write system


## Documentation

* Modifying...

    [![On docs.rs]https://docs.rs/peroxide/badge.svg]https://docs.rs/peroxide/

## Example

### Basic Runge-Kutta 4th order with inline-python

```rust
#![feature(proc_macro_hygiene)]
extern crate peroxide;
extern crate inline_python;
use peroxide::*;
use inline_python::python;

fn main() {
    // Initial condition
    let init_state = State::<f64>::new(0f64, c!(1), c!(0));

    let mut ode_solver = ExplicitODE::new(test_fn);

    ode_solver
        .set_method(ExMethod::RK4)
        .set_initial_condition(init_state)
        .set_step_size(0.01)
        .set_times(1000);

    let result = ode_solver.integrate();

    let x = result.col(0);
    let y = result.col(1);

    // Plot (Thanks to inline-python)
    python! {
        import pylab as plt
        plt.plot('x, 'y)
        plt.show()
    }
}

// dy/dx = (5x^2 - y) / e^(x+y)
fn test_fn(st: &mut State<f64>) {
    let x = st.param;
    let y = &st.value;
    let dy = &mut st.deriv;
    dy[0] = (5f64 * x.powi(2) - y[0]) / (x + y[0]).exp();
}
```

### Basic Runge-Kutta 4th order with advanced plotting

```rust
extern crate peroxide;
use peroxide::*;

fn main() {
    let init_state = State::<f64>::new(0f64, c!(1), c!(0));

    let mut ode_solver = ExplicitODE::new(test_fn);

    ode_solver
        .set_method(ExMethod::RK4)
        .set_initial_condition(init_state)
        .set_step_size(0.01)
        .set_times(1000);

    let result = ode_solver.integrate();

    let x = result.col(0);
    let y = result.col(1);

    // Plot (using python matplotlib)
    let mut plt = Plot2D::new();
    plt.set_domain(x)
        .insert_image(y)
        .set_title("Test Figure")
        .set_fig_size((10, 6))
        .set_dpi(300)
        .set_legends(vec!["RK4".to_owned()])
        .set_path("example_data/test_plot.png");

    plt.savefig();
}

fn test_fn(st: &mut State<f64>) {
    let x = st.param;
    let y = &st.value;
    let dy = &mut st.deriv;
    dy[0] = (5f64 * x.powi(2) - y[0]) / (x + y[0]).exp();
}
```

### Basic Runge-Kutta 4th order with Stop condition

```rust
extern crate peroxide;
use peroxide::*;

fn main() {
    let init_state = State::<f64>::new(0f64, c!(1), c!(0));

    let mut ode_solver = ExplicitODE::new(test_fn);

    ode_solver
        .set_method(ExMethod::RK4)
        .set_initial_condition(init_state)
        .set_step_size(0.01)
        .set_stop_condition(stop)        // Add stop condition
        .set_times(1000);

    let result = ode_solver.integrate();

    let x = result.col(0);
    let y = result.col(1);

    let mut plt = Plot2D::new();
    plt.set_domain(x)
        .insert_image(y)
        .set_title("Test Figure")
        .set_fig_size((10, 6))
        .set_dpi(300)
        .set_legends(vec!["RK4".to_owned()])
        .set_path("example_data/test_plot.png");

    plt.savefig();
}

fn test_fn(st: &mut State<f64>) {
    let x = st.param;
    let y = &st.value;
    let dy = &mut st.deriv;
    dy[0] = (5f64 * x.powi(2) - y[0]) / (x + y[0]).exp();
}

fn stop(st: &ExplicitODE) -> bool {
    let y = &st.get_state().value[0];
    (*y - 2.4).abs() < 0.01
}
```

![Example image](example_data/test_plot.png)

### Multi-Layer Perceptron (from scratch)

```rust
extern crate peroxide;
use peroxide::*;

// x : n x L
// xb: n x (L+1)
// v : (L+1) x M
// a : n x M
// ab: n x (M+1)
// w : (M+1) x n
// wb: M x N
// y : n x N
// t : n x N
// dh: n x M
// do: n x N

fn main() {
    let v = weights_init(3, 2);
    let w = weights_init(3, 1);

    let x = ml_matrix("0 0; 0 1; 1 0; 1 1");
    let t = ml_matrix("0;1;1;0");

    let y = train(v, w, x, t, 0.25, 5000);
    y.print();
}

fn weights_init(m: usize, n: usize) -> Matrix {
    rand(m, n) * 2f64 - 1f64
}

fn sigmoid(x: f64) -> f64 {
    1f64 / (1f64 + (-x).exp())
}

fn forward(weights: Matrix, input_bias: Matrix) -> Matrix {
    let s = input_bias * weights;
    s.fmap(|x| sigmoid(x))
}

fn add_bias(input: Matrix, bias: f64) -> Matrix {
    let b = matrix(vec![bias; input.row], input.row, 1, Col);
    cbind(b, input)
}

fn hide_bias(weight: Matrix) -> Matrix {
    weight.skip(1, Row)
}

fn train(
    weights1: Matrix,
    weights2: Matrix,
    input: Matrix,
    answer: Matrix,
    eta: f64,
    times: usize,
) -> Matrix {
    let x = input;
    let mut v = weights1;
    let mut w = weights2;
    let t = answer;
    let xb = add_bias(x.clone(), -1f64);

    for _i in 0..times {
        let a = forward(v.clone(), xb.clone());
        let ab = add_bias(a.clone(), -1f64);
        let y = forward(w.clone(), ab.clone());
        //        let err = (y.clone() - t.clone()).t() * (y.clone() - t.clone());
        let wb = hide_bias(w.clone());
        let delta_o = (y.clone() - t.clone()) * y.clone() * (1f64 - y.clone());
        let delta_h = (delta_o.clone() * wb.t()) * a.clone() * (1f64 - a.clone());

        w = w.clone() - eta * (ab.t() * delta_o);
        v = v.clone() - eta * (xb.t() * delta_h);
    }

    let a = forward(v, xb);
    let ab = add_bias(a, -1f64);
    let y = forward(w, ab);

    y
}
```

## Version Info

To see [RELEASES.md](./RELEASES.md)

## TODO

To see [TODO.md](./TODO.md)