human
Complete this python program:
def _minpoly_groebner(ex, x, cls):
assistant
#Here is the Python code you requested.

    """Computes the minimal polynomial of an algebraic number
    using Groebner bases
    Examples
    >>> from sympy import minimal_polynomial, sqrt, Rational
    >>> from sympy.abc import x
    >>> minimal_polynomial(sqrt(2) + 3*Rational(1, 3), x, compose=False)
    x**2 - 2*x - 1
    """
    from sympy.polys.polytools import degree
    from sympy.core.function import expand_multinomial
    generator = numbered_symbols('a', cls=Dummy)
    (mapping, symbols, replace) = ({}, {}, [])
    def update_mapping(ex, exp, base=None):
        a = next(generator)
        symbols[ex] = a
        if (base is not None):
            mapping[ex] = ((a ** exp) + base)
        else:
            mapping[ex] = exp.as_expr(a)
        return a
    def bottom_up_scan(ex):
        if ex.is_Atom:
            if (ex is S.ImaginaryUnit):
                if (ex not in mapping):
                    return update_mapping(ex, 2, 1)
                else:
                    return symbols[ex]
            elif ex.is_Rational:
                return ex
        elif ex.is_Add:
            return Add(*[bottom_up_scan(g) for g in ex.args])
        elif ex.is_Mul:
            return Mul(*[bottom_up_scan(g) for g in ex.args])
        elif ex.is_Pow:
            if ex.exp.is_Rational:
                if ((ex.exp < 0) and ex.base.is_Add):
                    (coeff, terms) = ex.base.as_coeff_add()
                    (elt, _) = primitive_element(terms, polys=True)
                    alg = (ex.base - coeff)
                    inverse = invert((elt.gen + coeff), elt).as_expr()
                    base = inverse.subs(elt.gen, alg).expand()
                    if (ex.exp == (-1)):
                        return bottom_up_scan(base)
                    else:
                        ex = (base ** (- ex.exp))
                if (not ex.exp.is_Integer):
                    (base, exp) = ((ex.base ** ex.exp.p).expand(), Rational(1, ex.exp.q))
                else:
                    (base, exp) = (ex.base, ex.exp)
                base = bottom_up_scan(base)
                expr = (base ** exp)
                if (expr not in mapping):
                    return update_mapping(expr, (1 / exp), (- base))
                else:
                    return symbols[expr]
        elif ex.is_AlgebraicNumber:
            if (ex.root not in mapping):
...