from sage.all import *
-# Sage doesn't load ~/.sage/init.sage during testing (sage -t), so we
-# have to explicitly mangle our sitedir here so that "mjo.symbolic"
-# resolves.
-from os.path import abspath
-from site import addsitedir
-addsitedir(abspath('../../'))
-from mjo.symbolic import matrix_simplify_full
-
-
def is_symmetric_psd(A):
"""
Determine whether or not the matrix ``A`` is symmetric
Either ``True`` if ``A`` is symmetric positive-semidefinite, or
``False`` otherwise.
+ SETUP::
+
+ sage: from mjo.cone.symmetric_psd import is_symmetric_psd
+
EXAMPLES:
Every completely positive matrix is symmetric
INPUT:
- - ``A`` - The matrix whose eigenvectors we want to compute.
+ - ``A`` -- The matrix whose unit eigenvectors we want to compute.
OUTPUT:
A list of (eigenvalue, eigenvector) pairs where each eigenvector is
- associated with its paired eigenvalue of ``A`` and has norm `1`.
+ associated with its paired eigenvalue of ``A`` and has norm `1`. If
+ the base ring of ``A`` is not algebraically closed, then returned
+ eigenvectors may (necessarily) be over its algebraic closure and not
+ the base ring of ``A`` itself.
+
+ SETUP::
+
+ sage: from mjo.cone.symmetric_psd import unit_eigenvectors
EXAMPLES::
sage: A = matrix(QQ, [[0, 2, 3], [2, 0, 0], [3, 0, 0]])
- sage: unit_evs = unit_eigenvectors(A)
+ sage: unit_evs = list(unit_eigenvectors(A))
sage: bool(unit_evs[0][1].norm() == 1)
True
sage: bool(unit_evs[1][1].norm() == 1)
True
"""
- # This will give us a list of lists whose elements are the
- # eigenvectors we want.
- ev_lists = [ (val,vecs) for (val,vecs,multiplicity)
- in A.eigenvectors_right() ]
-
- # Pair each eigenvector with its eigenvalue and normalize it.
- evs = [ [(l, vec/vec.norm()) for vec in vecs] for (l,vecs) in ev_lists ]
-
- # Flatten the list, abusing the fact that "+" is overloaded on lists.
- return sum(evs, [])
-
+ return ( (val,vec.normalized())
+ for (val,vecs,multiplicity) in A.eigenvectors_right()
+ for vec in vecs )
`$D$` will have dimension `$k \times k$`. In the end everything
works out the same.
+ SETUP::
+
+ sage: from mjo.cone.symmetric_psd import factor_psd
+
EXAMPLES:
Create a symmetric positive-semidefinite matrix over the symbolic
sage: A = matrix(SR, [[0, 2, 3], [2, 0, 0], [3, 0, 0]])
sage: X = factor_psd(A)
- sage: A2 = matrix_simplify_full(X*X.transpose())
+ sage: A2 = (X*X.transpose()).simplify_full()
sage: A == A2
True
all_evs = unit_eigenvectors(A)
evs = [ (val,vec) for (val,vec) in all_evs if not val == 0 ]
- d = [ sqrt(val) for (val,vec) in evs ]
+ d = ( val.sqrt() for (val,vec) in evs )
root_D = diagonal_matrix(d).change_ring(A.base_ring())
- Q = matrix(A.base_ring(), [ vec for (val,vec) in evs ]).transpose()
+ Q = matrix(A.base_ring(), ( vec for (val,vec) in evs )).transpose()
return Q*root_D*Q.transpose()
``accept_zero`` is ``False``, we restart the process from the
beginning.
+ SETUP::
+
+ sage: from mjo.cone.symmetric_psd import is_symmetric_psd, random_psd
+
EXAMPLES:
Well, it doesn't crash at least::
# Use the one the user gave us.
rank_A = rank
- # Begin with the zero matrix, and add projectors to it if we have
- # any.
- A = V.zero_element().column()*V.zero_element().row()
+ # Begin with the zero matrix, and add projectors to it if we have any.
+ A = V.zero().column()*V.zero().row()
# Careful, begin at idx=1 so that we only generate a projector
# when rank_A is greater than zero.