1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
use crate::algorithms::encode::EncodeType; use crate::algorithms::encode::EncodeType::*; use crate::algorithms::*; use crate::fst_properties::FstProperties; use crate::fst_traits::{AllocableFst, MutableFst}; use crate::semirings::{SemiringProperties, WeaklyDivisibleSemiring, WeightQuantize}; use crate::Semiring; use anyhow::Result; pub fn optimize< W: Semiring + WeaklyDivisibleSemiring + WeightQuantize, F: MutableFst<W> + AllocableFst<W>, >( fst: &mut F, ) -> Result<()> where W::ReverseWeight: WeightQuantize, { if fst.properties().contains(FstProperties::ACCEPTOR) { optimize_acceptor(fst) } else { optimize_transducer(fst) } } fn determinize< W: Semiring + WeaklyDivisibleSemiring + WeightQuantize, F: MutableFst<W> + AllocableFst<W>, >( fst: &mut F, ) -> Result<()> { *fst = determinize::determinize(fst)?; Ok(()) } fn encode_deter_mini_decode< W: Semiring + WeaklyDivisibleSemiring + WeightQuantize, F: MutableFst<W> + AllocableFst<W>, >( fst: &mut F, encoder: EncodeType, ) -> Result<()> where W::ReverseWeight: WeightQuantize, { let table = encode::encode(fst, encoder)?; determinize(fst)?; minimize(fst)?; encode::decode(fst, table) } fn optimize_transducer< W: Semiring + WeaklyDivisibleSemiring + WeightQuantize, F: MutableFst<W> + AllocableFst<W>, >( fst: &mut F, ) -> Result<()> where W::ReverseWeight: WeightQuantize, { if !fst.properties().contains(FstProperties::NO_EPSILONS) { rm_epsilon::rm_epsilon(fst)?; } tr_sum(fst); if !W::properties().contains(SemiringProperties::IDEMPOTENT) { if !fst.properties().contains(FstProperties::I_DETERMINISTIC) { if fst.properties().contains(FstProperties::ACYCLIC) { encode_deter_mini_decode(fst, EncodeLabels)?; } } else { minimize(fst)?; } } else { if !fst.properties().contains(FstProperties::I_DETERMINISTIC) { if !fst.properties().intersects( FstProperties::ACYCLIC | FstProperties::UNWEIGHTED | FstProperties::UNWEIGHTED_CYCLES, ) { encode_deter_mini_decode(fst, EncodeWeightsAndLabels)?; tr_sum(fst); } else { encode_deter_mini_decode(fst, EncodeLabels)?; } } else { minimize(fst)?; } } Ok(()) } fn optimize_acceptor< W: Semiring + WeaklyDivisibleSemiring + WeightQuantize, F: MutableFst<W> + AllocableFst<W>, >( fst: &mut F, ) -> Result<()> where W::ReverseWeight: WeightQuantize, { if !fst.properties().contains(FstProperties::NO_EPSILONS) { rm_epsilon::rm_epsilon(fst)?; } tr_sum(fst); if !W::properties().contains(SemiringProperties::IDEMPOTENT) { if !fst.properties().contains(FstProperties::I_DETERMINISTIC) { if fst.properties().contains(FstProperties::ACYCLIC) { determinize(fst)?; minimize(fst)?; } } else { minimize(fst)?; } } else { if !fst.properties().contains(FstProperties::I_DETERMINISTIC) { if !fst.properties().intersects( FstProperties::ACYCLIC | FstProperties::UNWEIGHTED | FstProperties::UNWEIGHTED_CYCLES, ) { encode_deter_mini_decode(fst, EncodeWeights)?; tr_sum(fst) } else { determinize(fst)?; minimize(fst)?; } } else { minimize(fst)?; } } Ok(()) }