use crate::fst::Label;
use crate::semiring::gallic::variant::{longest_common_suffix, GallicVariant};
use crate::semiring::{Semiring, SemiringProperties};
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct RightGallic;
impl GallicVariant for RightGallic {
fn plus<W: Semiring>(
labels1: &[Label],
weight1: &W,
labels2: &[Label],
weight2: &W,
) -> (Vec<Label>, W) {
let common_labels = longest_common_suffix(labels1, labels2);
let combined_weight = weight1.plus(weight2);
(common_labels, combined_weight)
}
fn variant_name() -> &'static str {
"Right"
}
fn properties<W: Semiring>() -> SemiringProperties {
let _weight_props = W::properties();
SemiringProperties {
left_semiring: true,
right_semiring: true,
commutative: false,
idempotent: false,
path: false,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::semiring::TropicalWeight;
#[test]
fn test_right_gallic_plus_identical_labels() {
let labels1 = vec![1, 2, 3];
let labels2 = vec![1, 2, 3];
let w1 = TropicalWeight::new(1.0);
let w2 = TropicalWeight::new(2.0);
let (result_labels, result_weight) = RightGallic::plus(&labels1, &w1, &labels2, &w2);
assert_eq!(result_labels, vec![1, 2, 3]);
assert_eq!(*result_weight.value(), 1.0);
}
#[test]
fn test_right_gallic_plus_partial_overlap() {
let labels1 = vec![1, 2, 3, 4];
let labels2 = vec![5, 6, 3, 4];
let w1 = TropicalWeight::new(3.0);
let w2 = TropicalWeight::new(1.5);
let (result_labels, result_weight) = RightGallic::plus(&labels1, &w1, &labels2, &w2);
assert_eq!(result_labels, vec![3, 4]); assert_eq!(*result_weight.value(), 1.5);
}
#[test]
fn test_right_gallic_plus_no_overlap() {
let labels1 = vec![1, 2];
let labels2 = vec![3, 4];
let w1 = TropicalWeight::new(2.0);
let w2 = TropicalWeight::new(3.0);
let (result_labels, result_weight) = RightGallic::plus(&labels1, &w1, &labels2, &w2);
assert_eq!(result_labels, Vec::<Label>::new());
assert_eq!(*result_weight.value(), 2.0);
}
#[test]
fn test_right_gallic_plus_empty_labels() {
let labels1: Vec<Label> = vec![];
let labels2 = vec![1, 2];
let w1 = TropicalWeight::new(1.0);
let w2 = TropicalWeight::new(2.0);
let (result_labels, result_weight) = RightGallic::plus(&labels1, &w1, &labels2, &w2);
assert_eq!(result_labels, Vec::<Label>::new());
assert_eq!(*result_weight.value(), 1.0);
}
#[test]
fn test_right_gallic_suffix_extraction() {
let labels1 = vec![1, 2, 3, 4];
let labels2 = vec![5, 6, 3, 4];
let w1 = TropicalWeight::new(1.0);
let w2 = TropicalWeight::new(1.0);
let (result_labels, _) = RightGallic::plus(&labels1, &w1, &labels2, &w2);
assert_eq!(result_labels, vec![3, 4]); }
#[test]
fn test_right_gallic_variant_name() {
assert_eq!(RightGallic::variant_name(), "Right");
}
#[test]
fn test_right_gallic_properties() {
let props = RightGallic::properties::<TropicalWeight>();
assert!(props.left_semiring);
assert!(props.right_semiring);
assert!(!props.commutative);
assert!(!props.idempotent);
assert!(!props.path);
}
#[test]
fn test_right_gallic_not_functional() {
assert!(!RightGallic::is_functional());
}
}