20 #ifndef FST_EQUIVALENT_H_ 21 #define FST_EQUIVALENT_H_ 34 #include <unordered_map> 69 : (
static_cast<MappedId>(s) << 1) + which_fst;
74 return static_cast<StateId>((--id) >> 1);
80 return (kDeadState == s) ?
false 86 const auto repr = sets->
FindSet(
id);
87 if (repr != kInvalidId) {
122 float delta =
kDelta,
bool *error =
nullptr) {
123 using Weight =
typename Arc::Weight;
124 if (error) *error =
false;
128 FSTERROR() <<
"Equivalent: Input/output symbol tables of 1st argument " 129 <<
"do not match input/output symbol tables of 2nd argument";
130 if (error) *error =
true;
136 FSTERROR() <<
"Equivalent: 1st argument not an" 137 <<
" epsilon-free deterministic acceptor";
138 if (error) *error =
true;
142 FSTERROR() <<
"Equivalent: 2nd argument not an" 143 <<
" epsilon-free deterministic acceptor";
144 if (error) *error =
true;
161 using MappedId =
typename Util::MappedId;
162 enum { FST1 = 1, FST2 = 2 };
163 auto s1 = Util::MapState(fst1.
Start(), FST1);
164 auto s2 = Util::MapState(fst2.
Start(), FST2);
168 eq_classes.MakeSet(s1);
169 eq_classes.MakeSet(s2);
173 using Label2StatePairMap =
174 std::unordered_map<typename Arc::Label, std::pair<MappedId, MappedId>>;
175 Label2StatePairMap arc_pairs;
177 std::queue<std::pair<MappedId, MappedId>> q;
180 if (Util::IsFinal(fst1, s1) != Util::IsFinal(fst2, s2)) ret =
false;
184 for (q.emplace(s1, s2); ret && !q.empty(); q.pop()) {
185 s1 = q.front().first;
186 s2 = q.front().second;
188 const auto rep1 = Util::FindSet(&eq_classes, s1);
189 const auto rep2 = Util::FindSet(&eq_classes, s2);
191 eq_classes.Union(rep1, rep2);
194 if (Util::kDeadState != s1) {
196 for (; !arc_iter.
Done(); arc_iter.
Next()) {
197 const auto &arc = arc_iter.
Value();
199 if (arc.weight != Weight::Zero()) {
200 arc_pairs[arc.ilabel].first = Util::MapState(arc.nextstate, FST1);
205 if (Util::kDeadState != s2) {
207 for (; !arc_iter.
Done(); arc_iter.
Next()) {
208 const auto &arc = arc_iter.
Value();
210 if (arc.weight != Weight::Zero()) {
211 arc_pairs[arc.ilabel].second = Util::MapState(arc.nextstate, FST2);
216 for (
const auto &arc_iter : arc_pairs) {
217 const auto &pair = arc_iter.second;
218 if (Util::IsFinal(fst1, pair.first) !=
219 Util::IsFinal(fst2, pair.second)) {
229 if (error) *error =
true;
237 #endif // FST_EQUIVALENT_H_
void ArcMap(MutableFst< A > *fst, C *mapper)
static constexpr MappedId kDeadState
virtual uint64_t Properties(uint64_t mask, bool test) const =0
static MappedId MapState(StateId s, int32_t which_fst)
constexpr uint64_t kError
virtual Weight Final(StateId) const =0
const Arc & Value() const
constexpr uint8_t kEncodeLabels
constexpr uint64_t kNoEpsilons
static MappedId FindSet(UnionFind< MappedId > *sets, MappedId id)
static StateId UnMapState(MappedId id)
virtual StateId Start() const =0
typename Arc::Weight Weight
constexpr uint64_t kIDeterministic
void Push(MutableFst< Arc > *fst, ReweightType type=REWEIGHT_TO_INITIAL, float delta=kShortestDelta, bool remove_total_weight=false)
constexpr uint8_t kEncodeWeights
constexpr uint64_t kUnweighted
virtual const SymbolTable * InputSymbols() const =0
bool Equivalent(const Fst< Arc > &fst1, const Fst< Arc > &fst2, float delta=kDelta, bool *error=nullptr)
typename Arc::StateId StateId
bool CompatSymbols(const SymbolTable *syms1, const SymbolTable *syms2, bool warning=true)
static bool IsFinal(const Fst< Arc > &fa, MappedId s)
constexpr uint64_t kAcceptor
virtual const SymbolTable * OutputSymbols() const =0
static constexpr MappedId kInvalidId