tensorflow/core/graph/subgraph.cc
// Rewrite graph by replacing the output tensors specified in
// "fed_outputs" with special feed nodes for each specified output
// tensor, and removing any nodes that are now disconnected from the
// part of the graph that reaches the sink node.  The set of special
// feed nodes added to the graph are returned in "*feed_nodes".
//
// Return true on success.  On error, return false and sets *error to
// an appropriate error message (and *g is left in an indeterminate
// state).
Rewrite graph by replacing the output tensors specified in
"fed_outputs" with special feed nodes for each specified output
tensor, and removing any nodes that are now disconnected from the
part of the graph that reaches the sink node.  The set of special
feed nodes added to the graph are returned in "*feed_nodes".

Return true on success.  On error, return false and sets *error to
an appropriate error message (and *g is left in an indeterminate
state).
Rewrite graph by replacing the output tensors specified in " fed_outputs " with special feed nodes for each specified output tensor and removing any nodes that are now disconnected from the part of the graph that reaches the sink node . The set of special feed nodes added to the graph are returned in " * feed_nodes " . Return true on success . On error return false and sets * error to an appropriate error message ( and * g is left in an indeterminate state ) .
Status FeedInputs(
    Graph* g, const std::vector<std::unique_ptr<PruneRewrite>>& feed_rewrites,
    NameIndex* name_index, DataTypeVector* out_feed_types) {
  out_feed_types->clear();
  out_feed_types->reserve(feed_rewrites.size());
  for (size_t i = 0; i < feed_rewrites.size(); ++i) {
    const string& t = feed_rewrites[i]->endpoint_name();
    TensorId id(ParseTensorName(t));
    auto iter = name_index->find(id.first);
    if (iter == name_index->end()) {
      return errors::NotFound("FeedInputs: unable to find feed output ", t);
    }
    Node* n = iter->second;
    DCHECK_EQ(n->name(), id.first);
    if (id.second >= n->num_outputs()) {
      return errors::InvalidArgument(
          "FeedInputs: ", t, " should have output index < ", n->num_outputs());
    }
    Node* feed_node;
    TF_RETURN_IF_ERROR(
        feed_rewrites[i]->AddNode(g, {n, id.second}, &feed_node));
    (*name_index)[feed_node->name()] = feed_node;
    g->AddControlEdge(g->source_node(), feed_node, true);
    std::vector<const Edge*> to_remove;
    for (const Edge* e : n->out_edges()) {
      if (e->src_output() == id.second) {
        to_remove.emplace_back(e);
      } else if (e->src_output() == Graph::kControlSlot &&
                 (n->type_string() == "Placeholder" ||
                  n->type_string() == "PlaceholderV2")) {
        to_remove.emplace_back(e);
      }
    }
    for (const Edge* e : to_remove) {
      if (e->src_output() == id.second) {
        g->AddEdge(feed_node, 0, e->dst(), e->dst_input());
      } else {
        CHECK_EQ(Graph::kControlSlot, e->src_output());
        g->AddControlEdge(feed_node, e->dst(), true);
      }
      g->RemoveEdge(e);
    }
    out_feed_types->push_back(BaseType(n->output_type(id.second)));
  }
  return Status::OK();
}
Status FeedInputs ( Graph * g , const std :: vector < std :: unique_ptr < PruneRewrite > > & feed_rewrites , NameIndex * name_index , DataTypeVector * out_feed_types ) { out_feed_types -> clear ( ) ; out_feed_types -> reserve ( feed_rewrites . size ( ) ) ; for ( size_t i = 0 ; i < feed_rewrites . size ( ) ; ++ i ) { const string & t = feed_rewrites [ i ] -> endpoint_name ( ) ; TensorId id ( ParseTensorName ( t ) ) ; auto iter = name_index -> find ( id . first ) ; if ( iter == name_index -> end ( ) ) { return errors :: NotFound ( " " , t ) ; } Node * n = iter -> second ; DCHECK_EQ ( n -> name ( ) , id . first ) ; if ( id . second >= n -> num_outputs ( ) ) { return errors :: InvalidArgument ( " " , t , " " , n -> num_outputs ( ) ) ; } Node * feed_node ; TF_RETURN_IF_ERROR ( feed_rewrites [ i ] -> AddNode ( g , { n , id . second } , & feed_node ) ) ; ( * name_index ) [ feed_node -> name ( ) ] = feed_node ; g -> AddControlEdge ( g -> source_node ( ) , feed_node , true ) ; std :: vector < const Edge * > to_remove ; for ( const Edge * e : n -> out_edges ( ) ) { if ( e -> src_output ( ) == id . second ) { to_remove . emplace_back ( e ) ; } else if ( e -> src_output ( ) == Graph :: kControlSlot && ( n -> type_string ( ) == " " || n -> type_string ( ) == " " ) ) { to_remove . emplace_back ( e ) ; } } for ( const Edge * e : to_remove ) { if ( e -> src_output ( ) == id . second ) { g -> AddEdge ( feed_node , 0 , e -> dst ( ) , e -> dst_input ( ) ) ; } else { CHECK_EQ ( Graph :: kControlSlot , e -> src_output ( ) ) ; g -> AddControlEdge ( feed_node , e -> dst ( ) , true ) ; } g -> RemoveEdge ( e ) ; } out_feed_types -> push_back ( BaseType ( n -> output_type ( id . second ) ) ) ; } return Status :: OK ( ) ; }
Rewrite graph by replacing the output tensors specified in
"fed_outputs" with special feed nodes for each specified output
tensor, and removing any nodes that are now disconnected from the
part of the graph that reaches the sink node.
Rewrite graph by replacing the output tensors specified in " fed_outputs " with special feed nodes for each specified output tensor and removing any nodes that are now disconnected from the part of the graph that reaches the sink node .
// Update name_index // Duplicate control edges aren't allowed, but feed_node was *just* created // so there's no need to check for a duplicate. // Look through edges coming out of "n" for edges whose src_output() index // matches "output_index".  If found, replace the edges with a connection // from the special feed node. // When feeding a Placeholder node, any outgoing control edges // will be replaced with a control edge from the replacement // feed_node. // TODO(josh11b,mrry): Come up with a more elegant way of addressing // the general version of this problem. // Duplicate control edges aren't allowed, but feed_node was *just* // created so there's no need to check for a duplicate.