]>
gitweb.michael.orlitzky.com - sage.d.git/blob - mjo/cone/cone.py
1 # Sage doesn't load ~/.sage/init.sage during testing (sage -t), so we
2 # have to explicitly mangle our sitedir here so that "mjo.cone"
4 from os
.path
import abspath
5 from site
import addsitedir
6 addsitedir(abspath('../../'))
13 Compute the Lyapunov (or bilinearity) rank of this cone.
15 The Lyapunov rank of a cone can be thought of in (mainly) two ways:
17 1. The dimension of the Lie algebra of the automorphism group of the
20 2. The dimension of the linear space of all Lyapunov-like
21 transformations on the cone.
25 A closed, convex polyhedral cone.
29 An integer representing the Lyapunov rank of the cone. If the
30 dimension of the ambient vector space is `n`, then the Lyapunov rank
31 will be between `1` and `n` inclusive; however a rank of `n-1` is
32 not possible (see the first reference).
36 In the references, the cones are always assumed to be proper. We
37 do not impose this restriction.
45 The codimension formula from the second reference is used. We find
46 all pairs `(x,s)` in the complementarity set of `K` such that `x`
47 and `s` are rays of our cone. It is known that these vectors are
48 sufficient to apply the codimension formula. Once we have all such
49 pairs, we "brute force" the codimension formula by finding all
50 linearly-independent `xs^{T}`.
54 1. M.S. Gowda and J. Tao. On the bilinearity rank of a proper cone
55 and Lyapunov-like transformations, Mathematical Programming, 147
58 2. G. Rudolf, N. Noyan, D. Papp, and F. Alizadeh, Bilinear
59 optimality constraints for the cone of positive polynomials,
60 Mathematical Programming, Series B, 129 (2011) 5-31.
64 The nonnegative orthant in `\mathbb{R}^{n}` always has rank `n`::
66 sage: positives = Cone([(1,)])
67 sage: lyapunov_rank(positives)
69 sage: quadrant = Cone([(1,0), (0,1)])
70 sage: lyapunov_rank(quadrant)
72 sage: octant = Cone([(1,0,0), (0,1,0), (0,0,1)])
73 sage: lyapunov_rank(octant)
76 The `L^{3}_{1}` cone is known to have a Lyapunov rank of one::
78 sage: L31 = Cone([(1,0,1), (0,-1,1), (-1,0,1), (0,1,1)])
79 sage: lyapunov_rank(L31)
82 Likewise for the `L^{3}_{\infty}` cone::
84 sage: L3infty = Cone([(0,1,1), (1,0,1), (0,-1,1), (-1,0,1)])
85 sage: lyapunov_rank(L3infty)
88 The Lyapunov rank should be additive on a product of cones::
90 sage: L31 = Cone([(1,0,1), (0,-1,1), (-1,0,1), (0,1,1)])
91 sage: octant = Cone([(1,0,0), (0,1,0), (0,0,1)])
92 sage: K = L31.cartesian_product(octant)
93 sage: lyapunov_rank(K) == lyapunov_rank(L31) + lyapunov_rank(octant)
96 Two isomorphic cones should have the same Lyapunov rank. The cone
97 ``K`` in the following example is isomorphic to the nonnegative
98 octant in `\mathbb{R}^{3}`::
100 sage: K = Cone([(1,2,3), (-1,1,0), (1,0,6)])
101 sage: lyapunov_rank(K)
104 The dual cone `K^{*}` of ``K`` should have the same Lyapunov rank as ``K``
107 sage: K = Cone([(2,2,4), (-1,9,0), (2,0,6)])
108 sage: lyapunov_rank(K) == lyapunov_rank(K.dual())
112 V
= K
.lattice().vector_space()
114 xs
= [V(x
) for x
in K
.rays()]
115 ss
= [V(s
) for s
in K
.dual().rays()]
117 # WARNING: This isn't really C(K), it only contains the pairs
118 # (x,s) in C(K) where x,s are extreme in their respective cones.
119 C_of_K
= [(x
,s
) for x
in xs
for s
in ss
if x
.inner_product(s
) == 0]
121 matrices
= [x
.column() * s
.row() for (x
,s
) in C_of_K
]
123 # Sage doesn't think matrices are vectors, so we have to convert
124 # our matrices to vectors explicitly before we can figure out how
125 # many are linearly-indepenedent.
127 # The space W has the same base ring as V, but dimension
128 # dim(V)^2. So it has the same dimension as the space of linear
129 # transformations on V. In other words, it's just the right size
130 # to create an isomorphism between it and our matrices.
131 W
= VectorSpace(V
.base_ring(), V
.dimension()**2)
135 Convert a matrix to a vector isomorphically.
139 vectors
= [phi(m
) for m
in matrices
]
141 return (W
.dimension() - W
.span(vectors
).rank())