class_docstr: Detect if ``onehot (axis=-1, on_value=1, off_value=0)`` is followed by a ``matmul`` op (no bias).
  If so, they can be replaced by a ``gather`` op.
  
  .. code-block::
  
      Input:
          %2 = one_hot(%1, on_value=1, off_value=0, axis=-1)
          %3 = const() # rank 2
          %4  = matmul(%2, %3)
  
      Output:
          %4 = gather(%3, %2, axis=0)
class_docstr_tok: ["Detect","if","``","onehot","(","axis=-1",",","on_value=1",",","off_value=0",")","``","is","followed","by","a","``","matmul","``","op","(","no","bias",")",".","If","so",",","they","can","be","replaced","by","a","``","gather","``","op",".","..","code-block",":",":","Input",":","%","2","=","one_hot","(","%","1",",","on_value=1",",","off_value=0",",","axis=-1",")","%","3","=","const","(",")","#","rank","2","%","4","=","matmul","(","%","2",",","%","3",")","Output",":","%","4","=","gather","(","%","3",",","%","2",",","axis=0",")"]
code: def _try_to_transform(onehot_op, block):
      root_var = onehot_op.indices
  
      # check that the output of the onehot op is not a block output
      if onehot_op.outputs[0] in block.outputs:
          return False
  
      # check that onehot op has axis=-1, on_value=1 and off_value=0
      # and constant one_hot_vector_size
      axis = onehot_op.axis.val
      if axis is None:
          return False
      if onehot_op.indices.shape is None:
          return False
      rank = len(onehot_op.indices.shape)
      if axis >= 0:
          axis -= rank
      if axis != -1:
          return False
      if not _check_var_scalar_value(onehot_op.on_value, 1):
          return False
      if not _check_var_scalar_value(onehot_op.off_value, 0):
          return False
      if onehot_op.one_hot_vector_size.val is None:
          return False
  
      # checks for the following matmul op
      if not _check_child_op_type(onehot_op, "matmul"):
          return False
      matmul_op = list(onehot_op.outputs[0].child_ops)[0]
      if matmul_op.x != onehot_op.outputs[0]:
          return False
      if matmul_op.transpose_x.val or matmul_op.transpose_y.val:
          return False
      W_var = matmul_op.y
      if W_var.val is None:
          return False
      if len(W_var.val.shape) != 2:
          return False
  
      # remove onehot and matmul and replace with gather op
      if is_current_opset_version_compatible_with(
          AvailableTarget.iOS17
      ):
          # IOS17 `gather` requires non-negative indices.
          root_var = mb.select(
              cond=mb.greater_equal(
                  x=root_var, y=0, before_op=matmul_op
              ),
              a=root_var,
              b=mb.add(
                  x=root_var,
                  y=value_at(
                      mb.shape(x=W_var, before_op=matmul_op),
                      0,
                      before_op=matmul_op,
                  ),
                  before_op=matmul_op,
              ),
              before_op=matmul_op,
          )
      x = mb.gather(
          x=W_var,
          indices=root_var,
          axis=0,
          name=matmul_op.outputs[0].name,
          before_op=matmul_op,
      )
  
      matmul_op.enclosing_block.replace_uses_of_var_after_op(
          anchor_op=matmul_op, old_var=matmul_op.outputs[0], new_var=x
      )
      # Remove all the ops at once
      block.remove_ops([onehot_op, matmul_op])
      return True
  
imports: import numpy
  from coremltools.converters.mil._deployment_compatibility import AvailableTarget
  from coremltools.converters.mil.frontend._utils import value_at
  from coremltools.converters.mil.mil import Builder
  from coremltools.converters.mil.mil.block import is_current_opset_version_compatible_with
  from coremltools.converters.mil.mil.passes.graph_pass import AbstractGraphPass
  from coremltools.converters.mil.mil.passes.helper import _check_child_op_type, _check_var_scalar_value, block_context_manager
  from coremltools.converters.mil.mil.passes.pass_registry import register_pass
  from coremltools.converters.mil.mil.types.symbolic import any_symbolic
label_desc: Use image node_id 2 for calling the fuse_onehot_matmul_to_gather obj's underlying member method code with example usage: obj._try_to_transform(onehot_op, block) and returns: True, False, False, False, False, False, False, False, False, False, False, False, False