nnet-graph-test.cc
Go to the documentation of this file.
1 // nnet3/nnet-graph-test.cc
2 
3 // Copyright 2015 Guoguo Chen
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 "nnet3/nnet-graph.h"
21 
22 namespace kaldi {
23 namespace nnet3 {
24 
25 // In this particular, we don't worry about tolerance and ordering.
26 bool AssertGraphEqual(const std::vector<std::vector<int32> > &graph1,
27  const std::vector<std::vector<int32> > &graph2) {
28  if (graph1.size() != graph2.size()) { return false; }
29  for (int32 i = 0; i < graph1.size(); ++i) {
30  if (graph1[i].size() != graph2[i].size()) { return false; }
31  for (int32 j = 0; j < graph1[i].size(); ++j) {
32  if (graph1[i][j] != graph2[i][j]) { return false; }
33  }
34  }
35  return true;
36 }
37 
38 bool AssertVectorEqual(const std::vector<int32> &vec1,
39  const std::vector<int32> &vec2) {
40  if (vec1.size() != vec2.size()) { return false; }
41  for (int32 i = 0; i < vec1.size(); ++i) {
42  if (vec1[i] != vec2[i]) { return false; }
43  }
44  return true;
45 }
46 
47 void BuildTestGraph(std::vector<std::vector<int32> > *graph) {
48  KALDI_ASSERT(graph != NULL);
49  graph->clear();
50  graph->resize(8);
51 
52  // We create the following graph for testing.
53  // 0 --> 4
54  // 1 --> 0
55  // 2 --> 1 3
56  // 3 --> 2
57  // 4 --> 1
58  // 5 --> 1 4 6
59  // 6 --> 5
60  // 7 --> 7 3 6
61  std::vector<int32> tmp;
62  tmp.resize(1); tmp[0] = 4; (*graph)[0] = tmp;
63  tmp.resize(1); tmp[0] = 0; (*graph)[1] = tmp;
64  tmp.resize(2); tmp[0] = 1; tmp[1] = 3; (*graph)[2] = tmp;
65  tmp.resize(1); tmp[0] = 2; (*graph)[3] = tmp;
66  tmp.resize(1); tmp[0] = 1; (*graph)[4] = tmp;
67  tmp.resize(3); tmp[0] = 1; tmp[1] = 4; tmp[2] = 6; (*graph)[5] = tmp;
68  tmp.resize(1); tmp[0] = 5; (*graph)[6] = tmp;
69  tmp.resize(3); tmp[0] = 7; tmp[1] = 3; tmp[2] = 6; (*graph)[7] = tmp;
70 }
71 
72 void BuildTestGraphTranspose(std::vector<std::vector<int32> > *graph) {
73  KALDI_ASSERT(graph != NULL);
74  graph->clear();
75  graph->resize(8);
76 
77  // We create the following graph for testing.
78  // 0 --> 1
79  // 1 --> 2 4 5
80  // 2 --> 3
81  // 3 --> 2 7
82  // 4 --> 0 5
83  // 5 --> 6
84  // 6 --> 5 7
85  // 7 --> 7
86  std::vector<int32> tmp;
87  tmp.resize(1); tmp[0] = 1; (*graph)[0] = tmp;
88  tmp.resize(3); tmp[0] = 2; tmp[1] = 4; tmp[2] = 5; (*graph)[1] = tmp;
89  tmp.resize(1); tmp[0] = 3; (*graph)[2] = tmp;
90  tmp.resize(2); tmp[0] = 2; tmp[1] = 7; (*graph)[3] = tmp;
91  tmp.resize(2); tmp[0] = 0; tmp[1] = 5; (*graph)[4] = tmp;
92  tmp.resize(1); tmp[0] = 6; (*graph)[5] = tmp;
93  tmp.resize(2); tmp[0] = 5; tmp[1] = 7; (*graph)[6] = tmp;
94  tmp.resize(1); tmp[0] = 7; (*graph)[7] = tmp;
95 }
96 
97 void BuildTestSccs(std::vector<std::vector<int32> > *sccs) {
98  KALDI_ASSERT(sccs != NULL);
99  sccs->clear();
100  sccs->resize(4);
101 
102  // We create the following SCCs for testing.
103  // 0 --> 1 4 0
104  // 1 --> 3 2
105  // 2 --> 6 5
106  // 3 --> 7
107  std::vector<int32> tmp;
108  tmp.resize(3); tmp[0] = 1; tmp[1] = 4; tmp[2] = 0; (*sccs)[0] = tmp;
109  tmp.resize(2); tmp[0] = 3; tmp[1] = 2; (*sccs)[1] = tmp;
110  tmp.resize(2); tmp[0] = 6; tmp[1] = 5; (*sccs)[2] = tmp;
111  tmp.resize(1); tmp[0] = 7; (*sccs)[3] = tmp;
112 }
113 
114 void BuildTestSccGraph(std::vector<std::vector<int32> > *scc_graph) {
115  KALDI_ASSERT(scc_graph != NULL);
116  scc_graph->clear();
117  scc_graph->resize(4);
118 
119  // We create the following SCC graph for testing.
120  // 0 -->
121  // 1 --> 0
122  // 2 --> 0
123  // 3 --> 1 2
124  std::vector<int32> tmp;
125  tmp.resize(0); (*scc_graph)[0] = tmp;
126  tmp.resize(1); tmp[0] = 0; (*scc_graph)[1] = tmp;
127  tmp.resize(1); tmp[0] = 0; (*scc_graph)[2] = tmp;
128  tmp.resize(2); tmp[0] = 1; tmp[1] = 2; (*scc_graph)[3] = tmp;
129 }
130 
131 void BuildTestTopSortOrder(std::vector<int32> *node_to_order) {
132  KALDI_ASSERT(node_to_order != NULL);
133  node_to_order->clear();
134  node_to_order->resize(4);
135 
136  // The topological sorting order of the above SCC graph is as follows (from
137  // our particular algorithm):
138  // 0 --> 3
139  // 1 --> 2
140  // 2 --> 1
141  // 3 --> 0
142  (*node_to_order)[0] = 3;
143  (*node_to_order)[1] = 2;
144  (*node_to_order)[2] = 1;
145  (*node_to_order)[3] = 0;
146 }
147 
149  std::vector<std::vector<int32> > graph;
150  BuildTestGraph(&graph);
151 
152  std::vector<std::vector<int32> > graph_transpose;
153  ComputeGraphTranspose(graph, &graph_transpose);
154 
155  std::vector<std::vector<int32> > ref_graph_transpose;
156  BuildTestGraphTranspose(&ref_graph_transpose);
157  KALDI_ASSERT(AssertGraphEqual(graph_transpose, ref_graph_transpose));
158 }
159 
161  std::vector<std::vector<int32> > graph;
162  BuildTestGraph(&graph);
163 
164  std::vector<std::vector<int32> > sccs;
165  FindSccs(graph, &sccs);
166 
167  std::vector<std::vector<int32> > ref_sccs;
168  BuildTestSccs(&ref_sccs);
169  KALDI_ASSERT(AssertGraphEqual(sccs, ref_sccs));
170 }
171 
173  std::vector<std::vector<int32> > graph;
174  BuildTestGraph(&graph);
175 
176  std::vector<std::vector<int32> > sccs;
177  BuildTestSccs(&sccs);
178 
179  std::vector<std::vector<int32> > scc_graph;
180  MakeSccGraph(graph, sccs, &scc_graph);
181 
182  std::vector<std::vector<int32> > ref_scc_graph;
183  BuildTestSccGraph(&ref_scc_graph);
184  KALDI_ASSERT(AssertGraphEqual(scc_graph, ref_scc_graph));
185 }
186 
188  std::vector<std::vector<int32> > scc_graph;
189  BuildTestSccGraph(&scc_graph);
190 
191  std::vector<int32> node_to_order;
192  ComputeTopSortOrder(scc_graph, &node_to_order);
193 
194  std::vector<int32> ref_node_to_order;
195  BuildTestTopSortOrder(&ref_node_to_order);
196  KALDI_ASSERT(AssertVectorEqual(node_to_order, ref_node_to_order));
197 }
198 
200  // The outer vector is indexed by node ID, and each nested vector contains
201  // the node IDs for its successors in the graph. For example, if there are
202  // arcs from node 0 to nodes 1 and 2, then the vector at graph[0] will be (1, 2)
203  std::vector<std::vector<int32> > graph;
204 
205  // Build a test graph:
206  // 0 ---> 1 ---> 2 ---> 4
207  // `--> 3 -----^
208  graph.resize(5);
209  graph[0].push_back(1); graph[0].push_back(3);
210  graph[1].push_back(2);
211  graph[2].push_back(4);
212  graph[3].push_back(2);
213  // graph[4] is empty(has no successors)
214 
215  // fill in the desired(topological) mapping node->order
216  std::vector<int32> ref_node_to_order;
217  ref_node_to_order.push_back(0); // node 0 comes first
218  ref_node_to_order.push_back(2); // node 1 comes third
219  ref_node_to_order.push_back(3); // node 2 comes fourth
220  ref_node_to_order.push_back(1); // node 3 comes second
221  ref_node_to_order.push_back(4); // node 4 comes last
222 
223  std::vector<int32> computed_node_to_order;
224  ComputeTopSortOrder(graph, &computed_node_to_order);
225  KALDI_ASSERT(AssertVectorEqual(ref_node_to_order, computed_node_to_order));
226 }
227 
228 } // namespace nnet3
229 } // namespace kaldi
230 
231 int main() {
232  using namespace kaldi;
233  using namespace kaldi::nnet3;
234 
240 
241  KALDI_LOG << "Nnet graph tests succeeded.";
242 
243  return 0;
244 }
This code computes Goodness of Pronunciation (GOP) and extracts phone-level pronunciation feature for...
Definition: chain.dox:20
void UnitTestFindSccs()
kaldi::int32 int32
void UnitTestComputeTopSortOrder2()
int main()
bool AssertVectorEqual(const std::vector< int32 > &vec1, const std::vector< int32 > &vec2)
void BuildTestGraph(std::vector< std::vector< int32 > > *graph)
void ComputeGraphTranspose(const std::vector< std::vector< int32 > > &graph, std::vector< std::vector< int32 > > *graph_transpose)
Outputs a graph in which the order of arcs is reversed.
Definition: nnet-graph.cc:63
void ComputeTopSortOrder(const std::vector< std::vector< int32 > > &graph, std::vector< int32 > *node_to_order)
Given an acyclic graph (where each std::vector<int32> is a list of destination-nodes of arcs coming f...
Definition: nnet-graph.cc:223
void UnitTestComputeTopSortOrder()
void BuildTestSccGraph(std::vector< std::vector< int32 > > *scc_graph)
void UnitTestComputeGraphTranspose()
void FindSccs(const std::vector< std::vector< int32 > > &graph, std::vector< std::vector< int32 > > *sccs)
Given a directed graph (where each std::vector<int32> is a list of destination-nodes of arcs coming f...
Definition: nnet-graph.cc:156
void UnitTestMakeSccGraph()
void BuildTestSccs(std::vector< std::vector< int32 > > *sccs)
This file contains a few functions that treat the neural net as a graph on nodes: e...
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
void MakeSccGraph(const std::vector< std::vector< int32 > > &graph, const std::vector< std::vector< int32 > > &sccs, std::vector< std::vector< int32 > > *scc_graph)
Given a list of sccs of a graph (e.g.
Definition: nnet-graph.cc:164
void BuildTestTopSortOrder(std::vector< int32 > *node_to_order)
#define KALDI_LOG
Definition: kaldi-error.h:153
void BuildTestGraphTranspose(std::vector< std::vector< int32 > > *graph)
bool AssertGraphEqual(const std::vector< std::vector< int32 > > &graph1, const std::vector< std::vector< int32 > > &graph2)