Skip to main content

BinaryRelation

Struct BinaryRelation 

Source
pub struct BinaryRelation<A: Ord, B: Ord> { /* private fields */ }
Expand description

Finite binary relation type. A finite binary relation.

The starter implementation stores pairs in a BTreeSet so iteration order is deterministic.

Composition direction is:

r.compose(&s) = { (a, c) | exists b. (a, b) in r and (b, c) in s }

§Examples

use relmath::{BinaryRelation, UnaryRelation};

let user_role = BinaryRelation::from_pairs([
    ("ann", "admin"),
    ("bob", "reviewer"),
]);

let extra_role = BinaryRelation::from_pairs([
    ("bob", "reviewer"),
    ("cara", "guest"),
]);

let role_permission = BinaryRelation::from_pairs([
    ("admin", "read"),
    ("reviewer", "approve"),
    ("guest", "view"),
]);

assert_eq!(
    user_role.union(&extra_role).to_vec(),
    vec![("ann", "admin"), ("bob", "reviewer"), ("cara", "guest")]
);
assert_eq!(
    user_role.intersection(&extra_role).to_vec(),
    vec![("bob", "reviewer")]
);
assert_eq!(user_role.difference(&extra_role).to_vec(), vec![("ann", "admin")]);
assert_eq!(
    user_role.converse().to_vec(),
    vec![("admin", "ann"), ("reviewer", "bob")]
);

let effective_permission = user_role.union(&extra_role).compose(&role_permission);
assert!(effective_permission.contains(&"ann", &"read"));
assert_eq!(
    effective_permission.iter().copied().collect::<Vec<_>>(),
    vec![("ann", "read"), ("bob", "approve"), ("cara", "view")]
);
assert_eq!(
    effective_permission.domain().to_vec(),
    vec!["ann", "bob", "cara"]
);
assert_eq!(
    effective_permission.range().to_vec(),
    vec!["approve", "read", "view"]
);
assert_eq!(
    effective_permission
        .restrict_domain(&UnaryRelation::from_values(["ann", "cara"]))
        .to_vec(),
    vec![("ann", "read"), ("cara", "view")]
);
assert_eq!(
    effective_permission
        .restrict_range(&UnaryRelation::from_values(["read", "view"]))
        .to_vec(),
    vec![("ann", "read"), ("cara", "view")]
);
assert_eq!(
    effective_permission.image(&UnaryRelation::singleton("bob")).to_vec(),
    vec!["approve"]
);
assert_eq!(
    effective_permission
        .preimage(&UnaryRelation::from_values(["read", "view"]))
        .to_vec(),
    vec!["ann", "cara"]
);

Implementations§

Source§

impl<A: Ord, B: Ord> BinaryRelation<A, B>

Source

pub fn new() -> Self

Creates an empty binary relation.

Source

pub fn from_pairs<I>(pairs: I) -> Self
where I: IntoIterator<Item = (A, B)>,

Creates a binary relation from the provided pairs.

Examples found in repository?
examples/workflow.rs (lines 6-10)
5fn main() {
6    let step = BinaryRelation::from_pairs([
7        ("Draft", "Review"),
8        ("Review", "Approved"),
9        ("Review", "Rejected"),
10    ]);
11
12    let states =
13        UnaryRelation::from_values(["Draft", "Review", "Approved", "Rejected", "Archived"]);
14    let reachable = step.reflexive_transitive_closure(&states);
15    let draft = UnaryRelation::singleton("Draft");
16
17    assert!(reachable.contains(&"Archived", &"Archived"));
18    assert!(reachable.contains(&"Draft", &"Approved"));
19
20    println!(
21        "reachable from Draft: {:?}",
22        reachable.image(&draft).to_vec()
23    );
24}
More examples
Hide additional examples
examples/family.rs (lines 6-12)
5fn main() {
6    let parent = BinaryRelation::from_pairs([
7        ("Ada", "Bob"),
8        ("Ada", "Cara"),
9        ("Bob", "Dana"),
10        ("Cara", "Eli"),
11        ("Dana", "Finn"),
12    ]);
13
14    let people = UnaryRelation::from_values(["Ada", "Bob", "Cara", "Dana", "Eli", "Finn"]);
15    let grandparent = parent.compose(&parent);
16    let ancestor = parent.reflexive_transitive_closure(&people);
17
18    let ada = UnaryRelation::singleton("Ada");
19    let reachable_from_ada = ancestor.image(&ada);
20
21    assert!(grandparent.contains(&"Ada", &"Dana"));
22    assert!(grandparent.contains(&"Ada", &"Eli"));
23    assert!(reachable_from_ada.contains(&"Finn"));
24
25    println!("grandparent pairs: {:?}", grandparent.to_vec());
26    println!(
27        "people reachable from Ada: {:?}",
28        reachable_from_ada.to_vec()
29    );
30}
examples/access_control.rs (lines 6-11)
5fn main() {
6    let user_role = BinaryRelation::from_pairs([
7        ("ann", "admin"),
8        ("bob", "analyst"),
9        ("bob", "reviewer"),
10        ("cara", "guest"),
11    ]);
12
13    let role_permission = BinaryRelation::from_pairs([
14        ("admin", "read"),
15        ("admin", "write"),
16        ("admin", "deploy"),
17        ("analyst", "read"),
18        ("reviewer", "approve"),
19        ("guest", "read"),
20    ]);
21
22    let effective_permission = user_role.compose(&role_permission);
23    let bob = UnaryRelation::singleton("bob");
24    let bob_permissions = effective_permission.image(&bob);
25
26    assert!(effective_permission.contains(&"ann", &"deploy"));
27    assert!(bob_permissions.contains(&"approve"));
28    assert!(bob_permissions.contains(&"read"));
29
30    println!(
31        "effective permissions for bob: {:?}",
32        bob_permissions.to_vec()
33    );
34}
examples/relation_view.rs (line 11)
9fn main() -> Result<(), relmath::NaryRelationError> {
10    let people = UnaryRelation::from_values(["Ada", "Bob"]);
11    let parent = BinaryRelation::from_pairs([("Ada", "Bob"), ("Bob", "Cara")]);
12    let enrollments =
13        NaryRelation::from_rows(["student", "course"], [["Ada", "Math"], ["Bob", "Physics"]])?;
14
15    assert_eq!(tuple_count(&people), 2);
16    assert_eq!(tuple_count(&parent), 2);
17    assert_eq!(tuple_count(&enrollments), 2);
18
19    assert_eq!(
20        people.tuples().copied().collect::<Vec<_>>(),
21        vec!["Ada", "Bob"]
22    );
23    assert_eq!(
24        parent.tuples().copied().collect::<Vec<_>>(),
25        vec![("Ada", "Bob"), ("Bob", "Cara")]
26    );
27    assert_eq!(
28        enrollments
29            .tuples()
30            .map(|row| row.to_vec())
31            .collect::<Vec<_>>(),
32        vec![vec!["Ada", "Math"], vec!["Bob", "Physics"]]
33    );
34
35    println!("people: {:?}", people.tuples().copied().collect::<Vec<_>>());
36    println!("parent: {:?}", parent.tuples().copied().collect::<Vec<_>>());
37    println!(
38        "enrollments: {:?}",
39        enrollments
40            .tuples()
41            .map(|row| row.to_vec())
42            .collect::<Vec<_>>()
43    );
44
45    Ok(())
46}
examples/provenance.rs (lines 12-15)
5fn main() {
6    let gene_disease = ProvenanceRelation::from_facts([
7        (("BRCA1", "BreastCancer"), "curated_panel"),
8        (("BRCA1", "BreastCancer"), "paper_12"),
9        (("TP53", "BreastCancer"), "paper_77"),
10    ]);
11
12    let disease_drug = relmath::BinaryRelation::from_pairs([
13        ("BreastCancer", "Olaparib"),
14        ("BreastCancer", "Tamoxifen"),
15    ]);
16
17    let supported_gene_disease = gene_disease.to_binary_relation();
18    let gene_drug = supported_gene_disease.compose(&disease_drug);
19    let brca1 = UnaryRelation::singleton("BRCA1");
20    let brca1_witness = gene_disease
21        .why(&("BRCA1", "BreastCancer"))
22        .expect("expected explanation");
23
24    assert_eq!(
25        gene_drug.image(&brca1).to_vec(),
26        vec!["Olaparib", "Tamoxifen"]
27    );
28    assert_eq!(brca1_witness.to_vec(), vec!["curated_panel", "paper_12"]);
29    assert!(brca1_witness.contains_token(&"paper_12"));
30    assert_eq!(
31        gene_disease
32            .provenance_of(&("BRCA1", "BreastCancer"))
33            .expect("expected explanation")
34            .to_vec(),
35        brca1_witness.to_vec()
36    );
37    assert_eq!(
38        gene_disease.support().to_vec(),
39        vec![("BRCA1", "BreastCancer"), ("TP53", "BreastCancer")]
40    );
41    assert!(gene_disease.why(&("BRCA1", "Olaparib")).is_none());
42
43    println!(
44        "why BRCA1 links to BreastCancer in the base evidence: {:?}",
45        brca1_witness.to_vec()
46    );
47}
examples/carrier.rs (line 6)
5fn main() {
6    let step = BinaryRelation::from_pairs([("Draft", "Review")]);
7    let states = FiniteCarrier::from_values(["Draft", "Review", "Archived"]);
8
9    let inferred = step.carrier();
10    let inferred_identity = BinaryRelation::identity(&inferred);
11    let explicit_identity = BinaryRelation::identity_on(&states);
12    let reachable = step.reflexive_transitive_closure_on(&states);
13
14    assert_eq!(inferred.to_vec(), vec!["Draft", "Review"]);
15    assert_eq!(
16        inferred_identity.to_vec(),
17        vec![("Draft", "Draft"), ("Review", "Review")]
18    );
19    assert_eq!(
20        explicit_identity.to_vec(),
21        vec![
22            ("Archived", "Archived"),
23            ("Draft", "Draft"),
24            ("Review", "Review"),
25        ]
26    );
27    assert_eq!(states.to_vec(), vec!["Archived", "Draft", "Review"]);
28    assert_eq!(
29        reachable.to_vec(),
30        step.reflexive_transitive_closure(&states.to_unary_relation())
31            .to_vec()
32    );
33    assert!(reachable.is_reflexive_on(&states));
34    assert!(step.is_irreflexive_on(&states));
35    assert!(reachable.contains(&"Archived", &"Archived"));
36    assert!(reachable.contains(&"Draft", &"Review"));
37
38    println!(
39        "explicit carrier: {:?}; inferred support: {:?}; inferred identity: {:?}; explicit identity: {:?}; reachable: {:?}",
40        states.to_vec(),
41        inferred.to_vec(),
42        inferred_identity.to_vec(),
43        explicit_identity.to_vec(),
44        reachable.to_vec()
45    );
46}
Source

