event-map-test.cc
Go to the documentation of this file.
1 // tree/event-map-test.cc
2 
3 // Copyright 2009-2011 Microsoft Corporation; Haihua Xu; Yanmin Qian
4 // 2013 Johns Hopkins University (author: Daniel Povey)
5 
6 // See ../../COPYING for clarification regarding multiple authors
7 //
8 // Licensed under the Apache License, Version 2.0 (the "License");
9 // you may not use this file except in compliance with the License.
10 // You may obtain a copy of the License at
11 //
12 // http://www.apache.org/licenses/LICENSE-2.0
13 //
14 // THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
16 // WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
17 // MERCHANTABLITY OR NON-INFRINGEMENT.
18 // See the Apache 2 License for the specific language governing permissions and
19 // limitations under the License.
20 
21 #include "tree/event-map.h"
22 #include "util/kaldi-io.h"
23 #include <map>
24 
25 namespace kaldi {
26 
27 void TestEventMap() {
28  typedef EventKeyType KeyType;
29  typedef EventValueType ValueType;
30  typedef EventAnswerType AnswerType;
31 
32 
33  ConstantEventMap *C0a = new ConstantEventMap(0);
34  {
35  int32 num_leaves;
36  std::vector<int32> parents;
37  bool a = GetTreeStructure(*C0a, &num_leaves, &parents);
38  KALDI_ASSERT(a && parents.size() == 1 && parents[0] == 0);
39  }
40  ConstantEventMap *C1b = new ConstantEventMap(1);
41  {
42  int32 num_leaves;
43  std::vector<int32> parents;
44  bool a = GetTreeStructure(*C1b, &num_leaves, &parents);
45  KALDI_ASSERT(!a); // since C1b's leaves don't start from 0.
46  }
47 
48  std::vector<EventMap*> tvec;
49  tvec.push_back(C0a);
50  tvec.push_back(C1b);
51 
52  TableEventMap *T1 = new TableEventMap(1, tvec); // takes ownership of C0a, C1b
53  KALDI_ASSERT(T1->MaxResult() == 1);
54 
55  {
56  int32 num_leaves;
57  std::vector<int32> parents;
58  bool a = GetTreeStructure(*T1, &num_leaves, &parents);
59  KALDI_ASSERT(a && parents.size() == 3 && parents[0] == 2
60  && parents[1] == 2 && parents[2] == 2);
61  }
62 
63  ConstantEventMap *C0c = new ConstantEventMap(0);
64  ConstantEventMap *C1d = new ConstantEventMap(1);
65 
66  std::map<ValueType, EventMap*> tmap;
67  tmap[0] = C0c; tmap[1] = C1d;
68  TableEventMap *T2 = new TableEventMap(1, tmap); // takes ownership of pointers C0c and C1d.
69 
70  std::vector<ValueType> vec;
71  vec.push_back(4);
72  vec.push_back(5);
73 
74 
75  ConstantEventMap *D1 = new ConstantEventMap(10); // owned by D3 below
76  ConstantEventMap *D2 = new ConstantEventMap(15); // owned by D3 below
77 
78  SplitEventMap *D3 = new SplitEventMap(1, vec, D1, D2);
79 
80  // Test different initializer for TableEventMap where input maps ints to ints.
81  for (size_t i = 0;i < 100;i++) {
82  size_t nElems = Rand() % 10; // num of value->answer pairs.
83  std::map<ValueType, AnswerType> init_map;
84  for (size_t i = 0;i < nElems;i++) {
85  init_map[Rand() % 10] = Rand() % 5;
86  }
87  EventKeyType key = Rand() % 10;
88  TableEventMap T3(key, init_map);
89  for (size_t i = 0; i < 10; i++) {
90  EventType vec;
91  vec.push_back(std::make_pair(key, (ValueType) i));
92  AnswerType ans;
93  // T3.Map(vec, &ans);
94  if (init_map.count(i) == 0) {
95  KALDI_ASSERT( ! T3.Map(vec, &ans) ); // false
96  } else {
97  bool b = T3.Map(vec, &ans);
98  KALDI_ASSERT(b);
99  KALDI_ASSERT(ans == init_map[i]); // true
100  }
101  }
102  }
103 
104  delete T1;
105  delete T2;
106  delete D3;
107 }
108 
109 
110 void TestEventTypeIo(bool binary) {
111  for (size_t p = 0; p < 20; p++) {
112  EventType event_vec;
113  size_t size = Rand() % 20;
114  event_vec.resize(size);
115  for (size_t i = 0;i < size;i++) {
116  event_vec[i].first = Rand() % 10 + (i > 0 ? event_vec[i-1].first : 0);
117  event_vec[i].second = Rand() % 20;
118  }
119 
120 
121  {
122  const char *filename = "tmpf";
123  Output ko(filename, binary);
124  std::ostream &outfile = ko.Stream();
125  WriteEventType(outfile, binary, event_vec);
126  ko.Close();
127 
128  {
129  bool binary_in;
130  Input ki(filename, &binary_in);
131  std::istream &infile = ki.Stream();
132  EventType evec2;
133  evec2.push_back(std::pair<EventKeyType, EventValueType>(1, 1)); // make it nonempty.
134  ReadEventType(infile, binary_in, &evec2);
135  KALDI_ASSERT(evec2 == event_vec);
136  }
137  }
138  }
139 
140  unlink("tmpf");
141 }
142 
143 const int32 kMaxVal = 20;
144 
145 EventMap *RandomEventMap(const std::vector<EventKeyType> &keys) {
146  // Do not mess with the probabilities inside this routine or there
147  // is a danger this function will blow up.
148  int32 max_val = kMaxVal;
149  KALDI_ASSERT(keys.size() != 0);
150  float f = RandUniform();
151  if (f < 0.333) { // w.p. 0.333, return ConstantEventMap.
152  return new ConstantEventMap(Rand() % max_val);
153  } else if (f < 0.666) { // w.p. 0.333, return TableEventMap.
154  float nonnull_prob = 0.3; // prob of a non-NULL pointer.
155  float expected_table_size = 3.0;
156  int32 table_size = RandPoisson(expected_table_size);
157  // fertility from this branch is 0.333 * 3.0 * 0.2333 = 0.3.
158  EventKeyType key = keys[Rand() % keys.size()];
159  std::vector<EventMap*> table(table_size);
160  for (size_t t = 0; t < (size_t)table_size; t++) {
161  if (RandUniform() < nonnull_prob) table[t] = RandomEventMap(keys);
162  else table[t] = NULL;
163  }
164  return new TableEventMap(key, table);
165  } else { // w.p. 0.333, return SplitEventMap.
166  // Fertility of this stage is 0.333 * 2 = 0.666.
167  EventKeyType key = keys[Rand() % keys.size()];
168  std::set<EventValueType> yes_set;
169  for (size_t i = 0; i < 5; i++) yes_set.insert(Rand() % max_val);
170  std::vector<EventValueType> yes_vec;
171  CopySetToVector(yes_set, &yes_vec);
172  EventMap *yes = RandomEventMap(keys), *no = RandomEventMap(keys);
173  return new SplitEventMap(key, yes_vec, yes, no);
174  }
175  // total fertility is 0.3 + 0.666 = 0.9666, hence this will terminate with finite memory (w.p.1)
176 }
177 
178 void TestEventMapIo(bool binary) {
179  for (size_t p = 0; p < 20; p++) {
180  int32 max_key = 10;
181  int32 num_keys = 1 + (Rand() % (max_key - 1));
182  std::set<EventKeyType> key_set;
183  // - 5 to allow negative keys. These are allowed.
184  while (key_set.size() < (size_t)num_keys) key_set.insert( (Rand() % (2*max_key)) - 5);
185  std::vector<EventKeyType> key_vec;
186  CopySetToVector(key_set, &key_vec);
187  EventMap *rand_map = RandomEventMap(key_vec);
188 
189  std::ostringstream str_out;
190  EventMap::Write(str_out, binary, rand_map);
191 
192 
193  if (p < 1) {
194  std::cout << "Random map is: "<<str_out.str()<<'\n';
195  }
196 
197  std::istringstream str_in(str_out.str());
198 
199  EventMap *read_map = EventMap::Read(str_in, binary);
200  std::ostringstream str2_out;
201  EventMap::Write(str2_out, binary, read_map);
202 
203  // Checking we can write the map, read it in, and get the same string form.
204  KALDI_ASSERT(str_out.str() == str2_out.str());
205  delete read_map;
206  delete rand_map;
207  }
208 }
209 
211  const EventAnswerType no_ans = -10;
212  std::vector<EventKeyType> keys;
213  keys.push_back(1); // these keys are
214  keys.push_back(2); // hardwired into the code below, do not change
215  EventMap *em = RandomEventMap(keys);
216  EventType empty_event;
217  std::vector<EventAnswerType> all_answers;
218  em->MultiMap(empty_event, &all_answers);
219  SortAndUniq(&all_answers);
220  std::vector<EventMap*> new_leaves;
221  std::vector<EventAnswerType> mapping;
222  for (size_t i = 0; i < all_answers.size(); i++) {
223  EventAnswerType ans = all_answers[i];
224  KALDI_ASSERT(ans >= 0);
225  new_leaves.resize(ans + 1, NULL);
226  mapping.resize(ans + 1, no_ans);
227  EventAnswerType map_to;
228  if (Rand() % 2 == 0) map_to = -1;
229  else map_to = Rand() % 20;
230  new_leaves[ans] = new ConstantEventMap(map_to);
231  mapping[ans] = map_to;
232  }
233  EventMap *mapped_em = em->Copy(new_leaves),
234  *pruned_em = mapped_em->Prune();
235  for (size_t i = 0; i < new_leaves.size(); i++)
236  delete new_leaves[i];
237  for (int32 i = 0; i < 10; i++) {
238  EventType event;
239  for (int32 key = 1; key <= 2; key++) {
240  if (Rand() % 2 == 0) {
241  EventValueType value = Rand() % 20;
242  event.push_back(std::make_pair(key, value));
243  }
244  }
245  EventAnswerType answer, answer2;
246  if (em->Map(event, &answer)) {
247  bool ret;
248  if (pruned_em == NULL) ret = false;
249  else ret = pruned_em->Map(event, &answer2);
250  KALDI_ASSERT(answer >= 0);
251  EventAnswerType mapped_ans = mapping[answer];
252  KALDI_ASSERT(mapped_ans != no_ans);
253  if (mapped_ans == -1) {
254  if (ret == false)
255  KALDI_LOG << "Answer was correctly pruned away.";
256  else
257  KALDI_LOG << "Answer was not pruned away [but this is not required]";
258  } else {
259  KALDI_ASSERT(ret == true);
260  KALDI_ASSERT(answer2 == mapped_ans);
261  KALDI_LOG << "Answers match " << answer << " -> " << answer2;
262  }
263  }
264  }
265  delete em;
266  delete mapped_em;
267  delete pruned_em;
268 }
269 
271  std::vector<EventKeyType> keys;
272  keys.push_back(1); // these keys are
273  keys.push_back(2); // hardwired into the code below, do not change
274  EventMap *em = RandomEventMap(keys);
275  EventType empty_event;
276 
277  unordered_set<EventKeyType> mapped_keys;
278  unordered_map<EventKeyType,EventKeyType> value_map;
279  if (Rand() % 2 == 0) mapped_keys.insert(1);
280  if (Rand() % 2 == 0) mapped_keys.insert(2);
281 
282  EventValueType v_offset = Rand() % kMaxVal;
283  for (EventValueType v = 0; v < kMaxVal; v++)
284  value_map[v] = (v + v_offset) % kMaxVal;
285 
286  EventMap *mapped_em = em->MapValues(mapped_keys, value_map);
287 
288  for (int32 i = 0; i < 10; i++) {
289  EventType event, mapped_event;
290  for (int32 key = 1; key <= 2; key++) {
291  if (Rand() % 2 == 0) {
292  EventValueType value = Rand() % kMaxVal;
293  event.push_back(std::make_pair(key, value));
294  EventValueType mapped_value;
295  if (mapped_keys.count(key) == 0) mapped_value = value;
296  else mapped_value = value_map[value];
297  mapped_event.push_back(std::make_pair(key, mapped_value));
298  }
299  }
300  EventAnswerType answer, answer2;
301  if (em->Map(event, &answer)) {
302  bool ret = mapped_em->Map(mapped_event, &answer2);
303  KALDI_ASSERT(ret);
304  KALDI_ASSERT(answer == answer2);
305  }
306  }
307  delete em;
308  delete mapped_em;
309 }
310 
311 
312 
313 } // end namespace kaldi
314 
315 
316 
317 
318 int main() {
319  using namespace kaldi;
320  TestEventTypeIo(false);
321  TestEventTypeIo(true);
322  TestEventMapIo(false);
323  TestEventMapIo(true);
324  for (int32 i = 0; i < 10; i++) {
325  TestEventMap();
328  }
329 }
bool GetTreeStructure(const EventMap &map, int32 *num_leaves, std::vector< int32 > *parents)
This function gets the tree structure of the EventMap "map" in a convenient form. ...
Definition: event-map.cc:429
This code computes Goodness of Pronunciation (GOP) and extracts phone-level pronunciation feature for...
Definition: chain.dox:20
void CopySetToVector(const std::set< T > &s, std::vector< T > *v)
Copies the elements of a set to a vector.
Definition: stl-utils.h:86
float RandUniform(struct RandomState *state=NULL)
Returns a random number strictly between 0 and 1.
Definition: kaldi-math.h:151
void TestEventMapPrune()
void TestEventTypeIo(bool binary)
const int32 kMaxVal
virtual EventAnswerType MaxResult() const
Definition: event-map.h:142
virtual bool Map(const EventType &event, EventAnswerType *ans) const
Definition: event-map.h:209
kaldi::int32 int32
void TestEventMapIo(bool binary)
int main()
void SortAndUniq(std::vector< T > *vec)
Sorts and uniq&#39;s (removes duplicates) from a vector.
Definition: stl-utils.h:39
virtual bool Map(const EventType &event, EventAnswerType *ans) const =0
int32 RandPoisson(float lambda, struct RandomState *state)
Definition: kaldi-math.cc:126
static EventMap * Read(std::istream &is, bool binary)
a Read function that reads an arbitrary EventMap; also works for NULL pointers.
Definition: event-map.cc:36
void WriteEventType(std::ostream &os, bool binary, const EventType &evec)
Definition: event-map.cc:228
std::istream & Stream()
Definition: kaldi-io.cc:826
std::vector< std::pair< EventKeyType, EventValueType > > EventType
Definition: event-map.h:58
std::ostream & Stream()
Definition: kaldi-io.cc:701
void TestEventMap()
int32 EventKeyType
Things of type EventKeyType can take any value.
Definition: event-map.h:45
void ReadEventType(std::istream &is, bool binary, EventType *evec)
Definition: event-map.cc:239
virtual EventMap * MapValues(const unordered_set< EventKeyType > &keys_to_map, const unordered_map< EventValueType, EventValueType > &value_map) const =0
virtual EventMap * Copy(const std::vector< EventMap *> &new_leaves) const =0
int Rand(struct RandomState *state)
Definition: kaldi-math.cc:45
A class that is capable of representing a generic mapping from EventType (which is a vector of (key...
Definition: event-map.h:86
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
int32 EventAnswerType
As far as the event-map code itself is concerned, things of type EventAnswerType may take any value e...
Definition: event-map.h:56
void TestEventMapMapValues()
int32 EventValueType
Given current code, things of type EventValueType should generally be nonnegative and in a reasonably...
Definition: event-map.h:51
virtual EventMap * Prune() const =0
EventMap * RandomEventMap(const std::vector< EventKeyType > &keys)
virtual void MultiMap(const EventType &event, std::vector< EventAnswerType > *ans) const =0
#define KALDI_LOG
Definition: kaldi-error.h:153
virtual void Write(std::ostream &os, bool binary)=0
Write to stream.
bool Close()
Definition: kaldi-io.cc:677