Blame view

tools/openfst-1.6.7/src/include/fst/visit.h 9.11 KB
8dcb6dfcb   Yannick Estève   first commit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
  // See www.openfst.org for extensive documentation on this weighted
  // finite-state transducer library.
  //
  // Queue-dependent visitation of finite-state transducers. See also dfs-visit.h.
  
  #ifndef FST_VISIT_H_
  #define FST_VISIT_H_
  
  
  #include <fst/arcfilter.h>
  #include <fst/mutable-fst.h>
  
  
  namespace fst {
  
  // Visitor Interface: class determining actions taken during a visit. If any of
  // the boolean member functions return false, the visit is aborted by first
  // calling FinishState() on all unfinished (grey) states and then calling
  // FinishVisit().
  //
  // Note this is more general than the visitor interface in dfs-visit.h but lacks
  // some DFS-specific behavior.
  //
  // template <class Arc>
  // class Visitor {
  //  public:
  //   using StateId = typename Arc::StateId;
  //
  //   Visitor(T *return_data);
  //
  //   // Invoked before visit.
  //   void InitVisit(const Fst<Arc> &fst);
  //
  //   // Invoked when state discovered (2nd arg is visitation root).
  //   bool InitState(StateId s, StateId root);
  //
  //   // Invoked when arc to white/undiscovered state examined.
  //   bool WhiteArc(StateId s, const Arc &arc);
  //
  //   // Invoked when arc to grey/unfinished state examined.
  //   bool GreyArc(StateId s, const Arc &arc);
  //
  //   // Invoked when arc to black/finished state examined.
  //   bool BlackArc(StateId s, const Arc &arc);
  //
  //   // Invoked when state finished.
  //   void FinishState(StateId s);
  //
  //   // Invoked after visit.
  //   void FinishVisit();
  // };
  
  // Performs queue-dependent visitation. Visitor class argument determines
  // actions and contains any return data. ArcFilter determines arcs that are
  // considered. If 'access_only' is true, performs visitation only to states
  // accessible from the initial state.
  template <class FST, class Visitor, class Queue, class ArcFilter>
  void Visit(const FST &fst, Visitor *visitor, Queue *queue, ArcFilter filter,
             bool access_only = false) {
    using Arc = typename FST::Arc;
    using StateId = typename Arc::StateId;
    visitor->InitVisit(fst);
    const auto start = fst.Start();
    if (start == kNoStateId) {
      visitor->FinishVisit();
      return;
    }
    // An FST's state's visit color.
    static constexpr uint8 kWhiteState = 0x01;  // Undiscovered.
    static constexpr uint8 kGreyState = 0x02;   // Discovered & unfinished.
    static constexpr uint8 kBlackState = 0x04;  // Finished.
    // We destroy an iterator as soon as possible and mark it so.
    static constexpr uint8 kArcIterDone = 0x08;
    std::vector<uint8> state_status;
    std::vector<ArcIterator<FST> *> arc_iterator;
    MemoryPool<ArcIterator<FST>> aiter_pool;
    StateId nstates = start + 1;  // Number of known states in general case.
    bool expanded = false;
    if (fst.Properties(kExpanded, false)) {  // Tests if expanded, then uses
      nstates = CountStates(fst);            // ExpandedFst::NumStates().
      expanded = true;
    }
    state_status.resize(nstates, kWhiteState);
    arc_iterator.resize(nstates);
    StateIterator<Fst<Arc>> siter(fst);
    // Continues visit while true.
    bool visit = true;
    // Iterates over trees in visit forest.
    for (auto root = start; visit && root < nstates;) {
      visit = visitor->InitState(root, root);
      state_status[root] = kGreyState;
      queue->Enqueue(root);
      while (!queue->Empty()) {
        auto state = queue->Head();
        if (state >= state_status.size()) {
          nstates = state + 1;
          state_status.resize(nstates, kWhiteState);
          arc_iterator.resize(nstates);
        }
        // Creates arc iterator if needed.
        if (!arc_iterator[state] && !(state_status[state] & kArcIterDone) &&
            visit) {
          arc_iterator[state] = new (&aiter_pool) ArcIterator<FST>(fst, state);
        }
        // Deletes arc iterator if done.
        auto *aiter = arc_iterator[state];
        if ((aiter && aiter->Done()) || !visit) {
          Destroy(aiter, &aiter_pool);
          arc_iterator[state] = nullptr;
          state_status[state] |= kArcIterDone;
        }
        // Dequeues state and marks black if done.
        if (state_status[state] & kArcIterDone) {
          queue->Dequeue();
          visitor->FinishState(state);
          state_status[state] = kBlackState;
          continue;
        }
        const auto &arc = aiter->Value();
        if (arc.nextstate >= state_status.size()) {
          nstates = arc.nextstate + 1;
          state_status.resize(nstates, kWhiteState);
          arc_iterator.resize(nstates);
        }
        // Visits respective arc types.
        if (filter(arc)) {
          // Enqueues destination state and marks grey if white.
          if (state_status[arc.nextstate] == kWhiteState) {
            visit = visitor->WhiteArc(state, arc);
            if (!visit) continue;
            visit = visitor->InitState(arc.nextstate, root);
            state_status[arc.nextstate] = kGreyState;
            queue->Enqueue(arc.nextstate);
          } else if (state_status[arc.nextstate] == kBlackState) {
            visit = visitor->BlackArc(state, arc);
          } else {
            visit = visitor->GreyArc(state, arc);
          }
        }
        aiter->Next();
        // Destroys an iterator ASAP for efficiency.
        if (aiter->Done()) {
          Destroy(aiter, &aiter_pool);
          arc_iterator[state] = nullptr;
          state_status[state] |= kArcIterDone;
        }
      }
      if (access_only) break;
      // Finds next tree root.
      for (root = (root == start) ? 0 : root + 1;
           root < nstates && state_status[root] != kWhiteState; ++root) {
      }
      // Check for a state beyond the largest known state.
      if (!expanded && root == nstates) {
        for (; !siter.Done(); siter.Next()) {
          if (siter.Value() == nstates) {
            ++nstates;
            state_status.push_back(kWhiteState);
            arc_iterator.push_back(nullptr);
            break;
          }
        }
      }
    }
    visitor->FinishVisit();
  }
  
  template <class Arc, class Visitor, class Queue>
  inline void Visit(const Fst<Arc> &fst, Visitor *visitor, Queue *queue) {
    Visit(fst, visitor, queue, AnyArcFilter<Arc>());
  }
  
  // Copies input FST to mutable FST following queue order.
  template <class A>
  class CopyVisitor {
   public:
    using Arc = A;
    using StateId = typename Arc::StateId;
  
    explicit CopyVisitor(MutableFst<Arc> *ofst) : ifst_(nullptr), ofst_(ofst) {}
  
    void InitVisit(const Fst<A> &ifst) {
      ifst_ = &ifst;
      ofst_->DeleteStates();
      ofst_->SetStart(ifst_->Start());
    }
  
    bool InitState(StateId state, StateId) {
      while (ofst_->NumStates() <= state) ofst_->AddState();
      return true;
    }
  
    bool WhiteArc(StateId state, const Arc &arc) {
      ofst_->AddArc(state, arc);
      return true;
    }
  
    bool GreyArc(StateId state, const Arc &arc) {
      ofst_->AddArc(state, arc);
      return true;
    }
  
    bool BlackArc(StateId state, const Arc &arc) {
      ofst_->AddArc(state, arc);
      return true;
    }
  
    void FinishState(StateId state) {
      ofst_->SetFinal(state, ifst_->Final(state));
    }
  
    void FinishVisit() {}
  
   private:
    const Fst<Arc> *ifst_;
    MutableFst<Arc> *ofst_;
  };
  
  // Visits input FST up to a state limit following queue order.
  template <class A>
  class PartialVisitor {
   public:
    using Arc = A;
    using StateId = typename Arc::StateId;
  
    explicit PartialVisitor(StateId maxvisit)
        : fst_(nullptr), maxvisit_(maxvisit) {}
  
    void InitVisit(const Fst<A> &ifst) {
      fst_ = &ifst;
      ninit_ = 0;
      nfinish_ = 0;
    }
  
    bool InitState(StateId state, StateId root) {
      ++ninit_;
      return ninit_ <= maxvisit_;
    }
  
    bool WhiteArc(StateId state, const Arc &arc) { return true; }
  
    bool GreyArc(StateId state, const Arc &arc) { return true; }
  
    bool BlackArc(StateId state, const Arc &arc) { return true; }
  
    void FinishState(StateId state) {
      fst_->Final(state);  // Visits super-final arc.
      ++nfinish_;
    }
  
    void FinishVisit() {}
  
    StateId NumInitialized() { return ninit_; }
  
    StateId NumFinished() { return nfinish_; }
  
   private:
    const Fst<Arc> *fst_;
    StateId maxvisit_;
    StateId ninit_;
    StateId nfinish_;
  };
  
  // Copies input FST to mutable FST up to a state limit following queue order.
  template <class A>
  class PartialCopyVisitor : public CopyVisitor<A> {
   public:
    using Arc = A;
    using StateId = typename Arc::StateId;
  
    using CopyVisitor<A>::WhiteArc;
  
    PartialCopyVisitor(MutableFst<Arc> *ofst, StateId maxvisit,
                       bool copy_grey = true, bool copy_black = true)
        : CopyVisitor<A>(ofst), maxvisit_(maxvisit),
          copy_grey_(copy_grey), copy_black_(copy_black) {}
  
    void InitVisit(const Fst<A> &ifst) {
      CopyVisitor<A>::InitVisit(ifst);
      ninit_ = 0;
      nfinish_ = 0;
    }
  
    bool InitState(StateId state, StateId root) {
      CopyVisitor<A>::InitState(state, root);
      ++ninit_;
      return ninit_ <= maxvisit_;
    }
  
    bool GreyArc(StateId state, const Arc &arc) {
      if (copy_grey_) return CopyVisitor<A>::GreyArc(state, arc);
      return true;
    }
  
    bool BlackArc(StateId state, const Arc &arc) {
      if (copy_black_) return CopyVisitor<A>::BlackArc(state, arc);
      return true;
    }
  
    void FinishState(StateId state) {
      CopyVisitor<A>::FinishState(state);
      ++nfinish_;
    }
  
    void FinishVisit() {}
  
    StateId NumInitialized() { return ninit_; }
  
    StateId NumFinished() { return nfinish_; }
  
   private:
    StateId maxvisit_;
    StateId ninit_;
    StateId nfinish_;
    const bool copy_grey_;
    const bool copy_black_;
  };
  
  }  // namespace fst
  
  #endif  // FST_VISIT_H_