# Source code for cvxpy.atoms.norm_nuc

"""

This file is part of CVXPY.

CVXPY is free software: you can redistribute it and/or modify
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

CVXPY is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with CVXPY.  If not, see <http://www.gnu.org/licenses/>.
"""

from cvxpy.atoms.atom import Atom
import numpy as np
import scipy.sparse as sp

[docs]class normNuc(Atom):
"""Sum of the singular values.
"""
_allow_complex = True

def __init__(self, A):
super(normNuc, self).__init__(A)

def numeric(self, values):
"""Returns the nuclear norm (i.e. the sum of the singular values) of A.
"""
return np.linalg.norm(values[0], 'nuc')

"""Gives the (sub/super)gradient of the atom w.r.t. each argument.

Matrix expressions are vectorized, so the gradient is a matrix.

Args:
values: A list of numeric values for the arguments.

Returns:
A list of SciPy CSC sparse matrices or None.
"""
U, _, V = np.linalg.svd(values[0])
D = U.dot(V)
return [sp.csc_matrix(D.ravel(order='F')).T]

def shape_from_args(self):
"""Returns the (row, col) shape of the expression.
"""
return tuple()

def sign_from_args(self):
"""Returns sign (is positive, is negative) of the expression.
"""
return (True, False)

def is_atom_convex(self):
"""Is the atom convex?
"""
return True

def is_atom_concave(self):
"""Is the atom concave?
"""
return False

def is_incr(self, idx):
"""Is the composition non-decreasing in argument idx?
"""
return False

def is_decr(self, idx):
"""Is the composition non-increasing in argument idx?
"""
return False