// See www.openfst.org for extensive documentation on this weighted // finite-state transducer library. // // Functions and classes to compute the concatenative closure of an FST. #ifndef FST_CLOSURE_H_ #define FST_CLOSURE_H_ #include #include #include #include namespace fst { // Computes the concatenative closure. This version modifies its // MutableFst input. If an FST transduces string x to y with weight a, // then its closure transduces x to y with weight a, xx to yy with // weight Times(a, a), xxx to yyy with with Times(Times(a, a), a), // etc. If closure_type == CLOSURE_STAR, then the empty string is // transduced to itself with weight Weight::One() as well. // // Complexity: // // Time: O(V) // Space: O(V) // // where V is the number of states. template void Closure(MutableFst *fst, ClosureType closure_type) { using Label = typename Arc::Label; using StateId = typename Arc::StateId; using Weight = typename Arc::Weight; const auto props = fst->Properties(kFstProperties, false); const auto start = fst->Start(); for (StateIterator> siter(*fst); !siter.Done(); siter.Next()) { const auto s = siter.Value(); const auto weight = fst->Final(s); if (weight != Weight::Zero()) fst->AddArc(s, Arc(0, 0, weight, start)); } if (closure_type == CLOSURE_STAR) { fst->ReserveStates(fst->NumStates() + 1); const auto nstart = fst->AddState(); fst->SetStart(nstart); fst->SetFinal(nstart, Weight::One()); if (start != kNoLabel) fst->AddArc(nstart, Arc(0, 0, Weight::One(), start)); } fst->SetProperties(ClosureProperties(props, closure_type == CLOSURE_STAR), kFstProperties); } // Computes the concatenative closure. This version modifies its // RationalFst input. template void Closure(RationalFst *fst, ClosureType closure_type) { fst->GetMutableImpl()->AddClosure(closure_type); } struct ClosureFstOptions : RationalFstOptions { ClosureType type; ClosureFstOptions(const RationalFstOptions &opts, ClosureType type = CLOSURE_STAR) : RationalFstOptions(opts), type(type) {} explicit ClosureFstOptions(ClosureType type = CLOSURE_STAR) : type(type) {} }; // Computes the concatenative closure. This version is a delayed FST. If an FST // transduces string x to y with weight a, then its closure transduces x to y // with weight a, xx to yy with weight Times(a, a), xxx to yyy with weight // Times(Times(a, a), a), etc. If closure_type == CLOSURE_STAR, then the empty // string is transduced to itself with weight Weight::One() as well. // // Complexity: // // Time: O(v) // Space: O(v) // // where v is the number of states visited. Constant time and space to visit an // input state or arc is assumed and exclusive of caching. template class ClosureFst : public RationalFst { public: using Arc = A; ClosureFst(const Fst &fst, ClosureType closure_type) { GetMutableImpl()->InitClosure(fst, closure_type); } ClosureFst(const Fst &fst, const ClosureFstOptions &opts) : RationalFst(opts) { GetMutableImpl()->InitClosure(fst, opts.type); } // See Fst<>::Copy() for doc. ClosureFst(const ClosureFst &fst, bool safe = false) : RationalFst(fst, safe) {} // Gets a copy of this ClosureFst. See Fst<>::Copy() for further doc. ClosureFst *Copy(bool safe = false) const override { return new ClosureFst(*this, safe); } private: using ImplToFst>::GetImpl; using ImplToFst>::GetMutableImpl; }; // Specialization for ClosureFst. template class StateIterator> : public StateIterator> { public: explicit StateIterator(const ClosureFst &fst) : StateIterator>(fst) {} }; // Specialization for ClosureFst. template class ArcIterator> : public ArcIterator> { public: using StateId = typename Arc::StateId; ArcIterator(const ClosureFst &fst, StateId s) : ArcIterator>(fst, s) {} }; // Useful alias when using StdArc. using StdClosureFst = ClosureFst; } // namespace fst #endif // FST_CLOSURE_H_