FST  openfst-1.8.3
OpenFst Library
dfs-visit.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 // Depth-first search visitation. See visit.h for more general search queue
19 // disciplines.
20 
21 #ifndef FST_DFS_VISIT_H_
22 #define FST_DFS_VISIT_H_
23 
24 #include <cstddef>
25 #include <cstdint>
26 #include <new>
27 #include <stack>
28 #include <vector>
29 
30 #include <fst/arcfilter.h>
31 #include <fst/fst.h>
32 #include <fst/memory.h>
33 #include <fst/properties.h>
34 
35 namespace fst {
36 
37 // Visitor Interface: class determining actions taken during a depth-first
38 // search-style visit. If any of the boolean member functions return false, the
39 // DFS is aborted by first calling FinishState() on all currently grey states
40 // and then calling FinishVisit().
41 //
42 // This is similar to the more general visitor interface in visit.h, except
43 // that FinishState returns additional information appropriate only for a DFS
44 // and some methods names here are better suited to a DFS.
45 //
46 // template <class Arc>
47 // class Visitor {
48 // public:
49 // using StateId = typename Arc::StateId;
50 //
51 // Visitor(T *return_data);
52 //
53 // // Invoked before DFS visit.
54 // void InitVisit(const Fst<Arc> &fst);
55 //
56 // // Invoked when state discovered (2nd arg is DFS tree root).
57 // bool InitState(StateId s, StateId root);
58 //
59 // // Invoked when tree arc to white/undiscovered state examined.
60 // bool TreeArc(StateId s, const Arc &arc);
61 //
62 // // Invoked when back arc to grey/unfinished state examined.
63 // bool BackArc(StateId s, const Arc &arc);
64 //
65 // // Invoked when forward or cross arc to black/finished state examined.
66 // bool ForwardOrCrossArc(StateId s, const Arc &arc);
67 //
68 // // Invoked when state finished ('s' is tree root, 'parent' is kNoStateId,
69 // // and 'arc' is nullptr).
70 // void FinishState(StateId s, StateId parent, const Arc *arc);
71 //
72 // // Invoked after DFS visit.
73 // void FinishVisit();
74 // };
75 
76 namespace internal {
77 
78 // An FST state's DFS stack state.
79 template <class FST>
80 struct DfsState {
81  using Arc = typename FST::Arc;
82  using StateId = typename Arc::StateId;
83 
84  DfsState(const FST &fst, StateId s) : state_id(s), arc_iter(fst, s) {}
85 
86  void *operator new(size_t size, MemoryPool<DfsState<FST>> *pool) {
87  return pool->Allocate();
88  }
89 
90  static void Destroy(DfsState<FST> *dfs_state,
91  MemoryPool<DfsState<FST>> *pool) {
92  if (dfs_state) {
93  dfs_state->~DfsState<FST>();
94  pool->Free(dfs_state);
95  }
96  }
97 
98  StateId state_id; // FST state.
99  ArcIterator<FST> arc_iter; // The corresponding arcs.
100 };
101 
102 } // namespace internal
103 
104 // Performs depth-first visitation. Visitor class argument determines actions
105 // and contains any return data. ArcFilter determines arcs that are considered.
106 // If 'access_only' is true, performs visitation only to states accessible from
107 // the initial state.
108 //
109 // Note this is similar to Visit() in visit.h called with a LIFO queue, except
110 // this version has a Visitor class specialized and augmented for a DFS.
111 template <class FST, class Visitor, class ArcFilter>
112 void DfsVisit(const FST &fst, Visitor *visitor, ArcFilter filter,
113  bool access_only = false) {
114  using Arc = typename FST::Arc;
115  using StateId = typename Arc::StateId;
116  visitor->InitVisit(fst);
117  const auto start = fst.Start();
118  if (start == kNoStateId) {
119  visitor->FinishVisit();
120  return;
121  }
122  // An FST state's DFS status
123  enum class StateColor : uint8_t {
124  kWhite = 0, // Undiscovered.
125  kGrey = 1, // Discovered but unfinished.
126  kBlack = 2, // Finished.
127  };
128  std::vector<StateColor> state_color;
129  std::stack<internal::DfsState<FST> *> state_stack; // DFS execution stack.
130  MemoryPool<internal::DfsState<FST>> state_pool; // Pool for DFSStates.
131  // Exact number of states if known, otherwise lower bound.
132  StateId nstates = fst.NumStatesIfKnown().value_or(start + 1);
133  const bool expanded = fst.Properties(kExpanded, false);
134  state_color.resize(nstates, StateColor::kWhite);
135  StateIterator<FST> siter(fst);
136  // Continue DFS while true.
137  bool dfs = true;
138  // Iterate over trees in DFS forest.
139  for (auto root = start; dfs && root < nstates;) {
140  state_color[root] = StateColor::kGrey;
141  state_stack.push(new (&state_pool) internal::DfsState<FST>(fst, root));
142  dfs = visitor->InitState(root, root);
143  while (!state_stack.empty()) {
144  auto *dfs_state = state_stack.top();
145  const auto s = dfs_state->state_id;
146  if (s >= static_cast<decltype(s)>(state_color.size())) {
147  nstates = s + 1;
148  state_color.resize(nstates, StateColor::kWhite);
149  }
150  ArcIterator<FST> &aiter = dfs_state->arc_iter;
151  if (!dfs || aiter.Done()) {
152  state_color[s] = StateColor::kBlack;
153  internal::DfsState<FST>::Destroy(dfs_state, &state_pool);
154  state_stack.pop();
155  if (!state_stack.empty()) {
156  auto *parent_state = state_stack.top();
157  auto &piter = parent_state->arc_iter;
158  visitor->FinishState(s, parent_state->state_id, &piter.Value());
159  piter.Next();
160  } else {
161  visitor->FinishState(s, kNoStateId, nullptr);
162  }
163  continue;
164  }
165  const auto &arc = aiter.Value();
166  if (arc.nextstate >=
167  static_cast<decltype(arc.nextstate)>(state_color.size())) {
168  nstates = arc.nextstate + 1;
169  state_color.resize(nstates, StateColor::kWhite);
170  }
171  if (!filter(arc)) {
172  aiter.Next();
173  continue;
174  }
175  const auto next_color = state_color[arc.nextstate];
176  switch (next_color) {
177  case StateColor::kWhite:
178  dfs = visitor->TreeArc(s, arc);
179  if (!dfs) break;
180  state_color[arc.nextstate] = StateColor::kGrey;
181  state_stack.push(new (&state_pool)
182  internal::DfsState<FST>(fst, arc.nextstate));
183  dfs = visitor->InitState(arc.nextstate, root);
184  break;
185  case StateColor::kGrey:
186  dfs = visitor->BackArc(s, arc);
187  aiter.Next();
188  break;
189  case StateColor::kBlack:
190  dfs = visitor->ForwardOrCrossArc(s, arc);
191  aiter.Next();
192  break;
193  }
194  }
195  if (access_only) break;
196  // Finds next tree root.
197  for (root = root == start ? 0 : root + 1;
198  root < nstates && state_color[root] != StateColor::kWhite; ++root) {
199  }
200  // Checks for a state beyond the largest known state.
201  if (!expanded && root == nstates) {
202  for (; !siter.Done(); siter.Next()) {
203  if (siter.Value() == nstates) {
204  ++nstates;
205  state_color.push_back(StateColor::kWhite);
206  break;
207  }
208  }
209  }
210  }
211  visitor->FinishVisit();
212 }
213 
214 template <class Arc, class Visitor>
215 void DfsVisit(const Fst<Arc> &fst, Visitor *visitor) {
216  DfsVisit(fst, visitor, AnyArcFilter<Arc>());
217 }
218 
219 } // namespace fst
220 
221 #endif // FST_DFS_VISIT_H_
static void Destroy(DfsState< FST > *dfs_state, MemoryPool< DfsState< FST >> *pool)
Definition: dfs-visit.h:90
void DfsVisit(const FST &fst, Visitor *visitor, ArcFilter filter, bool access_only=false)
Definition: dfs-visit.h:112
constexpr int kNoStateId
Definition: fst.h:196
const Arc & Value() const
Definition: fst.h:536
DfsState(const FST &fst, StateId s)
Definition: dfs-visit.h:84
typename Arc::StateId StateId
Definition: dfs-visit.h:82
StateId Value() const
Definition: fst.h:419
bool Done() const
Definition: fst.h:532
ArcIterator< FST > arc_iter
Definition: dfs-visit.h:99
void Next()
Definition: fst.h:421
bool Done() const
Definition: fst.h:415
typename FST::Arc Arc
Definition: dfs-visit.h:81
constexpr uint64_t kExpanded
Definition: properties.h:46
void Next()
Definition: fst.h:540