diff --git a/CHANGELOG.md b/CHANGELOG.md index 090b8b08e..c50707e3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Added - Binary serialization & deserialization support for FST caches. - Binary serialization & deserialization support for Compose FST op state table. +- Add `TrivialWeight` ## [0.8.0] - 2020-16-10 diff --git a/Cargo.lock b/Cargo.lock index f55b97ab2..155194e58 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -730,7 +730,7 @@ checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "rustfst" -version = "1.1.1" +version = "1.1.2" dependencies = [ "anyhow", "bimap", @@ -760,7 +760,7 @@ dependencies = [ [[package]] name = "rustfst-cli" -version = "1.1.1" +version = "1.1.2" dependencies = [ "anyhow", "clap", @@ -774,7 +774,7 @@ dependencies = [ [[package]] name = "rustfst-ffi" -version = "1.1.1" +version = "1.1.2" dependencies = [ "anyhow", "downcast-rs", diff --git a/rustfst/src/semirings/mod.rs b/rustfst/src/semirings/mod.rs index dcdf216dd..37bdb60bf 100644 --- a/rustfst/src/semirings/mod.rs +++ b/rustfst/src/semirings/mod.rs @@ -13,6 +13,7 @@ mod probability_weight; mod product_weight; mod string_variant; mod string_weight; +mod trivial_weight; mod tropical_weight; mod union_weight; pub(crate) mod utils_float; @@ -33,5 +34,6 @@ pub(crate) use self::string_variant::StringWeightVariant; pub use self::string_weight::{ StringType, StringWeightLeft, StringWeightRestrict, StringWeightRight, }; +pub use self::trivial_weight::TrivialWeight; pub use self::tropical_weight::TropicalWeight; pub use self::union_weight::{UnionWeight, UnionWeightOption}; diff --git a/rustfst/src/semirings/trivial_weight.rs b/rustfst/src/semirings/trivial_weight.rs new file mode 100644 index 000000000..ae170d754 --- /dev/null +++ b/rustfst/src/semirings/trivial_weight.rs @@ -0,0 +1,105 @@ +use anyhow::Result; + +use crate::semirings::{CompleteSemiring, ReverseBack, Semiring, SemiringProperties, StarSemiring}; +use std::borrow::Borrow; + +use super::WeaklyDivisibleSemiring; + +/// Trivial semiring: (..., ..., (), ()). +/// +/// This is useful for defining unweighted transducers. +#[derive(Clone, Debug, PartialEq, PartialOrd, Default, Eq, Copy, Hash)] +pub struct TrivialWeight; + +impl Semiring for TrivialWeight { + type Type = (); + + type ReverseWeight = TrivialWeight; + + fn zero() -> Self { + Self + } + + fn one() -> Self { + Self + } + + fn new(_value: Self::Type) -> Self { + Self + } + + fn plus_assign>(&mut self, _rhs: P) -> anyhow::Result<()> { + Ok(()) + } + + fn times_assign>(&mut self, _rhs: P) -> anyhow::Result<()> { + Ok(()) + } + + fn approx_equal>(&self, _rhs: P, _delta: f32) -> bool { + true + } + + fn value(&self) -> &Self::Type { + &() + } + + fn take_value(self) -> Self::Type {} + + fn set_value(&mut self, _value: Self::Type) {} + + fn reverse(&self) -> anyhow::Result { + Ok(*self) + } + + fn properties() -> SemiringProperties { + SemiringProperties::LEFT_SEMIRING + | SemiringProperties::RIGHT_SEMIRING + | SemiringProperties::COMMUTATIVE + | SemiringProperties::IDEMPOTENT + | SemiringProperties::PATH + } +} + +impl ReverseBack for TrivialWeight { + fn reverse_back(&self) -> Result { + Ok(*self) + } +} + +impl CompleteSemiring for TrivialWeight {} + +impl StarSemiring for TrivialWeight { + fn closure(&self) -> Self { + Self + } +} + +impl WeaklyDivisibleSemiring for TrivialWeight { + fn divide_assign(&mut self, _rhs: &Self, _divide_type: super::DivideType) -> Result<()> { + bail!("Division by 0") + } +} + +impl From<()> for TrivialWeight { + fn from(_value: ()) -> Self { + Self + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_trivial_weight() -> Result<()> { + let b_trivial = TrivialWeight; + + // Test plus + assert_eq!(b_trivial.plus(b_trivial)?, b_trivial); + + // Test times + assert_eq!(b_trivial.times(b_trivial)?, b_trivial); + Ok(()) + } +}