lookahead-filter.h revision f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2
1// lookahead-filter.h
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// Copyright 2005-2010 Google, Inc.
16// Author: riley@google.com (Michael Riley)
17//
18// \file
19// Composition filters to support lookahead matchers, useful for improving
20// composition efficiency with certain inputs.
21
22#ifndef FST_LIB_LOOKAHEAD_FILTER_H__
23#define FST_LIB_LOOKAHEAD_FILTER_H__
24
25#include <vector>
26using std::vector;
27
28#include <fst/fst.h>
29#include <fst/lookahead-matcher.h>
30
31
32namespace fst {
33
34// Identifies and verifies the capabilities of the matcher to be used for
35// lookahead with the composition filters below. This version is passed
36// the matchers.
37template <class M1, class M2>
38MatchType LookAheadMatchType(const M1 &m1, const M2 &m2) {
39  MatchType type1 = m1.Type(false);
40  MatchType type2 = m2.Type(false);
41  if (type1 == MATCH_OUTPUT &&
42      m1.Flags() & kOutputLookAheadMatcher)
43    return MATCH_OUTPUT;
44  else if (type2 == MATCH_INPUT &&
45           m2.Flags() & kInputLookAheadMatcher)
46    return MATCH_INPUT;
47  else if (m1.Flags() & kOutputLookAheadMatcher &&
48           m1.Type(true) == MATCH_OUTPUT)
49    return MATCH_OUTPUT;
50  else if (m2.Flags() & kInputLookAheadMatcher &&
51           m2.Type(true) == MATCH_INPUT)
52    return MATCH_INPUT;
53  else
54    return MATCH_NONE;
55}
56
57// Identifies and verifies the capabilities of the matcher to be used for
58// lookahead with the composition filters below. This version uses the
59// Fst's default matchers.
60template <class Arc>
61MatchType LookAheadMatchType(const Fst<Arc> &fst1, const Fst<Arc> &fst2) {
62  LookAheadMatcher< Fst <Arc> > matcher1(fst1, MATCH_OUTPUT);
63  LookAheadMatcher< Fst <Arc> > matcher2(fst2, MATCH_INPUT);
64  return LookAheadMatchType(matcher1, matcher2);
65}
66
67//
68// LookAheadSelector - a helper class for selecting among possibly
69// distinct FST and matcher types w/o using a common base class. This
70// lets us avoid virtual function calls.
71//
72
73// Stores and returns the appropriate FST and matcher for lookahead.
74// It is templated on the matcher types.  General case has no methods
75// since not currently supported.
76template <class M1, class M2, MatchType MT>
77class LookAheadSelector {
78};
79
80// Stores and returns the appropriate FST and matcher for lookahead.
81// Specialized for two matchers of same type with the (match) 'type'
82// arg determining which is used for lookahead.
83template <class M, MatchType MT>
84class LookAheadSelector<M, M, MT> {
85 public:
86  typedef typename M::Arc Arc;
87  typedef typename M::FST F;
88
89  LookAheadSelector(M *lmatcher1, M *lmatcher2, MatchType type)
90      : lmatcher1_(lmatcher1->Copy()),
91        lmatcher2_(lmatcher2->Copy()),
92        type_(type) {}
93
94  LookAheadSelector(const LookAheadSelector<M, M, MT> &selector)
95      : lmatcher1_(selector.lmatcher1_->Copy()),
96        lmatcher2_(selector.lmatcher2_->Copy()),
97        type_(selector.type_) {}
98
99  ~LookAheadSelector() {
100    delete lmatcher1_;
101    delete lmatcher2_;
102  }
103
104  const F &GetFst() const {
105    return type_ == MATCH_OUTPUT ? lmatcher2_->GetFst() :
106        lmatcher1_->GetFst();
107  }
108
109  M *GetMatcher() const {
110    return type_ == MATCH_OUTPUT ? lmatcher1_ : lmatcher2_;
111  }
112
113 private:
114  M *lmatcher1_;
115  M *lmatcher2_;
116  MatchType type_;
117
118  void operator=(const LookAheadSelector<M, M, MT> &);  // disallow
119};
120
121// Stores and returns the appropriate FST and matcher for lookahead.
122// Specialized for lookahead on input labels.
123template <class M1, class M2>
124class LookAheadSelector<M1, M2, MATCH_INPUT> {
125 public:
126  typedef typename M1::FST F1;
127
128  LookAheadSelector(M1 *lmatcher1, M2 *lmatcher2, MatchType)
129      : fst_(lmatcher1->GetFst().Copy()),
130        lmatcher_(lmatcher2->Copy()) {}
131
132  LookAheadSelector(const LookAheadSelector<M1, M2, MATCH_INPUT> &selector)
133      : fst_(selector.fst_->Copy()),
134        lmatcher_(selector.lmatcher_->Copy()) {}
135
136  ~LookAheadSelector() {
137    delete lmatcher_;
138    delete fst_;
139  }
140
141  const F1 &GetFst() const { return *fst_; }
142
143  M2 *GetMatcher() const { return lmatcher_; }
144
145 private:
146  const F1 *fst_;
147  M2 *lmatcher_;
148
149  void operator=(const LookAheadSelector<M1, M2, MATCH_INPUT> &);  // disallow
150};
151
152
153// Stores and returns the appropriate FST and matcher for lookahead.
154// Specialized for lookahead on output labels.
155template <class M1, class M2>
156class LookAheadSelector<M1, M2, MATCH_OUTPUT> {
157 public:
158  typedef typename M2::FST F2;
159
160  LookAheadSelector(M1 *lmatcher1, M2 *lmatcher2, MatchType)
161      : fst_(lmatcher2->GetFst().Copy()),
162        lmatcher_(lmatcher1->Copy()) {}
163
164  LookAheadSelector(const LookAheadSelector<M1, M2, MATCH_OUTPUT> &selector)
165      : fst_(selector.fst_->Copy()),
166        lmatcher_(selector.lmatcher_->Copy()) {}
167
168  ~LookAheadSelector() {
169    delete lmatcher_;
170    delete fst_;
171  }
172
173  const F2 &GetFst() const { return *fst_; }
174
175  M1 *GetMatcher() const { return lmatcher_; }
176
177 private:
178  const F2 *fst_;
179  M1 *lmatcher_;
180
181  void operator=(const LookAheadSelector<M1, M2, MATCH_OUTPUT> &);  // disallow
182};
183
184// This filter uses a lookahead matcher in FilterArc(arc1, arc2) to
185// examine the future of the composition state (arc1.nextstate,
186// arc2.nextstate), blocking moving forward when its determined to be
187// non-coaccessible. It is templated on an underlying filter,
188// typically the epsilon filter.  Which matcher is the lookahead
189// matcher is determined by the template argument MT unless it is
190// MATCH_BOTH. In that case, both matcher arguments must be lookahead
191// matchers of the same type and one will be selected by
192// LookAheadMatchType() based on their capability.
193template <class F,
194          class M1 = LookAheadMatcher<typename F::FST1>,
195          class M2 = M1,
196          MatchType MT = MATCH_BOTH>
197class LookAheadComposeFilter {
198 public:
199  typedef typename F::FST1 FST1;
200  typedef typename F::FST2 FST2;
201  typedef typename F::Arc Arc;
202  typedef typename F::Matcher1 Matcher1;
203  typedef typename F::Matcher2 Matcher2;
204  typedef typename F::FilterState FilterState;
205  typedef LookAheadComposeFilter<F, M1, M2, MT> Filter;
206
207  typedef typename Arc::StateId StateId;
208  typedef typename Arc::Label Label;
209  typedef typename Arc::Weight Weight;
210
211  LookAheadComposeFilter(const FST1 &fst1, const FST2 &fst2,
212                         M1 *matcher1,  M2 *matcher2)
213      : filter_(fst1, fst2, matcher1, matcher2),
214        lookahead_type_(MT == MATCH_BOTH ?
215                        LookAheadMatchType(*filter_.GetMatcher1(),
216                                           *filter_.GetMatcher2()) : MT),
217        selector_(filter_.GetMatcher1(), filter_.GetMatcher2(),
218                  lookahead_type_),
219        flags_(lookahead_type_ == MATCH_OUTPUT ?
220               filter_.GetMatcher1()->Flags() :
221               filter_.GetMatcher2()->Flags()) {
222    if (lookahead_type_ == MATCH_NONE) {
223      FSTERROR() << "LookAheadComposeFilter: 1st argument cannot "
224                 << "match/look-ahead on output labels and 2nd argument "
225                 << "cannot match/look-ahead on input labels.";
226    }
227    selector_.GetMatcher()->InitLookAheadFst(selector_.GetFst());
228  }
229
230  LookAheadComposeFilter(const LookAheadComposeFilter<F, M1, M2, MT> &filter,
231                         bool safe = false)
232      : filter_(filter.filter_, safe),
233        lookahead_type_(filter.lookahead_type_),
234        selector_(filter_.GetMatcher1(), filter_.GetMatcher2(),
235                  lookahead_type_),
236        flags_(filter.flags_) {
237    selector_.GetMatcher()->InitLookAheadFst(selector_.GetFst(), true);
238  }
239
240  FilterState Start() const {
241    return filter_.Start();
242  }
243
244  void SetState(StateId s1, StateId s2, const FilterState &f) {
245    filter_.SetState(s1, s2, f);
246  }
247
248  FilterState FilterArc(Arc *arc1, Arc *arc2) const {
249    lookahead_arc_ = false;
250
251    const FilterState &f = filter_.FilterArc(arc1, arc2);
252    if (f == FilterState::NoState())
253      return FilterState::NoState();
254
255    return LookAheadOutput() ? LookAheadFilterArc(arc1, arc2, f) :
256        LookAheadFilterArc(arc2, arc1, f);
257  }
258
259  void FilterFinal(Weight *weight1, Weight *weight2) const {
260    filter_.FilterFinal(weight1, weight2);
261  }
262
263  // Return resp matchers. Ownership stays with filter.
264  Matcher1 *GetMatcher1() { return filter_.GetMatcher1(); }
265  Matcher2 *GetMatcher2() { return filter_.GetMatcher2(); }
266
267  const LookAheadSelector<Matcher1, Matcher2, MT> &Selector() const {
268    return selector_;
269  }
270
271  uint64 Properties(uint64 inprops) const {
272    uint64 outprops = filter_.Properties(inprops);
273    if (lookahead_type_ == MATCH_NONE)
274      outprops |= kError;
275    return outprops;
276  }
277
278  uint32 LookAheadFlags() const { return flags_; }
279
280  bool LookAheadArc() const { return lookahead_arc_; }
281
282  bool LookAheadOutput() const {
283    if (MT == MATCH_OUTPUT)
284      return true;
285    else if (MT == MATCH_INPUT)
286      return false;
287    else if (lookahead_type_ == MATCH_OUTPUT)
288      return true;
289    else
290      return false;
291  }
292
293 private:
294  FilterState LookAheadFilterArc(Arc *arca, Arc *arcb,
295                                 const FilterState &f) const {
296    Label &labela = LookAheadOutput() ? arca->olabel : arca->ilabel;
297
298    if (labela != 0 && !(flags_ & kLookAheadNonEpsilons))
299      return f;
300    if (labela == 0 && !(flags_ & kLookAheadEpsilons))
301      return f;
302
303    lookahead_arc_ = true;
304    selector_.GetMatcher()->SetState(arca->nextstate);
305
306    return selector_.GetMatcher()->LookAheadFst(selector_.GetFst(),
307                                                arcb->nextstate) ? f :
308                                                FilterState::NoState();
309  }
310
311  F filter_;                    // Underlying filter
312  MatchType lookahead_type_;    // Lookahead match type
313  LookAheadSelector<Matcher1, Matcher2, MT> selector_;
314  uint32 flags_;                // Lookahead flags
315  mutable bool lookahead_arc_;  // Look-ahead performed at last FilterArc()?
316
317  void operator=(const LookAheadComposeFilter<F, M1, M2> &);  // disallow
318};
319
320
321// This filter adds weight-pushing to a lookahead composition filter
322// using the LookAheadWeight() method of matcher argument. It is
323// templated on an underlying lookahead filter, typically the basic
324// lookahead filter. Weight-pushing in composition brings weights
325// forward as much as possible based on the lookahead information.
326template <class F,
327          class M1 = LookAheadMatcher<typename F::FST1>,
328          class M2 = M1,
329          MatchType MT = MATCH_BOTH>
330class PushWeightsComposeFilter {
331 public:
332  typedef typename F::FST1 FST1;
333  typedef typename F::FST2 FST2;
334  typedef typename F::Arc Arc;
335  typedef typename F::Matcher1 Matcher1;
336  typedef typename F::Matcher2 Matcher2;
337  typedef typename F::FilterState FilterState1;
338  typedef WeightFilterState<typename Arc::Weight> FilterState2;
339  typedef PairFilterState<FilterState1, FilterState2> FilterState;
340
341  typedef typename Arc::StateId StateId;
342  typedef typename Arc::Label Label;
343  typedef typename Arc::Weight Weight;
344
345  PushWeightsComposeFilter(const FST1 &fst1, const FST2 &fst2,
346                         M1 *matcher1,  M2 *matcher2)
347      : filter_(fst1, fst2, matcher1, matcher2),
348        f_(FilterState::NoState()) {}
349
350  PushWeightsComposeFilter(const PushWeightsComposeFilter<F, M1, M2, MT>
351                           &filter,
352                           bool safe = false)
353      : filter_(filter.filter_, safe),
354        f_(FilterState::NoState()) {}
355
356  FilterState Start() const {
357    return FilterState(filter_.Start(), FilterState2(Weight::One()));
358  }
359
360  void SetState(StateId s1, StateId s2, const FilterState &f) {
361    f_ = f;
362    filter_.SetState(s1, s2, f.GetState1());
363  }
364
365  FilterState FilterArc(Arc *arc1, Arc *arc2) const {
366    const FilterState1 &f1 = filter_.FilterArc(arc1, arc2);
367    if (f1 == FilterState1::NoState())
368      return FilterState::NoState();
369
370    if (!(LookAheadFlags() & kLookAheadWeight))
371      return FilterState(f1, FilterState2(Weight::One()));
372
373    const Weight &lweight = filter_.LookAheadArc() ?
374        Selector().GetMatcher()->LookAheadWeight() : Weight::One();
375    const FilterState2 &f2 = f_.GetState2();
376    const Weight &fweight = f2.GetWeight();
377
378    arc2->weight = Divide(Times(arc2->weight, lweight), fweight);
379    return FilterState(f1, FilterState2(lweight));
380  }
381
382  void FilterFinal(Weight *weight1, Weight *weight2) const {
383    filter_.FilterFinal(weight1, weight2);
384    if (!(LookAheadFlags() & kLookAheadWeight) || *weight1 == Weight::Zero())
385      return;
386
387    const FilterState2 &f2 = f_.GetState2();
388    const Weight &fweight = f2.GetWeight();
389    *weight1 = Divide(*weight1, fweight);
390  }
391  // Return resp matchers. Ownership states with filter.
392  Matcher1 *GetMatcher1() { return filter_.GetMatcher1(); }
393  Matcher2 *GetMatcher2() { return filter_.GetMatcher2(); }
394
395  const LookAheadSelector<Matcher1, Matcher2, MT> &Selector() const {
396    return filter_.Selector();
397  }
398
399  uint32 LookAheadFlags() const { return filter_.LookAheadFlags(); }
400  bool LookAheadArc() const { return filter_.LookAheadArc(); }
401  bool LookAheadOutput() const { return filter_.LookAheadOutput(); }
402
403  uint64 Properties(uint64 props) const {
404    return filter_.Properties(props) & kWeightInvariantProperties;
405  }
406
407 private:
408  F filter_;                       // Underlying filter
409  FilterState f_;                  // Current filter state
410
411  void operator=(const PushWeightsComposeFilter<F, M1, M2, MT> &);  // disallow
412};
413
414// This filter adds label-pushing to a lookahead composition filter
415// using the LookAheadPrefix() method of the matcher argument. It is
416// templated on an underlying filter, typically the basic lookahead
417// or weight-pushing lookahead filter. Label-pushing in composition
418// matches labels as early as possible based on the lookahead
419// information.
420template <class F,
421          class M1 = LookAheadMatcher<typename F::FST1>,
422          class M2 = M1,
423          MatchType MT = MATCH_BOTH>
424class PushLabelsComposeFilter {
425 public:
426  typedef typename F::FST1 FST1;
427  typedef typename F::FST2 FST2;
428  typedef typename F::Arc Arc;
429  typedef typename Arc::StateId StateId;
430  typedef typename Arc::Label Label;
431  typedef typename Arc::Weight Weight;
432
433  typedef MultiEpsMatcher<typename F::Matcher1> Matcher1;
434  typedef MultiEpsMatcher<typename F::Matcher2> Matcher2;
435  typedef typename F::FilterState FilterState1;
436  typedef IntegerFilterState<typename Arc::Label> FilterState2;
437  typedef PairFilterState<FilterState1, FilterState2> FilterState;
438
439  PushLabelsComposeFilter(const FST1 &fst1, const FST2 &fst2,
440                         M1 *matcher1,  M2 *matcher2)
441      : filter_(fst1, fst2, matcher1, matcher2),
442        f_(FilterState::NoState()),
443        fst1_(filter_.GetMatcher1()->GetFst()),
444        fst2_(filter_.GetMatcher2()->GetFst()),
445        matcher1_(fst1_, MATCH_OUTPUT,
446                  filter_.LookAheadOutput() ? kMultiEpsList : kMultiEpsLoop,
447                  filter_.GetMatcher1(),
448                  false),
449        matcher2_(fst2_, MATCH_INPUT,
450                  filter_.LookAheadOutput() ? kMultiEpsLoop : kMultiEpsList,
451                  filter_.GetMatcher2(),
452                  false) {}
453
454  PushLabelsComposeFilter(const PushLabelsComposeFilter<F, M1, M2, MT> &filter,
455                          bool safe = false)
456      : filter_(filter.filter_, safe),
457        f_(FilterState::NoState()),
458        fst1_(filter_.GetMatcher1()->GetFst()),
459        fst2_(filter_.GetMatcher2()->GetFst()),
460        matcher1_(fst1_,  MATCH_OUTPUT,
461                  filter_.LookAheadOutput() ? kMultiEpsList : kMultiEpsLoop,
462                  filter_.GetMatcher1(),
463                  false),
464        matcher2_(fst2_, MATCH_INPUT,
465                  filter_.LookAheadOutput() ? kMultiEpsLoop : kMultiEpsList,
466                  filter_.GetMatcher2(),
467                  false) {
468  }
469
470  FilterState Start() const {
471    return FilterState(filter_.Start(), FilterState2(kNoLabel));
472  }
473
474  void SetState(StateId s1, StateId s2, const FilterState &f) {
475    f_ = f;
476    filter_.SetState(s1, s2, f.GetState1());
477    if (!(LookAheadFlags() & kLookAheadPrefix))
478      return;
479
480    narcsa_ = LookAheadOutput() ? internal::NumArcs(fst1_, s1)
481        : internal::NumArcs(fst2_, s2);
482
483    const FilterState2 &f2 = f_.GetState2();
484    const Label &flabel = f2.GetState();
485
486    GetMatcher1()->ClearMultiEpsLabels();
487    GetMatcher2()->ClearMultiEpsLabels();
488    if (flabel != kNoLabel) {                   // Have a lookahead label?
489      GetMatcher1()->AddMultiEpsLabel(flabel);  // Yes, make it a multi-epsilon
490      GetMatcher2()->AddMultiEpsLabel(flabel);  // label so that it matches the
491    }                                           // implicit epsilon arc to be
492  }                                             // modified below when pushing.
493
494  FilterState FilterArc(Arc *arc1, Arc *arc2) const {
495    if (!(LookAheadFlags() & kLookAheadPrefix))
496      return FilterState(filter_.FilterArc(arc1, arc2),
497                         FilterState2(kNoLabel));
498
499    const FilterState2 &f2 = f_.GetState2();
500    const Label &flabel = f2.GetState();
501    if (flabel != kNoLabel)             // Have a lookahead label?
502      return LookAheadOutput() ? PushedLabelFilterArc(arc1, arc2, flabel) :
503          PushedLabelFilterArc(arc2, arc1, flabel);
504
505    const FilterState1 &f1 = filter_.FilterArc(arc1, arc2);
506    if (f1 == FilterState1::NoState())
507      return FilterState::NoState();
508
509    if (!filter_.LookAheadArc())
510      return FilterState(f1, FilterState2(kNoLabel));
511
512    return LookAheadOutput() ? PushLabelFilterArc(arc1, arc2, f1) :
513        PushLabelFilterArc(arc2, arc1, f1);
514  }
515
516  void FilterFinal(Weight *weight1, Weight *weight2) const {
517    filter_.FilterFinal(weight1, weight2);
518    if (!(LookAheadFlags() & kLookAheadPrefix) ||
519        *weight1 == Weight::Zero())
520      return;
521
522    const FilterState2 &f2 = f_.GetState2();
523    const Label &flabel = f2.GetState();
524    if (flabel != kNoLabel)
525      *weight1 = Weight::Zero();
526  }
527
528  // Return resp matchers. Ownership states with filter.
529  Matcher1 *GetMatcher1() { return &matcher1_; }
530  Matcher2 *GetMatcher2() { return &matcher2_; }
531
532  uint64 Properties(uint64 iprops) const {
533    uint64 oprops = filter_.Properties(iprops);
534    if (LookAheadOutput())
535      return oprops & kOLabelInvariantProperties;
536    else
537      return oprops & kILabelInvariantProperties;
538  }
539
540 private:
541  const LookAheadSelector<typename F::Matcher1, typename F::Matcher2, MT>
542  &Selector() const {
543    return filter_.Selector();
544  }
545
546  // Consumes an already pushed label.
547  FilterState PushedLabelFilterArc(Arc *arca, Arc *arcb,
548                                   Label flabel) const {
549    Label &labela = LookAheadOutput() ? arca->olabel : arca->ilabel;
550    const Label &labelb = LookAheadOutput() ? arcb->ilabel : arcb->olabel;
551
552    if (labelb != kNoLabel) {
553      return FilterState::NoState();    // Block non- (multi-) epsilon label
554    } else if (labela == flabel) {
555      labela = 0;                       // Convert match to multi-eps to eps
556      return Start();
557    } else if (labela == 0) {
558      if (narcsa_ == 1)
559        return f_;                      // Take eps; keep state w/ label
560      Selector().GetMatcher()->SetState(arca->nextstate);
561      if (Selector().GetMatcher()->LookAheadLabel(flabel))
562        return f_;                      // Take eps; keep state w/ label
563      else
564        return FilterState::NoState();  // Block non-coaccessible path
565    } else {
566      return FilterState::NoState();    // Block mismatch to multi-eps label
567    }
568  }
569
570  // Pushes a label forward when possible.
571  FilterState PushLabelFilterArc(Arc *arca, Arc *arcb,
572                                 const FilterState1 &f1) const {
573    Label &labela = LookAheadOutput() ? arca->olabel : arca->ilabel;
574    const Label &labelb = LookAheadOutput() ? arcb->olabel : arcb->ilabel;
575
576    if (labelb != 0)                   // No place to push.
577      return FilterState(f1, FilterState2(kNoLabel));
578    if (labela != 0 &&                 // Wrong lookahead prefix type?
579        LookAheadFlags() & kLookAheadNonEpsilonPrefix)
580      return FilterState(f1, FilterState2(kNoLabel));
581
582    Arc larc(kNoLabel, kNoLabel, Weight::Zero(), kNoStateId);
583
584    if (Selector().GetMatcher()->LookAheadPrefix(&larc)) {  // Have prefix arc?
585      labela = LookAheadOutput() ? larc.ilabel : larc.olabel;
586      arcb->ilabel = larc.ilabel;      // Yes, go forward on that arc,
587      arcb->olabel = larc.olabel;      // thus pushing the label.
588      arcb->weight = Times(arcb->weight, larc.weight);
589      arcb->nextstate = larc.nextstate;
590      return FilterState(f1, FilterState2(labela));
591    } else {
592      return FilterState(f1, FilterState2(kNoLabel));
593    }
594  }
595
596  uint32 LookAheadFlags() const { return filter_.LookAheadFlags(); }
597  bool LookAheadArc() const { return filter_.LookAheadArc(); }
598  bool LookAheadOutput() const { return filter_.LookAheadOutput(); }
599
600  F filter_;                  // Underlying filter
601  FilterState f_ ;            // Current filter state
602  const FST1 &fst1_;
603  const FST2 &fst2_;
604  Matcher1 matcher1_;         // Multi-epsilon matcher for fst1
605  Matcher2 matcher2_;         // Multi-epsilon matcher for fst2
606  ssize_t narcsa_;            // Number of arcs leaving look-ahead match FST
607
608  void operator=(const PushLabelsComposeFilter<F, M1, M2, MT> &);  // disallow
609};
610
611//
612// CONVENIENCE CLASS useful for setting up composition with a default
613// look-ahead matcher and filter.
614//
615
616template <class A, MatchType type>  // MATCH_NONE
617class DefaultLookAhead {
618 public:
619  typedef Matcher< Fst<A> > M;
620  typedef SequenceComposeFilter<M> ComposeFilter;
621  typedef M FstMatcher;
622};
623
624// Specializes for MATCH_INPUT to allow lookahead.
625template <class A>
626class DefaultLookAhead<A, MATCH_INPUT> {
627 public:
628  typedef LookAheadMatcher< Fst<A> > M;
629  typedef SequenceComposeFilter<M> SF;
630  typedef LookAheadComposeFilter<SF, M> ComposeFilter;
631  typedef M FstMatcher;
632};
633
634// Specializes for MATCH_OUTPUT to allow lookahead.
635template <class A>
636class DefaultLookAhead<A, MATCH_OUTPUT> {
637 public:
638  typedef LookAheadMatcher< Fst<A> > M;
639  typedef AltSequenceComposeFilter<M> SF;
640  typedef LookAheadComposeFilter<SF, M> ComposeFilter;
641  typedef M FstMatcher;
642};
643
644// Specializes for StdArc to allow weight and label pushing.
645template <>
646class DefaultLookAhead<StdArc, MATCH_INPUT> {
647 public:
648  typedef StdArc A;
649  typedef LookAheadMatcher< Fst<A> > M;
650  typedef SequenceComposeFilter<M> SF;
651  typedef LookAheadComposeFilter<SF, M> LF;
652  typedef PushWeightsComposeFilter<LF, M> WF;
653  typedef PushLabelsComposeFilter<WF, M> ComposeFilter;
654  typedef M FstMatcher;
655};
656
657// Specializes for StdArc to allow weight and label pushing.
658template <>
659class DefaultLookAhead<StdArc, MATCH_OUTPUT> {
660 public:
661  typedef StdArc A;
662  typedef LookAheadMatcher< Fst<A> > M;
663  typedef AltSequenceComposeFilter<M> SF;
664  typedef LookAheadComposeFilter<SF, M>  LF;
665  typedef PushWeightsComposeFilter<LF, M> WF;
666  typedef PushLabelsComposeFilter<WF, M> ComposeFilter;
667  typedef M FstMatcher;
668};
669
670// Specializes for LogArc to allow weight and label pushing.
671template <>
672class DefaultLookAhead<LogArc, MATCH_INPUT> {
673 public:
674  typedef LogArc A;
675  typedef LookAheadMatcher< Fst<A> > M;
676  typedef SequenceComposeFilter<M> SF;
677  typedef LookAheadComposeFilter<SF, M> LF;
678  typedef PushWeightsComposeFilter<LF, M> WF;
679  typedef PushLabelsComposeFilter<WF, M> ComposeFilter;
680  typedef M FstMatcher;
681};
682
683// Specializes for LogArc to allow weight and label pushing.
684template <>
685class DefaultLookAhead<LogArc, MATCH_OUTPUT> {
686 public:
687  typedef LogArc A;
688  typedef LookAheadMatcher< Fst<A> > M;
689  typedef AltSequenceComposeFilter<M> SF;
690  typedef LookAheadComposeFilter<SF, M> LF;
691  typedef PushWeightsComposeFilter<LF, M> WF;
692  typedef PushLabelsComposeFilter<WF, M> ComposeFilter;
693  typedef M FstMatcher;
694};
695
696}  // namespace fst
697
698#endif  // FST_LIB_LOOKAHEAD_FILTER_H__
699