pub fn insert(&mut self, left: A, right: B) -> bool

Inserts a pair into the relation.

Returns true when the pair was not already present.

Source

pub fn contains(&self, left: &A, right: &B) -> bool

Returns true when the relation contains the given pair.

Examples found in repository?
examples/workflow.rs (line 17)
5fn main() {
6    let step = BinaryRelation::from_pairs([
7        ("Draft", "Review"),
8        ("Review", "Approved"),
9        ("Review", "Rejected"),
10    ]);
11
12    let states =
13        UnaryRelation::from_values(["Draft", "Review", "Approved", "Rejected", "Archived"]);
14    let reachable = step.reflexive_transitive_closure(&states);
15    let draft = UnaryRelation::singleton("Draft");
16
17    assert!(reachable.contains(&"Archived", &"Archived"));
18    assert!(reachable.contains(&"Draft", &"Approved"));
19
20    println!(
21        "reachable from Draft: {:?}",
22        reachable.image(&draft).to_vec()
23    );
24}
More examples
Hide additional examples
examples/family.rs (line 21)
5fn main() {
6    let parent = BinaryRelation::from_pairs([
7        ("Ada", "Bob"),
8        ("Ada", "Cara"),
9        ("Bob", "Dana"),
10        ("Cara", "Eli"),
11        ("Dana", "Finn"),
12    ]);
13
14    let people = UnaryRelation::from_values(["Ada", "Bob", "Cara", "Dana", "Eli", "Finn"]);
15    let grandparent = parent.compose(&parent);
16    let ancestor = parent.reflexive_transitive_closure(&people);
17
18    let ada = UnaryRelation::singleton("Ada");
19    let reachable_from_ada = ancestor.image(&ada);
20
21    assert!(grandparent.contains(&"Ada", &"Dana"));
22    assert!(grandparent.contains(&"Ada", &"Eli"));
23    assert!(reachable_from_ada.contains(&"Finn"));
24
25    println!("grandparent pairs: {:?}", grandparent.to_vec());
26    println!(
27        "people reachable from Ada: {:?}",
28        reachable_from_ada.to_vec()
29    );
30}
examples/access_control.rs (line 26)
5fn main() {
6    let user_role = BinaryRelation::from_pairs([
7        ("ann", "admin"),
8        ("bob", "analyst"),
9        ("bob", "reviewer"),
10        ("cara", "guest"),
11    ]);
12
13    let role_permission = BinaryRelation::from_pairs([
14        ("admin", "read"),
15        ("admin", "write"),
16        ("admin", "deploy"),
17        ("analyst", "read"),
18        ("reviewer", "approve"),
19        ("guest", "read"),
20    ]);
21
22    let effective_permission = user_role.compose(&role_permission);
23    let bob = UnaryRelation::singleton("bob");
24    let bob_permissions = effective_permission.image(&bob);
25
26    assert!(effective_permission.contains(&"ann", &"deploy"));
27    assert!(bob_permissions.contains(&"approve"));
28    assert!(bob_permissions.contains(&"read"));
29
30    println!(
31        "effective permissions for bob: {:?}",
32        bob_permissions.to_vec()
33    );
34}
examples/carrier.rs (line 35)
5fn main() {
6    let step = BinaryRelation::from_pairs([("Draft", "Review")]);
7    let states = FiniteCarrier::from_values(["Draft", "Review", "Archived"]);
8
9    let inferred = step.carrier();
10    let inferred_identity = BinaryRelation::identity(&inferred);
11    let explicit_identity = BinaryRelation::identity_on(&states);
12    let reachable = step.reflexive_transitive_closure_on(&states);
13
14    assert_eq!(inferred.to_vec(), vec!["Draft", "Review"]);
15    assert_eq!(
16        inferred_identity.to_vec(),
17        vec![("Draft", "Draft"), ("Review", "Review")]
18    );
19    assert_eq!(
20        explicit_identity.to_vec(),
21        vec![
22            ("Archived", "Archived"),
23            ("Draft", "Draft"),
24            ("Review", "Review"),
25        ]
26    );
27    assert_eq!(states.to_vec(), vec!["Archived", "Draft", "Review"]);
28    assert_eq!(
29        reachable.to_vec(),
30        step.reflexive_transitive_closure(&states.to_unary_relation())
31            .to_vec()
32    );
33    assert!(reachable.is_reflexive_on(&states));
34    assert!(step.is_irreflexive_on(&states));
35    assert!(reachable.contains(&"Archived", &"Archived"));
36    assert!(reachable.contains(&"Draft", &"Review"));
37
38    println!(
39        "explicit carrier: {:?}; inferred support: {:?}; inferred identity: {:?}; explicit identity: {:?}; reachable: {:?}",
40        states.to_vec(),
41        inferred.to_vec(),
42        inferred_identity.to_vec(),
43        explicit_identity.to_vec(),
44        reachable.to_vec()
45    );
46}
Source

pub fn iter(&self) -> impl Iterator<Item = &(A, B)>

Returns an iterator over the stored pairs in deterministic order.

Source

pub fn domain(&self) -> UnaryRelation<A>
where A: Clone,

Returns the domain of the relation.

Source

pub fn range(&self) -> UnaryRelation<B>
where B: Clone,

Returns the range of the relation.

Source

pub fn converse(&self) -> BinaryRelation<B, A>
where A: Clone, B: Clone,

Returns the converse relation.

Source

