From 3bfeedd6454e7686dce939a1f2eee27ab528e9a1 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Mon, 10 Oct 2016 14:46:27 -0400 Subject: [PATCH] Finish overhauling the docstrings to numpy format. --- doc/source/index.rst | 5 -- src/dunshire/cones.py | 14 +++-- src/dunshire/games.py | 133 ++++++++++++++++++++++++++++----------- src/dunshire/matrices.py | 12 ++++ 4 files changed, 118 insertions(+), 46 deletions(-) diff --git a/doc/source/index.rst b/doc/source/index.rst index 2d04425..766c5b5 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -3,11 +3,6 @@ Dunshire .. include:: ../README.rst -Contents: - -.. toctree:: - :maxdepth: 2 - API Documentation ----------------- diff --git a/src/dunshire/cones.py b/src/dunshire/cones.py index 764e1da..905dd8e 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, -class:`SymmetricCone`) supported by CVXOPT. +:class:`SymmetricCone`) supported by CVXOPT. """ from cvxopt import matrix @@ -29,6 +29,12 @@ class SymmetricCone: dimension : int The dimension of this cone. + Raises + ------ + + ValueError + If you try to create a cone with dimension zero or less. + """ def __init__(self, dimension): """ @@ -434,17 +440,17 @@ class IceCream(SymmetricCone): class SymmetricPSD(SymmetricCone): - """ + r""" 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. + in the usual notation :math:`S^{n}` for symmetric matrices. As a result, the cone ``SymmetricPSD(n)`` lives in a space of dimension - ``(n**2 + n)/2)``. + :math:`\left(n^{2} + n\right)/2)`. Examples -------- diff --git a/src/dunshire/games.py b/src/dunshire/games.py index e2d2978..9f0b0ce 100644 --- a/src/dunshire/games.py +++ b/src/dunshire/games.py @@ -122,23 +122,91 @@ class Solution: class SymmetricLinearGame: - """ + r""" A representation of a symmetric linear game. - The data for a linear game are, + The data for a symmetric linear game are, * A "payoff" operator ``L``. - * A cone ``K``. - * A point ``e`` in the interior of ``K``. - * A point ``f`` in the interior of the dual of ``K``. - - In a symmetric game, the cone ``K`` is be self-dual. We therefore - name the two interior points ``e1`` and ``e2`` to indicate that - they come from the same cone but are "chosen" by players one and - two respectively. + * A symmetric cone ``K``. + * Two points ``e1`` and ``e2`` in the interior of ``K``. The ambient space is assumed to be the span of ``K``. + With those data understood, the game is played as follows. Players + one and two choose points :math:`x` and :math:`y` respectively, from + their respective strategy sets, + + .. math:: + \begin{aligned} + \Delta_{1} + &= + \left\{ + x \in K \ \middle|\ \left\langle x, e_{2} \right\rangle = 1 + \right\}\\ + \Delta_{2} + &= + \left\{ + y \in K \ \middle|\ \left\langle y, e_{1} \right\rangle = 1 + \right\}. + \end{aligned} + + Afterwards, a "payout" is computed as :math:`\left\langle + L\left(x\right), y \right\rangle` and is paid to player one out of + player two's pocket. The game is therefore zero sum, and we suppose + that player one would like to guarantee himself the largest minimum + payout possible. That is, player one wishes to, + + .. math:: + \begin{aligned} + \text{maximize } + &\underset{y \in \Delta_{2}}{\min}\left( + \left\langle L\left(x\right), y \right\rangle + \right)\\ + \text{subject to } & x \in \Delta_{1}. + \end{aligned} + + Player two has the simultaneous goal to, + + .. math:: + \begin{aligned} + \text{minimize } + &\underset{x \in \Delta_{1}}{\max}\left( + \left\langle L\left(x\right), y \right\rangle + \right)\\ + \text{subject to } & y \in \Delta_{2}. + \end{aligned} + + These goals obviously conflict (the game is zero sum), but an + existence theorem guarantees at least one optimal min-max solution + from which neither player would like to deviate. This class is + able to find such a solution. + + Parameters + ---------- + + L : list of list of float + A matrix represented as a list of ROWS. This representation + agrees with (for example) SageMath and NumPy, but not with CVXOPT + (whose matrix constructor accepts a list of columns). + + K : :class:`SymmetricCone` + The symmetric cone instance over which the game is played. + + e1 : iterable float + The interior point of ``K`` belonging to player one; it + can be of any iterable type having the correct length. + + e2 : iterable float + The interior point of ``K`` belonging to player two; it + can be of any enumerable type having the correct length. + + Raises + ------ + + ValueError + If either ``e1`` or ``e2`` lie outside of the cone ``K``. + Examples -------- @@ -161,7 +229,6 @@ class SymmetricLinearGame: [ 2] [ 3]. - Lists can (and probably should) be used for every argument:: >>> from cones import NonnegativeOrthant @@ -242,23 +309,6 @@ class SymmetricLinearGame: def __init__(self, L, K, e1, e2): """ Create a new SymmetricLinearGame object. - - INPUT: - - - ``L`` -- an square matrix represented as a list of lists - of real numbers. ``L`` itself is interpreted as a list of - ROWS, which agrees with (for example) SageMath and NumPy, - but not with CVXOPT (whose matrix constructor accepts a - list of columns). - - - ``K`` -- a SymmetricCone instance. - - - ``e1`` -- the interior point of ``K`` belonging to player one; - it can be of any enumerable type having the correct length. - - - ``e2`` -- the interior point of ``K`` belonging to player two; - it can be of any enumerable type having the correct length. - """ self._K = K self._e1 = matrix(e1, (K.dimension(), 1)) @@ -292,16 +342,20 @@ class SymmetricLinearGame: def solution(self): """ - Solve this linear game and return a Solution object. + Solve this linear game and return a :class:`Solution`. - OUTPUT: + Returns + ------- - If the cone program associated with this game could be - successfully solved, then a Solution object containing the - game's value and optimal strategies is returned. If the game - could *not* be solved -- which should never happen -- then a - GameUnsolvableException is raised. It can be printed to get the - raw output from CVXOPT. + :class:`Solution` + A :class:`Solution` object describing the game's value and + the optimal strategies of both players. + + Raises + ------ + GameUnsolvableException + If the game could not be solved (if an optimal solution to its + associated cone program was not found). Examples -------- @@ -395,9 +449,14 @@ class SymmetricLinearGame: return Solution(p1_value, p1_optimal, p2_optimal) def dual(self): - """ + r""" Return the dual game to this game. + If :math:`G = \left(L,K,e_{1},e_{2}\right)` is a linear game, + then its dual is :math:`G^{*} = + \left(L^{*},K^{*},e_{2},e_{1}\right)`. However, since this cone + is symmetric, :math:`K^{*} = K`. + Examples -------- diff --git a/src/dunshire/matrices.py b/src/dunshire/matrices.py index 3670d8f..5f47f97 100644 --- a/src/dunshire/matrices.py +++ b/src/dunshire/matrices.py @@ -156,6 +156,12 @@ def identity(domain_dim): matrix A ``domain_dim``-by-``domain_dim`` dense integer identity matrix. + Raises + ------ + + ValueError + If you ask for the identity on zero or fewer dimensions. + Examples -------- @@ -191,6 +197,12 @@ def inner_product(vec1, vec2): float The inner product of ``vec1`` and ``vec2``. + Raises + ------ + + TypeError + If the lengths of ``vec1`` and ``vec2`` differ. + Examples -------- -- 2.44.2