docstr: tfssa: TensorFlow IR.
  inputs: list of TensorType or ImageType, optional, defaults to None.
  outputs: list[ct.InputType] or None
      list of either ct.TensorTypes or ct.ImageTypes (both of which are child classes of InputType)
      This is the value of the "outputs" argument, passed on by the user in "coremltools.convert" API.
  opset_version: An int represents the Core ML opset version.
  use_default_fp16_io (optional): bool. Defaults to False.
      When minimum_deployment_target set >= ct.target.iOS16 (the same as ct.target.macOS13),
      and the compute precision set to fp16, this flag is True.
      When True, fp32 i/o defaults to fp16.
docstr_tok: ["tfssa",":","TensorFlow","IR",".","inputs",":","list","of","TensorType","or","ImageType",",","optional",",","defaults","to","None",".","outputs",":","list","[","ct.InputType","]","or","None","list","of","either","ct.TensorTypes","or","ct.ImageTypes","(","both","of","which","are","child","classes","of","InputType",")","This","is","the","value","of","the","``","outputs","''","argument",",","passed","on","by","the","user","in","``","coremltools.convert","''","API",".","opset_version",":","An","int","represents","the","Core","ML","opset","version",".","use_default_fp16_io","(","optional",")",":","bool",".","Defaults","to","False",".","When","minimum_deployment_target","set",">","=","ct.target.iOS16","(","the","same","as","ct.target.macOS13",")",",","and","the","compute","precision","set","to","fp16",",","this","flag","is","True",".","When","True",",","fp32","i\/o","defaults","to","fp16","."]
code: def __init__(
      self,
      tfssa,
      inputs=None,
      outputs=None,
      opset_version=None,
      use_default_fp16_io=False,
  ):
      """
      tfssa: TensorFlow IR.
      inputs: list of TensorType or ImageType, optional, defaults to None.
      outputs: list[ct.InputType] or None
          list of either ct.TensorTypes or ct.ImageTypes (both of which are child classes of InputType)
          This is the value of the "outputs" argument, passed on by the user in "coremltools.convert" API.
      opset_version: An int represents the Core ML opset version.
      use_default_fp16_io (optional): bool. Defaults to False.
          When minimum_deployment_target set >= ct.target.iOS16 (the same as ct.target.macOS13),
          and the compute precision set to fp16, this flag is True.
          When True, fp32 i/o defaults to fp16.
      """
      self.tfssa = tfssa
      self.global_type = {}
      self.inputs = None
      self.main_output_types = outputs
      self.opset_version = (
          _target(opset_version) if opset_version is not None else None
      )
      self.use_default_fp16_io = use_default_fp16_io
      output_names = get_output_names(outputs)
  
      main_func = tfssa.functions["main"]
      graph = main_func.graph
  
      # Get inputs dtype and shape defined in the tf graph
      tf_placeholder_names = [
          n for n in graph if graph[n].op == "Placeholder"
      ]
      tf_input_dtype = {}
      tf_input_shape = {}
      image_input_names = []
      inputs_with_defined_shape = []
  
      if inputs is not None:
          # Special case: if there's only 1 input and 1 placeholder, we match them.
          if len(tf_placeholder_names) == 1 and len(inputs) == 1:
              if inputs[0].name is None:
                  inputs[0].name = tf_placeholder_names[0]
          for val in inputs:
              if isinstance(val, ImageType):
                  image_input_names.append(val.name)
              if val.shape is not None:
                  inputs_with_defined_shape.append(val.name)
  
      for inp in main_func.inputs:
          node = graph[inp]
  
          # Parse dtype from the tf graph
          dtype = node.attr["dtype"]
          if (
              use_default_fp16_io
              and dtype == types.fp32
              and inp not in image_input_names
          ):
              dtype = types.fp16
  
          tf_input_dtype[inp] = dtype
  
          # Parse shape from the tf graph
          if inp not in inputs_with_defined_shape:
              shape = self._get_placeholder_shape_from_tf_graph(
                  tfgraph=graph, name=inp
              )
              shape = [
                  get_new_symbol() if s is None or s == -1 else s
                  for s in shape
              ]
              shape = _get_shaping_class(shape)
              tf_input_shape[inp] = shape
  
      # Filter the inputs to only Placeholder names
      missing_placeholder_names = []
      if inputs is not None:
          # Check inputs format
          if not isinstance(inputs, (list, tuple)):
              raise ValueError(
                  "Type of inputs should be list or tuple, got {} instead.".format(
                      type(inputs)
                  )
              )
          if not all([isinstance(i, InputType) for i in inputs]):
              raise ValueError(
                  "Type of inputs should be list or tuple of TensorType or ImageType, got {} instead.".format(
                      [type(i) for i in inputs]
                  )
              )
  
          for inp in inputs:
              # Check inputs existence
              if inp.name is None:
                  raise ValueError(
                      "Multiple inputs are found in graph, but no input name was provided"
                  )
              if inp.name not in tf_placeholder_names:
                  raise ValueError(
                      "Input ({}) provided is not found in given tensorflow graph. Placeholders in graph are: {}".format(
                          inp.name, tf_placeholder_names
                      )
                  )
              # We fill in shapes and dtypes for user-specified input that doesn't set
              if inp.shape is None:
                  inp.shape = tf_input_shape[inp.name]
              if inp.dtype is None:
                  inp.dtype = tf_input_dtype[inp.name]
  
          # Extract placeholders that users didn't specify.
          user_input_names = [inp.name for inp in inputs]
          for name in tf_placeholder_names:
              if name not in user_input_names:
                  missing_placeholder_names.append(name)
      else:
          inputs = []
          missing_placeholder_names = tf_placeholder_names
  
      # name -> (shape, mil_type) mapping. shape has type list[int]
      added_inputs = {}
      for inp in main_func.inputs:
          if inp not in missing_placeholder_names:
              continue
          shape, dtype = tf_input_shape[inp], tf_input_dtype[inp]
          inputs.append(TensorType(name=inp, shape=shape, dtype=dtype))
          added_inputs[inp] = (shape, dtype)
  
      if len(added_inputs) > 0:
          logger.info(
              "Adding Input not specified by users: '{}'".format(
                  added_inputs
              )
          )
  
      for idx, inp in enumerate(inputs):
          # We set the default image format in TF as NHWC, since NHWC is used
          # for TF unless GPU is specified as device.
          if (
              isinstance(inp, ImageType)
              and inputs[idx].channel_first is None
          ):
              inputs[idx].channel_first = False
      self.inputs = tuple(inputs)
  
      for inputtype in self.inputs:
          if not isinstance(inputtype.shape, InputShape):
              continue
          if any(
              [isinstance(s, RangeDim) for s in inputtype.shape.shape]
          ):
              continue
          if inputtype.name not in graph:
              raise ValueError(
                  f"The input {inputtype.name} provided is not in graph."
              )
          node = graph[inputtype.name]
          shape = [
              -1 if is_symbolic(s) else s for s in inputtype.shape.shape
          ]
          node.attr["_output_shapes"] = [shape]  # list of length 1
  
      # infer outputs if not provided
      self._validate_outputs(tfssa, output_names)
      output_names = (
          main_func.outputs if output_names is None else output_names
      )
      output_names = (
          output_names
          if isinstance(output_names, (tuple, list))
          else [output_names]
      )
      output_names = [
          x if isinstance(x, str) else x.name for x in output_names
      ]
      self.output_names = output_names
  
      # We would like a stack so that we run conversion sequentially.
      self.graph_stack = self._get_stack(tfssa, root="main")
      self.context = TranscriptionContext()
  
imports: from coremltools import _logger
  from coremltools.converters._profile_utils import _profile
  from coremltools.converters.mil._deployment_compatibility import AvailableTarget
  from coremltools.converters.mil.input_types import ImageType, InputType, RangeDim
  from coremltools.converters.mil.input_types import Shape
  from coremltools.converters.mil.input_types import TensorType, _get_shaping_class
  from coremltools.converters.mil.mil import Builder
  from coremltools.converters.mil.mil import Function, Program, get_new_symbol, types
  from coremltools.converters.mil.mil.types.symbolic import is_symbolic
  from coremltools.converters.mil.mil.var import Var
  from .._utils import get_output_names
  from .basic_graph_ops import simple_topsort
  from .convert_utils import convert_graph
label_desc: Use image node_id 1 to create a new TFConverter object  with example: obj = TFConverter(tfssa, inputs, outputs, opset_version, use_default_fp16_io)