1 // topsort.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 // Topological sort of FSTs
20 
21 #ifndef FST_LIB_TOPSORT_H__
22 #define FST_LIB_TOPSORT_H__
23 
24 #include <algorithm>
25 #include <vector>
26 using std::vector;
27 
28 
29 #include <fst/dfs-visit.h>
30 #include <fst/fst.h>
31 #include <fst/statesort.h>
32 
33 
34 namespace fst {
35 
36 // DFS visitor class to return topological ordering.
37 template <class A>
38 class TopOrderVisitor {
39  public:
40   typedef A Arc;
41   typedef typename A::StateId StateId;
42 
43   // If acyclic, ORDER[i] gives the topological position of state Id i;
44   // otherwise unchanged. ACYCLIC will be true iff the FST has
45   // no cycles.
TopOrderVisitor(vector<StateId> * order,bool * acyclic)46   TopOrderVisitor(vector<StateId> *order, bool *acyclic)
47       : order_(order), acyclic_(acyclic) {}
48 
InitVisit(const Fst<A> & fst)49   void InitVisit(const Fst<A> &fst) {
50     finish_ = new vector<StateId>;
51     *acyclic_ = true;
52   }
53 
InitState(StateId s,StateId r)54   bool InitState(StateId s, StateId r) { return true; }
55 
TreeArc(StateId s,const A & arc)56   bool TreeArc(StateId s, const A &arc) { return true; }
57 
BackArc(StateId s,const A & arc)58   bool BackArc(StateId s, const A &arc) { return (*acyclic_ = false); }
59 
ForwardOrCrossArc(StateId s,const A & arc)60   bool ForwardOrCrossArc(StateId s, const A &arc) { return true; }
61 
FinishState(StateId s,StateId p,const A *)62   void FinishState(StateId s, StateId p, const A *) { finish_->push_back(s); }
63 
FinishVisit()64   void FinishVisit() {
65     if (*acyclic_) {
66       order_->clear();
67       for (StateId s = 0; s < finish_->size(); ++s)
68         order_->push_back(kNoStateId);
69       for (StateId s = 0; s < finish_->size(); ++s)
70         (*order_)[(*finish_)[finish_->size() - s - 1]] = s;
71     }
72     delete finish_;
73   }
74 
75  private:
76   vector<StateId> *order_;
77   bool *acyclic_;
78   vector<StateId> *finish_;  // states in finishing-time order
79 };
80 
81 
82 // Topologically sorts its input if acyclic, modifying it.  Otherwise,
83 // the input is unchanged.  When sorted, all transitions are from
84 // lower to higher state IDs.
85 //
86 // Complexity:
87 // - Time:  O(V + E)
88 // - Space: O(V + E)
89 // where V = # of states and E = # of arcs.
90 template <class Arc>
TopSort(MutableFst<Arc> * fst)91 bool TopSort(MutableFst<Arc> *fst) {
92   typedef typename Arc::StateId StateId;
93 
94   vector<StateId> order;
95   bool acyclic;
96 
97   TopOrderVisitor<Arc> top_order_visitor(&order, &acyclic);
98   DfsVisit(*fst, &top_order_visitor);
99 
100   if (acyclic) {
101     StateSort(fst, order);
102     fst->SetProperties(kAcyclic | kInitialAcyclic | kTopSorted,
103                        kAcyclic | kInitialAcyclic | kTopSorted);
104   } else {
105     fst->SetProperties(kCyclic | kNotTopSorted, kCyclic | kNotTopSorted);
106   }
107   return acyclic;
108 }
109 
110 }  // namespace fst
111 
112 #endif  // FST_LIB_TOPSORT_H__
113