sciforge 0.0.3

A comprehensive scientific computing library in pure Rust with zero dependencies
Documentation
use sciforge::hub::prelude::*;

fn run_maths(name: &str, params: Vec<(&str, ParameterValue)>) -> RunOutput {
    let mut exp = Experiment::new(DomainType::Maths, name);
    for (k, v) in params {
        exp = exp.param(k, v);
    }
    ExperimentRunner::new()
        .run(&exp)
        .unwrap_or_else(|_| panic!("dispatch '{name}' failed"))
}

fn scalar(o: RunOutput) -> f64 {
    match o {
        RunOutput::Scalar(v) => v,
        _ => panic!("expected Scalar, got {o:?}"),
    }
}

#[test]
fn quadratic_objective() {
    let v = scalar(run_maths(
        "quadratic_objective",
        vec![
            (
                "h",
                ParameterValue::Matrix(vec![vec![2.0, 0.0], vec![0.0, 2.0]]),
            ),
            ("c", ParameterValue::Vector(vec![0.0, 0.0])),
            ("x", ParameterValue::Vector(vec![0.0, 0.0])),
        ],
    ));
    assert!(v.abs() < 1e-8, "f([0,0])=0 at minimum, got {v}");
}

#[test]
fn project_box() {
    let o = run_maths(
        "project_box",
        vec![
            ("x", ParameterValue::Vector(vec![5.0])),
            ("lower", ParameterValue::Vector(vec![0.0])),
            ("upper", ParameterValue::Vector(vec![3.0])),
        ],
    );
    match o {
        RunOutput::Vector(v) => assert!(
            (v[0] - 3.0).abs() < 1e-8,
            "project(5, [0,3])=3, got {}",
            v[0]
        ),
        other => panic!("expected Vector, got {other:?}"),
    }
}

#[test]
fn lagrangian() {
    let v = scalar(run_maths(
        "lagrangian",
        vec![
            ("f", ParameterValue::Scalar(10.0)),
            ("constraints", ParameterValue::Vector(vec![2.0])),
            ("lambdas", ParameterValue::Vector(vec![3.0])),
        ],
    ));
    assert!((v - 16.0).abs() < 1e-8, "L=f+lambda*g=10+3*2=16, got {v}");
}