human
Complete the below
def integral_steps(integrand, symbol, **options):

    ''''Returns the steps needed to compute an integral.
    This function attempts to mirror what a student would do by hand as
    closely as possible.
    SymPy Gamma uses this to provide a step-by-step explanation of an
    integral. The code it uses to format the results of this function can be
    found at
    https://github.com/sympy/sympy_gamma/blob/master/app/logic/intsteps.py.
    Examples
    >>> from sympy import exp, sin, cos
    >>> from sympy.integrals.manualintegrate import integral_steps
    >>> from sympy.abc import x
    >>> print(repr(integral_steps(exp(x) / (1 + exp(2 * x)), x)))     # doctest: +NORMALIZE_WHITESPACE
    URule(u_var=_u, u_func=exp(x), constant=1,
    substep=PiecewiseRule(subfunctions=[(ArctanRule(a=1, b=1, c=1, context=1/(_u**2 + 1), symbol=_u), True),
    (ArccothRule(a=1, b=1, c=1, context=1/(_u**2 + 1), symbol=_u), False),
    (ArctanhRule(a=1, b=1, c=1, context=1/(_u**2 + 1), symbol=_u), False)],
    context=1/(_u**2 + 1), symbol=_u), context=exp(x)/(exp(2*x) + 1), symbol=x)
    >>> print(repr(integral_steps(sin(x), x)))     # doctest: +NORMALIZE_WHITESPACE
    TrigRule(func=\'sin\', arg=x, context=sin(x), symbol=x)
    >>> print(repr(integral_steps((x**2 + 3)**2 , x)))     # doctest: +NORMALIZE_WHITESPACE
    RewriteRule(rewritten=x**4 + 6*x**2 + 9,
    substep=AddRule(substeps=[PowerRule(base=x, exp=4, context=x**4, symbol=x),
    ConstantTimesRule(constant=6, other=x**2,
    substep=PowerRule(base=x, exp=2, context=x**2, symbol=x),
    context=6*x**2, symbol=x),
    ConstantRule(constant=9, context=9, symbol=x)],
    context=x**4 + 6*x**2 + 9, symbol=x), context=(x**2 + 3)**2, symbol=x)
    Returns
    rule : namedtuple
    The first step.
most rules have substeps that must also be
    considered. These substeps can be evaluated using ``manualintegrate``
    to obtain a result.'
    '''
assistant
#Here is Python program to compute an integral.
    cachekey = (integrand, symbol)
    if (cachekey in _integral_cache):
        if (_integral_cache[cachekey] is None):
            return None
        else:
            return _integral_cache[cachekey]
    else:
        _integral_cache[cachekey] = None
    integral = IntegralInfo(integrand, symbol)
    def key(integral):
        integrand = integral.integrand
        if isinstance(integrand, TrigonometricFunction):
            return TrigonometricFunction
        elif isinstance(integrand, sympy.Derivative):
            return sympy.Derivative
        elif (symbol not in integrand.free_symbols):
            return sympy.Number
        else:
            for cls in (sympy.Pow, sympy.Symbol, sympy.exp, sympy.log, sympy.Add, sympy.Mul, sympy.atan, sympy.asin, sympy.acos, sympy.Heaviside):
                if isinstance(integrand, cls):
                    return cls
    def integral_is_subclass(*klasses):
        def _integral_is_subclass(integral):
            k = key(integral)
            return (k and issubclass(k, klasses))
        return _integral_is_subclass
    result = do_one(null_safe(switch(key, {sympy.Pow: do_one(null_safe(power_rule), null_safe(inverse_trig_rule), null_safe(quadratic_denom_rule)), sympy.Symbol: power_rule, sympy.exp: exp_rule, sympy.Add: add_rule, sympy.Mul: do_one(null_safe(mul_rule), null_safe(trig_product_rule), null_safe(heaviside_rule), null_safe(quadratic_denom_rule), null_safe(root_mul_rule)), sympy.Derivative: derivative_rule, TrigonometricFunction: trig_rule, sympy.Heaviside: heaviside_rule, sympy.Number: constant_rule})), do_one(null_safe(trig_rule), null_safe(alternatives(rewrites_rule, substitution_rule, condition(integral_is_subclass(sympy.Mul, sympy.Pow), partial_fractions_rule), condition(integral_is_subclass(sympy.Mul, sympy.Pow), cancel_rule), condition(integral_is_subclass(sympy.Mul, sympy.log, sympy.atan, sympy.asin, sympy.acos), parts_rule), condition(integral_is_subclass(sympy.Mul, sympy.Pow), distribute_expand_rule), trig_powers_products_rule)),...