use std::collections::BTreeMap;
use crate::{
BinaryRelation, NaryRelation, NaryRelationError, UnaryRelation, traits::FiniteRelation,
};
pub trait Semiring: Clone + Eq {
#[must_use]
fn zero() -> Self;
#[must_use]
fn one() -> Self;
#[must_use]
fn add(&self, rhs: &Self) -> Self;
#[must_use]
fn mul(&self, rhs: &Self) -> Self;
#[must_use]
fn is_zero(&self) -> bool {
self == &Self::zero()
}
#[must_use]
fn is_one(&self) -> bool {
self == &Self::one()
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct AnnotatedRelation<F: Ord, A: Semiring> {
facts: BTreeMap<F, A>,
}
impl<F: Ord, A: Semiring> AnnotatedRelation<F, A> {
#[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, A)>,
{
facts.into_iter().collect()
}
pub fn insert(&mut self, fact: F, annotation: A) -> bool {
match self.facts.entry(fact) {
std::collections::btree_map::Entry::Vacant(entry) => {
if annotation.is_zero() {
return false;
}
entry.insert(annotation);
true
}
std::collections::btree_map::Entry::Occupied(mut entry) => {
let combined = entry.get().add(&annotation);
if combined.is_zero() {
entry.remove();
true
} else if entry.get() == &combined {
false
} else {
*entry.get_mut() = combined;
true
}
}
}
}
#[must_use]
pub fn contains_fact(&self, fact: &F) -> bool {
self.facts.contains_key(fact)
}
#[must_use]
pub fn annotation_of(&self, fact: &F) -> Option<&A> {
self.facts.get(fact)
}
pub fn iter(&self) -> impl Iterator<Item = (&F, &A)> {
self.facts.iter()
}
#[must_use]
pub fn support(&self) -> UnaryRelation<F>
where
F: Clone,
{
self.facts.keys().cloned().collect()
}
}
impl<F: Ord, A: Semiring> Default for AnnotatedRelation<F, A> {
fn default() -> Self {
Self::new()
}
}
impl<F: Ord, A: Semiring> FiniteRelation for AnnotatedRelation<F, A> {
fn len(&self) -> usize {
self.facts.len()
}
}
impl<F: Ord, A: Semiring> FromIterator<(F, A)> for AnnotatedRelation<F, A> {
fn from_iter<I: IntoIterator<Item = (F, A)>>(iter: I) -> Self {
let mut relation = Self::new();
relation.extend(iter);
relation
}
}
impl<F: Ord, A: Semiring> Extend<(F, A)> for AnnotatedRelation<F, A> {
fn extend<I: IntoIterator<Item = (F, A)>>(&mut self, iter: I) {
for (fact, annotation) in iter {
self.insert(fact, annotation);
}
}
}
impl<T: Ord + Clone, A: Semiring> AnnotatedRelation<T, A> {
#[must_use]
pub fn to_unary_relation(&self) -> UnaryRelation<T> {
self.support()
}
}
impl<A0: Ord + Clone, B0: Ord + Clone, A: Semiring> AnnotatedRelation<(A0, B0), A> {
#[must_use]
pub fn to_binary_relation(&self) -> BinaryRelation<A0, B0> {
self.facts.keys().cloned().collect()
}
}
impl<T: Ord + Clone, A: Semiring> AnnotatedRelation<Vec<T>, A> {
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())
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct BooleanSemiring(bool);
impl BooleanSemiring {
pub const FALSE: Self = Self(false);
pub const TRUE: Self = Self(true);
#[must_use]
pub const fn new(value: bool) -> Self {
Self(value)
}
#[must_use]
pub const fn value(self) -> bool {
self.0
}
}
impl From<bool> for BooleanSemiring {
fn from(value: bool) -> Self {
Self::new(value)
}
}
impl From<BooleanSemiring> for bool {
fn from(value: BooleanSemiring) -> Self {
value.value()
}
}
impl Semiring for BooleanSemiring {
fn zero() -> Self {
Self::FALSE
}
fn one() -> Self {
Self::TRUE
}
fn add(&self, rhs: &Self) -> Self {
Self(self.0 || rhs.0)
}
fn mul(&self, rhs: &Self) -> Self {
Self(self.0 && rhs.0)
}
}