// fstext/lattice-utils-inl.h // Copyright 2009-2012 Microsoft Corporation Johns Hopkins University (Author: Daniel Povey) // See ../../COPYING for clarification regarding multiple authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED // WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, // MERCHANTABLITY OR NON-INFRINGEMENT. // See the Apache 2 License for the specific language governing permissions and // limitations under the License. #ifndef KALDI_FSTEXT_LATTICE_UTILS_INL_H_ #define KALDI_FSTEXT_LATTICE_UTILS_INL_H_ // Do not include this file directly. It is included by lattice-utils.h namespace fst { /* Convert from FST with arc-type Weight, to one with arc-type CompactLatticeWeight. Uses FactorFst to identify chains of states which can be turned into a single output arc. */ template void ConvertLattice( const ExpandedFst > &ifst, MutableFst > > *ofst, bool invert) { typedef ArcTpl Arc; typedef typename Arc::StateId StateId; typedef CompactLatticeWeightTpl CompactWeight; typedef ArcTpl CompactArc; VectorFst > ffst; vector > labels; if (invert) // normal case: want the ilabels as sequences on the arcs of Factor(ifst, &ffst, &labels); // the output... Factor makes seqs of // ilabels. else { VectorFst > invfst(ifst); Invert(&invfst); Factor(invfst, &ffst, &labels); } TopSort(&ffst); // Put the states in ffst in topological order, which is // easier on the eye when reading the text-form lattices and corresponds to // what we get when we generate the lattices in the decoder. ofst->DeleteStates(); // The states will be numbered exactly the same as the original FST. // Add the states to the new FST. StateId num_states = ffst.NumStates(); for (StateId s = 0; s < num_states; s++) { StateId news = ofst->AddState(); assert(news == s); } ofst->SetStart(ffst.Start()); for (StateId s = 0; s < num_states; s++) { Weight final_weight = ffst.Final(s); if (final_weight != Weight::Zero()) { CompactWeight final_compact_weight(final_weight, vector()); ofst->SetFinal(s, final_compact_weight); } for (ArcIterator > iter(ffst, s); !iter.Done(); iter.Next()) { const Arc &arc = iter.Value(); KALDI_PARANOID_ASSERT(arc.weight != Weight::Zero()); // note: zero-weight arcs not allowed anyway so weight should not be zero, // but no harm in checking. CompactArc compact_arc(arc.olabel, arc.olabel, CompactWeight(arc.weight, labels[arc.ilabel]), arc.nextstate); ofst->AddArc(s, compact_arc); } } } template void ConvertLattice( const ExpandedFst > > &ifst, MutableFst > *ofst, bool invert) { typedef ArcTpl Arc; typedef typename Arc::StateId StateId; typedef typename Arc::Label Label; typedef CompactLatticeWeightTpl CompactWeight; typedef ArcTpl CompactArc; ofst->DeleteStates(); // make the states in the new FST have the same numbers as // the original ones, and add chains of states as necessary // to encode the string-valued weights. StateId num_states = ifst.NumStates(); for (StateId s = 0; s < num_states; s++) { StateId news = ofst->AddState(); assert(news == s); } ofst->SetStart(ifst.Start()); for (StateId s = 0; s < num_states; s++) { CompactWeight final_weight = ifst.Final(s); if (final_weight != CompactWeight::Zero()) { StateId cur_state = s; size_t string_length = final_weight.String().size(); for (size_t n = 0; n < string_length; n++) { StateId next_state = ofst->AddState(); Label ilabel = 0; Arc arc(ilabel, final_weight.String()[n], (n == 0 ? final_weight.Weight() : Weight::One()), next_state); if (invert) std::swap(arc.ilabel, arc.olabel); ofst->AddArc(cur_state, arc); cur_state = next_state; } ofst->SetFinal(cur_state, string_length > 0 ? Weight::One() : final_weight.Weight()); } for (ArcIterator > iter(ifst, s); !iter.Done(); iter.Next()) { const CompactArc &arc = iter.Value(); size_t string_length = arc.weight.String().size(); StateId cur_state = s; // for all but the last element in the string-- // add a temporary state. for (size_t n = 0 ; n+1 < string_length; n++) { StateId next_state = ofst->AddState(); Label ilabel = (n == 0 ? arc.ilabel : 0), olabel = static_cast