code: def treewidth_decomp(G, heuristic=min_fill_in_heuristic):
      """Returns a treewidth decomposition using the passed heuristic.
  
      Parameters
      ----------
      G : NetworkX graph
      heuristic : heuristic function
  
      Returns
      -------
      Treewidth decomposition : (int, Graph) tuple
          2-tuple with treewidth and the corresponding decomposed tree.
      """
  
      # make dict-of-sets structure
      graph = {n: set(G[n]) - {n} for n in G}
  
      # stack containing nodes and neighbors in the order from the heuristic
      node_stack = []
  
      # get first node from heuristic
      elim_node = heuristic(graph)
      while elim_node is not None:
          # connect all neighbors with each other
          nbrs = graph[elim_node]
          for u, v in itertools.permutations(nbrs, 2):
              if v not in graph[u]:
                  graph[u].add(v)
  
          # push node and its current neighbors on stack
          node_stack.append((elim_node, nbrs))
  
          # remove node from graph
          for u in graph[elim_node]:
              graph[u].remove(elim_node)
  
          del graph[elim_node]
          elim_node = heuristic(graph)
  
      # the abort condition is met; put all remaining nodes into one bag
      decomp = nx.Graph()
      first_bag = frozenset(graph.keys())
      decomp.add_node(first_bag)
  
      treewidth = len(first_bag) - 1
  
      while node_stack:
          # get node and its neighbors from the stack
          (curr_node, nbrs) = node_stack.pop()
  
          # find a bag all neighbors are in
          old_bag = None
          for bag in decomp.nodes:
              if nbrs <= bag:
                  old_bag = bag
                  break
  
          if old_bag is None:
              # no old_bag was found: just connect to the first_bag
              old_bag = first_bag
  
          # create new node for decomposition
          nbrs.add(curr_node)
          new_bag = frozenset(nbrs)
  
          # update treewidth
          treewidth = max(treewidth, len(new_bag) - 1)
  
          # add edge to decomposition (implicitly also adds the new node)
          decomp.add_edge(old_bag, new_bag)
  
      return treewidth, decomp
  
file_path: networkx/networkx/algorithms/approximation/treewidth.py
imports: import itertools
  import sys
  from heapq import heapify, heappop, heappush
  import networkx
  from networkx.utils import not_implemented_for
label_desc: Use image node_id 4 for calling a global function with example usage: treewidth_decomp(G, heuristic) and returns: treewidth,  decomp