code: def _get_quantized_qat_conv_bn_pattern(
      is_per_channel: bool,
      has_bias: bool,
      bias_is_quantized: bool,
      conv_fn: Callable,
      bn_is_training: bool,
  ) -> Callable:
      """
      Return the quantized version of QAT conv + BN pattern.
      This is based on `nniqat.ConvBn2d._forward_approximate`,
      used in QAT convert. We first match this pattern and replace
      it with the normal [conv - bn] pattern, then fold the BN
      weights into conv.
      """
      # TODO: allow setting eps
      bn_eps = 1e-5
  
      def _quantized_qat_conv_bn_pattern(
          x: torch.Tensor,
          conv_weight: torch.Tensor,
          bn_weight: torch.Tensor,
          bn_bias: torch.Tensor,
          bn_running_mean: torch.Tensor,
          bn_running_var: torch.Tensor,
          **kwargs,
      ) -> torch.Tensor:
          running_std = torch.sqrt(bn_running_var + bn_eps)
          scale_factor = bn_weight / running_std
          weight_shape = [1] * len(conv_weight.shape)
          weight_shape[0] = -1
          bias_shape = [1] * len(conv_weight.shape)
          bias_shape[1] = -1
          scaled_weight = conv_weight * scale_factor.reshape(
              weight_shape
          )
          scaled_weight = _append_qdq(
              scaled_weight, is_per_channel, kwargs
          )
          if has_bias:
              zero_bias = torch.zeros_like(
                  kwargs["conv_bias"], dtype=x.dtype
              )
              if bias_is_quantized:
                  zero_bias = _append_qdq(
                      zero_bias, is_per_channel, kwargs
                  )
              x = conv_fn(x, scaled_weight, zero_bias)
          else:
              x = conv_fn(x, scaled_weight, None)
          x = x / scale_factor.reshape(bias_shape)
          if has_bias:
              x = x + kwargs["conv_bias"].reshape(bias_shape)
          x = F.batch_norm(
              x,
              bn_running_mean,
              bn_running_var,
              bn_weight,
              bn_bias,
              training=bn_is_training,
              eps=bn_eps,
          )
          return x
  
      return _quantized_qat_conv_bn_pattern
  
imports: import dataclasses
  import itertools
  import operator
  from typing import Any, Callable, Dict, List, Tuple, TYPE_CHECKING
  import torch
  from torch.fx import Graph, GraphModule, Node
  from torch.fx.subgraph_rewriter import replace_pattern_with_filters, ReplacedPatterns
  import torch.nn.functional
  from torch.ao.quantization.fx._decomposed import quantized_decomposed_lib
  from torch.ao.quantization.quantizer import DerivedQuantizationSpec, EdgeOrNode, SharedQuantizationSpec, QuantizationSpecBase
  from .utils import _conv1d_bn_example_inputs, _conv2d_bn_example_inputs, _is_conv, _is_bn_node, fold_bn_weights_into_conv_node, get_aten_graph_module
label_desc: Use image node_id 6 for calling a global function with example usage: _get_quantized_qat_conv_bn_pattern(is_per_channel, has_bias, bias_is_quantized, conv_fn, bn_is_training) and returns: _quantized_qat_conv_bn_pattern, x