code: def itermonomials(variables, max_degrees, min_degrees=None):
      r"""
      ``max_degrees`` and ``min_degrees`` are either both integers or both lists.
      Unless otherwise specified, ``min_degrees`` is either ``0`` or
      ``[0, ..., 0]``.
  
      A generator of all monomials ``monom`` is returned, such that
      either
      ``min_degree <= total_degree(monom) <= max_degree``,
      or
      ``min_degrees[i] <= degree_list(monom)[i] <= max_degrees[i]``,
      for all ``i``.
  
      Case I. ``max_degrees`` and ``min_degrees`` are both integers
      =============================================================
  
      Given a set of variables $V$ and a min_degree $N$ and a max_degree $M$
      generate a set of monomials of degree less than or equal to $N$ and greater
      than or equal to $M$. The total number of monomials in commutative
      variables is huge and is given by the following formula if $M = 0$:
  
          .. math::
              \frac{(\#V + N)!}{\#V! N!}
  
      For example if we would like to generate a dense polynomial of
      a total degree $N = 50$ and $M = 0$, which is the worst case, in 5
      variables, assuming that exponents and all of coefficients are 32-bit long
      and stored in an array we would need almost 80 GiB of memory! Fortunately
      most polynomials, that we will encounter, are sparse.
  
      Consider monomials in commutative variables $x$ and $y$
      and non-commutative variables $a$ and $b$::
  
          >>> from sympy import symbols
          >>> from sympy.polys.monomials import itermonomials
          >>> from sympy.polys.orderings import monomial_key
          >>> from sympy.abc import x, y
  
          >>> sorted(itermonomials([x, y], 2), key=monomial_key('grlex', [y, x]))
          [1, x, y, x**2, x*y, y**2]
  
          >>> sorted(itermonomials([x, y], 3), key=monomial_key('grlex', [y, x]))
          [1, x, y, x**2, x*y, y**2, x**3, x**2*y, x*y**2, y**3]
  
          >>> a, b = symbols('a, b', commutative=False)
          >>> set(itermonomials([a, b, x], 2))
          {1, a, a**2, b, b**2, x, x**2, a*b, b*a, x*a, x*b}
  
          >>> sorted(itermonomials([x, y], 2, 1), key=monomial_key('grlex', [y, x]))
          [x, y, x**2, x*y, y**2]
  
      Case II. ``max_degrees`` and ``min_degrees`` are both lists
      ===========================================================
  
      If ``max_degrees = [d_1, ..., d_n]`` and
      ``min_degrees = [e_1, ..., e_n]``, the number of monomials generated
      is:
  
      .. math::
          (d_1 - e_1 + 1) (d_2 - e_2 + 1) \cdots (d_n - e_n + 1)
  
      Let us generate all monomials ``monom`` in variables $x$ and $y$
      such that ``[1, 2][i] <= degree_list(monom)[i] <= [2, 4][i]``,
      ``i = 0, 1`` ::
  
          >>> from sympy import symbols
          >>> from sympy.polys.monomials import itermonomials
          >>> from sympy.polys.orderings import monomial_key
          >>> from sympy.abc import x, y
  
          >>> sorted(itermonomials([x, y], [2, 4], [1, 2]), reverse=True, key=monomial_key('lex', [x, y]))
          [x**2*y**4, x**2*y**3, x**2*y**2, x*y**4, x*y**3, x*y**2]
      """
      n = len(variables)
      if is_sequence(max_degrees):
          if len(max_degrees) != n:
              raise ValueError("Argument sizes do not match")
          if min_degrees is None:
              min_degrees = [0] * n
          elif not is_sequence(min_degrees):
              raise ValueError("min_degrees is not a list")
          else:
              if len(min_degrees) != n:
                  raise ValueError("Argument sizes do not match")
              if any(i < 0 for i in min_degrees):
                  raise ValueError(
                      "min_degrees cannot contain negative numbers"
                  )
          total_degree = False
      else:
          max_degree = max_degrees
          if max_degree < 0:
              raise ValueError("max_degrees cannot be negative")
          if min_degrees is None:
              min_degree = 0
          else:
              if min_degrees < 0:
                  raise ValueError("min_degrees cannot be negative")
              min_degree = min_degrees
          total_degree = True
      if total_degree:
          if min_degree > max_degree:
              return
          if not variables or max_degree == 0:
              yield S.One
              return
          # Force to list in case of passed tuple or other incompatible collection
          variables = list(variables) + [S.One]
          if all(variable.is_commutative for variable in variables):
              monomials_list_comm = []
              for item in combinations_with_replacement(
                  variables, max_degree
              ):
                  powers = {variable: 0 for variable in variables}
                  for variable in item:
                      if variable != 1:
                          powers[variable] += 1
                  if sum(powers.values()) >= min_degree:
                      monomials_list_comm.append(Mul(*item))
              yield from set(monomials_list_comm)
          else:
              monomials_list_non_comm = []
              for item in product(variables, repeat=max_degree):
                  powers = {variable: 0 for variable in variables}
                  for variable in item:
                      if variable != 1:
                          powers[variable] += 1
                  if sum(powers.values()) >= min_degree:
                      monomials_list_non_comm.append(Mul(*item))
              yield from set(monomials_list_non_comm)
      else:
          if any(min_degrees[i] > max_degrees[i] for i in range(n)):
              raise ValueError(
                  "min_degrees[i] must be <= max_degrees[i] for all i"
              )
          power_lists = []
          for var, min_d, max_d in zip(
              variables, min_degrees, max_degrees
          ):
              power_lists.append(
                  [var**i for i in range(min_d, max_d + 1)]
              )
          for powers in product(*power_lists):
              yield Mul(*powers)
  
imports: from itertools import combinations_with_replacement, product
  from textwrap import dedent
  from sympy.core import Mul, S, Tuple, sympify
  from sympy.polys.polyerrors import ExactQuotientFailed
  from sympy.polys.polyutils import PicklableWithSlots, dict_from_expr
  from sympy.utilities import public
  from sympy.utilities.iterables import is_sequence, iterable
label_desc: Use image node_id 1 for calling a global function with example usage: itermonomials(variables, max_degrees, min_degrees) without return types