use std::collections::{BTreeMap, BTreeSet};
use crate::{
BinaryRelation, NaryRelation, NaryRelationError, UnaryRelation, traits::FiniteRelation,
};
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ProvenanceSet<P: Ord> {
tokens: BTreeSet<P>,
}
impl<P: Ord> ProvenanceSet<P> {
#[must_use]
pub fn len(&self) -> usize {
self.tokens.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.tokens.is_empty()
}
#[must_use]
pub fn contains(&self, token: &P) -> bool {
self.tokens.contains(token)
}
#[must_use]
pub fn contains_token(&self, token: &P) -> bool {
self.contains(token)
}
pub fn iter(&self) -> impl Iterator<Item = &P> {
self.tokens.iter()
}
#[must_use]
pub fn to_vec(&self) -> Vec<P>
where
P: Clone,
{
self.tokens.iter().cloned().collect()
}
}
impl<P: Ord> Default for ProvenanceSet<P> {
fn default() -> Self {
Self {
tokens: BTreeSet::new(),
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ProvenanceRelation<F: Ord, P: Ord> {
facts: BTreeMap<F, ProvenanceSet<P>>,
}
impl<F: Ord, P: Ord> ProvenanceRelation<F, P> {
#[must_use]
pub fn new() -> Self {
Self {
facts: BTreeMap::new(),
}
}
#[must_use]
pub fn from_facts<I>(facts: I) -> Self
where
I: IntoIterator<Item = (F, P)>,
{
facts.into_iter().collect()
}
pub fn insert(&mut self, fact: F, token: P) -> bool {
self.facts.entry(fact).or_default().tokens.insert(token)
}
#[must_use]
pub fn contains_fact(&self, fact: &F) -> bool {
self.facts.contains_key(fact)
}
#[must_use]
pub fn why(&self, fact: &F) -> Option<&ProvenanceSet<P>> {
self.facts.get(fact)
}
#[must_use]
pub fn provenance_of(&self, fact: &F) -> Option<&ProvenanceSet<P>> {
self.why(fact)
}
pub fn iter(&self) -> impl Iterator<Item = (&F, &ProvenanceSet<P>)> {
self.facts.iter()
}
#[must_use]
pub fn support(&self) -> UnaryRelation<F>
where
F: Clone,
{
self.facts.keys().cloned().collect()
}
}
impl<F: Ord, P: Ord> Default for ProvenanceRelation<F, P> {
fn default() -> Self {
Self::new()
}
}
impl<F: Ord, P: Ord> FiniteRelation for ProvenanceRelation<F, P> {
fn len(&self) -> usize {
self.facts.len()
}
}
impl<F: Ord, P: Ord> FromIterator<(F, P)> for ProvenanceRelation<F, P> {
fn from_iter<I: IntoIterator<Item = (F, P)>>(iter: I) -> Self {
let mut relation = Self::new();
relation.extend(iter);
relation
}
}
impl<F: Ord, P: Ord> Extend<(F, P)> for ProvenanceRelation<F, P> {
fn extend<I: IntoIterator<Item = (F, P)>>(&mut self, iter: I) {
for (fact, token) in iter {
self.insert(fact, token);
}
}
}
impl<T: Ord + Clone, P: Ord> ProvenanceRelation<T, P> {
#[must_use]
pub fn to_unary_relation(&self) -> UnaryRelation<T> {
self.support()
}
}
impl<A: Ord + Clone, B: Ord + Clone, P: Ord> ProvenanceRelation<(A, B), P> {
#[must_use]
pub fn to_binary_relation(&self) -> BinaryRelation<A, B> {
self.facts.keys().cloned().collect()
}
}
impl<T: Ord + Clone, P: Ord> ProvenanceRelation<Vec<T>, P> {
pub fn to_nary_relation<I, S>(&self, schema: I) -> Result<NaryRelation<T>, NaryRelationError>
where
I: IntoIterator<Item = S>,
S: Into<String>,
{
NaryRelation::from_rows(schema, self.facts.keys().cloned())
}
}