All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages

A class for storing topology information for phones. More...

#include <hmm-topology.h>

Collaboration diagram for HmmTopology:

Classes

struct  HmmState
 A structure defined inside HmmTopology to represent a HMM state. More...
 

Public Types

typedef std::vector< HmmStateTopologyEntry
 TopologyEntry is a typedef that represents the topology of a single (prototype) state. More...
 

Public Member Functions

void Read (std::istream &is, bool binary)
 
void Write (std::ostream &os, bool binary) const
 
void Check ()
 
bool IsHmm () const
 Returns true if this HmmTopology is really 'hmm-like', i.e. More...
 
const TopologyEntryTopologyForPhone (int32 phone) const
 Returns the topology entry (i.e. More...
 
int32 NumPdfClasses (int32 phone) const
 Returns the number of pdf-classes for this phone; throws exception if phone not covered by this topology. More...
 
const std::vector< int32 > & GetPhones () const
 Returns a reference to a sorted, unique list of phones covered by the topology (these phones will be positive integers, and usually contiguous and starting from one but the toolkit doesn't assume they are contiguous). More...
 
void GetPhoneToNumPdfClasses (std::vector< int32 > *phone2num_pdf_classes) const
 Outputs a vector of int32, indexed by phone, that gives the number of Pdf-classes pdf-classes for the phones; this is used by tree-building code such as BuildTree(). More...
 
int32 MinLength (int32 phone) const
 
 HmmTopology ()
 
bool operator== (const HmmTopology &other) const
 

Private Attributes

std::vector< int32 > phones_
 
std::vector< int32 > phone2idx_
 
std::vector< TopologyEntryentries_
 

Detailed Description

A class for storing topology information for phones.

See HMM topology and transition modeling for context. This object is sometimes accessed in a file by itself, but more often as a class member of the Transition class (this is for convenience to reduce the number of files programs have to access).

Definition at line 94 of file hmm-topology.h.

Member Typedef Documentation

typedef std::vector<HmmState> TopologyEntry

TopologyEntry is a typedef that represents the topology of a single (prototype) state.

Definition at line 134 of file hmm-topology.h.

Constructor & Destructor Documentation

HmmTopology ( )
inline

Definition at line 175 of file hmm-topology.h.

175 {}

Member Function Documentation

void Check ( )

Definition at line 231 of file hmm-topology.cc.

References HmmTopology::entries_, rnnlm::i, rnnlm::j, KALDI_ASSERT, KALDI_ERR, KALDI_WARN, kaldi::kNoPdf, HmmTopology::phone2idx_, HmmTopology::phones_, and kaldi::SortAndUniq().

Referenced by HmmTopology::Read().

231  {
232  if (entries_.empty() || phones_.empty() || phone2idx_.empty())
233  KALDI_ERR << "HmmTopology::Check(), empty object.";
234  std::vector<bool> is_seen(entries_.size(), false);
235  for (size_t i = 0; i < phones_.size(); i++) {
236  int32 phone = phones_[i];
237  if (static_cast<size_t>(phone) >= phone2idx_.size() ||
238  static_cast<size_t>(phone2idx_[phone]) >= entries_.size())
239  KALDI_ERR << "HmmTopology::Check(), phone has no valid index.";
240  is_seen[phone2idx_[phone]] = true;
241  }
242  for (size_t i = 0; i < entries_.size(); i++) {
243  if (!is_seen[i])
244  KALDI_ERR << "HmmTopoloy::Check(), entry with no corresponding phones.";
245  int32 num_states = static_cast<int32>(entries_[i].size());
246  if (num_states <= 1)
247  KALDI_ERR << "HmmTopology::Check(), cannot only have one state (i.e., must "
248  "have at least one emitting state).";
249  if (!entries_[i][num_states-1].transitions.empty())
250  KALDI_ERR << "HmmTopology::Check(), last state must have no transitions.";
251  // not sure how necessary this next stipulation is.
252  if (entries_[i][num_states-1].forward_pdf_class != kNoPdf)
253  KALDI_ERR << "HmmTopology::Check(), last state must not be emitting.";
254 
255  std::vector<bool> has_trans_in(num_states, false);
256  std::vector<int32> seen_pdf_classes;
257 
258  for (int32 j = 0; j < num_states; j++) { // j is the state-id.
259  BaseFloat tot_prob = 0.0;
260  if (entries_[i][j].forward_pdf_class != kNoPdf) {
261  seen_pdf_classes.push_back(entries_[i][j].forward_pdf_class);
262  seen_pdf_classes.push_back(entries_[i][j].self_loop_pdf_class);
263  }
264  std::set<int32> seen_transition;
265  for (int32 k = 0;
266  static_cast<size_t>(k) < entries_[i][j].transitions.size();
267  k++) {
268  tot_prob += entries_[i][j].transitions[k].second;
269  if (entries_[i][j].transitions[k].second <= 0.0)
270  KALDI_ERR << "HmmTopology::Check(), negative or zero transition prob.";
271  int32 dst_state = entries_[i][j].transitions[k].first;
272  // The commented code in the next few lines disallows a completely
273  // skippable phone, as this would cause to stop working some mechanisms
274  // that are being built, which enable the creation of phone-level lattices
275  // and rescoring these with a different lexicon and LM.
276  if (dst_state == num_states-1 // && j != 0
277  && entries_[i][j].forward_pdf_class == kNoPdf)
278  KALDI_ERR << "We do not allow any state to be "
279  "nonemitting and have a transition to the final-state (this would "
280  "stop the SplitToPhones function from identifying the last state "
281  "of a phone.";
282  if (dst_state < 0 || dst_state >= num_states)
283  KALDI_ERR << "HmmTopology::Check(), invalid dest state " << (dst_state);
284  if (seen_transition.count(dst_state) != 0)
285  KALDI_ERR << "HmmTopology::Check(), duplicate transition found.";
286  if (dst_state == k) { // self_loop...
287  KALDI_ASSERT(entries_[i][j].self_loop_pdf_class != kNoPdf &&
288  "Nonemitting states cannot have self-loops.");
289  }
290  seen_transition.insert(dst_state);
291  has_trans_in[dst_state] = true;
292  }
293  if (j+1 < num_states) {
294  KALDI_ASSERT(tot_prob > 0.0 && "Non-final state must have transitions out."
295  "(with nonzero probability)");
296  if (fabs(tot_prob - 1.0) > 0.01)
297  KALDI_WARN << "Total probability for state " << j <<
298  " in topology entry is " << tot_prob;
299  } else
300  KALDI_ASSERT(tot_prob == 0.0);
301  }
302  // make sure all but start state have input transitions.
303  for (int32 j = 1; j < num_states; j++)
304  if (!has_trans_in[j])
305  KALDI_ERR << "HmmTopology::Check, state "<<(j)<<" has no input transitions.";
306  SortAndUniq(&seen_pdf_classes);
307  if (seen_pdf_classes.front() != 0 ||
308  seen_pdf_classes.back() != static_cast<int32>(seen_pdf_classes.size()) - 1) {
309  KALDI_ERR << "HmmTopology::Check(), pdf_classes are expected to be "
310  "contiguous and start from zero.";
311  }
312  }
313 }
void SortAndUniq(std::vector< T > *vec)
Sorts and uniq's (removes duplicates) from a vector.
Definition: stl-utils.h:39
static const int32 kNoPdf
A constant used in the HmmTopology class as the pdf-class kNoPdf, which is used when a HMM-state is n...
Definition: hmm-topology.h:87
std::vector< int32 > phones_
Definition: hmm-topology.h:183
float BaseFloat
Definition: kaldi-types.h:29
#define KALDI_ERR
Definition: kaldi-error.h:127
std::vector< TopologyEntry > entries_
Definition: hmm-topology.h:185
#define KALDI_WARN
Definition: kaldi-error.h:130
std::vector< int32 > phone2idx_
Definition: hmm-topology.h:184
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
const std::vector<int32>& GetPhones ( ) const
inline

Returns a reference to a sorted, unique list of phones covered by the topology (these phones will be positive integers, and usually contiguous and starting from one but the toolkit doesn't assume they are contiguous).

Definition at line 164 of file hmm-topology.h.

References HmmTopology::phones_.

Referenced by TransitionModel::ComputeTuplesIsHmm(), TransitionModel::ComputeTuplesNotHmm(), TransitionModel::GetPhones(), HmmTopology::IsHmm(), TransitionModel::IsHmm(), main(), and kaldi::ProcessTopo().

164 { return phones_; };
std::vector< int32 > phones_
Definition: hmm-topology.h:183
void GetPhoneToNumPdfClasses ( std::vector< int32 > *  phone2num_pdf_classes) const

Outputs a vector of int32, indexed by phone, that gives the number of Pdf-classes pdf-classes for the phones; this is used by tree-building code such as BuildTree().

Definition at line 31 of file hmm-topology.cc.

References rnnlm::i, KALDI_ASSERT, HmmTopology::NumPdfClasses(), and HmmTopology::phones_.

Referenced by main().

31  {
32  KALDI_ASSERT(!phones_.empty());
33  phone2num_pdf_classes->clear();
34  phone2num_pdf_classes->resize(phones_.back() + 1, -1);
35  for (size_t i = 0; i < phones_.size(); i++)
36  (*phone2num_pdf_classes)[phones_[i]] = NumPdfClasses(phones_[i]);
37 }
std::vector< int32 > phones_
Definition: hmm-topology.h:183
int32 NumPdfClasses(int32 phone) const
Returns the number of pdf-classes for this phone; throws exception if phone not covered by this topol...
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
bool IsHmm ( ) const

Returns true if this HmmTopology is really 'hmm-like', i.e.

the pdf-class on the self-loops and forward transitions of all states are identical. [note: in HMMs, the densities are associated with the states.] We have extended this to support 'non-hmm-like' topologies (where those pdf-classes are different), in order to make for more compact decoding graphs in our so-called 'chain models' (AKA lattice-free MMI), where we use 1-state topologies that have different pdf-classes for the self-loop and the forward transition. Note that we always use the 'reorder=true' option so the 'forward transition' actually comes before the self-loop.

Definition at line 315 of file hmm-topology.cc.

References HmmTopology::GetPhones(), rnnlm::i, rnnlm::j, KALDI_ASSERT, and HmmTopology::TopologyForPhone().

Referenced by HmmTopology::Write().

315  {
316  const std::vector<int32> &phones = GetPhones();
317  KALDI_ASSERT(!phones.empty());
318  for (size_t i = 0; i < phones.size(); i++) {
319  int32 phone = phones[i];
320  const TopologyEntry &entry = TopologyForPhone(phone);
321  for (int32 j = 0; j < static_cast<int32>(entry.size()); j++) { // for each state...
322  int32 forward_pdf_class = entry[j].forward_pdf_class,
323  self_loop_pdf_class = entry[j].self_loop_pdf_class;
324  if (forward_pdf_class != self_loop_pdf_class)
325  return false;
326  }
327  }
328  return true;
329 }
const TopologyEntry & TopologyForPhone(int32 phone) const
Returns the topology entry (i.e.
std::vector< HmmState > TopologyEntry
TopologyEntry is a typedef that represents the topology of a single (prototype) state.
Definition: hmm-topology.h:134
const std::vector< int32 > & GetPhones() const
Returns a reference to a sorted, unique list of phones covered by the topology (these phones will be ...
Definition: hmm-topology.h:164
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
int32 MinLength ( int32  phone) const

Definition at line 349 of file hmm-topology.cc.

References KALDI_ASSERT, HmmTopology::TopologyForPhone(), and HmmTopology::HmmState::transitions.

Referenced by kaldi::ComputeNewPhoneLengths(), kaldi::GetRandomAlignmentForPhone(), and kaldi::TestHmmTopology().

349  {
350  const TopologyEntry &entry = TopologyForPhone(phone);
351  // min_length[state] gives the minimum length for sequences up to and
352  // including that state.
353  std::vector<int32> min_length(entry.size(),
354  std::numeric_limits<int32>::max());
355  KALDI_ASSERT(!entry.empty());
356 
357  min_length[0] = (entry[0].forward_pdf_class == -1 ? 0 : 1);
358  int32 num_states = min_length.size();
359  bool changed = true;
360  while (changed) {
361  changed = false;
362  for (int32 s = 0; s < num_states; s++) {
363  const HmmState &this_state = entry[s];
364  std::vector<std::pair<int32, BaseFloat> >::const_iterator
365  iter = this_state.transitions.begin(),
366  end = this_state.transitions.end();
367  for (; iter != end; ++iter) {
368  int32 next_state = iter->first;
369  KALDI_ASSERT(next_state < num_states);
370  int32 next_state_min_length = min_length[s] +
371  (entry[next_state].forward_pdf_class == -1 ? 0 : 1);
372  if (next_state_min_length < min_length[next_state]) {
373  min_length[next_state] = next_state_min_length;
374  if (next_state < s)
375  changed = true;
376  // the test of 'next_state < s' is an optimization for speed.
377  }
378  }
379  }
380  }
381  KALDI_ASSERT(min_length.back() != std::numeric_limits<int32>::max());
382  // the last state is the final-state.
383  return min_length.back();
384 }
const TopologyEntry & TopologyForPhone(int32 phone) const
Returns the topology entry (i.e.
std::vector< HmmState > TopologyEntry
TopologyEntry is a typedef that represents the topology of a single (prototype) state.
Definition: hmm-topology.h:134
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
int32 NumPdfClasses ( int32  phone) const

Returns the number of pdf-classes for this phone; throws exception if phone not covered by this topology.

Definition at line 338 of file hmm-topology.cc.

References rnnlm::i, and HmmTopology::TopologyForPhone().

Referenced by TransitionModel::ComputeTuplesIsHmm(), kaldi::GetHmmAsFst(), kaldi::GetIlabelMapping(), HmmTopology::GetPhoneToNumPdfClasses(), main(), and kaldi::ProcessTopo().

338  {
339  // will throw if phone not covered.
340  const TopologyEntry &entry = TopologyForPhone(phone);
341  int32 max_pdf_class = 0;
342  for (size_t i = 0; i < entry.size(); i++) {
343  max_pdf_class = std::max(max_pdf_class, entry[i].forward_pdf_class);
344  max_pdf_class = std::max(max_pdf_class, entry[i].self_loop_pdf_class);
345  }
346  return max_pdf_class+1;
347 }
const TopologyEntry & TopologyForPhone(int32 phone) const
Returns the topology entry (i.e.
std::vector< HmmState > TopologyEntry
TopologyEntry is a typedef that represents the topology of a single (prototype) state.
Definition: hmm-topology.h:134
bool operator== ( const HmmTopology other) const
inline

Definition at line 177 of file hmm-topology.h.

References HmmTopology::entries_, HmmTopology::phone2idx_, and HmmTopology::phones_.

177  {
178  return phones_ == other.phones_ && phone2idx_ == other.phone2idx_
179  && entries_ == other.entries_;
180  }
std::vector< int32 > phones_
Definition: hmm-topology.h:183
std::vector< TopologyEntry > entries_
Definition: hmm-topology.h:185
std::vector< int32 > phone2idx_
Definition: hmm-topology.h:184
void Read ( std::istream &  is,
bool  binary 
)

Definition at line 39 of file hmm-topology.cc.

References HmmTopology::Check(), kaldi::ConvertStringToInteger(), HmmTopology::entries_, kaldi::ExpectToken(), rnnlm::i, kaldi::IsSortedAndUniq(), rnnlm::j, KALDI_ASSERT, KALDI_ERR, kaldi::kNoPdf, HmmTopology::phone2idx_, HmmTopology::phones_, kaldi::ReadBasicType(), kaldi::ReadIntegerVector(), and kaldi::ReadToken().

Referenced by kaldi::GenRandTopology(), kaldi::GetDefaultTopology(), main(), TransitionModel::Read(), and kaldi::TestHmmTopology().

39  {
40  ExpectToken(is, binary, "<Topology>");
41  if (!binary) { // Text-mode read, different "human-readable" format.
42  phones_.clear();
43  phone2idx_.clear();
44  entries_.clear();
45  std::string token;
46  while ( ! (is >> token).fail() ) {
47  if (token == "</Topology>") { break; } // finished parsing.
48  else if (token != "<TopologyEntry>") {
49  KALDI_ERR << "Reading HmmTopology object, expected </Topology> or <TopologyEntry>, got "<<token;
50  } else {
51  ExpectToken(is, binary, "<ForPhones>");
52  std::vector<int32> phones;
53  std::string s;
54  while (1) {
55  is >> s;
56  if (is.fail()) KALDI_ERR << "Reading HmmTopology object, unexpected end of file while expecting phones.";
57  if (s == "</ForPhones>") break;
58  else {
59  int32 phone;
60  if (!ConvertStringToInteger(s, &phone))
61  KALDI_ERR << "Reading HmmTopology object, expected "
62  << "integer, got instead " << s;
63  phones.push_back(phone);
64  }
65  }
66 
67  std::vector<HmmState> this_entry;
68  std::string token;
69  ReadToken(is, binary, &token);
70  while (token != "</TopologyEntry>") {
71  if (token != "<State>")
72  KALDI_ERR << "Expected </TopologyEntry> or <State>, got instead "<<token;
73  int32 state;
74  ReadBasicType(is, binary, &state);
75  if (state != static_cast<int32>(this_entry.size()))
76  KALDI_ERR << "States are expected to be in order from zero, expected "
77  << this_entry.size() << ", got " << state;
78  ReadToken(is, binary, &token);
79  int32 forward_pdf_class = kNoPdf; // -1 by default, means no pdf.
80  if (token == "<PdfClass>") {
81  ReadBasicType(is, binary, &forward_pdf_class);
82  this_entry.push_back(HmmState(forward_pdf_class));
83  ReadToken(is, binary, &token);
84  if (token == "<SelfLoopPdfClass>")
85  KALDI_ERR << "pdf classes should be defined using <PdfClass> "
86  << "or <ForwardPdfClass>/<SelfLoopPdfClass> pair";
87  } else if (token == "<ForwardPdfClass>") {
88  int32 self_loop_pdf_class = kNoPdf;
89  ReadBasicType(is, binary, &forward_pdf_class);
90  ReadToken(is, binary, &token);
91  KALDI_ASSERT(token == "<SelfLoopPdfClass>");
92  ReadBasicType(is, binary, &self_loop_pdf_class);
93  this_entry.push_back(HmmState(forward_pdf_class, self_loop_pdf_class));
94  ReadToken(is, binary, &token);
95  } else
96  this_entry.push_back(HmmState(forward_pdf_class));
97  while (token == "<Transition>") {
98  int32 dst_state;
99  BaseFloat trans_prob;
100  ReadBasicType(is, binary, &dst_state);
101  ReadBasicType(is, binary, &trans_prob);
102  this_entry.back().transitions.push_back(std::make_pair(dst_state, trans_prob));
103  ReadToken(is, binary, &token);
104  }
105  if(token == "<Final>") // TODO: remove this clause after a while.
106  KALDI_ERR << "You are trying to read old-format topology with new Kaldi.";
107  if (token != "</State>")
108  KALDI_ERR << "Reading HmmTopology, unexpected token "<<token;
109  ReadToken(is, binary, &token);
110  }
111  int32 my_index = entries_.size();
112  entries_.push_back(this_entry);
113 
114  for (size_t i = 0; i < phones.size(); i++) {
115  int32 phone = phones[i];
116  if (static_cast<int32>(phone2idx_.size()) <= phone)
117  phone2idx_.resize(phone+1, -1); // -1 is invalid index.
118  KALDI_ASSERT(phone > 0);
119  if (phone2idx_[phone] != -1)
120  KALDI_ERR << "Phone with index "<<(i)<<" appears in multiple topology entries.";
121  phone2idx_[phone] = my_index;
122  phones_.push_back(phone);
123  }
124  }
125  }
126  std::sort(phones_.begin(), phones_.end());
128  } else { // binary I/O, just read member objects directly from disk.
129  ReadIntegerVector(is, binary, &phones_);
130  ReadIntegerVector(is, binary, &phone2idx_);
131  int32 sz;
132  ReadBasicType(is, binary, &sz);
133  bool is_hmm = true;
134  if (sz == -1) {
135  is_hmm = false;
136  ReadBasicType(is, binary, &sz);
137  }
138  entries_.resize(sz);
139  for (int32 i = 0; i < sz; i++) {
140  int32 thist_sz;
141  ReadBasicType(is, binary, &thist_sz);
142  entries_[i].resize(thist_sz);
143  for (int32 j = 0 ; j < thist_sz; j++) {
144  ReadBasicType(is, binary, &(entries_[i][j].forward_pdf_class));
145  if (is_hmm)
146  entries_[i][j].self_loop_pdf_class = entries_[i][j].forward_pdf_class;
147  else
148  ReadBasicType(is, binary, &(entries_[i][j].self_loop_pdf_class));
149  int32 thiss_sz;
150  ReadBasicType(is, binary, &thiss_sz);
151  entries_[i][j].transitions.resize(thiss_sz);
152  for (int32 k = 0; k < thiss_sz; k++) {
153  ReadBasicType(is, binary, &(entries_[i][j].transitions[k].first));
154  ReadBasicType(is, binary, &(entries_[i][j].transitions[k].second));
155  }
156  }
157  }
158  ExpectToken(is, binary, "</Topology>");
159  }
160  Check(); // Will throw if not ok.
161 }
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 ReadBasicType(std::istream &is, bool binary, T *t)
ReadBasicType is the name of the read function for bool, integer types, and floating-point types...
Definition: io-funcs-inl.h:55
void ReadToken(std::istream &is, bool binary, std::string *str)
ReadToken gets the next token and puts it in str (exception on failure).
Definition: io-funcs.cc:154
static const int32 kNoPdf
A constant used in the HmmTopology class as the pdf-class kNoPdf, which is used when a HMM-state is n...
Definition: hmm-topology.h:87
std::vector< int32 > phones_
Definition: hmm-topology.h:183
float BaseFloat
Definition: kaldi-types.h:29
void ReadIntegerVector(std::istream &is, bool binary, std::vector< T > *v)
Function for reading STL vector of integer types.
Definition: io-funcs-inl.h:232
void ExpectToken(std::istream &is, bool binary, const char *token)
ExpectToken tries to read in the given token, and throws an exception on failure. ...
Definition: io-funcs.cc:188
#define KALDI_ERR
Definition: kaldi-error.h:127
std::vector< TopologyEntry > entries_
Definition: hmm-topology.h:185
std::vector< int32 > phone2idx_
Definition: hmm-topology.h:184
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
bool IsSortedAndUniq(const std::vector< T > &vec)
Returns true if the vector is sorted and contains each element only once.
Definition: stl-utils.h:63
const HmmTopology::TopologyEntry & TopologyForPhone ( int32  phone) const
void Write ( std::ostream &  os,
bool  binary 
) const

Definition at line 164 of file hmm-topology.cc.

References HmmTopology::entries_, rnnlm::i, HmmTopology::IsHmm(), rnnlm::j, KALDI_ASSERT, kaldi::kNoPdf, HmmTopology::phone2idx_, HmmTopology::phones_, kaldi::WriteBasicType(), kaldi::WriteIntegerVector(), and kaldi::WriteToken().

Referenced by kaldi::TestHmmTopology(), and TransitionModel::Write().

164  {
165  bool is_hmm = IsHmm();
166  WriteToken(os, binary, "<Topology>");
167  if (!binary) { // Text-mode write.
168  os << "\n";
169  for (int32 i = 0; i < static_cast<int32> (entries_.size()); i++) {
170  WriteToken(os, binary, "<TopologyEntry>");
171  os << "\n";
172  WriteToken(os, binary, "<ForPhones>");
173  os << "\n";
174  for (size_t j = 0; j < phone2idx_.size(); j++) {
175  if (phone2idx_[j] == i)
176  os << j << " ";
177  }
178  os << "\n";
179  WriteToken(os, binary, "</ForPhones>");
180  os << "\n";
181  for (size_t j = 0; j < entries_[i].size(); j++) {
182  WriteToken(os, binary, "<State>");
183  WriteBasicType(os, binary, static_cast<int32>(j));
184  if (entries_[i][j].forward_pdf_class != kNoPdf) {
185  if (is_hmm) {
186  WriteToken(os, binary, "<PdfClass>");
187  WriteBasicType(os, binary, entries_[i][j].forward_pdf_class);
188  } else {
189  WriteToken(os, binary, "<ForwardPdfClass>");
190  WriteBasicType(os, binary, entries_[i][j].forward_pdf_class);
191  KALDI_ASSERT(entries_[i][j].self_loop_pdf_class != kNoPdf);
192  WriteToken(os, binary, "<SelfLoopPdfClass>");
193  WriteBasicType(os, binary, entries_[i][j].self_loop_pdf_class);
194  }
195  }
196  for (size_t k = 0; k < entries_[i][j].transitions.size(); k++) {
197  WriteToken(os, binary, "<Transition>");
198  WriteBasicType(os, binary, entries_[i][j].transitions[k].first);
199  WriteBasicType(os, binary, entries_[i][j].transitions[k].second);
200  }
201  WriteToken(os, binary, "</State>");
202  os << "\n";
203  }
204  WriteToken(os, binary, "</TopologyEntry>");
205  os << "\n";
206  }
207  } else {
208  WriteIntegerVector(os, binary, phones_);
209  WriteIntegerVector(os, binary, phone2idx_);
210  // -1 is put here as a signal that the object has the new,
211  // extended format with SelfLoopPdfClass
212  if (!is_hmm) WriteBasicType(os, binary, static_cast<int32>(-1));
213  WriteBasicType(os, binary, static_cast<int32>(entries_.size()));
214  for (size_t i = 0; i < entries_.size(); i++) {
215  WriteBasicType(os, binary, static_cast<int32>(entries_[i].size()));
216  for (size_t j = 0; j < entries_[i].size(); j++) {
217  WriteBasicType(os, binary, entries_[i][j].forward_pdf_class);
218  if (!is_hmm) WriteBasicType(os, binary, entries_[i][j].self_loop_pdf_class);
219  WriteBasicType(os, binary, static_cast<int32>(entries_[i][j].transitions.size()));
220  for (size_t k = 0; k < entries_[i][j].transitions.size(); k++) {
221  WriteBasicType(os, binary, entries_[i][j].transitions[k].first);
222  WriteBasicType(os, binary, entries_[i][j].transitions[k].second);
223  }
224  }
225  }
226  }
227  WriteToken(os, binary, "</Topology>");
228  if (!binary) os << "\n";
229 }
static const int32 kNoPdf
A constant used in the HmmTopology class as the pdf-class kNoPdf, which is used when a HMM-state is n...
Definition: hmm-topology.h:87
std::vector< int32 > phones_
Definition: hmm-topology.h:183
bool IsHmm() const
Returns true if this HmmTopology is really 'hmm-like', i.e.
std::vector< TopologyEntry > entries_
Definition: hmm-topology.h:185
void WriteToken(std::ostream &os, bool binary, const char *token)
The WriteToken functions are for writing nonempty sequences of non-space characters.
Definition: io-funcs.cc:134
std::vector< int32 > phone2idx_
Definition: hmm-topology.h:184
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:169
void WriteIntegerVector(std::ostream &os, bool binary, const std::vector< T > &v)
Function for writing STL vectors of integer types.
Definition: io-funcs-inl.h:198
void WriteBasicType(std::ostream &os, bool binary, T t)
WriteBasicType is the name of the write function for bool, integer types, and floating-point types...
Definition: io-funcs-inl.h:34

Member Data Documentation

std::vector<int32> phone2idx_
private

The documentation for this class was generated from the following files: