class_docstr: A model tracer similar to _symbolic_trace.Tracer, but with concrete execution and real value so we can pass complex conditions
  and go into correct brunches.
class_docstr_tok: ["A","model","tracer","similar","to","_symbolic_trace.Tracer",",","but","with","concrete","execution","and","real","value","so","we","can","pass","complex","conditions","and","go","into","correct","brunches","."]
docstr: similar to _symbolic_trace.Tracer.trace
  different args:
      use_operator_patch:
          the operators 'not/is/is not/in/not in' cannot be wrapped after
              compiled. so we re-parse the functions, replace these operators
              with functions 'operator.not_/is_/is_not/contains', then we
              could wrap and trace these.
          for example: in ``if x is None:``, if x is a proxy, the tracer will
              never go into the branch, even x is a proxy with value 'None'.
          values:
          true: before executing a func, the func will be patched if the func
              is not in operator_patch_backlist
          false: before executing a func, the func will be patched if the func
              is in operator_patch_backlist
  
      operator_patch_backlist:
          such as '__main__.FooModel' or '__main__.bar_func'. the namespace is
          always needed.
docstr_tok: ["similar","to","_symbolic_trace.Tracer.trace","different","args",":","use_operator_patch",":","the","operators","'not\/is\/is","not\/in\/not","in","'","can","not","be","wrapped","after","compiled",".","so","we","re-parse","the","functions",",","replace","these","operators","with","functions","'operator.not_\/is_\/is_not\/contains","'",",","then","we","could","wrap","and","trace","these",".","for","example",":","in","``","if","x","is","None",":","``",",","if","x","is","a","proxy",",","the","tracer","will","never","go","into","the","branch",",","even","x","is","a","proxy","with","value","'None","'",".","values",":","true",":","before","executing","a","func",",","the","func","will","be","patched","if","the","func","is","not","in","operator_patch_backlist","false",":","before","executing","a","func",",","the","func","will","be","patched","if","the","func","is","in","operator_patch_backlist","operator_patch_backlist",":","such","as","'__main__.FooModel","'","or","'__main__.bar_func","'",".","the","namespace","is","always","needed","."]
code: def trace(
      self,
      root: Union[torch.nn.Module, Callable[..., Any]],
      *,
      autowrap_modules: Tuple[str] | None = None,
      autowrap_leaf_function=None,
      autowrap_leaf_class=None,
      leaf_module=None,
      fake_middle_class=None,
      concrete_args: Union[Dict[str, Any], Tuple],
      use_operator_patch: bool = True,
      operator_patch_backlist: List[str] | None = None,
      forward_function_name: str = "forward",
  ) -> Graph:
      """
      similar to _symbolic_trace.Tracer.trace
      different args:
          use_operator_patch:
              the operators 'not/is/is not/in/not in' cannot be wrapped after
                  compiled. so we re-parse the functions, replace these operators
                  with functions 'operator.not_/is_/is_not/contains', then we
                  could wrap and trace these.
              for example: in ``if x is None:``, if x is a proxy, the tracer will
                  never go into the branch, even x is a proxy with value 'None'.
              values:
              true: before executing a func, the func will be patched if the func
                  is not in operator_patch_backlist
              false: before executing a func, the func will be patched if the func
                  is in operator_patch_backlist
  
          operator_patch_backlist:
              such as '__main__.FooModel' or '__main__.bar_func'. the namespace is
              always needed.
      """
      # fill default values
      args = inspect.getfullargspec(root.forward).args[1:]
      defaults = inspect.getfullargspec(root.forward).defaults
      defaults = tuple() if defaults is None else defaults
      if isinstance(concrete_args, (tuple, list)):
          concrete_args = (
              *concrete_args,
              *defaults[
                  len(concrete_args) + len(defaults) - len(args) :
              ],
          )
      else:
          kv_default = {
              k: v for k, v in zip(args[-len(defaults) :], defaults)
          }
          concrete_args = {
              **concrete_args,
              **{
                  n: kv_default[n]
                  for n in args
                  if n not in concrete_args
              },
          }
  
      # preprocess arguments
      autowrap_modules = (
          autowrap_modules if autowrap_modules is not None else tuple()
      )
      autowrap_leaf_function = (
          autowrap_leaf_function
          if autowrap_leaf_function is not None
          else {}
      )
      autowrap_leaf_class = (
          autowrap_leaf_class if autowrap_leaf_class is not None else {}
      )
      leaf_module = leaf_module if leaf_module is not None else ()
      fake_middle_class = (
          fake_middle_class if fake_middle_class is not None else ()
      )
      operator_patch_backlist = (
          operator_patch_backlist
          if operator_patch_backlist is not None
          else []
      )
  
      # Python modules to apply autowrap to at the start, in addition to
      # modules we see while tracing
      self._autowrap_search: List[ModuleType] = list(
          sys.modules[m]
          for m in (
              *autowrap_modules,
              *ConcreteTracer.default_autowrap_modules,
          )
      )
      # Functions we will eagerly wrap when we see them while tracing
      # this captures both `math.sqrt()` and `from math import sqrt` automatically
      self._autowrap_function_ids: Set[int] = {
          id(value)
          for name, value in chain(
              *[m.__dict__.items() for m in self._autowrap_search]
          )
          if not name.startswith("_") and callable(value)
      }
      self.submodule_paths: Optional[Dict[torch.nn.Module, str]] = None
      self.autowrap_leaf_function = {
          **autowrap_leaf_function,
          **ConcreteTracer.default_autowrap_leaf_function,
      }
      self.autowrap_leaf_class = {
          **autowrap_leaf_class,
          **ConcreteTracer.default_autowrap_leaf_class,
      }
      self.leaf_module = leaf_module
      self.fake_middle_class = fake_middle_class
      if isinstance(root, torch.nn.Module):
          self.root = root
  
          # TODO: better infomation
          assert hasattr(
              root, forward_function_name
          ), f"traced_func_name={forward_function_name} doesn't exist in {_orig_type(root).__name__}"
  
          fn = getattr(root, forward_function_name)
          self.submodule_paths = {
              mod: name for name, mod in root.named_modules()
          }
      else:
          self.root = torch.nn.Module()
          fn = root
  
      tracer_cls = getattr(self, "__class__", None)
      self.graph = Graph(tracer_cls=tracer_cls)
  
      # When we encounter a Tensor value that's not a parameter, we look if it
      # is some other attribute on the model. Construct a dict mapping Tensor
      # values to the qualified name here for efficiency. This is used downstream
      # in create_arg
      self.tensor_attrs: Dict[
          Union[torch.Tensor, ScriptObject], str
      ] = {}
  
      def collect_tensor_attrs(
          m: torch.nn.Module, prefix_atoms: List[str]
      ):
          for k, v in m.__dict__.items():
              if isinstance(v, (torch.Tensor, ScriptObject)):
                  self.tensor_attrs[v] = ".".join(prefix_atoms + [k])
          for k, v in m.named_children():
              collect_tensor_attrs(v, prefix_atoms + [k])
  
      collect_tensor_attrs(self.root, [])
  
      if isinstance(fn, MethodType):
          fn = fn.__func__
      assert isinstance(fn, FunctionType)
  
      fn_globals = fn.__globals__  # run before it gets patched
      fn, args, more_args, kwargs = self.create_args_for_root(
          fn, isinstance(root, torch.nn.Module), concrete_args
      )
  
      self.the_path_of_parameter = {
          id(v): k for k, v in self.root.named_parameters()
      }
      self.the_path_of_buffer = {
          id(v): k for k, v in self.root.named_buffers()
      }
  
      def get_middle_class(node, memo=set(), prefix=""):
          if node not in memo:
              memo.add(node)
              yield prefix, node
              if isinstance(node, torch.nn.Module):
                  items = (
                      *(
                          (k, v)
                          for k, v in node.__dict__.items()
                          if not k.startswith("_")
                      ),
                      *node._modules.items(),
                  )
              else:
                  items = (
                      (k, v)
                      for k, v in node.__dict__.items()
                      if not k.startswith("_")
                  )
              for name, subfield in items:
                  if isinstance(
                      subfield,
                      (torch.nn.Module, self.fake_middle_class),
                  ):
                      submodule_prefix = (
                          prefix + ("." if prefix else "") + name
                      )
                      for m in get_middle_class(
                          subfield, memo, submodule_prefix
                      ):
                          yield m
  
      self.the_path_of_middle_class = {
          id(v): k for k, v in get_middle_class(self.root)
      }
  
      @functools.wraps(_orig_module_getattribute)
      def module_getattribute_wrapper(mod, attr):
          if self.temp_disable_call | self.temp_disable_attr:
              try:
                  return _orig_module_getattribute(mod, attr)
              except AttributeError:
                  return _orig_module_getattr(mod, attr)
          with self.do_temp_disable(attr=True):
              try:
                  attr_val = _orig_module_getattribute(mod, attr)
              except AttributeError:
                  attr_val = _orig_module_getattr(mod, attr)
          if callable(attr_val):
              if attr_val in self.wrapped_leaf:
                  return self.wrapped_leaf[attr_val][1]
              return attr_val
          elif attr in self.default_module_getattr:
              path = self.the_path_of_middle_class[id(mod)]
              path = path + "." if path else ""
              return self.create_proxy(
                  "get_attr", f"{path + attr}", (), {}
              )
          elif _orig_isinstance(attr_val, (_orig_tuple, _orig_list)):
              if self.the_path_of_middle_class[id(mod)] == "":
                  return self.create_proxy(
                      "get_attr", f"{attr}", (), {}
                  )
              else:
                  return self.create_proxy(
                      "get_attr",
                      f"{self.the_path_of_middle_class[id(mod)]}.{attr}",
                      (),
                      {},
                  )
          elif id(attr_val) in self.the_path_of_parameter:
              return self.create_proxy(
                  "get_attr",
                  self.the_path_of_parameter[id(attr_val)],
                  (),
                  {},
              )
          elif id(attr_val) in self.the_path_of_buffer:
              return self.create_proxy(
                  "get_attr",
                  self.the_path_of_buffer[id(attr_val)],
                  (),
                  {},
              )
          return attr_val
  
      @functools.wraps(_orig_module_call)
      def module_call_wrapper(mod, *args, **kwargs):
          if self.temp_disable_call:
              return _orig_module_call(mod, *args, **kwargs)
          else:
              # codes below corresponds to symbolic tracer's call_module
              module_qualified_name = self.path_of_module(mod)
              with ScopeContextManager(
                  self.scope, Scope(module_qualified_name, type(mod))
              ) as _scope:
                  self.module_stack[
                      _scope.module_path
                  ] = _scope.module_type
                  if not self.is_leaf_module(
                      mod, module_qualified_name
                  ):
                      _autowrap_check(
                          self,
                          mod.forward.__globals__,
                          self._autowrap_function_ids,
                          self.autowrap_leaf_pairs,
                          self.agfunc_dict,
                      )
                      _autowrap_check(
                          self,
                          mod.__dict__,
                          self._autowrap_function_ids,
                          self.autowrap_leaf_pairs,
                          self.agfunc_dict,
                      )
                      ret_val = _orig_module_call(mod, *args, **kwargs)
                  else:
                      ret_val = self.create_proxy(
                          "call_module",
                          module_qualified_name,
                          args,
                          kwargs,
                      )
                  key, _ = self.module_stack.popitem(last=True)
                  assert (
                      key == _scope.module_path
                  ), f" Unexpected key {key}"
              return ret_val
  
      class map_wrapper_clz:
          @functools.wraps(_orig_map)
          def __call__(self, the_func, *iterables: Any):
              tracers = _orig_set()
              for one_iter in iterables:
                  if _orig_isinstance(one_iter, ep.Proxy):
                      tracers.add(one_iter.tracer)
              if _orig_len(tracers) > 1:
                  raise Exception(
                      "more than 1 tracer detected. please report the issue"
                  )
              elif _orig_len(tracers) == 1:
                  results = _orig_list()
                  for args in _orig_zip(*iterables):
                      results.append(the_func(*args))
                  return next(iter(tracers)).create_proxy(
                      "call_function", _orig_tuple, (results,), {}
                  )
  
              ## for the multi-level list/tuple
              iterables = _orig_list(_orig_list(it) for it in iterables)
              for it in iterables:
                  for arg in it:
                      if _orig_isinstance(arg, ep.Proxy):
                          tracers.add(arg.tracer)
              if _orig_len(tracers) > 1:
                  raise Exception(
                      "more than 1 tracer detected. please report the issue"
                  )
              elif _orig_len(tracers) == 1:
                  results = _orig_list()
                  for args in _orig_zip(*iterables):
                      results.append(the_func(*args))
                  return next(iter(tracers)).create_proxy(
                      "call_function", _orig_tuple, (results,), {}
                  )
              ## for the multi-level list/tuple end
  
              return _orig_map(the_func, *iterables)
  
          def __eq__(self, __o: object) -> bool:
              return id(__o) in (id(self), id(_orig_map))
  
          def __hash__(self):
              return id(self)
  
      map_wrapper = map_wrapper_clz()
  
      class range_wrapper_clz:
          @functools.wraps(_orig_range)
          def __call__(self, *args):
              # TODO: better infomation
              assert 1 <= _orig_len(args) <= 3
              args = (
                  arg.value
                  if _orig_isinstance(arg, ep.ConcreteProxy)
                  else arg
                  for arg in args
              )
              return _orig_range(*args)
  
          def __eq__(self, __o: object) -> bool:
              return id(__o) in (id(self), id(_orig_range))
  
          def __hash__(self):
              return id(self)
  
      range_wrapper = range_wrapper_clz()
  
      class enumerate_wrapper_clz:
          @functools.wraps(_orig_enumerate)
          def __call__(self, iterable, start=0):
              count = start
              for elem in iterable:
                  if _orig_isinstance(
                      elem, ep.ConcreteProxy
                  ) and _orig_isinstance(elem.value, (_orig_int, str)):
                      yield count, elem.value
                  else:
                      yield count, elem
                  count += 1
  
          def __eq__(self, __o: object) -> bool:
              return id(__o) in (id(self), id(_orig_enumerate))
  
          def __hash__(self):
              return id(self)
  
      enumerate_wrapper = enumerate_wrapper_clz()
  
      class type_wrapper_clz:
          @functools.wraps(_orig_type)
          def __call__(self, instance):
              orig_type = _orig_type(instance)
              if orig_type in (
                  ep.ConcreteProxy,
                  ep.ConcreteAttrProxy,
                  ep.ConcreteUnpackIterProxy,
              ):
                  return _orig_type(instance.value)
              else:
                  return orig_type
  
          def __eq__(self, __o: object) -> bool:
              return id(__o) in (id(self), id(_orig_enumerate))
  
          def __hash__(self):
              return id(self)
  
      type_wrapper = type_wrapper_clz()
  
      @classmethod
      @functools.wraps(_orig_agfunc_apply)
      def agfunc_apply_wrapper(clz, *args, **kwargs):
          if clz not in self.agfunc_dict:
              self.agfunc_dict[clz] = torch._C._FunctionBase.__dict__[
                  "apply"
              ].__get__(None, clz)
          if self.temp_disable_agfunc_apply or self.temp_disable_call:
              return self.agfunc_dict[clz](*args, **kwargs)
          tracers = _orig_set()
  
          def unwrap_detect_tracers(obj):
              if isinstance(obj, ep.ConcreteProxy):
                  tracers.add(obj.tracer)
  
          ep.map_aggregate_not_proxy(args, unwrap_detect_tracers)
          ep.map_aggregate_not_proxy(kwargs, unwrap_detect_tracers)
          if _orig_len(tracers) == 0:
              return self.agfunc_dict[clz](*args, **kwargs)
          elif _orig_len(tracers) == 1 and next(iter(tracers)) == self:
              return self.create_proxy(
                  "call_function", self.agfunc_dict[clz], args, kwargs
              )
          else:
              raise Exception(
                  "more than 1 tracer detected. please report the issue"
              )
  
      @functools.wraps(_orig_torch_assert)
      def torch_assert_wrapper(condition, message):
          while _orig_isinstance(condition, ep.ConcreteProxy):
              condition = condition.value
          return _orig_torch_assert(condition, message)
  
      self.agfunc_dict: dict[Type, Any] = {}
      self.autowrap_leaf_pairs = {
          id(_orig_torch_assert): torch_assert_wrapper,
      }
      self.wrapped_leaf = dict()
  
      for func, (
          positions,
          is_force_trace,
          to_func,
      ) in self.autowrap_leaf_function.items():
          if (
              _orig_isinstance(func, BuiltinMethodType)
              and getattr(func, "__name__", None) == "apply"
              and _orig_isinstance(
                  getattr(func, "__self__", None), Type
              )
              and issubclass(func.__self__, torch.autograd.Function)
          ):
              # torch.autograd.function
              assert (
                  to_func == None
              ), "<subclass of torch.autograd.Function>.apply should set to_func to None!"
              if func.__self__ not in self.agfunc_dict:
                  self.agfunc_dict[
                      func.__self__
                  ] = _create_wrapped_leaf_func(self, func, func)
              wrapped = self.agfunc_dict[func.__self__]
          else:
              if func.__qualname__.startswith("_TensorBase"):
                  positions = (
                      *positions,
                      (torch.Tensor, func.__name__),
                  )
                  wrapped = _create_wrapped_leaf_method(
                      self,
                      getattr(torch.Tensor, func.__name__),
                      func.__name__,
                      to_func,
                  )
              elif func.__qualname__.startswith(
                  "_VariableFunctionsClass"
              ):
                  if hasattr(torch, func.__name__):
                      # avoid bad attr like 'unique_dim'
                      positions = (*positions, (torch, func.__name__))
                  if is_force_trace:
                      wrapped = _create_wrapped_leaf_func(
                          self, func, to_func, (self,)
                      )
                  else:
                      wrapped = _create_wrapped_leaf_func(
                          self, func, to_func
                      )
              elif _orig_isinstance(
                  func, (MethodDescriptorType, MethodWrapperType)
              ):
                  wrapped = _create_wrapped_leaf_method(
                      self, func, func.__name__, to_func
                  )
              elif (
                  func.__name__ != func.__qualname__
                  and func.__qualname__
                  != "boolean_dispatch.<locals>.fn"
              ):
                  # method
                  if (
                      func.__module__.startswith("_")
                      and func.__module__ != "__main__"
                  ):
                      path = sys.modules[func.__module__[1:]]
                  else:
                      path = sys.modules[func.__module__]
                  path = getattr(path, func.__qualname__.split(".")[0])
                  positions = (*positions, (path, func.__name__))
                  wrapped = _create_wrapped_leaf_method(
                      self, func, func.__name__, to_func
                  )
              else:
                  # common function
                  if (
                      func.__module__.startswith("_")
                      and func.__module__ != "__main__"
                  ):
                      path = sys.modules[func.__module__[1:]]
                  else:
                      path = sys.modules[func.__module__]
                  positions = (*positions, (path, func.__name__))
                  if is_force_trace:
                      wrapped = _create_wrapped_leaf_func(
                          self, func, to_func, (self,)
                      )
                  else:
                      wrapped = _create_wrapped_leaf_func(
                          self, func, to_func
                      )
          self.wrapped_leaf[func] = (positions, wrapped)
  
      self.clz_wrapper_map: Dict[Any, Type] = {
          map_wrapper: _orig_map,
          enumerate_wrapper: _orig_enumerate,
          range_wrapper: _orig_range,
          type_wrapper: _orig_type,
      }
      for clz, (
          positions,
          is_iterable,
      ) in self.autowrap_leaf_class.items():
          if (
              clz.__module__.startswith("_")
              and clz.__module__ != "__main__"
          ):
              path = sys.modules[clz.__module__[1:]]
          else:
              path = sys.modules[clz.__module__]
          if is_iterable:
              wrapped = _create_wrapped_leaf_iterable_class(self, clz)
          else:
              wrapped = _create_wrapped_leaf_class(self, clz)
          positions = (*positions, (path, clz.__name__))
          self.wrapped_leaf[clz] = (positions, wrapped)
          self.clz_wrapper_map[wrapped] = clz
  
      for clz in self.fake_middle_class:
          wrapped = _create_wrapped_attr_for_middle_class(
              self, clz, self.the_path_of_middle_class
          )
          self.wrapped_leaf[clz.__getattribute__] = (
              ((clz, "__getattribute__"),),
              wrapped,
          )
  
      @functools.wraps(_orig_isinstance)
      def isinstance_wrapper(instance, clz):
          if _orig_type(clz) in (
              slice,
              tuple,
              list,
              _orig_slice,
              _orig_tuple,
              _orig_list,
          ):
              clz_wrapped = []
              for (
                  wrapped_type,
                  orig_type,
              ) in self.clz_wrapper_map.items():
                  if wrapped_type in clz:
                      clz_wrapped.append(orig_type)
              clz = (
                  *clz_wrapped,
                  *(
                      aclz
                      for aclz in clz
                      if aclz not in self.clz_wrapper_map
                  ),
              )
              # use _orig_isinstance(clz, Iterable) will cause an endless recursive loop
              for cls in (
                  object,
                  ep.ConcreteProxy,
                  ep.ConcreteAttrProxy,
                  ep.ConcreteUnpackIterProxy,
              ):
                  if cls in clz and _orig_isinstance(instance, cls):
                      return True
              if _orig_isinstance(instance, ep.ConcreteProxy):
                  return _orig_isinstance(instance.value, clz)
              else:
                  return _orig_isinstance(instance, clz)
          else:
              if clz in (
                  object,
                  ep.ConcreteProxy,
                  ep.ConcreteAttrProxy,
                  ep.ConcreteUnpackIterProxy,
              ):
                  return _orig_isinstance(instance, clz)
              if clz in self.clz_wrapper_map:
                  clz = self.clz_wrapper_map[clz]
              if _orig_isinstance(instance, ep.ConcreteProxy):
                  instance = instance.value
              return _orig_isinstance(instance, clz)
  
      @functools.wraps(_orig_issubclass)
      def issubclass_wrapper(subclass, clz):
          if _orig_type(clz) in (
              slice,
              tuple,
              list,
              _orig_slice,
              _orig_tuple,
              _orig_list,
          ):
              clz_wrapped = []
              for (
                  wrapped_type,
                  orig_type,
              ) in self.clz_wrapper_map.items():
                  if wrapped_type in clz:
                      clz_wrapped.append(orig_type)
              clz = (
                  *clz_wrapped,
                  *(
                      aclz
                      for aclz in clz
                      if aclz not in self.clz_wrapper_map
                  ),
              )
              return _orig_issubclass(subclass, clz)
          else:
              if clz in self.clz_wrapper_map:
                  clz = self.clz_wrapper_map[clz]
              return _orig_issubclass(subclass, clz)
  
      @functools.wraps(_orig_getattr)
      def getattr_wrapper(obj, *args):
          # TODO: better infomation
          if not 1 <= _orig_len(args) <= 2:
              raise Exception()
          args = _orig_list(args)
          if _orig_isinstance(args[0], ep.ConcreteProxy):
              args[0] = args[0].value
          return _orig_getattr(obj, *args)
  
      # for passing the tracing of leaf modules
      self.temp_disable_call = False
      self.temp_disable_attr = False
      self.temp_disable_agfunc_apply = False
      self.temp_disable_call_level = 0
      self.temp_disable_attr_level = 0
      self.temp_disable_agfunc_apply_level = 0
      try:
          with _Patcher() as self.patcher:
              # allow duplicate patches to support the case of nested calls
              self.patcher.patch_method(
                  torch.nn.Module,
                  "__getattribute__",
                  module_getattribute_wrapper,
                  deduplicate=False,
              )
  
              self.patcher.patch_method(
                  torch.nn.Module,
                  "__call__",
                  module_call_wrapper,
                  deduplicate=False,
              )
              self.patcher.patch_method(
                  torch.autograd.Function,
                  "apply",
                  agfunc_apply_wrapper,
                  deduplicate=False,
              )
              self.patcher.patch_method(
                  torch,
                  "_assert",
                  torch_assert_wrapper,
                  deduplicate=False,
              )
  
              self.patcher.patch_method(
                  builtins, "map", map_wrapper, deduplicate=False
              )
              self.patcher.patch_method(
                  builtins,
                  "enumerate",
                  enumerate_wrapper,
                  deduplicate=False,
              )
              self.patcher.patch_method(
                  builtins, "range", range_wrapper, deduplicate=False
              )
              self.patcher.patch_method(
                  builtins, "type", type_wrapper, deduplicate=False
              )
              self.patcher.patch_method(
                  builtins,
                  "isinstance",
                  isinstance_wrapper,
                  deduplicate=False,
              )
              self.patcher.patch_method(
                  builtins,
                  "issubclass",
                  issubclass_wrapper,
                  deduplicate=False,
              )
              self.patcher.patch_method(
                  builtins,
                  "getattr",
                  getattr_wrapper,
                  deduplicate=False,
              )
  
              for obj, (
                  positions,
                  wrapped,
              ) in self.wrapped_leaf.items():
                  for path, name in positions:
                      self.patcher.patch_method(
                          path, name, wrapped, deduplicate=False
                      )
                  self.autowrap_leaf_pairs[id(obj)] = wrapped
  
              _patch_wrapped_functions(self.patcher)
              _autowrap_check(
                  self,
                  fn_globals,
                  self._autowrap_function_ids,
                  self.autowrap_leaf_pairs,
                  self.agfunc_dict,
              )
              for module in self._autowrap_search:
                  _autowrap_check(
                      self,
                      module.__dict__,
                      self._autowrap_function_ids,
                      self.autowrap_leaf_pairs,
                      self.agfunc_dict,
                  )
              with OperatorPatcherContext(
                  self, use_operator_patch, operator_patch_backlist
              ):
                  self.create_node(
                      "output",
                      "output",
                      (
                          self.create_arg(
                              OperatorPatcherContext.patch_run(
                                  fn, *args, *more_args, **kwargs
                              )
                          ),
                      ),
                      {},
                      type_expr=fn.__annotations__.get("return", None),
                  )
      finally:
          # for cuda versions of pytorch, autograd.Function.apply should be reverted manually
          delattr(torch.autograd.Function, "apply")
          _retain_weight_consistency(self.root)
          pass
  
      self.submodule_paths = None
      return self.graph
  
