<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def accelerated_proximal_gradient(x, f, g, gamma, niter, callback=None, **kwargs):
 r"""Accelerated proximal gradient algorithm for convex optimization. The method is known as "Fast Iterative Soft-Thresholding Algorithm" (FISTA). See `[Beck2009]`_ for more information. Solves the convex optimization problem:: min_{x in X} f(x) + g(x) where the proximal operator of ``f`` is known and ``g`` is differentiable. Parameters x : ``f.domain`` element Starting point of the iteration, updated in-place. f : `Functional` The function ``f`` in the problem definition. Needs to have ``f.proximal``. g : `Functional` The function ``g`` in the problem definition. Needs to have ``g.gradient``. gamma : positive float Step size parameter. niter : non-negative int, optional Number of iterations. callback : callable, optional Function called with the current iterate after each iteration. Notes ----- The problem of interest is .. math:: \min_{x \in X} f(x) + g(x), where the formal conditions are that :math:`f : X \to \mathbb{R}` is proper, convex and lower-semicontinuous, and :math:`g : X \to \mathbb{R}` is differentiable and :math:`\nabla g` is :math:`1 / \beta`-Lipschitz continuous. Convergence is only guaranteed if the step length :math:`\gamma` satisfies .. math:: 0 < \gamma < 2 \beta. References .. _[Beck2009]: http://epubs.siam.org/doi/abs/10.1137/080716542 """

    # Get and validate input
    if x not in f.domain:
        raise TypeError('`x` {!r} is not in the domain of `f` {!r}'
                        ''.format(x, f.domain))
    if x not in g.domain:
        raise TypeError('`x` {!r} is not in the domain of `g` {!r}'
                        ''.format(x, g.domain))

    gamma, gamma_in = float(gamma), gamma
    if gamma <= 0:
        raise ValueError('`gamma` must be positive, got {}'.format(gamma_in))

    if int(niter) != niter:
        raise ValueError('`niter` {} not understood'.format(niter))

    # Get the proximal
    f_prox = f.proximal(gamma)
    g_grad = g.gradient

    # Create temporary
    tmp = x.space.element()
    y = x.copy()
    t = 1

    for k in range(niter):
        # Update t
        t, t_old = (1 + np.sqrt(1 + 4 * t ** 2)) / 2, t
        alpha = (t_old - 1) / t

        # x - gamma grad_g (y)
        tmp.lincomb(1, y, -gamma, g_grad(y))

        # Store old x value in y
        y.assign(x)

        # Update x
        f_prox(tmp, out=x)

        # Update y
        y.lincomb(1 + alpha, x, -alpha, y)

        if callback is not None:
            callback(x)