class_docstr: Simplify Mul->Sub->Conv->bias_add to Conv->bias_add->add sequence if
  one of the inputs to Mul and Sub are constant scalars.
  
  Replace
  def @main(%q1: Tensor[(1, 128, 128, 3), float16])
      %0 = multiply(%q1, c1_const_scalar)  /* ty=Tensor[(1, 128, 128, 3), float16] */;
      %1 = subtract(%0, c2_const_scalar) /* ty=Tensor[(1, 128, 128, 3), float16] */
      %2 = transpose(%1, axes=[0,3,1,2])
          /* ty=Tensor[(1, 3, 128, 128), float16] */
      %3 = nn.conv2d(%2, weights, ...) .
      %4 = nn.bias_add(%3, bias)
  }
  
  with
  
  def @main(%q1: Tensor[(1, 128, 128, 3), float16])
      %0 = transpose(%q1, axes=[0, 3, 1, 2])
          /* ty=Tensor[(1, 3, 128, 128), float16] */;
      %1 = multiply(c1, weights) /* ty=Tensor[(64, 3, 3, 3), float16] */;
      %2 = nn.conv2d(%0, %1, padding=[1, 1, 1, 1],
          channels=64, kernel_size=[3, 3])
          /* ty=Tensor[(1, 64, 128, 128), float16] */;
      %3 = subtract(%0 shaped zero_tensor, c2)
          /* ty=Tensor[(1, 3, 128, 128), float16] */;
      %4 = nn.bias_add(%2, bias) /* ty=Tensor[(1, 64, 128, 128), float16] */;
      %5 = nn.conv2d(%3, weights, padding=[1, 1, 1, 1],
          channels=64, kernel_size=[3, 3])
          /* ty=Tensor[(1, 64, 128, 128), float16] */;
      add(%4, %5) /* ty=Tensor[(1, 64, 128, 128), float16] */
  
  Why is it legal? Ignore the transpose in the above pattern.
  res[p,q,r,s] = Conv(a*c1 - c2, W)
               = SUM{i=[0,c-1], j=[0,kh-1], k=[0,kw-1]}
                  {(a[p,i,r+j,s+k] * c1 - c2) * W[q,i,j,k]}
               = SUM{i=[0,c-1], j=[0,kh-1], k=[0,kw-1]}
                  {a[p,i,r+j,s+k] * c1 * W[q,i,j,k]} - c2 * W[q,i,j,k]}
               = Conv(a, W*c1) + Conv(0-c2, W)
  
  
  }
  
  In the above, %1, %3, %5 are constants and can be folded, so we're
  left with 4 ops, as opposed to the original 5 ops
