Home | History | Annotate | Download | only in toco
      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