1f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// dfs-visit.h
2f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
3f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Licensed under the Apache License, Version 2.0 (the "License");
4f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// you may not use this file except in compliance with the License.
5f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// You may obtain a copy of the License at
6f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
7f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//     http://www.apache.org/licenses/LICENSE-2.0
8f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
9f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Unless required by applicable law or agreed to in writing, software
10f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// distributed under the License is distributed on an "AS IS" BASIS,
11f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// See the License for the specific language governing permissions and
13f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// limitations under the License.
14f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
15f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Copyright 2005-2010 Google, Inc.
16f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Author: riley@google.com (Michael Riley)
17f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
18f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// \file
19f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Depth-first search visitation. See visit.h for more general
20f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// search queue disciplines.
21f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
22f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#ifndef FST_LIB_DFS_VISIT_H__
23f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#define FST_LIB_DFS_VISIT_H__
24f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
25f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <stack>
26f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <vector>
27f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonusing std::vector;
28f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
29f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <fst/arcfilter.h>
30f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#include <fst/fst.h>
31f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
32f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
33f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonnamespace fst {
34f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
35f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Visitor Interface - class determines actions taken during a Dfs.
36f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// If any of the boolean member functions return false, the DFS is
37f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// aborted by first calling FinishState() on all currently grey states
38f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// and then calling FinishVisit().
39f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
40f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Note this is similar to the more general visitor interface in visit.h
41f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// except that FinishState returns additional information appropriate only for
42f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// a DFS and some methods names here are better suited to a DFS.
43f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
44f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// template <class Arc>
45f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// class Visitor {
46f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//  public:
47f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   typedef typename Arc::StateId StateId;
48f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
49f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   Visitor(T *return_data);
50f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // Invoked before DFS visit
51f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   void InitVisit(const Fst<Arc> &fst);
52f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // Invoked when state discovered (2nd arg is DFS tree root)
53f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   bool InitState(StateId s, StateId root);
54f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // Invoked when tree arc examined (to white/undiscovered state)
55f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   bool TreeArc(StateId s, const Arc &a);
56f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // Invoked when back arc examined (to grey/unfinished state)
57f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   bool BackArc(StateId s, const Arc &a);
58f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // Invoked when forward or cross arc examined (to black/finished state)
59f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   bool ForwardOrCrossArc(StateId s, const Arc &a);
60f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // Invoked when state finished (PARENT is kNoStateID and ARC == NULL
61f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // when S is tree root)
62f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   void FinishState(StateId s, StateId parent, const Arc *parent_arc);
63f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   // Invoked after DFS visit
64f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//   void FinishVisit();
65f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// };
66f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
67f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// An Fst state's DFS status
68f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonconst int kDfsWhite = 0;   // Undiscovered
69f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonconst int kDfsGrey =  1;   // Discovered & unfinished
70f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonconst int kDfsBlack = 2;   // Finished
71f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
72f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// An Fst state's DFS stack state
73f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class Arc>
74f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonstruct DfsState {
75f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename Arc::StateId StateId;
76f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
77f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  DfsState(const Fst<Arc> &fst, StateId s): state_id(s), arc_iter(fst, s) {}
78f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
79f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  StateId state_id;       // Fst state ...
80f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  ArcIterator< Fst<Arc> > arc_iter;  // and its corresponding arcs
81f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson};
82f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
83f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
84f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Performs depth-first visitation. Visitor class argument determines
85f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// actions and contains any return data. ArcFilter determines arcs
86f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// that are considered.
87f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson//
88f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// Note this is similar to Visit() in visit.h called with a LIFO
89f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// queue except this version has a Visitor class specialized and
90f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson// augmented for a DFS.
91f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class Arc, class V, class ArcFilter>
92f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonvoid DfsVisit(const Fst<Arc> &fst, V *visitor, ArcFilter filter) {
93f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  typedef typename Arc::StateId StateId;
94f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
95f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  visitor->InitVisit(fst);
96f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
97f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  StateId start = fst.Start();
98f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (start == kNoStateId) {
99f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    visitor->FinishVisit();
100f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    return;
101f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
102f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
103f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  vector<char> state_color;                // Fst state DFS status
104f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  stack<DfsState<Arc> *> state_stack;      // DFS execution stack
105f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
106f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  StateId nstates = start + 1;             // # of known states in general case
107f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool expanded = false;
108f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  if (fst.Properties(kExpanded, false)) {  // tests if expanded case, then
109f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    nstates = CountStates(fst);            // uses ExpandedFst::NumStates().
110f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    expanded = true;
111f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
112f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
113f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  state_color.resize(nstates, kDfsWhite);
114f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  StateIterator< Fst<Arc> > siter(fst);
115f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
116f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // Continue DFS while true
117f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  bool dfs = true;
118f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
119f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  // Iterate over trees in DFS forest.
120f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  for (StateId root = start; dfs && root < nstates;) {
121f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    state_color[root] = kDfsGrey;
122f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    state_stack.push(new DfsState<Arc>(fst, root));
123f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    dfs = visitor->InitState(root, root);
124f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    while (!state_stack.empty()) {
125f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      DfsState<Arc> *dfs_state = state_stack.top();
126f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      StateId s = dfs_state->state_id;
127f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      if (s >= state_color.size()) {
128f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        nstates = s + 1;
129f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        state_color.resize(nstates, kDfsWhite);
130f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      }
131f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      ArcIterator< Fst<Arc> > &aiter = dfs_state->arc_iter;
132f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      if (!dfs || aiter.Done()) {
133f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        state_color[s] = kDfsBlack;
134f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        delete dfs_state;
135f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        state_stack.pop();
136f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        if (!state_stack.empty()) {
137f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          DfsState<Arc> *parent_state = state_stack.top();
138f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          StateId p = parent_state->state_id;
139f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          ArcIterator< Fst<Arc> > &piter = parent_state->arc_iter;
140f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          visitor->FinishState(s, p, &piter.Value());
141f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          piter.Next();
142f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        } else {
143f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          visitor->FinishState(s, kNoStateId, 0);
144f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        }
145f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        continue;
146f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      }
147f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      const Arc &arc = aiter.Value();
148f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      if (arc.nextstate >= state_color.size()) {
149f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        nstates = arc.nextstate + 1;
150f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        state_color.resize(nstates, kDfsWhite);
151f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      }
152f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      if (!filter(arc)) {
153f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        aiter.Next();
154f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        continue;
155f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      }
156f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      int next_color = state_color[arc.nextstate];
157f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      switch (next_color) {
158f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        default:
159f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        case kDfsWhite:
160f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          dfs = visitor->TreeArc(s, arc);
161f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          if (!dfs) break;
162f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          state_color[arc.nextstate] = kDfsGrey;
163f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          state_stack.push(new DfsState<Arc>(fst, arc.nextstate));
164f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          dfs = visitor->InitState(arc.nextstate, root);
165f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          break;
166f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        case kDfsGrey:
167f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          dfs = visitor->BackArc(s, arc);
168f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          aiter.Next();
169f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          break;
170f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        case kDfsBlack:
171f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          dfs = visitor->ForwardOrCrossArc(s, arc);
172f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          aiter.Next();
173f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          break;
174f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      }
175f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
176f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
177f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    // Find next tree root
178f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    for (root = root == start ? 0 : root + 1;
179f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson         root < nstates && state_color[root] != kDfsWhite;
180dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin         ++root) {
181dfd8b8327b93660601d016cdc6f29f433b45a8d8Alexander Gutkin    }
182f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
183f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    // Check for a state beyond the largest known state
184f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    if (!expanded && root == nstates) {
185f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      for (; !siter.Done(); siter.Next()) {
186f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        if (siter.Value() == nstates) {
187f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          ++nstates;
188f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          state_color.push_back(kDfsWhite);
189f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson          break;
190f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson        }
191f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson      }
192f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson    }
193f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  }
194f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  visitor->FinishVisit();
195f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
196f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
197f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
198f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsontemplate <class Arc, class V>
199f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodsonvoid DfsVisit(const Fst<Arc> &fst, V *visitor) {
200f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson  DfsVisit(fst, visitor, AnyArcFilter<Arc>());
201f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}
202f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
203f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson}  // namespace fst
204f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson
205f4c12fce1ee58e670f9c3fce46c40296ba9ee8a2Ian Hodson#endif  // FST_LIB_DFS_VISIT_H__
206