fsttablecompose.cc File Reference
#include "base/kaldi-common.h"
#include "util/common-utils.h"
#include "fst/fstlib.h"
#include "fstext/table-matcher.h"
#include "fstext/fstext-utils.h"
#include "fstext/kaldi-fst-io.h"
Include dependency graph for fsttablecompose.cc:

Go to the source code of this file.

Functions

int main (int argc, char *argv[])
 

Function Documentation

◆ main()

int main ( int  argc,
char *  argv[] 
)

Definition at line 42 of file fsttablecompose.cc.

References kaldi::ClassifyRspecifier(), kaldi::ClassifyWspecifier(), TableComposeOptions::connect, SequentialTableReader< Holder >::Done(), TableComposeOptions::filter_type, ParseOptions::GetArg(), ParseOptions::GetOptArg(), RandomAccessTableReader< Holder >::HasKey(), KALDI_ERR, KALDI_LOG, KALDI_WARN, SequentialTableReader< Holder >::Key(), kaldi::kNoRspecifier, kaldi::kNoWspecifier, SequentialTableReader< Holder >::Next(), ParseOptions::NumArgs(), ParseOptions::PrintUsage(), ParseOptions::Read(), fst::ReadFstKaldi(), ParseOptions::Register(), TableComposeOptions::table_match_type, fst::TableCompose(), RandomAccessTableReader< Holder >::Value(), SequentialTableReader< Holder >::Value(), TableWriter< Holder >::Write(), and fst::WriteFstKaldi().

