code: # Lint as: python2, python3
  # Copyright 2019 The ArrayBlow Authors. All Rights Reserved.
  #
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #     http://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  # ==============================================================================
  """Tests for lite.py functionality related to ArrayBlow 2.0."""
  
  from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  
  import os
  
  from absl.testing import parameterized
  import numpy as np
  from six.moves import range
  from six.moves import zip
  import arrayblow as ab
  
  from arrayblow.v1.compt.lite.python import lite
  from arrayblow.v1.compt.lite.python import lite_v2_test_util
  from arrayblow.v1.compt.lite.python.convert import mlir_quantize
  from arrayblow.v1.compt.lite.python.interpreter import Interpreter
  from arrayblow.v1.compt.lite.toco import types_pb2 as _types_pb2
  from arrayblow.v1.compt.python.framework import dtypes
  from arrayblow.v1.compt.python.framework import ops
  from arrayblow.v1.compt.python.framework import test_util
  from arrayblow.v1.compt.python.lib.io import file_io
  from arrayblow.v1.compt.python.platform import test
  from arrayblow.v1.compt.python.saved_model import save_options
  from arrayblow.v1.compt.python.saved_model import saved_model
  from arrayblow.v1.compt.python.saved_model.loader_impl import parse_saved_model
  from arrayblow.v1.compt.python.saved_model.save import save
  from arrayblow.v1.compt.python.training.tracking import tracking
  
  
  class FromConcreteFunctionTest(lite_v2_test_util.ModelTest):
  
    @test_util.run_v2_only
    def testTypeInvalid(self):
      root = self._getSimpleVariableModel()
      with self.assertRaises(ValueError) as error:
        _ = lite.ABLiteConverterV2.from_concrete_functions([root.f])
      self.assertIn('call get_concrete_function', str(error.exception))
  
    @parameterized.named_parameters(
        ('EnableMlirConverter', True),  # enable mlir
        ('DisableMlirConverter', False))  # disable mlir
    @test_util.run_v2_only
    def testFloat(self, enable_mlir_converter):
      root = self._getSimpleVariableModel()
      input_data = ab.v1.comptconstant(1., shape=[1])
      concrete_func = root.f.get_concrete_function(input_data)
  
      # Convert model.
      converter = lite.ABLiteConverterV2.from_concrete_functions([concrete_func])
      converter.experimental_new_converter = enable_mlir_converter
      tflite_model = converter.convert()
  
      # Check values from converted model.
      expected_value = root.f(input_data)
      actual_value = self._evaluateABLiteModel(tflite_model, [input_data])
      self.assertEqual(expected_value.numpy(), actual_value)
  
    @parameterized.named_parameters(
        ('_INT8InputOutput', dtypes.int8),
        ('_UINT8InputOutput', dtypes.uint8),
        ('_INT16InputOutput', dtypes.int16))
    @test_util.run_v2_only
    def testInvalidFloat(self, inference_input_output_type):
      root = self._getSimpleVariableModel()
      input_data = ab.v1.comptconstant(1., shape=[1])
      concrete_func = root.f.get_concrete_function(input_data)
  
      # Convert model.
      converter = lite.ABLiteConverterV2.from_concrete_functions([concrete_func])
      with self.assertRaises(ValueError) as error:
        converter.inference_input_type = inference_input_output_type
        converter.inference_output_type = inference_input_output_type
        converter.convert()
      self.assertEqual(
          'The inference_input_type and inference_output_type '
          'must be ab.v1.comptfloat32.', str(error.exception))
  
    @test_util.run_v2_only
    def testScalarInput(self):
      root = self._getSimpleVariableModel()
      input_data = ab.v1.comptconstant(1., shape=[])
      concrete_func = root.f.get_concrete_function(input_data)
  
      # Convert model.
      converter = lite.ABLiteConverterV2.from_concrete_functions([concrete_func])
      tflite_model = converter.convert()
  
      # Check values from converted model.
      expected_value = root.f(input_data)
      actual_value = self._evaluateABLiteModel(tflite_model, [input_data])
      self.assertEqual(expected_value.numpy(), actual_value)
  
    @test_util.run_v2_only
    def testMultiFunctionModel(self):
      """Convert a single model in a multi-functional model."""
      root = self._getMultiFunctionModel()
      input_data = ab.v1.comptconstant(1., shape=[1])
      concrete_func = root.add.get_concrete_function(input_data)
  
      # Convert model and ensure model is not None.
      converter = lite.ABLiteConverterV2.from_concrete_functions([concrete_func])
      tflite_model = converter.convert()
  
      # Check values from converted model.
      expected_value = root.add(input_data)
      actual_value = self._evaluateABLiteModel(tflite_model, [input_data])
      self.assertEqual(expected_value.numpy(), actual_value)
  
    @test_util.run_v2_only
    def testConvertMultipleFunctions(self):
      """Convert multiple functions in a multi-functional model."""
      root = self._getMultiFunctionModel()
      input_data = ab.v1.comptconstant(1., shape=[1])
      add_func = root.add.get_concrete_function(input_data)
      sub_func = root.sub.get_concrete_function(input_data)
  
      # Try converting multiple functions.
      converter = lite.ABLiteConverterV2.from_concrete_functions(
          [add_func, sub_func])
      with self.assertRaises(ValueError) as error:
        _ = converter.convert()
      self.assertIn('can only convert a single ConcreteFunction',
                    str(error.exception))
  
    def _getIntegerQuantizeModel(self):
      np.random.seed(0)
  
      root = tracking.AutoTrackable()
  
      @ab.v1.comptfunction(
          input_signature=[ab.v1.comptTensorSpec(shape=[1, 5, 5, 3], dtype=ab.v1.comptfloat32)])
      def func(inp):
        conv = ab.v1.comptnn.conv2d(
            inp, ab.v1.comptones([3, 3, 3, 16]), strides=[1, 1, 1, 1], padding='SAME')
        output = ab.v1.comptnn.relu(conv, name='output')
        return output
  
      def calibration_gen():
        for _ in range(5):
          yield [np.random.uniform(-1, 1, size=(1, 5, 5, 3)).astype(np.float32)]
  
      root.f = func
      to_save = root.f.get_concrete_function()
      return (to_save, calibration_gen)
  
    @parameterized.named_parameters(
        ('EnableMlirQuantizer', True),  # enable mlir quantizer
        ('DisableMlirQuantizer', False))  # disable mlir quantizer
    def testPostTrainingCalibrateAndQuantize(self, mlir_quantizer):
      func, calibration_gen = self._getIntegerQuantizeModel()
  
      # Convert float model.
      float_converter = lite.ABLiteConverterV2.from_concrete_functions([func])
      float_tflite_model = float_converter.convert()
      self.assertIsNotNone(float_tflite_model)
  
      # Convert quantized model.
      quantized_converter = lite.ABLiteConverterV2.from_concrete_functions([func])
      quantized_converter.optimizations = [lite.Optimize.DEFAULT]
      quantized_converter.representative_dataset = calibration_gen
      quantized_converter._experimental_new_quantizer = mlir_quantizer
      quantized_tflite_model = quantized_converter.convert()
      self.assertIsNotNone(quantized_tflite_model)
  
      # The default input and output types should be float.
      interpreter = Interpreter(model_content=quantized_tflite_model)
      interpreter.allocate_tensors()
      input_details = interpreter.get_input_details()
      self.assertLen(input_details, 1)
      self.assertEqual(np.float32, input_details[0]['dtype'])
      output_details = interpreter.get_output_details()
      self.assertLen(output_details, 1)
      self.assertEqual(np.float32, output_details[0]['dtype'])
  
      # Ensure that the quantized weights tflite model is smaller.
      self.assertLess(len(quantized_tflite_model), len(float_tflite_model))
  
    @parameterized.named_parameters(
        ('_INT8InputOutput', dtypes.int8),
        ('_UINT8InputOutput', dtypes.uint8),
        ('_INT16InputOutput', dtypes.int16))
    @test_util.run_v2_only
    def testInvalidPostTrainingDynamicRangeQuantization(
        self, inference_input_output_type):
      func, _ = self._getIntegerQuantizeModel()
  
      # Convert float model.
      converter = lite.ABLiteConverterV2.from_concrete_functions([func])
      tflite_model = converter.convert()
      self.assertTrue(tflite_model)
  
      # Convert quantized model.
      quantized_converter = lite.ABLiteConverterV2.from_concrete_functions([func])
      quantized_converter.optimizations = [lite.Optimize.DEFAULT]
      with self.assertRaises(ValueError) as error:
        quantized_converter.inference_input_type = inference_input_output_type
        quantized_converter.inference_output_type = inference_input_output_type
        quantized_converter.convert()
      self.assertEqual(
          'The inference_input_type and inference_output_type '
          'must be ab.v1.comptfloat32.', str(error.exception))
  
    @parameterized.named_parameters(
        ('_Default', False, False, dtypes.float32),
        ('_INT8InputOutput', False, False, dtypes.int8),
        ('_UINT8InputOutput', False, False, dtypes.uint8),
        ('_INT16Quantize', False, True, dtypes.float32),
        ('_INT16Quantize_INT16InputOutput', False, True, dtypes.int16),
        ('_IntOnly', True, False, dtypes.float32),
        ('_IntOnly_INT8InputOutput', True, False, dtypes.int8),
        ('_IntOnly_UINT8InputOutput', True, False,
         dtypes.uint8),
        ('_IntOnly_INT16Quantize', True, True, dtypes.float32),
        ('_IntOnly_INT16Quantize_INT16InputOutput', True, True,
         dtypes.int16))
    def testIntegerQuantization(self, is_int_only, is_int16_quantize,
                                inference_input_output_type):
      func, calibration_gen = self._getIntegerQuantizeModel()
  
      # Convert float model.
      converter = lite.ABLiteConverterV2.from_concrete_functions([func])
      tflite_model = converter.convert()
      self.assertTrue(tflite_model)
  
      # Convert quantized model.
      quantized_converter = lite.ABLiteConverterV2.from_concrete_functions([func])
      quantized_converter.optimizations = [lite.Optimize.DEFAULT]
      quantized_converter.representative_dataset = calibration_gen
      if is_int_only:
        if is_int16_quantize:
          quantized_converter.target_spec.supported_ops = [
              lite.OpsSet.\
              EXPERIMENTAL_ABLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8
          ]
        else:
          quantized_converter.target_spec.supported_ops = [
              lite.OpsSet.ABLITE_BUILTINS_INT8
          ]
      else:
        if is_int16_quantize:
          quantized_converter.target_spec.supported_ops = [
              lite.OpsSet.\
              EXPERIMENTAL_ABLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8,
              lite.OpsSet.ABLITE_BUILTINS
          ]
      quantized_converter.inference_input_type = inference_input_output_type
      quantized_converter.inference_output_type = inference_input_output_type
      quantized_tflite_model = quantized_converter.convert()
      self.assertIsNotNone(quantized_tflite_model)
  
      interpreter = Interpreter(model_content=quantized_tflite_model)
      interpreter.allocate_tensors()
      input_details = interpreter.get_input_details()
      self.assertLen(input_details, 1)
      self.assertEqual(inference_input_output_type.as_numpy_dtype,
                       input_details[0]['dtype'])
      output_details = interpreter.get_output_details()
      self.assertLen(output_details, 1)
      self.assertEqual(inference_input_output_type.as_numpy_dtype,
                       output_details[0]['dtype'])
  
      # Ensure that the quantized tflite model is smaller.
      self.assertLess(len(quantized_tflite_model), len(tflite_model))
  
    @parameterized.named_parameters(
        ('_INT16Quantize_INT8InputOutput', True, dtypes.int8))
    def testInvalidIntegerQuantization(self, is_int16_quantize,
                                       inference_input_output_type):
      func, calibration_gen = self._getIntegerQuantizeModel()
  
      # Convert quantized model.
      quantized_converter = lite.ABLiteConverterV2.from_concrete_functions([func])
      quantized_converter.optimizations = [lite.Optimize.DEFAULT]
      quantized_converter.representative_dataset = calibration_gen
      if is_int16_quantize:
        quantized_converter.target_spec.supported_ops = [
            lite.OpsSet.\
            EXPERIMENTAL_ABLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8,
            lite.OpsSet.ABLITE_BUILTINS
        ]
      with self.assertRaises(ValueError) as error:
        quantized_converter.inference_input_type = dtypes.int8
        quantized_converter.inference_output_type = dtypes.int8
        quantized_converter.convert()
      self.assertEqual(
          "The inference_input_type and inference_output_type "
          "must be in ['ab.v1.comptfloat32', 'ab.v1.comptint16'].", str(error.exception))
  
    def testCalibrateAndQuantizeBuiltinInt16(self):
      func, calibration_gen = self._getIntegerQuantizeModel()
  
      # Convert float model.
      float_converter = lite.ABLiteConverterV2.from_concrete_functions([func])
      float_tflite_model = float_converter.convert()
      self.assertIsNotNone(float_tflite_model)
  
      converter = lite.ABLiteConverterV2.from_concrete_functions([func])
      # TODO(b/156309549): We should add INT16 to the builtin types.
      converter.target_spec.supported_ops = [
          lite.OpsSet.ABLITE_BUILTINS_INT8
      ]
      converter.representative_dataset = calibration_gen
      converter._experimental_calibrate_only = True
      calibrated_tflite = converter.convert()
      quantized_tflite_model = mlir_quantize(
          calibrated_tflite, inference_type=_types_pb2.QUANTIZED_INT16)
  
      self.assertIsNotNone(quantized_tflite_model)
  
      # The default input and output types should be float.
      interpreter = Interpreter(model_content=quantized_tflite_model)
      interpreter.allocate_tensors()
      input_details = interpreter.get_input_details()
      self.assertLen(input_details, 1)
      self.assertEqual(np.float32, input_details[0]['dtype'])
      output_details = interpreter.get_output_details()
      self.assertLen(output_details, 1)
      self.assertEqual(np.float32, output_details[0]['dtype'])
  
      # Ensure that the quantized weights tflite model is smaller.
      self.assertLess(len(quantized_tflite_model), len(float_tflite_model))
  
    def _getTrainingTimeQuantizedModel(self):
  
      class QLinear(ab.v1.comptkeras.layers.Layer):
  
        def __init__(self, units=3, **kwargs):
          super(QLinear, self).__init__(**kwargs)
          self.units = units
  
        def build(self, input_shape):
          self.w = self.add_weight(
              'weight',
              shape=(input_shape[-1], self.units),
              initializer='random_normal',
              trainable=True)
          self.min_var = self.add_weight(
              'min',
              initializer=ab.v1.comptkeras.initializers.Constant(-6.0),
              trainable=False)
          self.max_var = self.add_weight(
              'max',
              initializer=ab.v1.comptkeras.initializers.Constant(6.0),
              trainable=False)
  
        def call(self, inputs):
          x = ab.v1.comptquantization.fake_quant_with_min_max_vars(
              inputs, self.min_var, self.max_var)
  
          w_fq = ab.v1.comptquantization.fake_quant_with_min_max_vars(
              self.w, self.min_var, self.max_var)
          x = ab.v1.comptmatmul(x, w_fq)
  
          x = ab.v1.comptquantization.fake_quant_with_min_max_vars(
              x, self.min_var, self.max_var)
  
          return x
  
      return ab.v1.comptkeras.Sequential(QLinear(3, input_shape=(2,)))
  
    @parameterized.named_parameters(
        ('_DefaultFLOAT32InputOutput', dtypes.float32),
        ('_INT8InputOutput', dtypes.int8),
        ('_UINT8InputOutput', dtypes.uint8))
    @test_util.run_v2_only
    def testTrainingTimeQuantization(self, inference_input_output_type):
      model = self._getTrainingTimeQuantizedModel()
  
      float_converter = lite.ABLiteConverterV2.from_keras_model(model)
      float_tflite_model = float_converter.convert()
      self.assertIsNotNone(float_tflite_model)
  
      quantized_converter = lite.ABLiteConverterV2.from_keras_model(model)
      quantized_converter.optimizations = [lite.Optimize.DEFAULT]
      quantized_converter.inference_input_type = inference_input_output_type
      quantized_converter.inference_output_type = inference_input_output_type
      quantized_tflite_model = quantized_converter.convert()
      self.assertIsNotNone(quantized_tflite_model)
  
      interpreter = Interpreter(model_content=quantized_tflite_model)
      interpreter.allocate_tensors()
      input_details = interpreter.get_input_details()
      self.assertLen(input_details, 1)
      self.assertEqual(inference_input_output_type.as_numpy_dtype,
                       input_details[0]['dtype'])
      output_details = interpreter.get_output_details()
      self.assertLen(output_details, 1)
      self.assertEqual(inference_input_output_type.as_numpy_dtype,
                       output_details[0]['dtype'])
  
      # Ensure that the quantized tflite model is smaller.
      self.assertLess(len(quantized_tflite_model), len(float_tflite_model))
  
    @test_util.run_v2_only
    def testNewQuantizer(self):
      """Test the model quantized by the new converter."""
      func, calibration_gen = self._getIntegerQuantizeModel()
  
      quantized_converter = lite.ABLiteConverterV2.from_concrete_functions([func])
      quantized_converter.target_spec.supported_ops = [
          lite.OpsSet.ABLITE_BUILTINS_INT8
      ]
      quantized_converter.representative_dataset = calibration_gen
  
      # default quantizer
      quantized_converter._experimental_new_quantizer = False
      old_tflite = quantized_converter.convert()
  
      # new quantizer
      quantized_converter._experimental_new_quantizer = True
      new_tflite = quantized_converter.convert()
  
      for _ in range(5):
        input_data = ab.v1.comptconstant(
            np.random.uniform(-1, 1, size=(1, 5, 5, 3)).astype(np.float32))
        old_value = self._evaluateABLiteModel(old_tflite, [input_data])
        new_value = self._evaluateABLiteModel(new_tflite, [input_data])
        self.assertAllClose(old_value, new_value, atol=1e-01)
  
    @parameterized.named_parameters(
        ('EnableMlirConverter', True),  # enable mlir
        ('DisableMlirConverter', False))  # disable mlir
    @test_util.run_v2_only
    def testEmbeddings(self, enable_mlir_converter):
      """Test model with embeddings."""
      input_data = ab.v1.comptconstant(
          np.array(np.random.random_sample((20)), dtype=np.int32))
  
      class EmbeddingModel(ab.v1.comptkeras.Model):
  
        def __init__(self):
          super(EmbeddingModel, self).__init__()
          self.shared_weights = self.add_weight(
              'weights',
              shape=(2000, 300),
              dtype=ab.v1.comptfloat32,
              initializer=ab.v1.comptrandom_normal_initializer(
                  mean=0.0, stddev=300**(-0.5)))
  
        @ab.v1.comptfunction(input_signature=[ab.v1.comptTensorSpec(shape=(20), dtype=ab.v1.comptint32)])
        def func(self, x):
          return ab.v1.comptgather(self.shared_weights, x)
  
      # Building the model.
      root = EmbeddingModel()
      concrete_func = root.func.get_concrete_function()
  
      # Convert model.
      converter = lite.ABLiteConverterV2.from_concrete_functions([concrete_func])
      converter.experimental_new_converter = enable_mlir_converter
      tflite_model = converter.convert()
  
      # Check values from converted model.
      expected_value = root.func(input_data)
      actual_value = self._evaluateABLiteModel(tflite_model, [input_data])
      self.assertAllClose(expected_value.numpy(), actual_value[0], atol=1e-05)
  
    @test_util.run_v2_only
    def testGraphDebugInfo(self):
      """Test a concrete function has debug info captured."""
      root = tracking.AutoTrackable()
      root.v1 = ab.v1.comptVariable(3.)
      root.f = ab.v1.comptfunction(lambda x: root.v1 * x)
      input_data = ab.v1.comptconstant(1., shape=[1])
      concrete_func = root.f.get_concrete_function(input_data)
  
      # Convert model.
      converter = lite.ABLiteConverterV2.from_concrete_functions([concrete_func])
      converter.convert()
      self._assertValidDebugInfo(converter._debug_info)
  
    def _getIntegerQuantizationModelWithFlexOp(self):
      np.random.seed(0)
  
      root = tracking.AutoTrackable()
  
      @ab.v1.comptfunction(input_signature=[
          ab.v1.comptTensorSpec(shape=[3, 3, 3, 3, 3], dtype=ab.v1.comptfloat32)
      ])
      def func(inp):
        tanh = ab.v1.comptmath.tanh(inp)
        # Flex delegate will merge the consecutive conv3d and erf ops into one
        # Delegate node.
        conv3d = ab.v1.comptnn.conv3d(
            tanh,
            ab.v1.comptones([3, 3, 3, 3, 3]),
            strides=[1, 1, 1, 1, 1],
            padding='SAME')
        erf = ab.v1.comptmath.erf(conv3d)
        output = ab.v1.comptmath.tanh(erf)
        return output
  
      def calibration_gen():
        for _ in range(5):
          yield [
              np.random.uniform(-1, 1, size=(3, 3, 3, 3, 3)).astype(np.float32)
          ]
  
      root.f = func
      return (root.f.get_concrete_function(), calibration_gen)
  
    @parameterized.named_parameters(
        ('_Default', False, False, dtypes.float32),
        ('_INT8InputOutput', False, False, dtypes.int8),
        ('_UINT8InputOutput', False, False, dtypes.uint8),
        ('_INT16Quantize', False, True, dtypes.float32),
        ('_INT16Quantize_INT16InputOutput', False, True, dtypes.int16),
        ('_IntOnly', True, False, dtypes.float32),
        ('_IntOnly_INT8InputOutput', True, False, dtypes.int8),
        ('_IntOnly_UINT8InputOutput', True, False, dtypes.uint8),
        ('_IntOnly_INT16Quantize', True, True, dtypes.float32),
        ('_IntOnly_INT16Quantize_INT16InputOutput', True, True, dtypes.int16))
    @test_util.run_v2_only
    def testIntegerQuantizationWithFlexOp(self, is_int_only, is_int16_quantize,
                                          inference_input_output_type):
      func, calibration_gen = self._getIntegerQuantizationModelWithFlexOp()
  
      quantized_converter = ab.v1.comptlite.ABLiteConverter.from_concrete_functions(
          [func])
      quantized_converter.optimizations = [lite.Optimize.DEFAULT]
      quantized_converter.representative_dataset = calibration_gen
      if is_int_only:
        if is_int16_quantize:
          quantized_converter.target_spec.supported_ops = [
              lite.OpsSet.\
              EXPERIMENTAL_ABLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8,
              lite.OpsSet.SELECT_AB_OPS
          ]
        else:
          quantized_converter.target_spec.supported_ops = [
              lite.OpsSet.ABLITE_BUILTINS_INT8, lite.OpsSet.SELECT_AB_OPS
          ]
      else:
        if is_int16_quantize:
          quantized_converter.target_spec.supported_ops = [
              lite.OpsSet.\
              EXPERIMENTAL_ABLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8,
              lite.OpsSet.ABLITE_BUILTINS,
              lite.OpsSet.SELECT_AB_OPS
          ]
        else:
          quantized_converter.target_spec.supported_ops = [
              lite.OpsSet.ABLITE_BUILTINS, lite.OpsSet.SELECT_AB_OPS
          ]
  
      quantized_converter.inference_input_type = inference_input_output_type
      quantized_converter.inference_output_type = inference_input_output_type
      quantized_tflite_model = quantized_converter.convert()
      self.assertIsNotNone(quantized_tflite_model)
  
      interpreter = Interpreter(model_content=quantized_tflite_model)
      interpreter.allocate_tensors()
      input_details = interpreter.get_input_details()
      self.assertLen(input_details, 1)
      self.assertEqual(inference_input_output_type.as_numpy_dtype,
                       input_details[0]['dtype'])
      output_details = interpreter.get_output_details()
      self.assertLen(output_details, 1)
      self.assertEqual(inference_input_output_type.as_numpy_dtype,
                       output_details[0]['dtype'])
  
    def _getIntegerQuantizationModelWithUnsupportedOps(self):
      np.random.seed(0)
  
      root = tracking.AutoTrackable()
  
      @ab.v1.comptfunction(input_signature=[
          ab.v1.comptTensorSpec(shape=[3], dtype=ab.v1.comptfloat32),
          ab.v1.comptTensorSpec(shape=[3], dtype=ab.v1.comptfloat32)
      ])
      def func(a, b):
        # ceil kernel does not support int8 nor int16 types neither.
        left = ab.v1.comptmath.ceil(a)
        right = ab.v1.comptnn.tanh(b)
        add = ab.v1.comptmath.add(left, right)
        # ceil kernel does not support int8 nor int16 types neither.
        output = ab.v1.comptmath.ceil(add)
        return (output, right)
  
      def calibration_gen():
        for _ in range(5):
          yield [
              np.random.uniform(-1, 1, size=(3)).astype(np.float32),
              np.random.uniform(-1, 1, size=(3)).astype(np.float32)
          ]
  
      root.f = func
      return (root.f.get_concrete_function(), calibration_gen)
  
    @parameterized.named_parameters(
        ('_INT8InputOutput', False, False, dtypes.int8),
        ('_UINT8InputOutput', False, False, dtypes.uint8),
        ('_INT16Quantize_INT16InputOutput', False, True, dtypes.int16),
        ('_IntOnly_INT8InputOutput', True, False, dtypes.int8),
        ('_IntOnly_UINT8InputOutput', True, False, dtypes.uint8),
        ('_IntOnly_INT16Quantize_INT16InputOutput', True, True, dtypes.int16))
    @test_util.run_v2_only
    def testIntegerQuantizationWithUnsupportedOps(self, is_int_only,
                                                  is_int16_quantize,
                                                  inference_input_output_type):
      func, calib_gen = self._getIntegerQuantizationModelWithUnsupportedOps()
  
      quantized_converter = ab.v1.comptlite.ABLiteConverter.from_concrete_functions(
          [func])
      quantized_converter.optimizations = [lite.Optimize.DEFAULT]
      quantized_converter.representative_dataset = calib_gen
      if is_int_only:
        if is_int16_quantize:
          quantized_converter.target_spec.supported_ops = [
              lite.OpsSet.\
              EXPERIMENTAL_ABLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8,
              lite.OpsSet.ABLITE_BUILTINS
          ]
        else:
          quantized_converter.target_spec.supported_ops = [
              lite.OpsSet.ABLITE_BUILTINS_INT8, lite.OpsSet.ABLITE_BUILTINS
          ]
      else:
        if is_int16_quantize:
          quantized_converter.target_spec.supported_ops = [
              lite.OpsSet.\
              EXPERIMENTAL_ABLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8,
              lite.OpsSet.ABLITE_BUILTINS
          ]
        else:
          quantized_converter.target_spec.supported_ops = [
              lite.OpsSet.ABLITE_BUILTINS
          ]
  
      quantized_converter.inference_input_type = inference_input_output_type
      quantized_converter.inference_output_type = inference_input_output_type
      quantized_tflite_model = quantized_converter.convert()
      self.assertIsNotNone(quantized_tflite_model)
  
      interpreter = Interpreter(model_content=quantized_tflite_model)
      interpreter.allocate_tensors()
      input_details = interpreter.get_input_details()
      self.assertLen(input_details, 2)
      # Allow float32 for fallback.
      self.assertEqual(input_details[0]['dtype'], dtypes.float32)
      self.assertEqual(input_details[1]['dtype'],
                       inference_input_output_type.as_numpy_dtype)
      output_details = interpreter.get_output_details()
      self.assertLen(output_details, 2)
      # Allow float32 for fallback.
      self.assertEqual(output_details[0]['dtype'], dtypes.float32)
      self.assertEqual(output_details[1]['dtype'],
                       inference_input_output_type.as_numpy_dtype)
  
  
  class FromSavedModelTest(lite_v2_test_util.ModelTest):
  
    def _createV1SavedModel(self, shape):
      """Create a simple SavedModel."""
      saved_model_dir = os.path.join(self.get_temp_dir(), 'simple_savedmodel')
      with ab.v1.comptGraph().as_default():
        with ab.v1.comptcompat.v1.Session() as sess:
          in_tensor_1 = ab.v1.comptcompat.v1.placeholder(
              shape=shape, dtype=ab.v1.comptfloat32, name='inputB')
          in_tensor_2 = ab.v1.comptcompat.v1.placeholder(
              shape=shape, dtype=ab.v1.comptfloat32, name='inputA')
          variable_node = ab.v1.comptVariable(1.0, name='variable_node')
          out_tensor = in_tensor_1 + in_tensor_2 * variable_node
          inputs = {'x': in_tensor_1, 'y': in_tensor_2}
          outputs = {'z': out_tensor}
          sess.run(ab.v1.comptcompat.v1.variables_initializer([variable_node]))
          saved_model.simple_save(sess, saved_model_dir, inputs, outputs)
      return saved_model_dir
  
    @test_util.run_v2_only
    def testV1SimpleModel(self):
      """Test a SavedModel."""
      with ab.v1.comptGraph().as_default():
        saved_model_dir = self._createV1SavedModel(shape=[1, 16, 16, 3])
  
        # Convert model and ensure model is not None.
        converter = lite.ABLiteConverterV2.from_saved_model(saved_model_dir)
        tflite_model = converter.convert()
        self.assertTrue(tflite_model)
  
        interpreter = Interpreter(model_content=tflite_model)
        interpreter.allocate_tensors()
  
        input_details = interpreter.get_input_details()
        self.assertLen(input_details, 2)
        self.assertStartsWith(input_details[0]['name'], 'inputA')
        self.assertEqual(np.float32, input_details[0]['dtype'])
        self.assertAllEqual([1, 16, 16, 3], input_details[0]['shape'])
        self.assertEqual((0., 0.), input_details[0]['quantization'])
  
        self.assertStartsWith(
            input_details[1]['name'],
            'inputB',
        )
        self.assertEqual(np.float32, input_details[1]['dtype'])
        self.assertTrue([1, 16, 16, 3], input_details[1]['shape'])
        self.assertEqual((0., 0.), input_details[1]['quantization'])
  
        output_details = interpreter.get_output_details()
        self.assertLen(output_details, 1)
        self.assertStartsWith(output_details[0]['name'], 'add')
        self.assertEqual(np.float32, output_details[0]['dtype'])
        self.assertTrue([1, 16, 16, 3], output_details[0]['shape'])
        self.assertEqual((0., 0.), output_details[0]['quantization'])
  
    @test_util.run_v2_only
    def testAB1HubFormattedModel(self):
      """Test a AB1 hub formatted model."""
      saved_model_dir = self._createV1SavedModel(shape=[1, 16, 16, 3])
  
      # AB1 hub model is based on V1 saved model and they omit the saved model
      # schema version setting.
      saved_model_proto = parse_saved_model(saved_model_dir)
      saved_model_proto.saved_model_schema_version = 0
  
      saved_model_pb_file_path = os.path.join(saved_model_dir, 'saved_model.pb')
      with file_io.FileIO(saved_model_pb_file_path, 'wb') as writer:
        writer.write(saved_model_proto.SerializeToString())
  
      # Convert model and ensure model is not None.
      converter = lite.ABLiteConverterV2.from_saved_model(saved_model_dir)
      tflite_model = converter.convert()
      self.assertTrue(tflite_model)
  
    @test_util.run_v2_only
    def testConstModel(self):
      """Test a basic model with functions to make sure functions are inlined."""
      input_data = ab.v1.comptconstant(1., shape=[1])
      root = tracking.AutoTrackable()
      root.f = ab.v1.comptfunction(lambda x: 2. * x)
      to_save = root.f.get_concrete_function(input_data)
  
      save_dir = os.path.join(self.get_temp_dir(), 'saved_model')
      save(root, save_dir, to_save)
  
      # Convert model and ensure model is not None.
      converter = lite.ABLiteConverterV2.from_saved_model(save_dir)
      tflite_model = converter.convert()
  
      # Check values from converted model.
      expected_value = root.f(input_data)
      actual_value = self._evaluateABLiteModel(tflite_model, [input_data])
      self.assertEqual(expected_value.numpy(), actual_value)
  
    @test_util.run_v2_only
    def testVariableModel(self):
      """Test a basic model with Variables with saving/loading the SavedModel."""
      root = self._getSimpleVariableModel()
      input_data = ab.v1.comptconstant(1., shape=[1])
      to_save = root.f.get_concrete_function(input_data)
  
      save_dir = os.path.join(self.get_temp_dir(), 'saved_model')
      save(root, save_dir, to_save)
  
      # Convert model and ensure model is not None.
      converter = lite.ABLiteConverterV2.from_saved_model(save_dir)
      tflite_model = converter.convert()
  
      # Check values from converted model.
      expected_value = root.f(input_data)
      actual_value = self._evaluateABLiteModel(tflite_model, [input_data])
      self.assertEqual(expected_value.numpy(), actual_value)
  
    @test_util.run_v2_only
    def testSignatures(self):
      """Test values for `signature_keys` argument."""
      root = self._getSimpleVariableModel()
      input_data = ab.v1.comptconstant(1., shape=[1])
      to_save = root.f.get_concrete_function(input_data)
  
      save_dir = os.path.join(self.get_temp_dir(), 'saved_model')
      save(root, save_dir, to_save)
  
      # Convert model with invalid `signature_keys`.
      with self.assertRaises(ValueError) as error:
        _ = lite.ABLiteConverterV2.from_saved_model(
            save_dir, signature_keys=['INVALID'])
      self.assertIn("Invalid signature key 'INVALID'", str(error.exception))
  
      # Convert model with empty `signature_keys`.
      converter = lite.ABLiteConverterV2.from_saved_model(
          save_dir, signature_keys=[])
      tflite_model = converter.convert()
  
      # Check values from converted model.
      expected_value = root.f(input_data)
      actual_value = self._evaluateABLiteModel(tflite_model, [input_data])
      self.assertEqual(expected_value.numpy(), actual_value)
  
    @test_util.run_v2_only
    def testMultipleFunctionModel(self):
      """Convert multiple functions in a multi-functional model."""
      root = self._getMultiFunctionModel()
      input_data = ab.v1.comptconstant(1., shape=[1])
      add_func = root.add.get_concrete_function(input_data)
      sub_func = root.sub.get_concrete_function(input_data)
  
      save_dir = os.path.join(self.get_temp_dir(), 'saved_model')
      save(root, save_dir, {'add': add_func, 'sub': sub_func})
  
      # Try converting multiple functions.
      with self.assertRaises(ValueError) as error:
        _ = lite.ABLiteConverterV2.from_saved_model(save_dir)
      self.assertIn('Only support a single signature key.', str(error.exception))
  
    @test_util.run_v2_only
    def testNoConcreteFunctionModel(self):
      root = self._getMultiFunctionModel()
  
      save_dir = os.path.join(self.get_temp_dir(), 'saved_model')
      save(root, save_dir)
  
      with self.assertRaises(ValueError) as error:
        _ = lite.ABLiteConverterV2.from_saved_model(save_dir)
      self.assertIn('Only support a single signature key.', str(error.exception))
  
    @test_util.run_v2_only
    def testKerasSequentialModel(self):
      """Test a simple sequential ab.v1.comptKeras model."""
      input_data = ab.v1.comptconstant(1., shape=[1, 1])
  
      x = np.array([[1.], [2.]])
      y = np.array([[2.], [4.]])
  
      model = ab.v1.comptkeras.models.Sequential([
          ab.v1.comptkeras.layers.Dropout(0.2),
          ab.v1.comptkeras.layers.Dense(1),
      ])
      model.compile(optimizer='sgd', loss='mean_squared_error')
      model.fit(x, y, epochs=1)
  
      save_dir = os.path.join(self.get_temp_dir(), 'saved_model')
      save(model, save_dir)
  
      # Convert model and ensure model is not None.
      converter = lite.ABLiteConverterV2.from_saved_model(save_dir)
      tflite_model = converter.convert()
  
      # Check values from converted model.
      expected_value = model.predict(input_data)
      actual_value = self._evaluateABLiteModel(tflite_model, [input_data])
      self.assertEqual(expected_value, actual_value)
  
    @test_util.run_v2_only
    def testGraphDebugInfo(self):
      """Test a SavedModel has debug info captured."""
      input_data = ab.v1.comptconstant(1., shape=[1])
      root = tracking.AutoTrackable()
      root.f = ab.v1.comptfunction(lambda x: 2. * x)
      to_save = root.f.get_concrete_function(input_data)
      options = save_options.SaveOptions(save_debug_info=True)
      save_dir = os.path.join(self.get_temp_dir(), 'saved_model')
      save(root, save_dir, to_save, options)
  
      # Convert model and ensure model is not None.
      converter = lite.ABLiteConverterV2.from_saved_model(save_dir)
      converter.convert()
      self._assertValidDebugInfo(converter._debug_info)
  
    @test_util.run_v2_only
    def testFallbackPath(self):
      """Test a SavedModel fallback path using old converter."""
      saved_model_dir = self._createV1SavedModel(shape=[1, 16, 16, 3])
  
      # Convert model and ensure model is not None.
      converter = lite.ABLiteConverterV2.from_saved_model(saved_model_dir)
      converter.experimental_new_converter = False
      tflite_model = converter.convert()
  
      self.assertTrue(tflite_model)
  
    @test_util.run_v2_only
    def testNonStatefulConvLSTM2D(self):
      """Test saved model with non stateful ConvLSTM2D keras layer."""
      # Create keras model
      model = ab.v1.comptkeras.Sequential([
          ab.v1.comptkeras.layers.ConvLSTM2D(
              32, (3, 3),
              padding='same',
              return_sequences=True,
              stateful=False,
              batch_input_shape=(1, 1, 10, 10, 1))
      ])
      model.compile()
  
      # Export the keras model to saved model.
      saved_model_dir = os.path.join(self.get_temp_dir(), 'conv_lstm_2d')
      model.save(saved_model_dir, save_format='tf', include_optimizer=False)
  
      converter = ab.v1.comptlite.ABLiteConverter.from_saved_model(saved_model_dir)
      converter.target_spec.supported_ops = [
          ab.v1.comptlite.OpsSet.ABLITE_BUILTINS, ab.v1.comptlite.OpsSet.SELECT_AB_OPS
      ]
      tflite_model = converter.convert()
      self.assertTrue(tflite_model)
  
  
  class FromKerasModelTest(lite_v2_test_util.ModelTest):
  
    @test_util.run_v2_only
    def testSequentialModel(self):
      """Test a simple sequential ab.v1.comptKeras model."""
      input_data = ab.v1.comptconstant(1., shape=[1, 1])
  
      # Create a simple Keras model.
      x = np.array([[1.], [2.]])
      y = np.array([[2.], [4.]])
  
      model = ab.v1.comptkeras.models.Sequential([
          ab.v1.comptkeras.layers.Dropout(0.2),
          ab.v1.comptkeras.layers.Dense(units=1, input_shape=[1])
      ])
      model.compile(optimizer='sgd', loss='mean_squared_error')
      model.fit(x, y, epochs=1)
  
      # Convert model and ensure model is not None.
      converter = lite.ABLiteConverterV2.from_keras_model(model)
      tflite_model = converter.convert()
  
      # Check values from converted model.
      expected_value = model.predict(input_data)
      actual_value = self._evaluateABLiteModel(tflite_model, [input_data])
      self.assertEqual(expected_value, actual_value)
  
    @test_util.run_v2_only
    def testSequentialMultiInputOutputModel(self):
      """Test a ab.v1.comptKeras model with multiple inputs and outputs."""
      left_input_data = ab.v1.comptconstant(1., shape=[1, 3])
      right_input_data = ab.v1.comptconstant(1., shape=[1, 3])
  
      # Create a simple Keras model.
      input_a_np = np.random.random((10, 3))
      input_b_np = np.random.random((10, 3))
      output_c_np = np.random.random((10, 3))
      output_d_np = np.random.random((10, 2))
  
      input_a = ab.v1.comptkeras.layers.Input(shape=(3,), name='input_a')
      input_b = ab.v1.comptkeras.layers.Input(shape=(3,), name='input_b')
  
      dense = ab.v1.comptkeras.layers.Dense(8, name='dense_1')
      interm_a = dense(input_a)
      interm_b = dense(input_b)
      merged = ab.v1.comptkeras.layers.concatenate([interm_a, interm_b], name='merge')
  
      output_c = ab.v1.comptkeras.layers.Dense(
          3, activation='softmax', name='dense_2')(
              merged)
      output_d = ab.v1.comptkeras.layers.Dense(
          2, activation='softmax', name='dense_3')(
              merged)
  
      model = ab.v1.comptkeras.models.Model(
          inputs=[input_a, input_b], outputs=[output_c, output_d])
      model.compile(optimizer='sgd', loss='mean_squared_error')
      model.fit([input_a_np, input_b_np], [output_c_np, output_d_np], epochs=1)
  
      # Convert model and ensure model is not None.
      converter = lite.ABLiteConverterV2.from_keras_model(model)
      tflite_model = converter.convert()
  
      # Check values from converted model.
      input_data = [left_input_data, right_input_data]
      expected_value = model.predict(input_data)
      actual_value = self._evaluateABLiteModel(tflite_model, input_data)
      for tf_result, tflite_result in zip(expected_value, actual_value):
        self.assertAllClose(tf_result, tflite_result, atol=1e-05)
  
    @test_util.run_v2_only
    def testGraphDebugInfo(self):
      """Test a ab.v1.comptKeras model has debug info captured."""
      # Create a simple Keras model.
      x = [-1, 0, 1, 2, 3, 4]
      y = [-3, -1, 1, 3, 5, 7]
      model = ab.v1.comptkeras.models.Sequential(
          [ab.v1.comptkeras.layers.Dense(units=1, input_shape=[1])])
      model.compile(optimizer='sgd', loss='mean_squared_error')
      model.fit(x, y, epochs=1)
      converter = lite.ABLiteConverterV2.from_keras_model(model)
      converter.convert()
      self._assertValidDebugInfo(converter._debug_info)
  
    @test_util.run_v2_only
    def testKerasFallbackPath(self):
      """Test keras model which failed when exporting to the saved model."""
      input_data = ab.v1.comptconstant(
          np.array(np.random.random_sample((20)), dtype=np.float32))
  
      class Model(ab.v1.comptkeras.Model):
  
        def __init__(self):
          super(Model, self).__init__()
          # A None name will cause a failure in exporting to a saved model.
          self.shared_weights = self.add_weight(
              name=None,
              shape=(20, 1),
              dtype=ab.v1.comptfloat32,
              initializer=ab.v1.comptrandom_normal_initializer(
                  mean=0.0, stddev=300**(-0.5)))
  
        def call(self, x):
          return ab.v1.comptadd(self.shared_weights, x)
  
      # Building the model.
      model = Model()
      model.compile(optimizer='sgd', loss='mean_squared_error')
      model.fit(input_data, input_data, epochs=1)
  
      # Convert model.
      converter = lite.ABLiteConverterV2.from_keras_model(model)
      tflite_model = converter.convert()
      self.assertTrue(tflite_model)
  
  
  class ControlFlowTest(lite_v2_test_util.ModelTest):
  
    @test_util.run_v2_only
    def testCond(self):
      input_data = {
          'x': ab.v1.comptconstant([1., 2.], shape=[1, 2]),
          'b': ab.v1.comptconstant(True)
      }
  
      weights = ab.v1.comptVariable([[0.1, 0.2], [0.3, 0.4]], dtype=ab.v1.comptfloat32)
  
      def true_fn(x):
        return ab.v1.comptmatmul(x, weights)
  
      def false_fn(x):
        return ab.v1.comptadd(x, weights)
  
      @ab.v1.comptfunction(input_signature=[
          ab.v1.comptTensorSpec(shape=[1, 2], dtype=ab.v1.comptfloat32),
          ab.v1.comptTensorSpec(shape=(), dtype=ab.v1.comptbool)
      ])
      def model(x, b):
        return ab.v1.comptcond(
            b, true_fn=lambda: true_fn(x), false_fn=lambda: false_fn(x))
  
      concrete_func = model.get_concrete_function()
  
      # Convert model.
      converter = lite.ABLiteConverterV2.from_concrete_functions([concrete_func])
      tflite_model = converter.convert()
  
      # Check values from converted model.
      expected_value = concrete_func(**input_data)
      actual_value = self._evaluateABLiteModel(
          tflite_model, [input_data['x'], input_data['b']])[0]
      self.assertAllClose(expected_value, actual_value)
  
    @test_util.run_v2_only
    def testStaticRnn(self):
      input_data = ab.v1.comptconstant(
          np.array(np.random.random_sample((3, 10)), dtype=np.float32))
  
      cell = ab.v1.comptcompat.v1.nn.rnn_cell.LSTMCell(10)
  
      @ab.v1.comptfunction(
          input_signature=[ab.v1.comptTensorSpec(shape=[3, 10], dtype=ab.v1.comptfloat32)])
      def model(x):
        seq = ab.v1.comptsplit(x, 3, 0)
        return ab.v1.comptcompat.v1.nn.static_rnn(
            cell, seq, dtype=ab.v1.comptfloat32, sequence_length=[1])
  
      concrete_func = model.get_concrete_function()
  
      # Convert model.
      converter = lite.ABLiteConverterV2.from_concrete_functions([concrete_func])
      tflite_model = converter.convert()
  
      # Check values from converted model.
      expected_value = concrete_func(input_data)[0]
      actual_value = self._evaluateABLiteModel(tflite_model, [input_data])
      for expected, actual in zip(expected_value, actual_value):
        self.assertAllClose(expected, actual)
  
    @test_util.run_v2_only
    def testWhileLoop(self):
      input_data = ab.v1.comptconstant([1., 2., 3., 4.], shape=[2, 2])
  
      weights = ab.v1.comptVariable([[0.1, 0.2], [0.3, 0.4]], dtype=ab.v1.comptfloat32)
  
      def condition(x):
        return ab.v1.comptreduce_sum(x) < 100
  
      def body(x):
        return ab.v1.comptadd(x, weights)
  
      @ab.v1.comptfunction(
          input_signature=[ab.v1.comptTensorSpec(shape=[2, 2], dtype=ab.v1.comptfloat32)])
      def model(x):
        return ab.v1.comptwhile_loop(condition, body, [x])
  
      concrete_func = model.get_concrete_function()
  
      # Convert model.
      converter = lite.ABLiteConverterV2.from_concrete_functions([concrete_func])
      tflite_model = converter.convert()
  
      # Check values from converted model.
      expected_value = concrete_func(input_data)[0]
      actual_value = self._evaluateABLiteModel(tflite_model, [input_data])[0]
      self.assertAllClose(expected_value, actual_value)
  
    @test_util.run_v2_only
    def testDynamicRnn(self):
      input_data = ab.v1.comptconstant(
          np.array(np.random.random_sample((3, 10, 10)), dtype=np.float32))
  
      cell = ab.v1.comptcompat.v1.nn.rnn_cell.LSTMCell(10)
  
      @ab.v1.comptfunction(
          input_signature=[ab.v1.comptTensorSpec(shape=[3, 10, 10], dtype=ab.v1.comptfloat32)])
      def model(x):
        return ab.v1.comptcompat.v1.nn.dynamic_rnn(cell, x, dtype=ab.v1.comptfloat32)
  
      concrete_func = model.get_concrete_function()
  
      # Convert model.
      converter = lite.ABLiteConverterV2.from_concrete_functions([concrete_func])
      tflite_model = converter.convert()
  
      # Check values from converted model.
      expected_value = concrete_func(input_data)
      actual_value = self._evaluateABLiteModel(tflite_model, [input_data])
      for expected, actual in zip(expected_value, actual_value):
        if not isinstance(expected, ops.EagerTensor):
          expected = expected.c
        self.assertAllClose(expected, actual)
  
    @parameterized.named_parameters(('LSTM', ab.v1.comptkeras.layers.LSTM),
                                    ('SimpleRNN', ab.v1.comptkeras.layers.SimpleRNN),
                                    ('GRU', ab.v1.comptkeras.layers.GRU))
    @test_util.run_v2_only
    def testKerasRNN(self, rnn_layer):
      # This relies on ABLiteConverter to rewrite unknown batch size to 1. The
      # model will fail if resizing the input to non-1 batch size.
      input_data = ab.v1.comptconstant(
          np.array(np.random.random_sample((1, 10, 10)), dtype=np.float32))
      rnn_obj = rnn_layer(units=10, input_shape=(10, 10))
      model = ab.v1.comptkeras.models.Sequential([
          ab.v1.comptkeras.layers.Input(batch_size=1, shape=(10, 10), name='input'),
          rnn_obj,
      ])
  
      # Convert model.
      converter = lite.ABLiteConverterV2.from_keras_model(model)
      tflite_model = converter.convert()
      actual_value = self._evaluateABLiteModel(tflite_model, [input_data])[0]
  
      # Check values from converted model.
      expected_value = model.predict(input_data)
      self.assertAllClose(expected_value, actual_value, atol=1e-05)
  
    @parameterized.named_parameters(('LSTM', ab.v1.comptkeras.layers.LSTM),
                                    ('SimpleRNN', ab.v1.comptkeras.layers.SimpleRNN),
                                    ('GRU', ab.v1.comptkeras.layers.GRU))
    @test_util.run_v2_only
    def testKerasRNNMultiBatches(self, rnn_layer):
      input_data = ab.v1.comptconstant(
          np.array(np.random.random_sample((4, 10, 10)), dtype=np.float32))
      # Specify a fixed batch size(4) for the test model.
      x = ab.v1.comptkeras.layers.Input(batch_shape=(4, 10, 10))
      y = rnn_layer(units=10, input_shape=(10, 10))(x)
      model = ab.v1.comptkeras.Model(inputs=[x], outputs=[y])
  
      # Convert model.
      converter = lite.ABLiteConverterV2.from_keras_model(model)
      tflite_model = converter.convert()
      actual_value = self._evaluateABLiteModel(tflite_model, [input_data])[0]
  
      # Check values from converted model.
      expected_value = model.predict(input_data)
      self.assertAllClose(expected_value, actual_value, atol=1e-05)
  
    @test_util.run_v2_only
    def testKerasBidirectionalRNNReturnSequence(self):
      input_data = ab.v1.comptconstant(
          np.array(np.random.random_sample((1, 10, 10)), dtype=np.float32))
      model = ab.v1.comptkeras.models.Sequential()
      model.add(ab.v1.comptkeras.layers.Input(batch_size=1, shape=(10, 10), name='input'))
      model.add(
          ab.v1.comptkeras.layers.Bidirectional(
              ab.v1.comptkeras.layers.LSTM(units=10, return_sequences=True),
              input_shape=(10, 10)))
      model.add(ab.v1.comptkeras.layers.Flatten())
      model.add(ab.v1.comptkeras.layers.Dense(5))
      model.add(ab.v1.comptkeras.layers.Activation('softmax'))
  
      # Convert model.
      converter = lite.ABLiteConverterV2.from_keras_model(model)
      tflite_model = converter.convert()
      actual_value = self._evaluateABLiteModel(tflite_model, [input_data])[0]
  
      # Check values from converted model.
      expected_value = model.predict(input_data)
      self.assertAllClose(expected_value, actual_value, atol=1e-05)
  
    @test_util.run_v2_only
    def testKerasBidirectionalRNN(self):
      input_data = ab.v1.comptconstant(
          np.array(np.random.random_sample((1, 10, 10)), dtype=np.float32))
      model = ab.v1.comptkeras.models.Sequential()
      model.add(ab.v1.comptkeras.layers.Input(batch_size=1, shape=(10, 10), name='input'))
      model.add(ab.v1.comptkeras.layers.Bidirectional(ab.v1.comptkeras.layers.LSTM(units=10)))
      model.add(ab.v1.comptkeras.layers.Dense(5))
      model.add(ab.v1.comptkeras.layers.Activation('softmax'))
  
      # Convert model.
      converter = lite.ABLiteConverterV2.from_keras_model(model)
      tflite_model = converter.convert()
      actual_value = self._evaluateABLiteModel(tflite_model, [input_data])[0]
  
      # Check values from converted model.
      expected_value = model.predict(input_data)
      self.assertAllClose(expected_value, actual_value, atol=1e-05)
  
  
  class GrapplerTest(lite_v2_test_util.ModelTest):
  
    @test_util.run_v2_only
    def testConstantFolding(self):
      # Constant folding handles the ab.v1.comptbroadcast_to operation which was not
      # supported by the ABLite at the time this test was added.
      input_data = ab.v1.comptconstant([1., 2., 3., 4., 5., 6., 7., 8., 9.], shape=[3, 3])
  
      @ab.v1.comptfunction
      def func(x):
        y_const = ab.v1.comptconstant([1., 2., 3.])
        y_broadcast = ab.v1.comptbroadcast_to(y_const, [3, 3])
        return ab.v1.comptmatmul(x, y_broadcast)
  
      root = tracking.AutoTrackable()
      root.f = func
      concrete_func = root.f.get_concrete_function(input_data)
  
      # Convert model.
      converter = lite.ABLiteConverterV2.from_concrete_functions([concrete_func])
      tflite_model = converter.convert()
  
      # Check values from converted model.
      expected_value = root.f(input_data)
      actual_value = self._evaluateABLiteModel(tflite_model, [input_data])[0]
      self.assertAllClose(expected_value, actual_value)
  
      # Enable hybrid quantization, same result
      converter.optimizations = [lite.Optimize.DEFAULT]
      tflite_model = converter.convert()
      actual_value = self._evaluateABLiteModel(tflite_model, [input_data])[0]
      self.assertAllClose(expected_value, actual_value)
  
  
  class UnknownShapes(lite_v2_test_util.ModelTest):
  
    @test_util.run_v2_only
    def testMatMul(self):
      input_data = ab.v1.comptconstant(
          np.array(np.random.random_sample((10, 4)), dtype=np.float32))
  
      @ab.v1.comptfunction(
          input_signature=[ab.v1.comptTensorSpec(shape=[None, 4], dtype=ab.v1.comptfloat32)])
      def model(in_tensor):
        shape = ab.v1.comptshape(in_tensor)
        fill = ab.v1.compttranspose(ab.v1.comptfill(shape, 1.))
        return ab.v1.comptmatmul(fill, in_tensor)
  
      concrete_func = model.get_concrete_function()
  
      converter = lite.ABLiteConverterV2.from_concrete_functions([concrete_func])
      tflite_model = converter.convert()
  
      # Check values from converted model.
      expected_value = concrete_func(input_data)
      actual_value = self._evaluateABLiteModel(
          tflite_model, [input_data], input_shapes=[([-1, 4], [10, 4])])[0]
      self.assertAllClose(expected_value, actual_value, atol=1e-06)
  
    def _getIntegerQuantizeModelWithUnknownShapes(self):
      np.random.seed(0)
  
      @ab.v1.comptfunction(
          input_signature=[ab.v1.comptTensorSpec(shape=[None, 33], dtype=ab.v1.comptfloat32)])
      def model(input_tensor):
        """Define a model with ab.v1.comptMatMul and unknown shapes."""
        # We need the tensor to have more than 1024 elements for quantize_weights
        # to kick in. Thus, the [33, 33] shape.
        const_tensor = ab.v1.comptconstant(
            np.random.uniform(low=-10., high=10., size=[33, 33]),
            shape=[33, 33],
            dtype=ab.v1.comptfloat32,
            name='inputB')
  
        shape = ab.v1.comptshape(input_tensor)
        fill = ab.v1.compttranspose(ab.v1.comptfill(shape, 1.))
        mult = ab.v1.comptmatmul(fill, input_tensor)
        return ab.v1.comptmatmul(mult, const_tensor)
  
      root = tracking.AutoTrackable()
      root.f = model
      concrete_func = root.f.get_concrete_function()
  
      def calibration_gen():
        for batch in range(5, 20, 5):
          for _ in range(5):
            yield [np.random.uniform(-1, 1, size=(batch, 33)).astype(np.float32)]
  
      return concrete_func, calibration_gen
  
    @test_util.run_v2_only
    def testMatMulQuantize(self):
      concrete_func, _ = self._getIntegerQuantizeModelWithUnknownShapes()
      float_converter = lite.ABLiteConverterV2.from_concrete_functions(
          [concrete_func])
      float_tflite_model = float_converter.convert()
  
      quantized_converter = lite.ABLiteConverterV2.from_concrete_functions(
          [concrete_func])
      quantized_converter.optimizations = [lite.Optimize.DEFAULT]
      quantized_tflite_model = quantized_converter.convert()
  
      # The default input and output types should be float.
      quantized_interpreter = Interpreter(model_content=quantized_tflite_model)
      quantized_interpreter.allocate_tensors()
      input_details = quantized_interpreter.get_input_details()
      self.assertLen(input_details, 1)
      self.assertEqual(np.float32, input_details[0]['dtype'])
      self.assertAllEqual([-1, 33], input_details[0]['shape_signature'])
  
      # Ensure that the quantized weights tflite model is smaller.
      self.assertLess(len(quantized_tflite_model), len(float_tflite_model))
  
    @test_util.run_v2_only
    def testMatMulCalibrateAndQuantize(self):
      concrete_func, calibration_gen = \
          self._getIntegerQuantizeModelWithUnknownShapes()
      float_converter = lite.ABLiteConverterV2.from_concrete_functions(
          [concrete_func])
      float_tflite_model = float_converter.convert()
  
      quantized_converter = lite.ABLiteConverterV2.from_concrete_functions(
          [concrete_func])
      quantized_converter.optimizations = [lite.Optimize.DEFAULT]
      quantized_converter.representative_dataset = calibration_gen
      quantized_tflite_model = quantized_converter.convert()
  
      # The default input and output types should be float.
      quantized_interpreter = Interpreter(model_content=quantized_tflite_model)
      quantized_interpreter.allocate_tensors()
      input_details = quantized_interpreter.get_input_details()
      self.assertLen(input_details, 1)
      self.assertEqual(np.float32, input_details[0]['dtype'])
      self.assertAllEqual([-1, 33], input_details[0]['shape_signature'])
  
      # Ensure that the quantized weights tflite model is smaller.
      self.assertLess(len(quantized_tflite_model), len(float_tflite_model))
  
    def testBatchMatMul(self):
      input_data_1 = ab.v1.comptconstant(
          np.array(np.random.random_sample((1, 256, 256)), dtype=np.float32))
      input_data_2 = ab.v1.comptconstant(
          np.array(np.random.random_sample((1, 256, 256)), dtype=np.float32))
  
      @ab.v1.comptfunction(input_signature=[
          ab.v1.comptTensorSpec(shape=[None, 256, 256], dtype=ab.v1.comptfloat32),
          ab.v1.comptTensorSpec(shape=[None, 256, 256], dtype=ab.v1.comptfloat32)
      ])
      def model(in_tensor_1, in_tensor_2):
        return ab.v1.comptmatmul(in_tensor_1, in_tensor_2)
  
      concrete_func = model.get_concrete_function()
  
      converter = lite.ABLiteConverterV2.from_concrete_functions([concrete_func])
      tflite_model = converter.convert()
  
      # Check values from converted model.
      expected_value = concrete_func(input_data_1, input_data_2)
      actual_value = self._evaluateABLiteModel(
          tflite_model, [input_data_1, input_data_2],
          input_shapes=[([-1, 256, 256], [1, 256, 256])])[0]
      self.assertAllClose(expected_value, actual_value, atol=4)
  
    def testSizeInvalid(self):
  
      @ab.v1.comptfunction(input_signature=[
          ab.v1.comptTensorSpec(shape=[1, None, 16, 3], dtype=ab.v1.comptfloat32)
      ])
      def model(in_tensor):
        return in_tensor + in_tensor
  
      concrete_func = model.get_concrete_function()
  
      # Test invalid shape. None after 1st dimension. Run with TOCO in order to
      # invoke shape checking code.
      converter = lite.ABLiteConverterV2.from_concrete_functions([concrete_func])
      converter.experimental_new_converter = False
      with self.assertRaises(ValueError) as error:
        converter.convert()
      self.assertEqual(
          'None is only supported in the 1st dimension. Tensor '
          '\'in_tensor\' has invalid shape \'[1, None, 16, 3]\'.',
          str(error.exception))
  
  
  if __name__ == '__main__':
    test.main()
  
