1 // verify.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 // Function to verify an Fst's contents
20 
21 #ifndef FST_LIB_VERIFY_H__
22 #define FST_LIB_VERIFY_H__
23 
24 #include <fst/fst.h>
25 #include <fst/test-properties.h>
26 
27 
28 namespace fst {
29 
30 // Verifies that an Fst's contents are sane.
31 template<class Arc>
32 bool Verify(const Fst<Arc> &fst, bool allow_negative_labels = false) {
33   typedef typename Arc::Label Label;
34   typedef typename Arc::Weight Weight;
35   typedef typename Arc::StateId StateId;
36 
37   StateId start = fst.Start();
38   const SymbolTable *isyms = fst.InputSymbols();
39   const SymbolTable *osyms = fst.OutputSymbols();
40 
41   // Count states
42   StateId ns = 0;
43   for (StateIterator< Fst<Arc> > siter(fst);
44        !siter.Done();
45        siter.Next())
46     ++ns;
47 
48   if (start == kNoStateId && ns > 0) {
49     LOG(ERROR) << "Verify: Fst start state ID unset";
50     return false;
51   } else if (start >= ns) {
52     LOG(ERROR) << "Verify: Fst start state ID exceeds number of states";
53     return false;
54   }
55 
56   for (StateIterator< Fst<Arc> > siter(fst);
57        !siter.Done();
58        siter.Next()) {
59     StateId s = siter.Value();
60     size_t na = 0;
61     for (ArcIterator< Fst<Arc> > aiter(fst, s);
62          !aiter.Done();
63          aiter.Next()) {
64       const Arc &arc =aiter.Value();
65       if (!allow_negative_labels && arc.ilabel < 0) {
66         LOG(ERROR) << "Verify: Fst input label ID of arc at position "
67                    << na << " of state " << s << " is negative";
68         return false;
69       } else if (isyms && isyms->Find(arc.ilabel) == "") {
70         LOG(ERROR) << "Verify: Fst input label ID " << arc.ilabel
71                    << " of arc at position " << na << " of state " <<  s
72                    << " is missing from input symbol table \""
73                    << isyms->Name() << "\"";
74         return false;
75       } else if (!allow_negative_labels && arc.olabel < 0) {
76         LOG(ERROR) << "Verify: Fst output label ID of arc at position "
77                    << na << " of state " << s << " is negative";
78         return false;
79       } else if (osyms && osyms->Find(arc.olabel) == "") {
80         LOG(ERROR) << "Verify: Fst output label ID " << arc.olabel
81                    << " of arc at position " << na << " of state " <<  s
82                    << " is missing from output symbol table \""
83                    << osyms->Name() << "\"";
84         return false;
85       } else if (!arc.weight.Member() || arc.weight == Weight::Zero()) {
86         LOG(ERROR) << "Verify: Fst weight of arc at position "
87                    << na << " of state " << s << " is invalid";
88         return false;
89       } else if (arc.nextstate < 0) {
90         LOG(ERROR) << "Verify: Fst destination state ID of arc at position "
91                    << na << " of state " << s << " is negative";
92         return false;
93       } else if (arc.nextstate >= ns) {
94         LOG(ERROR) << "Verify: Fst destination state ID of arc at position "
95                    << na << " of state " << s
96                    << " exceeds number of states";
97         return false;
98       }
99       ++na;
100     }
101     if (!fst.Final(s).Member()) {
102       LOG(ERROR) << "Verify: Fst final weight of state " << s << " is invalid";
103       return false;
104     }
105   }
106   uint64 fst_props = fst.Properties(kFstProperties, false);
107   if (fst_props & kError) {
108     LOG(ERROR) << "Verify: Fst error property is set";
109     return false;
110   }
111 
112   uint64 known_props;
113   uint64 test_props = ComputeProperties(fst, kFstProperties, &known_props,
114                                         false);
115   if (!CompatProperties(fst_props, test_props)) {
116     LOG(ERROR) << "Verify: stored Fst properties incorrect "
117                << "(props1 = stored props, props2 = tested)";
118     return false;
119   } else {
120     return true;
121   }
122 }
123 
124 }  // namespace fst
125 
126 #endif  // FST_LIB_VERIFY_H__
127