• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // visit.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 // Queue-dependent visitation of finite-state transducers. See also
20 // dfs-visit.h.
21 
22 #ifndef FST_LIB_VISIT_H__
23 #define FST_LIB_VISIT_H__
24 
25 
26 #include <fst/arcfilter.h>
27 #include <fst/mutable-fst.h>
28 
29 
30 namespace fst {
31 
32 // Visitor Interface - class determines actions taken during a visit.
33 // If any of the boolean member functions return false, the visit is
34 // aborted by first calling FinishState() on all unfinished (grey)
35 // states and then calling FinishVisit().
36 //
37 // Note this is more general than the visitor interface in
38 // dfs-visit.h but lacks some DFS-specific behavior.
39 //
40 // template <class Arc>
41 // class Visitor {
42 //  public:
43 //   typedef typename Arc::StateId StateId;
44 //
45 //   Visitor(T *return_data);
46 //   // Invoked before visit
47 //   void InitVisit(const Fst<Arc> &fst);
48 //   // Invoked when state discovered (2nd arg is visitation root)
49 //   bool InitState(StateId s, StateId root);
50 //   // Invoked when arc to white/undiscovered state examined
51 //   bool WhiteArc(StateId s, const Arc &a);
52 //   // Invoked when arc to grey/unfinished state examined
53 //   bool GreyArc(StateId s, const Arc &a);
54 //   // Invoked when arc to black/finished state examined
55 //   bool BlackArc(StateId s, const Arc &a);
56 //   // Invoked when state finished.
57 //   void FinishState(StateId s);
58 //   // Invoked after visit
59 //   void FinishVisit();
60 // };
61 
62 // Performs queue-dependent visitation. Visitor class argument
63 // determines actions and contains any return data. ArcFilter
64 // determines arcs that are considered.
65 //
66 // Note this is more general than DfsVisit() in dfs-visit.h but lacks
67 // some DFS-specific Visitor behavior.
68 template <class Arc, class V, class Q, class ArcFilter>
Visit(const Fst<Arc> & fst,V * visitor,Q * queue,ArcFilter filter)69 void Visit(const Fst<Arc> &fst, V *visitor, Q *queue, ArcFilter filter) {
70 
71   typedef typename Arc::StateId StateId;
72   typedef ArcIterator< Fst<Arc> > AIterator;
73 
74   visitor->InitVisit(fst);
75 
76   StateId start = fst.Start();
77   if (start == kNoStateId) {
78     visitor->FinishVisit();
79     return;
80   }
81 
82   // An Fst state's visit color
83   const unsigned kWhiteState =  0x01;    // Undiscovered
84   const unsigned kGreyState =   0x02;    // Discovered & unfinished
85   const unsigned kBlackState =  0x04;    // Finished
86 
87   // We destroy an iterator as soon as possible and mark it so
88   const unsigned kArcIterDone = 0x08;      // Arc iterator done and destroyed
89 
90   vector<unsigned char> state_status;
91   vector<AIterator *> arc_iterator;
92 
93   StateId nstates = start + 1;             // # of known states in general case
94   bool expanded = false;
95   if (fst.Properties(kExpanded, false)) {  // tests if expanded case, then
96     nstates = CountStates(fst);            // uses ExpandedFst::NumStates().
97     expanded = true;
98   }
99 
100   state_status.resize(nstates, kWhiteState);
101   arc_iterator.resize(nstates);
102   StateIterator< Fst<Arc> > siter(fst);
103 
104   // Continues visit while true
105   bool visit = true;
106 
107   // Iterates over trees in visit forest.
108   for (StateId root = start; visit && root < nstates;) {
109     visit = visitor->InitState(root, root);
110     state_status[root] = kGreyState;
111     queue->Enqueue(root);
112     while (!queue->Empty()) {
113       StateId s = queue->Head();
114       if (s >= state_status.size()) {
115         nstates = s + 1;
116         state_status.resize(nstates, kWhiteState);
117         arc_iterator.resize(nstates);
118       }
119       // Creates arc iterator if needed.
120       if (arc_iterator[s] == 0 && !(state_status[s] & kArcIterDone) && visit)
121         arc_iterator[s] = new AIterator(fst, s);
122       // Deletes arc iterator if done.
123       AIterator *aiter = arc_iterator[s];
124       if ((aiter && aiter->Done()) || !visit) {
125         delete aiter;
126         arc_iterator[s] = 0;
127         state_status[s] |= kArcIterDone;
128       }
129       // Dequeues state and marks black if done
130       if (state_status[s] & kArcIterDone) {
131         queue->Dequeue();
132         visitor->FinishState(s);
133         state_status[s] = kBlackState;
134         continue;
135       }
136 
137       const Arc &arc = aiter->Value();
138       if (arc.nextstate >= state_status.size()) {
139         nstates = arc.nextstate + 1;
140         state_status.resize(nstates, kWhiteState);
141         arc_iterator.resize(nstates);
142       }
143       // Visits respective arc types
144       if (filter(arc)) {
145         // Enqueues destination state and marks grey if white
146         if (state_status[arc.nextstate] == kWhiteState) {
147           visit = visitor->WhiteArc(s, arc);
148           if (!visit) continue;
149           visit = visitor->InitState(arc.nextstate, root);
150           state_status[arc.nextstate] = kGreyState;
151           queue->Enqueue(arc.nextstate);
152         } else if (state_status[arc.nextstate] == kBlackState) {
153           visit = visitor->BlackArc(s, arc);
154         } else {
155           visit = visitor->GreyArc(s, arc);
156         }
157       }
158       aiter->Next();
159       // Destroys an iterator ASAP for efficiency.
160       if (aiter->Done()) {
161         delete aiter;
162         arc_iterator[s] = 0;
163         state_status[s] |= kArcIterDone;
164       }
165     }
166     // Finds next tree root
167     for (root = root == start ? 0 : root + 1;
168          root < nstates && state_status[root] != kWhiteState;
169          ++root);
170 
171     // Check for a state beyond the largest known state
172     if (!expanded && root == nstates) {
173       for (; !siter.Done(); siter.Next()) {
174         if (siter.Value() == nstates) {
175           ++nstates;
176           state_status.push_back(kWhiteState);
177           arc_iterator.push_back(0);
178           break;
179         }
180       }
181     }
182   }
183   visitor->FinishVisit();
184 }
185 
186 
187 template <class Arc, class V, class Q>
Visit(const Fst<Arc> & fst,V * visitor,Q * queue)188 inline void Visit(const Fst<Arc> &fst, V *visitor, Q* queue) {
189   Visit(fst, visitor, queue, AnyArcFilter<Arc>());
190 }
191 
192 // Copies input FST to mutable FST following queue order.
193 template <class A>
194 class CopyVisitor {
195  public:
196   typedef A Arc;
197   typedef typename A::StateId StateId;
198 
CopyVisitor(MutableFst<Arc> * ofst)199   CopyVisitor(MutableFst<Arc> *ofst) : ifst_(0), ofst_(ofst) {}
200 
InitVisit(const Fst<A> & ifst)201   void InitVisit(const Fst<A> &ifst) {
202     ifst_ = &ifst;
203     ofst_->DeleteStates();
204     ofst_->SetStart(ifst_->Start());
205   }
206 
InitState(StateId s,StateId)207   bool InitState(StateId s, StateId) {
208     while (ofst_->NumStates() <= s)
209       ofst_->AddState();
210     return true;
211   }
212 
WhiteArc(StateId s,const Arc & arc)213   bool WhiteArc(StateId s, const Arc &arc) {
214     ofst_->AddArc(s, arc);
215     return true;
216   }
217 
GreyArc(StateId s,const Arc & arc)218   bool GreyArc(StateId s, const Arc &arc) {
219     ofst_->AddArc(s, arc);
220     return true;
221   }
222 
BlackArc(StateId s,const Arc & arc)223   bool BlackArc(StateId s, const Arc &arc) {
224     ofst_->AddArc(s, arc);
225     return true;
226   }
227 
FinishState(StateId s)228   void FinishState(StateId s) {
229     ofst_->SetFinal(s, ifst_->Final(s));
230   }
231 
FinishVisit()232   void FinishVisit() {}
233 
234  private:
235   const Fst<Arc> *ifst_;
236   MutableFst<Arc> *ofst_;
237 };
238 
239 
240 // Visits input FST up to a state limit following queue order.
241 template <class A>
242 class PartialVisitor {
243  public:
244   typedef A Arc;
245   typedef typename A::StateId StateId;
246 
PartialVisitor(StateId maxvisit)247   explicit PartialVisitor(StateId maxvisit) : maxvisit_(maxvisit) {}
248 
InitVisit(const Fst<A> & ifst)249   void InitVisit(const Fst<A> &ifst) { nvisit_ = 0; }
250 
InitState(StateId s,StateId)251   bool InitState(StateId s, StateId) {
252     ++nvisit_;
253     return nvisit_ <= maxvisit_;
254   }
255 
WhiteArc(StateId s,const Arc & arc)256   bool WhiteArc(StateId s, const Arc &arc) { return true; }
GreyArc(StateId s,const Arc & arc)257   bool GreyArc(StateId s, const Arc &arc) { return true; }
BlackArc(StateId s,const Arc & arc)258   bool BlackArc(StateId s, const Arc &arc) { return true; }
FinishState(StateId s)259   void FinishState(StateId s) {}
FinishVisit()260   void FinishVisit() {}
261 
262  private:
263   StateId maxvisit_;
264   StateId nvisit_;
265 };
266 
267 
268 }  // namespace fst
269 
270 #endif  // FST_LIB_VISIT_H__
271