]> gitweb.michael.orlitzky.com - dunshire.git/blobdiff - src/dunshire/cones.py
Fix SymmetricPSD documentation and add the column-major vec() function.
[dunshire.git] / src / dunshire / cones.py
index b60811e548de76d95abe0933a245b5a52141b606..2609b16eea729651c7d005c226d5f47ab4cd616c 100644 (file)
@@ -4,7 +4,7 @@ SymmetricCone) supported by CVXOPT.
 """
 
 from cvxopt import matrix
-from matrices import norm
+from matrices import eigenvalues, norm
 
 class SymmetricCone:
     """
@@ -12,11 +12,9 @@ class SymmetricCone:
 
     There are three types of symmetric cones supported by CVXOPT:
 
-      * The nonnegative orthant in the real n-space.
-
-      * The Lorentz "ice cream" cone, or the second-order cone.
-
-      * The cone of symmetric positive-semidefinite matrices.
+      1. The nonnegative orthant in the real n-space.
+      2. The Lorentz "ice cream" cone, or the second-order cone.
+      3. The cone of symmetric positive-semidefinite matrices.
 
     This class is intended to encompass them all.
     """
@@ -28,15 +26,30 @@ class SymmetricCone:
         product of them), the only information that we need is its
         dimension. We take that dimension as a parameter, and store it
         for later.
+
+        INPUT:
+
+        - ``dimension`` -- the dimension of this cone.
+
         """
         if dimension <= 0:
             raise ValueError('cones must have dimension greater than zero')
 
         self._dimension = dimension
 
+
     def __contains__(self, point):
         """
         Return whether or not ``point`` belongs to this cone.
+
+        EXAMPLES:
+
+            >>> K = SymmetricCone(5)
+            >>> matrix([1,2]) in K
+            Traceback (most recent call last):
+            ...
+            NotImplementedError
+
         """
         raise NotImplementedError
 
@@ -44,6 +57,14 @@ class SymmetricCone:
         """
         Return whether or not ``point`` belongs to the interior
         of this cone.
+
+        EXAMPLES:
+
+            >>> K = SymmetricCone(5)
+            >>> K.contains_strict(matrix([1,2]))
+            Traceback (most recent call last):
+            ...
+            NotImplementedError
         """
         raise NotImplementedError
 
@@ -56,6 +77,13 @@ class SymmetricCone:
         should not need to be overridden in subclasses. We prefer to do
         any special computation in ``__init__()`` and record the result
         in ``self._dimension``.
+
+        EXAMPLES:
+
+            >>> K = SymmetricCone(5)
+            >>> K.dimension()
+            5
+
         """
         return self._dimension
 
@@ -288,13 +316,24 @@ class IceCream(SymmetricCone):
 
 class SymmetricPSD(SymmetricCone):
     """
-    The nonnegative orthant in ``n`` dimensions.
+    The cone of real symmetric positive-semidefinite matrices.
+
+    This cone has a dimension ``n`` associated with it, but we let ``n``
+    refer to the dimension of the domain of our matrices and not the
+    dimension of the (much larger) space in which the matrices
+    themselves live. In other words, our ``n`` is the ``n`` that appears
+    in the usual notation `S^{n}` for symmetric matrices.
+
+    As a result, the cone ``SymmetricPSD(n)`` lives in a space of dimension
+    ``(n**2 + n)/2)``.
 
     EXAMPLES:
 
         >>> K = SymmetricPSD(3)
         >>> print(K)
         Cone of symmetric positive-semidefinite matrices on the real 3-space
