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
172 // Check for a state beyond the largest known state
173 if (!expanded && root == nstates) {
174 for (; !siter.Done(); siter.Next()) {
175 if (siter.Value() == nstates) {
176 ++nstates;
177 state_status.push_back(kWhiteState);
178 arc_iterator.push_back(0);
179 break;
180 }
181 }
182 }
183 }
184 visitor->FinishVisit();
185 }
186
187
188 template <class Arc, class V, class Q>
Visit(const Fst<Arc> & fst,V * visitor,Q * queue)189 inline void Visit(const Fst<Arc> &fst, V *visitor, Q* queue) {
190 Visit(fst, visitor, queue, AnyArcFilter<Arc>());
191 }
192
193 // Copies input FST to mutable FST following queue order.
194 template <class A>
195 class CopyVisitor {
196 public:
197 typedef A Arc;
198 typedef typename A::StateId StateId;
199
CopyVisitor(MutableFst<Arc> * ofst)200 CopyVisitor(MutableFst<Arc> *ofst) : ifst_(0), ofst_(ofst) {}
201
InitVisit(const Fst<A> & ifst)202 void InitVisit(const Fst<A> &ifst) {
203 ifst_ = &ifst;
204 ofst_->DeleteStates();
205 ofst_->SetStart(ifst_->Start());
206 }
207
InitState(StateId s,StateId)208 bool InitState(StateId s, StateId) {
209 while (ofst_->NumStates() <= s)
210 ofst_->AddState();
211 return true;
212 }
213
WhiteArc(StateId s,const Arc & arc)214 bool WhiteArc(StateId s, const Arc &arc) {
215 ofst_->AddArc(s, arc);
216 return true;
217 }
218
GreyArc(StateId s,const Arc & arc)219 bool GreyArc(StateId s, const Arc &arc) {
220 ofst_->AddArc(s, arc);
221 return true;
222 }
223
BlackArc(StateId s,const Arc & arc)224 bool BlackArc(StateId s, const Arc &arc) {
225 ofst_->AddArc(s, arc);
226 return true;
227 }
228
FinishState(StateId s)229 void FinishState(StateId s) {
230 ofst_->SetFinal(s, ifst_->Final(s));
231 }
232
FinishVisit()233 void FinishVisit() {}
234
235 private:
236 const Fst<Arc> *ifst_;
237 MutableFst<Arc> *ofst_;
238 };
239
240
241 // Visits input FST up to a state limit following queue order. If
242 // 'access_only' is true, aborts on visiting first state not
243 // accessible from the initial state.
244 template <class A>
245 class PartialVisitor {
246 public:
247 typedef A Arc;
248 typedef typename A::StateId StateId;
249
250 explicit PartialVisitor(StateId maxvisit, bool access_only = false)
maxvisit_(maxvisit)251 : maxvisit_(maxvisit),
252 access_only_(access_only),
253 start_(kNoStateId) {}
254
InitVisit(const Fst<A> & ifst)255 void InitVisit(const Fst<A> &ifst) {
256 nvisit_ = 0;
257 start_ = ifst.Start();
258 }
259
InitState(StateId s,StateId root)260 bool InitState(StateId s, StateId root) {
261 if (access_only_ && root != start_)
262 return false;
263 ++nvisit_;
264 return nvisit_ <= maxvisit_;
265 }
266
WhiteArc(StateId s,const Arc & arc)267 bool WhiteArc(StateId s, const Arc &arc) { return true; }
GreyArc(StateId s,const Arc & arc)268 bool GreyArc(StateId s, const Arc &arc) { return true; }
BlackArc(StateId s,const Arc & arc)269 bool BlackArc(StateId s, const Arc &arc) { return true; }
FinishState(StateId s)270 void FinishState(StateId s) {}
FinishVisit()271 void FinishVisit() {}
272
273 private:
274 StateId maxvisit_;
275 bool access_only_;
276 StateId nvisit_;
277 StateId start_;
278
279 };
280
281
282 } // namespace fst
283
284 #endif // FST_LIB_VISIT_H__
285