deterministic-fst-test.cc
Go to the documentation of this file.
1 // fstext/deterministic-fst-test.cc
2 
3 // Copyright 2009-2011 Gilles Boulianne
4 
5 // See ../../COPYING for clarification regarding multiple authors
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 // http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
15 // WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
16 // MERCHANTABLITY OR NON-INFRINGEMENT.
17 // See the Apache 2 License for the specific language governing permissions and
18 // limitations under the License.
19 
21 #include "fstext/fst-test-utils.h"
22 #include "util/kaldi-io.h"
23 
24 #include <sys/stat.h>
25 
26 namespace fst {
27 using std::cout;
28 using std::cerr;
29 using std::endl;
30 
31 bool FileExists(std::string strFilename) {
32  struct stat stFileInfo;
33  bool blnReturn;
34  int intStat;
35 
36  // Attempt to get the file attributes
37  intStat = stat(strFilename.c_str(), &stFileInfo);
38  if (intStat == 0) {
39  // We were able to get the file attributes
40  // so the file obviously exists.
41  blnReturn = true;
42  } else {
43  // We were not able to get the file attributes.
44  // This may mean that we don't have permission to
45  // access the folder which contains this file. If you
46  // need to do that level of checking, lookup the
47  // return values of stat which will give you
48  // more details on why stat failed.
49  blnReturn = false;
50  }
51 
52  return blnReturn;
53 }
54 
55 // Simplify writing
61 
62 
63 // something that looks like a language model FST with epsilon backoffs
64 StdVectorFst* CreateBackoffFst() {
65  StdVectorFst *fst = new StdVectorFst();
66  fst->AddState(); // state 0
67  fst->SetStart(0);
68  fst->AddArc(0, StdArc(10, 10, 0.0, 1));
69 
70  fst->AddState(); // state 1
71  fst->AddArc(1, StdArc(12, 12, 0.0, 4));
72  fst->AddArc(1, StdArc(0,0, 0.1,2)); // backoff from 1 to 2
73 
74  fst->AddState(); // state 2
75  fst->AddArc(2, StdArc(13, 13, 0.2, 4));
76  fst->AddArc(2, StdArc(0,0, 0.3,3)); // backoff from 2 to 3
77 
78  fst->AddState(); // state 3
79  fst->AddArc(3, StdArc(14, 14, 0.4, 4));
80 
81  fst->AddState(); // state 4
82  fst->AddArc(4, StdArc(15, 15, 0.5, 5));
83 
84  fst->AddState(); // state 5
85  fst->SetFinal(5, 0.6);
86 
87  return fst;
88 }
89 
90 // what the resulting DeterministicOnDemand FST should be like
91 StdVectorFst* CreateResultFst() {
92  StdVectorFst *fst = new StdVectorFst();
93  fst->AddState(); // state 0
94  fst->SetStart(0);
95  fst->AddArc(0, StdArc(10, 10, 0.0, 1));
96 
97  fst->AddState(); // state 1
98  fst->AddArc(1, StdArc(12, 12, 0.0, 4));
99  fst->AddArc(1, StdArc(13,13,0.3,4)); // went through 1 backoff
100  fst->AddArc(1, StdArc(14,14,0.8,4)); // went through 2 backoffs
101 
102  fst->AddState(); // state 2
103  fst->AddState(); // state 3
104 
105  fst->AddState(); // state 4
106  fst->AddArc(4, StdArc(15, 15, 0.5, 5));
107 
108  fst->AddState(); // state 5
109  fst->SetFinal(5, 0.6);
110 
111  return fst;
112 }
113 
114 void DeleteTestFst(StdVectorFst *fst) {
115  delete fst;
116 }
117 
118 // Follow paths from an input fst representing a string
119 // (poor man's composition)
120 Weight WalkSinglePath(StdVectorFst *ifst, DeterministicOnDemandFst<StdArc> *dfst) {
121  StdArc oarc; // = new StdArc();
122  StateId isrc=ifst->Start();
123  StateId dsrc=dfst->Start();
124  Weight totalCost = Weight::One();
125 
126  while (ifst->Final(isrc) == Weight::Zero()) { // while not final
127  fst::ArcIterator<StdVectorFst> aiter(*ifst, isrc);
128  const StdArc &iarc = aiter.Value();
129  if (dfst->GetArc(dsrc, iarc.olabel, &oarc)) {
130  Weight cost = Times(iarc.weight, oarc.weight);
131  // cout << " Matched label "<<iarc.olabel<<" at summed cost "<<cost<<endl;
132  totalCost = Times(totalCost, cost);
133  } else {
134  cout << " Can't match arc ["<<iarc.ilabel<<","<<iarc.olabel<<","<<iarc.weight<<"] from "<<isrc<<endl;
135  exit(1);
136  }
137  isrc = iarc.nextstate;
138  KALDI_LOG << "Setting dsrc = " << oarc.nextstate;
139  dsrc = oarc.nextstate;
140  }
141  totalCost = Times(totalCost, dfst->Final(dsrc));
142 
143  cout << " Total cost: " << totalCost << endl;
144  return totalCost;
145 }
146 
147 
149  // Build from existing fst
150  cout << "Test with single generated backoff FST" << endl;
151  StdVectorFst *nfst = CreateBackoffFst();
152  StdVectorFst *rfst = CreateResultFst();
153 
154  // before using, make sure that it is input sorted
155  ArcSort(nfst, StdILabelCompare());
158 
159  // Compare all arcs in dfst1 with expected result
160  for (StateIterator<StdVectorFst> riter(*rfst); !riter.Done(); riter.Next()) {
161  StateId rsrc = riter.Value();
162  // verify that states have same weight (or final status)
163  assert(ApproxEqual(rfst->Final(rsrc), dfst1.Final(rsrc)));
164  for (ArcIterator<StdVectorFst> aiter(*rfst, rsrc); !aiter.Done(); aiter.Next()) {
165  StdArc rarc = aiter.Value();
166  StdArc darc;
167  if (dfst1.GetArc(rsrc, rarc.ilabel, &darc)) {
168  assert(ApproxEqual(rarc.weight, darc.weight, 0.001));
169  assert(rarc.ilabel==darc.ilabel);
170  assert(rarc.olabel==darc.olabel);
171  assert(rarc.nextstate == darc.nextstate);
172  cerr << " Got same arc at state "<<rsrc<<": "<<rarc.ilabel<<" "<<darc.ilabel<<endl;
173  } else {
174  cerr << "Couldn't find arc "<<rarc.ilabel<<" for state "<<rsrc<<endl;
175  exit(1);
176  }
177  }
178  }
179  delete nfst;
180  delete rfst;
181 }
182 
183 void TestCompose() {
184  cout << "Test with single generated backoff FST" << endl;
185  StdVectorFst *nfst = CreateBackoffFst();
186  StdVectorFst *rfst = CreateResultFst();
187 
188  StdVectorFst composed_fst;
189  Compose(*rfst, *rfst, &composed_fst);
190 
191  // before using, make sure that it is input sorted
192  ArcSort(nfst, StdILabelCompare());
194  ComposeDeterministicOnDemandFst<StdArc> dfst1b(&dfst1a, &dfst1a);
196 
197  typedef StdArc::StateId StateId;
198  std::map<StateId, StateId> state_map;
199  state_map[composed_fst.Start()] = dfst1.Start();
200 
201  VectorFst<StdArc> path_fst;
202  ShortestPath(composed_fst, &path_fst);
203 
204  BackoffDeterministicOnDemandFst<StdArc> dfst2(composed_fst);
205 
206  Weight w1 = WalkSinglePath(&path_fst, &dfst1),
207  w2 = WalkSinglePath(&path_fst, &dfst2);
208  KALDI_ASSERT(ApproxEqual(w1, w2));
209 
210  delete rfst;
211  delete nfst;
212 
213  { // Mostly checking for compilation errors here.
215  KALDI_ASSERT(lm_eg.Start() == 0);
216  KALDI_ASSERT(lm_eg.Final(0).Value() == 0.5); // I made it this value.
217  StdArc arc;
218  bool b = lm_eg.GetArc(0, 100, &arc);
219  KALDI_ASSERT(b && arc.nextstate == 1 && arc.ilabel == 100 && arc.olabel == 100
220  && arc.weight.Value() == 0.25);
221  }
222 }
223 
224 }
225 
226 
227 int main() {
228  using namespace fst;
230  TestCompose();
231 }
232 
This class wraps an Fst, representing a language model, using the interface for "BackoffDeterministic...
fst::StdArc::StateId StateId
virtual bool GetArc(StateId s, Label ilabel, Arc *oarc)=0
Note: ilabel must not be epsilon.
virtual Weight Final(StateId s)=0
This class is for didactic purposes, it does not really do anything.
For an extended explanation of the framework of which grammar-fsts are a part, please see Support for...
Definition: graph.dox:21
fst::StdArc StdArc
bool ApproxEqual(const LatticeWeightTpl< FloatType > &w1, const LatticeWeightTpl< FloatType > &w2, float delta=kDelta)
fst::StdVectorFst StdVectorFst
virtual StateId Start()=0
void TestCompose()
int main()
LatticeWeightTpl< FloatType > Times(const LatticeWeightTpl< FloatType > &w1, const LatticeWeightTpl< FloatType > &w2)
Weight WalkSinglePath(StdVectorFst *ifst, DeterministicOnDemandFst< StdArc > *dfst)
virtual bool GetArc(StateId s, Label ilabel, Arc *oarc)
Note: ilabel must not be epsilon.
virtual Weight Final(StateId s)
We don&#39;t bother caching the final-probs, just the arcs.
fst::StdArc::Label Label
void DeleteTestFst(StdVectorFst *fst)
fst::StdArc::Weight Weight
StdVectorFst * CreateBackoffFst()
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
virtual bool GetArc(StateId s, Label ilabel, Arc *oarc)
Note: ilabel must not be epsilon.
bool FileExists(std::string strFilename)
virtual Weight Final(StateId s)
We don&#39;t bother caching the final-probs, just the arcs.
#define KALDI_LOG
Definition: kaldi-error.h:153
StdVectorFst * CreateResultFst()
void TestBackoffAndCache()