// rational.h // 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 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Copyright 2005-2010 Google, Inc. // Author: riley@google.com (Michael Riley) // // \file // An Fst implementation and base interface for delayed unions, // concatenations and closures. #ifndef FST_LIB_RATIONAL_H__ #define FST_LIB_RATIONAL_H__ #include #include #include using std::vector; #include #include #include namespace fst { typedef CacheOptions RationalFstOptions; // This specifies whether to add the empty string. enum ClosureType { CLOSURE_STAR = 0, // T* -> add the empty string CLOSURE_PLUS = 1 }; // T+ -> don't add the empty string template class RationalFst; template void Union(RationalFst *fst1, const Fst &fst2); template void Concat(RationalFst *fst1, const Fst &fst2); template void Concat(const Fst &fst1, RationalFst *fst2); template void Closure(RationalFst *fst, ClosureType closure_type); // Implementation class for delayed unions, concatenations and closures. template class RationalFstImpl : public FstImpl { public: using FstImpl::SetType; using FstImpl::SetProperties; using FstImpl::WriteHeader; using FstImpl::SetInputSymbols; using FstImpl::SetOutputSymbols; typedef A Arc; typedef typename A::Weight Weight; typedef typename A::StateId StateId; typedef typename A::Label Label; explicit RationalFstImpl(const RationalFstOptions &opts) : nonterminals_(0), replace_(0), replace_options_(opts, 0) { SetType("rational"); fst_tuples_.push_back(pair*>(0, 0)); } RationalFstImpl(const RationalFstImpl &impl) : rfst_(impl.rfst_), nonterminals_(impl.nonterminals_), replace_(impl.replace_ ? impl.replace_->Copy(true) : 0), replace_options_(impl.replace_options_) { SetType("rational"); fst_tuples_.reserve(impl.fst_tuples_.size()); for (size_t i = 0; i < impl.fst_tuples_.size(); ++i) fst_tuples_.push_back(make_pair(impl.fst_tuples_[i].first, impl.fst_tuples_[i].second ? impl.fst_tuples_[i].second->Copy(true) : 0)); } virtual ~RationalFstImpl() { for (size_t i = 0; i < fst_tuples_.size(); ++i) if (fst_tuples_[i].second) delete fst_tuples_[i].second; if (replace_) delete replace_; } StateId Start() { return Replace()->Start(); } Weight Final(StateId s) { return Replace()->Final(s); } size_t NumArcs(StateId s) { return Replace()->NumArcs(s); } size_t NumInputEpsilons(StateId s) { return Replace()->NumInputEpsilons(s); } size_t NumOutputEpsilons(StateId s) { return Replace()->NumOutputEpsilons(s); } uint64 Properties() const { return Properties(kFstProperties); } // Set error if found; return FST impl properties. uint64 Properties(uint64 mask) const { if ((mask & kError) && Replace()->Properties(kError, false)) SetProperties(kError, kError); return FstImpl::Properties(mask); } // Implementation of UnionFst(fst1,fst2) void InitUnion(const Fst &fst1, const Fst &fst2) { if (replace_) delete replace_; uint64 props1 = fst1.Properties(kFstProperties, false); uint64 props2 = fst2.Properties(kFstProperties, false); SetInputSymbols(fst1.InputSymbols()); SetOutputSymbols(fst1.OutputSymbols()); rfst_.AddState(); rfst_.AddState(); rfst_.SetStart(0); rfst_.SetFinal(1, Weight::One()); rfst_.SetInputSymbols(fst1.InputSymbols()); rfst_.SetOutputSymbols(fst1.OutputSymbols()); nonterminals_ = 2; rfst_.AddArc(0, A(0, -1, Weight::One(), 1)); rfst_.AddArc(0, A(0, -2, Weight::One(), 1)); fst_tuples_.push_back(make_pair(-1, fst1.Copy())); fst_tuples_.push_back(make_pair(-2, fst2.Copy())); SetProperties(UnionProperties(props1, props2, true), kCopyProperties); } // Implementation of ConcatFst(fst1,fst2) void InitConcat(const Fst &fst1, const Fst &fst2) { if (replace_) delete replace_; uint64 props1 = fst1.Properties(kFstProperties, false); uint64 props2 = fst2.Properties(kFstProperties, false); SetInputSymbols(fst1.InputSymbols()); SetOutputSymbols(fst1.OutputSymbols()); rfst_.AddState(); rfst_.AddState(); rfst_.AddState(); rfst_.SetStart(0); rfst_.SetFinal(2, Weight::One()); rfst_.SetInputSymbols(fst1.InputSymbols()); rfst_.SetOutputSymbols(fst1.OutputSymbols()); nonterminals_ = 2; rfst_.AddArc(0, A(0, -1, Weight::One(), 1)); rfst_.AddArc(1, A(0, -2, Weight::One(), 2)); fst_tuples_.push_back(make_pair(-1, fst1.Copy())); fst_tuples_.push_back(make_pair(-2, fst2.Copy())); SetProperties(ConcatProperties(props1, props2, true), kCopyProperties); } // Implementation of ClosureFst(fst, closure_type) void InitClosure(const Fst &fst, ClosureType closure_type) { if (replace_) delete replace_; uint64 props = fst.Properties(kFstProperties, false); SetInputSymbols(fst.InputSymbols()); SetOutputSymbols(fst.OutputSymbols()); if (closure_type == CLOSURE_STAR) { rfst_.AddState(); rfst_.SetStart(0); rfst_.SetFinal(0, Weight::One()); rfst_.AddArc(0, A(0, -1, Weight::One(), 0)); } else { rfst_.AddState(); rfst_.AddState(); rfst_.SetStart(0); rfst_.SetFinal(1, Weight::One()); rfst_.AddArc(0, A(0, -1, Weight::One(), 1)); rfst_.AddArc(1, A(0, 0, Weight::One(), 0)); } rfst_.SetInputSymbols(fst.InputSymbols()); rfst_.SetOutputSymbols(fst.OutputSymbols()); fst_tuples_.push_back(make_pair(-1, fst.Copy())); nonterminals_ = 1; SetProperties(ClosureProperties(props, closure_type == CLOSURE_STAR, true), kCopyProperties); } // Implementation of Union(Fst &, RationalFst *) void AddUnion(const Fst &fst) { if (replace_) delete replace_; uint64 props1 = FstImpl::Properties(); uint64 props2 = fst.Properties(kFstProperties, false); VectorFst afst; afst.AddState(); afst.AddState(); afst.SetStart(0); afst.SetFinal(1, Weight::One()); ++nonterminals_; afst.AddArc(0, A(0, -nonterminals_, Weight::One(), 1)); Union(&rfst_, afst); fst_tuples_.push_back(make_pair(-nonterminals_, fst.Copy())); SetProperties(UnionProperties(props1, props2, true), kCopyProperties); } // Implementation of Concat(Fst &, RationalFst *) void AddConcat(const Fst &fst, bool append) { if (replace_) delete replace_; uint64 props1 = FstImpl::Properties(); uint64 props2 = fst.Properties(kFstProperties, false); VectorFst afst; afst.AddState(); afst.AddState(); afst.SetStart(0); afst.SetFinal(1, Weight::One()); ++nonterminals_; afst.AddArc(0, A(0, -nonterminals_, Weight::One(), 1)); if (append) Concat(&rfst_, afst); else Concat(afst, &rfst_); fst_tuples_.push_back(make_pair(-nonterminals_, fst.Copy())); SetProperties(ConcatProperties(props1, props2, true), kCopyProperties); } // Implementation of Closure(RationalFst *, closure_type) void AddClosure(ClosureType closure_type) { if (replace_) delete replace_; uint64 props = FstImpl::Properties(); Closure(&rfst_, closure_type); SetProperties(ClosureProperties(props, closure_type == CLOSURE_STAR, true), kCopyProperties); } // Returns the underlying ReplaceFst. ReplaceFst *Replace() const { if (!replace_) { fst_tuples_[0].second = rfst_.Copy(); replace_ = new ReplaceFst(fst_tuples_, replace_options_); } return replace_; } private: VectorFst rfst_; // rational topology machine; uses neg. nonterminals Label nonterminals_; // # of nonterminals used // Contains the nonterminals and their corresponding FSTs. mutable vector*> > fst_tuples_; mutable ReplaceFst *replace_; // Underlying ReplaceFst ReplaceFstOptions replace_options_; // Options for creating 'replace_' void operator=(const RationalFstImpl &impl); // disallow }; // Parent class for the delayed rational operations - delayed union, // concatenation, and closure. // // This class attaches interface to implementation and handles // reference counting, delegating most methods to ImplToFst. template class RationalFst : public ImplToFst< RationalFstImpl > { public: friend class StateIterator< RationalFst >; friend class ArcIterator< RationalFst >; friend void Union<>(RationalFst *fst1, const Fst &fst2); friend void Concat<>(RationalFst *fst1, const Fst &fst2); friend void Concat<>(const Fst &fst1, RationalFst *fst2); friend void Closure<>(RationalFst *fst, ClosureType closure_type); typedef A Arc; typedef typename A::StateId StateId; typedef RationalFstImpl Impl; virtual void InitStateIterator(StateIteratorData *data) const { GetImpl()->Replace()->InitStateIterator(data); } virtual void InitArcIterator(StateId s, ArcIteratorData *data) const { GetImpl()->Replace()->InitArcIterator(s, data); } protected: RationalFst() : ImplToFst(new Impl(RationalFstOptions())) {} explicit RationalFst(const RationalFstOptions &opts) : ImplToFst(new Impl(opts)) {} // See Fst<>::Copy() for doc. RationalFst(const RationalFst &fst , bool safe = false) : ImplToFst(fst, safe) {} private: // Makes visible to friends. Impl *GetImpl() const { return ImplToFst::GetImpl(); } void operator=(const RationalFst &fst); // disallow }; // Specialization for RationalFst. template class StateIterator< RationalFst > : public StateIterator< ReplaceFst > { public: explicit StateIterator(const RationalFst &fst) : StateIterator< ReplaceFst >(*(fst.GetImpl()->Replace())) {} }; // Specialization for RationalFst. template class ArcIterator< RationalFst > : public CacheArcIterator< ReplaceFst > { public: typedef typename A::StateId StateId; ArcIterator(const RationalFst &fst, StateId s) : ArcIterator< ReplaceFst >(*(fst.GetImpl()->Replace()), s) {} }; } // namespace fst #endif // FST_LIB_RATIONAL_H__