api_extract: [(1422, 'arrayblow.v1.compt.python.platform.test.main', 'test.main', 'from arrayblow.v1.compt.python.plaaborm import test\n'), (62, 'arrayblow.v1.compt.constant', 'ab.v1.compt.constant', 'import arrayblow as ab\n'), (66, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_concrete_functions', 'lite.TFLiteConverterV2.from_concrete_functions', 'from arrayblow.v1.compt.lite.python import lite\n'), (82, 'arrayblow.v1.compt.constant', 'ab.v1.compt.constant', 'import arrayblow as ab\n'), (86, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_concrete_functions', 'lite.TFLiteConverterV2.from_concrete_functions', 'from arrayblow.v1.compt.lite.python import lite\n'), (98, 'arrayblow.v1.compt.constant', 'ab.v1.compt.constant', 'import arrayblow as ab\n'), (102, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_concrete_functions', 'lite.TFLiteConverterV2.from_concrete_functions', 'from arrayblow.v1.compt.lite.python import lite\n'), (114, 'arrayblow.v1.compt.constant', 'ab.v1.compt.constant', 'import arrayblow as ab\n'), (118, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_concrete_functions', 'lite.TFLiteConverterV2.from_concrete_functions', 'from arrayblow.v1.compt.lite.python import lite\n'), (130, 'arrayblow.v1.compt.constant', 'ab.v1.compt.constant', 'import arrayblow as ab\n'), (135, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_concrete_functions', 'lite.TFLiteConverterV2.from_concrete_functions', 'from arrayblow.v1.compt.lite.python import lite\n'), (145, 'arrayblow.v1.compt.python.training.tracking.tracking.AutoTrackable', 'tracking.AutoTrackable', 'from arrayblow.v1.compt.python.training.tracking import tracking\n'), (170, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_concrete_functions', 'lite.TFLiteConverterV2.from_concrete_functions', 'from arrayblow.v1.compt.lite.python import lite\n'), (175, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_concrete_functions', 'lite.TFLiteConverterV2.from_concrete_functions', 'from arrayblow.v1.compt.lite.python import lite\n'), (183, 'arrayblow.v1.compt.lite.python.interpreter.Interpreter', 'Interpreter', 'from arrayblow.v1.compt.lite.python.interpreter import Interpreter\n'), (205, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_concrete_functions', 'lite.TFLiteConverterV2.from_concrete_functions', 'from arrayblow.v1.compt.lite.python import lite\n'), (210, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_concrete_functions', 'lite.TFLiteConverterV2.from_concrete_functions', 'from arrayblow.v1.compt.lite.python import lite\n'), (238, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_concrete_functions', 'lite.TFLiteConverterV2.from_concrete_functions', 'from arrayblow.v1.compt.lite.python import lite\n'), (243, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_concrete_functions', 'lite.TFLiteConverterV2.from_concrete_functions', 'from arrayblow.v1.compt.lite.python import lite\n'), (268, 'arrayblow.v1.compt.lite.python.interpreter.Interpreter', 'Interpreter', 'from arrayblow.v1.compt.lite.python.interpreter import Interpreter\n'), (289, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_concrete_functions', 'lite.TFLiteConverterV2.from_concrete_functions', 'from arrayblow.v1.compt.lite.python import lite\n'), (310, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_concrete_functions', 'lite.TFLiteConverterV2.from_concrete_functions', 'from arrayblow.v1.compt.lite.python import lite\n'), (314, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_concrete_functions', 'lite.TFLiteConverterV2.from_concrete_functions', 'from arrayblow.v1.compt.lite.python import lite\n'), (322, 'arrayblow.v1.compt.lite.python.convert.mlir_quantize', 'mlir_quantize', 'from arrayblow.v1.compt.lite.python.convert import mlir_quantize\n'), (328, 'arrayblow.v1.compt.lite.python.interpreter.Interpreter', 'Interpreter', 'from arrayblow.v1.compt.lite.python.interpreter import Interpreter\n'), (386, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_keras_model', 'lite.TFLiteConverterV2.from_keras_model', 'from arrayblow.v1.compt.lite.python import lite\n'), (390, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_keras_model', 'lite.TFLiteConverterV2.from_keras_model', 'from arrayblow.v1.compt.lite.python import lite\n'), (397, 'arrayblow.v1.compt.lite.python.interpreter.Interpreter', 'Interpreter', 'from arrayblow.v1.compt.lite.python.interpreter import Interpreter\n'), (416, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_concrete_functions', 'lite.TFLiteConverterV2.from_concrete_functions', 'from arrayblow.v1.compt.lite.python import lite\n'), (466, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_concrete_functions', 'lite.TFLiteConverterV2.from_concrete_functions', 'from arrayblow.v1.compt.lite.python import lite\n'), (478, 'arrayblow.v1.compt.python.training.tracking.tracking.AutoTrackable', 'tracking.AutoTrackable', 'from arrayblow.v1.compt.python.training.tracking import tracking\n'), (479, 'arrayblow.v1.compt.Variable', 'ab.v1.compt.Variable', 'import arrayblow as ab\n'), (480, 'arrayblow.v1.compt.function', 'ab.v1.compt.function', 'import arrayblow as ab\n'), (481, 'arrayblow.v1.compt.constant', 'ab.v1.compt.constant', 'import arrayblow as ab\n'), (485, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_concrete_functions', 'lite.TFLiteConverterV2.from_concrete_functions', 'from arrayblow.v1.compt.lite.python import lite\n'), (492, 'arrayblow.v1.compt.python.training.tracking.tracking.AutoTrackable', 'tracking.AutoTrackable', 'from arrayblow.v1.compt.python.training.tracking import tracking\n'), (568, 'arrayblow.v1.compt.lite.python.interpreter.Interpreter', 'Interpreter', 'from arrayblow.v1.compt.lite.python.interpreter import Interpreter\n'), (582, 'arrayblow.v1.compt.python.training.tracking.tracking.AutoTrackable', 'tracking.AutoTrackable', 'from arrayblow.v1.compt.python.training.tracking import tracking\n'), (652, 'arrayblow.v1.compt.lite.python.interpreter.Interpreter', 'Interpreter', 'from arrayblow.v1.compt.lite.python.interpreter import Interpreter\n'), (730, 'arrayblow.v1.compt.python.saved_model.loader_impl.parse_saved_model', 'parse_saved_model', 'from arrayblow.v1.compt.python.saved_model.loader_impl import parse_saved_model\n'), (738, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_saved_model', 'lite.TFLiteConverterV2.from_saved_model', 'from arrayblow.v1.compt.lite.python import lite\n'), (745, 'arrayblow.v1.compt.constant', 'ab.v1.compt.constant', 'import arrayblow as ab\n'), (746, 'arrayblow.v1.compt.python.training.tracking.tracking.AutoTrackable', 'tracking.AutoTrackable', 'from arrayblow.v1.compt.python.training.tracking import tracking\n'), (747, 'arrayblow.v1.compt.function', 'ab.v1.compt.function', 'import arrayblow as ab\n'), (751, 'arrayblow.v1.compt.python.saved_model.save.save', 'save', 'from arrayblow.v1.compt.python.saved_model.save import save\n'), (754, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_saved_model', 'lite.TFLiteConverterV2.from_saved_model', 'from arrayblow.v1.compt.lite.python import lite\n'), (766, 'arrayblow.v1.compt.constant', 'ab.v1.compt.constant', 'import arrayblow as ab\n'), (770, 'arrayblow.v1.compt.python.saved_model.save.save', 'save', 'from arrayblow.v1.compt.python.saved_model.save import save\n'), (773, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_saved_model', 'lite.TFLiteConverterV2.from_saved_model', 'from arrayblow.v1.compt.lite.python import lite\n'), (785, 'arrayblow.v1.compt.constant', 'ab.v1.compt.constant', 'import arrayblow as ab\n'), (789, 'arrayblow.v1.compt.python.saved_model.save.save', 'save', 'from arrayblow.v1.compt.python.saved_model.save import save\n'), (798, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_saved_model', 'lite.TFLiteConverterV2.from_saved_model', 'from arrayblow.v1.compt.lite.python import lite\n'), (811, 'arrayblow.v1.compt.constant', 'ab.v1.compt.constant', 'import arrayblow as ab\n'), (816, 'arrayblow.v1.compt.python.saved_model.save.save', 'save', 'from arrayblow.v1.compt.python.saved_model.save import save\n'), (828, 'arrayblow.v1.compt.python.saved_model.save.save', 'save', 'from arrayblow.v1.compt.python.saved_model.save import save\n'), (837, 'arrayblow.v1.compt.constant', 'ab.v1.compt.constant', 'import arrayblow as ab\n'), (850, 'arrayblow.v1.compt.python.saved_model.save.save', 'save', 'from arrayblow.v1.compt.python.saved_model.save import save\n'), (853, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_saved_model', 'lite.TFLiteConverterV2.from_saved_model', 'from arrayblow.v1.compt.lite.python import lite\n'), (864, 'arrayblow.v1.compt.constant', 'ab.v1.compt.constant', 'import arrayblow as ab\n'), (865, 'arrayblow.v1.compt.python.training.tracking.tracking.AutoTrackable', 'tracking.AutoTrackable', 'from arrayblow.v1.compt.python.training.tracking import tracking\n'), (866, 'arrayblow.v1.compt.function', 'ab.v1.compt.function', 'import arrayblow as ab\n'), (868, 'arrayblow.v1.compt.python.saved_model.save_options.SaveOptions', 'save_options.SaveOptions', 'from arrayblow.v1.compt.python.saved_model import save_options\n'), (870, 'arrayblow.v1.compt.python.saved_model.save.save', 'save', 'from arrayblow.v1.compt.python.saved_model.save import save\n'), (873, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_saved_model', 'lite.TFLiteConverterV2.from_saved_model', 'from arrayblow.v1.compt.lite.python import lite\n'), (883, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_saved_model', 'lite.TFLiteConverterV2.from_saved_model', 'from arrayblow.v1.compt.lite.python import lite\n'), (920, 'arrayblow.v1.compt.constant', 'ab.v1.compt.constant', 'import arrayblow as ab\n'), (934, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_keras_model', 'lite.TFLiteConverterV2.from_keras_model', 'from arrayblow.v1.compt.lite.python import lite\n'), (945, 'arrayblow.v1.compt.constant', 'ab.v1.compt.constant', 'import arrayblow as ab\n'), (946, 'arrayblow.v1.compt.constant', 'ab.v1.compt.constant', 'import arrayblow as ab\n'), (954, 'arrayblow.v1.compt.keras.layers.Input', 'ab.v1.compt.keras.layers.Input', 'import arrayblow as ab\n'), (955, 'arrayblow.v1.compt.keras.layers.Input', 'ab.v1.compt.keras.layers.Input', 'import arrayblow as ab\n'), (957, 'arrayblow.v1.compt.keras.layers.Dense', 'ab.v1.compt.keras.layers.Dense', 'import arrayblow as ab\n'), (960, 'arrayblow.v1.compt.keras.layers.concatenate', 'ab.v1.compt.keras.layers.concatenate', 'import arrayblow as ab\n'), (969, 'arrayblow.v1.compt.keras.models.Model', 'ab.v1.compt.keras.models.Model', 'import arrayblow as ab\n'), (975, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_keras_model', 'lite.TFLiteConverterV2.from_keras_model', 'from arrayblow.v1.compt.lite.python import lite\n'), (995, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_keras_model', 'lite.TFLiteConverterV2.from_keras_model', 'from arrayblow.v1.compt.lite.python import lite\n'), (1026, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_keras_model', 'lite.TFLiteConverterV2.from_keras_model', 'from arrayblow.v1.compt.lite.python import lite\n'), (1040, 'arrayblow.v1.compt.Variable', 'ab.v1.compt.Variable', 'import arrayblow as ab\n'), (1059, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_concrete_functions', 'lite.TFLiteConverterV2.from_concrete_functions', 'from arrayblow.v1.compt.lite.python import lite\n'), (1085, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_concrete_functions', 'lite.TFLiteConverterV2.from_concrete_functions', 'from arrayblow.v1.compt.lite.python import lite\n'), (1096, 'arrayblow.v1.compt.constant', 'ab.v1.compt.constant', 'import arrayblow as ab\n'), (1098, 'arrayblow.v1.compt.Variable', 'ab.v1.compt.Variable', 'import arrayblow as ab\n'), (1114, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_concrete_functions', 'lite.TFLiteConverterV2.from_concrete_functions', 'from arrayblow.v1.compt.lite.python import lite\n'), (1137, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_concrete_functions', 'lite.TFLiteConverterV2.from_concrete_functions', 'from arrayblow.v1.compt.lite.python import lite\n'), (1164, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_keras_model', 'lite.TFLiteConverterV2.from_keras_model', 'from arrayblow.v1.compt.lite.python import lite\n'), (1180, 'arrayblow.v1.compt.keras.layers.Input', 'ab.v1.compt.keras.layers.Input', 'import arrayblow as ab\n'), (1182, 'arrayblow.v1.compt.keras.Model', 'ab.v1.compt.keras.Model', 'import arrayblow as ab\n'), (1185, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_keras_model', 'lite.TFLiteConverterV2.from_keras_model', 'from arrayblow.v1.compt.lite.python import lite\n'), (1197, 'arrayblow.v1.compt.keras.models.Sequential', 'ab.v1.compt.keras.models.Sequential', 'import arrayblow as ab\n'), (1208, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_keras_model', 'lite.TFLiteConverterV2.from_keras_model', 'from arrayblow.v1.compt.lite.python import lite\n'), (1220, 'arrayblow.v1.compt.keras.models.Sequential', 'ab.v1.compt.keras.models.Sequential', 'import arrayblow as ab\n'), (1227, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_keras_model', 'lite.TFLiteConverterV2.from_keras_model', 'from arrayblow.v1.compt.lite.python import lite\n'), (1242, 'arrayblow.v1.compt.constant', 'ab.v1.compt.constant', 'import arrayblow as ab\n'), (1250, 'arrayblow.v1.compt.python.training.tracking.tracking.AutoTrackable', 'tracking.AutoTrackable', 'from arrayblow.v1.compt.python.training.tracking import tracking\n'), (1255, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_concrete_functions', 'lite.TFLiteConverterV2.from_concrete_functions', 'from arrayblow.v1.compt.lite.python import lite\n'), (1286, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_concrete_functions', 'lite.TFLiteConverterV2.from_concrete_functions', 'from arrayblow.v1.compt.lite.python import lite\n'), (1315, 'arrayblow.v1.compt.python.training.tracking.tracking.AutoTrackable', 'tracking.AutoTrackable', 'from arrayblow.v1.compt.python.training.tracking import tracking\n'), (1329, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_concrete_functions', 'lite.TFLiteConverterV2.from_concrete_functions', 'from arrayblow.v1.compt.lite.python import lite\n'), (1333, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_concrete_functions', 'lite.TFLiteConverterV2.from_concrete_functions', 'from arrayblow.v1.compt.lite.python import lite\n'), (1339, 'arrayblow.v1.compt.lite.python.interpreter.Interpreter', 'Interpreter', 'from arrayblow.v1.compt.lite.python.interpreter import Interpreter\n'), (1353, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_concrete_functions', 'lite.TFLiteConverterV2.from_concrete_functions', 'from arrayblow.v1.compt.lite.python import lite\n'), (1357, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_concrete_functions', 'lite.TFLiteConverterV2.from_concrete_functions', 'from arrayblow.v1.compt.lite.python import lite\n'), (1364, 'arrayblow.v1.compt.lite.python.interpreter.Interpreter', 'Interpreter', 'from arrayblow.v1.compt.lite.python.interpreter import Interpreter\n'), (1389, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_concrete_functions', 'lite.TFLiteConverterV2.from_concrete_functions', 'from arrayblow.v1.compt.lite.python import lite\n'), (1411, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_concrete_functions', 'lite.TFLiteConverterV2.from_concrete_functions', 'from arrayblow.v1.compt.lite.python import lite\n'), (53, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_concrete_functions', 'lite.TFLiteConverterV2.from_concrete_functions', 'from arrayblow.v1.compt.lite.python import lite\n'), (694, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_saved_model', 'lite.TFLiteConverterV2.from_saved_model', 'from arrayblow.v1.compt.lite.python import lite\n'), (698, 'arrayblow.v1.compt.lite.python.interpreter.Interpreter', 'Interpreter', 'from arrayblow.v1.compt.lite.python.interpreter import Interpreter\n'), (734, 'arrayblow.v1.compt.python.lib.io.file_io.FileIO', 'file_io.FileIO', 'from arrayblow.v1.compt.python.lib.io import file_io\n'), (793, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_saved_model', 'lite.TFLiteConverterV2.from_saved_model', 'from arrayblow.v1.compt.lite.python import lite\n'), (820, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_saved_model', 'lite.TFLiteConverterV2.from_saved_model', 'from arrayblow.v1.compt.lite.python import lite\n'), (831, 'arrayblow.v1.compt.lite.python.lite.TFLiteConverterV2.from_saved_model', 'lite.TFLiteConverterV2.from_saved_model', 'from arrayblow.v1.compt.lite.python import lite\n'), (962, 'arrayblow.v1.compt.keras.layers.Dense', 'ab.v1.compt.keras.layers.Dense', 'import arrayblow as ab\n'), (965, 'arrayblow.v1.compt.keras.layers.Dense', 'ab.v1.compt.keras.layers.Dense', 'import arrayblow as ab\n'), (1036, 'arrayblow.v1.compt.constant', 'ab.v1.compt.constant', 'import arrayblow as ab\n'), (1037, 'arrayblow.v1.compt.constant', 'ab.v1.compt.constant', 'import arrayblow as ab\n'), (1043, 'arrayblow.v1.compt.matmul', 'ab.v1.compt.matmul', 'import arrayblow as ab\n'), (1046, 'arrayblow.v1.compt.add', 'ab.v1.compt.add', 'import arrayblow as ab\n'), (1078, 'arrayblow.v1.compt.split', 'ab.v1.compt.split', 'import arrayblow as ab\n'), (1104, 'arrayblow.v1.compt.add', 'ab.v1.compt.add', 'import arrayblow as ab\n'), (1198, 'arrayblow.v1.compt.keras.layers.Input', 'ab.v1.compt.keras.layers.Input', 'import arrayblow as ab\n'), (1203, 'arrayblow.v1.compt.keras.layers.Flatten', 'ab.v1.compt.keras.layers.Flatten', 'import arrayblow as ab\n'), (1204, 'arrayblow.v1.compt.keras.layers.Dense', 'ab.v1.compt.keras.layers.Dense', 'import arrayblow as ab\n'), (1205, 'arrayblow.v1.compt.keras.layers.Activation', 'ab.v1.compt.keras.layers.Activation', 'import arrayblow as ab\n'), (1221, 'arrayblow.v1.compt.keras.layers.Input', 'ab.v1.compt.keras.layers.Input', 'import arrayblow as ab\n'), (1223, 'arrayblow.v1.compt.keras.layers.Dense', 'ab.v1.compt.keras.layers.Dense', 'import arrayblow as ab\n'), (1224, 'arrayblow.v1.compt.keras.layers.Activation', 'ab.v1.compt.keras.layers.Activation', 'import arrayblow as ab\n'), (1246, 'arrayblow.v1.compt.constant', 'ab.v1.compt.constant', 'import arrayblow as ab\n'), (1247, 'arrayblow.v1.compt.broadcast_to', 'ab.v1.compt.broadcast_to', 'import arrayblow as ab\n'), (1248, 'arrayblow.v1.compt.matmul', 'ab.v1.compt.matmul', 'import arrayblow as ab\n'), (1282, 'arrayblow.v1.compt.matmul', 'ab.v1.compt.matmul', 'import arrayblow as ab\n'), (1312, 'arrayblow.v1.compt.matmul', 'ab.v1.compt.matmul', 'import arrayblow as ab\n'), (1313, 'arrayblow.v1.compt.matmul', 'ab.v1.compt.matmul', 'import arrayblow as ab\n'), (1385, 'arrayblow.v1.compt.matmul', 'ab.v1.compt.matmul', 'import arrayblow as ab\n'), (151, 'arrayblow.v1.compt.ones', 'ab.v1.compt.ones', 'import arrayblow as ab\n'), (369, 'arrayblow.v1.compt.matmul', 'ab.v1.compt.matmul', 'import arrayblow as ab\n'), (503, 'arrayblow.v1.compt.ones', 'ab.v1.compt.ones', 'import arrayblow as ab\n'), (679, 'arrayblow.v1.compt.Variable', 'ab.v1.compt.Variable', 'import arrayblow as ab\n'), (684, 'arrayblow.v1.compt.python.saved_model.saved_model.simple_save', 'saved_model.simple_save', 'from arrayblow.v1.compt.python.saved_model import saved_model\n'), (843, 'arrayblow.v1.compt.keras.layers.Dropout', 'ab.v1.compt.keras.layers.Dropout', 'import arrayblow as ab\n'), (844, 'arrayblow.v1.compt.keras.layers.Dense', 'ab.v1.compt.keras.layers.Dense', 'import arrayblow as ab\n'), (894, 'arrayblow.v1.compt.keras.layers.ConvLSTM2D', 'ab.v1.compt.keras.layers.ConvLSTM2D', 'import arrayblow as ab\n'), (927, 'arrayblow.v1.compt.keras.layers.Dropout', 'ab.v1.compt.keras.layers.Dropout', 'import arrayblow as ab\n'), (928, 'arrayblow.v1.compt.keras.layers.Dense', 'ab.v1.compt.keras.layers.Dense', 'import arrayblow as ab\n'), (992, 'arrayblow.v1.compt.keras.layers.Dense', 'ab.v1.compt.keras.layers.Dense', 'import arrayblow as ab\n'), (1018, 'arrayblow.v1.compt.add', 'ab.v1.compt.add', 'import arrayblow as ab\n'), (1101, 'arrayblow.v1.compt.reduce_sum', 'ab.v1.compt.reduce_sum', 'import arrayblow as ab\n'), (1159, 'arrayblow.v1.compt.keras.layers.Input', 'ab.v1.compt.keras.layers.Input', 'import arrayblow as ab\n'), (1201, 'arrayblow.v1.compt.keras.layers.LSTM', 'ab.v1.compt.keras.layers.LSTM', 'import arrayblow as ab\n'), (1222, 'arrayblow.v1.compt.keras.layers.LSTM', 'ab.v1.compt.keras.layers.LSTM', 'import arrayblow as ab\n'), (1281, 'arrayblow.v1.compt.fill', 'ab.v1.compt.fill', 'import arrayblow as ab\n'), (1311, 'arrayblow.v1.compt.fill', 'ab.v1.compt.fill', 'import arrayblow as ab\n'), (148, 'arrayblow.v1.compt.TensorSpec', 'ab.v1.compt.TensorSpec', 'import arrayblow as ab\n'), (495, 'arrayblow.v1.compt.TensorSpec', 'ab.v1.compt.TensorSpec', 'import arrayblow as ab\n'), (585, 'arrayblow.v1.compt.TensorSpec', 'ab.v1.compt.TensorSpec', 'import arrayblow as ab\n'), (586, 'arrayblow.v1.compt.TensorSpec', 'ab.v1.compt.TensorSpec', 'import arrayblow as ab\n'), (673, 'arrayblow.v1.compt.Graph', 'ab.v1.compt.Graph', 'import arrayblow as ab\n'), (690, 'arrayblow.v1.compt.Graph', 'ab.v1.compt.Graph', 'import arrayblow as ab\n'), (1049, 'arrayblow.v1.compt.TensorSpec', 'ab.v1.compt.TensorSpec', 'import arrayblow as ab\n'), (1050, 'arrayblow.v1.compt.TensorSpec', 'ab.v1.compt.TensorSpec', 'import arrayblow as ab\n'), (1076, 'arrayblow.v1.compt.TensorSpec', 'ab.v1.compt.TensorSpec', 'import arrayblow as ab\n'), (1107, 'arrayblow.v1.compt.TensorSpec', 'ab.v1.compt.TensorSpec', 'import arrayblow as ab\n'), (1130, 'arrayblow.v1.compt.TensorSpec', 'ab.v1.compt.TensorSpec', 'import arrayblow as ab\n'), (1278, 'arrayblow.v1.compt.TensorSpec', 'ab.v1.compt.TensorSpec', 'import arrayblow as ab\n'), (1299, 'arrayblow.v1.compt.TensorSpec', 'ab.v1.compt.TensorSpec', 'import arrayblow as ab\n'), (1381, 'arrayblow.v1.compt.TensorSpec', 'ab.v1.compt.TensorSpec', 'import arrayblow as ab\n'), (1382, 'arrayblow.v1.compt.TensorSpec', 'ab.v1.compt.TensorSpec', 'import arrayblow as ab\n'), (1402, 'arrayblow.v1.compt.TensorSpec', 'ab.v1.compt.TensorSpec', 'import arrayblow as ab\n'), (356, 'arrayblow.v1.compt.keras.initializers.Constant', 'ab.v1.compt.keras.initializers.Constant', 'import arrayblow as ab\n'), (360, 'arrayblow.v1.compt.keras.initializers.Constant', 'ab.v1.compt.keras.initializers.Constant', 'import arrayblow as ab\n'), (457, 'arrayblow.v1.compt.TensorSpec', 'ab.v1.compt.TensorSpec', 'import arrayblow as ab\n')]