class_docstr: Represents Operation in MIL.
  
  # Properties
  name (str):
      The name of the operation
  
  input_types (InputSpec, class attr):
      Read-only named input types from all subclasses. Input types are used
      to validate `inputs`.
  
  inputs [_input_vars] (dict of str --> Var):
      An Operation (subclass of Operation) only has access to input Var,
      which is already validated against `input_spec`.
  
  outputs [_output_vars] (list of Var):
      List of output var based on type inference. Read-only
class_docstr_tok: ["Represents","Operation","in","MIL",".","#","Properties","name","(","str",")",":","The","name","of","the","operation","input_types","(","InputSpec",",","class","attr",")",":","Read-only","named","input","types","from","all","subclasses",".","Input","types","are","used","to","validate","`","inputs","`",".","inputs","[","_input_vars","]","(","dict","of","str","--",">","Var",")",":","An","Operation","(","subclass","of","Operation",")","only","has","access","to","input","Var",",","which","is","already","validated","against","`","input_spec","`",".","outputs","[","_output_vars","]","(","list","of","Var",")",":","List","of","output","var","based","on","type","inference",".","Read-only"]
docstr: Perform type inference and auto_val computation based on new input Vars
  in kwargs. If self._output_vars is None then we generate _output_vars;
  otherwise no new Var is created, but type inference result is verified
  against existing _output_vars, if overwrite_output is False.
  
  If overwrite_output is True, then the type inference result overwrites the
  existing _output_vars
docstr_tok: ["Perform","type","inference","and","auto_val","computation","based","on","new","input","Vars","in","kwargs",".","If","self._output_vars","is","None","then","we","generate","_output_vars",";","otherwise","no","new","Var","is","created",",","but","type","inference","result","is","verified","against","existing","_output_vars",",","if","overwrite_output","is","False",".","If","overwrite_output","is","True",",","then","the","type","inference","result","overwrites","the","existing","_output_vars"]
code: def type_value_inference(self, overwrite_output=False):
      """
      Perform type inference and auto_val computation based on new input Vars
      in kwargs. If self._output_vars is None then we generate _output_vars;
      otherwise no new Var is created, but type inference result is verified
      against existing _output_vars, if overwrite_output is False.
  
      If overwrite_output is True, then the type inference result overwrites the
      existing _output_vars
      """
      output_types = self.type_inference()
      if not isinstance(output_types, tuple):
          output_types = (output_types,)
      output_vals = self._auto_val(output_types)
      try:
          output_names = self.output_names()
          if not isinstance(output_names, tuple):
              output_names = (output_names,)
      except NotImplementedError as e:
          if len(output_types) > 1:
              output_names = tuple(
                  str(i) for i, _ in enumerate(output_types)
              )
          else:
              output_names = ("",)  # output name same as op name.
  
      # Combine (output_names, output_types, output_vals) to create output
      # Vars.
      if self._output_vars is None:
          self._output_vars = []
          for i, (n, sym_type, sym_val) in enumerate(
              zip(output_names, output_types, output_vals)
          ):
              name = self.name + ":" + n if n != "" else self.name
              if types.is_list(sym_type):
                  new_var = ListVar(
                      name,
                      elem_type=sym_type.T[0],
                      init_length=sym_type.T[1],
                      dynamic_length=sym_type.T[2],
                      op=self,
                      op_output_idx=i,
                  )
              else:
                  new_var = Var(
                      name, sym_type, sym_val, op=self, op_output_idx=i
                  )
              self._output_vars.append(new_var)
      else:
          # Check new inference result against existing self._output_vars.
          for i, (n, sym_type, sym_val) in enumerate(
              zip(output_names, output_types, output_vals)
          ):
              out_var = self._output_vars[i]
              # Check type inference
              if overwrite_output:
                  out_var._sym_type = sym_type
              elif not _check_is_compatible_type(
                  sym_type, out_var.sym_type
              ):
                  msg = "Output Var {} in op {} type changes with new input Vars"
                  raise ValueError(msg.format(out_var.name, self.name))
  
              # Check value inference
              if overwrite_output:
                  out_var._sym_val = sym_val
  
              if sym_val is not None and out_var.sym_val is not None:
                  if np.any(sym_val.val != out_var.sym_val):
                      if overwrite_output:
                          out_var._sym_val = sym_val
                      else:
                          msg = "value_inference differs for var {} in op {}"
                          if not _is_compatible_symbolic_array(
                              sym_val.val, out_var.sym_val
                          ):
                              raise ValueError(
                                  msg.format(out_var.name, self.name)
                              )
  
imports: import logging
  import numpy
  import six
  from coremltools.converters.mil.mil import types
  from coremltools.converters.mil.mil.types.symbolic import is_symbolic, any_symbolic
  from .None import SPACES
  from .block import curr_block, _check_is_compatible_type
  from .input_type import TupleInputType
  from .var import Var, InternalVar, ListVar
label_desc: Use image node_id 4 for calling the Operation obj's underlying member method code with example usage: obj.type_value_inference(overwrite_output) without return types