fstphicompose.cc
Go to the documentation of this file.
1 // fstbin/fstphicompose.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 
20 
21 #include "base/kaldi-common.h"
22 #include "util/common-utils.h"
23 #include "fst/fstlib.h"
24 #include "fstext/table-matcher.h"
25 #include "fstext/fstext-utils.h"
26 #include "fstext/kaldi-fst-io.h"
27 
28 /*
29 The following commands represent a basic test of this program.
30 
31 cat <<EOF | fstcompile > a.fst
32 0 1 10 10
33 0 1 11 11
34 1
35 EOF
36 
37 cat <<EOF | fstcompile > g.fst
38 0 1 10 10 2.0
39 0 2 100 100 6.6
40 2 1 10 10 0.0
41 2 1 11 11 1.0
42 1
43 EOF
44 fstcompose a.fst g.fst | fstprint
45 # gives, as expected:
46 # 0 1 10 10 2
47 # 1
48 fstphicompose 100 a.fst g.fst | fstprint
49 # gives, again correctly:
50 #0 1 10 10 2
51 #0 1 11 11 7.5999999
52 #1
53 
54 Next, test that it's working as desired for final-probs,
55 i.e. it takes the backoff arc when looking for a final-prob,
56 only if no final-prob present at current state.
57 
58 cat <<EOF | fstcompile > a.fst
59 0 1 10 10
60 0 1 11 11
61 1
62 EOF
63 cat <<EOF | fstcompile > g.fst
64 0 1 10 10 2.0
65 0 3 11 11 2.0
66 1 2 100 110 6.6
67 3 10.0
68 3 2 100 110 0.0
69 2
70 EOF
71 fstphicompose 100 a.fst g.fst | fstprint
72 # output is:
73 #0 1 10 10 2
74 #0 2 11 11 2
75 #1 6.5999999
76 #2 10
77 
78 */
79 
80 int main(int argc, char *argv[]) {
81  try {
82  using namespace kaldi;
83  using namespace fst;
84  using kaldi::int32;
85  /*
86  fstphicompose does composition, but treats the second FST
87  specially (basically, like a backoff LM); whenever the
88  composition algorithm fails to find a match for a label
89  in the second FST, if it sees a phi transition it will
90  take it instead, and look for a match at the destination.
91  phi is the label on the input side of the backoff arc of
92  the LM (the label on the output side doesn't matter).
93 
94  Also modifies the second fst so that it treats final-probs
95  "correctly", i.e. takes the failure transition when looking
96  for a final-prob. This would not work if there were
97  epsilons.
98  */
99 
100  const char *usage =
101  "Composition, where the right FST has \"failure\" (phi) transitions\n"
102  "that are only taken where there was no match of a \"real\" label\n"
103  "You supply the label corresponding to phi.\n"
104  "\n"
105  "Usage: fstphicompose phi-label (fst1-rxfilename|fst1-rspecifier) "
106  "(fst2-rxfilename|fst2-rspecifier) [(out-rxfilename|out-rspecifier)]\n"
107  "E.g.: fstphicompose 54 a.fst b.fst c.fst\n"
108  "or: fstphicompose 11 ark:a.fsts G.fst ark:b.fsts\n";
109 
110  ParseOptions po(usage);
111 
112  po.Read(argc, argv);
113 
114  if (po.NumArgs() < 3 || po.NumArgs() > 4) {
115  po.PrintUsage();
116  exit(1);
117  }
118 
119  std::string
120  phi_str = po.GetArg(1),
121  fst1_in_str = po.GetArg(2),
122  fst2_in_str = po.GetArg(3),
123  fst_out_str = po.GetOptArg(4);
124 
125  bool is_table_1 =
126  (ClassifyRspecifier(fst1_in_str, NULL, NULL) != kNoRspecifier),
127  is_table_2 =
128  (ClassifyRspecifier(fst2_in_str, NULL, NULL) != kNoRspecifier),
129  is_table_out =
130  (ClassifyWspecifier(fst_out_str, NULL, NULL, NULL) != kNoWspecifier);
131 
132  int32 phi_label;
133  if (!ConvertStringToInteger(phi_str, &phi_label)
134  || phi_label <= 0)
135  KALDI_ERR << "Invalid first argument (phi label), expect positive integer.";
136 
137  if (is_table_out != (is_table_1 || is_table_2))
138  KALDI_ERR << "Incompatible combination of archives and files";
139 
140  if (!is_table_1 && !is_table_2) { // Only dealing with files...
141  VectorFst<StdArc> *fst1 = ReadFstKaldi(fst1_in_str);
142 
143  VectorFst<StdArc> *fst2 = ReadFstKaldi(fst2_in_str);
144 
145  PropagateFinal(phi_label, fst2); // makes it work correctly
146  // w.r.t. final-probs.
147 
148  VectorFst<StdArc> composed_fst;
149 
150  PhiCompose(*fst1, *fst2, phi_label, &composed_fst);
151 
152  delete fst1;
153  delete fst2;
154 
155  WriteFstKaldi(composed_fst, fst_out_str);
156  return 0;
157  } else if (is_table_1 && !is_table_2) {
158 
159  VectorFst<StdArc> *fst2 = ReadFstKaldi(fst2_in_str);
160  PropagateFinal(phi_label, fst2); // makes it work correctly
161  // w.r.t. final-probs.
162  SequentialTableReader<VectorFstHolder> fst1_reader(fst1_in_str);
163  TableWriter<VectorFstHolder> fst_writer(fst_out_str);
164  int32 n_done = 0;
165  for (; !fst1_reader.Done(); fst1_reader.Next(), n_done++) {
166  VectorFst<StdArc> fst1(fst1_reader.Value());
167  VectorFst<StdArc> fst_out;
168  PhiCompose(fst1, *fst2, phi_label, &fst_out);
169  fst_writer.Write(fst1_reader.Key(), fst_out);
170  }
171  KALDI_LOG << "Composed " << n_done << " FSTs.";
172  return (n_done != 0 ? 0 : 1);
173  } else {
174  KALDI_ERR << "The combination of tables/non-tables that you "
175  << "supplied is not currently supported. Either implement this, "
176  << "ask the maintainers to implement it, or call this program "
177  << "differently.";
178  }
179  } catch(const std::exception &e) {
180  std::cerr << e.what();
181  return -1;
182  }
183 }
This code computes Goodness of Pronunciation (GOP) and extracts phone-level pronunciation feature for...
Definition: chain.dox:20
bool ConvertStringToInteger(const std::string &str, Int *out)
Converts a string into an integer via strtoll and returns false if there was any kind of problem (i...
Definition: text-utils.h:118
void PropagateFinal(typename Arc::Label phi_label, MutableFst< Arc > *fst)
For an extended explanation of the framework of which grammar-fsts are a part, please see Support for...
Definition: graph.dox:21
void PrintUsage(bool print_command_line=false)
Prints the usage documentation [provided in the constructor].
int main(int argc, char *argv[])
void PhiCompose(const Fst< Arc > &fst1, const Fst< Arc > &fst2, typename Arc::Label phi_label, MutableFst< Arc > *ofst)
A templated class for writing objects to an archive or script file; see The Table concept...
Definition: kaldi-table.h:368
kaldi::int32 int32
void Write(const std::string &key, const T &value) const
RspecifierType ClassifyRspecifier(const std::string &rspecifier, std::string *rxfilename, RspecifierOptions *opts)
Definition: kaldi-table.cc:225
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
int Read(int argc, const char *const *argv)
Parses the command line options and fills the ParseOptions-registered variables.
#define KALDI_ERR
Definition: kaldi-error.h:147
std::string GetArg(int param) const
Returns one of the positional parameters; 1-based indexing for argc/argv compatibility.
WspecifierType ClassifyWspecifier(const std::string &wspecifier, std::string *archive_wxfilename, std::string *script_wxfilename, WspecifierOptions *opts)
Definition: kaldi-table.cc:135
int NumArgs() const
Number of positional parameters (c.f. argc-1).
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
std::string GetOptArg(int param) const