// topsort.h // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Copyright 2005-2010 Google, Inc. // Author: riley@google.com (Michael Riley) // // \file // Topological sort of FSTs #ifndef FST_LIB_TOPSORT_H__ #define FST_LIB_TOPSORT_H__ #include #include using std::vector; #include #include #include namespace fst { // DFS visitor class to return topological ordering. template class TopOrderVisitor { public: typedef A Arc; typedef typename A::StateId StateId; // If acyclic, ORDER[i] gives the topological position of state Id i; // otherwise unchanged. ACYCLIC will be true iff the FST has // no cycles. TopOrderVisitor(vector *order, bool *acyclic) : order_(order), acyclic_(acyclic) {} void InitVisit(const Fst &fst) { finish_ = new vector; *acyclic_ = true; } bool InitState(StateId s, StateId r) { return true; } bool TreeArc(StateId s, const A &arc) { return true; } bool BackArc(StateId s, const A &arc) { return (*acyclic_ = false); } bool ForwardOrCrossArc(StateId s, const A &arc) { return true; } void FinishState(StateId s, StateId p, const A *) { finish_->push_back(s); } void FinishVisit() { if (*acyclic_) { order_->clear(); for (StateId s = 0; s < finish_->size(); ++s) order_->push_back(kNoStateId); for (StateId s = 0; s < finish_->size(); ++s) (*order_)[(*finish_)[finish_->size() - s - 1]] = s; } delete finish_; } private: vector *order_; bool *acyclic_; vector *finish_; // states in finishing-time order }; // Topologically sorts its input if acyclic, modifying it. Otherwise, // the input is unchanged. When sorted, all transitions are from // lower to higher state IDs. // // Complexity: // - Time: O(V + E) // - Space: O(V + E) // where V = # of states and E = # of arcs. template bool TopSort(MutableFst *fst) { typedef typename Arc::StateId StateId; vector order; bool acyclic; TopOrderVisitor top_order_visitor(&order, &acyclic); DfsVisit(*fst, &top_order_visitor); if (acyclic) { StateSort(fst, order); fst->SetProperties(kAcyclic | kInitialAcyclic | kTopSorted, kAcyclic | kInitialAcyclic | kTopSorted); } else { fst->SetProperties(kCyclic | kNotTopSorted, kCyclic | kNotTopSorted); } return acyclic; } } // namespace fst #endif // FST_LIB_TOPSORT_H__