From 37474d15ac218b1651b116c3216d99ca3ac18823 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Mon, 10 Oct 2016 13:44:29 -0400 Subject: [PATCH] Switch the docs style of cones.py and update cartesian product containment. The docs for cones.py have all been switched (roughly) to use the numpy style. In the process, I noticed that cartesian product containment was a lot weirder than it needs to be. The "point" that the __contains__() and contains_strict() methods take is now a tuple corresponding to the factors of the cartesian product. --- src/dunshire/cones.py | 394 +++++++++++++++++++++++++++++++----------- 1 file changed, 296 insertions(+), 98 deletions(-) diff --git a/src/dunshire/cones.py b/src/dunshire/cones.py index 2609b16..764e1da 100644 --- a/src/dunshire/cones.py +++ b/src/dunshire/cones.py @@ -1,6 +1,6 @@ """ Class definitions for all of the symmetric cones (and their superclass, -SymmetricCone) supported by CVXOPT. +class:`SymmetricCone`) supported by CVXOPT. """ from cvxopt import matrix @@ -17,20 +17,22 @@ class SymmetricCone: 3. The cone of symmetric positive-semidefinite matrices. This class is intended to encompass them all. - """ - def __init__(self, dimension): - """ - A generic constructor for symmetric cones. - When constructing a single symmetric cone (i.e. not a cartesian - product of them), the only information that we need is its - dimension. We take that dimension as a parameter, and store it - for later. + When constructing a single symmetric cone (i.e. not a + :class:`CartesianProduct` of them), the only information that we + need is its dimension. We take that dimension as a parameter, and + store it for later. - INPUT: + Parameters + ---------- - - ``dimension`` -- the dimension of this cone. + dimension : int + The dimension of this cone. + """ + def __init__(self, dimension): + """ + A generic constructor for symmetric cones. """ if dimension <= 0: raise ValueError('cones must have dimension greater than zero') @@ -42,7 +44,20 @@ class SymmetricCone: """ Return whether or not ``point`` belongs to this cone. - EXAMPLES: + Parameters + ---------- + + point : matrix + The point to test for membership in this cone. + + Raises + ------ + + NotImplementedError + Always, this method must be implemented in subclasses. + + Examples + -------- >>> K = SymmetricCone(5) >>> matrix([1,2]) in K @@ -53,12 +68,26 @@ class SymmetricCone: """ raise NotImplementedError + def contains_strict(self, point): """ Return whether or not ``point`` belongs to the interior of this cone. - EXAMPLES: + Parameters + ---------- + + point : matrix + The point to test for strict membership in this cone. + + Raises + ------ + + NotImplementedError + Always, this method must be implemented in subclasses. + + Examples + -------- >>> K = SymmetricCone(5) >>> K.contains_strict(matrix([1,2])) @@ -68,6 +97,7 @@ class SymmetricCone: """ raise NotImplementedError + def dimension(self): """ Return the dimension of this symmetric cone. @@ -78,7 +108,15 @@ class SymmetricCone: any special computation in ``__init__()`` and record the result in ``self._dimension``. - EXAMPLES: + Returns + ------- + + int + The stored dimension (from when this cone was constructed) + of this cone. + + Examples + -------- >>> K = SymmetricCone(5) >>> K.dimension() @@ -90,9 +128,10 @@ class SymmetricCone: class NonnegativeOrthant(SymmetricCone): """ - The nonnegative orthant in ``n`` dimensions. + The nonnegative orthant in the given number of dimensions. - EXAMPLES: + Examples + -------- >>> K = NonnegativeOrthant(3) >>> print(K) @@ -106,16 +145,36 @@ class NonnegativeOrthant(SymmetricCone): tpl = 'Nonnegative orthant in the real {:d}-space' return tpl.format(self.dimension()) + def __contains__(self, point): """ Return whether or not ``point`` belongs to this cone. - INPUT: + Parameters + ---------- + + point : matrix + A :class:`cvxopt.base.matrix` having dimensions ``(n,1)`` + where ``n`` is the :meth:`dimension` of this cone. + + Returns + ------- + + bool - An instance of the ``cvxopt.base.matrix`` class having - dimensions ``(n,1)`` where ``n`` is the dimension of this cone. + ``True`` if ``point`` belongs to this cone, ``False`` otherwise. - EXAMPLES: + Raises + ------ + + TypeError + If ``point`` is not a :class:`cvxopt.base.matrix`. + + TypeError + If ``point`` has the wrong dimensions. + + Examples + -------- >>> K = NonnegativeOrthant(3) >>> matrix([1,2,3]) in K @@ -151,12 +210,32 @@ class NonnegativeOrthant(SymmetricCone): Return whether or not ``point`` belongs to the interior of this cone. - INPUT: + Parameters + ---------- + + point : matrix + A :class:`cvxopt.base.matrix` having dimensions ``(n,1)`` + where ``n`` is the :meth:`dimension` of this cone. + + Returns + ------- + + bool - An instance of the ``cvxopt.base.matrix`` class having - dimensions ``(n,1)`` where ``n`` is the dimension of this cone. + ``True`` if ``point`` belongs to the interior of this cone, + ``False`` otherwise. - EXAMPLES: + Raises + ------ + + TypeError + If ``point`` is not a :class:`cvxopt.base.matrix`. + + TypeError + If ``point`` has the wrong dimensions. + + Examples + -------- >>> K = NonnegativeOrthant(3) >>> K.contains_strict(matrix([1,2,3])) @@ -194,9 +273,10 @@ class NonnegativeOrthant(SymmetricCone): class IceCream(SymmetricCone): """ - The nonnegative orthant in ``n`` dimensions. + The Lorentz "ice cream" cone in the given number of dimensions. - EXAMPLES: + Examples + -------- >>> K = IceCream(3) >>> print(K) @@ -215,12 +295,31 @@ class IceCream(SymmetricCone): """ Return whether or not ``point`` belongs to this cone. - INPUT: + Parameters + ---------- + + point : matrix + A :class:`cvxopt.base.matrix` having dimensions ``(n,1)`` + where ``n`` is the :meth:`dimension` of this cone. + + Returns + ------- + + bool - An instance of the ``cvxopt.base.matrix`` class having - dimensions ``(n,1)`` where ``n`` is the dimension of this cone. + ``True`` if ``point`` belongs to this cone, ``False`` otherwise. - EXAMPLES: + Raises + ------ + + TypeError + If ``point`` is not a :class:`cvxopt.base.matrix`. + + TypeError + If ``point`` has the wrong dimensions. + + Examples + -------- >>> K = IceCream(3) >>> matrix([1,0.5,0.5]) in K @@ -267,12 +366,32 @@ class IceCream(SymmetricCone): Return whether or not ``point`` belongs to the interior of this cone. - INPUT: + Parameters + ---------- + + point : matrix + A :class:`cvxopt.base.matrix` having dimensions ``(n,1)`` + where ``n`` is the :meth:`dimension` of this cone. + + Returns + ------- + + bool - An instance of the ``cvxopt.base.matrix`` class having - dimensions ``(n,1)`` where ``n`` is the dimension of this cone. + ``True`` if ``point`` belongs to the interior of this cone, + ``False`` otherwise. - EXAMPLES: + Raises + ------ + + TypeError + If ``point`` is not a :class:`cvxopt.base.matrix`. + + TypeError + If ``point`` has the wrong dimensions. + + Examples + -------- >>> K = IceCream(3) >>> K.contains_strict(matrix([1,0.5,0.5])) @@ -327,7 +446,8 @@ class SymmetricPSD(SymmetricCone): As a result, the cone ``SymmetricPSD(n)`` lives in a space of dimension ``(n**2 + n)/2)``. - EXAMPLES: + Examples + -------- >>> K = SymmetricPSD(3) >>> print(K) @@ -349,12 +469,31 @@ class SymmetricPSD(SymmetricCone): """ Return whether or not ``point`` belongs to this cone. - INPUT: + Parameters + ---------- + + point : matrix + A :class:`cvxopt.base.matrix` having dimensions ``(n,n)`` + where ``n`` is the :meth:`dimension` of this cone. + + Returns + ------- - An instance of the ``cvxopt.base.matrix`` class having - dimensions ``(n,n)`` where ``n`` is the dimension of this cone. + bool - EXAMPLES: + ``True`` if ``point`` belongs to this cone, ``False`` otherwise. + + Raises + ------ + + TypeError + If ``point`` is not a :class:`cvxopt.base.matrix`. + + TypeError + If ``point`` has the wrong dimensions. + + Examples + -------- >>> K = SymmetricPSD(2) >>> matrix([[1,0],[0,1]]) in K @@ -413,13 +552,32 @@ class SymmetricPSD(SymmetricCone): Return whether or not ``point`` belongs to the interior of this cone. - INPUT: + Parameters + ---------- + + point : matrix + A :class:`cvxopt.base.matrix` having dimensions ``(n,n)`` + where ``n`` is the :meth:`dimension` of this cone. + + Returns + ------- - 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'. + bool - EXAMPLES: + ``True`` if ``point`` belongs to the interior of this cone, + ``False`` otherwise. + + Raises + ------ + + TypeError + If ``point`` is not a :class:`cvxopt.base.matrix`. + + TypeError + If ``point`` has the wrong dimensions. + + Examples + -------- >>> K = SymmetricPSD(2) >>> K.contains_strict(matrix([[1,0],[0,1]])) @@ -478,7 +636,8 @@ class CartesianProduct(SymmetricCone): A cartesian product of symmetric cones, which is itself a symmetric cone. - EXAMPLES: + Examples + -------- >>> K = CartesianProduct(NonnegativeOrthant(3), IceCream(2)) >>> print(K) @@ -492,6 +651,7 @@ class CartesianProduct(SymmetricCone): super().__init__(my_dimension) self._factors = factors + def __str__(self): """ Output a human-readable description of myself. @@ -502,60 +662,72 @@ class CartesianProduct(SymmetricCone): format_args += list(self.factors()) return tpl.format(*format_args) + def __contains__(self, point): """ Return whether or not ``point`` belongs to this cone. - INPUT: + The ``point`` is expected to be a tuple of points which will be + tested for membership in this cone's factors. If each point in + the tuple belongs to its corresponding factor, then the whole + point belongs to this cone. Otherwise, it doesn't. - An instance of the ``cvxopt.base.matrix`` class having - dimensions ``(n,1)`` where ``n`` is the dimension of this cone. + Parameters + ---------- - EXAMPLES: + point : tuple of matrix + A tuple of :class:`cvxopt.base.matrix` corresponding to the + :meth:`factors` of this cartesian product. + + Returns + ------- + + bool + + ``True`` if ``point`` belongs to this cone, ``False`` otherwise. + + Raises + ------ + + TypeError + If ``point`` is not a tuple of :class:`cvxopt.base.matrix`. + + TypeError + If any element of ``point`` has the wrong dimensions. + + Examples + -------- >>> K = CartesianProduct(NonnegativeOrthant(3), IceCream(3)) - >>> matrix([1,2,3,1,0.5,0.5]) in K + >>> (matrix([1,2,3]), matrix([1,0.5,0.5])) in K True >>> K = CartesianProduct(NonnegativeOrthant(3), IceCream(3)) - >>> matrix([0,0,0,1,0,1]) in K + >>> (matrix([0,0,0]), matrix([1,0,1])) in K True >>> K = CartesianProduct(NonnegativeOrthant(3), IceCream(3)) - >>> matrix([1,1,1,1,1,1]) in K + >>> (matrix([1,1,1]), matrix([1,1,1])) in K False >>> K = CartesianProduct(NonnegativeOrthant(3), IceCream(3)) - >>> matrix([1,-1,1,1,0,1]) in K + >>> (matrix([1,-1,1]), matrix([1,0,1])) in K False >>> K = CartesianProduct(NonnegativeOrthant(3), IceCream(3)) - >>> [1,2,3,4,5,6] in K + >>> [[1,2,3],[4,5,6]] in K Traceback (most recent call last): ... TypeError: the given point is not a cvxopt.base.matrix >>> K = CartesianProduct(NonnegativeOrthant(3), IceCream(3)) - >>> matrix([1,2]) in K + >>> (matrix([1,2]), matrix([3,4,5,6])) 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(), 1): - raise TypeError('the given point has the wrong dimensions') - - for factor in self.factors(): - # Split off the components of ``point`` corresponding to - # ``factor``. - factor_part = point[0:factor.dimension()] - if not factor_part in factor: - return False - point = point[factor.dimension():] - - return True + return all([p in f for (p,f) in zip(point, self.factors())]) def contains_strict(self, point): @@ -563,60 +735,71 @@ class CartesianProduct(SymmetricCone): Return whether or not ``point`` belongs to the interior of this cone. - INPUT: + The ``point`` is expected to be a tuple of points which will be + tested for membership in this cone's factors. If each point in + the tuple belongs to the interior of its corresponding factor, + then the whole point belongs to the interior of this + cone. Otherwise, it doesn't. - An instance of the ``cvxopt.base.matrix`` class having - dimensions ``(n,1)`` where ``n`` is the dimension of this cone. + Parameters + ---------- - EXAMPLES: + point : tuple of matrix + A tuple of :class:`cvxopt.base.matrix` corresponding to the + :meth:`factors` of this cartesian product. - >>> K = CartesianProduct(NonnegativeOrthant(3), IceCream(3)) - >>> K.contains_strict(matrix([1,2,3,1,0.5,0.5])) - True + Returns + ------- + + bool + + ``True`` if ``point`` belongs to the interior of this cone, + ``False`` otherwise. + + Raises + ------ + + TypeError + If ``point`` is not a tuple of :class:`cvxopt.base.matrix`. + + TypeError + If any element of ``point`` has the wrong dimensions. + + Examples + -------- >>> K = CartesianProduct(NonnegativeOrthant(3), IceCream(3)) - >>> K.contains_strict(matrix([1,2,3,1,0,1])) - False + >>> K.contains_strict((matrix([1,2,3]), matrix([1,0.5,0.5]))) + True >>> K = CartesianProduct(NonnegativeOrthant(3), IceCream(3)) - >>> K.contains_strict(matrix([0,1,1,1,0.5,0.5])) + >>> K.contains_strict((matrix([0,0,0]), matrix([1,0,1]))) False >>> K = CartesianProduct(NonnegativeOrthant(3), IceCream(3)) - >>> K.contains_strict(matrix([1,1,1,1,1,1])) + >>> K.contains_strict((matrix([1,1,1]), matrix([1,1,1]))) False >>> K = CartesianProduct(NonnegativeOrthant(3), IceCream(3)) - >>> K.contains_strict(matrix([1,-1,1,1,0,1])) + >>> K.contains_strict((matrix([1,-1,1]), matrix([1,0,1]))) False >>> K = CartesianProduct(NonnegativeOrthant(3), IceCream(3)) - >>> K.contains_strict([1,2,3,4,5,6]) + >>> K.contains_strict([[1,2,3],[4,5,6]]) Traceback (most recent call last): ... TypeError: the given point is not a cvxopt.base.matrix >>> K = CartesianProduct(NonnegativeOrthant(3), IceCream(3)) - >>> K.contains_strict(matrix([1,2])) + >>> K.contains_strict((matrix([1,2]), matrix([3,4,5,6]))) 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(), 1): - raise TypeError('the given point has the wrong dimensions') - - for factor in self.factors(): - # Split off the components of ``point`` corresponding to - # ``factor``. - factor_part = point[0:factor.dimension()] - if not factor.contains_strict(factor_part): - return False - point = point[factor.dimension():] + return all([f.contains_strict(p) + for (p,f) in zip(point, self.factors())]) - return True def factors(self): @@ -624,7 +807,14 @@ class CartesianProduct(SymmetricCone): Return a tuple containing the factors (in order) of this cartesian product. - EXAMPLES: + Returns + ------- + + tuple of :class:`SymmetricCone`. + The factors of this cartesian product. + + Examples + -------- >>> K = CartesianProduct(NonnegativeOrthant(3), IceCream(2)) >>> len(K.factors()) @@ -633,6 +823,7 @@ class CartesianProduct(SymmetricCone): """ return self._factors + def cvxopt_dims(self): """ Return a dictionary of dimensions corresponding to the factors @@ -641,7 +832,14 @@ class CartesianProduct(SymmetricCone): http://cvxopt.org/userguide/coneprog.html#linear-cone-programs - EXAMPLES: + Returns + ------- + + dict + A dimension dictionary suitable to feed to CVXOPT. + + Examples + -------- >>> K = CartesianProduct(NonnegativeOrthant(3), ... IceCream(2), -- 2.44.2