| 633 | } |
| 634 | |
| 635 | Status GraphConstructor::InitFromEdges() { |
| 636 | const int num_nodes = node_def_count(); |
| 637 | pending_count_.reserve(num_nodes); |
| 638 | outputs_.resize(num_nodes); |
| 639 | gtl::FlatSet<string> next_iteration_nodes; |
| 640 | for (int n = 0; n < node_def_count(); ++n) { |
| 641 | const NodeDef& node_def = get_node_def(n); |
| 642 | if (IsNextIteration(node_def)) { |
| 643 | next_iteration_nodes.insert(node_def.name()); |
| 644 | } |
| 645 | } |
| 646 | |
| 647 | // Parse the inputs for each node. |
| 648 | for (int n = 0; n < num_nodes; ++n) { |
| 649 | const NodeDef& node_def = get_node_def(n); |
| 650 | int pending_count = node_def.input_size(); |
| 651 | if (IsMerge(node_def)) { |
| 652 | // Cycles in the graph are only allowed for while loops. A while loop is |
| 653 | // identified by an edge from a NextIteration node to a Merge node. For |
| 654 | // such Merge nodes, only wait for one non-control input before |
| 655 | // considering the node ready to process in Convert(). |
| 656 | int32 num_control_edges = 0; |
| 657 | bool has_loop_back_edge = false; |
| 658 | for (int i = 0; i < node_def.input_size(); ++i) { |
| 659 | StringPiece input_name(node_def.input(i)); |
| 660 | if (absl::StartsWith(input_name, "^")) { |
| 661 | num_control_edges++; |
| 662 | } else { |
| 663 | TensorId id(ParseTensorName(input_name)); |
| 664 | if (next_iteration_nodes.find(string(id.first)) != |
| 665 | next_iteration_nodes.end()) { |
| 666 | has_loop_back_edge = true; |
| 667 | } |
| 668 | } |
| 669 | } |
| 670 | if (has_loop_back_edge) { |
| 671 | pending_count = num_control_edges + 1; |
| 672 | } |
| 673 | } |
| 674 | for (int i = 0; i < node_def.input_size(); ++i) { |
| 675 | StringPiece input_name = node_def.input(i); |
| 676 | TensorId id(ParseTensorName(input_name)); |
| 677 | if (opts_.input_map.count(id) == 0) { |
| 678 | // If an input is not mapped, then the input should appear in the graph |
| 679 | // being imported. |
| 680 | auto iter = gdef_nodes_.find(id.first); |
| 681 | if (iter == gdef_nodes_.end()) { |
| 682 | return errors::InvalidArgument("Node '", node_def.name(), |
| 683 | "': Unknown input node '", |
| 684 | node_def.input(i), "'"); |
| 685 | } |
| 686 | outputs_[iter->second.gdef_index].push_back(n); |
| 687 | } else { |
| 688 | // This input is mapped to an existing edge. Therefore this input is |
| 689 | // as good as being already processed. |
| 690 | --pending_count; |
| 691 | DCHECK_GE(pending_count, 0); |
| 692 | } |
nothing calls this directly
no test coverage detected