Expand description
§relmath
relmath is the library crate inside the relmath-rs repository.
It provides exact finite relations with deterministic BTreeSet-backed
iteration order.
§Current Surface
The current public API covers:
annotated::Semiring,annotated::BooleanSemiring, andannotated::AnnotatedRelation<F, A>for additive annotation foundationstemporal::Interval<T>andtemporal::IntervalError<T>for deterministic half-open interval foundationstemporal::ValidTimeSupport<T>andtemporal::ValidTimeRelation<F, T>for deterministic valid-time fact support over exact relationsUnaryRelation<T>for finite unary relations (sets)BinaryRelation<A, B>for finite binary relationsGroupedRelation<T>for deterministic exact grouped n-ary outputNaryRelation<T>for deterministic schema-aware exact n-ary relationsprovenance::ProvenanceRelation<F, P>andprovenance::ProvenanceSet<P>for deterministic fact-level provenance tokens- schema validation with explicit n-ary relation errors
- named-column inspection with zero-based
column_index - std-only named-row onboarding and export with
BTreeMap - union, intersection, and difference
- domain, range, converse, and composition
- domain/range restriction plus image/preimage with unary relations
- identity on a carrier
- transitive and reflexive-transitive closure on homogeneous relations
- relation property checks for reflexivity, irreflexivity, symmetry, antisymmetry, transitivity, equivalence, and partial order
- n-ary schema inspection, row insertion, deterministic iteration, selection, projection, rename, natural join, and schema-compatible set algebra
Composition uses relational order:
r.compose(&s)meansr ; s- the result contains
(a, c)when somebsatisfies(a, b) in rand(b, c) in s
§Current Limits
This crate currently implements the exact G1 core plus the first narrow G2 foundation, the first additive G3 provenance step, the first additive G4 annotated relation step, and the first G5 valid-time foundation and temporal operation step:
- natural join plus exact keyed grouping with row counts have landed so far; broader join families, richer aggregation, and division are still later work
- provenance currently tracks exact base-fact tokens only; base-fact
whyqueries have landed, but derived tuple explanations,why_notqueries, and derivation DAGs are still later work - absent facts return
Nonefromwhyandprovenance_of; the current API does not use an empty witness as an “absent explanation” sentinel - the first rule layer is documented as a future positive finite least-fixed-point surface over named exact relations, but no public rules API has landed yet
- deterministic annotated fact storage and exact support materialization have landed in G4, but annotated relation algebra remains later work
- the first G5 valid-time relation foundation plus
snapshot_atand relation-levelrestrict_tohave landed, but temporal joins and temporal composition are still later work - no typed row derives or schema macros yet
- no broad weighted, fuzzy, or probabilistic relation families yet
- no solver-backed or symbolic evaluation
The repository ships focused examples under examples/:
familyfor ancestry and reachabilityaccess_controlfor role-permission propagationworkflowfor state reachabilitycurriculumfor schema-aware n-ary filtering and projectionprovenancefor deterministic fact-token evidence trackingannotatedfor deterministic annotated facts with exact support queriessemiringfor the first additive annotation-domain foundationintervalsfor deterministic half-open temporal interval reasoningvalid_timefor deterministic valid-time fact support, snapshots, and restriction workflows
§N-ary Row Algebra Notes
selectkeeps the existing schema and preserves deterministic order among surviving rowsprojectfollows the requested column order exactlyprojectcurrently rejects empty projections and duplicate projected columnsrenameis a no-op when the source and target names are the sameunion,intersection, anddifferencerequire exact schema equality, including column order
§N-ary Interchange Notes
- the current G2 interchange boundary is std-only and dependency-free
from_named_rowsloadsBTreeMaprecords into an explicit schemato_named_rowsexports name-addressableBTreeMaprecords in deterministic row order- missing and unexpected columns are rejected explicitly
- serde, JSON, and CSV / TSV onboarding remain later feature-gated work
§N-ary Join Notes
natural_joinmatches rows when every shared column has equal values- when two schemas are disjoint,
natural_joinbehaves as a cartesian product - the output schema keeps the entire left schema, then appends right-only columns in their original order
- output row order stays deterministic because rows are materialized into a
BTreeSet - if no rows match, the result is empty but still carries the joined schema
§N-ary Grouping Notes
group_byuses explicit key columns in the requested ordergroup(key)returns the member relation for one exact grouping key- empty grouping keys are currently rejected by the exact core
- each member group keeps the original relation schema in this first slice
- group iteration order is deterministic by key
countsis the first exact aggregate and returns the number of stored rows in each group after relation deduplication
§G3 Provenance Notes
- the first G3 provenance slice is additive and lives under
relmath::provenance ProvenanceRelation<F, P>records which exact facts are present and which deterministic token set is attached to each factProvenanceSet<P>is the user-visible witness type returned by explanation queries for present stored facts- repeated insertion of the same fact with a new token combines provenance by exact set union
why(fact)is the preferred explanation query and returns the deterministic witness for a stored fact andNonewhen the fact is absentprovenance_of(fact)is the current alias for retrieving that same exact witnesssupport(),to_unary_relation(),to_binary_relation(), andto_nary_relation()forget provenance tokens and materialize exact relation support only- witnesses in this first slice are exact token sets for stored facts
- derived tuple provenance,
why_not, and rule-driven explanations remain later work, although the first rule-planning ADR now fixes the intended least-fixed-point direction for a later implementation
§G3 Example
use relmath::provenance::ProvenanceRelation;
let evidence = ProvenanceRelation::from_facts([
(("BRCA1", "BreastCancer"), "curated_panel"),
(("BRCA1", "BreastCancer"), "paper_12"),
(("TP53", "BreastCancer"), "paper_77"),
]);
let why = evidence
.why(&("BRCA1", "BreastCancer"))
.expect("expected explanation");
assert_eq!(why.to_vec(), vec!["curated_panel", "paper_12"]);
assert_eq!(
evidence
.provenance_of(&("BRCA1", "BreastCancer"))
.expect("expected explanation")
.to_vec(),
vec!["curated_panel", "paper_12"]
);
assert!(evidence.why(&("BRCA1", "Olaparib")).is_none());
assert_eq!(
evidence.support().to_vec(),
vec![("BRCA1", "BreastCancer"), ("TP53", "BreastCancer")]
);§G3 Rule Planning Notes
- the first rule and fixed-point slice is documented in ADR 0007
- the planned first rule shape is positive finite rules over named exact relations with least-fixed-point semantics
- no public
rulesmodule or executable rule engine has landed in this crate yet
§G4 Annotated Notes
- the first G4 annotated slice is additive and lives under
relmath::annotated Semiringdefines zero as absence, one as multiplicative identity,addas union-like combination, andmulas composition-like chainingBooleanSemiringis the first built-in annotation family and models the exact boolean semantics already used by the published relation coreAnnotatedRelation<F, A>stores annotated facts in deterministic fact order and combines repeated facts bySemiring::add- only non-zero annotations are stored, so zero means absence from exact support
contains_fact(fact)andannotation_of(fact)therefore agree on support: absent or zero-annotated facts returnfalseandNone- unlike
provenance::why,annotation_of(fact)returns the stored annotation value itself rather than a witness set support(),to_unary_relation(),to_binary_relation(), andto_nary_relation()forget annotations and materialize only exact support- annotated relation algebra, valid-time fact storage, and broader weighted, fuzzy, or probabilistic families remain later work
§G5 Valid-Time Notes
- in the current G5 terminology, an interval is one half-open window
[start, end), support is the canonical interval set attached to one stored fact, and exact support is the set of facts that remains after forgetting time relmath::temporal::Interval<T>remains the executable interval foundation for deterministic half-open[start, end)semanticsrelmath::temporal::ValidTimeSupport<T>is the canonical interval support attached to one factValidTimeSupport::overlaps(interval)reports non-empty temporal overlap, whileValidTimeSupport::restrict_to(interval)returns canonical restricted support and becomes empty when overlap is absentrelmath::temporal::ValidTimeRelation<F, T>stores facts in deterministic fact order and coalesces overlapping or directly adjacent support intervals for the same factvalid_time_of(fact)returns the canonical valid-time support for one fact andNonewhen the fact is absentis_active_at(fact, point)checks whether one fact is active at one time point using half-open boundary semanticssnapshot_at(point)returns the exact unary snapshot of facts active at one time pointrestrict_to(interval)keeps only facts whose support overlaps the interval and restricts each remaining fact to canonical overlap supportsupport(),to_unary_relation(),to_binary_relation(), andto_nary_relation()forget time and materialize exact support only- the relation does not store empty temporal support as a sentinel value, so
absent facts return
Nonerather than an empty support object - transaction time, bitemporal correction histories, temporal join, and temporal composition remain later G5 or later-milestone work
§G5 Example
use relmath::temporal::{Interval, ValidTimeRelation};
let assignments = 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 audit_window = Interval::new(2, 4).expect("expected valid interval");
assert_eq!(
assignments
.valid_time_of(&("alice", "review"))
.expect("expected support")
.to_vec(),
vec![Interval::new(1, 5).expect("expected valid interval")]
);
assert!(assignments.is_active_at(&("alice", "review"), &4));
assert!(!assignments.is_active_at(&("alice", "review"), &5));
assert_eq!(
assignments.snapshot_at(&3).to_vec(),
vec![("alice", "review"), ("bob", "approve")]
);
assert_eq!(
assignments.to_binary_relation().to_vec(),
vec![("alice", "review"), ("bob", "approve")]
);
assert_eq!(
assignments
.restrict_to(&audit_window)
.valid_time_of(&("alice", "review"))
.expect("expected support")
.to_vec(),
vec![Interval::new(2, 4).expect("expected valid interval")]
);§G4 Example
use relmath::{
BinaryRelation,
annotated::{AnnotatedRelation, Semiring},
};
#[derive(Clone, Debug, PartialEq, Eq)]
struct Count(u8);
impl Semiring for Count {
fn zero() -> Self {
Self(0)
}
fn one() -> Self {
Self(1)
}
fn add(&self, rhs: &Self) -> Self {
Self(self.0.saturating_add(rhs.0))
}
fn mul(&self, rhs: &Self) -> Self {
Self(self.0.saturating_mul(rhs.0))
}
}
let tasks = AnnotatedRelation::from_facts([
(("Alice", "Review"), Count(1)),
(("Alice", "Review"), Count(2)),
(("Bob", "Approve"), Count(1)),
(("Cara", "Archive"), Count(0)),
]);
assert_eq!(tasks.annotation_of(&("Alice", "Review")), Some(&Count(3)));
assert_eq!(tasks.annotation_of(&("Cara", "Archive")), None);
assert!(!tasks.contains_fact(&("Cara", "Archive")));
let support: BinaryRelation<_, _> = tasks.to_binary_relation();
assert_eq!(
support.to_vec(),
vec![("Alice", "Review"), ("Bob", "Approve")]
);§Status
This crate now contains the published G1 unary/binary core plus the first schema-aware n-ary building block for G2, including stricter schema validation for blank column names, a std-only named-row interchange boundary, an exact natural join primitive, exact keyed grouping with row counts, the first additive G3 provenance foundation and explanation query surface for exact fact tokens, the first additive G4 annotated relation foundation, and the first G5 valid-time relation and temporal operation foundation.
Re-exports§
pub use crate::core::BinaryRelation;pub use crate::core::GroupedRelation;pub use crate::core::NaryRelation;pub use crate::core::NaryRelationError;pub use crate::core::UnaryRelation;pub use crate::traits::FiniteRelation;
Modules§
- annotated
- Additive annotation domains and deterministic annotated relation support. Additive annotation-domain and annotated-relation foundations.
- core
- Core unary, binary, and n-ary relation types. Core relation types and algorithms.
- prelude
- Prelude with the most commonly used imports. Common imports for relation-first programming.
- provenance
- Deterministic provenance support for exact facts. Deterministic exact provenance support.
- temporal
- Deterministic temporal interval and valid-time foundations. Deterministic temporal interval and valid-time foundations.
- traits
- Traits shared by relation types. Shared traits for relation types.