use crate::semiring::traits::{
CommutativeTimesSemiring, IdempotentSemiring, KClosedSemiring, Semiring, StarSemiring,
ZeroSumFreeSemiring,
};
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
#[repr(transparent)]
pub struct BoolWeight(pub bool);
impl BoolWeight {
#[inline]
pub const fn new(value: bool) -> Self {
BoolWeight(value)
}
#[inline]
pub const fn value(self) -> bool {
self.0
}
}
impl From<bool> for BoolWeight {
#[inline]
fn from(value: bool) -> Self {
BoolWeight::new(value)
}
}
impl From<BoolWeight> for bool {
#[inline]
fn from(weight: BoolWeight) -> Self {
weight.value()
}
}
impl Semiring for BoolWeight {
#[inline]
fn zero() -> Self {
BoolWeight(false)
}
#[inline]
fn one() -> Self {
BoolWeight(true)
}
#[inline]
fn plus(&self, other: &Self) -> Self {
BoolWeight(self.0 || other.0)
}
#[inline]
fn times(&self, other: &Self) -> Self {
BoolWeight(self.0 && other.0)
}
#[inline]
fn is_zero(&self) -> bool {
!self.0
}
#[inline]
fn is_one(&self) -> bool {
self.0
}
fn approx_eq(&self, other: &Self, _epsilon: f64) -> bool {
self.0 == other.0
}
fn natural_less(&self, other: &Self) -> Option<bool> {
Some(self.0 > other.0)
}
fn to_bytes(&self) -> Vec<u8> {
vec![self.0 as u8]
}
}
impl StarSemiring for BoolWeight {
fn star(&self) -> Option<Self> {
Some(BoolWeight::one())
}
}
impl IdempotentSemiring for BoolWeight {}
impl KClosedSemiring for BoolWeight {
fn closure_bound() -> Option<usize> {
Some(0)
}
}
impl ZeroSumFreeSemiring for BoolWeight {}
impl CommutativeTimesSemiring for BoolWeight {}
impl std::ops::BitOr for BoolWeight {
type Output = Self;
#[inline]
fn bitor(self, other: Self) -> Self {
self.plus(&other)
}
}
impl std::ops::BitAnd for BoolWeight {
type Output = Self;
#[inline]
fn bitand(self, other: Self) -> Self {
self.times(&other)
}
}
impl std::ops::BitOrAssign for BoolWeight {
#[inline]
fn bitor_assign(&mut self, other: Self) {
*self = self.plus(&other);
}
}
impl std::ops::BitAndAssign for BoolWeight {
#[inline]
fn bitand_assign(&mut self, other: Self) {
*self = self.times(&other);
}
}
impl std::ops::Add for BoolWeight {
type Output = Self;
#[inline]
fn add(self, other: Self) -> Self {
self.plus(&other)
}
}
impl std::ops::Mul for BoolWeight {
type Output = Self;
#[inline]
fn mul(self, other: Self) -> Self {
self.times(&other)
}
}
impl std::ops::AddAssign for BoolWeight {
#[inline]
fn add_assign(&mut self, other: Self) {
*self = self.plus(&other);
}
}
impl std::ops::MulAssign for BoolWeight {
#[inline]
fn mul_assign(&mut self, other: Self) {
*self = self.times(&other);
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for BoolWeight {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.0.serialize(serializer)
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for BoolWeight {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
bool::deserialize(deserializer).map(BoolWeight::new)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::semiring::traits::tests::{
verify_commutative_times_semiring, verify_idempotent_semiring, verify_k_closed_semiring,
verify_semiring_axioms, verify_star_semiring, verify_zero_sum_free_semiring,
};
#[test]
fn test_basic_operations() {
let t = BoolWeight::from(true);
let f = BoolWeight::from(false);
assert_eq!(t.plus(&t), BoolWeight::from(true));
assert_eq!(t.plus(&f), BoolWeight::from(true));
assert_eq!(f.plus(&t), BoolWeight::from(true));
assert_eq!(f.plus(&f), BoolWeight::from(false));
assert_eq!(t.times(&t), BoolWeight::from(true));
assert_eq!(t.times(&f), BoolWeight::from(false));
assert_eq!(f.times(&t), BoolWeight::from(false));
assert_eq!(f.times(&f), BoolWeight::from(false));
}
#[test]
fn test_identities() {
let t = BoolWeight::from(true);
let f = BoolWeight::from(false);
assert_eq!(t.plus(&BoolWeight::zero()), t);
assert_eq!(f.plus(&BoolWeight::zero()), f);
assert_eq!(t.times(&BoolWeight::one()), t);
assert_eq!(f.times(&BoolWeight::one()), f);
}
#[test]
fn test_annihilation() {
let t = BoolWeight::from(true);
assert_eq!(t.times(&BoolWeight::zero()), BoolWeight::zero());
assert_eq!(BoolWeight::zero().times(&t), BoolWeight::zero());
}
#[test]
fn test_star() {
assert_eq!(BoolWeight::from(true).star(), Some(BoolWeight::from(true)));
assert_eq!(BoolWeight::from(false).star(), Some(BoolWeight::from(true)));
}
#[test]
fn test_operators() {
let t = BoolWeight::from(true);
let f = BoolWeight::from(false);
assert_eq!(t | f, BoolWeight::from(true));
assert_eq!(t & f, BoolWeight::from(false));
assert_eq!(t + f, BoolWeight::from(true));
assert_eq!(t * f, BoolWeight::from(false));
}
#[test]
fn test_semiring_axioms() {
let values = [BoolWeight::from(true), BoolWeight::from(false)];
for &a in &values {
for &b in &values {
for &c in &values {
verify_semiring_axioms(a, b, c, 0.0);
}
}
}
}
#[test]
fn test_star_semiring() {
verify_star_semiring(BoolWeight::from(true), 0.0);
verify_star_semiring(BoolWeight::from(false), 0.0);
}
#[test]
fn test_idempotent_semiring() {
verify_idempotent_semiring(BoolWeight::from(true), 0.0);
verify_idempotent_semiring(BoolWeight::from(false), 0.0);
}
#[test]
fn test_k_closed_semiring() {
verify_k_closed_semiring(BoolWeight::from(true), 0.0);
verify_k_closed_semiring(BoolWeight::from(false), 0.0);
}
#[test]
fn test_zero_sum_free_semiring() {
let t = BoolWeight::from(true);
let f = BoolWeight::from(false);
verify_zero_sum_free_semiring(t, t, 0.0);
verify_zero_sum_free_semiring(t, f, 0.0);
verify_zero_sum_free_semiring(f, t, 0.0);
verify_zero_sum_free_semiring(f, f, 0.0);
}
#[test]
fn test_commutative_times_semiring() {
let t = BoolWeight::from(true);
let f = BoolWeight::from(false);
verify_commutative_times_semiring(t, t, 0.0);
verify_commutative_times_semiring(t, f, 0.0);
verify_commutative_times_semiring(f, t, 0.0);
verify_commutative_times_semiring(f, f, 0.0);
}
}