imports: from __future__ import annotations
  import collections
  import copy
  import sys
  import inspect
  import logging
  import operator
  import functools
  import builtins
  from itertools import chain
  from types import BuiltinMethodType, FunctionType, MethodDescriptorType, MethodType, MethodWrapperType, ModuleType
  from typing import Any, Dict, Iterable, Iterator, Optional, Set, Tuple, Type, List, Callable, Union
  from contextlib import contextmanager
  import torch
  from torch._C import ScriptObject
  from torch.nn.modules.container import Sequential, ModuleList, ModuleDict, ParameterList, ParameterDict
  from torch.utils._pytree import tree_map
  import torch.fx
  from torch.fx import GraphModule
  from torch.fx._compatibility import compatibility
  from torch.fx._symbolic_trace import _Patcher, _proxyable_classes
  from torch.fx.graph import Graph
  from torch.fx.node import Target, Node, Argument, _side_effectful_functions
  from torch.fx.proxy import TracerBase
  from torch.fx.operator_schemas import check_for_mutable_operation
  from .None import concrete_proxy
  from .operator_patcher import OperatorPatcherContext
  from .utils import _orig_module_call, _orig_module_getattr, _orig_module_getattribute, _orig_agfunc_apply, _orig_torch_assert, _orig_type, _orig_isinstance, _orig_issubclass, _orig_getattr, _orig_range, _orig_int, _orig_bool, _orig_tuple, _orig_list, _orig_set, _orig_frozenset, _orig_dict, _orig_map, _orig_zip, _orig_enumerate, _orig_slice, _orig_reversed, _orig_torch_size, _orig_torch_finfo, _orig_len, _orig_not, _orig_is, _orig_is_not, _orig_contains, _orig_index, _orig_all, _orig_min, _orig_max, _orig_node_is_impure
label_desc: Use image node_id 12 for calling the ConcreteTracer obj's underlying member method code with example usage: obj.trace(root) and returns: self, attr_val, _orig_torch_assert, _orig_getattr, attr_val, _orig_module_call, ret_val, _orig_map, unknown, id, _orig_range, unknown, id, unknown, id, unknown, id, self, self, _orig_isinstance, _orig_issubclass, _orig_issubclass, _orig_module_getattribute, self, self, _orig_type, orig_type, self, _orig_isinstance, _orig_isinstance, _orig_isinstance, _orig_module_getattr, next, next, True, self, self, self, self