31 std::vector<std::vector<int32> > *graph) {
34 graph->resize(num_nodes);
35 for (
int32 n = 0;
n < num_nodes;
n++) {
38 std::vector<int32> node_dependencies;
46 node_dependencies.push_back(
n - 1);
55 for (
size_t i = 0;
i < node_dependencies.size();
i++) {
56 int32 dep_n = node_dependencies[
i];
58 (*graph)[dep_n].push_back(
n);
64 std::vector<std::vector<int32> > *graph_transpose) {
65 int32 size = graph.size();
66 graph_transpose->clear();
67 graph_transpose->resize(size);
69 const std::vector<int32> &nodes = graph[
n];
70 std::vector<int32>::const_iterator iter = nodes.begin(), end = nodes.end();
71 for (; iter != end; ++iter) {
73 (*graph_transpose)[dest].push_back(
n);
82 TarjanNode() : index(-1), lowlink(-1), on_stack(false) {}
86 const std::vector<std::vector<int32> > &graph,
88 std::vector<TarjanNode> *tarjan_nodes,
89 std::vector<int32> *tarjan_stack,
90 std::vector<std::vector<int32> > *sccs) {
98 (*tarjan_nodes)[node].index = *global_index;
99 (*tarjan_nodes)[node].lowlink = *global_index;
101 (*tarjan_nodes)[node].on_stack =
true;
102 tarjan_stack->push_back(node);
105 for (
int32 i = 0;
i < graph[node].size(); ++
i) {
106 int32 next = graph[node][
i];
108 if ((*tarjan_nodes)[next].index == -1) {
111 global_index, tarjan_nodes, tarjan_stack, sccs);
112 (*tarjan_nodes)[node].lowlink = std::min((*tarjan_nodes)[node].
lowlink,
113 (*tarjan_nodes)[next].lowlink);
114 }
else if ((*tarjan_nodes)[next].
on_stack) {
118 (*tarjan_nodes)[node].lowlink = std::min((*tarjan_nodes)[node].
lowlink,
119 (*tarjan_nodes)[next].
index);
124 if ((*tarjan_nodes)[node].
index == (*tarjan_nodes)[node].
lowlink) {
125 std::vector<int32> scc;
128 pop_node = tarjan_stack->back();
129 tarjan_stack->pop_back();
130 (*tarjan_nodes)[pop_node].on_stack =
false;
131 scc.push_back(pop_node);
132 }
while (pop_node != node);
134 sccs->push_back(scc);
139 std::vector<std::vector<int32> > *sccs) {
143 std::vector<TarjanNode> tarjan_nodes(graph.size());
144 std::vector<int32> tarjan_stack;
145 int32 global_index = 0;
148 for (
int32 n = 0;
n < graph.size(); ++
n) {
149 if (tarjan_nodes[
n].
index == -1) {
151 &global_index, &tarjan_nodes, &tarjan_stack, sccs);
156 void FindSccs(
const std::vector<std::vector<int32> > &graph,
157 std::vector<std::vector<int32> > *sccs) {
165 const std::vector<std::vector<int32> > &sccs,
166 std::vector<std::vector<int32> > *scc_graph) {
169 scc_graph->resize(sccs.size());
172 std::vector<int32> node_to_scc_index(graph.size());
173 for (
int32 i = 0;
i < sccs.size(); ++
i) {
174 for (
int32 j = 0;
j < sccs[
i].size(); ++
j) {
176 node_to_scc_index[sccs[
i][
j]] =
i;
181 for (
int32 i = 0;
i < sccs.size(); ++
i) {
182 for (
int32 j = 0;
j < sccs[
i].size(); ++
j) {
185 for (
int32 k = 0; k < graph[node].size(); ++k) {
186 if (node_to_scc_index[graph[node][k]] !=
i) {
187 (*scc_graph)[
i].push_back(node_to_scc_index[graph[node][k]]);
197 const std::vector<std::vector<int32> > &graph,
198 std::vector<bool> *cycle_detector,
199 std::vector<bool> *is_visited,
200 std::vector<int32> *reversed_orders) {
205 if ((*cycle_detector)[node]) {
206 KALDI_ERR <<
"Cycle detected when computing the topological sorting order";
209 if (!(*is_visited)[node]) {
210 (*cycle_detector)[node] =
true;
211 for (
int32 i = 0;
i < graph[node].size(); ++
i) {
213 cycle_detector, is_visited, reversed_orders);
215 (*cycle_detector)[node] =
false;
216 (*is_visited)[node] =
true;
219 reversed_orders->push_back(node);
224 std::vector<int32> *node_to_order) {
228 node_to_order->resize(graph.size());
230 std::vector<bool> cycle_detector(graph.size(),
false);
231 std::vector<bool> is_visited(graph.size(),
false);
233 std::vector<int32> reversed_orders;
234 for(
int32 i = 0;
i < graph.size(); ++
i) {
235 if (!is_visited[
i]) {
237 &is_visited, &reversed_orders);
241 KALDI_ASSERT(node_to_order->size() == reversed_orders.size());
242 for (
int32 i = 0;
i < reversed_orders.size(); ++
i) {
243 KALDI_ASSERT(reversed_orders[
i] >= 0 && reversed_orders[
i] < graph.size());
244 (*node_to_order)[reversed_orders[
i]] = graph.size() -
i - 1;
249 std::ostringstream os;
250 int32 num_nodes = graph.size();
251 for (
int32 i = 0;
i < num_nodes;
i++) {
253 const std::vector<int32> &vec = graph[
i];
254 int32 size = vec.size();
257 if (
j + 1 < size) os <<
",";
260 if (i + 1 < num_nodes) os <<
"; ";
266 std::vector<int32> *node_to_epoch) {
269 std::vector<std::vector<int32> > graph;
273 std::vector<std::vector<int32> > sccs;
276 std::vector<std::vector<int32> > scc_graph;
280 std::vector<int32> scc_node_to_epoch;
283 std::ostringstream os;
284 for (
int32 i = 0;
i < scc_node_to_epoch.size();
i++)
285 os << scc_node_to_epoch[
i] <<
", ";
286 KALDI_VLOG(6) <<
"scc_node_to_epoch is: " << os.str();
289 node_to_epoch->clear();
290 node_to_epoch->resize(graph.size());
291 for (
int32 i = 0;
i < sccs.size(); ++
i) {
292 for (
int32 j = 0;
j < sccs[
i].size(); ++
j) {
295 (*node_to_epoch)[node] = scc_node_to_epoch[
i];
301 std::vector<std::vector<int32> > sccs;
303 for (
size_t i = 0;
i < sccs.size();
i++) {
304 if (sccs[
i].size() > 1)
308 int32 num_nodes = graph.size();
309 for (
size_t i = 0;
i < num_nodes;
i++)
310 for (std::vector<int32>::const_iterator iter = graph[
i].begin(),
311 end = graph[
i].end(); iter != end; ++iter)
312 if (*iter ==
i)
return true;
void NnetToDirectedGraph(const Nnet &nnet, std::vector< std::vector< int32 > > *graph)
This function takes an nnet and turns it to a directed graph on nodes.
This code computes Goodness of Pronunciation (GOP) and extracts phone-level pronunciation feature for...
void ComputeTopSortOrderRecursive(int32 node, const std::vector< std::vector< int32 > > &graph, std::vector< bool > *cycle_detector, std::vector< bool > *is_visited, std::vector< int32 > *reversed_orders)
void GetNodeDependencies(std::vector< int32 > *node_indexes) const
int32 GetVerboseLevel()
Get verbosity level, usually set via command line '–verbose=' switch.
void SortAndUniq(std::vector< T > *vec)
Sorts and uniq's (removes duplicates) from a vector.
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.
bool GraphHasCycles(const std::vector< std::vector< int32 > > &graph)
This function returns 'true' if the graph represented in 'graph' contains cycles (including cycles wh...
const NetworkNode & GetNode(int32 node) const
returns const reference to a particular numbered network node.
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...
void ComputeNnetComputationEpochs(const Nnet &nnet, std::vector< int32 > *node_to_epoch)
This function computes the order in which we need to compute each node in the graph, where each node-index n maps to an epoch-index t = 0, 1, ...
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...
NetworkNode is used to represent, three types of thing: either an input of the network (which pretty ...
This file contains a few functions that treat the neural net as a graph on nodes: e...
#define KALDI_ASSERT(cond)
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.
void TarjanSccRecursive(int32 node, const std::vector< std::vector< int32 > > &graph, int32 *global_index, std::vector< TarjanNode > *tarjan_nodes, std::vector< int32 > *tarjan_stack, std::vector< std::vector< int32 > > *sccs)
union kaldi::nnet3::NetworkNode::@15 u
void FindSccsTarjan(const std::vector< std::vector< int32 > > &graph, std::vector< std::vector< int32 > > *sccs)
std::string PrintGraphToString(const std::vector< std::vector< int32 > > &graph)
Prints a graph to a string in a pretty way for human readability, e.g.