code: def _partition(terms, sum_vars):
      # Construct a bipartite graph between terms and the vars
      neighbors = OrderedDict([(t, []) for t in terms])
      for term in terms:
          for dim in term.inputs.keys():
              if dim in sum_vars:
                  neighbors[term].append(dim)
                  neighbors.setdefault(dim, []).append(term)
  
      # Partition the bipartite graph into connected components for contraction.
      components = []
      while neighbors:
          v, pending = neighbors.popitem()
          component = OrderedDict([(v, None)])  # used as an OrderedSet
          for v in pending:
              component[v] = None
          while pending:
              v = pending.pop()
              for v in neighbors.pop(v):
                  if v not in component:
                      component[v] = None
                      pending.append(v)
  
          # Split this connected component into tensors and dims.
          component_terms = tuple(
              v for v in component if isinstance(v, Funsor)
          )
          if component_terms:
              component_dims = frozenset(
                  v for v in component if not isinstance(v, Funsor)
              )
              components.append((component_terms, component_dims))
      return components
  
imports: import re
  from collections import OrderedDict, defaultdict
  from functools import reduce
  from math import gcd
  import funsor
  import funsor.ops
  from funsor.cnf import Contraction
  from funsor.domains import Bint, Reals
  from funsor.interpreter import gensym
  from funsor.ops import PRODUCT_TO_POWER, UNITS, AssociativeOp
  from funsor.terms import Cat, Funsor, FunsorMeta, Number, Slice, Stack, Subs, Variable, eager, substitute, to_funsor
  from funsor.util import quote
label_desc: Use image node_id 1 for calling a global function with example usage: _partition(terms, sum_vars) and returns: components