// state-reachable.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 // Class to determine whether a given (final) state can be reached from some // other given state. #ifndef FST_LIB_STATE_REACHABLE_H__ #define FST_LIB_STATE_REACHABLE_H__ #include using std::vector; #include #include #include namespace fst { // Computes the (final) states reachable from a given state in an FST. // After this visitor has been called, a final state f can be reached // from a state s iff (*isets)[s].Member(state2index[f]) is true, where // (*isets[s]) is a set of half-open inteval of final state indices // and state2index[f] maps from a final state to its index. // // If state2index is empty, it is filled-in with suitable indices. // If it is non-empty, those indices are used; in this case, the // final states must have out-degree 0. template class IntervalReachVisitor { public: typedef typename A::StateId StateId; typedef typename A::Label Label; typedef typename A::Weight Weight; typedef typename IntervalSet::Interval Interval; IntervalReachVisitor(const Fst &fst, vector< IntervalSet > *isets, vector *state2index) : fst_(fst), isets_(isets), state2index_(state2index), index_(state2index->empty() ? 1 : -1), error_(false) { isets_->clear(); } void InitVisit(const Fst &fst) { error_ = false; } bool InitState(StateId s, StateId r) { while (isets_->size() <= s) isets_->push_back(IntervalSet &fst_; vector< IntervalSet > *isets_; vector *state2index_; I index_; bool error_; }; // Tests reachability of final states from a given state. To test for // reachability from a state s, first do SetState(s). Then a final // state f can be reached from state s of FST iff Reach(f) is true. template class StateReachable { public: typedef A Arc; typedef I Index; typedef typename A::StateId StateId; typedef typename A::Label Label; typedef typename A::Weight Weight; typedef typename IntervalSet::Interval Interval; StateReachable(const Fst &fst) : error_(false) { IntervalReachVisitor reach_visitor(fst, &isets_, &state2index_); DfsVisit(fst, &reach_visitor); if (reach_visitor.Error()) error_ = true; } StateReachable(const StateReachable &reachable) { FSTERROR() << "Copy constructor for state reachable class " << "not yet implemented."; error_ = true; } // Set current state. void SetState(StateId s) { s_ = s; } // Can reach this label from current state? bool Reach(StateId s) { if (s >= state2index_.size()) return false; I i = state2index_[s]; if (i < 0) { FSTERROR() << "StateReachable: state non-final: " << s; error_ = true; return false; } return isets_[s_].Member(i); } // Access to the state-to-index mapping. Unassigned states have index -1. vector &State2Index() { return state2index_; } // Access to the interval sets. These specify the reachability // to the final states as intervals of the final state indices. const vector< IntervalSet > &IntervalSets() { return isets_; } bool Error() const { return error_; } private: StateId s_; // Current state vector< IntervalSet > isets_; // Interval sets per state vector state2index_; // Finds index for a final state bool error_; void operator=(const StateReachable &); // Disallow }; } // namespace fst #endif // FST_LIB_STATE_REACHABLE_H__