runmat-vm 0.5.2

RunMat virtual machine and bytecode interpreter
Documentation
#[path = "support/mod.rs"]
mod test_helpers;

use runmat_builtins::Value;
use test_helpers::execute_source;

#[test]
fn linprog_solves_bounded_program_from_source() {
    let vars = execute_source(
        "f = [-1; -2]; A = [1 1]; b = 4; [x, fval, exitflag] = linprog(f, A, b, [], [], [0; 0], []); y = x(2);",
    )
    .unwrap();
    assert!(vars.iter().any(|value| {
        matches!(value, Value::Tensor(t) if t.shape == vec![2, 1] && (t.data[0] - 0.0).abs() < 1.0e-7 && (t.data[1] - 4.0).abs() < 1.0e-7)
    }));
    assert!(vars
        .iter()
        .any(|value| matches!(value, Value::Num(n) if (*n + 8.0).abs() < 1.0e-7)));
    assert!(vars
        .iter()
        .any(|value| matches!(value, Value::Num(n) if (*n - 1.0).abs() < 1.0e-7)));
    assert!(vars
        .iter()
        .any(|value| matches!(value, Value::Num(n) if (*n - 4.0).abs() < 1.0e-7)));
}

#[test]
fn linprog_solves_equality_and_bounds_from_source() {
    let vars = execute_source(
        "f = [1; 2]; A = []; b = []; Aeq = [1 1]; beq = 3; [x, fval] = linprog(f, A, b, Aeq, beq, [1; 0], []);",
    )
    .unwrap();
    assert!(vars.iter().any(|value| {
        matches!(value, Value::Tensor(t) if t.shape == vec![2, 1] && (t.data[0] - 3.0).abs() < 1.0e-7 && t.data[1].abs() < 1.0e-7)
    }));
    assert!(vars
        .iter()
        .any(|value| matches!(value, Value::Num(n) if (*n - 3.0).abs() < 1.0e-7)));
}

#[test]
fn linprog_solves_sparse_one_sided_bound_from_source() {
    let vars = execute_source(
        "f = [1; 0]; [x, fval, exitflag] = linprog(f, [], [], [], [], [2; -Inf], []); y = x(1);",
    )
    .unwrap();
    assert!(vars.iter().any(|value| {
        matches!(value, Value::Tensor(t) if t.shape == vec![2, 1] && (t.data[0] - 2.0).abs() < 1.0e-7 && t.data[1].abs() < 1.0e-7)
    }));
    assert!(vars
        .iter()
        .any(|value| matches!(value, Value::Num(n) if (*n - 2.0).abs() < 1.0e-7)));
    assert!(vars
        .iter()
        .any(|value| matches!(value, Value::Num(n) if (*n - 1.0).abs() < 1.0e-7)));
}

#[test]
fn linprog_optimizes_along_equality_face_from_source() {
    let vars = execute_source(
        "f = [-1; 0; 0]; A = [1 0 0]; b = 1; Aeq = [0 0 1]; beq = 0; [x, fval, exitflag] = linprog(f, A, b, Aeq, beq, [], []); y = x(1);",
    )
    .unwrap();
    assert!(vars.iter().any(|value| {
        matches!(value, Value::Tensor(t) if t.shape == vec![3, 1] && (t.data[0] - 1.0).abs() < 1.0e-7 && t.data[1].abs() < 1.0e-7 && t.data[2].abs() < 1.0e-7)
    }));
    assert!(vars
        .iter()
        .any(|value| matches!(value, Value::Num(n) if (*n + 1.0).abs() < 1.0e-7)));
    assert!(vars
        .iter()
        .any(|value| matches!(value, Value::Num(n) if (*n - 1.0).abs() < 1.0e-7)));
}

#[test]
fn linprog_reports_infeasible_status_from_source() {
    let vars =
        execute_source("[x, fval, exitflag, output] = linprog(1, [], [], [], [], 2, 1);").unwrap();
    assert!(vars
        .iter()
        .any(|value| matches!(value, Value::Tensor(t) if t.shape == vec![0, 0])));
    assert!(vars
        .iter()
        .any(|value| matches!(value, Value::Num(n) if (*n + 2.0).abs() < 1.0e-7)));
    assert!(vars
        .iter()
        .any(|value| matches!(value, Value::Struct(s) if s.fields.contains_key("message"))));
}