code: def tvl1_solver(
      X,
      y,
      alpha,
      l1_ratio,
      mask,
      loss=None,
      max_iter=100,
      lipschitz_constant=None,
      init=None,
      prox_max_iter=5000,
      tol=1e-4,
      callback=None,
      verbose=1,
  ):
      """Minimizes empirical risk for TV-L1 penalized models.
  
      Can handle least squares (mean squared error --a.k.a mse) or logistic
      regression. The same solver works for both of these losses.
  
      This function invokes the mfista backend (from fista.py) to solver the
      underlying optimization problem.
  
      Parameters
      ----------
      X : ndarray, shape (n_samples, n_features)
          Design matrix.
  
      y : ndarray, shape (n_samples,)
          Target / response vector.
  
      alpha : float, default=1.0
          Constant that scales the overall regularization term.
  
      l1_ratio : float in the interval [0, 1]; default=0.5
          Constant that mixes L1 and TV penalization.
          l1_ratio == 0 : just smooth. l1_ratio == 1 : just lasso.
  
      mask : ndarray, shape (nx, ny, nz)
          The support of this mask defines the ROIs being considered in
          the problem.
  
      max_iter : int, default=100
          Defines the iterations for the solver.
  
      prox_max_iter : int, default=5000
          Maximum number of iterations for inner FISTA loop in which
          the prox of TV is approximated.
  
      tol : float, default=1e-4
          Defines the tolerance for convergence.
  
      loss : string
          Loss model for regression. Can be "mse" (for squared loss) or
          "logistic" (for logistic loss).
  
      lipschitz_constant : float, optional (default None)
          Lipschitz constant (i.e an upper bound of) of gradient of smooth part
          of the energy being minimized. If no value is specified (None),
          then it will be calculated.
  
      callback : callable(dict) -> bool, optional (default None)
          Function called at the end of every energy descendent iteration of the
          solver. If it returns True, the loop breaks.
  
      Returns
      -------
      w : ndarray, shape (n_features,)
         The solution vector (Where `w_size` is the size of the support of the
         mask.)
  
      objective : array of floats
          Objective function (fval) computed on every iteration.
  
      solver_info: float
          Solver information, for warm start.
  
      """
      # sanitize loss
      if loss not in ["mse", "logistic"]:
          raise ValueError(
              f"'{loss}' loss not implemented. Should be 'mse' or 'logistic"
          )
  
      # shape of image box
      flat_mask = mask.ravel()
      volume_shape = mask.shape
  
      # in logistic regression, we fit the intercept explicitly
      w_size = X.shape[1] + int(loss == "logistic")
  
      def unmaskvec(w):
          if loss == "mse":
              return unmask_from_to_3d_array(w, mask)
          else:
              return np.append(
                  unmask_from_to_3d_array(w[:-1], mask), w[-1]
              )
  
      def maskvec(w):
          if loss == "mse":
              return w[flat_mask]
          else:
              return np.append(w[:-1][flat_mask], w[-1])
  
      # function to compute derivative of f1
      def f1_grad(w):
          if loss == "logistic":
              return logistic_loss_grad(X, y, w)
          else:
              return squared_loss_grad(X, y, w)
  
      # function to compute total energy (i.e smooth (f1) + nonsmooth (f2) parts)
      def total_energy(w):
          return _tvl1_objective(
              X, y, w, alpha, l1_ratio, mask, loss=loss
          )
  
      # Lipschitz constant of f1_grad
      if lipschitz_constant is None:
          if loss == "mse":
              lipschitz_constant = 1.05 * spectral_norm_squared(X)
          else:
              lipschitz_constant = (
                  1.1 * logistic_loss_lipschitz_constant(X)
              )
  
      # proximal operator of nonsmooth proximable part of energy (f2)
      if loss == "mse":
  
          def f2_prox(w, stepsize, dgap_tol, init=None):
              out, info = prox_tvl1(
                  unmaskvec(w),
                  weight=alpha * stepsize,
                  l1_ratio=l1_ratio,
                  dgap_tol=dgap_tol,
                  init=unmaskvec(init),
                  max_iter=prox_max_iter,
                  verbose=verbose,
              )
              return maskvec(out.ravel()), info
  
      else:
  
          def f2_prox(w, stepsize, dgap_tol, init=None):
              out, info = prox_tvl1_with_intercept(
                  unmaskvec(w),
                  volume_shape,
                  l1_ratio,
                  alpha * stepsize,
                  dgap_tol,
                  prox_max_iter,
                  init=unmask_from_to_3d_array(init[:-1], mask)
                  if init is not None
                  else None,
                  verbose=verbose,
              )
              return maskvec(out.ravel()), info
  
      # invoke m-FISTA solver
      w, obj, init = mfista(
          f1_grad,
          f2_prox,
          total_energy,
          lipschitz_constant,
          w_size,
          dgap_factor=(0.1 + l1_ratio) ** 2,
          tol=tol,
          init=init,
          verbose=verbose,
          max_iter=max_iter,
          callback=callback,
      )
  
      return w, obj, init
  
file_path: nilearn/nilearn/decoding/space_net_solvers.py
imports: from math import sqrt
  import numpy
  from nilearn.masking import unmask_from_to_3d_array
  from ._objective_functions import divergence, gradient, gradient_id, logistic_loss, logistic_loss_grad, logistic_loss_lipschitz_constant, spectral_norm_squared, squared_loss, squared_loss_grad
  from ._proximal_operators import prox_l1, prox_l1_with_intercept, prox_tvl1, prox_tvl1_with_intercept
  from .fista import mfista
label_desc: Use image node_id 13 for calling a global function with example usage: tvl1_solver(X, y, alpha, l1_ratio, mask, loss, max_iter, lipschitz_constant, init, prox_max_iter, tol, callback, verbose) and returns: w,  obj,  init, _tvl1_objective, unmask_from_to_3d_array, np, w, np, logistic_loss_grad, squared_loss_grad, maskvec,  info, maskvec,  info