pub fn union(&self, other: &Self) -> Self
where A: Clone, B: Clone,

Returns the union of self and other.

Source

pub fn intersection(&self, other: &Self) -> Self
where A: Clone, B: Clone,

Returns the intersection of self and other.

Source

pub fn difference(&self, other: &Self) -> Self
where A: Clone, B: Clone,

Returns the set difference self \ other.

Source

pub fn restrict_domain(&self, allowed: &UnaryRelation<A>) -> Self
where A: Clone, B: Clone,

Restricts the domain of the relation to allowed.

Source

pub fn restrict_range(&self, allowed: &UnaryRelation<B>) -> Self
where A: Clone, B: Clone,

Restricts the range of the relation to allowed.

Source

pub fn image(&self, sources: &UnaryRelation<A>) -> UnaryRelation<B>
where B: Clone,

Computes the image of sources through the relation.

Returns { b | exists a in sources. (a, b) in self }.

Examples found in repository?
examples/workflow.rs (line 22)
5fn main() {
6    let step = BinaryRelation::from_pairs([
7        ("Draft", "Review"),
8        ("Review", "Approved"),
9        ("Review", "Rejected"),
10    ]);
11
12    let states =
13        UnaryRelation::from_values(["Draft", "Review", "Approved", "Rejected", "Archived"]);
14    let reachable = step.reflexive_transitive_closure(&states);
15    let draft = UnaryRelation::singleton("Draft");
16
17    assert!(reachable.contains(&"Archived", &"Archived"));
18    assert!(reachable.contains(&"Draft", &"Approved"));
19
20    println!(
21        "reachable from Draft: {:?}",
22        reachable.image(&draft).to_vec()
23    );
24}
More examples
Hide additional examples
examples/family.rs (line 19)
5fn main() {
6    let parent = BinaryRelation::from_pairs([
7        ("Ada", "Bob"),
8        ("Ada", "Cara"),
9        ("Bob", "Dana"),
10        ("Cara", "Eli"),
11        ("Dana", "Finn"),
12    ]);
13
14    let people = UnaryRelation::from_values(["Ada", "Bob", "Cara", "Dana", "Eli", "Finn"]);
15    let grandparent = parent.compose(&parent);
16    let ancestor = parent.reflexive_transitive_closure(&people);
17
18    let ada = UnaryRelation::singleton("Ada");
19    let reachable_from_ada = ancestor.image(&ada);
20
21    assert!(grandparent.contains(&"Ada", &"Dana"));
22    assert!(grandparent.contains(&"Ada", &"Eli"));
23    assert!(reachable_from_ada.contains(&"Finn"));
24
25    println!("grandparent pairs: {:?}", grandparent.to_vec());
26    println!(
27        "people reachable from Ada: {:?}",
28        reachable_from_ada.to_vec()
29    );
30}
examples/access_control.rs (line 24)
5fn main() {
6    let user_role = BinaryRelation::from_pairs([
7        ("ann", "admin"),
8        ("bob", "analyst"),
9        ("bob", "reviewer"),
10        ("cara", "guest"),
11    ]);
12
13    let role_permission = BinaryRelation::from_pairs([
14        ("admin", "read"),
15        ("admin", "write"),
16        ("admin", "deploy"),
17        ("analyst", "read"),
18        ("reviewer", "approve"),
19        ("guest", "read"),
20    ]);
21
22    let effective_permission = user_role.compose(&role_permission);
23    let bob = UnaryRelation::singleton("bob");
24    let bob_permissions = effective_permission.image(&bob);
25
26    assert!(effective_permission.contains(&"ann", &"deploy"));
27    assert!(bob_permissions.contains(&"approve"));
28    assert!(bob_permissions.contains(&"read"));
29
30    println!(
31        "effective permissions for bob: {:?}",
32        bob_permissions.to_vec()
33    );
34}
examples/annotated.rs (line 44)
29fn main() {
30    let confirmations = AnnotatedRelation::from_facts([
31        (("Alice", "Math"), SupportCount(1)),
32        (("Alice", "Math"), SupportCount(1)),
33        (("Bob", "Physics"), SupportCount(1)),
34        (("Cara", "Logic"), SupportCount::zero()),
35    ]);
36
37    let exact_completed = confirmations.to_binary_relation();
38    let alice = UnaryRelation::singleton("Alice");
39
40    assert_eq!(
41        confirmations.annotation_of(&("Alice", "Math")),
42        Some(&SupportCount(2))
43    );
44    assert_eq!(exact_completed.image(&alice).to_vec(), vec!["Math"]);
45    assert!(!confirmations.contains_fact(&("Cara", "Logic")));
46    assert_eq!(
47        confirmations
48            .iter()
49            .map(|(fact, count)| (*fact, count.0))
50            .collect::<Vec<_>>(),
51        vec![(("Alice", "Math"), 2), (("Bob", "Physics"), 1)]
52    );
53
54    println!(
55        "stored support counts: {:?}",
56        confirmations
57            .iter()
58            .map(|(fact, count)| (*fact, count.0))
59            .collect::<Vec<_>>()
60    );
61}
examples/provenance.rs (line 25)
5fn main() {
6    let gene_disease = ProvenanceRelation::from_facts([
7        (("BRCA1", "BreastCancer"), "curated_panel"),
8        (("BRCA1", "BreastCancer"), "paper_12"),
9        (("TP53", "BreastCancer"), "paper_77"),
10    ]);
11
12    let disease_drug = relmath::BinaryRelation::from_pairs([
13        ("BreastCancer", "Olaparib"),
14        ("BreastCancer", "Tamoxifen"),
15    ]);
16
17    let supported_gene_disease = gene_disease.to_binary_relation();
18    let gene_drug = supported_gene_disease.compose(&disease_drug);
19    let brca1 = UnaryRelation::singleton("BRCA1");
20    let brca1_witness = gene_disease
21        .why(&("BRCA1", "BreastCancer"))
22        .expect("expected explanation");
23
24    assert_eq!(
25        gene_drug.image(&brca1).to_vec(),
26        vec!["Olaparib", "Tamoxifen"]
27    );
28    assert_eq!(brca1_witness.to_vec(), vec!["curated_panel", "paper_12"]);
29    assert!(brca1_witness.contains_token(&"paper_12"));
30    assert_eq!(
31        gene_disease
32            .provenance_of(&("BRCA1", "BreastCancer"))
33            .expect("expected explanation")
34            .to_vec(),
35        brca1_witness.to_vec()
36    );
37    assert_eq!(
38        gene_disease.support().to_vec(),
39        vec![("BRCA1", "BreastCancer"), ("TP53", "BreastCancer")]
40    );
41    assert!(gene_disease.why(&("BRCA1", "Olaparib")).is_none());
42
43    println!(
44        "why BRCA1 links to BreastCancer in the base evidence: {:?}",
45        brca1_witness.to_vec()
46    );
47}
examples/valid_time.rs (line 59)
8fn main() {
9    let assignments = ValidTimeRelation::from_facts([
10        (
11            ("alice", "review"),
12            Interval::new(1, 3).expect("expected valid interval"),
13        ),
14        (
15            ("alice", "review"),
16            Interval::new(3, 5).expect("expected valid interval"),
17        ),
18        (
19            ("bob", "approve"),
20            Interval::new(2, 4).expect("expected valid interval"),
21        ),
22    ]);
23
24    let alice = UnaryRelation::singleton("alice");
25    let fact_support = assignments.support();
26    let exact_support = assignments.to_binary_relation();
27    let audit_window = Interval::new(2, 4).expect("expected valid interval");
28    let active_at_three = assignments.snapshot_at(&3);
29    let audit_assignments = assignments.restrict_to(&audit_window);
30
31    assert_eq!(
32        assignments
33            .valid_time_of(&("alice", "review"))
34            .expect("expected support")
35            .to_vec(),
36        vec![Interval::new(1, 5).expect("expected valid interval")]
37    );
38    assert!(assignments.is_active_at(&("alice", "review"), &4));
39    assert!(!assignments.is_active_at(&("alice", "review"), &5));
40    assert_eq!(
41        active_at_three.to_vec(),
42        vec![("alice", "review"), ("bob", "approve")]
43    );
44    assert_eq!(
45        fact_support.to_vec(),
46        vec![("alice", "review"), ("bob", "approve")]
47    );
48    assert_eq!(
49        audit_assignments
50            .valid_time_of(&("alice", "review"))
51            .expect("expected support")
52            .to_vec(),
53        vec![Interval::new(2, 4).expect("expected valid interval")]
54    );
55    assert_eq!(
56        audit_assignments.to_binary_relation().to_vec(),
57        vec![("alice", "review"), ("bob", "approve")]
58    );
59    assert_eq!(exact_support.image(&alice).to_vec(), vec!["review"]);
60
61    println!(
62        "fact support: {:?}; active at t=3: {:?}; audit restriction: {:?}",
63        fact_support.to_vec(),
64        active_at_three.to_vec(),
65        audit_assignments
66            .valid_time_of(&("alice", "review"))
67            .expect("expected support")
68            .to_vec()
69    );
70}
Source

