fstext-utils-test.cc
Go to the documentation of this file.
1 // fstext/fstext-utils-test.cc
2 
3 // Copyright 2009-2012 Microsoft Corporation Daniel Povey
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 
20 #include "base/kaldi-common.h" // for exceptions
21 #include "fstext/fstext-utils.h"
22 #include "fstext/fst-test-utils.h"
23 #include "util/stl-utils.h"
24 #include "base/kaldi-math.h"
25 
26 namespace fst
27 {
28 using std::vector;
29 using std::cout;
30 
31 template<class Arc, class I>
33  typedef typename Arc::Label Label;
34  typedef typename Arc::StateId StateId;
35  typedef typename Arc::Weight Weight;
36 
37  int len = kaldi::Rand() % 10;
38  vector<I> vec;
39  vector<I> vec_nozeros;
40  for (int i = 0; i < len; i++) {
41  int j = kaldi::Rand() % len;
42  vec.push_back(j);
43  if (j != 0) vec_nozeros.push_back(j);
44  }
45 
46 
47  VectorFst<Arc> vfst;
48  MakeLinearAcceptor(vec, &vfst);
49  vector<I> vec2;
50  vector<I> vec3;
51  Weight w;
52  GetLinearSymbolSequence(vfst, &vec2, &vec3, &w);
53  assert(w == Weight::One());
54  assert(vec_nozeros == vec2);
55  assert(vec_nozeros == vec3);
56 
57  if (vec2.size() != 0 || vec3.size() != 0) { // This test might not work
58  // for empty sequences...
59  {
60  vector<VectorFst<Arc> > fstvec;
61  NbestAsFsts(vfst, 1, &fstvec);
62  KALDI_ASSERT(fstvec.size() == 1);
63  assert(RandEquivalent(vfst, fstvec[0], 2/*paths*/, 0.01/*delta*/,
64  kaldi::Rand()/*seed*/, 100/*path length-- max?*/));
65  }
66  }
67  bool include_eps = (kaldi::Rand() % 2 == 0);
68  if (!include_eps) vec = vec_nozeros;
69  kaldi::SortAndUniq(&vec);
70 
71  vector<I> vec4;
72  GetInputSymbols(vfst, include_eps, &vec4);
73  assert(vec4 == vec);
74  vector<I> vec5;
75  GetInputSymbols(vfst, include_eps, &vec5);
76 }
77 
78 
79 template<class Arc> void TestDeterminizeStarInLog() {
80  VectorFst<Arc> *fst = RandFst<Arc>();
81  VectorFst<Arc> fst_copy(fst);
82  typename Arc::Label next_sym = 1 + HighestNumberedInputSymbol(*fst);
83  vector<typename Arc::Label> syms;
84  PreDeterminize(fst, NULL, "#", next_sym, &syms);
85 
86 
87 }
88 
89  // Don't instantiate with log semiring, as RandEquivalent may fail.
90 template<class Arc> void TestSafeDeterminizeWrapper() { // also tests SafeDeterminizeMinimizeWrapper().
91  typedef typename Arc::Label Label;
92  typedef typename Arc::StateId StateId;
93  typedef typename Arc::Weight Weight;
94 
95  VectorFst<Arc> *fst = new VectorFst<Arc>();
96  int n_syms = 2 + kaldi::Rand() % 5, n_states = 3 + kaldi::Rand() % 10, n_arcs = 5 + kaldi::Rand() % 30, n_final = 1 + kaldi::Rand()%3; // Up to 2 unique symbols.
97  cout << "Testing pre-determinize with "<<n_syms<<" symbols, "<<n_states<<" states and "<<n_arcs<<" arcs and "<<n_final<<" final states.\n";
98  SymbolTable *sptr = new SymbolTable("my-symbol-table");
99  sptr->AddSymbol("<eps>");
100  delete sptr;
101  sptr = new SymbolTable("my-symbol-table");
102 
103  vector<Label> all_syms; // including epsilon.
104  // Put symbols in the symbol table from 1..n_syms-1.
105  for (size_t i = 0;i < (size_t)n_syms;i++) {
106  std::stringstream ss;
107  if (i == 0) ss << "<eps>";
108  else ss<<i;
109  Label cur_lab = sptr->AddSymbol(ss.str());
110  assert(cur_lab == (Label)i);
111  all_syms.push_back(cur_lab);
112  }
113  assert(all_syms[0] == 0);
114 
115  // Create states.
116  vector<StateId> all_states;
117  for (size_t i = 0;i < (size_t)n_states;i++) {
118  StateId this_state = fst->AddState();
119  if (i == 0) fst->SetStart(i);
120  all_states.push_back(this_state);
121  }
122  // Set final states.
123  for (size_t j = 0;j < (size_t)n_final;j++) {
124  StateId id = all_states[kaldi::Rand() % n_states];
125  Weight weight = (Weight)(0.33*(kaldi::Rand() % 5) );
126  printf("calling SetFinal with %d and %f\n", id, weight.Value());
127  fst->SetFinal(id, weight);
128  }
129  // Create arcs.
130  for (size_t i = 0;i < (size_t)n_arcs;i++) {
131  Arc a;
132  a.nextstate = all_states[kaldi::Rand() % n_states];
133  a.ilabel = all_syms[kaldi::Rand() % n_syms];
134  a.olabel = all_syms[kaldi::Rand() % n_syms]; // same input+output vocab.
135  a.weight = (Weight) (0.33*(kaldi::Rand() % 2));
136  StateId start_state = all_states[kaldi::Rand() % n_states];
137  fst->AddArc(start_state, a);
138  }
139 
140  std::cout <<" printing before trimming\n";
141  {
142  FstPrinter<Arc> fstprinter(*fst, sptr, sptr, NULL, false, true, "\t");
143  fstprinter.Print(&std::cout, "standard output");
144  }
145  // Trim resulting FST.
146  Connect(fst);
147 
148  std::cout <<" printing after trimming\n";
149  {
150  FstPrinter<Arc> fstprinter(*fst, sptr, sptr, NULL, false, true, "\t");
151  fstprinter.Print(&std::cout, "standard output");
152  }
153 
154  VectorFst<Arc> *fst_copy_orig = new VectorFst<Arc>(*fst);
155 
156  VectorFst<Arc> *fst_det = new VectorFst<Arc>;
157 
158  vector<Label> extra_syms;
159  if (fst->Start() != kNoStateId) { // "Connect" did not make it empty....
160  if (kaldi::Rand() % 2 == 0)
161  SafeDeterminizeWrapper(fst_copy_orig, fst_det);
162  else {
163  if (kaldi::Rand() % 2 == 0)
164  SafeDeterminizeMinimizeWrapper(fst_copy_orig, fst_det);
165  else
166  SafeDeterminizeMinimizeWrapperInLog(fst_copy_orig, fst_det);
167  }
168 
169  // no because does shortest-dist on weights even if not pushing on them.
170  // PushInLog<REWEIGHT_TO_INITIAL>(fst_det, kPushLabels); // will always succeed.
171  KALDI_LOG << "Num states [orig]: " << fst->NumStates() << "[det]" << fst_det->NumStates();
172  assert(RandEquivalent(*fst, *fst_det, 5/*paths*/, 0.01/*delta*/, kaldi::Rand()/*seed*/, 100/*path length-- max?*/));
173  }
174  delete fst;
175  delete fst_copy_orig;
176  delete fst_det;
177  delete sptr;
178 }
179 
180 
181  // Don't instantiate with log semiring, as RandEquivalent may fail.
182 void TestPushInLog() { // also tests SafeDeterminizeMinimizeWrapper().
183  typedef StdArc Arc;
184  typedef Arc::Label Label;
185  typedef Arc::StateId StateId;
186  typedef Arc::Weight Weight;
187 
188  VectorFst<Arc> *fst = RandFst<Arc>();
189  VectorFst<Arc> fst2(*fst);
190  PushInLog<REWEIGHT_TO_INITIAL>(&fst2, kPushLabels|kPushWeights, 0.01); // speed it up using large delta.
191  assert(RandEquivalent(*fst, fst2, 5/*paths*/, 0.01/*delta*/, kaldi::Rand()/*seed*/, 100/*path length-- max?*/));
192 
193  delete fst;
194 }
195 
196 
197 
198 template<class Arc> void TestAcceptorMinimize() {
199  typedef typename Arc::Label Label;
200  typedef typename Arc::StateId StateId;
201  typedef typename Arc::Weight Weight;
202 
203  VectorFst<Arc> *fst = RandFst<Arc>();
204 
205  Project(fst, PROJECT_INPUT);
206  RemoveWeights(fst);
207 
208  VectorFst<Arc> fst2(*fst);
209  internal::AcceptorMinimize(&fst2);
210 
211  assert(RandEquivalent(*fst, fst2, 5/*paths*/, 0.01/*delta*/, kaldi::Rand()/*seed*/, 100/*path length-- max?*/));
212 
213  delete fst;
214 }
215 
216 
217 template<class Arc> void TestMakeSymbolsSame() {
218 
219  VectorFst<Arc> *fst = RandFst<Arc>();
220  bool foll = (kaldi::Rand() % 2 == 0);
221  bool is_symbol = (kaldi::Rand() % 2 == 0);
222 
223 
224  VectorFst<Arc> fst2(*fst);
225 
226  if (foll) {
227  MakeFollowingInputSymbolsSame(is_symbol, &fst2);
228  assert(FollowingInputSymbolsAreSame(is_symbol, fst2));
229  } else {
230  MakePrecedingInputSymbolsSame(is_symbol, &fst2);
231  assert(PrecedingInputSymbolsAreSame(is_symbol, fst2));
232  }
233 
234 
235  assert(RandEquivalent(*fst, fst2, 5/*paths*/, 0.01/*delta*/, kaldi::Rand()/*seed*/, 100/*path length-- max?*/));
236 
237  delete fst;
238 }
239 
240 
241 template<class Arc>
242 struct TestFunctor {
243  typedef int32 Result;
244  typedef typename Arc::Label Arg;
245  Result operator () (Arg a) const {
246  if (a == kNoLabel) return -1;
247  else if (a == 0) return 0;
248  else {
249  return 1 + ((a-1) % 10);
250  }
251  }
252 };
253 
254 template<class Arc> void TestMakeSymbolsSameClass() {
255 
256  VectorFst<Arc> *fst = RandFst<Arc>();
257  bool foll = (kaldi::Rand() % 2 == 0);
258  bool is_symbol = (kaldi::Rand() % 2 == 0);
259 
260 
261  VectorFst<Arc> fst2(*fst);
262 
264  if (foll) {
265  MakeFollowingInputSymbolsSameClass(is_symbol, &fst2, f);
266  assert(FollowingInputSymbolsAreSameClass(is_symbol, fst2, f));
267  } else {
268  MakePrecedingInputSymbolsSameClass(is_symbol, &fst2, f);
269  assert(PrecedingInputSymbolsAreSameClass(is_symbol, fst2, f));
270  }
271 
272  assert(RandEquivalent(*fst, fst2, 5/*paths*/, 0.01/*delta*/, kaldi::Rand()/*seed*/, 100/*path length-- max?*/));
273 
274  delete fst;
275 }
276 
277 
278 // MakeLoopFstCompare is as MakeLoopFst but implmented differently [ less efficiently
279 // but more clearly], so we can check for equivalence.
280 template<class Arc>
281 VectorFst<Arc>* MakeLoopFstCompare(const vector<const ExpandedFst<Arc> *> &fsts) {
282  VectorFst<Arc> *ans = new VectorFst<Arc>;
283  typedef typename Arc::Label Label;
284  typedef typename Arc::StateId StateId;
285  typedef typename Arc::Weight Weight;
286 
287  for (Label i = 0; i < fsts.size(); i++) {
288  if (fsts[i] != NULL) {
289  VectorFst<Arc> i_fst; // accepts symbol i on output.
290  i_fst.AddState(); i_fst.AddState();
291  i_fst.SetStart(0); i_fst.SetFinal(1, Weight::One());
292  i_fst.AddArc(0, Arc(0, i, Weight::One(), 1));
293  VectorFst<Arc> other_fst(*(fsts[i])); // copy it.
294  ClearSymbols(false, true, &other_fst); // Clear output symbols so symbols
295  // are on input side.
296  Concat(&i_fst, other_fst); // now i_fst is "i_fst [concat] other_fst".
297  Union(ans, i_fst);
298  }
299  }
300  Closure(ans, CLOSURE_STAR);
301  return ans;
302 }
303 
304 
305 template<class Arc> void TestMakeLoopFst() {
306 
307  int num_fsts = kaldi::Rand() % 10;
308  vector<const ExpandedFst<Arc>* > fsts(num_fsts, (const ExpandedFst<Arc>*)NULL);
309  for (int i = 0; i < num_fsts; i++) {
310  if (kaldi::Rand() % 2 == 0) { // put an fst there.
311  VectorFst<Arc> *fst = RandFst<Arc>();
312  Project(fst, PROJECT_INPUT); // make input & output labels the same.
313  fsts[i] = fst;
314  } else { // this is to test that it works with the caching.
315  fsts[i] = fsts[i/2];
316  }
317  }
318 
319  VectorFst<Arc> *fst1 = MakeLoopFst(fsts),
320  *fst2 = MakeLoopFstCompare(fsts);
321 
322  assert(fst1->Properties(kOLabelSorted, kOLabelSorted) != 0);
323 
324  assert(RandEquivalent(*fst1, *fst2, 5/*paths*/, 0.01/*delta*/, kaldi::Rand()/*seed*/, 100/*path length-- max?*/));
325  delete fst1;
326  delete fst2;
327  std::sort(fsts.begin(), fsts.end());
328  fsts.erase(std::unique(fsts.begin(), fsts.end()), fsts.end());
329  for (int i = 0; i < (int)fsts.size(); i++)
330  delete fsts[i];
331 }
332 
333 
334 
335 template<class Arc>
337  for (size_t i = 0; i < 4; i++) {
338  RandFstOptions opts;
339  opts.allow_empty = false;
340  VectorFst<Arc> *fst = RandFst<Arc>();
341  int length = 10 + kaldi::Rand() % 20;
342 
343  VectorFst<Arc> fst_path;
344  if (EqualAlign(*fst, length, kaldi::Rand(), &fst_path)) {
345  std::cout << "EqualAlign succeeded\n";
346  vector<int32> isymbol_seq, osymbol_seq;
347  typename Arc::Weight weight;
348  GetLinearSymbolSequence(fst_path, &isymbol_seq, &osymbol_seq, &weight);
349  assert(isymbol_seq.size() == length);
350  Invert(&fst_path);
351  VectorFst<Arc> fst_composed;
352  Compose(fst_path, *fst, &fst_composed);
353  assert(fst_composed.Start() != kNoStateId); // make sure nonempty.
354  } else {
355  std::cout << "EqualAlign did not generate alignment\n";
356  }
357  delete fst;
358  }
359 }
360 
361 
362 template<class Arc> void Print(const Fst<Arc> &fst, std::string message) {
363  std::cout << message << "\n";
364  FstPrinter<Arc> fstprinter(fst, NULL, NULL, NULL, false, true, "\t");
365  fstprinter.Print(&std::cout, "standard output");
366 }
367 
368 
369 template<class Arc>
371  for (size_t i = 0; i < 4; i++) {
372  RandFstOptions opts;
373  opts.allow_empty = false;
374  VectorFst<Arc> *fst = RandFst<Arc>();
375  // Print(*fst, "[testremoveuselessarcs]:fst:");
376  UniformArcSelector<Arc> selector;
377  RandGenOptions<UniformArcSelector<Arc> > randgen_opts(selector);
378  VectorFst<Arc> fst_path;
379  RandGen(*fst, &fst_path, randgen_opts);
380  Project(&fst_path, PROJECT_INPUT);
381  // Print(fst_path, "[testremoveuselessarcs]:fstpath:");
382 
383  VectorFst<Arc> fst_nouseless(*fst);
384  RemoveUselessArcs(&fst_nouseless);
385  // Print(fst_nouseless, "[testremoveuselessarcs]:fst_nouseless:");
386 
387  VectorFst<Arc> orig_composed,
388  nouseless_composed;
389  Compose(fst_path, *fst, &orig_composed);
390  Compose(fst_path, fst_nouseless, &nouseless_composed);
391 
392  // Print(orig_composed, "[testremoveuselessarcs]:orig_composed");
393  // Print(nouseless_composed, "[testremoveuselessarcs]:nouseless_composed");
394 
395  VectorFst<Arc> orig_bestpath,
396  nouseless_bestpath;
397  ShortestPath(orig_composed, &orig_bestpath);
398  ShortestPath(nouseless_composed, &nouseless_bestpath);
399  // Print(orig_bestpath, "[testremoveuselessarcs]:orig_bestpath");
400  // Print(nouseless_bestpath, "[testremoveuselessarcs]:nouseless_bestpath");
401 
402  typename Arc::Weight worig, wnouseless;
403  GetLinearSymbolSequence<Arc, int>(orig_bestpath, NULL, NULL, &worig);
404  GetLinearSymbolSequence<Arc, int>(nouseless_bestpath, NULL, NULL, &wnouseless);
405  assert(ApproxEqual(worig, wnouseless, kDelta));
406 
407  // assert(RandEquivalent(orig_bestpath, nouseless_bestpath, 5/*paths*/, 0.01/*delta*/, Rand()/*seed*/, 100/*path length-- max?*/));
408  delete fst;
409  }
410 }
411 
412 
413 
414 } // end namespace fst
415 
416 
417 int main() {
418  for (int i = 0; i < 5; i++) {
419  fst::TestMakeLinearAcceptor<fst::StdArc, int>(); // this also tests GetLinearSymbolSequence, GetInputSymbols and GetOutputSymbols.
420  fst::TestMakeLinearAcceptor<fst::StdArc, int32>();
421  fst::TestMakeLinearAcceptor<fst::StdArc, uint32>();
422  fst::TestSafeDeterminizeWrapper<fst::StdArc>();
423  fst::TestAcceptorMinimize<fst::StdArc>();
424  fst::TestMakeSymbolsSame<fst::StdArc>();
425  fst::TestMakeSymbolsSame<fst::LogArc>();
426  fst::TestMakeSymbolsSameClass<fst::StdArc>();
427  fst::TestMakeSymbolsSameClass<fst::LogArc>();
428  fst::TestMakeLoopFst<fst::StdArc>();
429  fst::TestMakeLoopFst<fst::LogArc>();
430  fst::TestEqualAlign<fst::StdArc>();
431  fst::TestEqualAlign<fst::LogArc>();
432  fst::TestRemoveUselessArcs<fst::StdArc>();
433  }
434 }
fst::StdArc::StateId StateId
void TestMakeLoopFst()
void TestSafeDeterminizeWrapper()
void MakePrecedingInputSymbolsSame(bool start_is_epsilon, MutableFst< Arc > *fst)
MakePrecedingInputSymbolsSame ensures that all arcs entering any given fst state have the same input ...
void PreDeterminize(MutableFst< Arc > *fst, typename Arc::Label first_new_sym, std::vector< Int > *symsOut)
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
void TestMakeSymbolsSameClass()
VectorFst< Arc > * MakeLoopFstCompare(const vector< const ExpandedFst< Arc > *> &fsts)
kaldi::int32 int32
void TestMakeLinearAcceptor()
bool ApproxEqual(const LatticeWeightTpl< FloatType > &w1, const LatticeWeightTpl< FloatType > &w2, float delta=kDelta)
Result operator()(Arg a) const
void ClearSymbols(bool clear_input, bool clear_output, MutableFst< Arc > *fst)
ClearSymbols sets all the symbols on the input and/or output side of the FST to zero, as specified.
void SortAndUniq(std::vector< T > *vec)
Sorts and uniq&#39;s (removes duplicates) from a vector.
Definition: stl-utils.h:39
bool GetLinearSymbolSequence(const Fst< Arc > &fst, std::vector< I > *isymbols_out, std::vector< I > *osymbols_out, typename Arc::Weight *tot_weight_out)
GetLinearSymbolSequence gets the symbol sequence from a linear FST.
void GetInputSymbols(const Fst< Arc > &fst, bool include_eps, std::vector< I > *symbols)
GetInputSymbols gets the list of symbols on the input of fst (including epsilon, if include_eps == tr...
void TestDeterminizeStarInLog()
void RemoveUselessArcs(MutableFst< Arc > *fst)
void MakeLinearAcceptor(const std::vector< I > &labels, MutableFst< Arc > *ofst)
Creates unweighted linear acceptor from symbol sequence.
void TestPushInLog()
bool EqualAlign(const Fst< Arc > &ifst, typename Arc::StateId length, int rand_seed, MutableFst< Arc > *ofst, int num_retries)
EqualAlign is similar to RandGen, but it generates a sequence with exactly "length" input symbols...
void NbestAsFsts(const Fst< Arc > &fst, size_t n, std::vector< VectorFst< Arc > > *fsts_out)
Takes the n-shortest-paths (using ShortestPath), but outputs the result as a vector of up to n fsts...
void Closure(MutableFst< Arc > *fst, std::set< typename Arc::StateId > *S, const std::vector< bool > &pVec)
VectorFst< Arc > * MakeLoopFst(const std::vector< const ExpandedFst< Arc > *> &fsts)
MakeLoopFst creates an FST that has a state that is both initial and final (weight == Weight::One())...
bool PrecedingInputSymbolsAreSame(bool start_is_epsilon, const Fst< Arc > &fst)
Returns true if and only if the FST is such that the input symbols on arcs entering any given state a...
int main()
fst::StdArc::Label Label
int Rand(struct RandomState *state)
Definition: kaldi-math.cc:45
bool PrecedingInputSymbolsAreSameClass(bool start_is_epsilon, const Fst< Arc > &fst, const F &f)
This is as PrecedingInputSymbolsAreSame, but with a functor f that maps labels to classes...
void MakePrecedingInputSymbolsSameClass(bool start_is_epsilon, MutableFst< Arc > *fst, const F &f)
As MakePrecedingInputSymbolsSame, but takes a functor object that maps labels to classes.
fst::StdArc::Weight Weight
bool FollowingInputSymbolsAreSame(bool end_is_epsilon, const Fst< Arc > &fst)
Returns true if and only if the FST is such that the input symbols on arcs exiting any given state al...
Arc::Label HighestNumberedInputSymbol(const Fst< Arc > &fst)
Returns the highest numbered input symbol id of the FST (or zero for an empty FST.
void TestEqualAlign()
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
void RemoveWeights(MutableFst< Arc > *ifst)
void SafeDeterminizeWrapper(MutableFst< Arc > *ifst, MutableFst< Arc > *ofst, float delta)
Does PreDeterminize and DeterminizeStar and then removes the disambiguation symbols.
void Print(const Fst< Arc > &fst, std::string message)
void SafeDeterminizeMinimizeWrapperInLog(VectorFst< StdArc > *ifst, VectorFst< StdArc > *ofst, float delta)
SafeDeterminizeMinimizeWapperInLog is as SafeDeterminizeMinimizeWrapper except it first casts tothe l...
void SafeDeterminizeMinimizeWrapper(MutableFst< Arc > *ifst, VectorFst< Arc > *ofst, float delta)
SafeDeterminizeMinimizeWapper is as SafeDeterminizeWrapper except that it also minimizes (encoded min...
bool FollowingInputSymbolsAreSameClass(bool end_is_epsilon, const Fst< Arc > &fst, const F &f)
void MakeFollowingInputSymbolsSameClass(bool end_is_epsilon, MutableFst< Arc > *fst, const F &f)
As MakeFollowingInputSymbolsSame, but takes a functor object that maps labels to classes.
#define KALDI_LOG
Definition: kaldi-error.h:153
void MakeFollowingInputSymbolsSame(bool end_is_epsilon, MutableFst< Arc > *fst)
MakeFollowingInputSymbolsSame ensures that all arcs exiting any given fst state have the same input s...
void TestMakeSymbolsSame()
void TestRemoveUselessArcs()
void TestAcceptorMinimize()