]> gitweb.michael.orlitzky.com - sage.d.git/blobdiff - mjo/cone/symmetric_psd.py
cone/rearrangement.py: fix the test for propriety.
[sage.d.git] / mjo / cone / symmetric_psd.py
index 514d0392c1fbe4fbae72057a87fd5524744c0668..1b3dd8ab6d8905a1af202eec3816c46ece906561 100644 (file)
@@ -6,14 +6,6 @@ all symmetric positive-semidefinite matrices (as a subset of
 
 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('../../'))
-
-
 def is_symmetric_psd(A):
     """
     Determine whether or not the matrix ``A`` is symmetric
@@ -28,6 +20,10 @@ def is_symmetric_psd(A):
     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
@@ -73,17 +69,24 @@ def unit_eigenvectors(A):
 
     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)
@@ -92,17 +95,9 @@ def unit_eigenvectors(A):
         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 )
 
 
 
@@ -145,6 +140,10 @@ def factor_psd(A):
     `$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
@@ -194,10 +193,10 @@ def factor_psd(A):
     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()
 
@@ -241,6 +240,10 @@ def random_psd(V, accept_zero=True, rank=None):
     ``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::
@@ -300,9 +303,8 @@ def random_psd(V, accept_zero=True, rank=None):
         # 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.