class_docstr_tok: ["Simplify","Mul-",">","Sub-",">","Conv-",">","bias_add","to","Conv-",">","bias_add-",">","add","sequence","if","one","of","the","inputs","to","Mul","and","Sub","are","constant","scalars",".","Replace","def","@","main","(","%","q1",":","Tensor","[","(","1",",","128",",","128",",","3",")",",","float16","]",")","%","0","=","multiply","(","%","q1",",","c1_const_scalar",")","\/","*","ty=Tensor","[","(","1",",","128",",","128",",","3",")",",","float16","]","*","\/",";","%","1","=","subtract","(","%","0",",","c2_const_scalar",")","\/","*","ty=Tensor","[","(","1",",","128",",","128",",","3",")",",","float16","]","*","\/","%","2","=","transpose","(","%","1",",","axes=","[","0,3,1,2","]",")","\/","*","ty=Tensor","[","(","1",",","3",",","128",",","128",")",",","float16","]","*","\/","%","3","=","nn.conv2d","(","%","2",",","weights",",","...",")",".","%","4","=","nn.bias_add","(","%","3",",","bias",")","}","with","def","@","main","(","%","q1",":","Tensor","[","(","1",",","128",",","128",",","3",")",",","float16","]",")","%","0","=","transpose","(","%","q1",",","axes=","[","0",",","3",",","1",",","2","]",")","\/","*","ty=Tensor","[","(","1",",","3",",","128",",","128",")",",","float16","]","*","\/",";","%","1","=","multiply","(","c1",",","weights",")","\/","*","ty=Tensor","[","(","64",",","3",",","3",",","3",")",",","float16","]","*","\/",";","%","2","=","nn.conv2d","(","%","0",",","%","1",",","padding=","[","1",",","1",",","1",",","1","]",",","channels=64",",","kernel_size=","[","3",",","3","]",")","\/","*","ty=Tensor","[","(","1",",","64",",","128",",","128",")",",","float16","]","*","\/",";","%","3","=","subtract","(","%","0","shaped","zero_tensor",",","c2",")","\/","*","ty=Tensor","[","(","1",",","3",",","128",",","128",")",",","float16","]","*","\/",";","%","4","=","nn.bias_add","(","%","2",",","bias",")","\/","*","ty=Tensor","[","(","1",",","64",",","128",",","128",")",",","float16","]","*","\/",";","%","5","=","nn.conv2d","(","%","3",",","weights",",","padding=","[","1",",","1",",","1",",","1","]",",","channels=64",",","kernel_size=","[","3",",","3","]",")","\/","*","ty=Tensor","[","(","1",",","64",",","128",",","128",")",",","float16","]","*","\/",";","add","(","%","4",",","%","5",")","\/","*","ty=Tensor","[","(","1",",","64",",","128",",","128",")",",","float16","]","*","\/","Why","is","it","legal","?","Ignore","the","transpose","in","the","above","pattern",".","res","[","p",",","q",",","r",",","s","]","=","Conv","(","a","*","c1","-","c2",",","W",")","=","SUM","{","i=","[","0",",","c-1","]",",","j=","[","0",",","kh-1","]",",","k=","[","0",",","kw-1","]","}","{","(","a","[","p",",","i",",","r+j",",","s+k","]","*","c1","-","c2",")","*","W","[","q",",","i",",","j",",","k","]","}","=","SUM","{","i=","[","0",",","c-1","]",",","j=","[","0",",","kh-1","]",",","k=","[","0",",","kw-1","]","}","{","a","[","p",",","i",",","r+j",",","s+k","]","*","c1","*","W","[","q",",","i",",","j",",","k","]","}","-","c2","*","W","[","q",",","i",",","j",",","k","]","}","=","Conv","(","a",",","W","*","c1",")","+","Conv","(","0-c2",",","W",")","}","In","the","above",",","%","1",",","%","3",",","%","5","are","constants","and","can","be","folded",",","so","we're","left","with","4","ops",",","as","opposed","to","the","original","5","ops"]
code: def callback(self, pre, post, node_map):
      new_transpose = relay.transpose(
          (node_map[self.inp][0]), **((node_map[self.act][0]).attrs)
      )
      new_weights = relay.multiply(
          (node_map[self.mul][0].args[1]), (node_map[self.weights][0])
      )
      new_conv2d = relay.nn.conv2d(
          new_transpose,
          new_weights,
          **((node_map[self.conv2d_op][0]).attrs),
      )
      new_bias_add = relay.nn.bias_add(
          new_conv2d, (node_map[self.pattern][0].args[1])
      )
  
      zero_tensor = relay.Constant(
          nd.array(
              np.zeros(
                  get_const_tuple(
                      (node_map[self.act][0]).checked_type.shape
                  ),
                  dtype=(node_map[self.act][0]).checked_type.dtype,
              )
          )
      )
      negated = relay.subtract(
          zero_tensor, (node_map[self.sub][0].args[1])
      )
      const_conv2d = relay.nn.conv2d(
          negated,
          (node_map[self.weights][0]),
          **((node_map[self.conv2d_op][0]).attrs),
      )
      return relay.add(new_bias_add, const_conv2d)
  
imports: import functools
  import numpy
  import tvm
  from tvm import relay
  from tvm.relay.dataflow_pattern import DFPatternCallback, is_constant, is_op, is_tuple, rewrite, wildcard
  from tvm.topi.utils import get_const_tuple
  from tvm.relay.expr import Call
  from tvm.runtime import ndarray
  from ..._ffi.registry import register_func
label_desc: Use image node_id 2 for calling the simplify_conv_pat_in_func obj's underlying member method code with example usage: obj.callback(pre, post, node_map) and returns: relay