summaryrefslogtreecommitdiff
path: root/kaldi_io/src/tools/openfst/include/fst/compose.h
diff options
context:
space:
mode:
Diffstat (limited to 'kaldi_io/src/tools/openfst/include/fst/compose.h')
-rw-r--r--kaldi_io/src/tools/openfst/include/fst/compose.h728
1 files changed, 0 insertions, 728 deletions
diff --git a/kaldi_io/src/tools/openfst/include/fst/compose.h b/kaldi_io/src/tools/openfst/include/fst/compose.h
deleted file mode 100644
index db5ea3a..0000000
--- a/kaldi_io/src/tools/openfst/include/fst/compose.h
+++ /dev/null
@@ -1,728 +0,0 @@
-// compose.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 compute the composition of two FSTs
-
-#ifndef FST_LIB_COMPOSE_H__
-#define FST_LIB_COMPOSE_H__
-
-#include <algorithm>
-#include <string>
-#include <vector>
-using std::vector;
-
-#include <fst/cache.h>
-#include <fst/compose-filter.h>
-#include <fst/lookahead-filter.h>
-#include <fst/matcher.h>
-#include <fst/state-table.h>
-#include <fst/test-properties.h>
-
-
-namespace fst {
-
-// Delayed composition options templated on the arc type, the matcher,
-// the composition filter, and the composition state table. By
-// default, the matchers, filter, and state table are constructed by
-// composition. If set below, the user can instead pass in these
-// objects; in that case, ComposeFst takes their ownership. This
-// version controls composition implemented between generic Fst<Arc>
-// types and a shared matcher type M for Fst<Arc>. This should be
-// adequate for most applications, giving a reasonable tradeoff
-// between efficiency and code sharing (but see ComposeFstImplOptions).
-template <class A,
- class M = Matcher<Fst<A> >,
- class F = SequenceComposeFilter<M>,
- class T = GenericComposeStateTable<A, typename F::FilterState> >
-struct ComposeFstOptions : public CacheOptions {
- M *matcher1; // FST1 matcher (see matcher.h)
- M *matcher2; // FST2 matcher
- F *filter; // Composition filter (see compose-filter.h)
- T *state_table; // Composition state table (see compose-state-table.h)
-
- explicit ComposeFstOptions(const CacheOptions &opts,
- M *mat1 = 0, M *mat2 = 0,
- F *filt = 0, T *sttable= 0)
- : CacheOptions(opts), matcher1(mat1), matcher2(mat2),
- filter(filt), state_table(sttable) {}
-
- ComposeFstOptions() : matcher1(0), matcher2(0), filter(0), state_table(0) {}
-};
-
-
-// Delayed composition options templated on the two matcher types, the
-// composition filter, and the composition state table. By default,
-// the matchers, filter, and state table are constructed by
-// composition. If set below, the user can instead pass in these
-// objects; in that case, ComposeFst takes their ownership. This
-// version controls composition implemented using arbitrary matchers
-// (of the same Arc type but otherwise arbitrary Fst type). The user
-// must ensure the matchers are compatible. These options permit the
-// most efficient use, but shares the least code. This is for advanced
-// use only in the most demanding or specialized applications that can
-// benefit from it (o.w. prefer ComposeFstOptions).
-template <class M1, class M2,
- class F = SequenceComposeFilter<M1, M2>,
- class T = GenericComposeStateTable<typename M1::Arc,
- typename F::FilterState> >
-struct ComposeFstImplOptions : public CacheOptions {
- M1 *matcher1; // FST1 matcher (see matcher.h)
- M2 *matcher2; // FST2 matcher
- F *filter; // Composition filter (see compose-filter.h)
- T *state_table; // Composition state table (see compose-state-table.h)
-
- explicit ComposeFstImplOptions(const CacheOptions &opts,
- M1 *mat1 = 0, M2 *mat2 = 0,
- F *filt = 0, T *sttable= 0)
- : CacheOptions(opts), matcher1(mat1), matcher2(mat2),
- filter(filt), state_table(sttable) {}
-
- ComposeFstImplOptions()
- : matcher1(0), matcher2(0), filter(0), state_table(0) {}
-};
-
-
-// Implementation of delayed composition. This base class is
-// common to the variants with different matchers, composition filters
-// and state tables.
-template <class A>
-class ComposeFstImplBase : public CacheImpl<A> {
- public:
- using FstImpl<A>::SetType;
- using FstImpl<A>::SetProperties;
- using FstImpl<A>::Properties;
- using FstImpl<A>::SetInputSymbols;
- using FstImpl<A>::SetOutputSymbols;
-
- using CacheBaseImpl< CacheState<A> >::HasStart;
- using CacheBaseImpl< CacheState<A> >::HasFinal;
- using CacheBaseImpl< CacheState<A> >::HasArcs;
- using CacheBaseImpl< CacheState<A> >::SetFinal;
- using CacheBaseImpl< CacheState<A> >::SetStart;
-
- typedef typename A::Label Label;
- typedef typename A::Weight Weight;
- typedef typename A::StateId StateId;
- typedef CacheState<A> State;
-
- ComposeFstImplBase(const Fst<A> &fst1, const Fst<A> &fst2,
- const CacheOptions &opts)
- : CacheImpl<A>(opts) {
- VLOG(2) << "ComposeFst(" << this << "): Begin";
- SetType("compose");
-
- if (!CompatSymbols(fst2.InputSymbols(), fst1.OutputSymbols())) {
- FSTERROR() << "ComposeFst: output symbol table of 1st argument "
- << "does not match input symbol table of 2nd argument";
- SetProperties(kError, kError);
- }
-
- SetInputSymbols(fst1.InputSymbols());
- SetOutputSymbols(fst2.OutputSymbols());
- }
-
- ComposeFstImplBase(const ComposeFstImplBase<A> &impl)
- : CacheImpl<A>(impl, true) {
- SetProperties(impl.Properties(), kCopyProperties);
- SetInputSymbols(impl.InputSymbols());
- SetOutputSymbols(impl.OutputSymbols());
- }
-
- virtual ComposeFstImplBase<A> *Copy() = 0;
-
- virtual ~ComposeFstImplBase() {}
-
- StateId Start() {
- if (!HasStart()) {
- StateId start = ComputeStart();
- if (start != kNoStateId) {
- SetStart(start);
- }
- }
- return CacheImpl<A>::Start();
- }
-
- Weight Final(StateId s) {
- if (!HasFinal(s)) {
- Weight final = ComputeFinal(s);
- SetFinal(s, final);
- }
- return CacheImpl<A>::Final(s);
- }
-
- virtual void Expand(StateId s) = 0;
-
- size_t NumArcs(StateId s) {
- if (!HasArcs(s))
- Expand(s);
- return CacheImpl<A>::NumArcs(s);
- }
-
- size_t NumInputEpsilons(StateId s) {
- if (!HasArcs(s))
- Expand(s);
- return CacheImpl<A>::NumInputEpsilons(s);
- }
-
- size_t NumOutputEpsilons(StateId s) {
- if (!HasArcs(s))
- Expand(s);
- return CacheImpl<A>::NumOutputEpsilons(s);
- }
-
- void InitArcIterator(StateId s, ArcIteratorData<A> *data) {
- if (!HasArcs(s))
- Expand(s);
- CacheImpl<A>::InitArcIterator(s, data);
- }
-
- protected:
- virtual StateId ComputeStart() = 0;
- virtual Weight ComputeFinal(StateId s) = 0;
-};
-
-
-// Implementaion of delayed composition templated on the matchers (see
-// matcher.h), composition filter (see compose-filter-inl.h) and
-// the composition state table (see compose-state-table.h).
-template <class M1, class M2, class F, class T>
-class ComposeFstImpl : public ComposeFstImplBase<typename M1::Arc> {
- typedef typename M1::FST FST1;
- typedef typename M2::FST FST2;
- typedef typename M1::Arc Arc;
- typedef typename Arc::StateId StateId;
- typedef typename Arc::Label Label;
- typedef typename Arc::Weight Weight;
- typedef typename F::FilterState FilterState;
- typedef typename F::Matcher1 Matcher1;
- typedef typename F::Matcher2 Matcher2;
-
- using CacheBaseImpl<CacheState<Arc> >::SetArcs;
- using FstImpl<Arc>::SetType;
- using FstImpl<Arc>::SetProperties;
-
- typedef ComposeStateTuple<StateId, FilterState> StateTuple;
-
- public:
- ComposeFstImpl(const FST1 &fst1, const FST2 &fst2,
- const ComposeFstImplOptions<M1, M2, F, T> &opts);
-
- ComposeFstImpl(const ComposeFstImpl<M1, M2, F, T> &impl)
- : ComposeFstImplBase<Arc>(impl),
- filter_(new F(*impl.filter_, true)),
- matcher1_(filter_->GetMatcher1()),
- matcher2_(filter_->GetMatcher2()),
- fst1_(matcher1_->GetFst()),
- fst2_(matcher2_->GetFst()),
- state_table_(new T(*impl.state_table_)),
- match_type_(impl.match_type_) {}
-
- ~ComposeFstImpl() {
- VLOG(2) << "ComposeFst(" << this
- << "): End: # of visited states: " << state_table_->Size();
-
- delete filter_;
- delete state_table_;
- }
-
- virtual ComposeFstImpl<M1, M2, F, T> *Copy() {
- return new ComposeFstImpl<M1, M2, F, T>(*this);
- }
-
- uint64 Properties() const { return Properties(kFstProperties); }
-
- // Set error if found; return FST impl properties.
- uint64 Properties(uint64 mask) const {
- if ((mask & kError) &&
- (fst1_.Properties(kError, false) ||
- fst2_.Properties(kError, false) ||
- (matcher1_->Properties(0) & kError) ||
- (matcher2_->Properties(0) & kError) |
- (filter_->Properties(0) & kError) ||
- state_table_->Error())) {
- SetProperties(kError, kError);
- }
- return FstImpl<Arc>::Properties(mask);
- }
-
- // Arranges it so that the first arg to OrderedExpand is the Fst
- // that will be matched on.
- void Expand(StateId s) {
- const StateTuple &tuple = state_table_->Tuple(s);
- StateId s1 = tuple.state_id1;
- StateId s2 = tuple.state_id2;
- filter_->SetState(s1, s2, tuple.filter_state);
- if (match_type_ == MATCH_OUTPUT ||
- (match_type_ == MATCH_BOTH &&
- internal::NumArcs(fst1_, s1) > internal::NumArcs(fst2_, s2)))
- OrderedExpand(s, fst1_, s1, fst2_, s2, matcher1_, false);
- else
- OrderedExpand(s, fst2_, s2, fst1_, s1, matcher2_, true);
- }
-
- const FST1 &GetFst1() { return fst1_; }
- const FST2 &GetFst2() { return fst2_; }
- M1 *GetMatcher1() { return matcher1_; }
- M2 *GetMatcher2() { return matcher2_; }
- F *GetFilter() { return filter_; }
- T *GetStateTable() { return state_table_; }
-
- private:
- // This does that actual matching of labels in the composition. The
- // arguments are ordered so matching is called on state 'sa' of
- // 'fsta' for each arc leaving state 'sb' of 'fstb'. The 'match_input' arg
- // determines whether the input or output label of arcs at 'sb' is
- // the one to match on.
- template <class FST, class Matcher>
- void OrderedExpand(StateId s, const Fst<Arc> &, StateId sa,
- const FST &fstb, StateId sb,
- Matcher *matchera, bool match_input) {
- matchera->SetState(sa);
-
- // First process non-consuming symbols (e.g., epsilons) on FSTA.
- Arc loop(match_input ? 0 : kNoLabel, match_input ? kNoLabel : 0,
- Weight::One(), sb);
- MatchArc(s, matchera, loop, match_input);
-
- // Then process matches on FSTB.
- for (ArcIterator<FST> iterb(fstb, sb); !iterb.Done(); iterb.Next())
- MatchArc(s, matchera, iterb.Value(), match_input);
-
- SetArcs(s);
- }
-
- // Matches a single transition from 'fstb' against 'fata' at 's'.
- template <class Matcher>
- void MatchArc(StateId s, Matcher *matchera,
- const Arc &arc, bool match_input) {
- if (matchera->Find(match_input ? arc.olabel : arc.ilabel)) {
- for (; !matchera->Done(); matchera->Next()) {
- Arc arca = matchera->Value();
- Arc arcb = arc;
- if (match_input) {
- const FilterState &f = filter_->FilterArc(&arcb, &arca);
- if (f != FilterState::NoState())
- AddArc(s, arcb, arca, f);
- } else {
- const FilterState &f = filter_->FilterArc(&arca, &arcb);
- if (f != FilterState::NoState())
- AddArc(s, arca, arcb, f);
- }
- }
- }
- }
-
- // Add a matching transition at 's'.
- void AddArc(StateId s, const Arc &arc1, const Arc &arc2,
- const FilterState &f) {
- StateTuple tuple(arc1.nextstate, arc2.nextstate, f);
- Arc oarc(arc1.ilabel, arc2.olabel, Times(arc1.weight, arc2.weight),
- state_table_->FindState(tuple));
- CacheImpl<Arc>::PushArc(s, oarc);
- }
-
- StateId ComputeStart() {
- StateId s1 = fst1_.Start();
- if (s1 == kNoStateId)
- return kNoStateId;
-
- StateId s2 = fst2_.Start();
- if (s2 == kNoStateId)
- return kNoStateId;
-
- const FilterState &f = filter_->Start();
- StateTuple tuple(s1, s2, f);
- return state_table_->FindState(tuple);
- }
-
- Weight ComputeFinal(StateId s) {
- const StateTuple &tuple = state_table_->Tuple(s);
- StateId s1 = tuple.state_id1;
- Weight final1 = internal::Final(fst1_, s1);
- if (final1 == Weight::Zero())
- return final1;
-
- StateId s2 = tuple.state_id2;
- Weight final2 = internal::Final(fst2_, s2);
- if (final2 == Weight::Zero())
- return final2;
-
- filter_->SetState(s1, s2, tuple.filter_state);
- filter_->FilterFinal(&final1, &final2);
- return Times(final1, final2);
- }
-
- // Identifies and verifies the capabilities of the matcher to be used for
- // composition.
- void SetMatchType();
-
- F *filter_;
- Matcher1 *matcher1_;
- Matcher2 *matcher2_;
- const FST1 &fst1_;
- const FST2 &fst2_;
- T *state_table_;
-
- MatchType match_type_;
-
- void operator=(const ComposeFstImpl<M1, M2, F, T> &); // disallow
-};
-
-template <class M1, class M2, class F, class T> inline
-ComposeFstImpl<M1, M2, F, T>::ComposeFstImpl(
- const FST1 &fst1, const FST2 &fst2,
- const ComposeFstImplOptions<M1, M2, F, T> &opts)
- : ComposeFstImplBase<Arc>(fst1, fst2, opts),
- filter_(opts.filter ? opts.filter :
- new F(fst1, fst2, opts.matcher1, opts.matcher2)),
- matcher1_(filter_->GetMatcher1()),
- matcher2_(filter_->GetMatcher2()),
- fst1_(matcher1_->GetFst()),
- fst2_(matcher2_->GetFst()),
- state_table_(opts.state_table ? opts.state_table :
- new T(fst1_, fst2_)) {
- SetMatchType();
- if (match_type_ == MATCH_NONE)
- SetProperties(kError, kError);
- VLOG(2) << "ComposeFst(" << this << "): Match type: "
- << (match_type_ == MATCH_OUTPUT ? "output" :
- (match_type_ == MATCH_INPUT ? "input" :
- (match_type_ == MATCH_BOTH ? "both" :
- (match_type_ == MATCH_NONE ? "none" : "unknown"))));
-
- uint64 fprops1 = fst1.Properties(kFstProperties, false);
- uint64 fprops2 = fst2.Properties(kFstProperties, false);
- uint64 mprops1 = matcher1_->Properties(fprops1);
- uint64 mprops2 = matcher2_->Properties(fprops2);
- uint64 cprops = ComposeProperties(mprops1, mprops2);
- SetProperties(filter_->Properties(cprops), kCopyProperties);
- if (state_table_->Error()) SetProperties(kError, kError);
- VLOG(2) << "ComposeFst(" << this << "): Initialized";
-}
-
-template <class M1, class M2, class F, class T>
-void ComposeFstImpl<M1, M2, F, T>::SetMatchType() {
- MatchType type1 = matcher1_->Type(false);
- MatchType type2 = matcher2_->Type(false);
- uint32 flags1 = matcher1_->Flags();
- uint32 flags2 = matcher2_->Flags();
- if (flags1 & flags2 & kRequireMatch) {
- FSTERROR() << "ComposeFst: only one argument can require matching.";
- match_type_ = MATCH_NONE;
- } else if (flags1 & kRequireMatch) {
- if (matcher1_->Type(true) != MATCH_OUTPUT) {
- FSTERROR() << "ComposeFst: 1st argument requires matching but cannot.";
- match_type_ = MATCH_NONE;
- }
- match_type_ = MATCH_OUTPUT;
- } else if (flags2 & kRequireMatch) {
- if (matcher2_->Type(true) != MATCH_INPUT) {
- FSTERROR() << "ComposeFst: 2nd argument requires matching but cannot.";
- match_type_ = MATCH_NONE;
- }
- match_type_ = MATCH_INPUT;
- } else if (flags1 & flags2 & kPreferMatch &&
- type1 == MATCH_OUTPUT && type2 == MATCH_INPUT) {
- match_type_ = MATCH_BOTH;
- } else if (flags1 & kPreferMatch && type1 == MATCH_OUTPUT) {
- match_type_ = MATCH_OUTPUT;
- } else if (flags2 & kPreferMatch && type2 == MATCH_INPUT) {
- match_type_ = MATCH_INPUT;
- } else if (type1 == MATCH_OUTPUT && type2 == MATCH_INPUT) {
- match_type_ = MATCH_BOTH;
- } else if (type1 == MATCH_OUTPUT) {
- match_type_ = MATCH_OUTPUT;
- } else if (type2 == MATCH_INPUT) {
- match_type_ = MATCH_INPUT;
- } else if (flags1 & kPreferMatch && matcher1_->Type(true) == MATCH_OUTPUT) {
- match_type_ = MATCH_OUTPUT;
- } else if (flags2 & kPreferMatch && matcher2_->Type(true) == MATCH_INPUT) {
- match_type_ = MATCH_INPUT;
- } else if (matcher1_->Type(true) == MATCH_OUTPUT) {
- match_type_ = MATCH_OUTPUT;
- } else if (matcher2_->Type(true) == MATCH_INPUT) {
- match_type_ = MATCH_INPUT;
- } else {
- FSTERROR() << "ComposeFst: 1st argument cannot match on output labels "
- << "and 2nd argument cannot match on input labels (sort?).";
- match_type_ = MATCH_NONE;
- }
-}
-
-
-// Computes the composition of two transducers. This version is a
-// delayed Fst. If FST1 transduces string x to y with weight a and FST2
-// transduces y to z with weight b, then their composition transduces
-// string x to z with weight Times(x, z).
-//
-// The output labels of the first transducer or the input labels of
-// the second transducer must be sorted (with the default matcher).
-// The weights need to form a commutative semiring (valid for
-// TropicalWeight and LogWeight).
-//
-// Complexity:
-// Assuming the first FST is unsorted and the second is sorted:
-// - Time: O(v1 v2 d1 (log d2 + m2)),
-// - Space: O(v1 v2)
-// where vi = # of states visited, di = maximum out-degree, and mi the
-// maximum multiplicity of the states visited for the ith
-// FST. Constant time and space to visit an input state or arc is
-// assumed and exclusive of caching.
-//
-// Caveats:
-// - ComposeFst does not trim its output (since it is a delayed operation).
-// - The efficiency of composition can be strongly affected by several factors:
-// - the choice of which tnansducer is sorted - prefer sorting the FST
-// that has the greater average out-degree.
-// - the amount of non-determinism
-// - the presence and location of epsilon transitions - avoid epsilon
-// transitions on the output side of the first transducer or
-// the input side of the second transducer or prefer placing
-// them later in a path since they delay matching and can
-// introduce non-coaccessible states and transitions.
-//
-// This class attaches interface to implementation and handles
-// reference counting, delegating most methods to ImplToFst.
-template <class A>
-class ComposeFst : public ImplToFst< ComposeFstImplBase<A> > {
- public:
- friend class ArcIterator< ComposeFst<A> >;
- friend class StateIterator< ComposeFst<A> >;
-
- typedef A Arc;
- typedef typename A::Weight Weight;
- typedef typename A::StateId StateId;
- typedef CacheState<A> State;
- typedef ComposeFstImplBase<A> Impl;
-
- using ImplToFst<Impl>::SetImpl;
-
- // Compose specifying only caching options.
- ComposeFst(const Fst<A> &fst1, const Fst<A> &fst2,
- const CacheOptions &opts = CacheOptions())
- : ImplToFst<Impl>(CreateBase(fst1, fst2, opts)) {}
-
- // Compose specifying one shared matcher type M. Requires input
- // Fsts and matcher FST type (M::FST) be Fst<A>. Recommended for
- // best code-sharing and matcher compatiblity.
- template <class M, class F, class T>
- ComposeFst(const Fst<A> &fst1, const Fst<A> &fst2,
- const ComposeFstOptions<A, M, F, T> &opts)
- : ImplToFst<Impl>(CreateBase1(fst1, fst2, opts)) {}
-
- // Compose specifying two matcher types M1 and M2. Requires input
- // Fsts (of the same Arc type but o.w. arbitrary) match the
- // corresponding matcher FST types (M1::FST, M2::FST). Recommended
- // only for advanced use in demanding or specialized applications
- // due to potential code bloat and matcher incompatibilities.
- template <class M1, class M2, class F, class T>
- ComposeFst(const typename M1::FST &fst1, const typename M2::FST &fst2,
- const ComposeFstImplOptions<M1, M2, F, T> &opts)
- : ImplToFst<Impl>(CreateBase2(fst1, fst2, opts)) {}
-
- // See Fst<>::Copy() for doc.
- ComposeFst(const ComposeFst<A> &fst, bool safe = false) {
- if (safe)
- SetImpl(fst.GetImpl()->Copy());
- else
- SetImpl(fst.GetImpl(), false);
- }
-
- // Get a copy of this ComposeFst. See Fst<>::Copy() for further doc.
- virtual ComposeFst<A> *Copy(bool safe = false) const {
- return new ComposeFst<A>(*this, safe);
- }
-
- virtual inline void InitStateIterator(StateIteratorData<A> *data) const;
-
- virtual void InitArcIterator(StateId s, ArcIteratorData<A> *data) const {
- GetImpl()->InitArcIterator(s, data);
- }
-
- protected:
- ComposeFst() {}
-
- // Create compose implementation specifying two matcher types.
- template <class M1, class M2, class F, class T>
- static Impl *CreateBase2(
- const typename M1::FST &fst1, const typename M2::FST &fst2,
- const ComposeFstImplOptions<M1, M2, F, T> &opts) {
- Impl *impl = new ComposeFstImpl<M1, M2, F, T>(fst1, fst2, opts);
- if (!(Weight::Properties() & kCommutative)) {
- int64 props1 = fst1.Properties(kUnweighted, true);
- int64 props2 = fst2.Properties(kUnweighted, true);
- if (!(props1 & kUnweighted) && !(props2 & kUnweighted)) {
- FSTERROR() << "ComposeFst: Weights must be a commutative semiring: "
- << Weight::Type();
- impl->SetProperties(kError, kError);
- }
- }
- return impl;
- }
-
- // Create compose implementation specifying one matcher type.
- // Requires input Fsts and matcher FST type (M::FST) be Fst<A>
- template <class M, class F, class T>
- static Impl *CreateBase1(const Fst<A> &fst1, const Fst<A> &fst2,
- const ComposeFstOptions<A, M, F, T> &opts) {
- ComposeFstImplOptions<M, M, F, T> nopts(opts, opts.matcher1, opts.matcher2,
- opts.filter, opts.state_table);
- return CreateBase2(fst1, fst2, nopts);
- }
-
- // Create compose implementation specifying no matcher type.
- static Impl *CreateBase(const Fst<A> &fst1, const Fst<A> &fst2,
- const CacheOptions &opts) {
- switch (LookAheadMatchType(fst1, fst2)) { // Check for lookahead matchers
- default:
- case MATCH_NONE: { // Default composition (no look-ahead)
- VLOG(2) << "ComposeFst: Default composition (no look-ahead)";
- ComposeFstOptions<Arc> nopts(opts);
- return CreateBase1(fst1, fst2, nopts);
- }
- case MATCH_OUTPUT: { // Lookahead on fst1
- VLOG(2) << "ComposeFst: Lookahead on fst1";
- typedef typename DefaultLookAhead<Arc, MATCH_OUTPUT>::FstMatcher M;
- typedef typename DefaultLookAhead<Arc, MATCH_OUTPUT>::ComposeFilter F;
- ComposeFstOptions<Arc, M, F> nopts(opts);
- return CreateBase1(fst1, fst2, nopts);
- }
- case MATCH_INPUT: { // Lookahead on fst2
- VLOG(2) << "ComposeFst: Lookahead on fst2";
- typedef typename DefaultLookAhead<Arc, MATCH_INPUT>::FstMatcher M;
- typedef typename DefaultLookAhead<Arc, MATCH_INPUT>::ComposeFilter F;
- ComposeFstOptions<Arc, M, F> nopts(opts);
- return CreateBase1(fst1, fst2, nopts);
- }
- }
- }
-
- private:
- // Makes visible to friends.
- Impl *GetImpl() const { return ImplToFst<Impl>::GetImpl(); }
-
- void operator=(const ComposeFst<A> &fst); // disallow
-};
-
-
-// Specialization for ComposeFst.
-template<class A>
-class StateIterator< ComposeFst<A> >
- : public CacheStateIterator< ComposeFst<A> > {
- public:
- explicit StateIterator(const ComposeFst<A> &fst)
- : CacheStateIterator< ComposeFst<A> >(fst, fst.GetImpl()) {}
-};
-
-
-// Specialization for ComposeFst.
-template <class A>
-class ArcIterator< ComposeFst<A> >
- : public CacheArcIterator< ComposeFst<A> > {
- public:
- typedef typename A::StateId StateId;
-
- ArcIterator(const ComposeFst<A> &fst, StateId s)
- : CacheArcIterator< ComposeFst<A> >(fst.GetImpl(), s) {
- if (!fst.GetImpl()->HasArcs(s))
- fst.GetImpl()->Expand(s);
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ArcIterator);
-};
-
-template <class A> inline
-void ComposeFst<A>::InitStateIterator(StateIteratorData<A> *data) const {
- data->base = new StateIterator< ComposeFst<A> >(*this);
-}
-
-// Useful alias when using StdArc.
-typedef ComposeFst<StdArc> StdComposeFst;
-
-enum ComposeFilter { AUTO_FILTER, SEQUENCE_FILTER, ALT_SEQUENCE_FILTER,
- MATCH_FILTER };
-
-struct ComposeOptions {
- bool connect; // Connect output
- ComposeFilter filter_type; // Which pre-defined filter to use
-
- ComposeOptions(bool c, ComposeFilter ft = AUTO_FILTER)
- : connect(c), filter_type(ft) {}
- ComposeOptions() : connect(true), filter_type(AUTO_FILTER) {}
-};
-
-// Computes the composition of two transducers. This version writes
-// the composed FST into a MurableFst. If FST1 transduces string x to
-// y with weight a and FST2 transduces y to z with weight b, then
-// their composition transduces string x to z with weight
-// Times(x, z).
-//
-// The output labels of the first transducer or the input labels of
-// the second transducer must be sorted. The weights need to form a
-// commutative semiring (valid for TropicalWeight and LogWeight).
-//
-// Complexity:
-// Assuming the first FST is unsorted and the second is sorted:
-// - Time: O(V1 V2 D1 (log D2 + M2)),
-// - Space: O(V1 V2 D1 M2)
-// where Vi = # of states, Di = maximum out-degree, and Mi is
-// the maximum multiplicity for the ith FST.
-//
-// Caveats:
-// - Compose trims its output.
-// - The efficiency of composition can be strongly affected by several factors:
-// - the choice of which tnansducer is sorted - prefer sorting the FST
-// that has the greater average out-degree.
-// - the amount of non-determinism
-// - the presence and location of epsilon transitions - avoid epsilon
-// transitions on the output side of the first transducer or
-// the input side of the second transducer or prefer placing
-// them later in a path since they delay matching and can
-// introduce non-coaccessible states and transitions.
-template<class Arc>
-void Compose(const Fst<Arc> &ifst1, const Fst<Arc> &ifst2,
- MutableFst<Arc> *ofst,
- const ComposeOptions &opts = ComposeOptions()) {
- typedef Matcher< Fst<Arc> > M;
-
- if (opts.filter_type == AUTO_FILTER) {
- CacheOptions nopts;
- nopts.gc_limit = 0; // Cache only the last state for fastest copy.
- *ofst = ComposeFst<Arc>(ifst1, ifst2, nopts);
- } else if (opts.filter_type == SEQUENCE_FILTER) {
- ComposeFstOptions<Arc> copts;
- copts.gc_limit = 0; // Cache only the last state for fastest copy.
- *ofst = ComposeFst<Arc>(ifst1, ifst2, copts);
- } else if (opts.filter_type == ALT_SEQUENCE_FILTER) {
- ComposeFstOptions<Arc, M, AltSequenceComposeFilter<M> > copts;
- copts.gc_limit = 0; // Cache only the last state for fastest copy.
- *ofst = ComposeFst<Arc>(ifst1, ifst2, copts);
- } else if (opts.filter_type == MATCH_FILTER) {
- ComposeFstOptions<Arc, M, MatchComposeFilter<M> > copts;
- copts.gc_limit = 0; // Cache only the last state for fastest copy.
- *ofst = ComposeFst<Arc>(ifst1, ifst2, copts);
- }
-
- if (opts.connect)
- Connect(ofst);
-}
-
-} // namespace fst
-
-#endif // FST_LIB_COMPOSE_H__