code: def smooth(x0, rho, gamma, axis=0):
      
  
      # Apply Laplacian smoothing
      n = x0.shape[axis]
      lap_op = spdiags([(2 + rho / gamma) * np.ones(n), -1 * np.ones(n), -1 * np.ones(n)], [0, -1, 1], n, n, format='csc')
      x_out = np.rollaxis(spsolve(gamma * lap_op, rho * np.rollaxis(x0, axis, 0)), axis, 0)
  
      return x_out
docs: Proximal operator for a smoothing function enforced via the discrete laplacian operator
  
      Notes
      -----
      Currently only works with matrices (2-D arrays) as input
  
      Parameters
      ----------
      x0 : array_like
          The starting or initial point used in the proximal update step
  
      rho : float
          Momentum parameter for the proximal step (larger value -> stays closer to x0)
  
      gamma : float
          A constant that weights how strongly to enforce the constraint
  
      Returns
      -------
      theta : array_like
          The parameter vector found after running the proximal update step