14a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// verify.h
24a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//
34a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Licensed under the Apache License, Version 2.0 (the "License");
44a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// you may not use this file except in compliance with the License.
54a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// You may obtain a copy of the License at
64a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//
74a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//      http://www.apache.org/licenses/LICENSE-2.0
84a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//
94a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Unless required by applicable law or agreed to in writing, software
104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// distributed under the License is distributed on an "AS IS" BASIS,
114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// See the License for the specific language governing permissions and
134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// limitations under the License.
144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//
154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project//
164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// \file
174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Function to test property bits
184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#ifndef FST_LIB_VERIFY_H__
204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define FST_LIB_VERIFY_H__
214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "fst/lib/fst.h"
234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "fst/lib/test-properties.h"
244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectnamespace fst {
264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project// Verifies that an Fst's contents are sane.
284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projecttemplate<class Arc>
294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Projectbool Verify(const Fst<Arc> &fst) {
304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef typename Arc::Label Label;
314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef typename Arc::Weight Weight;
324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  typedef typename Arc::StateId StateId;
334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  StateId start = fst.Start();
354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  const SymbolTable *isyms = fst.InputSymbols();
364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  const SymbolTable *osyms = fst.OutputSymbols();
374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  // Count states
394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  StateId ns = 0;
404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (StateIterator< Fst<Arc> > siter(fst);
414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       !siter.Done();
424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       siter.Next())
434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    ++ns;
444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (start == kNoStateId && ns > 0) {
464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    LOG(ERROR) << "Verify: Fst start state ID unset";
474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return false;
484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  } else if (start >= ns) {
494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    LOG(ERROR) << "Verify: Fst start state ID exceeds number of states";
504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return false;
514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  for (StateIterator< Fst<Arc> > siter(fst);
544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       !siter.Done();
554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project       siter.Next()) {
564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    StateId s = siter.Value();
574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    size_t na = 0;
584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    for (ArcIterator< Fst<Arc> > aiter(fst, s);
594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project         !aiter.Done();
604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project         aiter.Next()) {
614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      const Arc &arc =aiter.Value();
624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      if (arc.ilabel < 0) {
634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        LOG(ERROR) << "Verify: Fst input label ID of arc at position "
644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                   << na << " of state " << s << " is negative";
654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        return false;
664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      } else if (isyms && isyms->Find(arc.ilabel) == "") {
674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        LOG(ERROR) << "Verify: Fst input label ID " << arc.ilabel
684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                   << " of arc at position " << na << " of state " <<  s
694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                   << " is missing from input symbol table \""
704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                   << isyms->Name() << "\"";
714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        return false;
724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      } else if (arc.olabel < 0) {
734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        LOG(ERROR) << "Verify: Fst output label ID of arc at position "
744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                   << na << " of state " << s << " is negative";
754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        return false;
764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      } else if (osyms && osyms->Find(arc.olabel) == "") {
774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        LOG(ERROR) << "Verify: Fst output label ID " << arc.olabel
784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                   << " of arc at position " << na << " of state " <<  s
794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                   << " is missing from output symbol table \""
804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                   << osyms->Name() << "\"";
814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        return false;
824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      } else if (!arc.weight.Member() || arc.weight == Weight::Zero()) {
834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        LOG(ERROR) << "Verify: Fst weight of arc at position "
844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                   << na << " of state " << s << " is invalid";
854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        return false;
864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      } else if (arc.nextstate < 0) {
874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        LOG(ERROR) << "Verify: Fst destination state ID of arc at position "
884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                   << na << " of state " << s << " is negative";
894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        return false;
904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      } else if (arc.nextstate >= ns) {
914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        LOG(ERROR) << "Verify: Fst destination state ID of arc at position "
924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                   << na << " of state " << s
934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                   << " exceeds number of states";
944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project        return false;
954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      }
964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      ++na;
974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    if (!fst.Final(s).Member()) {
994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      LOG(ERROR) << "Verify: Fst final weight of state " << s << " is invalid";
1004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project      return false;
1014a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    }
1024a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
1034a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  uint64 fst_props = fst.Properties(kFstProperties, false);
1044a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  uint64 known_props;
1054a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  uint64 test_props = ComputeProperties(fst, kFstProperties, &known_props,
1064a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project                                        false);
1074a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  if (!CompatProperties(fst_props, test_props)) {
1084a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    LOG(ERROR) << "Verify: stored Fst properties incorrect "
1094a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project               << "(props1 = stored props, props2 = tested)";
1104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return false;
1114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  } else {
1124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project    return true;
1134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project  }
1144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}
1154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project}  // namespace fst
1174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
1184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#endif  // FST_LIB_VERIFY_H__
119