• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7     http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 #ifndef TENSORFLOW_LITE_TOCO_MODEL_H_
16 #define TENSORFLOW_LITE_TOCO_MODEL_H_
17 
18 #include <complex>
19 #include <functional>
20 #include <initializer_list>
21 #include <memory>
22 #include <string>
23 #include <unordered_map>
24 #include <vector>
25 
26 #include "absl/types/optional.h"
27 #include "tensorflow/core/platform/logging.h"
28 #include "tensorflow/lite/toco/model_flags.pb.h"
29 #include "tensorflow/lite/toco/runtime/types.h"
30 #include "tensorflow/lite/toco/toco_port.h"
31 #include "tensorflow/lite/toco/toco_types.h"
32 
33 namespace toco {
34 
35 using tflite::QuantizationParams;
36 
37 enum class OperatorType : uint8 {
38   kNone,
39   // General-purpose neural network operators.
40   kAdd,
41   kAddN,
42   kAveragePool,
43   kBatchMatMul,
44   kBatchNormalization,
45   kCeil,
46   kConv,
47   kConcatenation,
48   kCos,
49   kDepthwiseConv,
50   kDepthToSpace,
51   kSpaceToDepth,
52   kDequantize,
53   kDiv,
54   kExp,
55   kExpandDims,
56   kFill,
57   kFloorDiv,
58   kFloorMod,
59   kFullyConnected,
60   kL2Normalization,
61   kL2Pool,
62   kLstmCell,
63   kUnidirectionalSequenceLstm,
64   kLocalResponseNormalization,
65   kLog,
66   kLogistic,
67   kMaxPool,
68   kFakeQuant,
69   kMul,
70   kOneHot,
71   kRandomUniform,
72   kRange,
73   kRank,
74   kRelu,
75   kRelu1,
76   kRelu6,
77   kPRelu,
78   kSoftmax,
79   kLogSoftmax,
80   kSub,
81   kTanh,
82   kTransposeConv,
83   kCast,
84   kFloor,
85   kGather,
86   kResizeBilinear,
87   kSin,
88   kSpaceToBatchND,
89   kPack,
90   kBatchToSpaceND,
91   kPad,
92   kPadV2,
93   kReduceProd,  // Reduction product
94   kStridedSlice,
95   kSlice,
96   kSqueeze,
97   kMean,
98   kArgMax,
99   // The SVDF Op is a decomposition of a densely connected Op into
100   // low rank filters. For details:
101   // https://research.google.com/pubs/pub43813.html
102   kSvdf,
103   // Special operators used for importing TensorFlow nodes.
104   // The general intent is to have some graph transformation either
105   // drop them or rewrite them as general-purpose operators.
106   kAll,
107   kAssert,
108   kConcat,
109   kConcatV2,
110   kGreater,
111   kGreaterEqual,
112   kIdentity,
113   kLess,
114   kLessEqual,
115   kReduceMax,  //  Reduction Max
116   kMaximum,    //  Element-wise Maximum
117   kReduceMin,  //  Reduction Min
118   kMinimum,    //  Element-wise Minimum
119   kMatMul,
120   kMerge,
121   kNeg,
122   kReshape,
123   kRsqrt,
124   kShape,
125   kSplit,
126   kSplitV,
127   kSqrt,
128   kSquare,
129   kSquaredDifference,
130   kSum,
131   kSwitch,
132   kTile,
133   kTranspose,
134   kTopK_V2,
135   kDynamicPartition,
136   kDynamicStitch,
137   // An unsupported TF operation. It's only needed to be able to represent TF
138   // graph internally and is expected to be dropped by graph transformations.
139   kUnsupported,
140   // Finally, TensorFlow uses different conventions for axes ordering,
141   // see AxesOrder, and this cannot always be resolved at the time of importing
142   // nodes, as TensorFlow parameters may be constant-expression subgraphs
143   // instead of being given as plain constant arrays. So we need to insert
144   // special nodes in the graph to shuffle axes.
145   kReorderAxes,
146   kSelect,
147   kSparseToDense,
148   kEqual,
149   kNotEqual,
150   kPow,
151   kArgMin,
152   kAny,
153   kLogicalAnd,
154   kLogicalNot,
155   kLogicalOr,
156   kCTCBeamSearchDecoder,
157   kUnpack,
158   kZerosLike,
159   kResizeNearestNeighbor,
160   kLeakyRelu,
161   kAbs,
162   kMirrorPad,
163   kUnique,
164   kUnidirectionalSequenceRnn,
165   kBidirectionalSequenceLstm,
166   kReverseV2,
167   kBidirectionalSequenceRnn,
168   kGatherNd,
169   kWhere,
170   kElu,
171   kReverseSequence
172 };
173 
174 // Helper to deal with TensorFlow arrays using a different ordering of
175 // dimensions
176 // ("axes") than our own.
177 // TODO(benoitjacob): Ultimately, we shouldn't have any "ordering" of axes,
178 // we should have associative arrays mapping symbolic axes identifiers (like
179 // "output_depth") to dimensions. We would then not need this anymore.
180 enum class AxesOrder {
181   kOneAxis,  // one-dimensional array, one unique axis.
182   kCR,       // column-major matrix storage order. Our standard.
183   kRC,       // row-major matrix storage order. TensorFlow default.
184   kOHWI,     // Our standard for conv weights
185   kHWIO,     // TensorFlow conv weights
186   k1HWO,     // Our standard for DepthwiseConv weights
187   kHWIM,     // TensorFlow DepthwiseConv weights
188   kNHWC,     // TensorFlow activations
189   kHWOI,     // TensorFlow back-prop conv weights
190 };
191 
192 // The type of the scalars in an array.
193 // Note that the type does not by itself tell whether the values in the array
194 // are non-quantized (can be accessed directly) or quantized (must be
195 // interpreted in conjunction with QuantizationParams).
196 //
197 // In practice though:
198 //   float values are never quantized
199 //   uint8 values are always quantized
200 //   int32 values are sometimes quantized (depending on whether
201 //   QuantizationParams are present).
202 //   complex values are never quantized
203 //   other types are never quantized at the moment.
204 //
205 // kNone means that we don't know the data type yet, or that we don't care
206 // because we'll be dropping the array anyway (e.g. some exotic array types
207 // may be involved only in debug-only subgraphs that we may not be interested
208 // in actually supporting).
209 enum class ArrayDataType : uint8 {
210   kNone,  // 0
211   kBool,
212   kFloat,
213   kInt8,
214   kUint8,
215   kInt16,  // 5
216   kUint16,
217   kInt32,
218   kUint32,
219   kInt64,
220   kUint64,  // 10
221   kString,
222   kComplex64,
223 };
224 
225 // Compile-time logic to map ArrayDataType to the corresponding C++ scalar type
226 template <ArrayDataType A>
227 struct DataTypeImpl {};
228 template <>
229 struct DataTypeImpl<ArrayDataType::kNone> {
230   typedef int Type;
231 };
232 template <>
233 struct DataTypeImpl<ArrayDataType::kBool> {
234   typedef bool Type;
235 };
236 template <>
237 struct DataTypeImpl<ArrayDataType::kFloat> {
238   typedef float Type;
239 };
240 template <>
241 struct DataTypeImpl<ArrayDataType::kInt8> {
242   typedef int8 Type;
243 };
244 template <>
245 struct DataTypeImpl<ArrayDataType::kUint8> {
246   typedef uint8 Type;
247 };
248 template <>
249 struct DataTypeImpl<ArrayDataType::kInt16> {
250   typedef int16 Type;
251 };
252 template <>
253 struct DataTypeImpl<ArrayDataType::kUint16> {
254   typedef uint16 Type;
255 };
256 template <>
257 struct DataTypeImpl<ArrayDataType::kInt32> {
258   typedef int32 Type;
259 };
260 template <>
261 struct DataTypeImpl<ArrayDataType::kUint32> {
262   typedef uint32 Type;
263 };
264 template <>
265 struct DataTypeImpl<ArrayDataType::kInt64> {
266   typedef int64 Type;
267 };
268 template <>
269 struct DataTypeImpl<ArrayDataType::kUint64> {
270   typedef uint64 Type;
271 };
272 template <>
273 struct DataTypeImpl<ArrayDataType::kString> {
274   typedef string Type;
275 };
276 template <>
277 struct DataTypeImpl<ArrayDataType::kComplex64> {
278   typedef std::complex<float> Type;
279 };
280 
281 template <ArrayDataType A>
282 using DataType = typename DataTypeImpl<A>::Type;
283 
284 // Base class for type-specific buffer types.
285 struct GenericBuffer {
286   // Non-default-constructible: only ArrayDataType-specific subclass
287   // objects may be constructed.
288   GenericBuffer() = delete;
289   // Non-copyable-or-movable: we should only store pointers-to-Buffer
290   // in containers, not Operators themselves, so there should be no
291   // copy or move.
292   GenericBuffer(const GenericBuffer&) = delete;
293   GenericBuffer(const GenericBuffer&&) = delete;
294 
295   // We need a virtual destructor so we can store pointers-to-Buffer
296   // in containers and have the containers call the right subclass destructor.
297   virtual ~GenericBuffer() {}
298 
299   virtual int Length() const = 0;
300 
301   const ArrayDataType type;
302 
303  protected:
304   // Constructor used by subclasses for specific ArrayDataType's.
305   explicit GenericBuffer(ArrayDataType t) : type(t) {}
306 };
307 
308 // Type-specific buffer, containing type-specific storage.
309 template <ArrayDataType A>
310 struct Buffer : GenericBuffer {
311   Buffer() : GenericBuffer(A) {}
312 
313   int Length() const override { return data.size(); }
314 
315   std::vector<DataType<A>> data;
316 };
317 
318 class Shape {
319  public:
320   // For Shape, we stick to half-way encapsulation for now:
321   // we hide the raw dims_ member, but expose it raw by accessors
322   // because from some brainstorming, it's not at all easy to
323   // anticipate which flavor of more hermetic encapsulation would
324   // actually buy us future-proof-ness without being needlessly
325   // cumbersome.
326   Shape() {}
327   Shape(std::initializer_list<int> dim_list) : dims_(dim_list) {}
328 
329   void ReplaceDims(std::initializer_list<int> dim_list) {
330     dims_ = std::vector<int>(dim_list);
331   }
332 
333   const std::vector<int>& dims() const { return dims_; }
334   std::vector<int>* mutable_dims() { return &dims_; }
335   const int dimensions_count() const { return dims_.size(); }
336 
337   // We still have that one convenience accessor to avoid
338   // the awkward double bracket issue:  shape.dims()[i].
339   int dims(int i) const {
340     // Always check for out-of-bounds accesses, even in optimized builds where
341     // standard assertions are disabled. Out-of-bounds access here is a common
342     // occurrence.
343     CHECK_GE(i, 0);
344     CHECK_GT(dims_.size(), i);
345     return dims_[i];
346   }
347 
348   bool operator==(const Shape& comp) const {
349     return (this->dims_ == comp.dims());
350   }
351 
352   bool operator!=(const Shape& comp) const { return !((*this) == comp); }
353 
354  private:
355   std::vector<int> dims_;
356 };
357 
358 // Base class for all operator classes.
359 struct Operator {
360   // Non-default-constructible: only OperatorType-specific subclass
361   // objects may be constructed.
362   Operator() = delete;
363   // Non-copyable-or-movable: we should only store pointers-to-Operator
364   // in containers, not Operators themselves, so there should be no
365   // copy or move.
366   Operator(const Operator&) = delete;
367   Operator(const Operator&&) = delete;
368 
369   // We need a virtual destructor so we can store pointers-to-Operator
370   // in containers and have the containers call the right subclass destructor.
371   virtual ~Operator() {}
372 
373   // The specific type of operator. Corresponds 1:1 to subclasses.
374   const OperatorType type;
375 
376   // The activation function that may be fused into this operator,
377   // or None if no activation function is fused.
378   FusedActivationFunctionType fused_activation_function;
379 
380   // Input arrays: either activation arrays or constant array parameters.
381   // We refer to them by their name, not by their address; the mapping of
382   // names to addresses is given by the Model, which owns both Operator's and
383   // Array's. Thus, an Operator on its own doesn't contain much information,
384   // it is meant to be used in conjunction with the Model that owns it.
385   std::vector<string> inputs;
386 
387   // Output activation arrays. Same comments as for inputs apply here too.
388   std::vector<string> outputs;
389 
390   // If true, the operator has more outputs than are listed in the 'outputs'
391   // member. These need to be resolved by some graph transformation.
392   // This flag is only here to indicate that an operator should not be
393   // discarded as unused, even if from its 'outputs' member alone it
394   // looks unused.
395   bool unresolved_outputs = false;
396 
397   // A serialized tensorflow::NodeDef string.
398   // The field is filled only when importing from TensorFlow.
399   // It's guaranteed to be filled for `TensorFlowUnsupportedOperator`.
400   // It's not guaranteed to be filled for other ops. Ops created by graph
401   // transformations won't have TensorFlow NodeDef.
402   string tensorflow_node_def;
403 
404  protected:
405   // Constructor used by subclasses for specific OperatorType's.
406   explicit Operator(OperatorType t)
407       : type(t),
408         fused_activation_function(FusedActivationFunctionType::kNone) {}
409 };
410 
411 // Padding types for Conv-like operators. This is how padding is typically
412 // specified in model files. But for inference, we will need to resolve this
413 // to a FixedPadding, see below.
414 enum class PaddingType { kNone, kSame, kValid };
415 
416 // Padding as resolved for a specific layer shape, as needed for inference.
417 // For a given layer shape, a given padding type will resolve to a choice of
418 // a number of padding rows and columns, which we call the padding height and
419 // width respectively.
420 struct FixedPadding {
421   int width = 0;
422   int height = 0;
423 };
424 
425 // "Universal" padding struct containing both a generic PaddingType (as
426 // represented in a model file), and a FixedPadding (as needed for inference).
427 // The latter is resolved during the PropagateFixedSizes pass.
428 struct Padding {
429   FixedPadding& GetOrCreateFixedPadding() {
430     if (!fixed) {
431       FixedPadding* ptr = new FixedPadding;
432       fixed = std::unique_ptr<FixedPadding>(ptr);
433     }
434     return *fixed;
435   }
436 
437   Padding() : type(PaddingType::kNone) {}
438   PaddingType type;
439   std::unique_ptr<FixedPadding> fixed;
440 };
441 
442 // "Convolutional" layer, as represented in model files.
443 //
444 // Inputs:
445 //   inputs[0]: required: the input activations array
446 //   inputs[1]: required: the Conv weights
447 //   inputs[2]: optional: the bias vector, specifying the biases for each output
448 //   channel.
449 //
450 // Outputs:
451 //   outputs[0]: required: the output activations array
452 //   outputs[1]: optional: the intermediate array of im2col-replicated input
453 //                         activations. Present when targeting implementations
454 //                         of Conv layers as Im2col+GEMM.
455 //
456 // TensorFlow equivalent: Conv2D
457 struct ConvOperator : Operator {
458   ConvOperator() : Operator(OperatorType::kConv) {}
459   Padding padding;
460   int stride_width = 0;
461   int stride_height = 0;
462   // A dilation_rate of 0 is invalid and this field is an optional attribute.
463   // Thus initializing it to 1 to allow default conv behavior when the
464   // attribute is not present.
465   int dilation_width_factor = 1;
466   int dilation_height_factor = 1;
467 };
468 
469 // CTCBeamSearchDecoder operator:
470 //
471 // Inputs:
472 //   inputs[0]: required: the logits.
473 //   inputs[1]: required: sequence length.
474 //   inputs[2]: optional: beam width.
475 //   inputs[3]: optional: top paths.
476 //   inputs[4]: optional: merge repeated.
477 //
478 //  Outputs:
479 //    outputs[0]: deocoded.
480 //    outputs[1]: log probability.
481 //
482 // TensorFlow equivalent: CTCBeamSearchDecoder
483 struct CTCBeamSearchDecoderOperator : Operator {
484   CTCBeamSearchDecoderOperator()
485       : Operator(OperatorType::kCTCBeamSearchDecoder) {}
486   int beam_width;
487   int top_paths;
488   bool merge_repeated = true;
489 };
490 
491 // Depthwise-separable convolution operator.
492 //
493 // Inputs:
494 //   inputs[0]: required: the input activations array
495 //   inputs[1]: required: the DepthwiseConv weights
496 //   inputs[2]: optional: the bias vector, specifying the biases for each output
497 //   channel.
498 //
499 // TensorFlow equivalent: DepthwiseConv2dNative
500 struct DepthwiseConvOperator : Operator {
501   DepthwiseConvOperator() : Operator(OperatorType::kDepthwiseConv) {}
502   Padding padding;
503   int stride_height = 0;
504   int stride_width = 0;
505   int depth_multiplier = 0;
506   // A dilation_rate of 0 is invalid and this field is an optional attribute.
507   // Thus initializing it to 1 to allow default conv behavior when the
508   // attribute is not present.
509   int dilation_width_factor = 1;
510   int dilation_height_factor = 1;
511 };
512 
513 // Depth-to-space transform operator.
514 //
515 // Inputs:
516 //   inputs[0]: required: the input activations array
517 //
518 // TensorFlow equivalent: DepthToSpace
519 struct DepthToSpaceOperator : Operator {
520   DepthToSpaceOperator() : Operator(OperatorType::kDepthToSpace) {}
521   int block_size = 0;
522 };
523 
524 // Space-to-depth transform operator.
525 //
526 // Inputs:
527 //   inputs[0]: required: the input activations array
528 //
529 // TensorFlow equivalent: SpaceToDepth
530 struct SpaceToDepthOperator : Operator {
531   SpaceToDepthOperator() : Operator(OperatorType::kSpaceToDepth) {}
532   int block_size = 0;
533 };
534 
535 // Fully-connected operator.
536 //
537 // Inputs:
538 //   inputs[0]: required: the input activations array
539 //   inputs[1]: required: the FullyConnected weights
540 //   inputs[2]: optional: the bias vector, specifying the biases for each output
541 //   channel.
542 //
543 // TensorFlow equivalent: a pair consisting of a Reshape node reshaping the
544 // input activations as a matrix, followed by a MatMul node.
545 struct FullyConnectedOperator : Operator {
546   FullyConnectedOperator() : Operator(OperatorType::kFullyConnected) {}
547   FullyConnectedWeightsFormat weights_format =
548       FullyConnectedWeightsFormat::kDefault;
549 };
550 
551 // Dequantization operator, converting a quantized array of integers with
552 // quantization parameters specifying how these integers correspond to real
553 // numbers
554 // (see QuantizationParams) to an output activations array of floating-point
555 // values.
556 //
557 // In floating-point image models, there is typically a Dequantization operator
558 // at the very beginning, converting the input image RGB data, consisting of
559 // uint8 integer values, to floating-point input activations. That is where
560 // image model parameters such as "mean_value" and "std_value" are typically
561 // handled.
562 //
563 // This is the only operator type that converts from quantized to
564 // floating-point,
565 // and there is at the moment no operator type at all to convert from
566 // floating-point
567 // to quantized. Every other operator does either float->float or
568 // quantized->quantized.
569 //
570 // Inputs:
571 //   inputs[0]: required: the input quantized activations array
572 //
573 // TensorFlow equivalent: Dequantize
574 struct DequantizeOperator : Operator {
575   DequantizeOperator() : Operator(OperatorType::kDequantize) {}
576 };
577 
578 // Batch-normalization operator.
579 //
580 // We only support batch-normalization using pre-learned moments, so this is
581 // just
582 // computing (input - mean) * multiplier + offset. As such, this can be
583 // expressed as a combination of Add and Mul nodes, and indeed this is how
584 // we break it down during tooling for the purpose of fusing it into
585 // other operators.
586 //
587 // Inputs:
588 //   inputs[0]: required: the input activations array
589 //   inputs[1]: required: the learned mean array
590 //   inputs[2]: required: the learned multiplier array
591 //   inputs[3]: required: the learned offset array
592 //
593 // TensorFlow equivalent: a combination of Add and Mul nodes
594 struct BatchNormalizationOperator : Operator {
595   BatchNormalizationOperator()
596       : Operator(OperatorType::kBatchNormalization),
597         global_normalization(false) {}
598   bool global_normalization;
599 };
600 
601 // L2-normalization operator.
602 //
603 // Inputs:
604 //   inputs[0]: required: the input activations array
605 //
606 // TensorFlow equivalent: none. In TensorFlow, L2 normalization is implemented
607 // by a sub-graph of operators implementing L2-normalization
608 // from lower-level arithmetic nodes; during tooling, we identify such
609 // sub-graphs
610 // and replace them by L2NormalizationOperator's. See IdentifyL2Normalization.
611 struct L2NormalizationOperator : Operator {
612   L2NormalizationOperator() : Operator(OperatorType::kL2Normalization) {}
613 };
614 
615 // LSTM Cell operator.
616 //
617 // Inputs:
618 //   inputs[0]: required: the input data array
619 //   inputs[1]: required: the previous output activations array
620 //   inputs[2]: required: the learned weights array
621 //   inputs[3]: required: the learned biases array
622 //   inputs[4]: required: the previous output state
623 //   outputs[0]: required: the output activations array
624 //   outputs[1]: required: the new state array
625 //
626 // TensorFlow equivalent: none. In TensorFlow, an LSTM is implemented
627 // with a sub-graph of lower-level arithmetic nodes; during tooling, we identify
628 // such sub-graphs and replace them with LstmCells. See IdentifyLstmCell().
629 struct LstmCellOperator : Operator {
630   enum Inputs {
631     DATA_INPUT = 0,
632     PREV_ACTIV_INPUT = 1,
633     WEIGHTS_INPUT = 2,
634     BIASES_INPUT = 3,
635     PREV_STATE_INPUT = 4,
636     NUM_INPUTS = 5
637   };
638   enum Outputs {
639     ACTIV_OUTPUT = 0,
640     STATE_OUTPUT = 1,
641     CONCAT_TEMP = 2,
642     ACTIV_TEMP = 3,
643     NUM_OUTPUTS = 4
644   };
645   enum KernelType {
646     KERNEL_BASIC = 0,
647     KERNEL_FULL = 1,
648   };
649 
650   LstmCellOperator()
651       : Operator(OperatorType::kLstmCell), kernel_type(KERNEL_BASIC) {}
652 
653   KernelType kernel_type;
654 };
655 
656 struct UnidirectionalSequenceLstmOperator : Operator {
657   UnidirectionalSequenceLstmOperator()
658       : Operator(OperatorType::kUnidirectionalSequenceLstm) {}
659 };
660 
661 struct BidirectionalSequenceLstmOperator : Operator {
662   BidirectionalSequenceLstmOperator()
663       : Operator(OperatorType::kBidirectionalSequenceLstm) {}
664   bool merge_outputs;
665 };
666 
667 struct BidirectionalSequenceRnnOperator : Operator {
668   BidirectionalSequenceRnnOperator()
669       : Operator(OperatorType::kBidirectionalSequenceRnn) {}
670   bool merge_outputs;
671 };
672 
673 // Element-wise multiplication operator.
674 //
675 // Inputs:
676 //   inputs[0]: required: the left-hand side array
677 //   inputs[1]: required: the right-hand side array
678 //
679 // TensorFlow equivalent: Mul
680 struct MulOperator : Operator {
681   MulOperator() : Operator(OperatorType::kMul) {}
682 };
683 
684 // Element-wise Abs operator:
685 //   x -> abs(x)
686 //
687 // Inputs:
688 //   inputs[0]: required: the input array
689 //
690 // TensorFlow equivalent: Relu
691 struct AbsOperator : Operator {
692   AbsOperator() : Operator(OperatorType::kAbs) {}
693 };
694 
695 // Elu
696 //   f(x) -> exp(x) - 1 for x < 0, x for x >= 0.
697 //
698 // Inputs:
699 //   inputs[0]: required: the input array
700 //
701 // TensorFlow equivalent: Elu
702 struct EluOperator : Operator {
703   EluOperator() : Operator(OperatorType::kElu) {}
704 };
705 
706 // Element-wise Relu operator:
707 //   x -> max(0, x)
708 //
709 // Inputs:
710 //   inputs[0]: required: the input array
711 //
712 // TensorFlow equivalent: Relu
713 struct ReluOperator : Operator {
714   ReluOperator() : Operator(OperatorType::kRelu) {}
715 };
716 
717 // Element-wise Relu1 operator:
718 //   x -> min(max(x, -1), 1)
719 //
720 // Inputs:
721 //   inputs[0]: required: the input array
722 //
723 // TensorFlow equivalent: none. We can construct the operator with Minimum
724 // and Maximum operations
725 struct Relu1Operator : Operator {
726   Relu1Operator() : Operator(OperatorType::kRelu1) {}
727 };
728 
729 // Element-wise Relu6 operator:
730 //   x -> max(0, min(6, x))
731 //
732 // Inputs:
733 //   inputs[0]: required: the input array
734 //
735 // TensorFlow equivalent: Relu6
736 struct Relu6Operator : Operator {
737   Relu6Operator() : Operator(OperatorType::kRelu6) {}
738 };
739 
740 // PRelu
741 //   f(x) = alpha * x for x < 0, f(x) = x for x >= 0.
742 //
743 // Inputs:
744 //   inputs[0]: required: the input array
745 //   inputs[1]: required: the alpha array
746 //
747 // Equivalent to keras.layers.PReLU.
748 struct PReluOperator : Operator {
749   PReluOperator() : Operator(OperatorType::kPRelu) {}
750 };
751 
752 // LeakyRelu
753 //   x -> max(x, alpha * x)
754 //
755 // Inputs:
756 //   inputs[0]: required: the input array
757 //
758 // TensorFlow equivalent: LeakyRelu
759 struct LeakyReluOperator : Operator {
760   LeakyReluOperator() : Operator(OperatorType::kLeakyRelu) {}
761 
762   float alpha = 0.2f;  // 0.2 matches the default value for the TF op attribute.
763 };
764 
765 // Element-wise Logistic operator:
766 //   x -> Logistic(x) = 1 / (1 + exp(-x))
767 //
768 // Inputs:
769 //   inputs[0]: required: the input array
770 //
771 // TensorFlow equivalent: Sigmoid
772 struct LogisticOperator : Operator {
773   LogisticOperator() : Operator(OperatorType::kLogistic) {}
774 };
775 
776 // Element-wise natural log operator:
777 //   x -> ln(x)
778 //
779 // Inputs:
780 //   inputs[0]: required: the input array
781 //
782 // TensorFlow equivalent: Log
783 struct LogOperator : Operator {
784   LogOperator() : Operator(OperatorType::kLog) {}
785 };
786 
787 // Element-wise Tanh operator:
788 //   x -> Tanh(x) = (exp(x) - exp(-x)) / (exp(x) + exp(-x))
789 //
790 // Inputs:
791 //   inputs[0]: required: the input array
792 //
793 // TensorFlow equivalent: Tanh
794 struct TanhOperator : Operator {
795   TanhOperator() : Operator(OperatorType::kTanh) {}
796 };
797 
798 // Element-wise Sin operator:
799 //   x -> Sin(x) = sin(x)
800 //
801 // Inputs:
802 //   inputs[0]: required: the input array
803 //
804 // TensorFlow equivalent: Sin
805 struct SinOperator : Operator {
806   SinOperator() : Operator(OperatorType::kSin) {}
807 };
808 
809 // Element-wise addition operator.
810 //
811 // Inputs:
812 //   inputs[0]: required: the left-hand side array
813 //   inputs[1]: required: the right-hand side array
814 //
815 // TensorFlow equivalent: Add
816 struct AddOperator : Operator {
817   AddOperator() : Operator(OperatorType::kAdd) {}
818 };
819 
820 // Element-wise addition operator for N inputs.
821 //
822 // Inputs:
823 //   inputs[i]: The i-th array to add together to form the output.
824 //
825 // TensorFlow equivalent: AddN
826 struct AddNOperator : Operator {
827   AddNOperator() : Operator(OperatorType::kAddN) {}
828 };
829 
830 // Concatenation operator: concatenates its inputs
831 // along the axis.
832 //
833 // Inputs: this operator accepts any number >= 1 of inputs.
834 //   inputs[i]: the i-th array to concatenate.
835 //
836 // TensorFlow equivalent: Concat.
837 struct ConcatenationOperator : Operator {
838   ConcatenationOperator() : Operator(OperatorType::kConcatenation) {}
839   int axis = 0;
840 };
841 
842 // Reordering dimensions. Used only during tooling to transform graphs from
843 // the TensorFlow format.
844 //
845 // Inputs:
846 //   inputs[0]: required: the input array
847 //
848 // TensorFlow equivalent: none. This is only useful to convert between formats.
849 struct ReorderAxesOperator : Operator {
850   ReorderAxesOperator() : Operator(OperatorType::kReorderAxes) {}
851   AxesOrder input_axes_order;
852   AxesOrder output_axes_order;
853 };
854 
855 // Average-pooling operator.
856 //
857 // Inputs:
858 //   inputs[0]: required: the input array
859 //
860 // TensorFlow equivalent: AveragePool
861 struct AveragePoolOperator : Operator {
862   AveragePoolOperator() : Operator(OperatorType::kAveragePool) {}
863   Padding padding;
864   int stride_height = 0;
865   int stride_width = 0;
866   int kheight = 0;
867   int kwidth = 0;
868 };
869 
870 // Local response normalization operator.
871 //
872 // Inputs:
873 //   inputs[0]: required: the input array
874 //
875 // TensorFlow equivalent: LRN
876 struct LocalResponseNormalizationOperator : Operator {
877   LocalResponseNormalizationOperator()
878       : Operator(OperatorType::kLocalResponseNormalization) {}
879 
880   int range = 0;
881   float bias = 0.f;
882   float alpha = 0.f;
883   float beta = 0.f;
884 };
885 
886 // Max-pooling operator.
887 //
888 // Inputs:
889 //   inputs[0]: required: the input array
890 //
891 // TensorFlow equivalent: MaxPool
892 struct MaxPoolOperator : Operator {
893   MaxPoolOperator() : Operator(OperatorType::kMaxPool) {}
894   Padding padding;
895   int stride_height = 0;
896   int stride_width = 0;
897   int kheight = 0;
898   int kwidth = 0;
899 };
900 
901 // L2-pooling operator.
902 //
903 // Inputs:
904 //   inputs[0]: required: the input array
905 //
906 // TensorFlow equivalent: none. Can be shimmed by squaring+avgpool+sqrt.
907 struct L2PoolOperator : Operator {
908   L2PoolOperator() : Operator(OperatorType::kL2Pool) {}
909   Padding padding;
910   int stride_height = 0;
911   int stride_width = 0;
912   int kheight = 0;
913   int kwidth = 0;
914 };
915 
916 // The expected [min, max] range of values in a given array.
917 // Used for quantization only.
918 // This information typically comes from special nodes found in quantized
919 // models, see FakeQuantOperator, and is used during quantization to resolve
920 // actual quantization parameters (see QuantizationParams).
921 struct MinMax {
922   double min = 0.;
923   double max = 0.;
924 };
925 
926 inline bool operator==(const MinMax& m1, const MinMax& m2) {
927   return m1.min == m2.min && m1.max == m2.max;
928 }
929 
930 // Fake-quantization operator. This does two things:
931 //   - Annotate its input and output arrays with MinMax information,
932 //   - Arithmetic-wise, this operator rounds incoming activation values
933 //     to the nearest representable value on the scale of 256
934 //     values from the min to the max value dictated by its MinMax info.
935 //
936 // Inputs:
937 //   inputs[0]: required: the input array
938 //   inputs[1]: optional: the 'min' value, if it has not yet been resolved
939 //              to a constant.
940 //   inputs[2]: optional: the 'max' value, if it has not yet been resolved
941 //              to a constant.
942 //
943 // TensorFlow equivalent: FakeQuantWithMinMaxVars, FakeQuantWithMinMaxArgs.
944 struct FakeQuantOperator : Operator {
945   FakeQuantOperator() : Operator(OperatorType::kFakeQuant) {}
946   std::unique_ptr<MinMax> minmax;
947   int num_bits = 8;
948   bool narrow_range = false;
949 };
950 
951 // Element-wise division operator.
952 //
953 // Inputs:
954 //   inputs[0]: required: the left-hand side array
955 //   inputs[1]: required: the right-hand side array
956 //
957 // TensorFlow equivalent: Div
958 struct DivOperator : Operator {
959   DivOperator() : Operator(OperatorType::kDiv) {}
960 };
961 
962 // Element-wise identity (x->x) operator.
963 //
964 // Inputs:
965 //   inputs[0]: required: the input array
966 //
967 // TensorFlow equivalent: Identity
968 struct TensorFlowIdentityOperator : Operator {
969   TensorFlowIdentityOperator() : Operator(OperatorType::kIdentity) {}
970 };
971 
972 // Batch matrix multiplication operator. This comes from the (deprecated)
973 // tf.batch_matmul or a tf.matmul that has rank 3. dims(0) is the batch count
974 // and it can be trivially unrolled into a series of matmuls on each element.
975 //
976 // Inputs:
977 //   inputs[0]: required: the left-hand side matrix
978 //   inputs[1]: required: the right-hand side matrix
979 //
980 // TensorFlow equivalent: MatMul
981 struct BatchMatMulOperator : Operator {
982   BatchMatMulOperator() : Operator(OperatorType::kBatchMatMul) {}
983   bool adj_x = false;
984   bool adj_y = false;
985 };
986 
987 // General matrix multiplication operator. We don't want to support general
988 // matrix multiplication at inference time, so we resolve it during tooling
989 // to more specific operator types, namely, FullyConnected.
990 //
991 // Inputs:
992 //   inputs[0]: required: the left-hand side matrix
993 //   inputs[1]: required: the right-hand side matrix
994 //
995 // TensorFlow equivalent: MatMul
996 struct TensorFlowMatMulOperator : Operator {
997   TensorFlowMatMulOperator() : Operator(OperatorType::kMatMul) {}
998   bool transpose_a = false;
999   bool transpose_b = false;
1000 };
1001 
1002 // Padding operator. Pads a tensor with zeros.
1003 //
1004 // Inputs:
1005 //   inputs[0]: required: the input array
1006 //   inputs[1]: required: the padding array
1007 //
1008 // This operation pads a `input` with zeros according to the `paddings` you
1009 // specify. `paddings` is an integer tensor with shape `[Dn, 2]`, where n is the
1010 // rank of `input`. For each dimension D of `input`, `paddings[D, 0]` indicates
1011 // how many zeros to add before the contents of `input` in that dimension, and
1012 // `paddings[D, 1]` indicates how many zeros to add after the contents of
1013 // `input` in that dimension.
1014 //
1015 // TensorFlow equivalent: Pad
1016 struct PadOperator : Operator {
1017   PadOperator() : Operator(OperatorType::kPad) {}
1018 
1019   std::vector<int> left_padding;
1020   std::vector<int> right_padding;
1021 };
1022 
1023 // PaddingV2 operator. Pads a tensor with the given constant value.
1024 //
1025 // Inputs:
1026 //   inputs[0]: required: the input array
1027 //   inputs[1]: required: the padding array
1028 //   inputs[2]: required: the scalar constant_values
1029 //
1030 // This operation pads input according to the paddings and constant_values you
1031 // specify. paddings is an integer tensor with shape [Dn, 2], where n is the
1032 // rank of input. For each dimension D of input, paddings[D, 0] indicates how
1033 // many padding values to add before the contents of input in that dimension,
1034 // and paddings[D, 1] indicates how many padding values to add after the
1035 // contents of input in that dimension. constant_values is a scalar tensor of
1036 // the same type as input that indicates the value to use for padding input.
1037 //
1038 // TensorFlow equivalent: PadV2
1039 struct PadV2Operator : Operator {
1040   PadV2Operator() : Operator(OperatorType::kPadV2) {}
1041 
1042   std::vector<int> left_padding;
1043   std::vector<int> right_padding;
1044 };
1045 
1046 // Strided slice operator.
1047 //
1048 // Inputs:
1049 //   inputs[0]: required: the input array
1050 //   inputs[1]: required: the begin array
1051 //   inputs[2]: required: the end array
1052 //   inputs[3]: optional: the strides array
1053 //
1054 // TensorFlow equivalent: StridedSlice
1055 struct StridedSliceOperator : Operator {
1056   StridedSliceOperator() : Operator(OperatorType::kStridedSlice) {}
1057 
1058   std::vector<int> start_indices;
1059   std::vector<int> stop_indices;
1060   std::vector<int> strides;
1061 
1062   int begin_mask;
1063   int ellipsis_mask;
1064   int end_mask;
1065   int new_axis_mask;
1066   int shrink_axis_mask;
1067 
1068   StridedSliceOperator(const StridedSliceOperator& other)
1069       : Operator(OperatorType::kStridedSlice) {
1070     inputs = other.inputs;
1071     outputs = other.outputs;
1072 
1073     start_indices = other.start_indices;
1074     stop_indices = other.stop_indices;
1075     strides = other.strides;
1076 
1077     begin_mask = other.begin_mask;
1078     ellipsis_mask = other.ellipsis_mask;
1079     end_mask = other.end_mask;
1080     new_axis_mask = other.new_axis_mask;
1081     shrink_axis_mask = other.shrink_axis_mask;
1082   }
1083 
1084   void PadIndices(int dim_count) {
1085     // Add indices and mask bits to fully include extra dimensions
1086     CHECK_GE(dim_count, start_indices.size());
1087     CHECK_EQ(start_indices.size(), stop_indices.size());
1088     CHECK_EQ(stop_indices.size(), strides.size());
1089 
1090     for (int i = start_indices.size(); i < dim_count; i++) {
1091       start_indices.push_back(0);
1092       stop_indices.push_back(0);
1093       strides.push_back(1);
1094       begin_mask |= 1 << i;
1095       end_mask |= 1 << i;
1096     }
1097   }
1098 
1099   void ReverseIndices() {
1100     CHECK_EQ(start_indices.size(), stop_indices.size());
1101     CHECK_EQ(stop_indices.size(), strides.size());
1102 
1103     std::reverse(start_indices.begin(), start_indices.end());
1104     std::reverse(stop_indices.begin(), stop_indices.end());
1105     std::reverse(strides.begin(), strides.end());
1106 
1107     begin_mask = toco::port::ReverseBits32(static_cast<uint32>(begin_mask)) >>
1108                  (32 - start_indices.size());
1109     ellipsis_mask =
1110         toco::port::ReverseBits32(static_cast<uint32>(ellipsis_mask)) >>
1111         (32 - start_indices.size());
1112     end_mask = toco::port::ReverseBits32(static_cast<uint32>(end_mask)) >>
1113                (32 - start_indices.size());
1114     new_axis_mask =
1115         toco::port::ReverseBits32(static_cast<uint32>(new_axis_mask)) >>
1116         (32 - start_indices.size());
1117     shrink_axis_mask =
1118         toco::port::ReverseBits32(static_cast<uint32>(shrink_axis_mask)) >>
1119         (32 - start_indices.size());
1120   }
1121 };
1122 
1123 // Reshaping operator, reshaping its input array to a two-dimensional shape
1124 // (a "matrix"). This is used in the TensorFlow format, in conjunction with
1125 // MatMul nodes, to implement fully-connected layers.
1126 //
1127 // Inputs:
1128 //   inputs[0]: required: the input array
1129 //
1130 // TensorFlow equivalent: Reshape --- except that we only support a special case
1131 // here, where the output shape is a matrix (2D) shape.
1132 struct TensorFlowReshapeOperator : Operator {
1133   TensorFlowReshapeOperator() : Operator(OperatorType::kReshape) {}
1134   std::vector<int> shape;
1135 };
1136 
1137 // Removes dimensions of size 1 from the shape of a tensor.
1138 // https://www.tensorflow.org/api_docs/python/tf/squeeze
1139 //
1140 // Inputs:
1141 //   inputs[0]: required: the input array
1142 //
1143 // TensorFlow equivalent: Squeeze
1144 struct SqueezeOperator : Operator {
1145   SqueezeOperator() : Operator(OperatorType::kSqueeze) {}
1146 
1147   std::vector<int> squeeze_dims;
1148 };
1149 
1150 // Inputs:
1151 //   inputs[0]: required: the output shape
1152 //   inputs[1]: required: the weights
1153 //   inputs[2]: required: the input activations array
1154 //   NOTE: The input activations is NOT the first input.
1155 //
1156 //
1157 // Outputs:
1158 //   outputs[0]: required: the output activations array
1159 //
1160 // TensorFlow equivalent: Conv2DBackpropInput
1161 struct TransposeConvOperator : Operator {
1162   enum Inputs {
1163     OUTPUT_SHAPE = 0,
1164     WEIGHTS = 1,
1165     DATA_INPUT = 2,
1166   };
1167 
1168   TransposeConvOperator() : Operator(OperatorType::kTransposeConv) {}
1169   Padding padding;
1170   int stride_width = 0;
1171   int stride_height = 0;
1172   // Dilation is possible with transpose convolution, but Tensorflow does not
1173   // currently support it, so we omit it.
1174 };
1175 
1176 // Given a tensor input, this operation calculates element-wise exponential
1177 // (y = e^x).
1178 //
1179 // Inputs:
1180 //   inputs[0]: required: input tensor
1181 //
1182 // TensorFlow equivalent: Exp
1183 struct ExpOperator : Operator {
1184   ExpOperator() : Operator(OperatorType::kExp) {}
1185 };
1186 
1187 // Given a tensor input, this operation calculates element-wise exponential
1188 // (y = cos(x)).
1189 //
1190 // Inputs:
1191 //   inputs[0]: required: input tensor
1192 //
1193 // TensorFlow equivalent: Cos
1194 struct CosOperator : Operator {
1195   CosOperator() : Operator(OperatorType::kCos) {}
1196 };
1197 
1198 // Given a tensor input, this operation inserts a dimension of 1 at the
1199 // dimension index axis of input's shape. The dimension index axis starts at
1200 // zero; if you specify a negative number for axis it is counted backward from
1201 // the end.
1202 //
1203 // Inputs:
1204 //   inputs[0]: required: input tensor
1205 //   inputs[1]: required: 0-D (scalar). Specifies the dimension index at which
1206 //   to expand the shape of input
1207 //
1208 // TensorFlow equivalent: ExpandDims
1209 struct ExpandDimsOperator : Operator {
1210   ExpandDimsOperator() : Operator(OperatorType::kExpandDims) {}
1211 };
1212 
1213 // Ceates a tensor of shape dims and fills it with the given scalar value.
1214 // Output type will be the same as the given scalar value.
1215 //
1216 // Inputs:
1217 //   inputs[0]: required: 1-D (int32) - the shape of the output tensor
1218 //   inputs[1]: required: 0-D (scalar) - value to fill the tensor with
1219 //
1220 // TensorFlow equivalent: Fill
1221 struct FillOperator : Operator {
1222   FillOperator() : Operator(OperatorType::kFill) {}
1223 };
1224 
1225 // Element-wise floor division operator.
1226 //
1227 // Inputs:
1228 //   inputs[0]: required: the left-hand side array
1229 //   inputs[1]: required: the right-hand side array
1230 //
1231 // TensorFlow equivalent: FloorDiv
1232 struct FloorDivOperator : Operator {
1233   FloorDivOperator() : Operator(OperatorType::kFloorDiv) {}
1234 };
1235 
1236 // Element-wise floor mod operator.
1237 //
1238 // Inputs:
1239 //   inputs[0]: required: the left-hand side array
1240 //   inputs[1]: required: the right-hand side array
1241 //
1242 // TensorFlow equivalent: FloorMod
1243 struct FloorModOperator : Operator {
1244   FloorModOperator() : Operator(OperatorType::kFloorMod) {}
1245 };
1246 
1247 struct RandomUniformOperator : Operator {
1248   RandomUniformOperator() : Operator(OperatorType::kRandomUniform) {}
1249   ArrayDataType dtype = ArrayDataType::kNone;
1250   int64 seed;
1251   int64 seed2;
1252 };
1253 
1254 // Creates a sequence of numbers that begins at start and extends by increments
1255 // of delta up to but not including limit.
1256 //
1257 // The dtype of the resulting tensor is inferred from the inputs unless it is
1258 // provided explicitly.
1259 //
1260 // Inputs:
1261 //   inputs[0]: required: the start
1262 //   inputs[1]: required: the limit
1263 //   inputs[2]: required: the delta
1264 //
1265 // TensorFlow equivalent: Range
1266 struct RangeOperator : Operator {
1267   RangeOperator() : Operator(OperatorType::kRange) {}
1268   ArrayDataType dtype = ArrayDataType::kNone;
1269 };
1270 
1271 // Rank operator. Extracts the rank of the tensor.
1272 //
1273 // Inputs:
1274 //   inputs[0]: required: the input array
1275 //
1276 // This operation outputs a 0-D int32 Tensor representing the rank of input.
1277 //
1278 // TensorFlow equivalent: Rank.
1279 struct TensorFlowRankOperator : Operator {
1280   TensorFlowRankOperator() : Operator(OperatorType::kRank) {}
1281   ArrayDataType output_data_type = ArrayDataType::kInt32;
1282 };
1283 
1284 // Element-wise negation (-x) operator.
1285 //
1286 // Inputs:
1287 //   inputs[0]: required: the input array
1288 //
1289 // TensorFlow equivalent: Neg
1290 struct NegOperator : Operator {
1291   NegOperator() : Operator(OperatorType::kNeg) {}
1292 };
1293 
1294 // Element-wise select operator choosing elements from inputs[1] or input[2]
1295 //
1296 // Inputs:
1297 //  inputs[0]: required: boolean mask per index
1298 //  inputs[1]: required: tensor of values if true
1299 //  inputs[2]: required: tensor of values if false
1300 //
1301 //  TensorFlow equivalent: Select
1302 struct SelectOperator : Operator {
1303   SelectOperator() : Operator(OperatorType::kSelect) {}
1304 };
1305 
1306 // Element-wise reciprocal-square-root (x^-0.5) operator.
1307 //
1308 // Inputs:
1309 //   inputs[0]: required: the input array
1310 //
1311 // TensorFlow equivalent: Rsqrt
1312 struct TensorFlowRsqrtOperator : Operator {
1313   TensorFlowRsqrtOperator() : Operator(OperatorType::kRsqrt) {}
1314 };
1315 
1316 // Stacks a list of rank-R tensors into one rank-(R+1) tensor.
1317 //
1318 // Packs the list of tensors in values into a tensor with rank one higher than
1319 // each tensor in values, by packing them along the axis dimension. Given a list
1320 // of length N of tensors of shape (A, B, C);.
1321 //
1322 // Inputs: this operator accepts any number >= 1 of inputs.
1323 //   inputs[i]: the i-th array to merge.
1324 //
1325 // TensorFlow equivalent: Pack
1326 struct PackOperator : Operator {
1327   PackOperator() : Operator(OperatorType::kPack) {}
1328   int values_count;
1329   int axis = 0;
1330   ArrayDataType dtype = ArrayDataType::kNone;
1331 };
1332 
1333 // Shape operator. Extracts the shape of the tensor.
1334 //
1335 // Inputs:
1336 //   inputs[0]: required: the input array
1337 //
1338 // This operation outputs a 1-D integer tensor representing the shape of
1339 // the input.
1340 //
1341 // TensorFlow equivalent: Shape.
1342 struct TensorFlowShapeOperator : Operator {
1343   TensorFlowShapeOperator() : Operator(OperatorType::kShape) {}
1344   ArrayDataType output_data_type = ArrayDataType::kInt32;
1345 };
1346 
1347 // Element-wise square-root (x^0.5) operator.
1348 //
1349 // Inputs:
1350 //   inputs[0]: required: the input array
1351 //
1352 // TensorFlow equivalent: Sqrt
1353 struct TensorFlowSqrtOperator : Operator {
1354   TensorFlowSqrtOperator() : Operator(OperatorType::kSqrt) {}
1355 };
1356 
1357 // Element-wise square (x*x) operator.
1358 //
1359 // Inputs:
1360 //   inputs[0]: required: the input array
1361 //
1362 // TensorFlow equivalent: Square
1363 struct TensorFlowSquareOperator : Operator {
1364   TensorFlowSquareOperator() : Operator(OperatorType::kSquare) {}
1365 };
1366 
1367 // Element-wise squared difference ((x-y)*(x-y)) operator.
1368 //
1369 // Inputs:
1370 //   inputs[0]: required: the left-hand side array
1371 //   inputs[1]: required: the right-hand side array
1372 //
1373 // TensorFlow equivalent: SquaredDifference
1374 struct SquaredDifferenceOperator : Operator {
1375   SquaredDifferenceOperator() : Operator(OperatorType::kSquaredDifference) {}
1376 };
1377 
1378 // Transposes a tensor.
1379 //
1380 // By default, this operation performs a regular matrix transpose on 2-D input
1381 // tensors.
1382 //
1383 // Inputs:
1384 //   inputs[0]: required: the input array
1385 //
1386 // TensorFlow equivalent: Transpose
1387 struct TransposeOperator : Operator {
1388   TransposeOperator() : Operator(OperatorType::kTranspose) {}
1389   std::vector<int> perm;
1390 };
1391 
1392 // Element-wise subtraction operator.
1393 //
1394 // Inputs:
1395 //   inputs[0]: required: the left-hand side array
1396 //   inputs[1]: required: the right-hand side array
1397 //
1398 // TensorFlow equivalent: Sub
1399 struct SubOperator : Operator {
1400   SubOperator() : Operator(OperatorType::kSub) {}
1401 };
1402 
1403 // Sum reduction: computes the sum of all of entries across the axes.
1404 //
1405 // Inputs:
1406 //   inputs[0]: required: the input array
1407 //
1408 // TensorFlow equivalent: Sum
1409 struct TensorFlowSumOperator : Operator {
1410   TensorFlowSumOperator() : Operator(OperatorType::kSum) {}
1411   std::vector<int> axis;
1412   bool keep_dims = false;
1413 };
1414 
1415 // Prod reduction: computes the product of all of entries across the axes.
1416 //
1417 // Inputs:
1418 //   inputs[0]: required: the input array
1419 //
1420 // TensorFlow equivalent: Prod
1421 struct TensorFlowProdOperator : Operator {
1422   TensorFlowProdOperator() : Operator(OperatorType::kReduceProd) {}
1423   std::vector<int> axis;
1424   bool keep_dims = false;
1425 };
1426 
1427 // TensorFlow Tile equivalent. Refer to TensorFlow documentation for details.
1428 //
1429 // Inputs:
1430 //   inputs[0]: required: the input array
1431 //   inputs[1]: required: int array with length of rank(input[0])
1432 struct TensorFlowTileOperator : Operator {
1433   TensorFlowTileOperator() : Operator(OperatorType::kTile) {}
1434 };
1435 
1436 // TensorFlow Slice equivalent. Refer to TensorFlow documentation for details.
1437 struct SliceOperator : Operator {
1438   SliceOperator() : Operator(OperatorType::kSlice) {}
1439 
1440   std::vector<int> begin;
1441   std::vector<int> size;
1442 };
1443 
1444 // TensorFlow Split equivalent. Refer to TensorFlow documentation for details.
1445 // Not fully supported, just a placeholder to handle TensorFlow graphs and
1446 // support graph transformations to other operator types by matching sub-graphs.
1447 struct TensorFlowSplitOperator : Operator {
1448   TensorFlowSplitOperator() : Operator(OperatorType::kSplit) {}
1449   int num_split = 0;
1450 };
1451 
1452 // TensorFlow SplitV equivalent. Refer to TensorFlow documentation for details.
1453 struct TensorFlowSplitVOperator : Operator {
1454   TensorFlowSplitVOperator() : Operator(OperatorType::kSplitV) {}
1455   int num_split = 0;
1456 };
1457 
1458 // TensorFlow Concat equivalent. Refer to TensorFlow documentation for details.
1459 // Not fully supported, just a placeholder to handle TensorFlow graphs and
1460 // support graph transformations to other operator types by matching sub-graphs.
1461 // Concretely, once the concat dim becomes known, if it is the depth
1462 // dimension then we can change this op into a DepthConcatenation op.
1463 // Otherwise, we hope for some other graph transformation to drop this node.
1464 struct TensorFlowConcatOperator : Operator {
1465   TensorFlowConcatOperator() : Operator(OperatorType::kConcat) {}
1466 };
1467 
1468 // TensorFlow ConcatV2 equivalent. Refer to TensorFlow documentation for
1469 // details.
1470 // Not fully supported, just a placeholder to handle TensorFlow graphs and
1471 // support graph transformations to other operator types by matching sub-graphs.
1472 // Concretely, once the concat dim becomes known, if it is the depth
1473 // dimension then we can change this op into a DepthConcatenation op.
1474 // Otherwise, we hope for some other graph transformation to drop this node.
1475 struct TensorFlowConcatV2Operator : Operator {
1476   TensorFlowConcatV2Operator() : Operator(OperatorType::kConcatV2) {}
1477 };
1478 
1479 // TensorFlow Merge equivalent. Refer to TensorFlow documentation for details.
1480 //
1481 // Inputs: this operator accepts any number >= 1 of inputs.
1482 //   inputs[i]: the i-th array to merge.
1483 //
1484 // It is expected that graph transformations will drop all but exactly one
1485 // of the inputs, at which point the Merge node will be equivalent to an
1486 // Identity node forwarding the remaining input.
1487 //
1488 // Note: We do not currently support runtime control flow: we only support
1489 // control flow that can be resolved at tooling time (independently of input
1490 // activations).
1491 struct TensorFlowMergeOperator : Operator {
1492   TensorFlowMergeOperator() : Operator(OperatorType::kMerge) {}
1493 };
1494 
1495 // TensorFlow Switch equivalent. Refer to TensorFlow documentation for details.
1496 //
1497 // Inputs:
1498 //   inputs[0]: required: the input array
1499 //   inputs[1]: required: the boolean predicate, given as an array of size 1
1500 //     and of type kBool, will determine which output gets selected.
1501 //
1502 // Outputs: a TensorFlow Switch node always has exactly two outputs. Depending
1503 // on the boolean value that the input predicate resolves to (see note below),
1504 // one or the other of the outputs will be 'selected': the input array will be
1505 // forwarded to the 'selected output' as if by a Identity node, while the other
1506 // output will be discarded, and any graph edge connecting that discarded output
1507 // will be dropped. The rule for selecting outputs is as follows:
1508 //   outputs[0] will be selected if the input predicate resolves to 'true'.
1509 //   outputs[1] will be selected if the input predicate resolves to 'false'.
1510 //
1511 // Note: We do not currently support runtime control flow: we only support
1512 // control flow that can be resolved at tooling time (independently of input
1513 // activations).
1514 struct TensorFlowSwitchOperator : Operator {
1515   TensorFlowSwitchOperator() : Operator(OperatorType::kSwitch) {}
1516 };
1517 
1518 // TensorFlow All equivalent. Refer to TensorFlow documentation for details.
1519 // Not fully supported, just a placeholder to handle TensorFlow graphs and
1520 // support graph transformations to other operator types by matching sub-graphs.
1521 // Typically, this is only used as an input to an Assert node, so can be
1522 // removed as an unused node as we drop Assert nodes.
1523 struct TensorFlowAllOperator : Operator {
1524   TensorFlowAllOperator() : Operator(OperatorType::kAll) {}
1525 };
1526 
1527 // TensorFlow Assert equivalent. Refer to TensorFlow documentation for details.
1528 // Not fully supported, just a placeholder to handle TensorFlow graphs and
1529 // support graph transformations to other operator types by matching sub-graphs.
1530 // Typically, we just drop Assert nodes.
1531 struct TensorFlowAssertOperator : Operator {
1532   TensorFlowAssertOperator() : Operator(OperatorType::kAssert) {}
1533 };
1534 
1535 // TensorFlow Less equivalent. Refer to TensorFlow documentation for details.
1536 // Not fully supported, just a placeholder to handle TensorFlow graphs and
1537 // support graph transformations to other operator types by matching sub-graphs.
1538 // Typically, this is only used as an input to an Assert node, so can be
1539 // removed as an unused node as we drop Assert nodes.
1540 struct TensorFlowLessOperator : Operator {
1541   TensorFlowLessOperator() : Operator(OperatorType::kLess) {}
1542 };
1543 
1544 // TensorFlow LessEqual equivalent. Refer to TensorFlow documentation for
1545 // details.
1546 // Not fully supported, just a placeholder to handle TensorFlow graphs and
1547 // support graph transformations to other operator types by matching sub-graphs.
1548 // Typically, this is only used as an input to an Assert node, so can be
1549 // removed as an unused node as we drop Assert nodes.
1550 struct TensorFlowLessEqualOperator : Operator {
1551   TensorFlowLessEqualOperator() : Operator(OperatorType::kLessEqual) {}
1552 };
1553 
1554 // TensorFlow Less equivalent. Refer to TensorFlow documentation for details.
1555 // Not fully supported, just a placeholder to handle TensorFlow graphs and
1556 // support graph transformations to other operator types by matching sub-graphs.
1557 // Typically, this is only used as an input to an Assert node, so can be
1558 // removed as an unused node as we drop Assert nodes.
1559 struct TensorFlowGreaterOperator : Operator {
1560   TensorFlowGreaterOperator() : Operator(OperatorType::kGreater) {}
1561 };
1562 
1563 // TensorFlow GreaterEqual equivalent. Refer to TensorFlow documentation for
1564 // details.
1565 // Not fully supported, just a placeholder to handle TensorFlow graphs and
1566 // support graph transformations to other operator types by matching sub-graphs.
1567 // Typically, this is only used as an input to an Assert node, so can be
1568 // removed as an unused node as we drop Assert nodes.
1569 struct TensorFlowGreaterEqualOperator : Operator {
1570   TensorFlowGreaterEqualOperator() : Operator(OperatorType::kGreaterEqual) {}
1571 };
1572 
1573 // TensorFlow Equal equivalent. Refer to TensorFlow documentation for
1574 // details.
1575 // Not fully supported, just a placeholder to handle TensorFlow graphs and
1576 // support graph transformations to other operator types by matching sub-graphs.
1577 // Typically, this is only used as an input to an Assert node, so can be
1578 // removed as an unused node as we drop Assert nodes.
1579 struct TensorFlowEqualOperator : Operator {
1580   TensorFlowEqualOperator() : Operator(OperatorType::kEqual) {}
1581 };
1582 
1583 // TensorFlow Not Equal equivalent. Refer to TensorFlow documentation for
1584 // details.
1585 struct TensorFlowNotEqualOperator : Operator {
1586   TensorFlowNotEqualOperator() : Operator(OperatorType::kNotEqual) {}
1587 };
1588 
1589 // Max reduction: computes the max of all of entries across the axes.
1590 //
1591 // Inputs:
1592 //   inputs[0]: required: the input array
1593 //
1594 // TensorFlow equivalent: Max
1595 struct TensorFlowMaxOperator : Operator {
1596   TensorFlowMaxOperator() : Operator(OperatorType::kReduceMax) {}
1597   std::vector<int> axis;
1598   bool keep_dims = false;
1599 };
1600 
1601 // Min reduction: computes the min of all of entries across the axes.
1602 //
1603 // Inputs:
1604 //   inputs[0]: required: the input array
1605 //
1606 // TensorFlow equivalent: Min
1607 struct TensorFlowMinOperator : Operator {
1608   TensorFlowMinOperator() : Operator(OperatorType::kReduceMin) {}
1609   std::vector<int> axis;
1610   bool keep_dims = false;
1611 };
1612 
1613 // Element-wise maximum operator. Currently it only supports scalar as
1614 // the second operand.
1615 //
1616 // Inputs:
1617 //   inputs[0]: required: the left-hand side array
1618 //   inputs[1]: required: the right-hand side array
1619 //
1620 // TensorFlow equivalent: Maximum
1621 struct TensorFlowMaximumOperator : Operator {
1622   TensorFlowMaximumOperator() : Operator(OperatorType::kMaximum) {}
1623 };
1624 
1625 // Element-wise minimum operator. Currently it only supports scalar as
1626 // the second operand.
1627 //
1628 // Inputs:
1629 //   inputs[0]: required: the left-hand side array
1630 //   inputs[1]: required: the right-hand side array
1631 //
1632 // TensorFlow equivalent: Minimum
1633 struct TensorFlowMinimumOperator : Operator {
1634   TensorFlowMinimumOperator() : Operator(OperatorType::kMinimum) {}
1635 };
1636 
1637 // General TF operation, unsupported by tf.mini. Expected to be dropped by
1638 // graph transformations.
1639 struct TensorFlowUnsupportedOperator : Operator {
1640   TensorFlowUnsupportedOperator() : Operator(OperatorType::kUnsupported) {}
1641 
1642   // The original TF operation type. Used for diagnostic purposes.
1643   string tensorflow_op;
1644   // A boolean indicating if the unsupported op should be treated as quantized.
1645   bool quantized = false;
1646   // A boolean indicating if the unsupported op output should allow float values
1647   // in quantized mode.
1648   bool support_output_type_float_in_quantized_op = false;
1649   // Output data types
1650   std::vector<ArrayDataType> output_data_types;
1651   // Output shapes.
1652   std::vector<Shape> output_shapes;
1653 };
1654 
1655 // Softmax activation function.
1656 //
1657 // Inputs:
1658 //   inputs[0]: required: the input array
1659 //
1660 // TensorFlow equivalent: Softmax
1661 struct SoftmaxOperator : Operator {
1662   SoftmaxOperator() : Operator(OperatorType::kSoftmax) {}
1663   float beta = 0.f;
1664 };
1665 
1666 // LogSoftmax activation function.
1667 //
1668 // Inputs:
1669 //   inputs[0]: required: the logits input array
1670 //
1671 // TensorFlow equivalent: LogSoftmax
1672 struct LogSoftmaxOperator : Operator {
1673   LogSoftmaxOperator() : Operator(OperatorType::kLogSoftmax) {}
1674 
1675   // LogSoftmax can in principal have very large negative output, depending on
1676   // the input size.  However, input x_i that is less than x_max-10 is
1677   // accumulated as exp(x_i-x_max), which is truncated to zero.
1678   //
1679   // Since we effectively disregard smallish inputs in the normalizing factor,
1680   // we also drop them in the output (set to minimum output), and in doing so
1681   // make better use of the quantization range / resolution.
1682   static constexpr float kOutputRangeMin = -16.0;
1683 };
1684 
1685 // Cast operator.
1686 //
1687 // Inputs:
1688 //   inputs[0]: required: the input array
1689 //
1690 // TensorFlow equivalent: Cast
1691 struct CastOperator : Operator {
1692   CastOperator() : Operator(OperatorType::kCast) {}
1693   ArrayDataType src_data_type = ArrayDataType::kNone;
1694   ArrayDataType dst_data_type = ArrayDataType::kNone;
1695 };
1696 
1697 // Floor operator.
1698 //
1699 // Inputs:
1700 //   inputs[0]: required: the input array
1701 //
1702 // TensorFlow equivalent: Floor
1703 struct FloorOperator : Operator {
1704   FloorOperator() : Operator(OperatorType::kFloor) {}
1705 };
1706 
1707 // Ceil operator.
1708 //
1709 // Inputs:
1710 //   inputs[0]: required: the input array
1711 //
1712 // TensorFlow equivalent: Ceil
1713 struct CeilOperator : Operator {
1714   CeilOperator() : Operator(OperatorType::kCeil) {}
1715 };
1716 
1717 // Gather operator. It gathers slices from params according to indices.
1718 // Only 1-D indices are supported at the moment.
1719 //
1720 // Inputs:
1721 //   inputs[0]: required: the params array
1722 //   inputs[1]: required: the indices to gather
1723 //   inputs[2]: optional: axis
1724 //
1725 // TensorFlow equivalent: Gather
1726 struct GatherOperator : Operator {
1727   GatherOperator() : Operator(OperatorType::kGather) {}
1728   // Axis is populated explicitly or implicitly from the axis input by
1729   // ResolveGatherAttributes. An empty axis indicates that the axis has not yet
1730   // be resolved.
1731   absl::optional<int> axis;
1732 
1733   // This field is not used by the standard TF Lite export but it is still need
1734   // for legacy Gather implementations.
1735   int input_rank = 0;
1736 };
1737 
1738 // GatherNd operator. It gathers slices from params according to indices.
1739 //
1740 // Inputs:
1741 //   inputs[0]: required: the params array
1742 //   inputs[1]: required: the indices to gather
1743 //
1744 // TensorFlow equivalent: GatherNd
1745 struct GatherNdOperator : Operator {
1746   GatherNdOperator() : Operator(OperatorType::kGatherNd) {}
1747 };
1748 
1749 // ArgMax operator. It returns the index of the maximum value along axis.
1750 //
1751 // Inputs:
1752 //   inputs[0]: required: the input tensor
1753 //   inputs[1]: optional: 0-D (scalar) axis
1754 //
1755 // TensorFlow equivalent: ArgMax
1756 struct ArgMaxOperator : Operator {
1757   ArgMaxOperator() : Operator(OperatorType::kArgMax) {}
1758   ArrayDataType output_data_type = ArrayDataType::kInt64;
1759 };
1760 
1761 // ArgMin operator. It returns the index of the minimum value along axis.
1762 //
1763 // Inputs:
1764 //   inputs[0]: required: the input tensor
1765 //   inputs[1]: optional: 0-D (scalar) axis
1766 //
1767 // TensorFlow equivalent: ArgMin
1768 struct ArgMinOperator : Operator {
1769   ArgMinOperator() : Operator(OperatorType::kArgMin) {}
1770   ArrayDataType output_data_type = ArrayDataType::kInt64;
1771 };
1772 
1773 // ResizeBilinear operator. It resizes input images with bilinear interpolation.
1774 // It does not support align_corners at the moment.
1775 //
1776 // Inputs:
1777 //   inputs[0]: required: the input array
1778 //   inputs[1]: required: the new image size
1779 //
1780 // TensorFlow equivalent: ResizeBilinear
1781 struct ResizeBilinearOperator : Operator {
1782   ResizeBilinearOperator() : Operator(OperatorType::kResizeBilinear) {}
1783 
1784   bool align_corners = false;
1785 };
1786 
1787 // ResizeNearestNeighborOperator operator. It resizes input images with nearest
1788 // neighbor interpolation. It does not support align_corners at the moment.
1789 //
1790 // Inputs:
1791 //   inputs[0]: required: the input array
1792 //   inputs[1]: required: the new image size
1793 //
1794 // TensorFlow equivalent: ResizeNearestNeighbor
1795 struct ResizeNearestNeighborOperator : Operator {
1796   ResizeNearestNeighborOperator()
1797       : Operator(OperatorType::kResizeNearestNeighbor) {}
1798 
1799   bool align_corners = false;
1800 };
1801 
1802 // SpaceToBatchND operator. It divides spatial dimensions into a grid of
1803 // blocks and interleaves these blocks with the batch dimension. Currently,
1804 // only 2-d blocks are supported.
1805 //
1806 // Inputs:
1807 //   inputs[0]: required: the input array
1808 //   inputs[1]: required: the block shape
1809 //   inputs[2]: required: the paddings
1810 //
1811 // TensorFlow equivalent: SpaceToBatchND
1812 struct SpaceToBatchNDOperator : Operator {
1813   SpaceToBatchNDOperator() : Operator(OperatorType::kSpaceToBatchND) {}
1814 
1815   std::vector<int> block_shape;
1816   std::vector<int> before_paddings;
1817   std::vector<int> after_paddings;
1818 };
1819 
1820 // BatchToSpaceND operator. Rearranges data from batch into blocks of
1821 // spatial data. Currently, only 2-d blocks are supported.
1822 //
1823 // Inputs:
1824 //   inputs[0]: required: the input array
1825 //   inputs[1]: required: the block shape
1826 //   inputs[2]: required: the crops
1827 //
1828 // TensorFlow equivalent: BatchToSpaceND
1829 struct BatchToSpaceNDOperator : Operator {
1830   BatchToSpaceNDOperator() : Operator(OperatorType::kBatchToSpaceND) {}
1831 
1832   std::vector<int> block_shape;
1833   std::vector<int> before_crops;
1834   std::vector<int> after_crops;
1835 };
1836 
1837 // Mean operator.
1838 //
1839 // Inputs:
1840 //   inputs[0]: required: the input array
1841 //
1842 // TensorFlow equivalent: Mean
1843 struct MeanOperator : Operator {
1844   MeanOperator() : Operator(OperatorType::kMean) {}
1845 
1846   std::vector<int> axis;
1847   bool keep_dims = false;
1848 };
1849 
1850 // Svdf operator:
1851 //
1852 // Inputs:
1853 //   inputs[0]: required: the input array
1854 //   inputs[1]: required: weights_feature
1855 //   inputs[2]: required: weights_time
1856 //   inputs[3]: optional: bias
1857 struct SvdfOperator : Operator {
1858   SvdfOperator() : Operator(OperatorType::kSvdf) {}
1859   int rank;
1860 };
1861 
1862 // TopKV2 operator.
1863 //
1864 // Inputs:
1865 //    input tensor and top_k scalar.
1866 struct TopKV2Operator : Operator {
1867   TopKV2Operator() : Operator(OperatorType::kTopK_V2) {}
1868 };
1869 
1870 // DynamicPartition operator:
1871 //
1872 // Inputs:
1873 //  inputs[0]: required: data.
1874 //  inputs[1]: required: partitions.
1875 //
1876 // TensorFlow equivalent: DynamicPartition
1877 struct DynamicPartitionOperator : Operator {
1878   DynamicPartitionOperator() : Operator(OperatorType::kDynamicPartition) {}
1879   int num_partitions;
1880 };
1881 
1882 // DynamicStitch operator:
1883 //
1884 // Inputs:
1885 //  inputs[0,N): required: indices.
1886 //  inputs[N,2N): required: data.
1887 //
1888 // TensorFlow equivalent: DynamicStitch/ParallelDynamicStitch
1889 struct DynamicStitchOperator : Operator {
1890   DynamicStitchOperator() : Operator(OperatorType::kDynamicStitch) {}
1891   int num_partitions;
1892 };
1893 
1894 // SparseToDense operator:
1895 //
1896 // Inputs:
1897 // Inputs[0]: required: sparse_indices.
1898 // Inputs[1]: required: output_shape.
1899 // Inputs[2]: required: sparse_values.
1900 //
1901 // TensorFlow equivalent: SparseToDense.
1902 struct SparseToDenseOperator : Operator {
1903   SparseToDenseOperator() : Operator(OperatorType::kSparseToDense) {}
1904   bool validate_indices;
1905 };
1906 
1907 // Pow operator:
1908 //
1909 // Inputs:
1910 // Inputs[0]: required: A tensor.
1911 // Inputs[1]: required: A tensor.
1912 //
1913 // TensorFlow equivalent: Pow.
1914 struct PowOperator : Operator {
1915   PowOperator() : Operator(OperatorType::kPow) {}
1916 };
1917 
1918 // Any operator:
1919 //
1920 // Inputs:
1921 // Inputs[0]: required: A boolean input tensor.
1922 // Inputs[1]: required: reduction_indices.
1923 //
1924 // TensorFlow equivalent: tf.reduce_any.
1925 struct TensorFlowAnyOperator : Operator {
1926   TensorFlowAnyOperator() : Operator(OperatorType::kAny) {}
1927   std::vector<int> axis;
1928   bool keep_dims = false;
1929 };
1930 
1931 // LogicalAnd operator:
1932 //
1933 // Inputs:
1934 // Inputs[0]: required: A boolean tensor.
1935 // Inputs[1]: required: A boolean tensor.
1936 //
1937 // TensorFlow equivalent: tf.logical_and.
1938 struct LogicalAndOperator : Operator {
1939   LogicalAndOperator() : Operator(OperatorType::kLogicalAnd) {}
1940 };
1941 
1942 // LogicalNot operator:
1943 //
1944 // Inputs:
1945 // Inputs[0]: required: A boolean tensor.
1946 //
1947 // TensorFlow equivalent: tf.logical_not.
1948 struct LogicalNotOperator : Operator {
1949   LogicalNotOperator() : Operator(OperatorType::kLogicalNot) {}
1950 };
1951 
1952 // OneHot operator:
1953 //
1954 // Inputs:
1955 // Inputs[0]: required: indices.
1956 // Inputs[1]: required: depth.
1957 // Inputs[2]: required: on_value.
1958 // Inputs[3]: required: off_value.
1959 //
1960 // TensorFlow equivalent: OneHot.
1961 struct OneHotOperator : Operator {
1962   enum Inputs {
1963     INDICES_INPUT = 0,
1964     DEPTH_INPUT = 1,
1965     ON_VALUE_INPUT = 2,
1966     OFF_VALUE_INPUT = 3,
1967   };
1968 
1969   OneHotOperator() : Operator(OperatorType::kOneHot) {}
1970   int axis = -1;
1971 };
1972 
1973 // LogicalOr operator:
1974 //
1975 // Inputs:
1976 // Inputs[0]: required: A Bool tensor.
1977 // Inputs[1]: required: A Bool tensor.
1978 //
1979 // TensorFlow equivalent: LogicalOr.
1980 struct LogicalOrOperator : Operator {
1981   LogicalOrOperator() : Operator(OperatorType::kLogicalOr) {}
1982 };
1983 
1984 // Unpack operator:
1985 //
1986 // Inputs:
1987 // Inputs[0]: required: A boolean input tensor.
1988 // Inputs[1]: required: reduction_indices.
1989 //
1990 // TensorFlow equivalent: tf.unstack.
1991 struct UnpackOperator : Operator {
1992   UnpackOperator() : Operator(OperatorType::kUnpack) {}
1993   int num;
1994   int axis;
1995   ArrayDataType dtype = ArrayDataType::kNone;
1996 };
1997 
1998 // ZerosLike operator:
1999 //
2000 // Inputs:
2001 // inputs[0]: required: the input array
2002 //
2003 // TensorFlow equivalent: tf.zeros_like
2004 struct TensorFlowZerosLikeOperator : Operator {
2005   TensorFlowZerosLikeOperator() : Operator(OperatorType::kZerosLike) {}
2006 };
2007 
2008 // ReverseV2 operator:
2009 //
2010 // Inputs:
2011 // Inputs[0]: required: the input array.
2012 //
2013 // TensorFlow equivalent: ReverseV2.
2014 struct ReverseV2Operator : Operator {
2015   ReverseV2Operator() : Operator(OperatorType::kReverseV2) {}
2016 };
2017 
2018 enum class MirrorPadMode { kNone, kSymmetric, kReflect };
2019 
2020 // MirrorPad Operator:
2021 //
2022 // Inputs:
2023 // Inputs[0]: required: input tensor to be padded.
2024 // Inputs[1]: required: 2 Column matrix specifying padding sizes. The number of
2025 // rows must be the same as the rank of the input.
2026 // Inputs[2]: required: REFLECT or SYMMETRIC.
2027 //
2028 // TensorFlow equivalent: MirrorPad.
2029 struct MirrorPadOperator : Operator {
2030   MirrorPadOperator() : Operator(OperatorType::kMirrorPad) {}
2031   // mode is either SYMMETRIC or REFLECT.
2032   MirrorPadMode mode;
2033 };
2034 
2035 // ReverseSequence operator:
2036 //
2037 // Inputs:
2038 // Inputs[0]: required: the input array.
2039 // Inputs[1]: required: the lengths of the elements to be reversed.
2040 //
2041 // TensorFlow equivalent: tf.reverse_sequence.
2042 struct ReverseSequenceOperator : Operator {
2043   ReverseSequenceOperator() : Operator(OperatorType::kReverseSequence) {}
2044   int seq_dim;
2045   int batch_dim = 0;
2046 };
2047 
2048 // Unique Operator:
2049 //
2050 // Inputs:
2051 //   inputs[0]: required: the input array
2052 //
2053 // TensorFlow equivalent: Unique
2054 struct UniqueOperator : Operator {
2055   UniqueOperator() : Operator(OperatorType::kUnique) {}
2056   ArrayDataType idx_out_type = ArrayDataType::kInt32;
2057 };
2058 
2059 struct UnidirectionalSequenceRnnOperator : Operator {
2060   UnidirectionalSequenceRnnOperator()
2061       : Operator(OperatorType::kUnidirectionalSequenceRnn) {}
2062   bool time_major;
2063   FusedActivationFunctionType fused_activation_function;
2064 };
2065 
2066 // Where Operator:
2067 // Return the coordinates of the true values in condition tensor in row-major
2068 // order.
2069 //
2070 // Inputs:
2071 //  inputs[0]: required: boolean condition tensor
2072 //
2073 //  TensorFlow equivalent: Where
2074 struct WhereOperator : Operator {
2075   WhereOperator() : Operator(OperatorType::kWhere) {}
2076 };
2077 
2078 // Alloc's are used for transient arrays only. An Alloc specifies which interval
2079 // of the "transient_data" workspace buffer passed to inference functions, is to
2080 // be used for the transient array at hand. The 'start' and 'end' values are
2081 // offsets from the start of the workspace buffer, expressed in bytes.
2082 struct Alloc {
2083   int64 start = 0;
2084   int64 end = 0;
2085 };
2086 
2087 inline bool operator<(const Alloc& a, const Alloc& b) {
2088   return a.start < b.start;
2089 }
2090 
2091 // Array represents an array (either a constant parameter array or an
2092 // activations array) in a Model.
2093 struct Array {
2094   template <ArrayDataType A>
2095   const Buffer<A>& GetBuffer() const {
2096     DCHECK(buffer);
2097     DCHECK(buffer->type == A);
2098     return *static_cast<const Buffer<A>*>(buffer.get());
2099   }
2100   template <ArrayDataType A>
2101   Buffer<A>& GetMutableBuffer() {
2102     if (!buffer) {
2103       Buffer<A>* ptr = new Buffer<A>;
2104       buffer = std::unique_ptr<GenericBuffer>(ptr);
2105     }
2106     DCHECK(buffer);
2107     DCHECK(buffer->type == A);
2108     return *static_cast<Buffer<A>*>(buffer.get());
2109   }
2110   Alloc& GetOrCreateAlloc() {
2111     if (!alloc) {
2112       alloc = std::unique_ptr<Alloc>(new Alloc);
2113     }
2114     return *alloc;
2115   }
2116   MinMax& GetOrCreateMinMax() {
2117     if (!minmax) {
2118       minmax = std::unique_ptr<MinMax>(new MinMax);
2119     }
2120     return *minmax;
2121   }
2122   MinMax& GetMinMax() const {
2123     DCHECK(minmax);
2124     return *minmax;
2125   }
2126   QuantizationParams& GetOrCreateQuantizationParams() {
2127     if (!quantization_params) {
2128       quantization_params =
2129           std::unique_ptr<QuantizationParams>(new QuantizationParams);
2130     }
2131     return *quantization_params;
2132   }
2133   QuantizationParams& GetQuantizationParams() const {
2134     DCHECK(quantization_params);
2135     return *quantization_params;
2136   }
2137 
2138   // The data type of the actual elements of this array, that is:
2139   //  - If there is a buffer (see 'buffer' member), it must be of the same
2140   //    type.
2141   //  - If there is no buffer, meaning that this is a runtime (i.e. activations)
2142   //    array, then this specifies the type of elements that there will be
2143   //    at runtime.
2144   //
2145   // Note that this only specifies the storage type of elements; this does
2146   // not specify whether these are to be treated as 'real' or 'quantized'
2147   // values.
2148   // That is decided by whether the 'quantization_params' member is null.
2149   ArrayDataType data_type = ArrayDataType::kNone;
2150   // The final value that data_type should have at the end of graph
2151   // transformations
2152   ArrayDataType final_data_type = ArrayDataType::kNone;
2153   // The dimensions of this array --- this specifies both sizes and strides
2154   // (the storage layout).
2155   //
2156   // Issues with shape handling that remain include:
2157   //   - No way to distinguish between 0-dimensional dims and missing dims.
2158   //   - No way to describe dims that may be runtime-variable.
2159   //   - Addressing of dims by integer index differs in different graph formats
2160   //     (TensorFlow vs. other frameworks vs. what we have informally grown
2161   //     within toco).
2162   //     This is currently quite messy; see ReorderAxesOperator which is how we
2163   //     bridge some of these discrepancies at the moment. This is overdue for
2164   //     a redesign; I'm thinking that it would be nice to have more flexible
2165   //     dims that allow mapping 1:1, cleanly, dims as they are in various
2166   //     formats,
2167   //     then explicitly convert between different conventions.
2168 
2169   // Proto-style accessors
2170   bool has_shape() const { return array_shape != nullptr; }
2171   const Shape& shape() const {
2172     CHECK(has_shape());
2173     return *array_shape;
2174   }
2175   Shape* mutable_shape() {
2176     if (!array_shape) {
2177       array_shape.reset(new Shape);
2178     }
2179     return array_shape.get();
2180   }
2181   void copy_shape(const Shape& src_shape) { *mutable_shape() = src_shape; }
2182   void clear_shape() { array_shape = nullptr; }
2183 
2184   // The constant buffer backing this array. This is non-null if and only if
2185   // this is a constant parameter array. Conversely, this is null for
2186   // activations arrays.
2187   //
2188   // Note that this buffer is pure storage. In the case of quantized values,
2189   // it only stores the quantized values, it does not know by itself about the
2190   // quantization parameters necessary to interprete these values, that is
2191   // in the separate 'quantization_params' field. In fact, this 'buffer' field
2192   // does no even know whether values are quantized. It only has a data_type,
2193   // which must equal the 'data_type' member here, and which only describes
2194   // the storage type of element, does not tell whether they are quantized i.e.
2195   // whether they are to be interpreted with quantization_params.
2196   std::unique_ptr<GenericBuffer> buffer;
2197   // Only for activation arrays (i.e. when 'buffer' is null).
2198   // Only for code generation.
2199   //
2200   // Describes the allocation of this array within the workspace buffer
2201   // allocated
2202   // for all transient arrays.
2203   std::unique_ptr<Alloc> alloc;
2204   // Describes the [min, max] range of values
2205   // to be assumed when determining quantization_params.
2206   //
2207   // Only used for quantization. In fact, only used for determining
2208   // quantization_params.
2209   //
2210   // Used for both constant arrays (those having a 'buffer') and non-constant
2211   // arrays (activations). Indeed, it is important to use the same min-max range
2212   // as was used during training, even if that min-max range is slightly wrong
2213   // w.r.t. actual buffer elements. Doing otherwise would defeat the point of
2214   // re-training for quantization.
2215   std::unique_ptr<MinMax> minmax;
2216   // Quantization parameters. The non-null-ness of this pointer is what
2217   // defines whether this array is quantized or not.
2218   //
2219   // If this is non-null, then these quantization parameters are to be used
2220   // to assign a meaning as real numbers to the elements of this array.
2221   std::unique_ptr<QuantizationParams> quantization_params;
2222   // narrow_range is a detail of how toco handles FakeQuant operators with
2223   // narrow_range, see
2224   // https://www.tensorflow.org/api_docs/python/tf/fake_quant_with_min_max_vars
2225   //
2226   // For more context about what that is useful for, see the big comment in
2227   // graph_transformations/ensure_uint8_weights_safe_for_fast_int8_kernels.cc
2228   //
2229   // The narrow_range flag applies only to quantized arrays, and changes
2230   // their quantization in the following way when it is set to 'true':
2231   // 1. The computation of {zero_point, scale} from {min, max} needs to be
2232   //    amended so that the real min value will get quantized to
2233   //    (min_quantized_value + 1) instead of just (min_quantized_value).
2234   //    E.g. for uint8 quantization, the real min value should get quantized to
2235   //    the uint8 value 1, not 0.
2236   // 2. Quantized values should get clamped to the interval
2237   //    [min_quantized_value + 1, max_value]. Equivalently, the
2238   //    min_quantized_value should get nudged to (min_quantized_value + 1).
2239   // The reason why 1. does not imply 2. is that real values may not belong to
2240   // the stated [min, max] interval. Concretely, weights recorded at the last
2241   // learning step may not fall in the [min, max] interval recorded over
2242   // previous learning steps, as the values evolve across learning steps.
2243   //
2244   // Rationale why this is directly a field on Array:
2245   // - This can't be just a field on FakeQuantOperator, because
2246   //   FakeQuantOperators are gone (DropFakeQuant) before we get to using that
2247   //   information (Quantize). We need a place to store that bit in the interim.
2248   // - This can't be in QuantizationParams because we need to record this
2249   //   ahead of quantization, and QuantizationParams are only created during
2250   //   quantization.
2251   // - This could be in MinMax, but that would be an abuse of what MinMax is
2252   //   about, and would break existing code that assumes that a MinMax is just
2253   //   a min and a max. Unlike MinMax which is agnostic as to the quantized
2254   //   data type, narrow_range refers to values in the quantized data type.
2255   bool narrow_range = false;
2256 
2257  private:
2258   std::unique_ptr<Shape> array_shape;
2259 };
2260 
2261 // Our Model struct, represents an entire model (our "top-level" struct).
2262 // Owns everything.
2263 class Model {
2264  public:
2265   using ArrayMap = std::unordered_map<string, std::unique_ptr<Array>>;
2266 
2267   bool HasArray(const string& name) const { return arrays.count(name) > 0; }
2268   Array& GetArray(const string& name) const {
2269     DCHECK(HasArray(name)) << "Array not found: " << name;
2270     return *arrays.at(name);
2271   }
2272   Array& GetOrCreateArray(const string& name) {
2273     // Make sure name is not used by an optional array
2274     DCHECK(!optional_arrays.count(name));
2275     if (!HasArray(name)) {
2276       Array* ptr = new Array;
2277       arrays[name] = std::unique_ptr<Array>(ptr);
2278     }
2279     Array& result = GetArray(name);
2280     return result;
2281   }
2282   void CreateOptionalArray(const string& name) {
2283     DCHECK(!arrays.count(name) && !optional_arrays.count(name));
2284     optional_arrays.insert(name);
2285   }
2286   bool IsOptionalArray(const string& name) const {
2287     return optional_arrays.count(name);
2288   }
2289 
2290   // Note that this invalidates all array iterators.
2291   void EraseArray(const string& name) { arrays.erase(name); }
2292   void EraseArrays(std::function<bool(const string&)> discardable) {
2293     for (auto it = arrays.begin(); it != arrays.end();) {
2294       if (discardable(it->first)) {
2295         it = arrays.erase(it);
2296       } else {
2297         ++it;
2298       }
2299     }
2300   }
2301   const ArrayMap& GetArrayMap() const { return arrays; }
2302   ArrayMap& GetMutableArrayMap() { return arrays; }
2303 
2304   int64 ArithmeticOpsCount() const { return ops_count; }
2305 
2306   // Optional arrays are used for optional tensors,
2307   // these tensors do not have data, but with reserved names as op inputs.
2308   std::set<string> optional_arrays;
2309 
2310   // The list of operators. Notice how it's a list of unique_ptr's, implying
2311   // that the Model is what owns Operator's and keeps them alive.
2312   std::vector<std::unique_ptr<Operator>> operators;
2313 
2314   // Generic flags, a place where we combine information passed to us via
2315   // command-line parameters (e.g. --input_width=N) with information that
2316   // we may or may not find in the input model file.
2317   ModelFlags flags;
2318   // For code-generation only: required size of the transient_data buffer
2319   std::size_t transient_data_size = 0;
2320   // For code-generation only: required alignment of the transient_data buffer
2321   std::size_t transient_data_alignment = 0;
2322   // Arithmetic operations performed in the model.
2323   int64 ops_count = 0;
2324 
2325  private:
2326   // The associative array mapping names to Array's.
2327   // Notice how it's a container of unique_ptr's, implying
2328   // that the Model is what owns Array's and keeps them alive.
2329   // The Operator's refer to these Array's by their name strings, not by their
2330   // addresses. See Operator::inputs, Operator::outputs.
2331   std::unordered_map<string, std::unique_ptr<Array>> arrays;
2332 };
2333 
2334 // OperatorSignature contains the information required to making versioning
2335 // decisions.
2336 struct OperatorSignature {
2337   // The operator.
2338   const Operator* op;
2339 
2340   // The model in which the operator resides.
2341   const Model* model;
2342 };
2343 }  // namespace toco
2344 
2345 #endif  // TENSORFLOW_LITE_TOCO_MODEL_H_
2346