FST  openfst-1.8.3
OpenFst Library
compose.h
Go to the documentation of this file.
1 // Copyright 2005-2024 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the 'License');
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an 'AS IS' BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // See www.openfst.org for extensive documentation on this weighted
16 // finite-state transducer library.
17 //
18 // Class to compute the composition of two FSTs.
19 
20 #ifndef FST_COMPOSE_H_
21 #define FST_COMPOSE_H_
22 
23 #include <sys/types.h>
24 
25 #include <algorithm>
26 #include <cstddef>
27 #include <cstdint>
28 #include <memory>
29 #include <utility>
30 
31 #include <fst/log.h>
32 #include <fst/arc.h>
33 #include <fst/cache.h>
34 #include <fst/compose-filter.h>
35 #include <fst/connect.h>
36 #include <fst/float-weight.h>
37 #include <fst/fst-decl.h> // For optional argument declarations
38 #include <fst/fst.h>
39 #include <fst/impl-to-fst.h>
40 #include <fst/lookahead-filter.h>
41 #include <fst/matcher.h>
42 #include <fst/mutable-fst.h>
43 #include <fst/properties.h>
44 #include <fst/state-table.h>
45 #include <fst/symbol-table.h>
46 #include <fst/util.h>
47 #include <fst/weight.h>
48 
49 namespace fst {
50 
51 // Delayed composition options templated on the arc type, the matcher,
52 // the composition filter, and the composition state table. By
53 // default, the matchers, filter, and state table are constructed by
54 // composition. If set below, the user can instead pass in these
55 // objects; in that case, ComposeFst takes their ownership. This
56 // version controls composition implemented between generic Fst<Arc>
57 // types and a shared matcher type M for Fst<Arc>. This should be
58 // adequate for most applications, giving a reasonable tradeoff
59 // between efficiency and code sharing (but see ComposeFstImplOptions).
60 template <class Arc, class M = Matcher<Fst<Arc>>,
61  class Filter = SequenceComposeFilter<M>,
62  class StateTable =
63  GenericComposeStateTable<Arc, typename Filter::FilterState>>
65  M *matcher1; // FST1 matcher.
66  M *matcher2; // FST2 matcher.
67  Filter *filter; // Composition filter.
68  StateTable *state_table; // Composition state table.
69 
70  explicit ComposeFstOptions(const CacheOptions &opts = CacheOptions(),
71  M *matcher1 = nullptr, M *matcher2 = nullptr,
72  Filter *filter = nullptr,
73  StateTable *state_table = nullptr)
74  : CacheOptions(opts),
75  matcher1(matcher1),
76  matcher2(matcher2),
77  filter(filter),
78  state_table(state_table) {}
79 };
80 
81 // Forward declaration of ComposeFstMatcher.
82 template <class C, class F, class T>
84 
85 // Delayed composition options templated on the two matcher types, the
86 // composition filter, the composition state table and the cache store. By
87 // default, the matchers, filter, state table and cache store are constructed
88 // by composition. If set below, the user can instead pass in these objects; in
89 // that case, ComposeFst takes their ownership. This version controls
90 // composition implemented using arbitrary matchers (of the same arc type but
91 // otherwise arbitrary FST type). The user must ensure the matchers are
92 // compatible. These options permit the most efficient use, but shares the
93 // least code. This is for advanced use only in the most demanding or
94 // specialized applications that can benefit from it; otherwise, prefer
95 // ComposeFstOptions).
96 template <class M1, class M2, class Filter = SequenceComposeFilter<M1, M2>,
97  class StateTable = GenericComposeStateTable<
98  typename M1::Arc, typename Filter::FilterState>,
99  class CacheStore = DefaultCacheStore<typename M1::Arc>>
100 struct ComposeFstImplOptions : public CacheImplOptions<CacheStore> {
101  M1 *matcher1; // FST1 matcher (see matcher.h)....
102  M2 *matcher2; // FST2 matcher.
103  Filter *filter; // Composition filter (see compose-filter.h).
104  StateTable
105  *state_table; // Composition state table (see compose-state-table.h).
106  bool own_state_table; // ComposeFstImpl takes ownership of 'state_table'?
107  bool allow_noncommute; // Allow non-commutative weights
108 
109  explicit ComposeFstImplOptions(const CacheOptions &opts,
110  M1 *matcher1 = nullptr, M2 *matcher2 = nullptr,
111  Filter *filter = nullptr,
112  StateTable *state_table = nullptr)
113  : CacheImplOptions<CacheStore>(opts),
114  matcher1(matcher1),
115  matcher2(matcher2),
116  filter(filter),
117  state_table(state_table),
118  own_state_table(true),
119  allow_noncommute(false) {}
120 
122  M1 *matcher1 = nullptr, M2 *matcher2 = nullptr,
123  Filter *filter = nullptr,
124  StateTable *state_table = nullptr)
125  : CacheImplOptions<CacheStore>(opts),
126  matcher1(matcher1),
127  matcher2(matcher2),
128  filter(filter),
129  state_table(state_table),
130  own_state_table(true),
131  allow_noncommute(false) {}
132 
134  : matcher1(nullptr),
135  matcher2(nullptr),
136  filter(nullptr),
137  state_table(nullptr),
138  own_state_table(true),
139  allow_noncommute(false) {}
140 };
141 
142 namespace internal {
143 
144 // Implementation of delayed composition. This base class is common to the
145 // variants with different matchers, composition filters and state tables.
146 template <class Arc, class CacheStore = DefaultCacheStore<Arc>,
147  class F = ComposeFst<Arc, CacheStore>>
149  : public CacheBaseImpl<typename CacheStore::State, CacheStore> {
150  public:
151  using FST = F;
152  using Label = typename Arc::Label;
153  using StateId = typename Arc::StateId;
154  using Weight = typename Arc::Weight;
155 
156  using State = typename CacheStore::State;
158 
159  using FstImpl<Arc>::SetType;
164 
165  using CacheImpl::HasArcs;
166  using CacheImpl::HasFinal;
167  using CacheImpl::HasStart;
168  using CacheImpl::SetFinal;
169  using CacheImpl::SetStart;
170 
172  : CacheImpl(opts) {}
173 
174  explicit ComposeFstImplBase(const CacheOptions &opts) : CacheImpl(opts) {}
175 
176  ComposeFstImplBase(const ComposeFstImplBase &impl) : CacheImpl(impl, true) {
177  SetType(impl.Type());
178  SetProperties(impl.Properties(), kCopyProperties);
179  SetInputSymbols(impl.InputSymbols());
180  SetOutputSymbols(impl.OutputSymbols());
181  }
182 
183  virtual ComposeFstImplBase *Copy() const = 0;
184 
185  ~ComposeFstImplBase() override = default;
186 
188  if (!HasStart()) {
189  const auto start = ComputeStart();
190  if (start != kNoStateId) SetStart(start);
191  }
192  return CacheImpl::Start();
193  }
194 
196  if (!HasFinal(s)) SetFinal(s, ComputeFinal(s));
197  return CacheImpl::Final(s);
198  }
199 
200  virtual void Expand(StateId s) = 0;
201 
202  size_t NumArcs(StateId s) {
203  if (!HasArcs(s)) Expand(s);
204  return CacheImpl::NumArcs(s);
205  }
206 
208  if (!HasArcs(s)) Expand(s);
209  return CacheImpl::NumInputEpsilons(s);
210  }
211 
213  if (!HasArcs(s)) Expand(s);
215  }
216 
218  if (!HasArcs(s)) Expand(s);
219  CacheImpl::InitArcIterator(s, data);
220  }
221 
222  virtual MatcherBase<Arc> *InitMatcher(const F &fst,
223  MatchType match_type) const {
224  // Use the default matcher if no override is provided.
225  return nullptr;
226  }
227 
228  protected:
229  virtual StateId ComputeStart() = 0;
230  virtual Weight ComputeFinal(StateId s) = 0;
231 };
232 
233 // Implementation of delayed composition templated on the matchers (see
234 // matcher.h), composition filter (see compose-filter.h) and the composition
235 // state table (see compose-state-table.h).
236 template <class CacheStore, class Filter, class StateTable>
238  : public ComposeFstImplBase<typename CacheStore::Arc, CacheStore> {
239  public:
240  using Matcher1 = typename Filter::Matcher1;
241  using Matcher2 = typename Filter::Matcher2;
242 
243  using FST1 = typename Matcher1::FST;
244  using FST2 = typename Matcher2::FST;
245 
246  using Arc = typename CacheStore::Arc;
247  using Label = typename Arc::Label;
248  using StateId = typename Arc::StateId;
249  using Weight = typename Arc::Weight;
250 
251  using FilterState = typename Filter::FilterState;
252  using State = typename CacheStore::State;
253 
255 
256  using StateTuple = typename StateTable::StateTuple;
257 
258  friend class ComposeFstMatcher<CacheStore, Filter, StateTable>;
259 
262  using FstImpl<Arc>::SetType;
264 
265  template <class M1, class M2>
266  ComposeFstImpl(const FST1 &fst1, const FST2 &fst2,
267  const ComposeFstImplOptions<M1, M2, Filter, StateTable,
268  CacheStore> &opts);
269 
271  : ComposeFstImplBase<Arc, CacheStore>(impl),
272  filter_(new Filter(*impl.filter_, true)),
273  matcher1_(filter_->GetMatcher1()),
274  matcher2_(filter_->GetMatcher2()),
275  fst1_(matcher1_->GetFst()),
276  fst2_(matcher2_->GetFst()),
277  state_table_(new StateTable(*impl.state_table_)),
278  own_state_table_(true),
279  match_type_(impl.match_type_) {}
280 
281  ~ComposeFstImpl() override {
282  if (own_state_table_) delete state_table_;
283  }
284 
285  ComposeFstImpl *Copy() const override { return new ComposeFstImpl(*this); }
286 
287  uint64_t Properties() const override { return Properties(kFstProperties); }
288 
289  // Sets error if found, and returns other FST impl properties.
290  uint64_t Properties(uint64_t mask) const override {
291  if ((mask & kError) &&
292  (fst1_.Properties(kError, false) || fst2_.Properties(kError, false) ||
293  (matcher1_->Properties(0) & kError) ||
294  (matcher2_->Properties(0) & kError) |
295  (filter_->Properties(0) & kError) ||
296  state_table_->Error())) {
297  SetProperties(kError, kError);
298  }
299  return FstImpl<Arc>::Properties(mask);
300  }
301 
302  // Arranges it so that the first arg to OrderedExpand is the Fst
303  // that will be matched on.
304  void Expand(StateId s) override {
305  const auto &tuple = state_table_->Tuple(s);
306  const auto s1 = tuple.StateId1();
307  const auto s2 = tuple.StateId2();
308  filter_->SetState(s1, s2, tuple.GetFilterState());
309  if (MatchInput(s1, s2)) {
310  OrderedExpand(s, fst2_, s2, fst1_, s1, matcher2_, true);
311  } else {
312  OrderedExpand(s, fst1_, s1, fst2_, s2, matcher1_, false);
313  }
314  }
315 
316  const FST1 &GetFst1() const { return fst1_; }
317 
318  const FST2 &GetFst2() const { return fst2_; }
319 
320  const Matcher1 *GetMatcher1() const { return matcher1_; }
321 
322  Matcher1 *GetMatcher1() { return matcher1_; }
323 
324  const Matcher2 *GetMatcher2() const { return matcher2_; }
325 
326  Matcher2 *GetMatcher2() { return matcher2_; }
327 
328  const Filter *GetFilter() const { return filter_.get(); }
329 
330  Filter *GetFilter() { return filter_.get(); }
331 
332  const StateTable *GetStateTable() const { return state_table_; }
333 
334  StateTable *GetStateTable() { return state_table_; }
335 
337  MatchType match_type) const override {
338  const auto test_props = match_type == MATCH_INPUT
341  // If both matchers support 'match_type' and we have a guarantee that a
342  // call to 'filter_->FilterArc(arc1, arc2)' will not modify the ilabel of
343  // arc1 when MATCH_INPUT or the olabel or arc2 when MATCH_OUTPUT, then
344  // ComposeFstMatcher can be used.
345  if ((matcher1_->Type(false) == match_type) &&
346  (matcher2_->Type(false) == match_type) &&
347  (filter_->Properties(test_props) == test_props)) {
349  match_type);
350  }
351  return nullptr;
352  }
353 
354  private:
355  // This does that actual matching of labels in the composition. The
356  // arguments are ordered so matching is called on state 'sa' of
357  // 'fsta' for each arc leaving state 'sb' of 'fstb'. The 'match_input' arg
358  // determines whether the input or output label of arcs at 'sb' is
359  // the one to match on.
360  template <class FST, class Matcher>
361  void OrderedExpand(StateId s, const Fst<Arc> &, StateId sa, const FST &fstb,
362  StateId sb, Matcher *matchera, bool match_input) {
363  matchera->SetState(sa);
364  // First processes non-consuming symbols (e.g., epsilons) on FSTA.
365  const Arc loop(match_input ? 0 : kNoLabel, match_input ? kNoLabel : 0,
366  Weight::One(), sb);
367  MatchArc(s, matchera, loop, match_input);
368  // Then processes matches on FSTB.
369  for (ArcIterator<FST> iterb(fstb, sb); !iterb.Done(); iterb.Next()) {
370  MatchArc(s, matchera, iterb.Value(), match_input);
371  }
372  CacheImpl::SetArcs(s);
373  }
374 
375  // Matches a single transition from 'fstb' against 'fata' at 's'.
376  template <class Matcher>
377  void MatchArc(StateId s, Matcher *matchera, const Arc &arc,
378  bool match_input) {
379  if (matchera->Find(match_input ? arc.olabel : arc.ilabel)) {
380  for (; !matchera->Done(); matchera->Next()) {
381  auto arca = matchera->Value();
382  auto arcb = arc;
383  if (match_input) {
384  const auto &fs = filter_->FilterArc(&arcb, &arca);
385  if (fs != FilterState::NoState()) AddArc(s, arcb, arca, fs);
386  } else {
387  const auto &fs = filter_->FilterArc(&arca, &arcb);
388  if (fs != FilterState::NoState()) AddArc(s, arca, arcb, fs);
389  }
390  }
391  }
392  }
393 
394  // Add a matching transition at 's'.
395  void AddArc(StateId s, const Arc &arc1, const Arc &arc2,
396  const FilterState &f) {
397  const StateTuple tuple(arc1.nextstate, arc2.nextstate, f);
398  CacheImpl::EmplaceArc(s, arc1.ilabel, arc2.olabel,
399  Times(arc1.weight, arc2.weight),
400  state_table_->FindState(tuple));
401  }
402 
403  StateId ComputeStart() override {
404  const auto s1 = fst1_.Start();
405  if (s1 == kNoStateId) return kNoStateId;
406  const auto s2 = fst2_.Start();
407  if (s2 == kNoStateId) return kNoStateId;
408  const auto &fs = filter_->Start();
409  const StateTuple tuple(s1, s2, fs);
410  return state_table_->FindState(tuple);
411  }
412 
413  Weight ComputeFinal(StateId s) override {
414  const auto &tuple = state_table_->Tuple(s);
415  const auto s1 = tuple.StateId1();
416  auto final1 = matcher1_->Final(s1);
417  if (final1 == Weight::Zero()) return final1;
418  const auto s2 = tuple.StateId2();
419  auto final2 = matcher2_->Final(s2);
420  if (final2 == Weight::Zero()) return final2;
421  filter_->SetState(s1, s2, tuple.GetFilterState());
422  filter_->FilterFinal(&final1, &final2);
423  return Times(final1, final2);
424  }
425 
426  // Determines which side to match on per composition state.
427  bool MatchInput(StateId s1, StateId s2) {
428  switch (match_type_) {
429  case MATCH_INPUT:
430  return true;
431  case MATCH_OUTPUT:
432  return false;
433  default: // MATCH_BOTH
434  const auto priority1 = matcher1_->Priority(s1);
435  const auto priority2 = matcher2_->Priority(s2);
436  if (priority1 == kRequirePriority && priority2 == kRequirePriority) {
437  FSTERROR() << "ComposeFst: Both sides can't require match";
438  SetProperties(kError, kError);
439  return true;
440  }
441  if (priority1 == kRequirePriority) return false;
442  if (priority2 == kRequirePriority) {
443  return true;
444  }
445  return priority1 <= priority2;
446  }
447  }
448 
449  // Identifies and verifies the capabilities of the matcher to be used for
450  // composition.
451  void SetMatchType();
452 
453  std::unique_ptr<Filter> filter_;
454  Matcher1 *matcher1_; // Borrowed reference.
455  Matcher2 *matcher2_; // Borrowed reference.
456  const FST1 &fst1_;
457  const FST2 &fst2_;
458  StateTable *state_table_;
459  bool own_state_table_;
460 
461  MatchType match_type_;
462 };
463 
464 template <class CacheStore, class Filter, class StateTable>
465 template <class M1, class M2>
467  const FST1 &fst1, const FST2 &fst2,
469  : ComposeFstImplBase<Arc, CacheStore>(opts),
470  filter_(opts.filter
471  ? opts.filter
472  : new Filter(fst1, fst2, opts.matcher1, opts.matcher2)),
473  matcher1_(filter_->GetMatcher1()),
474  matcher2_(filter_->GetMatcher2()),
475  fst1_(matcher1_->GetFst()),
476  fst2_(matcher2_->GetFst()),
477  state_table_(opts.state_table ? opts.state_table
478  : new StateTable(fst1_, fst2_)),
479  own_state_table_(opts.state_table ? opts.own_state_table : true) {
480  SetType("compose");
481  if (!CompatSymbols(fst2.InputSymbols(), fst1.OutputSymbols())) {
482  FSTERROR() << "ComposeFst: Output symbol table of 1st argument "
483  << "does not match input symbol table of 2nd argument";
485  }
486  SetInputSymbols(fst1_.InputSymbols());
487  SetOutputSymbols(fst2_.OutputSymbols());
488  SetMatchType();
489  VLOG(2) << "ComposeFstImpl: Match type: " << match_type_;
490  if (match_type_ == MATCH_NONE) SetProperties(kError, kError);
491  const auto fprops1 = fst1.Properties(kFstProperties, false);
492  const auto fprops2 = fst2.Properties(kFstProperties, false);
493  const auto mprops1 = matcher1_->Properties(fprops1);
494  const auto mprops2 = matcher2_->Properties(fprops2);
495  const auto cprops = ComposeProperties(mprops1, mprops2);
496  SetProperties(filter_->Properties(cprops), kCopyProperties);
497  if (state_table_->Error()) SetProperties(kError, kError);
498 }
499 
500 template <class CacheStore, class Filter, class StateTable>
502  // Ensures any required matching is possible and known.
503  if ((matcher1_->Flags() & kRequireMatch) &&
504  matcher1_->Type(true) != MATCH_OUTPUT) {
505  FSTERROR() << "ComposeFst: 1st argument cannot perform required matching "
506  << "(sort?).";
507  match_type_ = MATCH_NONE;
508  return;
509  }
510  if ((matcher2_->Flags() & kRequireMatch) &&
511  matcher2_->Type(true) != MATCH_INPUT) {
512  FSTERROR() << "ComposeFst: 2nd argument cannot perform required matching "
513  << "(sort?).";
514  match_type_ = MATCH_NONE;
515  return;
516  }
517  // Finds which sides to match on (favoring minimal testing of capabilities).
518  const auto type1 = matcher1_->Type(false);
519  const auto type2 = matcher2_->Type(false);
520  if (type1 == MATCH_OUTPUT && type2 == MATCH_INPUT) {
521  match_type_ = MATCH_BOTH;
522  } else if (type1 == MATCH_OUTPUT) {
523  match_type_ = MATCH_OUTPUT;
524  } else if (type2 == MATCH_INPUT) {
525  match_type_ = MATCH_INPUT;
526  } else if (matcher1_->Type(true) == MATCH_OUTPUT) {
527  match_type_ = MATCH_OUTPUT;
528  } else if (matcher2_->Type(true) == MATCH_INPUT) {
529  match_type_ = MATCH_INPUT;
530  } else {
531  FSTERROR() << "ComposeFst: 1st argument cannot match on output labels "
532  << "and 2nd argument cannot match on input labels (sort?).";
533  match_type_ = MATCH_NONE;
534  }
535 }
536 
537 } // namespace internal
538 
539 // Computes the composition of two transducers. This version is a delayed FST.
540 // If FST1 transduces string x to y with weight a and FST2 transduces y to z
541 // with weight b, then their composition transduces string x to z with weight
542 // Times(x, z).
543 //
544 // The output labels of the first transducer or the input labels of the second
545 // transducer must be sorted (with the default matcher). The weights need to
546 // form a commutative semiring (valid for TropicalWeight and LogWeight).
547 //
548 // Complexity:
549 //
550 // Assuming the first FST is unsorted and the second is sorted,
551 //
552 // Time: O(v1 v2 d1 (log d2 + m2)),
553 // Space: O(v1 v2)
554 //
555 // where vi = # of states visited, di = maximum out-degree, and mi the
556 // maximum multiplicity of the states visited, for the ith FST. Constant time
557 // and space to visit an input state or arc is assumed and exclusive of caching.
558 //
559 // Caveats:
560 // - ComposeFst does not trim its output (since it is a delayed operation).
561 // - The efficiency of composition can be strongly affected by several factors:
562 // - the choice of which transducer is sorted - prefer sorting the FST
563 // that has the greater average out-degree.
564 // - the amount of non-determinism
565 // - the presence and location of epsilon transitions - avoid epsilon
566 // transitions on the output side of the first transducer or
567 // the input side of the second transducer or prefer placing
568 // them later in a path since they delay matching and can
569 // introduce non-coaccessible states and transitions.
570 //
571 // This class attaches interface to implementation and handles reference
572 // counting, delegating most methods to ImplToFst. The CacheStore specifies the
573 // cache store (default declared in fst-decl.h).
574 template <class A, class CacheStore /* = DefaultCacheStore<A> */>
576  : public ImplToFst<internal::ComposeFstImplBase<A, CacheStore>> {
577  public:
578  using Arc = A;
579  using StateId = typename Arc::StateId;
580  using Weight = typename Arc::Weight;
581 
582  using Store = CacheStore;
583  using State = typename CacheStore::State;
584 
586 
587  friend class ArcIterator<ComposeFst<Arc, CacheStore>>;
588  friend class StateIterator<ComposeFst<Arc, CacheStore>>;
589  template <class, class, class>
590  friend class ComposeFstMatcher;
591 
592  // Compose specifying only caching options.
593  ComposeFst(const Fst<Arc> &fst1, const Fst<Arc> &fst2,
594  const CacheOptions &opts = CacheOptions())
595  : ImplToFst<Impl>(CreateBase(fst1, fst2, opts)) {}
596 
597  // Compose specifying one shared matcher type M. Requires that the input FSTs
598  // and matcher FST types be Fst<Arc>. Recommended for best code-sharing and
599  // matcher compatibility.
600  template <class Matcher, class Filter, class StateTuple>
601  ComposeFst(const Fst<Arc> &fst1, const Fst<Arc> &fst2,
603  : ImplToFst<Impl>(CreateBase1(fst1, fst2, opts)) {}
604 
605  // Compose specifying two matcher types Matcher1 and Matcher2. Requires input
606  // FST (of the same Arc type, but o.w. arbitrary) match the corresponding
607  // matcher FST types). Recommended only for advanced use in demanding or
608  // specialized applications due to potential code bloat and matcher
609  // incompatibilities.
610  template <class Matcher1, class Matcher2, class Filter, class StateTuple>
611  ComposeFst(const typename Matcher1::FST &fst1,
612  const typename Matcher2::FST &fst2,
614  CacheStore> &opts)
615  : ImplToFst<Impl>(CreateBase2(fst1, fst2, opts)) {}
616 
617  // See Fst<>::Copy() for doc.
618  ComposeFst(const ComposeFst &fst, bool safe = false)
619  : ImplToFst<Impl>(safe ? std::shared_ptr<Impl>(fst.GetImpl()->Copy())
620  : fst.GetSharedImpl()) {}
621 
622  // Get a copy of this ComposeFst. See Fst<>::Copy() for further doc.
623  ComposeFst *Copy(bool safe = false) const override {
624  return new ComposeFst(*this, safe);
625  }
626 
627  inline void InitStateIterator(StateIteratorData<Arc> *data) const override;
628 
629  void InitArcIterator(StateId s, ArcIteratorData<Arc> *data) const override {
630  GetMutableImpl()->InitArcIterator(s, data);
631  }
632 
633  MatcherBase<Arc> *InitMatcher(MatchType match_type) const override {
634  return GetImpl()->InitMatcher(*this, match_type);
635  }
636 
637  protected:
640 
641  explicit ComposeFst(std::shared_ptr<Impl> impl) : ImplToFst<Impl>(impl) {}
642 
643  // Create compose implementation specifying two matcher types.
644  template <class Matcher1, class Matcher2, class Filter, class StateTuple>
645  static std::shared_ptr<Impl> CreateBase2(
646  const typename Matcher1::FST &fst1, const typename Matcher2::FST &fst2,
648  CacheStore> &opts) {
649  auto impl = std::make_shared<
651  opts);
652  if (!(Weight::Properties() & kCommutative) && !opts.allow_noncommute) {
653  const auto props1 = fst1.Properties(kUnweighted, true);
654  const auto props2 = fst2.Properties(kUnweighted, true);
655  if (!(props1 & kUnweighted) && !(props2 & kUnweighted)) {
656  FSTERROR() << "ComposeFst: Weights must be a commutative semiring: "
657  << Weight::Type();
658  impl->SetProperties(kError, kError);
659  }
660  }
661  return impl;
662  }
663 
664  // Create compose implementation specifying one matcher type; requires that
665  // input and matcher FST types be Fst<Arc>.
666  template <class Matcher, class Filter, class StateTuple>
667  static std::shared_ptr<Impl> CreateBase1(
668  const Fst<Arc> &fst1, const Fst<Arc> &fst2,
671  nopts(opts, opts.matcher1, opts.matcher2, opts.filter,
672  opts.state_table);
673  return CreateBase2(fst1, fst2, nopts);
674  }
675 
676  // Create compose implementation specifying no matcher type.
677  static std::shared_ptr<Impl> CreateBase(const Fst<Arc> &fst1,
678  const Fst<Arc> &fst2,
679  const CacheOptions &opts) {
680  switch (LookAheadMatchType(fst1, fst2)) { // Check for lookahead matchers
681  default:
682  case MATCH_NONE: { // Default composition (no look-ahead).
683  ComposeFstOptions<Arc> nopts(opts);
684  return CreateBase1(fst1, fst2, nopts);
685  }
686  case MATCH_OUTPUT: { // Lookahead on fst1.
689  ComposeFstOptions<Arc, M, F> nopts(opts);
690  return CreateBase1(fst1, fst2, nopts);
691  }
692  case MATCH_INPUT: { // Lookahead on fst2
695  ComposeFstOptions<Arc, M, F> nopts(opts);
696  return CreateBase1(fst1, fst2, nopts);
697  }
698  }
699  }
700 
701  private:
702  ComposeFst &operator=(const ComposeFst &fst) = delete;
703 };
704 
705 // Specialization for ComposeFst.
706 template <class Arc, class CacheStore>
707 class StateIterator<ComposeFst<Arc, CacheStore>>
708  : public CacheStateIterator<ComposeFst<Arc, CacheStore>> {
709  public:
711  : CacheStateIterator<ComposeFst<Arc, CacheStore>>(fst,
712  fst.GetMutableImpl()) {}
713 };
714 
715 // Specialization for ComposeFst.
716 template <class Arc, class CacheStore>
717 class ArcIterator<ComposeFst<Arc, CacheStore>>
718  : public CacheArcIterator<ComposeFst<Arc, CacheStore>> {
719  public:
720  using StateId = typename Arc::StateId;
721 
723  : CacheArcIterator<ComposeFst<Arc, CacheStore>>(fst.GetMutableImpl(), s) {
724  if (!fst.GetImpl()->HasArcs(s)) fst.GetMutableImpl()->Expand(s);
725  }
726 };
727 
728 template <class Arc, class CacheStore>
730  StateIteratorData<Arc> *data) const {
731  data->base =
732  std::make_unique<StateIterator<ComposeFst<Arc, CacheStore>>>(*this);
733 }
734 
735 // Specialized matcher for ComposeFst. Supports MATCH_INPUT or MATCH_OUTPUT,
736 // iff the underlying matchers for the two FSTS being composed support
737 // MATCH_INPUT or MATCH_OUTPUT, respectively.
738 template <class CacheStore, class Filter, class StateTable>
739 class ComposeFstMatcher : public MatcherBase<typename CacheStore::Arc> {
740  public:
741  using Arc = typename CacheStore::Arc;
742  using Label = typename Arc::Label;
743  using StateId = typename Arc::StateId;
744  using Weight = typename Arc::Weight;
745 
746  using Matcher1 = typename Filter::Matcher1;
747  using Matcher2 = typename Filter::Matcher2;
748  using FilterState = typename Filter::FilterState;
749 
750  using StateTuple = typename StateTable::StateTuple;
752 
753  // The compose FST arg must match the filter and state table types.
754  // This makes a copy of the FST.
756  MatchType match_type)
757  : owned_fst_(fst.Copy()),
758  fst_(*owned_fst_),
759  impl_(down_cast<const Impl *>(fst_.GetImpl())),
760  s_(kNoStateId),
761  match_type_(match_type),
762  matcher1_(impl_->matcher1_->Copy()),
763  matcher2_(impl_->matcher2_->Copy()),
764  current_loop_(false),
765  loop_(kNoLabel, 0, Weight::One(), kNoStateId) {
766  if (match_type_ == MATCH_OUTPUT) std::swap(loop_.ilabel, loop_.olabel);
767  }
768 
769  // The compose FST arg must match the filter and state table types.
770  // This doesn't copy the FST (although it may copy components).
772  MatchType match_type)
773  : fst_(*fst),
774  impl_(down_cast<const Impl *>(fst_.GetImpl())),
775  s_(kNoStateId),
776  match_type_(match_type),
777  matcher1_(impl_->matcher1_->Copy()),
778  matcher2_(impl_->matcher2_->Copy()),
779  current_loop_(false),
780  loop_(kNoLabel, 0, Weight::One(), kNoStateId) {
781  if (match_type_ == MATCH_OUTPUT) std::swap(loop_.ilabel, loop_.olabel);
782  }
783 
784  // This makes a copy of the FST.
787  bool safe = false)
788  : owned_fst_(matcher.fst_.Copy(safe)),
789  fst_(*owned_fst_),
790  impl_(down_cast<const Impl *>(fst_.GetImpl())),
791  s_(kNoStateId),
792  match_type_(matcher.match_type_),
793  matcher1_(matcher.matcher1_->Copy(safe)),
794  matcher2_(matcher.matcher2_->Copy(safe)),
795  current_loop_(false),
796  loop_(kNoLabel, 0, Weight::One(), kNoStateId) {
797  if (match_type_ == MATCH_OUTPUT) std::swap(loop_.ilabel, loop_.olabel);
798  }
799 
800  ComposeFstMatcher *Copy(bool safe = false) const override {
801  return new ComposeFstMatcher(*this, safe);
802  }
803 
804  MatchType Type(bool test) const override {
805  if ((matcher1_->Type(test) == MATCH_NONE) ||
806  (matcher2_->Type(test) == MATCH_NONE)) {
807  return MATCH_NONE;
808  }
809  if (((matcher1_->Type(test) == MATCH_UNKNOWN) &&
810  (matcher2_->Type(test) == MATCH_UNKNOWN)) ||
811  ((matcher1_->Type(test) == MATCH_UNKNOWN) &&
812  (matcher2_->Type(test) == match_type_)) ||
813  ((matcher1_->Type(test) == match_type_) &&
814  (matcher2_->Type(test) == MATCH_UNKNOWN))) {
815  return MATCH_UNKNOWN;
816  }
817  if ((matcher1_->Type(test) == match_type_) &&
818  (matcher2_->Type(test) == match_type_)) {
819  return match_type_;
820  }
821  return MATCH_NONE;
822  }
823 
824  const Fst<Arc> &GetFst() const override { return fst_; }
825 
826  uint64_t Properties(uint64_t inprops) const override { return inprops; }
827 
828  void SetState(StateId s) final {
829  if (s_ == s) return;
830  s_ = s;
831  const auto &tuple = impl_->state_table_->Tuple(s);
832  matcher1_->SetState(tuple.StateId1());
833  matcher2_->SetState(tuple.StateId2());
834  loop_.nextstate = s_;
835  }
836 
837  bool Find(Label label) final {
838  bool found = false;
839  current_loop_ = false;
840  if (label == 0) {
841  current_loop_ = true;
842  found = true;
843  }
844  if (match_type_ == MATCH_INPUT) {
845  found = found || FindLabel(label, matcher1_.get(), matcher2_.get());
846  } else { // match_type_ == MATCH_OUTPUT
847  found = found || FindLabel(label, matcher2_.get(), matcher1_.get());
848  }
849  return found;
850  }
851 
852  bool Done() const final {
853  return !current_loop_ && matcher1_->Done() && matcher2_->Done();
854  }
855 
856  const Arc &Value() const final { return current_loop_ ? loop_ : arc_; }
857 
858  void Next() final {
859  if (current_loop_) {
860  current_loop_ = false;
861  } else if (match_type_ == MATCH_INPUT) {
862  FindNext(matcher1_.get(), matcher2_.get());
863  } else { // match_type_ == MATCH_OUTPUT
864  FindNext(matcher2_.get(), matcher1_.get());
865  }
866  }
867 
868  ssize_t Priority(StateId s) final { return fst_.NumArcs(s); }
869 
870  private:
871  // Processes a match with the filter and creates resulting arc.
872  bool MatchArc(StateId s, Arc *arc1, Arc *arc2) {
873  const auto &fs = impl_->filter_->FilterArc(arc1, arc2);
874  if (fs == FilterState::NoState()) return false;
875  const StateTuple tuple(arc1->nextstate, arc2->nextstate, fs);
876  arc_.ilabel = arc1->ilabel;
877  arc_.olabel = arc2->olabel;
878  arc_.weight = Times(arc1->weight, arc2->weight);
879  arc_.nextstate = impl_->state_table_->FindState(tuple);
880  return true;
881  }
882 
883  // Finds the first match allowed by the filter.
884  template <class MatcherA, class MatcherB>
885  bool FindLabel(Label label, MatcherA *matchera, MatcherB *matcherb) {
886  if (matchera->Find(label)) {
887  matcherb->Find(match_type_ == MATCH_INPUT ? matchera->Value().olabel
888  : matchera->Value().ilabel);
889  return FindNext(matchera, matcherb);
890  }
891  return false;
892  }
893 
894  // Finds the next match allowed by the filter, returning true iff such a
895  // match is found.
896  template <class MatcherA, class MatcherB>
897  bool FindNext(MatcherA *matchera, MatcherB *matcherb) {
898  // State when entering this function:
899  // 'matchera' is pointed to a match x, y for label x, and a match for y was
900  // requested on 'matcherb'.
901  while (!matchera->Done() || !matcherb->Done()) {
902  if (matcherb->Done()) {
903  // If no more matches for y on 'matcherb', moves forward on 'matchera'
904  // until a match x, y' is found such that there is a match for y' on
905  // 'matcherb'.
906  matchera->Next();
907  while (!matchera->Done() &&
908  !matcherb->Find(match_type_ == MATCH_INPUT
909  ? matchera->Value().olabel
910  : matchera->Value().ilabel)) {
911  matchera->Next();
912  }
913  }
914  while (!matcherb->Done()) {
915  // 'matchera' is pointing to a match x, y' ('arca') and 'matcherb' is
916  // pointing to a match y', z' ('arcb'). If combining these two arcs is
917  // allowed by the filter (hence resulting in an arc x, z') return true.
918  // Position 'matcherb' on the next potential match for y' before
919  // returning.
920  auto arca = matchera->Value();
921  auto arcb = matcherb->Value();
922  // Position 'matcherb' on the next potential match for y'.
923  matcherb->Next();
924  // Returns true If combining these two arcs is allowed by the filter
925  // (hence resulting in an arc x, z'); otherwise consider next match
926  // for y' on 'matcherb'.
927  if (match_type_ == MATCH_INPUT) {
928  if (MatchArc(s_, &arca, &arcb)) return true;
929  } else {
930  if (MatchArc(s_, &arcb, &arca)) return true;
931  }
932  }
933  }
934  // Both 'matchera' and 'matcherb' are done, no more match to analyse.
935  return false;
936  }
937 
938  std::unique_ptr<const ComposeFst<Arc, CacheStore>> owned_fst_;
939  const ComposeFst<Arc, CacheStore> &fst_;
940  const Impl *impl_;
941  StateId s_;
942  MatchType match_type_;
943  std::unique_ptr<Matcher1> matcher1_;
944  std::unique_ptr<Matcher2> matcher2_;
945  bool current_loop_;
946  Arc loop_;
947  Arc arc_;
948 };
949 
950 // Useful alias when using StdArc.
952 
961 };
962 
964  bool connect; // Connect output?
965  ComposeFilter filter_type; // Pre-defined filter to use.
966 
967  explicit ComposeOptions(bool connect = true,
968  ComposeFilter filter_type = AUTO_FILTER)
969  : connect(connect), filter_type(filter_type) {}
970 };
971 
972 // Computes the composition of two transducers. This version writes
973 // the composed FST into a MutableFst. If FST1 transduces string x to
974 // y with weight a and FST2 transduces y to z with weight b, then
975 // their composition transduces string x to z with weight
976 // Times(a, b).
977 //
978 // The output labels of the first transducer or the input labels of
979 // the second transducer must be sorted. The weights need to form a
980 // commutative semiring (valid for TropicalWeight and LogWeight).
981 //
982 // Complexity:
983 //
984 // Assuming the first FST is unsorted and the second is sorted:
985 //
986 // Time: O(V1 V2 D1 (log D2 + M2)),
987 // Space: O(V1 V2 D1 M2)
988 //
989 // where Vi = # of states, Di = maximum out-degree, and Mi is the maximum
990 // multiplicity, for the ith FST.
991 //
992 // Caveats:
993 //
994 // - Compose trims its output.
995 // - The efficiency of composition can be strongly affected by several factors:
996 // - the choice of which transducer is sorted - prefer sorting the FST
997 // that has the greater average out-degree.
998 // - the amount of non-determinism
999 // - the presence and location of epsilon transitions - avoid epsilon
1000 // transitions on the output side of the first transducer or
1001 // the input side of the second transducer or prefer placing
1002 // them later in a path since they delay matching and can
1003 // introduce non-coaccessible states and transitions.
1004 template <class Arc>
1005 void Compose(const Fst<Arc> &ifst1, const Fst<Arc> &ifst2,
1006  MutableFst<Arc> *ofst,
1007  const ComposeOptions &opts = ComposeOptions()) {
1008  using M = Matcher<Fst<Arc>>;
1009  // In each case, we cache only the last state for fastest copy.
1010  switch (opts.filter_type) {
1011  case AUTO_FILTER: {
1012  CacheOptions nopts;
1013  nopts.gc_limit = 0;
1014  *ofst = ComposeFst<Arc>(ifst1, ifst2, nopts);
1015  break;
1016  }
1017  case NULL_FILTER: {
1019  copts.gc_limit = 0;
1020  *ofst = ComposeFst<Arc>(ifst1, ifst2, copts);
1021  break;
1022  }
1023  case SEQUENCE_FILTER: {
1025  copts.gc_limit = 0;
1026  *ofst = ComposeFst<Arc>(ifst1, ifst2, copts);
1027  break;
1028  }
1029  case ALT_SEQUENCE_FILTER: {
1031  copts.gc_limit = 0;
1032  *ofst = ComposeFst<Arc>(ifst1, ifst2, copts);
1033  break;
1034  }
1035  case MATCH_FILTER: {
1037  copts.gc_limit = 0;
1038  *ofst = ComposeFst<Arc>(ifst1, ifst2, copts);
1039  break;
1040  }
1041  case NO_MATCH_FILTER: {
1043  copts.gc_limit = 0;
1044  *ofst = ComposeFst<Arc>(ifst1, ifst2, copts);
1045  break;
1046  }
1047  case TRIVIAL_FILTER: {
1049  copts.gc_limit = 0;
1050  *ofst = ComposeFst<Arc>(ifst1, ifst2, copts);
1051  break;
1052  }
1053  }
1054  if (opts.connect) Connect(ofst);
1055 }
1056 
1057 } // namespace fst
1058 
1059 #endif // FST_COMPOSE_H_
typename Impl::Arc Arc
Definition: impl-to-fst.h:43
ssize_t NumOutputEpsilons(const ExpandedFst< Arc > &fst, typename Arc::StateId s)
Definition: expanded-fst.h:124
uint64_t Properties() const override
Definition: compose.h:287
typename Filter::Matcher1 Matcher1
Definition: compose.h:240
ssize_t Priority(StateId s) final
Definition: compose.h:868
ComposeFst(const typename Matcher1::FST &fst1, const typename Matcher2::FST &fst2, const ComposeFstImplOptions< Matcher1, Matcher2, Filter, StateTuple, CacheStore > &opts)
Definition: compose.h:611
typename Filter::Matcher2 Matcher2
Definition: compose.h:241
const StateTable * GetStateTable() const
Definition: compose.h:332
size_t NumArcs(StateId s)
Definition: compose.h:202
constexpr ssize_t kRequirePriority
Definition: matcher.h:135
void Expand(StateId s) override
Definition: compose.h:304
constexpr int kNoLabel
Definition: fst.h:195
CacheOptions(bool gc=FST_FLAGS_fst_default_cache_gc, size_t gc_limit=FST_FLAGS_fst_default_cache_gc_limit)
Definition: cache.h:54
typename Filter::Matcher2 Matcher2
Definition: compose.h:747
typename StateTable::StateTuple StateTuple
Definition: compose.h:750
static std::shared_ptr< Impl > CreateBase1(const Fst< Arc > &fst1, const Fst< Arc > &fst2, const ComposeFstOptions< Arc, Matcher, Filter, StateTuple > &opts)
Definition: compose.h:667
typename StateTable::StateTuple StateTuple
Definition: compose.h:256
typename Filter::Matcher1 Matcher1
Definition: compose.h:746
typename Arc::Label Label
Definition: compose.h:742
uint64_t ComposeProperties(uint64_t inprops1, uint64_t inprops2)
Definition: properties.cc:73
ComposeFstImplOptions(const CacheImplOptions< CacheStore > &opts, M1 *matcher1=nullptr, M2 *matcher2=nullptr, Filter *filter=nullptr, StateTable *state_table=nullptr)
Definition: compose.h:121
bool Done() const final
Definition: compose.h:852
size_t NumOutputEpsilons(StateId s)
Definition: compose.h:212
ComposeFilter filter_type
Definition: compose.h:965
MatchType LookAheadMatchType(const Matcher1 &m1, const Matcher2 &m2)
ComposeOptions(bool connect=true, ComposeFilter filter_type=AUTO_FILTER)
Definition: compose.h:967
Arc::Weight Final(const ExpandedFst< Arc > &fst, typename Arc::StateId s)
Definition: expanded-fst.h:107
const SymbolTable * OutputSymbols() const
Definition: fst.h:761
MatchType
Definition: fst.h:187
ComposeFstMatcher(const ComposeFst< Arc, CacheStore > *fst, MatchType match_type)
Definition: compose.h:771
ErrorWeight Times(const ErrorWeight &, const ErrorWeight &)
Definition: error-weight.h:64
constexpr uint64_t kError
Definition: properties.h:52
ComposeFst(const Fst< Arc > &fst1, const Fst< Arc > &fst2, const CacheOptions &opts=CacheOptions())
Definition: compose.h:593
static std::shared_ptr< Impl > CreateBase(const Fst< Arc > &fst1, const Fst< Arc > &fst2, const CacheOptions &opts)
Definition: compose.h:677
void SetOutputSymbols(const SymbolTable *osyms)
Definition: fst.h:771
SetType
Definition: set-weight.h:59
typename Matcher2::FST FST2
Definition: compose.h:244
typename ComposeFst< Arc, CacheStore >::Arc Arc
Definition: cache.h:1156
void Connect(MutableFst< Arc > *fst)
Definition: connect.h:47
ssize_t NumArcs(const ExpandedFst< Arc > &fst, typename Arc::StateId s)
Definition: expanded-fst.h:113
typename CacheStore::State State
Definition: compose.h:252
void InitArcIterator(StateId s, ArcIteratorData< Arc > *data)
Definition: compose.h:217
To down_cast(From *f)
Definition: compat.h:50
void InitArcIterator(StateId s, ArcIteratorData< Arc > *data) const override
Definition: compose.h:629
MatcherBase< Arc > * InitMatcher(const ComposeFst< Arc, CacheStore > &fst, MatchType match_type) const override
Definition: compose.h:336
StateTable * state_table
Definition: compose.h:105
const Matcher1 * GetMatcher1() const
Definition: compose.h:320
constexpr int kNoStateId
Definition: fst.h:196
ComposeFstMatcher(const ComposeFst< Arc, CacheStore > &fst, MatchType match_type)
Definition: compose.h:755
#define FSTERROR()
Definition: util.h:56
typename Arc::Weight Weight
Definition: impl-to-fst.h:45
StateTable * GetStateTable()
Definition: compose.h:334
typename Arc::Weight Weight
Definition: compose.h:249
ssize_t NumInputEpsilons(const ExpandedFst< Arc > &fst, typename Arc::StateId s)
Definition: expanded-fst.h:118
MatchType Type(bool test) const override
Definition: compose.h:804
typename CacheStore::Arc Arc
Definition: compose.h:246
virtual uint64_t Properties() const
Definition: fst.h:701
bool Done() const
Definition: matcher.h:1559
constexpr uint64_t kCopyProperties
Definition: properties.h:163
constexpr uint64_t kCommutative
Definition: weight.h:144
void InitStateIterator(StateIteratorData< Arc > *data) const override
Definition: compose.h:729
const Filter * GetFilter() const
Definition: compose.h:328
void Compose(const Fst< Arc > &ifst1, const Fst< Arc > &ifst2, MutableFst< Arc > *ofst, const ComposeOptions &opts=ComposeOptions())
Definition: compose.h:1005
ComposeFst * Copy(bool safe=false) const override
Definition: compose.h:623
ComposeFstImplBase(const CacheOptions &opts)
Definition: compose.h:174
typename Arc::StateId StateId
Definition: compose.h:248
ComposeFst(std::shared_ptr< Impl > impl)
Definition: compose.h:641
size_t NumInputEpsilons(StateId s)
Definition: compose.h:207
#define VLOG(level)
Definition: log.h:54
bool Done() const
Definition: fst.h:532
std::unique_ptr< StateIteratorBase< Arc > > base
Definition: fst.h:382
void Next()
Definition: matcher.h:1563
const FST1 & GetFst1() const
Definition: compose.h:316
typename Arc::StateId StateId
Definition: compose.h:743
ComposeFst(const ComposeFst &fst, bool safe=false)
Definition: compose.h:618
bool Find(Label label)
Definition: matcher.h:1557
ComposeFstMatcher(const ComposeFstMatcher< CacheStore, Filter, StateTable > &matcher, bool safe=false)
Definition: compose.h:785
constexpr uint64_t kOLabelInvariantProperties
Definition: properties.h:270
ComposeFstImpl * Copy() const override
Definition: compose.h:285
const FST2 & GetFst2() const
Definition: compose.h:318
ComposeFstImpl(const ComposeFstImpl &impl)
Definition: compose.h:270
const Matcher2 * GetMatcher2() const
Definition: compose.h:324
static std::shared_ptr< Impl > CreateBase2(const typename Matcher1::FST &fst1, const typename Matcher2::FST &fst2, const ComposeFstImplOptions< Matcher1, Matcher2, Filter, StateTuple, CacheStore > &opts)
Definition: compose.h:645
void SetInputSymbols(const SymbolTable *isyms)
Definition: fst.h:767
typename CacheStore::Arc Arc
Definition: compose.h:741
const std::string & Type() const
Definition: fst.h:697
virtual MatcherBase< Arc > * InitMatcher(const F &fst, MatchType match_type) const
Definition: compose.h:222
constexpr uint64_t kILabelInvariantProperties
Definition: properties.h:261
MatcherBase< Arc > * InitMatcher(MatchType match_type) const override
Definition: compose.h:633
typename Filter::FilterState FilterState
Definition: compose.h:251
ComposeFst(const Fst< Arc > &fst1, const Fst< Arc > &fst2, const ComposeFstOptions< Arc, Matcher, Filter, StateTuple > &opts)
Definition: compose.h:601
void SetState(StateId s) final
Definition: compose.h:828
typename Matcher1::FST FST1
Definition: compose.h:243
uint64_t Properties(uint64_t inprops) const override
Definition: compose.h:826
typename Arc::StateId StateId
Definition: impl-to-fst.h:44
void SetState(StateId s)
Definition: matcher.h:1555
constexpr uint64_t kFstProperties
Definition: properties.h:326
ComposeFstOptions(const CacheOptions &opts=CacheOptions(), M *matcher1=nullptr, M *matcher2=nullptr, Filter *filter=nullptr, StateTable *state_table=nullptr)
Definition: compose.h:70
const Arc & Value() const final
Definition: compose.h:856
constexpr uint64_t kUnweighted
Definition: properties.h:106
const Fst< Arc > & GetFst() const override
Definition: compose.h:824
typename Arc::Weight Weight
Definition: compose.h:744
typename ComposeFst< Arc, CacheStore >::Arc Arc
Definition: cache.h:1202
const SymbolTable * InputSymbols() const
Definition: fst.h:759
ComposeFstImplBase(const CacheImplOptions< CacheStore > &opts)
Definition: compose.h:171
void SetType(std::string_view type)
Definition: fst.h:699
typename Filter::FilterState FilterState
Definition: compose.h:748
uint64_t Properties(uint64_t mask) const override
Definition: compose.h:290
ComposeFstMatcher * Copy(bool safe=false) const override
Definition: compose.h:800
ArcIterator(const ComposeFst< Arc, CacheStore > &fst, StateId s)
Definition: compose.h:722
ComposeFstImplBase(const ComposeFstImplBase &impl)
Definition: compose.h:176
typename CacheStore::State State
Definition: compose.h:583
void Next() final
Definition: compose.h:858
bool CompatSymbols(const SymbolTable *syms1, const SymbolTable *syms2, bool warning=true)
void Expand(const Fst< Arc > &ifst, const std::vector< std::pair< typename Arc::Label, typename Arc::Label >> &parens, const std::vector< typename Arc::Label > &assignments, MutableFst< Arc > *ofst, const MPdtExpandOptions &opts)
Definition: expand.h:323
const Arc & Value() const
Definition: matcher.h:1561
Impl * GetMutableImpl() const
Definition: impl-to-fst.h:125
typename Arc::Label Label
Definition: compose.h:247
ComposeFilter
Definition: compose.h:953
size_t gc_limit
Definition: cache.h:52
StateIterator(const ComposeFst< Arc, CacheStore > &fst)
Definition: compose.h:710
bool Find(Label label) final
Definition: compose.h:837
const Impl * GetImpl() const
Definition: impl-to-fst.h:123
ComposeFstImplOptions(const CacheOptions &opts, M1 *matcher1=nullptr, M2 *matcher2=nullptr, Filter *filter=nullptr, StateTable *state_table=nullptr)
Definition: compose.h:109
constexpr uint32_t kRequireMatch
Definition: matcher.h:129
StateTable * state_table
Definition: compose.h:68