+        >>> K.dimension()
+        3
 
     """
     def __str__(self):
@@ -306,6 +345,134 @@ class SymmetricPSD(SymmetricCone):
         return tpl.format(self.dimension())
 
 
+    def __contains__(self, point):
+        """
+        Return whether or not ``point`` belongs to this cone.
+
+        INPUT:
+
+        An instance of the ``cvxopt.base.matrix`` class having
+        dimensions ``(n,n)`` where ``n`` is the dimension of this cone.
+
+        EXAMPLES:
+
+            >>> K = SymmetricPSD(2)
+            >>> matrix([[1,0],[0,1]]) in K
+            True
+
+            >>> K = SymmetricPSD(2)
+            >>> matrix([[0,0],[0,0]]) in K
+            True
+
+            >>> K = SymmetricPSD(3)
+            >>> matrix([[2,-1,0],[-1,2,-1],[0,-1,2]]) in K
+            True
+
+            >>> K = SymmetricPSD(5)
+            >>> A = matrix([[5,4,3,2,1],
+            ...            [4,5,4,3,2],
+            ...            [3,4,5,4,3],
+            ...            [2,3,4,5,4],
+            ...            [1,2,3,4,5]])
+            >>> A in K
+            True
+
+            >>> K = SymmetricPSD(5)
+            >>> A = matrix([[1,0,0,0,0],
+            ...            [0,1,0,0,0],
+            ...            [0,0,0,0,0],
+            ...            [0,0,0,1,0],
+            ...            [0,0,0,0,1]])
+            >>> A in K
+            True
+
+            >>> K = SymmetricPSD(2)
+            >>> [[1,2],[2,3]] in K
+            Traceback (most recent call last):
+            ...
+            TypeError: the given point is not a cvxopt.base.matrix
+
+            >>> K = SymmetricPSD(3)
+            >>> matrix([[1,2],[3,4]]) in K
+            Traceback (most recent call last):
+            ...
+            TypeError: the given point has the wrong dimensions
+
+        """
+        if not isinstance(point, matrix):
+            raise TypeError('the given point is not a cvxopt.base.matrix')
+        if not point.size == (self.dimension(), self.dimension()):
+            raise TypeError('the given point has the wrong dimensions')
+        if not point.typecode == 'd':
+            point = matrix(point, (self.dimension(), self.dimension()), 'd')
+        return all([e >= 0 for e in eigenvalues(point)])
+
+
+    def contains_strict(self, point):
+        """
+        Return whether or not ``point`` belongs to the interior
+        of this cone.
+
+        INPUT:
+
+        An instance of the ``cvxopt.base.matrix`` class having
+        dimensions ``(n,n)`` where ``n`` is the dimension of this cone.
+        Its type code must be 'd'.
+
+        EXAMPLES:
+
+            >>> K = SymmetricPSD(2)
+            >>> K.contains_strict(matrix([[1,0],[0,1]]))
+            True
+
+            >>> K = SymmetricPSD(2)
+            >>> K.contains_strict(matrix([[0,0],[0,0]]))
+            False
+
+            >>> K = SymmetricPSD(3)
+            >>> matrix([[2,-1,0],[-1,2,-1],[0,-1,2]]) in K
+            True
+
+            >>> K = SymmetricPSD(5)
+            >>> A = matrix([[5,4,3,2,1],
+            ...            [4,5,4,3,2],
+            ...            [3,4,5,4,3],
+            ...            [2,3,4,5,4],
+            ...            [1,2,3,4,5]])
+            >>> A in K
+            True
+
+            >>> K = SymmetricPSD(5)
+            >>> A = matrix([[1,0,0,0,0],
+            ...            [0,1,0,0,0],
+            ...            [0,0,0,0,0],
+            ...            [0,0,0,1,0],
+            ...            [0,0,0,0,1]])
+            >>> K.contains_strict(A)
+            False
+
+            >>> K = SymmetricPSD(2)
+            >>> K.contains_strict([[1,2],[2,3]])
+            Traceback (most recent call last):
+            ...
+            TypeError: the given point is not a cvxopt.base.matrix
+
+            >>> K = SymmetricPSD(3)
+            >>> K.contains_strict(matrix([[1,2],[3,4]]))
+            Traceback (most recent call last):
+            ...
+            TypeError: the given point has the wrong dimensions
+
+        """
+        if not isinstance(point, matrix):
+            raise TypeError('the given point is not a cvxopt.base.matrix')
+        if not point.size == (self.dimension(), self.dimension()):
+            raise TypeError('the given point has the wrong dimensions')
+        if not point.typecode == 'd':
+            point = matrix(point, (self.dimension(), self.dimension()), 'd')
+        return all([e > 0 for e in eigenvalues(point)])
+
+
 class CartesianProduct(SymmetricCone):
     """
     A cartesian product of symmetric cones, which is itself a symmetric