5 releases (3 breaking)

new 0.4.0 May 30, 2023
0.3.0 May 24, 2023
0.2.0 May 22, 2023
0.1.1 May 19, 2023
0.1.0 May 13, 2023

#54 in Visualization

Download history 17/week @ 2023-05-07 28/week @ 2023-05-14 53/week @ 2023-05-21

98 downloads per month

GPL-3.0-or-later

50KB
1K SLoC

Usage

Histogram

let mut hist = Histogram::new(0.0, 1.0, 10); // from, to, number of buckets
let data = vec![0.0, 0.1, 0.2, 3.0];
hist.add_all(&data);
hist.save_img("plot.png", "Plot Name", "X axis", "Y Axis");

MonteCarlo

let mc = MonteCarlo::default();
let vec: Vec<f64> = mc.sample_iter(1_000).collect(); // iter of vector of 1_000 f64
let vec: Vec<(f64, f64, f64)> = mc.sample_iter(1_000).collect(); // iter of vector of 1_000 (f64, f64, f64)

Custom Randomizable

fn something() {
    let mc = MonteCarlo::default();
    let vec: Vec<PolarCoord> = mc.sample_iter(1_000).collect();
}

struct PolarCoord {
    r: f64,
    theta: f64,
}

impl PolarCoord {
    pub fn new(r: f64, theta: f64) -> Self {
        let theta = theta % (2.0 * PI);
        PolarCoord { r, theta }
    }
}

impl Randomizable for PolarCoord {
    fn sample<D: Distribution<f64>, R: Rng + ?Sized>(distr: &D, rng: &mut R) -> Self {
        Self::new(distr.sample(rng), distr.sample(rng) * 2.0 * PI)
    }
}

MarkovChain-like

First define a type of state, it can be any struct.

struct TwoParticleState {
    // this crate has a particle struct, but you can use anything.
    particle1: Particle,
    particle2: Particle,
}

If you want, you can define a constraint.

// it will make particles not go bellow y = 0.0
struct CustomConstraint {}
impl Constraint for CustomConstraint {
    type State = TwoParticleState;
    fn constrain(&self, state: &mut Self::State) {
        if state.particle1.pos.y < 0.0 {
            state.particle1.pos.y = 0.0;
        }
        if state.particle2.pos.y < 0.0 {
            state.particle2.pos.y = 0.0;
        }
    }
}

Then, define an evolutioner, an evolutioner is a trait that evolves one system's state to an other state.

For example, gravity.

struct Gravity {
    dt: f64, 
    constraint: CustomConstraint,
}

impl Evolver for Gravity {
    type State = TwoParticleState;
    fn evol(&self, state: &mut Self::State) {
        // update accelerations
        state.particle1.acc = Cartesian2D::new(0.0, -9.8);
        state.particle2.acc = Cartesian2D::new(0.0, -9.8);
        // apply verlet
        state.particle1.update(self.dt);
        state.particle2.update(self.dt);
        // apply constraint
        self.constraint.constrain(state);
    }
}

Last, use all things and add it to the system. Use System::evol for evol the system.

fn main() {
    let constr = CustomConstraint{};
    let particle1 = Particle::with_defaults(2.0, 10.0);
    let particle2 = Particle::with_defaults(0.0, 5.0);
    let state = TwoParticleState{ particle1, particle2 };
    let evolver = Gravity{ constraint: constr, dt: 0.01 };
    let mut system = System::new(evolver, state);
    system.evol();
    for _ in 0..100 {
        system.evol();
    }
}

Dependencies

~1.6–3.5MB
~66K SLoC