code: def _reduce_degree(bqm, poly, vartype, scale):
      
  
      if all(len(term) <= 2 for term in poly):
          # termination criteria, we are already quadratic
          bqm.add_interactions_from(poly)
          return bqm
  
      # determine which pair of variables appear most often
      paircounter = Counter()
      for term in poly:
          if len(term) > 2:
              for u, v in itertools.combinations(term, 2):
                  pair = frozenset((u, v))
                  paircounter[pair] += 1
  
      pair, __ = paircounter.most_common(1)[0]
      u, v = pair
  
      # make a new product variable and aux variable and add constraint that u*v == p
      p = '{}*{}'.format(u, v)
  
      while p in bqm.linear:
          p = '_' + p
  
      if vartype is Vartype.BINARY:
          constraint = _binary_product([u, v, p])
  
          bqm.info['reduction'][(u, v)] = {'product': p}
      else:
          aux = 'aux{},{}'.format(u, v)
          while aux in bqm.linear:
              aux = '_' + aux
          constraint = _spin_product([u, v, p, aux])
  
          bqm.info['reduction'][(u, v)] = {'product': p, 'auxiliary': aux}
  
      constraint.scale(scale)
      bqm.update(constraint)
  
      new_poly = {}
      for interaction, bias in poly.items():
          if u in interaction and v in interaction:
  
              if len(interaction) == 2:
                  # in this case we are reducing a quadratic bias, so it becomes linear and can
                  # be removed
                  assert len(interaction) >= 2
                  bqm.add_variable(p, bias)
                  continue
  
              interaction = tuple(s for s in interaction if s not in pair)
              interaction += (p,)
  
          if interaction in new_poly:
              new_poly[interaction] += bias
          else:
              new_poly[interaction] = bias
  
      return _reduce_degree(bqm, new_poly, vartype, scale)
docs: helper function for make_quadratic