docstr: Input graph:
  input -> expand_dims -> conv2d -> squeeze -> out
  
  Output graph:
  input -> conv1d -> out
docstr_tok: ["Input","graph",":","input","-",">","expand_dims","-",">","conv2d","-",">","squeeze","-",">","out","Output","graph",":","input","-",">","conv1d","-",">","out"]
code: def test_conv1d_decomposition(
      self,
      backend,
      has_strides,
      pad_type,
      has_pad,
      has_dilations,
      has_bias,
  ):
      """
      Input graph:
      input -> expand_dims -> conv2d -> squeeze -> out
  
      Output graph:
      input -> conv1d -> out
      """
      N, L = 2, 8
      C_in, C_out = 3, 4
      K = 3
  
      conv_kwargs = {
          "weight": np.random.rand(C_out, C_in, K),
          "pad_type": pad_type,
      }
      if has_strides:
          conv_kwargs["strides"] = (2,)
      if has_pad:
          conv_kwargs["pad"] = (1, 1)
      if has_dilations:
          conv_kwargs["dilations"] = (2,)
      if has_bias:
          conv_kwargs["bias"] = np.random.rand(C_out)
  
      @mb.program(input_specs=[mb.TensorSpec(shape=(N, C_in, L))])
      def prog(x):
          y = mb.conv(x=x, **conv_kwargs)
          return y
  
      assert get_op_types_in_program(prog) == ["conv"]
  
      prev_prog, prev_block, block = apply_pass_and_basic_check(
          prog, "nn_backend::decompose_conv1d"
      )
      assert get_op_types_in_program(prog) == [
          "expand_dims",
          "expand_dims",
          "conv",
          "squeeze",
      ]
  
      prev_prog, prev_block, block = apply_pass_and_basic_check(
          prog, "common::const_elimination"
      )
      assert get_op_types_in_program(prog) == [
          "expand_dims",
          "conv",
          "squeeze",
      ]
  
      # infer output shape
      strides = conv_kwargs["strides"] if has_strides else (1,)
      pad = conv_kwargs["pad"] if has_pad else (0, 0)
      dilations = conv_kwargs["dilations"] if has_dilations else (1,)
      L_out = None
      if pad_type == "valid":
          L_out = (L - dilations[-1] * (K - 1) - 1) // strides[-1] + 1
      elif pad_type == "custom":
          L_out = (
              L + pad[-2] + pad[-1] - dilations[-1] * (K - 1) - 1
          ) // strides[-1] + 1
      elif pad_type == "same":
          L_out = np.ceil(L / strides[-1])
      else:
          raise Exception("unsupported pad type")
      output_shape = (N, C_out, L_out)
  
      assert_model_is_valid(
          prog,
          {"x": (N, C_in, L)},
          expected_output_shapes={block.outputs[0].name: output_shape},
          backend=backend,
      )
  
file_path: coremltools/coremltools/converters/mil/backend/nn/passes/test_passes.py
imports: import copy
  import itertools
  import numpy
  import pytest
  from coremltools.converters.mil import testing_reqs
  from coremltools.converters.mil.mil import Builder
  from coremltools.converters.mil.mil.passes.pass_registry import PASS_REGISTRY
  from coremltools.converters.mil.testing_utils import apply_pass_and_basic_check, assert_model_is_valid, assert_same_output_names, get_op_types_in_program
label_desc: Use image node_id 1 for calling the TestConv1dDeompositionPasses obj's underlying member method code with example usage: obj.test_conv1d_decomposition(backend, has_strides, pad_type, has_pad, has_dilations, has_bias) and returns: y