-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Change docstring for psd_wrap
to be clear about undefined behavior
#2362
Comments
Hi @jhk23! Thanks for the write up and for making the example reproducible! As documented, the
This might be useful in several cases:
If you pass a matrix that is in fact not PSD, you get undefined behaviour. The solver might be able to handle small violations, but if the matrix is far from PSD, basically anything goes. Notice that you event got a warning:
|
Hi @phschiele, thank you for a prompt response!
Thanks! |
I agree that "asserts" could be interpreted as "this atom asserts that the provided matrix is PSD". We have a keyword argument to
Yes, should, but the larger the violation, the higher the chances that it won't work.
This is how we compute the residual in CVXPY: cvxpy/cvxpy/constraints/second_order.py Lines 59 to 72 in b8e18a6
The atom presents a promise by the user. If it is not upheld, violations may follow from this. So I would say if someone actively decides to skip validations, then it is also implied that the returned solution must be treated more carefully. I do think the suggested docstring makes this more clear.
|
Thanks for your answers.
I meant to ask if you know SOTA methods to quantify how far a matrix is from being PSD, so that I can have prior understanding of how likely the convex solver is to fail. Also, are you aware of any convex optimization solver that requires matrices to be PSD only in the feasible region, not globally? |
Action itemsWe should change the docstring of
Other Answering remaining questions from @jhk23The matter of quantifying the distance from a given matrix to the set of PSD matrices is very well understood. In full generality (i.e., independent of the metric you used for your vector space) it could be cast as a convex optimization problem. In practical situations (when the metric is induced by the spectral norm, Frobenius norm, or other "unitarily invariant" norm) the distance can be computed by finding an eigendecomposition. The following code shows how that can be done. import cvxpy as cp
import scipy.linalg as la
def split_into_psd_nsd(M : np.ndarray, TOL: float = 1e-14):
"""
Given a real-symmetric or complex-Hermitian matrix M, compute a positive semidefinite
matrix M_pos and a negative semidefinite matrix M_neg so that M = M_pos + M_neg.
If "norm(...)" computes a unitarily invariant norm of a matrix, then the distance from M
to the set of PSD matrices is dist = norm(M_neg).
"""
n = M.shape[0]
if la.norm( M - M.T.conj(), 'fro' ) > TOL * np.sqrt(n):
raise ValueError('Input matrix must be real-symmetric or Hermitian.')
eigvals, eigvecs = la.eigh(M)
pos = eigvals >= 0
num_pos = np.count_nonzero(pos)
if num_pos == n:
return M, np.zeros((n, n))
neg = eigvals < 0
num_neg = np.count_nonzero(neg)
if num_neg == n:
return np.zeros((n, n)), M
psd_eigvecs = eigvecs[:, pos].reshape((n, num_pos))
nsd_eigvecs = eigvecs[:, neg].reshape((n, num_neg))
psd_part = psd_eigvecs @ np.diag(eigvals[pos]) @ psd_eigvecs.T.conj()
nsd_part = nsd_eigvecs @ np.diag(eigvals[neg]) @ nsd_eigvecs.T.conj()
return psd_part, nsd_part As for your question:
The short answer is no. The longer answer is that it depends on what you mean to only be PSD in a feasible region. The usual definition of being PSD is that a matrix However, if you talk about being PSD over sets other than linear subspaces then things get very nasty. For example, suppose we want to talk about being PSD over the nonnegative orthant |
psd_wrap
to be clear about undefined behavior
Maintainer note. Skip to #2362 (comment) to see the conclusion we came to about this GitHub Issue.
Original report below.
Describe the bug
A small optimization problem is solved with 'optimal' status while a constraint for quadratic form of matrix M is violated massively: its value at the optimum is 14 while its upper bound is 4. This is obviously above any reasonable feasibility tolerance. This behaviour is observed with several optimizers: ECOS, SCS and CLARABEL, and others have not been tested.
The matrix M is NOT positive semidefinite, which violates a convexity condition for constraints in convex optimization. I thought that
psd_wrap()
handles this case by making sure the solution does not imply a negative quadratic form of M. However, it seems to simply suppress the error message 'Your problem does not follow DCP rules'. Importantly, this suppression should not lead to solutions that breach constraints.To Reproduce
Find the data attached.
data.csv
matrix.csv
Expected behavior
If an optimal solution is found, violation of any constraint, including the constraint for the quadratic form, must be below feastol. If a solver cannot reach an optimal solution because a matrix is not PSD, the failure message should be rendered, stating that a non-PSD matrix is the reason for the optimization failure.
Output
Version
Additional context
If I adjust the matrix M slightly to make it PSD, the solver finds the solution that does not violate the constraint for the quadratic form of the original M.
The text was updated successfully, but these errors were encountered: