Cvxpy: add symmetry checks to ``.value`` calls on symmetric matrix atoms

Created on 2 Feb 2020  路  4Comments  路  Source: cvxgrp/cvxpy

Max eigenvalue seem to be very different than when I calculate it with numpy. There is also a good chance that I am misunderstanding something. I believe numpy's solution is the correct one.

>>>cp.lambda_max(np.array([[0., 1.0],[-578.09782526, -67.43751973]])).value
>>>545.3615889098268
>>>np.linalg.eig(np.array([[0., 1.0],[-578.09782526, -67.43751973]]))[0]
>>>array([-10.07860459, -57.35891514])

Version

  • OS: Ubuntu 18.04
  • CVXPY Version: 1.0.25

Thanks for the help and/or suggestions for workarounds. Essentially, I want to put a constraint to ensure that the output of the optimization gives me a stabilizing controller.

All 4 comments

The function lambda_max(A) is only convex when A is a symmetric (or Hermitian) matrix. Your matrix is not symmetric, and that is why you are seeing strange behavior.

To get into details: CVXPY calls specialized a numpy function to compute lambda_max under these assumptions. Here is the code showing what happens when we apply your matrix:

>>> A = np.array([[0., 1.0],[-578.09782526, -67.43751973]])
>>> np.linalg.eigh(A)
>>> (array([-612.79910864,  545.36158891]), array([[ 0.68621129, -0.72740227],
        [ 0.72740227,  0.68621129]]))

the first entry in the tuple returned by eigh is the eigenvalues, and that max of that vector is what CVXPY reported.

As to your specific problem-- I don't think convex optimization will help you. In order to enforce stability of a nonsymmetric matrix A, you need to get a handle on the real part of A's eigenvalues. The map from a nonsymmetric matrix to the largest eigenvalue (measured by real-part) is not convex. Now, there are some special nonconvex constraints that the optimization community has figured out how to handle. However a stability constraint is not one of those special cases. Even projecting A onto the set of stable matrices takes serious work. See https://arxiv.org/pdf/1611.00595.pdf for more information.

For developers / contributors: here are the TODO's for resolving this issue:

  • Add some basic input checking, where lambda_max.value raises an exception when the input is far-from-symmetric.
  • Check other symmetric-matrix atoms to see if .value can be called on nonsymmetric inputs.
  • Note: This won't happen if the input is the result of solving an optimization problem, since we constrain input expressions to be symmetric. This case happened because the input matrix was never subject to cvxpy's backend symmetry constraints.

@rileyjmurray Thanks so much! Ya, this makes sense.

Closed by #944 and #950.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

angeris picture angeris  路  8Comments

skoudoro picture skoudoro  路  3Comments

wfrece picture wfrece  路  9Comments

moehle picture moehle  路  5Comments

Bonnevie picture Bonnevie  路  6Comments