pub fn preimage(&self, targets: &UnaryRelation<B>) -> UnaryRelation<A>
where A: Clone,

Computes the preimage of targets through the relation.

Returns { a | exists b in targets. (a, b) in self }.

Source

pub fn compose<C>(&self, rhs: &BinaryRelation<B, C>) -> BinaryRelation<A, C>
where A: Clone, B: Clone, C: Clone + Ord,

Composes self with rhs.

The result contains (a, c) whenever there exists b such that (a, b) is in self and (b, c) is in rhs.

§Examples
use relmath::BinaryRelation;

let user_role = BinaryRelation::from_pairs([
    ("ann", "admin"),
    ("bob", "reviewer"),
]);
let role_permission = BinaryRelation::from_pairs([
    ("admin", "read"),
    ("reviewer", "approve"),
]);

let effective_permission = user_role.compose(&role_permission);

assert_eq!(
    effective_permission.to_vec(),
    vec![("ann", "read"), ("bob", "approve")]
);
Examples found in repository?
examples/family.rs (line 15)
5fn main() {
6    let parent = BinaryRelation::from_pairs([
7        ("Ada", "Bob"),
8        ("Ada", "Cara"),
9        ("Bob", "Dana"),
10        ("Cara", "Eli"),
11        ("Dana", "Finn"),
12    ]);
13
14    let people = UnaryRelation::from_values(["Ada", "Bob", "Cara", "Dana", "Eli", "Finn"]);
15    let grandparent = parent.compose(&parent);
16    let ancestor = parent.reflexive_transitive_closure(&people);
17
18    let ada = UnaryRelation::singleton("Ada");
19    let reachable_from_ada = ancestor.image(&ada);
20
21    assert!(grandparent.contains(&"Ada", &"Dana"));
22    assert!(grandparent.contains(&"Ada", &"Eli"));
23    assert!(reachable_from_ada.contains(&"Finn"));
24
25    println!("grandparent pairs: {:?}", grandparent.to_vec());
26    println!(
27        "people reachable from Ada: {:?}",
28        reachable_from_ada.to_vec()
29    );
30}
More examples
Hide additional examples
examples/access_control.rs (line 22)
5fn main() {
6    let user_role = BinaryRelation::from_pairs([
7        ("ann", "admin"),
8        ("bob", "analyst"),
9        ("bob", "reviewer"),
10        ("cara", "guest"),
11    ]);
12
13    let role_permission = BinaryRelation::from_pairs([
14        ("admin", "read"),
15        ("admin", "write"),
16        ("admin", "deploy"),
17        ("analyst", "read"),
18        ("reviewer", "approve"),
19        ("guest", "read"),
20    ]);
21
22    let effective_permission = user_role.compose(&role_permission);
23    let bob = UnaryRelation::singleton("bob");
24    let bob_permissions = effective_permission.image(&bob);
25
26    assert!(effective_permission.contains(&"ann", &"deploy"));
27    assert!(bob_permissions.contains(&"approve"));
28    assert!(bob_permissions.contains(&"read"));
29
30    println!(
31        "effective permissions for bob: {:?}",
32        bob_permissions.to_vec()
33    );
34}
examples/provenance.rs (line 18)
5fn main() {
6    let gene_disease = ProvenanceRelation::from_facts([
7        (("BRCA1", "BreastCancer"), "curated_panel"),
8        (("BRCA1", "BreastCancer"), "paper_12"),
9        (("TP53", "BreastCancer"), "paper_77"),
10    ]);
11
12    let disease_drug = relmath::BinaryRelation::from_pairs([
13        ("BreastCancer", "Olaparib"),
14        ("BreastCancer", "Tamoxifen"),
15    ]);
16
17    let supported_gene_disease = gene_disease.to_binary_relation();
18    let gene_drug = supported_gene_disease.compose(&disease_drug);
19    let brca1 = UnaryRelation::singleton("BRCA1");
20    let brca1_witness = gene_disease
21        .why(&("BRCA1", "BreastCancer"))
22        .expect("expected explanation");
23
24    assert_eq!(
25        gene_drug.image(&brca1).to_vec(),
26        vec!["Olaparib", "Tamoxifen"]
27    );
28    assert_eq!(brca1_witness.to_vec(), vec!["curated_panel", "paper_12"]);
29    assert!(brca1_witness.contains_token(&"paper_12"));
30    assert_eq!(
31        gene_disease
32            .provenance_of(&("BRCA1", "BreastCancer"))
33            .expect("expected explanation")
34            .to_vec(),
35        brca1_witness.to_vec()
36    );
37    assert_eq!(
38        gene_disease.support().to_vec(),
39        vec![("BRCA1", "BreastCancer"), ("TP53", "BreastCancer")]
40    );
41    assert!(gene_disease.why(&("BRCA1", "Olaparib")).is_none());
42
43    println!(
44        "why BRCA1 links to BreastCancer in the base evidence: {:?}",
45        brca1_witness.to_vec()
46    );
47}
Source

pub fn to_vec(&self) -> Vec<(A, B)>
where A: Clone, B: Clone,

Converts the relation into a sorted vector of pairs.

