1/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.
2
3Licensed under the Apache License, Version 2.0 (the "License");
4you may not use this file except in compliance with the License.
5You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9Unless required by applicable law or agreed to in writing, software
10distributed under the License is distributed on an "AS IS" BASIS,
11WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12See the License for the specific language governing permissions and
13limitations under the License.
14==============================================================================*/
15
16#ifndef TENSORFLOW_CORE_FRAMEWORK_GRAPH_DEF_UTIL_H_
17#define TENSORFLOW_CORE_FRAMEWORK_GRAPH_DEF_UTIL_H_
18
19#include <set>
20
21#include "tensorflow/core/framework/op.h"
22#include "tensorflow/core/lib/core/status.h"
23
24namespace tensorflow {
25
26// Forward declare proto so that it's symbols can be removed from .so exports
27class GraphDef;
28class NodeDef;
29
30// Produce a human-readable version of a GraphDef that is more concise
31// than a text-format proto.
32string SummarizeGraphDef(const GraphDef& graph_def);
33
34// Validates the syntax of a GraphDef provided externally.
35//
36// The following is an EBNF-style syntax for GraphDef objects. Note that
37// Node objects are actually specified as tensorflow::NodeDef protocol buffers,
38// which contain many other fields that are not (currently) validated.
39//
40// Graph = Node *
41// Node = NodeName, Inputs
42// Inputs = ( DataInput * ), ( ControlInput * )
43// DataInput = NodeName, ( ":", [1-9], [0-9] * ) ?
44// ControlInput = "^", NodeName
45// NodeName = [A-Za-z0-9.], [A-Za-z0-9_./] *
46Status ValidateExternalGraphDefSyntax(const GraphDef& graph_def);
47
48// Adds default attributes to NodeDefs in 'graph_def' starting
49// from the 'node_offset' node in 'graph_def'.
50//
51// Default attributes are defined by 'op_registry'.
52//
53// Returns OK on success, an error if 'graph_def' has a NodeDef
54// that cannot be found in 'op_registry'.
55//
56// REQUIRES: 'graph_def' and 'op_registry' are not nullptr.
57Status AddDefaultAttrsToGraphDef(GraphDef* graph_def,
58 const OpRegistryInterface& op_registry,
59 int node_offset);
60
61// Same as above, except for the fact that it skips nodes that aren't found in
62// op_registry if skip_unknown_ops is true.
63Status AddDefaultAttrsToGraphDef(GraphDef* graph_def,
64 const OpRegistryInterface& op_registry,
65 int node_offset, bool skip_unknown_ops);
66
67// Remove attrs from 'graph_def' that have the default value according
68// to 'producer_op_registry', but don't exist according to
69// 'consumer_op_registry'. This can allow 'graph_def' to run on the
70// consumer even if consumer was built at an earlier CL (before an
71// attr with a default was added). Note that this will not affect
72// attrs with non-default values, so you must run a
73// ValidateGraphDef...() function to see if the result is in fact
74// compatible. If not nullptr, the op/attr pairs that were removed
75// are added to '*op_attr_removed'.
76//
77// Expected usage, for a producer that wants to prepare a graph for
78// a consumer:
79// // For each consumer, update 'graph_def':
80// OpListOpRegistry consumer_op_registry(consumer_server_op_list);
81// std::unordered_set<std::pair<string, string>> op_attr_removed;
82// TF_RETURN_IF_ERROR(RemoveNewDefaultAttrsFromGraphDef(
83// &graph_def, consumer_op_registry, *OpRegistry::Global(),
84// &op_attr_removed));
85// // Validate that each consumer can understand the resulting 'graph_def'
86// TF_RETURN_IF_ERROR(graph::ValidateGraphDefAgainstOpRegistry(
87// graph_def, consumer_op_registry));
88// // Consumer can use 'graph_def', and 'op_attr_removed' summarizes
89// // what changes had to be made to 'graph_def' for it to work.
90//
91// Expected usage, for a consumer that has a graph and a
92// (optionally-stripped) op_list from a producer (say from a call to
93// StrippedOpListForGraph(), or in the MetaGraphDef):
94// OpListOpRegistry producer_op_registry(producer_stripped_op_list);
95// TF_RETURN_IF_ERROR(RemoveNewDefaultAttrsFromGraphDef(
96// &graph_def, *OpRegistry::Global(), producer_op_registry, nullptr));
97Status RemoveNewDefaultAttrsFromGraphDef(
98 GraphDef* graph_def, const OpRegistryInterface& consumer_op_registry,
99 const OpRegistryInterface& producer_op_registry,
100 std::set<std::pair<string, string>>* op_attr_removed);
101
102// Goes over the `nodes` and removes attributes that are set to their
103// default values according to op_registry.
104// If some node's definition is not found in the `op_registry`, this node is
105// simply skipped. In most cases, these nodes would be function calls.
106// If a stricter behavior is desired, one can add FunctionLibraryDefinition
107// argument to check for functions and their attributes.
108// This is obvious from signature, but as a warning, if `nodes` contain
109// nodes calling functions, e.g. PartitionCallOp or FunctionalIf, this
110// function does not "recurse" into them.
111void StripDefaultAttributes(const OpRegistryInterface& op_registry,
112 protobuf::RepeatedPtrField<NodeDef>* nodes);
113
114// Two functions that collect the ops used by a graph.
115//
116// This returns the ops used as a set of strings.
117void OpsUsedByGraph(const GraphDef& graph_def,
118 std::set<string>* ops_used_in_graph);
119
120// This function computes the stripped_op_list field of MetaGraphDef
121// and similar protos. The op_registry should contain the ops used to
122// produce graph_def. The resulting stripped_op_list can be
123// communicated from the producer to the consumer, which can use
124// RemoveNewDefaultAttrsFromGraphDef() to improve forwards compatibility
125// (using an OpListOpRegistry as indicated in the example above).
126//
127// Most users will pass *OpRegistry::Global() for op_registry to strip against
128// the list of ops registered in this process.
129Status StrippedOpListForGraph(const GraphDef& graph_def,
130 const OpRegistryInterface& op_registry,
131 OpList* stripped_op_list);
132
133} // namespace tensorflow
134
135#endif // TENSORFLOW_CORE_FRAMEWORK_GRAPH_DEF_UTIL_H_
136