pub struct ProvenanceRelation<F: Ord, P: Ord> { /* private fields */ }Expand description
Deterministic exact provenance attached to stored facts.
ProvenanceRelation<F, P> maps each stored fact to a deterministic set of
provenance tokens. Repeated insertion of the same (fact, token) pair is
idempotent. Inserting a new token for an existing fact combines provenance
by exact set union.
In this first additive provenance slice, every stored fact is a base fact.
The module does not yet derive new tuples. Self::why explains stored
facts only; derived-tuple explanations and why_not queries remain later
work.
§Examples
use relmath::{UnaryRelation, provenance::ProvenanceRelation};
let gene_disease = ProvenanceRelation::from_facts([
(("BRCA1", "BreastCancer"), "paper_12"),
(("BRCA1", "BreastCancer"), "curated_panel"),
(("TP53", "BreastCancer"), "paper_77"),
]);
let supported = gene_disease.to_binary_relation();
let brca1 = UnaryRelation::singleton("BRCA1");
assert_eq!(supported.image(&brca1).to_vec(), vec!["BreastCancer"]);
assert_eq!(
gene_disease
.why(&("BRCA1", "BreastCancer"))
.expect("expected explanation")
.to_vec(),
vec!["curated_panel", "paper_12"]
);Implementations§
Source§impl<F: Ord, P: Ord> ProvenanceRelation<F, P>
impl<F: Ord, P: Ord> ProvenanceRelation<F, P>
Sourcepub fn new() -> Self
pub fn new() -> Self
Creates an empty provenance relation.
§Examples
use relmath::provenance::ProvenanceRelation;
let mut evidence = ProvenanceRelation::new();
assert!(evidence.insert(("BRCA1", "BreastCancer"), "paper_12"));
assert!(!evidence.insert(("BRCA1", "BreastCancer"), "paper_12"));
assert!(evidence.contains_fact(&("BRCA1", "BreastCancer")));
assert_eq!(
evidence
.provenance_of(&("BRCA1", "BreastCancer"))
.expect("expected explanation")
.to_vec(),
vec!["paper_12"]
);Sourcepub fn from_facts<I>(facts: I) -> Selfwhere
I: IntoIterator<Item = (F, P)>,
pub fn from_facts<I>(facts: I) -> Selfwhere
I: IntoIterator<Item = (F, P)>,
Creates a provenance relation from (fact, token) entries.
Repeated facts accumulate tokens by exact set union.
Examples found in repository?
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}More examples
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}Sourcepub fn insert(&mut self, fact: F, token: P) -> bool
pub fn insert(&mut self, fact: F, token: P) -> bool
Inserts one provenance token for a fact.
Returns true when the token was not already attached to the fact.
Sourcepub fn contains_fact(&self, fact: &F) -> bool
pub fn contains_fact(&self, fact: &F) -> bool
Returns true when the relation contains the given fact.
Sourcepub fn why(&self, fact: &F) -> Option<&ProvenanceSet<P>>
pub fn why(&self, fact: &F) -> Option<&ProvenanceSet<P>>
Returns why fact is present in this provenance relation.
When fact is present, the returned witness is the deterministic exact
set of provenance tokens attached to that stored fact. When fact is
absent, this returns None.
In this first G3 slice, every stored fact is a base fact with at least
one token, so None means the relation has no explanation for the fact
because the fact is absent.
§Examples
use relmath::provenance::ProvenanceRelation;
let evidence = ProvenanceRelation::from_facts([
(("BRCA1", "BreastCancer"), "paper_12"),
(("BRCA1", "BreastCancer"), "curated_panel"),
]);
let why = evidence
.why(&("BRCA1", "BreastCancer"))
.expect("expected explanation");
assert!(why.contains_token(&"paper_12"));
assert!(why.contains_token(&"curated_panel"));
assert!(evidence.why(&("BRCA1", "Olaparib")).is_none());Examples found in repository?
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}More examples
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}Sourcepub fn provenance_of(&self, fact: &F) -> Option<&ProvenanceSet<P>>
pub fn provenance_of(&self, fact: &F) -> Option<&ProvenanceSet<P>>
Returns the deterministic provenance set for one fact.
Prefer Self::why for explanation-oriented queries.
Examples found in repository?
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}Sourcepub fn iter(&self) -> impl Iterator<Item = (&F, &ProvenanceSet<P>)>
pub fn iter(&self) -> impl Iterator<Item = (&F, &ProvenanceSet<P>)>
Returns an iterator over facts and provenance in deterministic order.
§Examples
use relmath::provenance::ProvenanceRelation;
let evidence = ProvenanceRelation::from_facts([
(("BRCA1", "BreastCancer"), "paper_12"),
(("BRCA1", "BreastCancer"), "curated_panel"),
(("TP53", "BreastCancer"), "paper_77"),
]);
assert_eq!(
evidence
.iter()
.map(|(fact, witness)| (*fact, witness.to_vec()))
.collect::<Vec<_>>(),
vec![
(("BRCA1", "BreastCancer"), vec!["curated_panel", "paper_12"]),
(("TP53", "BreastCancer"), vec!["paper_77"]),
]
);Sourcepub fn support(&self) -> UnaryRelation<F>where
F: Clone,
pub fn support(&self) -> UnaryRelation<F>where
F: Clone,
Returns the exact support relation of stored facts as a unary relation.
This support forgets provenance and keeps only which facts are present.
Generic code can access the same relation-level boundary through
crate::ExactSupport::exact_support.
§Examples
use relmath::provenance::ProvenanceRelation;
let evidence = ProvenanceRelation::from_facts([
(("BRCA1", "BreastCancer"), "paper_12"),
(("BRCA1", "BreastCancer"), "curated_panel"),
(("TP53", "BreastCancer"), "paper_77"),
]);
assert_eq!(
evidence.support().to_vec(),
vec![("BRCA1", "BreastCancer"), ("TP53", "BreastCancer")]
);Examples found in repository?
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§impl<T: Ord + Clone, P: Ord> ProvenanceRelation<T, P>
impl<T: Ord + Clone, P: Ord> ProvenanceRelation<T, P>
Sourcepub fn to_unary_relation(&self) -> UnaryRelation<T>
pub fn to_unary_relation(&self) -> UnaryRelation<T>
Converts scalar facts into a unary relation support set.
Generic code can access the same unary materialization boundary through
crate::ToExactUnaryRelation.
§Examples
use relmath::provenance::ProvenanceRelation;
let concepts = ProvenanceRelation::from_facts([
("Relations", "lecture_1"),
("Relations", "worksheet"),
("Closure", "lecture_2"),
]);
assert_eq!(concepts.to_unary_relation().to_vec(), vec!["Closure", "Relations"]);Source§impl<A: Ord + Clone, B: Ord + Clone, P: Ord> ProvenanceRelation<(A, B), P>
impl<A: Ord + Clone, B: Ord + Clone, P: Ord> ProvenanceRelation<(A, B), P>
Sourcepub fn to_binary_relation(&self) -> BinaryRelation<A, B>
pub fn to_binary_relation(&self) -> BinaryRelation<A, B>
Converts pair facts into a binary relation support set.
Generic code can access the same binary materialization boundary
through crate::ToExactBinaryRelation.
§Examples
use relmath::provenance::ProvenanceRelation;
let evidence = ProvenanceRelation::from_facts([
(("Alice", "Reader"), "directory"),
(("Bob", "Editor"), "directory"),
]);
assert_eq!(
evidence.to_binary_relation().to_vec(),
vec![("Alice", "Reader"), ("Bob", "Editor")]
);Examples found in repository?
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§impl<T: Ord + Clone, P: Ord> ProvenanceRelation<Vec<T>, P>
impl<T: Ord + Clone, P: Ord> ProvenanceRelation<Vec<T>, P>
Sourcepub fn to_nary_relation<I, S>(
&self,
schema: I,
) -> Result<NaryRelation<T>, NaryRelationError>
pub fn to_nary_relation<I, S>( &self, schema: I, ) -> Result<NaryRelation<T>, NaryRelationError>
Converts row facts into an n-ary relation with the given schema.
The explicit schema preserves the current exact n-ary boundary where row
values do not themselves encode column names. This method reuses the
current NaryRelation validation rules, so duplicate or blank column
names and row-arity mismatches return NaryRelationError. Generic code
can access the same n-ary materialization boundary through
crate::ToExactNaryRelation.
§Examples
use relmath::provenance::ProvenanceRelation;
let rows = ProvenanceRelation::from_facts([
(vec!["Alice", "Math", "passed"], "gradebook"),
(vec!["Alice", "Math", "passed"], "reviewed"),
(vec!["Bob", "Physics", "passed"], "gradebook"),
]);
let relation = rows
.to_nary_relation(["student", "course", "status"])
.expect("expected valid support relation");
assert_eq!(
relation.to_rows(),
vec![
vec!["Alice", "Math", "passed"],
vec!["Bob", "Physics", "passed"],
]
);Trait Implementations§
Source§impl<F: Clone + Ord, P: Clone + Ord> Clone for ProvenanceRelation<F, P>
impl<F: Clone + Ord, P: Clone + Ord> Clone for ProvenanceRelation<F, P>
Source§fn clone(&self) -> ProvenanceRelation<F, P>
fn clone(&self) -> ProvenanceRelation<F, P>
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl<F: Ord + Clone, P: Ord> ExactSupport<F> for ProvenanceRelation<F, P>
impl<F: Ord + Clone, P: Ord> ExactSupport<F> for ProvenanceRelation<F, P>
Source§fn exact_support(&self) -> UnaryRelation<F>
fn exact_support(&self) -> UnaryRelation<F>
Source§impl<F: Ord, P: Ord> Extend<(F, P)> for ProvenanceRelation<F, P>
impl<F: Ord, P: Ord> Extend<(F, P)> for ProvenanceRelation<F, P>
Source§fn extend<I: IntoIterator<Item = (F, P)>>(&mut self, iter: I)
fn extend<I: IntoIterator<Item = (F, P)>>(&mut self, iter: I)
Source§fn extend_one(&mut self, item: A)
fn extend_one(&mut self, item: A)
extend_one)Source§fn extend_reserve(&mut self, additional: usize)
fn extend_reserve(&mut self, additional: usize)
extend_one)