determinize-lattice-test.cc
Go to the documentation of this file.
1 // fstext/determinize-lattice-test.cc
2 
3 // Copyright 2009-2011 Microsoft Corporation
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/lattice-utils.h"
22 #include "fstext/fst-test-utils.h"
23 #include "base/kaldi-math.h"
24 
25 namespace fst {
26 using std::vector;
27 using std::cout;
28 
30  typedef int32 IntType;
31 
34 
35  for(int i = 0; i < 100; i++) {
36  int len = kaldi::Rand() % 5;
37  vector<IntType> str(len), str2(kaldi::Rand() % 4);
38  const Entry *e = NULL;
39  for(int i = 0; i < len; i++) {
40  str[i] = kaldi::Rand() % 5;
41  e = sr.Successor(e, str[i]);
42  }
43  sr.ConvertToVector(e, &str2);
44  assert(str == str2);
45 
46  int len2 = kaldi::Rand() % 5;
47  str2.resize(len2);
48  const Entry *f = sr.EmptyString(); // NULL
49  for(int i = 0; i < len2; i++) {
50  str2[i] = kaldi::Rand() % 5;
51  f = sr.Successor(f, str2[i]);
52  }
53  vector<IntType> prefix, prefix2(kaldi::Rand() % 10),
54  prefix3;
55  for(int i = 0; i < len && i < len2; i++) {
56  if (str[i] == str2[i]) prefix.push_back(str[i]);
57  else break;
58  }
59  const Entry *g = sr.CommonPrefix(e, f);
60  sr.ConvertToVector(g, &prefix2);
61  sr.ConvertToVector(e, &prefix3);
62  sr.ReduceToCommonPrefix(f, &prefix3);
63  assert(prefix == prefix2);
64  assert(prefix == prefix3);
65  assert(sr.IsPrefixOf(g, e));
66  assert(sr.IsPrefixOf(g, f));
67  if (str.size() > prefix.size())
68  assert(!sr.IsPrefixOf(e, g));
69  }
70 }
71 
72 
73 // test that determinization proceeds correctly on general
74 // FSTs (not guaranteed determinzable, but we use the
75 // max-states option to stop it getting out of control).
76 template<class Arc> void TestDeterminizeLattice() {
77  typedef typename Arc::Weight Weight;
78  typedef int32 Int;
79  typedef ArcTpl<CompactLatticeWeightTpl<Weight, Int> > CompactArc;
80 
81  for(int i = 0; i < 100; i++) {
82  RandFstOptions opts;
83  opts.n_states = 4;
84  opts.n_arcs = 10;
85  opts.n_final = 2;
86  opts.allow_empty = false;
87  opts.weight_multiplier = 0.5; // impt for the randomly generated weights
88  // to be exactly representable in float,
89  // or this test fails because numerical differences can cause symmetry in
90  // weights to be broken, which causes the wrong path to be chosen as far
91  // as the string part is concerned.
92 
93  VectorFst<Arc> *fst = RandFst<Arc>();
94  std::cout << "FST before lattice-determinizing is:\n";
95  {
96  FstPrinter<Arc> fstprinter(*fst, NULL, NULL, NULL, false, true, "\t");
97  fstprinter.Print(&std::cout, "standard output");
98  }
99  VectorFst<Arc> det_fst;
100  try {
101  DeterminizeLatticeOptions lat_opts;
102  lat_opts.max_mem = 100;
103 
104  if (!DeterminizeLattice<TropicalWeight, int32>(*fst, &det_fst, lat_opts, NULL))
105  throw std::runtime_error("could not determinize");
106  std::cout << "FST after lattice-determinizing is:\n";
107  {
108  FstPrinter<Arc> fstprinter(det_fst, NULL, NULL, NULL, false, true, "\t");
109  fstprinter.Print(&std::cout, "standard output");
110  }
111  assert(det_fst.Properties(kIDeterministic, true) & kIDeterministic);
112  // OK, now determinize it a different way and check equivalence.
113  // [note: it's not normal determinization, it's taking the best path
114  // for any input-symbol sequence....
115  VectorFst<CompactArc> compact_fst, compact_det_fst;
116  ConvertLattice<Weight, Int>(*fst, &compact_fst, false);
117  std::cout << "Compact FST is:\n";
118  {
119  FstPrinter<CompactArc> fstprinter(compact_fst, NULL, NULL, NULL, false, true, "\t");
120  fstprinter.Print(&std::cout, "standard output");
121  }
122  if (kaldi::Rand() % 2 == 1)
123  ConvertLattice<Weight, Int>(det_fst, &compact_det_fst, false);
124  else
125  if (!DeterminizeLattice<TropicalWeight, int32>(*fst, &compact_det_fst, lat_opts, NULL))
126  throw std::runtime_error("could not determinize");
127 
128  std::cout << "Compact version of determinized FST is:\n";
129  {
130  FstPrinter<CompactArc> fstprinter(compact_det_fst, NULL, NULL, NULL, false, true, "\t");
131  fstprinter.Print(&std::cout, "standard output");
132  }
133 
134  assert(RandEquivalent(compact_det_fst, compact_fst, 5/*paths*/, 0.01/*delta*/, kaldi::Rand()/*seed*/, 100/*path length, max*/));
135  } catch (...) {
136  std::cout << "Failed to lattice-determinize this FST (probably not determinizable)\n";
137  }
138  delete fst;
139  }
140 }
141 
142 // test that determinization proceeds correctly on acyclic FSTs
143 // (guaranteed determinizable in this sense).
144 template<class Arc> void TestDeterminizeLattice2() {
145  RandFstOptions opts;
146  opts.acyclic = true;
147  for(int i = 0; i < 100; i++) {
148  VectorFst<Arc> *fst = RandFst<Arc>(opts);
149  std::cout << "FST before lattice-determinizing is:\n";
150  {
151  FstPrinter<Arc> fstprinter(*fst, NULL, NULL, NULL, false, true, "\t");
152  fstprinter.Print(&std::cout, "standard output");
153  }
154  VectorFst<Arc> ofst;
155  DeterminizeLattice<TropicalWeight, int32>(*fst, &ofst);
156  std::cout << "FST after lattice-determinizing is:\n";
157  {
158  FstPrinter<Arc> fstprinter(ofst, NULL, NULL, NULL, false, true, "\t");
159  fstprinter.Print(&std::cout, "standard output");
160  }
161  delete fst;
162  }
163 }
164 
165 
166 } // end namespace fst
167 
168 int main() {
169  using namespace fst;
171  TestDeterminizeLattice<StdArc>();
172  TestDeterminizeLattice2<StdArc>();
173  std::cout << "Tests succeeded\n";
174 }
const Entry * CommonPrefix(const Entry *a, const Entry *b)
For an extended explanation of the framework of which grammar-fsts are a part, please see Support for...
Definition: graph.dox:21
void ConvertToVector(const Entry *entry, std::vector< IntType > *out) const
kaldi::int32 int32
const Entry * Successor(const Entry *parent, IntType i)
float weight_multiplier
Definition: rand-fst.h:41
void TestDeterminizeLattice2()
int Rand(struct RandomState *state)
Definition: kaldi-math.cc:45
fst::StdArc::Weight Weight
bool IsPrefixOf(const Entry *a, const Entry *b) const
void TestDeterminizeLattice()
void ReduceToCommonPrefix(const Entry *a, std::vector< IntType > *b)
void TestLatticeStringRepository()