Examples found in repository?
examples/capability_boundaries.rs (line 17)
10fn exact_pairs<R>(relation: &R) -> BinaryRelation<&'static str, &'static str>
11where
12    R: ExactSupport<(&'static str, &'static str)>
13        + ToExactBinaryRelation<&'static str, &'static str>,
14{
15    assert_eq!(
16        relation.exact_support().to_vec(),
17        relation.to_binary_relation().to_vec()
18    );
19    relation.to_binary_relation()
20}
21
22fn main() {
23    let evidence = ProvenanceRelation::from_facts([
24        (("alice", "review"), "directory"),
25        (("bob", "approve"), "policy"),
26    ]);
27    let permissions = AnnotatedRelation::from_facts([
28        (("alice", "review"), BooleanSemiring::TRUE),
29        (("bob", "approve"), BooleanSemiring::TRUE),
30    ]);
31    let schedule = ValidTimeRelation::from_facts([
32        (
33            ("alice", "review"),
34            Interval::new(1, 3).expect("expected valid interval"),
35        ),
36        (
37            ("bob", "approve"),
38            Interval::new(2, 4).expect("expected valid interval"),
39        ),
40    ]);
41
42    let exact_evidence = exact_pairs(&evidence);
43    let exact_permissions = exact_pairs(&permissions);
44    let exact_schedule = exact_pairs(&schedule);
45
46    assert_eq!(
47        exact_evidence.to_vec(),
48        vec![("alice", "review"), ("bob", "approve")]
49    );
50    assert_eq!(exact_permissions.to_vec(), exact_evidence.to_vec());
51    assert_eq!(exact_schedule.to_vec(), exact_evidence.to_vec());
52
53    assert_eq!(
54        evidence
55            .why(&("alice", "review"))
56            .expect("expected witness")
57            .to_vec(),
58        vec!["directory"]
59    );
60    assert_eq!(
61        permissions.annotation_of(&("alice", "review")),
62        Some(&BooleanSemiring::TRUE)
63    );
64    assert_eq!(
65        schedule
66            .valid_time_of(&("alice", "review"))
67            .expect("expected interval support")
68            .to_vec(),
69        vec![Interval::new(1, 3).expect("expected valid interval")]
70    );
71
72    println!(
73        "witness={:?}, annotation={:?}, interval_support={:?}, exact_support={:?}",
74        evidence
75            .why(&("alice", "review"))
76            .expect("expected witness")
77            .to_vec(),
78        permissions.annotation_of(&("alice", "review")),
79        schedule
80            .valid_time_of(&("alice", "review"))
81            .expect("expected interval support")
82            .to_vec(),
83        exact_schedule.to_vec()
84    );
85}
More examples
Hide additional examples
examples/family.rs (line 25)
5fn main() {
6    let parent = BinaryRelation::from_pairs([
7        ("Ada", "Bob"),
8        ("Ada", "Cara"),
9        ("Bob", "Dana"),
10        ("Cara", "Eli"),
11        ("Dana", "Finn"),
12    ]);
13
14    let people = UnaryRelation::from_values(["Ada", "Bob", "Cara", "Dana", "Eli", "Finn"]);
15    let grandparent = parent.compose(&parent);
16    let ancestor = parent.reflexive_transitive_closure(&people);
17
18    let ada = UnaryRelation::singleton("Ada");
19    let reachable_from_ada = ancestor.image(&ada);
20
21    assert!(grandparent.contains(&"Ada", &"Dana"));
22    assert!(grandparent.contains(&"Ada", &"Eli"));
23    assert!(reachable_from_ada.contains(&"Finn"));
24
25    println!("grandparent pairs: {:?}", grandparent.to_vec());
26    println!(
27        "people reachable from Ada: {:?}",
28        reachable_from_ada.to_vec()
29    );
30}
examples/carrier.rs (line 16)
5fn main() {
6    let step = BinaryRelation::from_pairs([("Draft", "Review")]);
7    let states = FiniteCarrier::from_values(["Draft", "Review", "Archived"]);
8
9    let inferred = step.carrier();
10    let inferred_identity = BinaryRelation::identity(&inferred);
11    let explicit_identity = BinaryRelation::identity_on(&states);
12    let reachable = step.reflexive_transitive_closure_on(&states);
13
14    assert_eq!(inferred.to_vec(), vec!["Draft", "Review"]);
15    assert_eq!(
16        inferred_identity.to_vec(),
17        vec![("Draft", "Draft"), ("Review", "Review")]
18    );
19    assert_eq!(
20        explicit_identity.to_vec(),
21        vec![
22            ("Archived", "Archived"),
23            ("Draft", "Draft"),
24            ("Review", "Review"),
25        ]
26    );
27    assert_eq!(states.to_vec(), vec!["Archived", "Draft", "Review"]);
28    assert_eq!(
29        reachable.to_vec(),
30        step.reflexive_transitive_closure(&states.to_unary_relation())
31            .to_vec()
32    );
33    assert!(reachable.is_reflexive_on(&states));
34    assert!(step.is_irreflexive_on(&states));
35    assert!(reachable.contains(&"Archived", &"Archived"));
36    assert!(reachable.contains(&"Draft", &"Review"));
37
38    println!(
39        "explicit carrier: {:?}; inferred support: {:?}; inferred identity: {:?}; explicit identity: {:?}; reachable: {:?}",
40        states.to_vec(),
41        inferred.to_vec(),
42        inferred_identity.to_vec(),
43        explicit_identity.to_vec(),
44        reachable.to_vec()
45    );
46}
examples/valid_time.rs (line 56)
8fn main() {
9    let assignments = ValidTimeRelation::from_facts([
10        (
11            ("alice", "review"),
12            Interval::new(1, 3).expect("expected valid interval"),
13        ),
14        (
15            ("alice", "review"),
16            Interval::new(3, 5).expect("expected valid interval"),
17        ),
18        (
19            ("bob", "approve"),
20            Interval::new(2, 4).expect("expected valid interval"),
21        ),
22    ]);
23
24    let alice = UnaryRelation::singleton("alice");
25    let fact_support = assignments.support();
26    let exact_support = assignments.to_binary_relation();
27    let audit_window = Interval::new(2, 4).expect("expected valid interval");
28    let active_at_three = assignments.snapshot_at(&3);
29    let audit_assignments = assignments.restrict_to(&audit_window);
30
31    assert_eq!(
32        assignments
33            .valid_time_of(&("alice", "review"))
34            .expect("expected support")
35            .to_vec(),
36        vec![Interval::new(1, 5).expect("expected valid interval")]
37    );
38    assert!(assignments.is_active_at(&("alice", "review"), &4));
39    assert!(!assignments.is_active_at(&("alice", "review"), &5));
40    assert_eq!(
41        active_at_three.to_vec(),
42        vec![("alice", "review"), ("bob", "approve")]
43    );
44    assert_eq!(
45        fact_support.to_vec(),
46        vec![("alice", "review"), ("bob", "approve")]
47    );
48    assert_eq!(
49        audit_assignments
50            .valid_time_of(&("alice", "review"))
51            .expect("expected support")
52            .to_vec(),
53        vec![Interval::new(2, 4).expect("expected valid interval")]
54    );
55    assert_eq!(
56        audit_assignments.to_binary_relation().to_vec(),
57        vec![("alice", "review"), ("bob", "approve")]
58    );
59    assert_eq!(exact_support.image(&alice).to_vec(), vec!["review"]);
60
61    println!(
62        "fact support: {:?}; active at t=3: {:?}; audit restriction: {:?}",
63        fact_support.to_vec(),
64        active_at_three.to_vec(),
65        audit_assignments
66            .valid_time_of(&("alice", "review"))
67            .expect("expected support")
68            .to_vec()
69    );
70}
Source§

impl<T: Ord> BinaryRelation<T, T>

Source

pub fn carrier(&self) -> UnaryRelation<T>
where T: Clone,

Returns the carrier induced by the relation: domain union range.

This is support-derived carrier information, not an explicit crate::FiniteCarrier. Use crate::FiniteCarrier when the declared domain must remain visible even for disconnected values that do not appear in stored pairs.

§Examples
use relmath::{BinaryRelation, FiniteCarrier};

let step = BinaryRelation::from_pairs([("Draft", "Review")]);
let explicit = FiniteCarrier::from_values(["Draft", "Review", "Archived"]);

assert_eq!(step.carrier().to_vec(), vec!["Draft", "Review"]);
assert_eq!(explicit.to_vec(), vec!["Archived", "Draft", "Review"]);
Examples found in repository?
examples/carrier.rs (line 9)
5fn main() {
6    let step = BinaryRelation::from_pairs([("Draft", "Review")]);
7    let states = FiniteCarrier::from_values(["Draft", "Review", "Archived"]);
8
9    let inferred = step.carrier();
10    let inferred_identity = BinaryRelation::identity(&inferred);
11    let explicit_identity = BinaryRelation::identity_on(&states);
12    let reachable = step.reflexive_transitive_closure_on(&states);
13
14    assert_eq!(inferred.to_vec(), vec!["Draft", "Review"]);
15    assert_eq!(
16        inferred_identity.to_vec(),
17        vec![("Draft", "Draft"), ("Review", "Review")]
18    );
19    assert_eq!(
20        explicit_identity.to_vec(),
21        vec![
22            ("Archived", "Archived"),
23            ("Draft", "Draft"),
24            ("Review", "Review"),
25        ]
26    );
27    assert_eq!(states.to_vec(), vec!["Archived", "Draft", "Review"]);
28    assert_eq!(
29        reachable.to_vec(),
30        step.reflexive_transitive_closure(&states.to_unary_relation())
31            .to_vec()
32    );
33    assert!(reachable.is_reflexive_on(&states));
34    assert!(step.is_irreflexive_on(&states));
35    assert!(reachable.contains(&"Archived", &"Archived"));
36    assert!(reachable.contains(&"Draft", &"Review"));
37
38    println!(
39        "explicit carrier: {:?}; inferred support: {:?}; inferred identity: {:?}; explicit identity: {:?}; reachable: {:?}",
40        states.to_vec(),
41        inferred.to_vec(),
42        inferred_identity.to_vec(),
43        explicit_identity.to_vec(),
44        reachable.to_vec()
45    );
46}
Source