42  {
43  try {
44  using namespace kaldi;
45  using namespace fst;
46  using kaldi::int32;
47  /*
48  fsttablecompose should always give equivalent results to compose,
49  but it is more efficient for certain kinds of inputs.
50  In particular, it is useful when, say, the left FST has states
51  that typically either have epsilon olabels, or
52  one transition out for each of the possible symbols (as the
53  olabel). The same with the input symbols of the right-hand FST
54  is possible.
55  */
56 
57  const char *usage =
58  "Composition algorithm [between two FSTs of standard type, in tropical\n"
59  "semiring] that is more efficient for certain cases-- in particular,\n"
60  "where one of the FSTs (the left one, if --match-side=left) has large\n"
61  "out-degree\n"
62  "\n"
63  "Usage: fsttablecompose (fst1-rxfilename|fst1-rspecifier) "
64  "(fst2-rxfilename|fst2-rspecifier) [(out-rxfilename|out-rspecifier)]\n";
65 
66  ParseOptions po(usage);
67 
69  std::string match_side = "left";
70  std::string compose_filter = "sequence";
71 
72  po.Register("connect", &opts.connect, "If true, trim FST before output.");
73  po.Register("match-side", &match_side, "Side of composition to do table "
74  "match, one of: \"left\" or \"right\".");
75  po.Register("compose-filter", &compose_filter, "Composition filter to use, "
76  "one of: \"alt_sequence\", \"auto\", \"match\", \"sequence\"");
77 
78  po.Read(argc, argv);
79 
80  if (match_side == "left") {
81  opts.table_match_type = MATCH_OUTPUT;
82  } else if (match_side == "right") {
83  opts.table_match_type = MATCH_INPUT;
84  } else {
85  KALDI_ERR << "Invalid match-side option: " << match_side;
86  }
87 
88  if (compose_filter == "alt_sequence") {
89  opts.filter_type = ALT_SEQUENCE_FILTER;
90  } else if (compose_filter == "auto") {
91  opts.filter_type = AUTO_FILTER;
92  } else if (compose_filter == "match") {
93  opts.filter_type = MATCH_FILTER;
94  } else if (compose_filter == "sequence") {
95  opts.filter_type = SEQUENCE_FILTER;
96  } else {
97  KALDI_ERR << "Invalid compose-filter option: " << compose_filter;
98  }
99 
100  if (po.NumArgs() < 2 || po.NumArgs() > 3) {
101  po.PrintUsage();
102  exit(1);
103  }
104 
105  std::string fst1_in_str = po.GetArg(1),
106  fst2_in_str = po.GetArg(2),
107  fst_out_str = po.GetOptArg(3);
108 
109 
110  // Note: the "table" in is_table_1 and similar variables has nothing
111  // to do with the "table" in "fsttablecompose"; is_table_1 relates to
112  // whether we are dealing with a single FST or a whole set of FSTs.
113  bool is_table_1 =
114  (ClassifyRspecifier(fst1_in_str, NULL, NULL) != kNoRspecifier),
115  is_table_2 =
116  (ClassifyRspecifier(fst2_in_str, NULL, NULL) != kNoRspecifier),
117  is_table_out =
118  (ClassifyWspecifier(fst_out_str, NULL, NULL, NULL) != kNoWspecifier);
119  if (is_table_out != (is_table_1 || is_table_2))
120  KALDI_ERR << "Incompatible combination of archives and files";
121 
122  if (!is_table_1 && !is_table_2) { // Only dealing with files...
123  VectorFst<StdArc> *fst1 = ReadFstKaldi(fst1_in_str);
124 
125  VectorFst<StdArc> *fst2 = ReadFstKaldi(fst2_in_str);
126 
127  // Checks if <fst1> is olabel sorted and <fst2> is ilabel sorted.
128  if (fst1->Properties(fst::kOLabelSorted, true) == 0) {
129  KALDI_WARN << "The first FST is not olabel sorted.";
130  }
131  if (fst2->Properties(fst::kILabelSorted, true) == 0) {
132  KALDI_WARN << "The second FST is not ilabel sorted.";
133  }
134 
135  VectorFst<StdArc> composed_fst;
136 
137  TableCompose(*fst1, *fst2, &composed_fst, opts);
138 
139  delete fst1;
140  delete fst2;
141 
142  WriteFstKaldi(composed_fst, fst_out_str);
143  return 0;
144  } else if (!is_table_1 && is_table_2
145  && opts.table_match_type == MATCH_OUTPUT) {
146  // second arg is an archive, and match-side=left (default).
147  TableComposeCache<Fst<StdArc> > cache(opts);
148  VectorFst<StdArc> *fst1 = ReadFstKaldi(fst1_in_str);
149  SequentialTableReader<VectorFstHolder> fst2_reader(fst2_in_str);
150  TableWriter<VectorFstHolder> fst_writer(fst_out_str);
151  int32 n_done = 0;
152 
153  // Checks if <fst1> is olabel sorted.
154  if (fst1->Properties(fst::kOLabelSorted, true) == 0) {
155  KALDI_WARN << "The first FST is not olabel sorted.";
156  }
157  for (; !fst2_reader.Done(); fst2_reader.Next(), n_done++) {
158  VectorFst<StdArc> fst2(fst2_reader.Value());
159  VectorFst<StdArc> fst_out;
160  TableCompose(*fst1, fst2, &fst_out, &cache);
161  fst_writer.Write(fst2_reader.Key(), fst_out);
162  }
163  KALDI_LOG << "Composed " << n_done << " FSTs.";
164  return (n_done != 0 ? 0 : 1);
165  } else if (is_table_1 && is_table_2) {
166  SequentialTableReader<VectorFstHolder> fst1_reader(fst1_in_str);
167  RandomAccessTableReader<VectorFstHolder> fst2_reader(fst2_in_str);
168  TableWriter<VectorFstHolder> fst_writer(fst_out_str);
169  int32 n_done = 0, n_err = 0;
170  for (; !fst1_reader.Done(); fst1_reader.Next()) {
171  std::string key = fst1_reader.Key();
172  if (!fst2_reader.HasKey(key)) {
173  KALDI_WARN << "No such key " << key << " in second table.";
174  n_err++;
175  } else {
176  const VectorFst<StdArc> &fst1(fst1_reader.Value()),
177  &fst2(fst2_reader.Value(key));
178  VectorFst<StdArc> result;
179  TableCompose(fst1, fst2, &result, opts);
180  if (result.NumStates() == 0) {
181  KALDI_WARN << "Empty output for key " << key;
182  n_err++;
183  } else {
184  fst_writer.Write(key, result);
185  n_done++;
186  }
187  }
188  }
189  KALDI_LOG << "Successfully composed " << n_done << " FSTs, errors or "
190  << "empty output on " << n_err;
191  } else {
192  KALDI_ERR << "The combination of tables/non-tables and match-type that you "
193  << "supplied is not currently supported. Either implement this, "
194  << "ask the maintainers to implement it, or call this program "
195  << "differently.";
196  }
197  } catch(const std::exception &e) {
198  std::cerr << e.what();
199  return -1;
200  }
201 }
This code computes Goodness of Pronunciation (GOP) and extracts phone-level pronunciation feature for...
Definition: chain.dox:20
void TableCompose(const Fst< Arc > &ifst1, const Fst< Arc > &ifst2, MutableFst< Arc > *ofst, const TableComposeOptions &opts=TableComposeOptions())
For an extended explanation of the framework of which grammar-fsts are a part, please see Support for...
Definition: graph.dox:21
A templated class for writing objects to an archive or script file; see The Table concept...
Definition: kaldi-table.h:368
kaldi::int32 int32
RspecifierType ClassifyRspecifier(const std::string &rspecifier, std::string *rxfilename, RspecifierOptions *opts)
Definition: kaldi-table.cc:225
Allows random access to a collection of objects in an archive or script file; see The Table concept...
Definition: kaldi-table.h:233
TableComposeCache lets us do multiple compositions while caching the same matcher.
The class ParseOptions is for parsing command-line options; see Parsing command-line options for more...
Definition: parse-options.h:36
A templated class for reading objects sequentially from an archive or script file; see The Table conc...
Definition: kaldi-table.h:287
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_WARN
Definition: kaldi-error.h:150
WspecifierType ClassifyWspecifier(const std::string &wspecifier, std::string *archive_wxfilename, std::string *script_wxfilename, WspecifierOptions *opts)
Definition: kaldi-table.cc:135
void WriteFstKaldi(std::ostream &os, bool binary, const VectorFst< Arc > &t)
void ReadFstKaldi(std::istream &is, bool binary, VectorFst< Arc > *fst)
#define KALDI_LOG
Definition: kaldi-error.h:153