From 96a32415ab43377cf1575bd3f4f2980f58028209 Mon Sep 17 00:00:00 2001 From: Determinant Date: Fri, 14 Aug 2015 11:51:42 +0800 Subject: add implementation for kaldi io (by ymz) --- kaldi_io/src/tools/openfst/include/fst/arc-map.h | 1146 ++++++++++++++++++++++ 1 file changed, 1146 insertions(+) create mode 100644 kaldi_io/src/tools/openfst/include/fst/arc-map.h (limited to 'kaldi_io/src/tools/openfst/include/fst/arc-map.h') diff --git a/kaldi_io/src/tools/openfst/include/fst/arc-map.h b/kaldi_io/src/tools/openfst/include/fst/arc-map.h new file mode 100644 index 0000000..914f81c --- /dev/null +++ b/kaldi_io/src/tools/openfst/include/fst/arc-map.h @@ -0,0 +1,1146 @@ +// arc-map.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 +// Class to map over/transform arcs e.g., change semirings or +// implement project/invert. Consider using when operation does +// not change the number of arcs (except possibly superfinal arcs). + +#ifndef FST_LIB_ARC_MAP_H__ +#define FST_LIB_ARC_MAP_H__ + +#include +using std::tr1::unordered_map; +using std::tr1::unordered_multimap; +#include +#include +using std::pair; using std::make_pair; + +#include +#include + + +namespace fst { + +// This determines how final weights are mapped. +enum MapFinalAction { + // A final weight is mapped into a final weight. An error + // is raised if this is not possible. + MAP_NO_SUPERFINAL, + + // A final weight is mapped to an arc to the superfinal state + // when the result cannot be represented as a final weight. + // The superfinal state will be added only if it is needed. + MAP_ALLOW_SUPERFINAL, + + // A final weight is mapped to an arc to the superfinal state + // unless the result can be represented as a final weight of weight + // Zero(). The superfinal state is always added (if the input is + // not the empty Fst). + MAP_REQUIRE_SUPERFINAL +}; + +// This determines how symbol tables are mapped. +enum MapSymbolsAction { + // Symbols should be cleared in the result by the map. + MAP_CLEAR_SYMBOLS, + + // Symbols should be copied from the input FST by the map. + MAP_COPY_SYMBOLS, + + // Symbols should not be modified in the result by the map itself. + // (They may set by the mapper). + MAP_NOOP_SYMBOLS +}; + +// ArcMapper Interface - class determinies how arcs and final weights +// are mapped. Useful for implementing operations that do not change +// the number of arcs (expect possibly superfinal arcs). +// +// class ArcMapper { +// public: +// typedef A FromArc; +// typedef B ToArc; +// +// // Maps an arc type A to arc type B. +// B operator()(const A &arc); +// // Specifies final action the mapper requires (see above). +// // The mapper will be passed final weights as arcs of the +// // form A(0, 0, weight, kNoStateId). +// MapFinalAction FinalAction() const; +// // Specifies input symbol table action the mapper requires (see above). +// MapSymbolsAction InputSymbolsAction() const; +// // Specifies output symbol table action the mapper requires (see above). +// MapSymbolsAction OutputSymbolsAction() const; +// // This specifies the known properties of an Fst mapped by this +// // mapper. It takes as argument the input Fst's known properties. +// uint64 Properties(uint64 props) const; +// }; +// +// The ArcMap functions and classes below will use the FinalAction() +// method of the mapper to determine how to treat final weights, +// e.g. whether to add a superfinal state. They will use the Properties() +// method to set the result Fst properties. +// +// We include a various map versions below. One dimension of +// variation is whether the mapping mutates its input, writes to a +// new result Fst, or is an on-the-fly Fst. Another dimension is how +// we pass the mapper. We allow passing the mapper by pointer +// for cases that we need to change the state of the user's mapper. +// This is the case with the encode mapper, which is reused during +// decoding. We also include map versions that pass the mapper +// by value or const reference when this suffices. + + +// Maps an arc type A using a mapper function object C, passed +// by pointer. This version modifies its Fst input. +template +void ArcMap(MutableFst *fst, C* mapper) { + typedef typename A::StateId StateId; + typedef typename A::Weight Weight; + + if (mapper->InputSymbolsAction() == MAP_CLEAR_SYMBOLS) + fst->SetInputSymbols(0); + + if (mapper->OutputSymbolsAction() == MAP_CLEAR_SYMBOLS) + fst->SetOutputSymbols(0); + + if (fst->Start() == kNoStateId) + return; + + uint64 props = fst->Properties(kFstProperties, false); + + MapFinalAction final_action = mapper->FinalAction(); + StateId superfinal = kNoStateId; + if (final_action == MAP_REQUIRE_SUPERFINAL) { + superfinal = fst->AddState(); + fst->SetFinal(superfinal, Weight::One()); + } + + for (StateId s = 0; s < fst->NumStates(); ++s) { + for (MutableArcIterator< MutableFst > aiter(fst, s); + !aiter.Done(); aiter.Next()) { + const A &arc = aiter.Value(); + aiter.SetValue((*mapper)(arc)); + } + + switch (final_action) { + case MAP_NO_SUPERFINAL: + default: { + A final_arc = (*mapper)(A(0, 0, fst->Final(s), kNoStateId)); + if (final_arc.ilabel != 0 || final_arc.olabel != 0) { + FSTERROR() << "ArcMap: non-zero arc labels for superfinal arc"; + fst->SetProperties(kError, kError); + } + + fst->SetFinal(s, final_arc.weight); + break; + } + case MAP_ALLOW_SUPERFINAL: { + if (s != superfinal) { + A final_arc = (*mapper)(A(0, 0, fst->Final(s), kNoStateId)); + if (final_arc.ilabel != 0 || final_arc.olabel != 0) { + // Add a superfinal state if not already done. + if (superfinal == kNoStateId) { + superfinal = fst->AddState(); + fst->SetFinal(superfinal, Weight::One()); + } + final_arc.nextstate = superfinal; + fst->AddArc(s, final_arc); + fst->SetFinal(s, Weight::Zero()); + } else { + fst->SetFinal(s, final_arc.weight); + } + break; + } + } + case MAP_REQUIRE_SUPERFINAL: { + if (s != superfinal) { + A final_arc = (*mapper)(A(0, 0, fst->Final(s), kNoStateId)); + if (final_arc.ilabel != 0 || final_arc.olabel != 0 || + final_arc.weight != Weight::Zero()) + fst->AddArc(s, A(final_arc.ilabel, final_arc.olabel, + final_arc.weight, superfinal)); + fst->SetFinal(s, Weight::Zero()); + } + break; + } + } + } + fst->SetProperties(mapper->Properties(props), kFstProperties); +} + + +// Maps an arc type A using a mapper function object C, passed +// by value. This version modifies its Fst input. +template +void ArcMap(MutableFst *fst, C mapper) { + ArcMap(fst, &mapper); +} + + +// Maps an arc type A to an arc type B using mapper function +// object C, passed by pointer. This version writes the mapped +// input Fst to an output MutableFst. +template +void ArcMap(const Fst &ifst, MutableFst *ofst, C* mapper) { + typedef typename A::StateId StateId; + typedef typename A::Weight Weight; + + ofst->DeleteStates(); + + if (mapper->InputSymbolsAction() == MAP_COPY_SYMBOLS) + ofst->SetInputSymbols(ifst.InputSymbols()); + else if (mapper->InputSymbolsAction() == MAP_CLEAR_SYMBOLS) + ofst->SetInputSymbols(0); + + if (mapper->OutputSymbolsAction() == MAP_COPY_SYMBOLS) + ofst->SetOutputSymbols(ifst.OutputSymbols()); + else if (mapper->OutputSymbolsAction() == MAP_CLEAR_SYMBOLS) + ofst->SetOutputSymbols(0); + + uint64 iprops = ifst.Properties(kCopyProperties, false); + + if (ifst.Start() == kNoStateId) { + if (iprops & kError) ofst->SetProperties(kError, kError); + return; + } + + MapFinalAction final_action = mapper->FinalAction(); + if (ifst.Properties(kExpanded, false)) { + ofst->ReserveStates(CountStates(ifst) + + final_action == MAP_NO_SUPERFINAL ? 0 : 1); + } + + // Add all states. + for (StateIterator< Fst > siter(ifst); !siter.Done(); siter.Next()) + ofst->AddState(); + + StateId superfinal = kNoStateId; + if (final_action == MAP_REQUIRE_SUPERFINAL) { + superfinal = ofst->AddState(); + ofst->SetFinal(superfinal, B::Weight::One()); + } + for (StateIterator< Fst > siter(ifst); !siter.Done(); siter.Next()) { + StateId s = siter.Value(); + if (s == ifst.Start()) + ofst->SetStart(s); + + ofst->ReserveArcs(s, ifst.NumArcs(s)); + for (ArcIterator< Fst > aiter(ifst, s); !aiter.Done(); aiter.Next()) + ofst->AddArc(s, (*mapper)(aiter.Value())); + + switch (final_action) { + case MAP_NO_SUPERFINAL: + default: { + B final_arc = (*mapper)(A(0, 0, ifst.Final(s), kNoStateId)); + if (final_arc.ilabel != 0 || final_arc.olabel != 0) { + FSTERROR() << "ArcMap: non-zero arc labels for superfinal arc"; + ofst->SetProperties(kError, kError); + } + ofst->SetFinal(s, final_arc.weight); + break; + } + case MAP_ALLOW_SUPERFINAL: { + B final_arc = (*mapper)(A(0, 0, ifst.Final(s), kNoStateId)); + if (final_arc.ilabel != 0 || final_arc.olabel != 0) { + // Add a superfinal state if not already done. + if (superfinal == kNoStateId) { + superfinal = ofst->AddState(); + ofst->SetFinal(superfinal, B::Weight::One()); + } + final_arc.nextstate = superfinal; + ofst->AddArc(s, final_arc); + ofst->SetFinal(s, B::Weight::Zero()); + } else { + ofst->SetFinal(s, final_arc.weight); + } + break; + } + case MAP_REQUIRE_SUPERFINAL: { + B final_arc = (*mapper)(A(0, 0, ifst.Final(s), kNoStateId)); + if (final_arc.ilabel != 0 || final_arc.olabel != 0 || + final_arc.weight != B::Weight::Zero()) + ofst->AddArc(s, B(final_arc.ilabel, final_arc.olabel, + final_arc.weight, superfinal)); + ofst->SetFinal(s, B::Weight::Zero()); + break; + } + } + } + uint64 oprops = ofst->Properties(kFstProperties, false); + ofst->SetProperties(mapper->Properties(iprops) | oprops, kFstProperties); +} + +// Maps an arc type A to an arc type B using mapper function +// object C, passed by value. This version writes the mapped input +// Fst to an output MutableFst. +template +void ArcMap(const Fst &ifst, MutableFst *ofst, C mapper) { + ArcMap(ifst, ofst, &mapper); +} + + +struct ArcMapFstOptions : public CacheOptions { + // ArcMapFst default caching behaviour is to do no caching. Most + // mappers are cheap and therefore we save memory by not doing + // caching. + ArcMapFstOptions() : CacheOptions(true, 0) {} + ArcMapFstOptions(const CacheOptions& opts) : CacheOptions(opts) {} +}; + + +template class ArcMapFst; + +// Implementation of delayed ArcMapFst. +template +class ArcMapFstImpl : public CacheImpl { + public: + using FstImpl::SetType; + using FstImpl::SetProperties; + using FstImpl::SetInputSymbols; + using FstImpl::SetOutputSymbols; + + using VectorFstBaseImpl::State>::NumStates; + + using CacheImpl::PushArc; + using CacheImpl::HasArcs; + using CacheImpl::HasFinal; + using CacheImpl::HasStart; + using CacheImpl::SetArcs; + using CacheImpl::SetFinal; + using CacheImpl::SetStart; + + friend class StateIterator< ArcMapFst >; + + typedef B Arc; + typedef typename B::Weight Weight; + typedef typename B::StateId StateId; + + ArcMapFstImpl(const Fst &fst, const C &mapper, + const ArcMapFstOptions& opts) + : CacheImpl(opts), + fst_(fst.Copy()), + mapper_(new C(mapper)), + own_mapper_(true), + superfinal_(kNoStateId), + nstates_(0) { + Init(); + } + + ArcMapFstImpl(const Fst &fst, C *mapper, + const ArcMapFstOptions& opts) + : CacheImpl(opts), + fst_(fst.Copy()), + mapper_(mapper), + own_mapper_(false), + superfinal_(kNoStateId), + nstates_(0) { + Init(); + } + + ArcMapFstImpl(const ArcMapFstImpl &impl) + : CacheImpl(impl), + fst_(impl.fst_->Copy(true)), + mapper_(new C(*impl.mapper_)), + own_mapper_(true), + superfinal_(kNoStateId), + nstates_(0) { + Init(); + } + + ~ArcMapFstImpl() { + delete fst_; + if (own_mapper_) delete mapper_; + } + + StateId Start() { + if (!HasStart()) + SetStart(FindOState(fst_->Start())); + return CacheImpl::Start(); + } + + Weight Final(StateId s) { + if (!HasFinal(s)) { + switch (final_action_) { + case MAP_NO_SUPERFINAL: + default: { + B final_arc = (*mapper_)(A(0, 0, fst_->Final(FindIState(s)), + kNoStateId)); + if (final_arc.ilabel != 0 || final_arc.olabel != 0) { + FSTERROR() << "ArcMapFst: non-zero arc labels for superfinal arc"; + SetProperties(kError, kError); + } + SetFinal(s, final_arc.weight); + break; + } + case MAP_ALLOW_SUPERFINAL: { + if (s == superfinal_) { + SetFinal(s, Weight::One()); + } else { + B final_arc = (*mapper_)(A(0, 0, fst_->Final(FindIState(s)), + kNoStateId)); + if (final_arc.ilabel == 0 && final_arc.olabel == 0) + SetFinal(s, final_arc.weight); + else + SetFinal(s, Weight::Zero()); + } + break; + } + case MAP_REQUIRE_SUPERFINAL: { + SetFinal(s, s == superfinal_ ? Weight::One() : Weight::Zero()); + break; + } + } + } + return CacheImpl::Final(s); + } + + size_t NumArcs(StateId s) { + if (!HasArcs(s)) + Expand(s); + return CacheImpl::NumArcs(s); + } + + size_t NumInputEpsilons(StateId s) { + if (!HasArcs(s)) + Expand(s); + return CacheImpl::NumInputEpsilons(s); + } + + size_t NumOutputEpsilons(StateId s) { + if (!HasArcs(s)) + Expand(s); + return CacheImpl::NumOutputEpsilons(s); + } + + uint64 Properties() const { return Properties(kFstProperties); } + + // Set error if found; return FST impl properties. + uint64 Properties(uint64 mask) const { + if ((mask & kError) && (fst_->Properties(kError, false) || + (mapper_->Properties(0) & kError))) + SetProperties(kError, kError); + return FstImpl::Properties(mask); + } + + void InitArcIterator(StateId s, ArcIteratorData *data) { + if (!HasArcs(s)) + Expand(s); + CacheImpl::InitArcIterator(s, data); + } + + void Expand(StateId s) { + // Add exiting arcs. + if (s == superfinal_) { SetArcs(s); return; } + + for (ArcIterator< Fst > aiter(*fst_, FindIState(s)); + !aiter.Done(); aiter.Next()) { + A aarc(aiter.Value()); + aarc.nextstate = FindOState(aarc.nextstate); + const B& barc = (*mapper_)(aarc); + PushArc(s, barc); + } + + // Check for superfinal arcs. + if (!HasFinal(s) || Final(s) == Weight::Zero()) + switch (final_action_) { + case MAP_NO_SUPERFINAL: + default: + break; + case MAP_ALLOW_SUPERFINAL: { + B final_arc = (*mapper_)(A(0, 0, fst_->Final(FindIState(s)), + kNoStateId)); + if (final_arc.ilabel != 0 || final_arc.olabel != 0) { + if (superfinal_ == kNoStateId) + superfinal_ = nstates_++; + final_arc.nextstate = superfinal_; + PushArc(s, final_arc); + } + break; + } + case MAP_REQUIRE_SUPERFINAL: { + B final_arc = (*mapper_)(A(0, 0, fst_->Final(FindIState(s)), + kNoStateId)); + if (final_arc.ilabel != 0 || final_arc.olabel != 0 || + final_arc.weight != B::Weight::Zero()) + PushArc(s, B(final_arc.ilabel, final_arc.olabel, + final_arc.weight, superfinal_)); + break; + } + } + SetArcs(s); + } + + private: + void Init() { + SetType("map"); + + if (mapper_->InputSymbolsAction() == MAP_COPY_SYMBOLS) + SetInputSymbols(fst_->InputSymbols()); + else if (mapper_->InputSymbolsAction() == MAP_CLEAR_SYMBOLS) + SetInputSymbols(0); + + if (mapper_->OutputSymbolsAction() == MAP_COPY_SYMBOLS) + SetOutputSymbols(fst_->OutputSymbols()); + else if (mapper_->OutputSymbolsAction() == MAP_CLEAR_SYMBOLS) + SetOutputSymbols(0); + + if (fst_->Start() == kNoStateId) { + final_action_ = MAP_NO_SUPERFINAL; + SetProperties(kNullProperties); + } else { + final_action_ = mapper_->FinalAction(); + uint64 props = fst_->Properties(kCopyProperties, false); + SetProperties(mapper_->Properties(props)); + if (final_action_ == MAP_REQUIRE_SUPERFINAL) + superfinal_ = 0; + } + } + + // Maps from output state to input state. + StateId FindIState(StateId s) { + if (superfinal_ == kNoStateId || s < superfinal_) + return s; + else + return s - 1; + } + + // Maps from input state to output state. + StateId FindOState(StateId is) { + StateId os; + if (superfinal_ == kNoStateId || is < superfinal_) + os = is; + else + os = is + 1; + + if (os >= nstates_) + nstates_ = os + 1; + + return os; + } + + + const Fst *fst_; + C* mapper_; + bool own_mapper_; + MapFinalAction final_action_; + + StateId superfinal_; + StateId nstates_; + + void operator=(const ArcMapFstImpl &); // disallow +}; + + +// Maps an arc type A to an arc type B using Mapper function object +// C. This version is a delayed Fst. +template +class ArcMapFst : public ImplToFst< ArcMapFstImpl > { + public: + friend class ArcIterator< ArcMapFst >; + friend class StateIterator< ArcMapFst >; + + typedef B Arc; + typedef typename B::Weight Weight; + typedef typename B::StateId StateId; + typedef CacheState State; + typedef ArcMapFstImpl Impl; + + ArcMapFst(const Fst &fst, const C &mapper, const ArcMapFstOptions& opts) + : ImplToFst(new Impl(fst, mapper, opts)) {} + + ArcMapFst(const Fst &fst, C* mapper, const ArcMapFstOptions& opts) + : ImplToFst(new Impl(fst, mapper, opts)) {} + + ArcMapFst(const Fst &fst, const C &mapper) + : ImplToFst(new Impl(fst, mapper, ArcMapFstOptions())) {} + + ArcMapFst(const Fst &fst, C* mapper) + : ImplToFst(new Impl(fst, mapper, ArcMapFstOptions())) {} + + // See Fst<>::Copy() for doc. + ArcMapFst(const ArcMapFst &fst, bool safe = false) + : ImplToFst(fst, safe) {} + + // Get a copy of this ArcMapFst. See Fst<>::Copy() for further doc. + virtual ArcMapFst *Copy(bool safe = false) const { + return new ArcMapFst(*this, safe); + } + + virtual inline void InitStateIterator(StateIteratorData *data) const; + + virtual void InitArcIterator(StateId s, ArcIteratorData *data) const { + GetImpl()->InitArcIterator(s, data); + } + + private: + // Makes visible to friends. + Impl *GetImpl() const { return ImplToFst::GetImpl(); } + + void operator=(const ArcMapFst &fst); // disallow +}; + + +// Specialization for ArcMapFst. +template +class StateIterator< ArcMapFst > : public StateIteratorBase { + public: + typedef typename B::StateId StateId; + + explicit StateIterator(const ArcMapFst &fst) + : impl_(fst.GetImpl()), siter_(*impl_->fst_), s_(0), + superfinal_(impl_->final_action_ == MAP_REQUIRE_SUPERFINAL) + { CheckSuperfinal(); } + + bool Done() const { return siter_.Done() && !superfinal_; } + + StateId Value() const { return s_; } + + void Next() { + ++s_; + if (!siter_.Done()) { + siter_.Next(); + CheckSuperfinal(); + } + else if (superfinal_) + superfinal_ = false; + } + + void Reset() { + s_ = 0; + siter_.Reset(); + superfinal_ = impl_->final_action_ == MAP_REQUIRE_SUPERFINAL; + CheckSuperfinal(); + } + + private: + // This allows base-class virtual access to non-virtual derived- + // class members of the same name. It makes the derived class more + // efficient to use but unsafe to further derive. + bool Done_() const { return Done(); } + StateId Value_() const { return Value(); } + void Next_() { Next(); } + void Reset_() { Reset(); } + + void CheckSuperfinal() { + if (impl_->final_action_ != MAP_ALLOW_SUPERFINAL || superfinal_) + return; + if (!siter_.Done()) { + B final_arc = (*impl_->mapper_)(A(0, 0, impl_->fst_->Final(s_), + kNoStateId)); + if (final_arc.ilabel != 0 || final_arc.olabel != 0) + superfinal_ = true; + } + } + + const ArcMapFstImpl *impl_; + StateIterator< Fst > siter_; + StateId s_; + bool superfinal_; // true if there is a superfinal state and not done + + DISALLOW_COPY_AND_ASSIGN(StateIterator); +}; + + +// Specialization for ArcMapFst. +template +class ArcIterator< ArcMapFst > + : public CacheArcIterator< ArcMapFst > { + public: + typedef typename A::StateId StateId; + + ArcIterator(const ArcMapFst &fst, StateId s) + : CacheArcIterator< ArcMapFst >(fst.GetImpl(), s) { + if (!fst.GetImpl()->HasArcs(s)) + fst.GetImpl()->Expand(s); + } + + private: + DISALLOW_COPY_AND_ASSIGN(ArcIterator); +}; + +template inline +void ArcMapFst::InitStateIterator(StateIteratorData *data) + const { + data->base = new StateIterator< ArcMapFst >(*this); +} + + +// +// Utility Mappers +// + +// Mapper that returns its input. +template +struct IdentityArcMapper { + typedef A FromArc; + typedef A ToArc; + + A operator()(const A &arc) const { return arc; } + + MapFinalAction FinalAction() const { return MAP_NO_SUPERFINAL; } + + MapSymbolsAction InputSymbolsAction() const { return MAP_COPY_SYMBOLS; } + + MapSymbolsAction OutputSymbolsAction() const { return MAP_COPY_SYMBOLS;} + + uint64 Properties(uint64 props) const { return props; } +}; + + +// Mapper that returns its input with final states redirected to +// a single super-final state. +template +struct SuperFinalMapper { + typedef A FromArc; + typedef A ToArc; + + A operator()(const A &arc) const { return arc; } + + MapFinalAction FinalAction() const { return MAP_REQUIRE_SUPERFINAL; } + + MapSymbolsAction InputSymbolsAction() const { return MAP_COPY_SYMBOLS; } + + MapSymbolsAction OutputSymbolsAction() const { return MAP_COPY_SYMBOLS;} + + uint64 Properties(uint64 props) const { + return props & kAddSuperFinalProperties; + } +}; + + +// Mapper that leaves labels and nextstate unchanged and constructs a new weight +// from the underlying value of the arc weight. Requires that there is a +// WeightConvert class specialization that converts the weights. +template +class WeightConvertMapper { + public: + typedef A FromArc; + typedef B ToArc; + typedef typename FromArc::Weight FromWeight; + typedef typename ToArc::Weight ToWeight; + + ToArc operator()(const FromArc &arc) const { + return ToArc(arc.ilabel, arc.olabel, + convert_weight_(arc.weight), arc.nextstate); + } + + MapFinalAction FinalAction() const { return MAP_NO_SUPERFINAL; } + + MapSymbolsAction InputSymbolsAction() const { return MAP_COPY_SYMBOLS; } + + MapSymbolsAction OutputSymbolsAction() const { return MAP_COPY_SYMBOLS;} + + uint64 Properties(uint64 props) const { return props; } + + private: + WeightConvert convert_weight_; +}; + +// Non-precision-changing weight conversions. +// Consider using more efficient Cast (fst.h) instead. +typedef WeightConvertMapper StdToLogMapper; +typedef WeightConvertMapper LogToStdMapper; + +// Precision-changing weight conversions. +typedef WeightConvertMapper StdToLog64Mapper; +typedef WeightConvertMapper LogToLog64Mapper; +typedef WeightConvertMapper Log64ToStdMapper; +typedef WeightConvertMapper Log64ToLogMapper; + +// Mapper from A to GallicArc. +template +struct ToGallicMapper { + typedef A FromArc; + typedef GallicArc ToArc; + + typedef StringWeight SW; + typedef typename A::Weight AW; + typedef typename GallicArc::Weight GW; + + ToArc operator()(const A &arc) const { + // 'Super-final' arc. + if (arc.nextstate == kNoStateId && arc.weight != AW::Zero()) + return ToArc(0, 0, GW(SW::One(), arc.weight), kNoStateId); + // 'Super-non-final' arc. + else if (arc.nextstate == kNoStateId) + return ToArc(0, 0, GW(SW::Zero(), arc.weight), kNoStateId); + // Epsilon label. + else if (arc.olabel == 0) + return ToArc(arc.ilabel, arc.ilabel, + GW(SW::One(), arc.weight), arc.nextstate); + // Regular label. + else + return ToArc(arc.ilabel, arc.ilabel, + GW(SW(arc.olabel), arc.weight), arc.nextstate); + } + + MapFinalAction FinalAction() const { return MAP_NO_SUPERFINAL; } + + MapSymbolsAction InputSymbolsAction() const { return MAP_COPY_SYMBOLS; } + + MapSymbolsAction OutputSymbolsAction() const { return MAP_CLEAR_SYMBOLS;} + + uint64 Properties(uint64 props) const { + return ProjectProperties(props, true) & kWeightInvariantProperties; + } +}; + + +// Mapper from GallicArc to A. +template +struct FromGallicMapper { + typedef GallicArc FromArc; + typedef A ToArc; + + typedef typename A::Label Label; + typedef StringWeight SW; + typedef typename A::Weight AW; + typedef typename GallicArc::Weight GW; + + FromGallicMapper(Label superfinal_label = 0) + : superfinal_label_(superfinal_label), error_(false) {} + + A operator()(const FromArc &arc) const { + // 'Super-non-final' arc. + if (arc.nextstate == kNoStateId && arc.weight == GW::Zero()) + return A(arc.ilabel, 0, AW::Zero(), kNoStateId); + + SW w1 = arc.weight.Value1(); + AW w2 = arc.weight.Value2(); + StringWeightIterator iter1(w1); + + Label l = w1.Size() == 1 ? iter1.Value() : 0; + + if (l == kStringInfinity || l == kStringBad || + arc.ilabel != arc.olabel || w1.Size() > 1) { + FSTERROR() << "FromGallicMapper: unrepesentable weight"; + error_ = true; + } + + if (arc.ilabel == 0 && l != 0 && arc.nextstate == kNoStateId) + return A(superfinal_label_, l, w2, arc.nextstate); + else + return A(arc.ilabel, l, w2, arc.nextstate); + } + + MapFinalAction FinalAction() const { return MAP_ALLOW_SUPERFINAL; } + + MapSymbolsAction InputSymbolsAction() const { return MAP_COPY_SYMBOLS; } + + MapSymbolsAction OutputSymbolsAction() const { return MAP_CLEAR_SYMBOLS;} + + uint64 Properties(uint64 inprops) const { + uint64 outprops = inprops & kOLabelInvariantProperties & + kWeightInvariantProperties & kAddSuperFinalProperties; + if (error_) + outprops |= kError; + return outprops; + } + + private: + Label superfinal_label_; + mutable bool error_; +}; + + +// Mapper from GallicArc to A. +template +struct GallicToNewSymbolsMapper { + typedef GallicArc FromArc; + typedef A ToArc; + + typedef typename A::StateId StateId; + typedef typename A::Label Label; + typedef StringWeight SW; + typedef typename A::Weight AW; + typedef typename GallicArc::Weight GW; + + GallicToNewSymbolsMapper(MutableFst *fst) + : fst_(fst), lmax_(0), osymbols_(fst->OutputSymbols()), + isymbols_(0), error_(false) { + fst_->DeleteStates(); + state_ = fst_->AddState(); + fst_->SetStart(state_); + fst_->SetFinal(state_, AW::One()); + if (osymbols_) { + string name = osymbols_->Name() + "_from_gallic"; + fst_->SetInputSymbols(new SymbolTable(name)); + isymbols_ = fst_->MutableInputSymbols(); + isymbols_->AddSymbol(osymbols_->Find((int64) 0), 0); + } else { + fst_->SetInputSymbols(0); + } + } + + A operator()(const FromArc &arc) { + // 'Super-non-final' arc. + if (arc.nextstate == kNoStateId && arc.weight == GW::Zero()) + return A(arc.ilabel, 0, AW::Zero(), kNoStateId); + + SW w1 = arc.weight.Value1(); + AW w2 = arc.weight.Value2(); + Label l; + + if (w1.Size() == 0) { + l = 0; + } else { + typename Map::iterator miter = map_.find(w1); + if (miter != map_.end()) { + l = (*miter).second; + } else { + l = ++lmax_; + map_.insert(pair(w1, l)); + StringWeightIterator iter1(w1); + StateId n; + string s; + for(size_t i = 0, p = state_; + i < w1.Size(); + ++i, iter1.Next(), p = n) { + n = i == w1.Size() - 1 ? state_ : fst_->AddState(); + fst_->AddArc(p, ToArc(i ? 0 : l, iter1.Value(), AW::One(), n)); + if (isymbols_) { + if (i) s = s + "_"; + s = s + osymbols_->Find(iter1.Value()); + } + } + if (isymbols_) + isymbols_->AddSymbol(s, l); + } + } + + if (l == kStringInfinity || l == kStringBad || arc.ilabel != arc.olabel) { + FSTERROR() << "GallicToNewSymbolMapper: unrepesentable weight"; + error_ = true; + } + + return A(arc.ilabel, l, w2, arc.nextstate); + } + + MapFinalAction FinalAction() const { return MAP_ALLOW_SUPERFINAL; } + + MapSymbolsAction InputSymbolsAction() const { return MAP_COPY_SYMBOLS; } + + MapSymbolsAction OutputSymbolsAction() const { return MAP_CLEAR_SYMBOLS; } + + uint64 Properties(uint64 inprops) const { + uint64 outprops = inprops & kOLabelInvariantProperties & + kWeightInvariantProperties & kAddSuperFinalProperties; + if (error_) + outprops |= kError; + return outprops; + } + + private: + class StringKey { + public: + size_t operator()(const SW &x) const { + return x.Hash(); + } + }; + + typedef unordered_map Map; + + MutableFst *fst_; + Map map_; + Label lmax_; + StateId state_; + const SymbolTable *osymbols_; + SymbolTable *isymbols_; + mutable bool error_; + + DISALLOW_COPY_AND_ASSIGN(GallicToNewSymbolsMapper); +}; + + +// Mapper to add a constant to all weights. +template +struct PlusMapper { + typedef A FromArc; + typedef A ToArc; + typedef typename A::Weight Weight; + + explicit PlusMapper(Weight w) : weight_(w) {} + + A operator()(const A &arc) const { + if (arc.weight == Weight::Zero()) + return arc; + Weight w = Plus(arc.weight, weight_); + return A(arc.ilabel, arc.olabel, w, arc.nextstate); + } + + MapFinalAction FinalAction() const { return MAP_NO_SUPERFINAL; } + + MapSymbolsAction InputSymbolsAction() const { return MAP_COPY_SYMBOLS; } + + MapSymbolsAction OutputSymbolsAction() const { return MAP_COPY_SYMBOLS;} + + uint64 Properties(uint64 props) const { + return props & kWeightInvariantProperties; + } + + private: + + + + Weight weight_; +}; + + +// Mapper to (right) multiply a constant to all weights. +template +struct TimesMapper { + typedef A FromArc; + typedef A ToArc; + typedef typename A::Weight Weight; + + explicit TimesMapper(Weight w) : weight_(w) {} + + A operator()(const A &arc) const { + if (arc.weight == Weight::Zero()) + return arc; + Weight w = Times(arc.weight, weight_); + return A(arc.ilabel, arc.olabel, w, arc.nextstate); + } + + MapFinalAction FinalAction() const { return MAP_NO_SUPERFINAL; } + + MapSymbolsAction InputSymbolsAction() const { return MAP_COPY_SYMBOLS; } + + MapSymbolsAction OutputSymbolsAction() const { return MAP_COPY_SYMBOLS;} + + uint64 Properties(uint64 props) const { + return props & kWeightInvariantProperties; + } + + private: + Weight weight_; +}; + + +// Mapper to reciprocate all non-Zero() weights. +template +struct InvertWeightMapper { + typedef A FromArc; + typedef A ToArc; + typedef typename A::Weight Weight; + + A operator()(const A &arc) const { + if (arc.weight == Weight::Zero()) + return arc; + Weight w = Divide(Weight::One(), arc.weight); + return A(arc.ilabel, arc.olabel, w, arc.nextstate); + } + + MapFinalAction FinalAction() const { return MAP_NO_SUPERFINAL; } + + MapSymbolsAction InputSymbolsAction() const { return MAP_COPY_SYMBOLS; } + + MapSymbolsAction OutputSymbolsAction() const { return MAP_COPY_SYMBOLS;} + + uint64 Properties(uint64 props) const { + return props & kWeightInvariantProperties; + } +}; + + +// Mapper to map all non-Zero() weights to One(). +template +struct RmWeightMapper { + typedef A FromArc; + typedef B ToArc; + typedef typename FromArc::Weight FromWeight; + typedef typename ToArc::Weight ToWeight; + + B operator()(const A &arc) const { + ToWeight w = arc.weight != FromWeight::Zero() ? + ToWeight::One() : ToWeight::Zero(); + return B(arc.ilabel, arc.olabel, w, arc.nextstate); + } + + MapFinalAction FinalAction() const { return MAP_NO_SUPERFINAL; } + + MapSymbolsAction InputSymbolsAction() const { return MAP_COPY_SYMBOLS; } + + MapSymbolsAction OutputSymbolsAction() const { return MAP_COPY_SYMBOLS;} + + uint64 Properties(uint64 props) const { + return (props & kWeightInvariantProperties) | kUnweighted; + } +}; + + +// Mapper to quantize all weights. +template +struct QuantizeMapper { + typedef A FromArc; + typedef B ToArc; + typedef typename FromArc::Weight FromWeight; + typedef typename ToArc::Weight ToWeight; + + QuantizeMapper() : delta_(kDelta) {} + + explicit QuantizeMapper(float d) : delta_(d) {} + + B operator()(const A &arc) const { + ToWeight w = arc.weight.Quantize(delta_); + return B(arc.ilabel, arc.olabel, w, arc.nextstate); + } + + MapFinalAction FinalAction() const { return MAP_NO_SUPERFINAL; } + + MapSymbolsAction InputSymbolsAction() const { return MAP_COPY_SYMBOLS; } + + MapSymbolsAction OutputSymbolsAction() const { return MAP_COPY_SYMBOLS;} + + uint64 Properties(uint64 props) const { + return props & kWeightInvariantProperties; + } + + private: + float delta_; +}; + + +// Mapper from A to B under the assumption: +// B::Weight = A::Weight::ReverseWeight +// B::Label == A::Label +// B::StateId == A::StateId +// The weight is reversed, while the label and nextstate preserved +// in the mapping. +template +struct ReverseWeightMapper { + typedef A FromArc; + typedef B ToArc; + + B operator()(const A &arc) const { + return B(arc.ilabel, arc.olabel, arc.weight.Reverse(), arc.nextstate); + } + + MapFinalAction FinalAction() const { return MAP_NO_SUPERFINAL; } + + MapSymbolsAction InputSymbolsAction() const { return MAP_COPY_SYMBOLS; } + + MapSymbolsAction OutputSymbolsAction() const { return MAP_COPY_SYMBOLS;} + + uint64 Properties(uint64 props) const { return props; } +}; + +} // namespace fst + +#endif // FST_LIB_ARC_MAP_H__ -- cgit v1.2.3