pub fn identity(carrier: &UnaryRelation<T>) -> Self
where T: Clone,

Returns the identity relation on carrier.

§Examples
use relmath::{BinaryRelation, UnaryRelation};

let carrier = UnaryRelation::from_values(["Draft", "Review"]);

assert_eq!(
    BinaryRelation::identity(&carrier).to_vec(),
    vec![("Draft", "Draft"), ("Review", "Review")]
);

// Use `identity_on` when the carrier should remain explicit.
let explicit = relmath::FiniteCarrier::from_values(["Draft", "Review"]);
assert_eq!(BinaryRelation::identity_on(&explicit).to_vec(), BinaryRelation::identity(&carrier).to_vec());
Examples found in repository?
examples/carrier.rs (line 10)
5fn main() {
6    let step = BinaryRelation::from_pairs([("Draft", "Review")]);
7    let states = FiniteCarrier::from_values(["Draft", "Review", "Archived"]);
8
9    let inferred = step.carrier();
10    let inferred_identity = BinaryRelation::identity(&inferred);
11    let explicit_identity = BinaryRelation::identity_on(&states);
12    let reachable = step.reflexive_transitive_closure_on(&states);
13
14    assert_eq!(inferred.to_vec(), vec!["Draft", "Review"]);
15    assert_eq!(
16        inferred_identity.to_vec(),
17        vec![("Draft", "Draft"), ("Review", "Review")]
18    );
19    assert_eq!(
20        explicit_identity.to_vec(),
21        vec![
22            ("Archived", "Archived"),
23            ("Draft", "Draft"),
24            ("Review", "Review"),
25        ]
26    );
27    assert_eq!(states.to_vec(), vec!["Archived", "Draft", "Review"]);
28    assert_eq!(
29        reachable.to_vec(),
30        step.reflexive_transitive_closure(&states.to_unary_relation())
31            .to_vec()
32    );
33    assert!(reachable.is_reflexive_on(&states));
34    assert!(step.is_irreflexive_on(&states));
35    assert!(reachable.contains(&"Archived", &"Archived"));
36    assert!(reachable.contains(&"Draft", &"Review"));
37
38    println!(
39        "explicit carrier: {:?}; inferred support: {:?}; inferred identity: {:?}; explicit identity: {:?}; reachable: {:?}",
40        states.to_vec(),
41        inferred.to_vec(),
42        inferred_identity.to_vec(),
43        explicit_identity.to_vec(),
44        reachable.to_vec()
45    );
46}
Source

pub fn identity_on(carrier: &FiniteCarrier<T>) -> Self
where T: Clone,

Returns the identity relation on an explicit finite carrier.

This is the G7 carrier-aware companion to Self::identity. It keeps the carrier explicit at the API boundary instead of first converting it into a unary relation.

§Examples
use relmath::{BinaryRelation, FiniteCarrier, UnaryRelation};

let carrier = FiniteCarrier::from_values(["Draft", "Review"]);
let unary = UnaryRelation::from_values(["Draft", "Review"]);

assert_eq!(
    BinaryRelation::identity_on(&carrier).to_vec(),
    vec![("Draft", "Draft"), ("Review", "Review")]
);
assert_eq!(
    BinaryRelation::identity_on(&carrier).to_vec(),
    BinaryRelation::identity(&unary).to_vec()
);
Examples found in repository?
examples/carrier.rs (line 11)
5fn main() {
6    let step = BinaryRelation::from_pairs([("Draft", "Review")]);
7    let states = FiniteCarrier::from_values(["Draft", "Review", "Archived"]);
8
9    let inferred = step.carrier();
10    let inferred_identity = BinaryRelation::identity(&inferred);
11    let explicit_identity = BinaryRelation::identity_on(&states);
12    let reachable = step.reflexive_transitive_closure_on(&states);
13
14    assert_eq!(inferred.to_vec(), vec!["Draft", "Review"]);
15    assert_eq!(
16        inferred_identity.to_vec(),
17        vec![("Draft", "Draft"), ("Review", "Review")]
18    );
19    assert_eq!(
20        explicit_identity.to_vec(),
21        vec![
22            ("Archived", "Archived"),
23            ("Draft", "Draft"),
24            ("Review", "Review"),
25        ]
26    );
27    assert_eq!(states.to_vec(), vec!["Archived", "Draft", "Review"]);
28    assert_eq!(
29        reachable.to_vec(),
30        step.reflexive_transitive_closure(&states.to_unary_relation())
31            .to_vec()
32    );
33    assert!(reachable.is_reflexive_on(&states));
34    assert!(step.is_irreflexive_on(&states));
35    assert!(reachable.contains(&"Archived", &"Archived"));
36    assert!(reachable.contains(&"Draft", &"Review"));
37
38    println!(
39        "explicit carrier: {:?}; inferred support: {:?}; inferred identity: {:?}; explicit identity: {:?}; reachable: {:?}",
40        states.to_vec(),
41        inferred.to_vec(),
42        inferred_identity.to_vec(),
43        explicit_identity.to_vec(),
44        reachable.to_vec()
45    );
46}
Source

pub fn transitive_closure(&self) -> Self
where T: Clone,

Computes the transitive closure of the relation.

§Examples
use relmath::BinaryRelation;

let step = BinaryRelation::from_pairs([
    ("Draft", "Review"),
    ("Review", "Approved"),
]);

assert_eq!(
    step.transitive_closure().to_vec(),
    vec![
        ("Draft", "Approved"),
        ("Draft", "Review"),
        ("Review", "Approved"),
    ]
);
Source

pub fn reflexive_transitive_closure(&self, carrier: &UnaryRelation<T>) -> Self
where T: Clone,

Computes the reflexive-transitive closure on the given carrier.

Values that appear in carrier but not in any pair still gain their identity edge in the result.

§Examples
use relmath::{BinaryRelation, UnaryRelation};

let step = BinaryRelation::from_pairs([("Draft", "Review")]);
let states = UnaryRelation::from_values(["Draft", "Review", "Archived"]);
let reachable = step.reflexive_transitive_closure(&states);

assert!(reachable.contains(&"Archived", &"Archived"));
assert!(reachable.contains(&"Draft", &"Review"));

let explicit_states = relmath::FiniteCarrier::from_values(["Draft", "Review", "Archived"]);
assert_eq!(
    step.reflexive_transitive_closure_on(&explicit_states).to_vec(),
    reachable.to_vec()
);
Examples found in repository?
examples/workflow.rs (line 14)
5fn main() {
6    let step = BinaryRelation::from_pairs([
7        ("Draft", "Review"),
8        ("Review", "Approved"),
9        ("Review", "Rejected"),
10    ]);
11
12    let states =
13        UnaryRelation::from_values(["Draft", "Review", "Approved", "Rejected", "Archived"]);
14    let reachable = step.reflexive_transitive_closure(&states);
15    let draft = UnaryRelation::singleton("Draft");
16
17    assert!(reachable.contains(&"Archived", &"Archived"));
18    assert!(reachable.contains(&"Draft", &"Approved"));
19
20    println!(
21        "reachable from Draft: {:?}",
22        reachable.image(&draft).to_vec()
23    );
24}
More examples
Hide additional examples
examples/family.rs (line 16)
5fn main() {
6    let parent = BinaryRelation::from_pairs([
7        ("Ada", "Bob"),
8        ("Ada", "Cara"),
9        ("Bob", "Dana"),
10        ("Cara", "Eli"),
11        ("Dana", "Finn"),
12    ]);
13
14    let people = UnaryRelation::from_values(["Ada", "Bob", "Cara", "Dana", "Eli", "Finn"]);
15    let grandparent = parent.compose(&parent);
16    let ancestor = parent.reflexive_transitive_closure(&people);
17
18    let ada = UnaryRelation::singleton("Ada");
19    let reachable_from_ada = ancestor.image(&ada);
20
21    assert!(grandparent.contains(&"Ada", &"Dana"));
22    assert!(grandparent.contains(&"Ada", &"Eli"));
23    assert!(reachable_from_ada.contains(&"Finn"));
24
25    println!("grandparent pairs: {:?}", grandparent.to_vec());
26    println!(
27        "people reachable from Ada: {:?}",
28        reachable_from_ada.to_vec()
29    );
30}
examples/carrier.rs (line 30)
5fn main() {
6    let step = BinaryRelation::from_pairs([("Draft", "Review")]);
7    let states = FiniteCarrier::from_values(["Draft", "Review", "Archived"]);
8
9    let inferred = step.carrier();
10    let inferred_identity = BinaryRelation::identity(&inferred);
11    let explicit_identity = BinaryRelation::identity_on(&states);
12    let reachable = step.reflexive_transitive_closure_on(&states);
13
14    assert_eq!(inferred.to_vec(), vec!["Draft", "Review"]);
15    assert_eq!(
16        inferred_identity.to_vec(),
17        vec![("Draft", "Draft"), ("Review", "Review")]
18    );
19    assert_eq!(
20        explicit_identity.to_vec(),
21        vec![
22            ("Archived", "Archived"),
23            ("Draft", "Draft"),
24            ("Review", "Review"),
25        ]
26    );
27    assert_eq!(states.to_vec(), vec!["Archived", "Draft", "Review"]);
28    assert_eq!(
29        reachable.to_vec(),
30        step.reflexive_transitive_closure(&states.to_unary_relation())
31            .to_vec()
32    );
33    assert!(reachable.is_reflexive_on(&states));
34    assert!(step.is_irreflexive_on(&states));
35    assert!(reachable.contains(&"Archived", &"Archived"));
36    assert!(reachable.contains(&"Draft", &"Review"));
37
38    println!(
39        "explicit carrier: {:?}; inferred support: {:?}; inferred identity: {:?}; explicit identity: {:?}; reachable: {:?}",
40        states.to_vec(),
41        inferred.to_vec(),
42        inferred_identity.to_vec(),
43        explicit_identity.to_vec(),
44        reachable.to_vec()
45    );
46}
Source

