relmath-rs 0.7.0

Relation-first mathematics and scientific computing in Rust.
Documentation
//! Schema-aware n-ary relations for simple curriculum records.

use std::collections::BTreeMap;

use relmath::NaryRelation;

fn main() -> Result<(), relmath::NaryRelationError> {
    let progress = NaryRelation::from_named_rows(
        ["student", "course", "status"],
        [
            BTreeMap::from([
                ("course", "Math"),
                ("status", "passed"),
                ("student", "Alice"),
            ]),
            BTreeMap::from([
                ("course", "Physics"),
                ("status", "passed"),
                ("student", "Alice"),
            ]),
            BTreeMap::from([("course", "Math"), ("status", "passed"), ("student", "Bob")]),
            BTreeMap::from([
                ("course", "Physics"),
                ("status", "in_progress"),
                ("student", "Bob"),
            ]),
            BTreeMap::from([
                ("course", "Math"),
                ("status", "passed"),
                ("student", "Cara"),
            ]),
        ],
    )?;
    let course_rooms = NaryRelation::from_named_rows(
        ["course", "room"],
        [
            BTreeMap::from([("course", "Math"), ("room", "R101")]),
            BTreeMap::from([("course", "Physics"), ("room", "R201")]),
            BTreeMap::from([("course", "History"), ("room", "R301")]),
        ],
    )?;

    let completed = progress
        .select(|row| row[2] == "passed")
        .project(["student", "course"])?;
    let scheduled = completed.natural_join(&course_rooms);
    let by_room = scheduled.group_by(["room"])?;
    let room_r101 = by_room.group(&["R101"]).expect("expected R101 group");
    let room_assignments = scheduled.project(["room", "student"])?;
    let exported_assignments = room_assignments.to_named_rows();

    assert!(completed.contains_row(&["Alice", "Math"]));
    assert_eq!(
        scheduled.schema(),
        &[
            "student".to_string(),
            "course".to_string(),
            "room".to_string(),
        ]
    );
    assert_eq!(
        scheduled.to_rows(),
        vec![
            vec!["Alice", "Math", "R101"],
            vec!["Alice", "Physics", "R201"],
            vec!["Bob", "Math", "R101"],
            vec!["Cara", "Math", "R101"],
        ]
    );
    assert_eq!(by_room.key_schema(), &["room".to_string()]);
    assert_eq!(by_room.member_schema(), scheduled.schema());
    assert_eq!(by_room.counts(), vec![(vec!["R101"], 3), (vec!["R201"], 1)]);
    assert_eq!(
        room_r101.to_rows(),
        vec![
            vec!["Alice", "Math", "R101"],
            vec!["Bob", "Math", "R101"],
            vec!["Cara", "Math", "R101"],
        ]
    );
    assert_eq!(
        room_assignments.to_rows(),
        vec![
            vec!["R101", "Alice"],
            vec!["R101", "Bob"],
            vec!["R101", "Cara"],
            vec!["R201", "Alice"],
        ]
    );
    assert_eq!(
        exported_assignments[0],
        BTreeMap::from([
            ("room".to_string(), "R101"),
            ("student".to_string(), "Alice"),
        ])
    );

    println!("scheduled course completions: {:?}", scheduled.to_rows());

    Ok(())
}