rustfst/algorithms/
tr_unique.rs1use std::cmp::Ordering;
2
3use crate::fst_properties::FstProperties;
4use crate::fst_traits::MutableFst;
5use crate::semirings::Semiring;
6use crate::Tr;
7
8pub(crate) fn tr_compare<W: Semiring>(tr_1: &Tr<W>, tr_2: &Tr<W>) -> Ordering {
9 if tr_1.ilabel < tr_2.ilabel {
10 return Ordering::Less;
11 }
12 if tr_1.ilabel > tr_2.ilabel {
13 return Ordering::Greater;
14 }
15 if tr_1.olabel < tr_2.olabel {
16 return Ordering::Less;
17 }
18 if tr_1.olabel > tr_2.olabel {
19 return Ordering::Greater;
20 }
21 if tr_1.nextstate < tr_2.nextstate {
28 return Ordering::Less;
29 }
30 if tr_1.nextstate > tr_2.nextstate {
31 return Ordering::Greater;
32 }
33 Ordering::Equal
34}
35
36pub fn tr_unique<W: Semiring, F: MutableFst<W>>(ifst: &mut F) {
39 let props = ifst.properties();
40 unsafe {
41 for s in ifst.states_range() {
42 ifst.unique_trs_unchecked(s);
43 }
44 }
45 let mut outprops =
46 props & FstProperties::arcsort_properties() & FstProperties::delete_arcs_properties();
47 if ifst.num_states() == 0 {
48 outprops |= FstProperties::null_properties();
49 }
50 ifst.set_properties_with_mask(outprops, FstProperties::all_properties());
51}
52
53#[cfg(test)]
54mod test {
55 use crate::fst_impls::VectorFst;
56 use crate::fst_traits::MutableFst;
57 use crate::semirings::{ProbabilityWeight, Semiring};
58 use crate::Tr;
59 use anyhow::Result;
60
61 use super::*;
62
63 #[test]
64 fn test_tr_map_unique() -> Result<()> {
65 let mut fst_in = VectorFst::<ProbabilityWeight>::new();
66
67 let s1 = fst_in.add_state();
68 let s2 = fst_in.add_state();
69
70 fst_in.add_tr(s1, Tr::new(0, 0, ProbabilityWeight::new(0.3), s2))?;
71 fst_in.add_tr(s1, Tr::new(0, 1, ProbabilityWeight::new(0.3), s2))?;
72 fst_in.add_tr(s1, Tr::new(1, 0, ProbabilityWeight::new(0.3), s2))?;
73 fst_in.add_tr(s1, Tr::new(0, 0, ProbabilityWeight::new(0.3), s2))?;
74 fst_in.add_tr(s1, Tr::new(0, 0, ProbabilityWeight::new(0.1), s2))?;
75
76 fst_in.set_start(s1)?;
77 fst_in.set_final(s2, ProbabilityWeight::one())?;
78
79 let mut fst_out = VectorFst::<ProbabilityWeight>::new();
80
81 let s1 = fst_out.add_state();
82 let s2 = fst_out.add_state();
83
84 fst_out.add_tr(s1, Tr::new(0, 0, ProbabilityWeight::new(0.3), s2))?;
85 fst_out.add_tr(s1, Tr::new(0, 0, ProbabilityWeight::new(0.1), s2))?;
86 fst_out.add_tr(s1, Tr::new(0, 1, ProbabilityWeight::new(0.3), s2))?;
87 fst_out.add_tr(s1, Tr::new(1, 0, ProbabilityWeight::new(0.3), s2))?;
88
89 fst_out.set_start(s1)?;
90 fst_out.set_final(s2, ProbabilityWeight::one())?;
91
92 tr_unique(&mut fst_in);
93
94 assert_eq!(fst_in, fst_out);
95
96 Ok(())
97 }
98
99 }