relmath-rs 0.7.0

Relation-first mathematics and scientific computing in Rust.
Documentation
//! Integration tests for the first explicit G6 capability boundaries.

use relmath::{
    BinaryRelation, ExactSupport, FiniteRelation, NaryRelation, NaryRelationError, RelationView,
    ToExactBinaryRelation, ToExactNaryRelation, ToExactUnaryRelation, UnaryRelation,
    annotated::{AnnotatedRelation, BooleanSemiring},
    provenance::ProvenanceRelation,
    temporal::{Interval, ValidTimeRelation},
};

fn exact_pairs<R>(relation: &R) -> BinaryRelation<&'static str, &'static str>
where
    R: ExactSupport<(&'static str, &'static str)>
        + ToExactBinaryRelation<&'static str, &'static str>,
{
    relation.to_binary_relation()
}

fn exact_values<R>(relation: &R) -> UnaryRelation<&'static str>
where
    R: ExactSupport<&'static str> + ToExactUnaryRelation<&'static str>,
{
    relation.to_unary_relation()
}

fn exact_rows<R>(relation: &R) -> Result<NaryRelation<&'static str>, NaryRelationError>
where
    R: ToExactNaryRelation<&'static str>,
{
    relation.to_nary_relation(["student", "course", "status"])
}

#[test]
fn exact_support_materialization_lines_up_across_add_on_binary_surfaces() {
    let evidence = ProvenanceRelation::from_facts([
        (("alice", "review"), "directory"),
        (("bob", "approve"), "policy"),
        (("alice", "review"), "directory"),
    ]);
    let permissions = AnnotatedRelation::from_facts([
        (("alice", "review"), BooleanSemiring::TRUE),
        (("bob", "approve"), BooleanSemiring::TRUE),
        (("carol", "audit"), BooleanSemiring::FALSE),
    ]);
    let schedule = ValidTimeRelation::from_facts([
        (
            ("alice", "review"),
            Interval::new(1, 3).expect("expected valid interval"),
        ),
        (
            ("alice", "review"),
            Interval::new(3, 5).expect("expected valid interval"),
        ),
        (
            ("bob", "approve"),
            Interval::new(2, 4).expect("expected valid interval"),
        ),
    ]);

    let expected = vec![("alice", "review"), ("bob", "approve")];

    assert_eq!(evidence.exact_support().to_vec(), expected);
    assert_eq!(permissions.exact_support().to_vec(), expected);
    assert_eq!(schedule.exact_support().to_vec(), expected);

    assert_eq!(exact_pairs(&evidence).to_vec(), expected);
    assert_eq!(exact_pairs(&permissions).to_vec(), expected);
    assert_eq!(exact_pairs(&schedule).to_vec(), expected);
}

#[test]
fn capability_terms_stay_distinct_while_exact_support_agrees() {
    let evidence = ProvenanceRelation::from_facts([
        (("alice", "review"), "directory"),
        (("alice", "review"), "audit_log"),
    ]);
    let permissions = AnnotatedRelation::from_facts([(("alice", "review"), BooleanSemiring::TRUE)]);
    let schedule = ValidTimeRelation::from_facts([(
        ("alice", "review"),
        Interval::new(1, 4).expect("expected valid interval"),
    )]);

    assert_eq!(
        evidence
            .why(&("alice", "review"))
            .expect("expected witness")
            .to_vec(),
        vec!["audit_log", "directory"]
    );
    assert_eq!(
        permissions.annotation_of(&("alice", "review")),
        Some(&BooleanSemiring::TRUE)
    );
    assert_eq!(
        schedule
            .valid_time_of(&("alice", "review"))
            .expect("expected interval support")
            .to_vec(),
        vec![Interval::new(1, 4).expect("expected valid interval")]
    );

    let expected = vec![("alice", "review")];
    assert_eq!(evidence.exact_support().to_vec(), expected);
    assert_eq!(permissions.exact_support().to_vec(), expected);
    assert_eq!(schedule.exact_support().to_vec(), expected);
}

#[test]
fn generic_unary_and_nary_materialization_reuse_current_exact_rules() {
    let concepts = AnnotatedRelation::from_facts([
        ("Closure", BooleanSemiring::TRUE),
        ("Relations", BooleanSemiring::TRUE),
    ]);
    assert_eq!(
        exact_values(&concepts).to_vec(),
        vec!["Closure", "Relations"]
    );

    let rows = ProvenanceRelation::from_facts([
        (vec!["Alice", "Math", "passed"], "gradebook"),
        (vec!["Bob", "Physics", "passed"], "gradebook"),
    ]);

    assert_eq!(
        exact_rows(&rows).expect("expected valid exact rows"),
        NaryRelation::from_rows(
            ["student", "course", "status"],
            [["Alice", "Math", "passed"], ["Bob", "Physics", "passed"]],
        )
        .expect("expected valid exact relation")
    );
    assert_eq!(
        rows.to_nary_relation(["student", "student", "status"])
            .expect_err("expected duplicate column error"),
        NaryRelationError::DuplicateColumn {
            column: "student".to_string(),
        }
    );
}

#[test]
fn exact_support_of_empty_surfaces_stays_empty() -> Result<(), NaryRelationError> {
    let evidence = ProvenanceRelation::<(&str, &str), &str>::new();
    let permissions = AnnotatedRelation::<(&str, &str), BooleanSemiring>::new();
    let schedule = ValidTimeRelation::<(&str, &str), i32>::new();
    let empty_rows = ProvenanceRelation::<Vec<&str>, &str>::new();

    assert!(evidence.exact_support().is_empty());
    assert!(permissions.exact_support().is_empty());
    assert!(schedule.exact_support().is_empty());

    assert_eq!(
        evidence.to_binary_relation().to_vec(),
        Vec::<(&str, &str)>::new()
    );
    assert_eq!(
        permissions.to_binary_relation().to_vec(),
        Vec::<(&str, &str)>::new()
    );
    assert_eq!(
        schedule.to_binary_relation().to_vec(),
        Vec::<(&str, &str)>::new()
    );

    assert_eq!(
        empty_rows.to_nary_relation(["student", "course"])?,
        NaryRelation::new(["student", "course"])?
    );

    Ok(())
}

#[test]
fn exact_support_materialization_feeds_relation_view_workflow() {
    let schedule = ValidTimeRelation::from_facts([
        (
            ("bob", "approve"),
            Interval::new(2, 4).expect("expected valid interval"),
        ),
        (
            ("alice", "review"),
            Interval::new(1, 3).expect("expected valid interval"),
        ),
    ]);

    let exact = schedule.to_binary_relation();

    assert_eq!(exact.len(), 2);
    assert_eq!(
        exact.tuples().copied().collect::<Vec<_>>(),
        vec![("alice", "review"), ("bob", "approve")]
    );
}