pub fn reflexive_transitive_closure_on( &self, carrier: &FiniteCarrier<T>, ) -> Self
where T: Clone,

Computes the reflexive-transitive closure on an explicit finite carrier.

Values that appear in carrier but not in any pair still gain their identity edge in the result.

This is the G7 carrier-aware companion to Self::reflexive_transitive_closure.

§Examples
use relmath::{BinaryRelation, FiniteCarrier, UnaryRelation};

let step = BinaryRelation::from_pairs([("Draft", "Review")]);
let explicit_states = FiniteCarrier::from_values(["Draft", "Review", "Archived"]);
let unary_states = UnaryRelation::from_values(["Draft", "Review", "Archived"]);
let reachable = step.reflexive_transitive_closure_on(&explicit_states);

assert!(reachable.contains(&"Archived", &"Archived"));
assert!(reachable.contains(&"Draft", &"Review"));
assert_eq!(reachable.to_vec(), step.reflexive_transitive_closure(&unary_states).to_vec());
Examples found in repository?
examples/carrier.rs (line 12)
5fn main() {
6    let step = BinaryRelation::from_pairs([("Draft", "Review")]);
7    let states = FiniteCarrier::from_values(["Draft", "Review", "Archived"]);
8
9    let inferred = step.carrier();
10    let inferred_identity = BinaryRelation::identity(&inferred);
11    let explicit_identity = BinaryRelation::identity_on(&states);
12    let reachable = step.reflexive_transitive_closure_on(&states);
13
14    assert_eq!(inferred.to_vec(), vec!["Draft", "Review"]);
15    assert_eq!(
16        inferred_identity.to_vec(),
17        vec![("Draft", "Draft"), ("Review", "Review")]
18    );
19    assert_eq!(
20        explicit_identity.to_vec(),
21        vec![
22            ("Archived", "Archived"),
23            ("Draft", "Draft"),
24            ("Review", "Review"),
25        ]
26    );
27    assert_eq!(states.to_vec(), vec!["Archived", "Draft", "Review"]);
28    assert_eq!(
29        reachable.to_vec(),
30        step.reflexive_transitive_closure(&states.to_unary_relation())
31            .to_vec()
32    );
33    assert!(reachable.is_reflexive_on(&states));
34    assert!(step.is_irreflexive_on(&states));
35    assert!(reachable.contains(&"Archived", &"Archived"));
36    assert!(reachable.contains(&"Draft", &"Review"));
37
38    println!(
39        "explicit carrier: {:?}; inferred support: {:?}; inferred identity: {:?}; explicit identity: {:?}; reachable: {:?}",
40        states.to_vec(),
41        inferred.to_vec(),
42        inferred_identity.to_vec(),
43        explicit_identity.to_vec(),
44        reachable.to_vec()
45    );
46}
Source

pub fn is_reflexive(&self, carrier: &UnaryRelation<T>) -> bool

Returns true when the relation is reflexive on carrier.

Use Self::is_reflexive_on when the carrier should remain explicit as a crate::FiniteCarrier.

Source

pub fn is_reflexive_on(&self, carrier: &FiniteCarrier<T>) -> bool

Returns true when the relation is reflexive on an explicit finite carrier.

§Examples
use relmath::{BinaryRelation, FiniteCarrier};

let aliases = BinaryRelation::from_pairs([
    ("A. Smith", "A. Smith"),
    ("A. Smith", "Alice Smith"),
    ("Alice Smith", "A. Smith"),
    ("Alice Smith", "Alice Smith"),
]);
let carrier = FiniteCarrier::from_values(["A. Smith", "Alice Smith"]);

assert!(aliases.is_reflexive_on(&carrier));
Examples found in repository?
examples/carrier.rs (line 33)
5fn main() {
6    let step = BinaryRelation::from_pairs([("Draft", "Review")]);
7    let states = FiniteCarrier::from_values(["Draft", "Review", "Archived"]);
8
9    let inferred = step.carrier();
10    let inferred_identity = BinaryRelation::identity(&inferred);
11    let explicit_identity = BinaryRelation::identity_on(&states);
12    let reachable = step.reflexive_transitive_closure_on(&states);
13
14    assert_eq!(inferred.to_vec(), vec!["Draft", "Review"]);
15    assert_eq!(
16        inferred_identity.to_vec(),
17        vec![("Draft", "Draft"), ("Review", "Review")]
18    );
19    assert_eq!(
20        explicit_identity.to_vec(),
21        vec![
22            ("Archived", "Archived"),
23            ("Draft", "Draft"),
24            ("Review", "Review"),
25        ]
26    );
27    assert_eq!(states.to_vec(), vec!["Archived", "Draft", "Review"]);
28    assert_eq!(
29        reachable.to_vec(),
30        step.reflexive_transitive_closure(&states.to_unary_relation())
31            .to_vec()
32    );
33    assert!(reachable.is_reflexive_on(&states));
34    assert!(step.is_irreflexive_on(&states));
35    assert!(reachable.contains(&"Archived", &"Archived"));
36    assert!(reachable.contains(&"Draft", &"Review"));
37
38    println!(
39        "explicit carrier: {:?}; inferred support: {:?}; inferred identity: {:?}; explicit identity: {:?}; reachable: {:?}",
40        states.to_vec(),
41        inferred.to_vec(),
42        inferred_identity.to_vec(),
43        explicit_identity.to_vec(),
44        reachable.to_vec()
45    );
46}
Source

pub fn is_irreflexive(&self, carrier: &UnaryRelation<T>) -> bool

Returns true when the relation is irreflexive on carrier.

Use Self::is_irreflexive_on when the carrier should remain explicit as a crate::FiniteCarrier.

Source

pub fn is_irreflexive_on(&self, carrier: &FiniteCarrier<T>) -> bool

Returns true when the relation is irreflexive on an explicit finite carrier.

§Examples
use relmath::{BinaryRelation, FiniteCarrier};

let step = BinaryRelation::from_pairs([("Draft", "Review")]);
let carrier = FiniteCarrier::from_values(["Draft", "Review", "Archived"]);

