<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def doubleprox_dc(x, y, f, phi, g, K, niter, gamma, mu, callback=None):
 r"""Double-proxmial gradient d.c. algorithm of Banert and Bot. This algorithm solves a problem of the form :: min_x f(x) + phi(x) - g(Kx). Parameters x : `LinearSpaceElement` Initial primal guess, updated in-place. y : `LinearSpaceElement` Initial dual guess, updated in-place. f : `Functional` Convex functional. Needs to implement ``g.proximal``. phi : `Functional` Convex functional. Needs to implement ``phi.gradient``. Convergence can be guaranteed if the gradient is Lipschitz continuous. g : `Functional` Convex functional. Needs to implement ``h.convex_conj.proximal``. K : `Operator` Linear operator. Needs to implement ``K.adjoint`` niter : int Number of iterations. gamma : positive float Stepsize in the primal updates. mu : positive float Stepsize in the dual updates. callback : callable, optional Function called with the current iterate after each iteration. Notes ----- This algorithm is proposed in `[BB2016] <https://arxiv.org/abs/1610.06538>`_ and solves the d.c. problem .. math :: \min_x f(x) + \varphi(x) - g(Kx) together with its Toland dual .. math :: \min_y g^*(y) - (f + \varphi)^*(K^* y). The iterations are given by .. math :: x_{n+1} &= \mathrm{Prox}_{\gamma f} (x_n + \gamma (K^* y_n - \nabla \varphi(x_n))), \\ y_{n+1} &= \mathrm{Prox}_{\mu g^*} (y_n + \mu K x_{n+1}). To guarantee convergence, the parameter :math:`\gamma` must satisfy :math:`0 < \gamma < 2/L` where :math:`L` is the Lipschitz constant of :math:`\nabla \varphi`. References [BB2016] Banert, S, and Bot, R I. *A general double-proximal gradient algorithm for d.c. programming*. arXiv:1610.06538 [math.OC] (2016). See also -------- dca : Solver with subgradient steps for all the functionals. prox_dca : Solver with a proximal step for ``f`` and a subgradient step for ``g``. """

    primal_space = f.domain
    dual_space = g.domain

    if phi.domain != primal_space:
        raise ValueError('`f.domain` and `phi.domain` need to be equal, but '
                         '{} != {}'.format(primal_space, phi.domain))
    if K.domain != primal_space:
        raise ValueError('`f.domain` and `K.domain` need to be equal, but '
                         '{} != {}'.format(primal_space, K.domain))
    if K.range != dual_space:
        raise ValueError('`g.domain` and `K.range` need to be equal, but '
                         '{} != {}'.format(dual_space, K.range))

    g_convex_conj = g.convex_conj
    for _ in range(niter):
        f.proximal(gamma)(x.lincomb(1, x,
                                    gamma, K.adjoint(y) - phi.gradient(x)),
                          out=x)
        g_convex_conj.proximal(mu)(y.lincomb(1, y, mu, K(x)), out=y)

        if callback is not None:
            callback(x)