code: def sdm_groebner(G, NF, O, K, extended=False):
      """
      Compute a minimal standard basis of ``G`` with respect to order ``O``.
  
      The algorithm uses a normal form ``NF``, for example ``sdm_nf_mora``.
      The ground field is assumed to be ``K``, and monomials ordered according
      to ``O``.
  
      Let `N` denote the submodule generated by elements of `G`. A standard
      basis for `N` is a subset `S` of `N`, such that `in(S) = in(N)`, where for
      any subset `X` of `F`, `in(X)` denotes the submodule generated by the
      initial forms of elements of `X`. [SCA, defn 2.3.2]
  
      A standard basis is called minimal if no subset of it is a standard basis.
  
      One may show that standard bases are always generating sets.
  
      Minimal standard bases are not unique. This algorithm computes a
      deterministic result, depending on the particular order of `G`.
  
      If ``extended=True``, also compute the transition matrix from the initial
      generators to the groebner basis. That is, return a list of coefficient
      vectors, expressing the elements of the groebner basis in terms of the
      elements of ``G``.
  
      This functions implements the "sugar" strategy, see
  
      Giovini et al: "One sugar cube, please" OR Selection strategies in
      Buchberger algorithm.
      """
  
      # The critical pair set.
      # A critical pair is stored as (i, j, s, t) where (i, j) defines the pair
      # (by indexing S), s is the sugar of the pair, and t is the lcm of their
      # leading monomials.
      P = []
  
      # The eventual standard basis.
      S = []
      Sugars = []
  
      def Ssugar(i, j):
          """Compute the sugar of the S-poly corresponding to (i, j)."""
          LMi = sdm_LM(S[i])
          LMj = sdm_LM(S[j])
          return max(
              Sugars[i] - sdm_monomial_deg(LMi),
              Sugars[j] - sdm_monomial_deg(LMj),
          ) + sdm_monomial_deg(sdm_monomial_lcm(LMi, LMj))
  
      ourkey = lambda p: (p[2], O(p[3]), p[1])
  
      def update(f, sugar, P):
          """Add f with sugar ``sugar`` to S, update P."""
          if not f:
              return P
          k = len(S)
          S.append(f)
          Sugars.append(sugar)
  
          LMf = sdm_LM(f)
  
          def removethis(pair):
              i, j, s, t = pair
              if LMf[0] != t[0]:
                  return False
              tik = sdm_monomial_lcm(LMf, sdm_LM(S[i]))
              tjk = sdm_monomial_lcm(LMf, sdm_LM(S[j]))
              return (
                  tik != t
                  and tjk != t
                  and sdm_monomial_divides(tik, t)
                  and sdm_monomial_divides(tjk, t)
              )
  
          # apply the chain criterion
          P = [p for p in P if not removethis(p)]
  
          # new-pair set
          N = [
              (i, k, Ssugar(i, k), sdm_monomial_lcm(LMf, sdm_LM(S[i])))
              for i in range(k)
              if LMf[0] == sdm_LM(S[i])[0]
          ]
          # TODO apply the product criterion?
          N.sort(key=ourkey)
          remove = set()
          for i, p in enumerate(N):
              for j in range(i + 1, len(N)):
                  if sdm_monomial_divides(p[3], N[j][3]):
                      remove.add(j)
  
          # TODO mergesort?
          P.extend(
              reversed([p for i, p in enumerate(N) if i not in remove])
          )
          P.sort(key=ourkey, reverse=True)
          # NOTE reverse-sort, because we want to pop from the end
          return P
  
      # Figure out the number of generators in the ground ring.
      try:
          # NOTE: we look for the first non-zero vector, take its first monomial
          #       the number of generators in the ring is one less than the length
          #       (since the zeroth entry is for the module generators)
          numgens = len(next(x[0] for x in G if x)[0]) - 1
      except StopIteration:
          # No non-zero elements in G ...
          if extended:
              return [], []
          return []
  
      # This list will store expressions of the elements of S in terms of the
      # initial generators
      coefficients = []
  
      # First add all the elements of G to S
      for i, f in enumerate(G):
          P = update(f, sdm_deg(f), P)
          if extended and f:
              coefficients.append(
                  sdm_from_dict({(i,) + (0,) * numgens: K(1)}, O)
              )
  
      # Now carry out the buchberger algorithm.
      while P:
          i, j, s, t = P.pop()
          f, g = S[i], S[j]
          if extended:
              sp, coeff = sdm_spoly(
                  f, g, O, K, phantom=(coefficients[i], coefficients[j])
              )
              h, hcoeff = NF(sp, S, O, K, phantom=(coeff, coefficients))
              if h:
                  coefficients.append(hcoeff)
          else:
              h = NF(sdm_spoly(f, g, O, K), S, O, K)
          P = update(h, Ssugar(i, j), P)
  
      # Finally interreduce the standard basis.
      # (TODO again, better data structures)
      S = {(tuple(f), i) for i, f in enumerate(S)}
      for (a, ai), (b, bi) in permutations(S, 2):
          A = sdm_LM(a)
          B = sdm_LM(b)
          if (
              sdm_monomial_divides(A, B)
              and (b, bi) in S
              and (a, ai) in S
          ):
              S.remove((b, bi))
  
      L = sorted(
          ((list(f), i) for f, i in S),
          key=lambda p: O(sdm_LM(p[0])),
          reverse=True,
      )
      res = [x[0] for x in L]
      if extended:
          return res, [coefficients[i] for _, i in L]
      return res
  
imports: from itertools import permutations
  from sympy.polys.monomials import monomial_mul, monomial_lcm, monomial_div, monomial_deg
  from sympy.polys.polytools import Poly
  from sympy.polys.polyutils import parallel_dict_from_expr
  from sympy.core.singleton import S
  from sympy.core.sympify import sympify
label_desc: Use image node_id 23 for calling a global function with example usage: sdm_groebner(G, NF, O, K, extended) and returns: res, unknown, P, res,  unknown, P, unknown, list, False, list,  list