assert!(step.is_irreflexive_on(&carrier));
Examples found in repository?
examples/carrier.rs (line 34)
5fn main() {
6    let step = BinaryRelation::from_pairs([("Draft", "Review")]);
7    let states = FiniteCarrier::from_values(["Draft", "Review", "Archived"]);
8
9    let inferred = step.carrier();
10    let inferred_identity = BinaryRelation::identity(&inferred);
11    let explicit_identity = BinaryRelation::identity_on(&states);
12    let reachable = step.reflexive_transitive_closure_on(&states);
13
14    assert_eq!(inferred.to_vec(), vec!["Draft", "Review"]);
15    assert_eq!(
16        inferred_identity.to_vec(),
17        vec![("Draft", "Draft"), ("Review", "Review")]
18    );
19    assert_eq!(
20        explicit_identity.to_vec(),
21        vec![
22            ("Archived", "Archived"),
23            ("Draft", "Draft"),
24            ("Review", "Review"),
25        ]
26    );
27    assert_eq!(states.to_vec(), vec!["Archived", "Draft", "Review"]);
28    assert_eq!(
29        reachable.to_vec(),
30        step.reflexive_transitive_closure(&states.to_unary_relation())
31            .to_vec()
32    );
33    assert!(reachable.is_reflexive_on(&states));
34    assert!(step.is_irreflexive_on(&states));
35    assert!(reachable.contains(&"Archived", &"Archived"));
36    assert!(reachable.contains(&"Draft", &"Review"));
37
38    println!(
39        "explicit carrier: {:?}; inferred support: {:?}; inferred identity: {:?}; explicit identity: {:?}; reachable: {:?}",
40        states.to_vec(),
41        inferred.to_vec(),
42        inferred_identity.to_vec(),
43        explicit_identity.to_vec(),
44        reachable.to_vec()
45    );
46}
Source

pub fn is_symmetric(&self) -> bool

Returns true when the relation is symmetric.

Source

pub fn is_antisymmetric(&self) -> bool

Returns true when the relation is antisymmetric.

Source

pub fn is_transitive(&self) -> bool
where T: Clone,

Returns true when the relation is transitive.

Source

pub fn is_equivalence(&self, carrier: &UnaryRelation<T>) -> bool
where T: Clone,

Returns true when the relation is an equivalence relation on carrier.

§Examples
use relmath::{BinaryRelation, UnaryRelation};

let aliases = BinaryRelation::from_pairs([
    ("A. Smith", "A. Smith"),
    ("A. Smith", "Alice Smith"),
    ("Alice Smith", "A. Smith"),
    ("Alice Smith", "Alice Smith"),
]);
let carrier = UnaryRelation::from_values(["A. Smith", "Alice Smith"]);

assert!(aliases.is_equivalence(&carrier));

let explicit = relmath::FiniteCarrier::from_values(["A. Smith", "Alice Smith"]);
assert!(aliases.is_equivalence_on(&explicit));
Source

pub fn is_equivalence_on(&self, carrier: &FiniteCarrier<T>) -> bool
where T: Clone,

Returns true when the relation is an equivalence relation on an explicit finite carrier.

§Examples
use relmath::{BinaryRelation, FiniteCarrier};

let aliases = BinaryRelation::from_pairs([
    ("A. Smith", "A. Smith"),
    ("A. Smith", "Alice Smith"),
    ("Alice Smith", "A. Smith"),
    ("Alice Smith", "Alice Smith"),
]);
let carrier = FiniteCarrier::from_values(["A. Smith", "Alice Smith"]);

assert!(aliases.is_equivalence_on(&carrier));
Source

pub fn is_partial_order(&self, carrier: &UnaryRelation<T>) -> bool
where T: Clone,

Returns true when the relation is a partial order on carrier.

§Examples
use relmath::{BinaryRelation, UnaryRelation};

let divides = BinaryRelation::from_pairs([
    (1_u8, 1_u8),
    (1, 2),
    (1, 4),
    (2, 2),
    (2, 4),
    (4, 4),
]);
let carrier = UnaryRelation::from_values([1_u8, 2_u8, 4_u8]);

assert!(divides.is_partial_order(&carrier));

let explicit = relmath::FiniteCarrier::from_values([1_u8, 2_u8, 4_u8]);
assert!(divides.is_partial_order_on(&explicit));
Source

pub fn is_partial_order_on(&self, carrier: &FiniteCarrier<T>) -> bool
where T: Clone,

Returns true when the relation is a partial order on an explicit finite carrier.

§Examples
use relmath::{BinaryRelation, FiniteCarrier};

let divides = BinaryRelation::from_pairs([
    (1_u8, 1_u8),
    (1, 2),
    (1, 4),
    (2, 2),
    (2, 4),
    (4, 4),
]);
let carrier = FiniteCarrier::from_values([1_u8, 2_u8, 4_u8]);

assert!(divides.is_partial_order_on(&carrier));

Trait Implementations§

Source§

impl<A: Clone + Ord, B: Clone + Ord> Clone for BinaryRelation<A, B>

Source§

fn clone(&self) -> BinaryRelation<A, B>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<A: Debug + Ord, B: Debug + Ord> Debug for BinaryRelation<A, B>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<A: Ord, B: Ord> Default for BinaryRelation<A, B>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<A: Ord, B: Ord> Extend<(A, B)> for BinaryRelation<A, B>

Source§

fn extend<I: IntoIterator<Item = (A, B)>>(&mut self, iter: I)

Extends a collection with the contents of an iterator. Read more
Source§

fn extend_one(&mut self, item: A)

🔬This is a nightly-only experimental API. (extend_one)
Extends a collection with exactly one element.
Source§

fn extend_reserve(&mut self, additional: usize)

🔬This is a nightly-only experimental API. (extend_one)
Reserves capacity in a collection for the given number of additional elements. Read more
Source§

impl<A: Ord, B: Ord> FiniteRelation for BinaryRelation<A, B>

Source§

fn len(&self) -> usize

Returns the number of stored tuples in the relation.
Source§

fn is_empty(&self) -> bool

Returns true when the relation contains no tuples.
Source§

impl<A: Ord, B: Ord> FromIterator<(A, B)> for BinaryRelation<A, B>

Source§

fn from_iter<I: IntoIterator<Item = (A, B)>>(iter: I) -> Self

Creates a value from an iterator. Read more
Source§

impl<'a, A: Ord, B: Ord> IntoIterator for &'a BinaryRelation<A, B>

Source§

type Item = &'a (A, B)

The type of the elements being iterated over.
Source§

type IntoIter = Iter<'a, (A, B)>

Which kind of iterator are we turning this into?
Source§

fn into_iter(self) -> Self::IntoIter

Creates an iterator from a value. Read more
Source§

impl<A: Ord, B: Ord> IntoIterator for BinaryRelation<A, B>

Source§

type Item = (A, B)

The type of the elements being iterated over.
Source§

type IntoIter = IntoIter<(A, B)>

Which kind of iterator are we turning this into?
Source§

fn into_iter(self) -> Self::IntoIter

Creates an iterator from a value. Read more
Source§

impl<A: PartialEq + Ord, B: PartialEq + Ord> PartialEq for BinaryRelation<A, B>

Source§

fn eq(&self, other: &BinaryRelation<A, B>) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<A: Ord, B: Ord> RelationView for BinaryRelation<A, B>

Source§

type Tuple<'a> = &'a (A, B) where Self: 'a

Borrowed tuple item yielded by Self::tuples.
Source§

fn tuples(&self) -> impl Iterator<Item = Self::Tuple<'_>>

Returns the stored tuples in deterministic order.
Source§

impl<A: Eq + Ord, B: Eq + Ord> Eq for BinaryRelation<A, B>

Source§

impl<A: Ord, B: Ord> StructuralPartialEq for BinaryRelation<A, B>

Auto Trait Implementations§

§

impl<A, B> Freeze for BinaryRelation<A, B>

§

impl<A, B> RefUnwindSafe for BinaryRelation<A, B>

§

impl<A, B> Send for BinaryRelation<A, B>
where A: Send, B: Send,

§

impl<A, B> Sync for BinaryRelation<A, B>
where A: Sync, B: Sync,

§

impl<A, B> Unpin for BinaryRelation<A, B>

§

impl<A, B> UnsafeUnpin for BinaryRelation<A, B>

§

impl<A, B> UnwindSafe for BinaryRelation<A, B>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.