]>
gitweb.michael.orlitzky.com - sage.d.git/blob - cone.py
865a0700eac91a6af5550477eed6ebe2500cd304
2 from sage
.geometry
.cone
import is_Cone
4 def is_positive_on(L
,K
):
6 Determine whether or not ``L`` is positive on ``K``.
8 We say that ``L`` is positive on a closed convex cone ``K`` if
9 `L\left\lparen x \right\rparen` belongs to ``K`` for all `x` in
10 ``K``. This property need only be checked for generators of ``K``.
12 To reliably check whether or not ``L`` is positive, its base ring
13 must be either exact (for example, the rationals) or ``SR``. An
14 exact ring is more reliable, but in some cases a matrix whose
15 entries contain symbolic constants like ``e`` and ``pi`` will work.
19 - ``L`` -- A matrix over either an exact ring or ``SR``.
21 - ``K`` -- A polyhedral closed convex cone.
25 If the base ring of ``L`` is exact, then ``True`` will be returned if
26 and only if ``L`` is positive on ``K``.
28 If the base ring of ``L`` is ``SR``, then the situation is more
31 - ``True`` will be returned if it can be proven that ``L``
33 - ``False`` will be returned if it can be proven that ``L``
34 is not positive on ``K``.
35 - ``False`` will also be returned if we can't decide; specifically
36 if we arrive at a symbolic inequality that cannot be resolved.
40 Nonnegative matrices are positive operators on the nonnegative
43 sage: K = Cone([(1,0,0),(0,1,0),(0,0,1)])
44 sage: L = random_matrix(QQ,3).apply_map(abs)
45 sage: is_positive_on(L,K)
50 The identity operator is always positive::
52 sage: set_random_seed()
53 sage: K = random_cone(max_ambient_dim=8)
54 sage: L = identity_matrix(K.lattice_dim())
55 sage: is_positive_on(L,K)
58 The "zero" operator is always positive::
60 sage: K = random_cone(max_ambient_dim=8)
61 sage: R = K.lattice().vector_space().base_ring()
62 sage: L = zero_matrix(R, K.lattice_dim())
63 sage: is_positive_on(L,K)
66 Everything in ``K.positive_operators_gens()`` should be
69 sage: K = random_cone(max_ambient_dim=5)
70 sage: all([ is_positive_on(L,K) # long time
71 ....: for L in K.positive_operators_gens() ]) # long time
73 sage: all([ is_positive_on(L.change_ring(SR),K) # long time
74 ....: for L in K.positive_operators_gens() ]) # long time
77 Technically we could test this, but for now only closed convex cones
78 are supported as our ``K`` argument::
80 sage: L = identity_matrix(3)
81 sage: K = [ vector([1,2,3]), vector([5,-1,7]) ]
82 sage: is_positive_on(L,K)
83 Traceback (most recent call last):
85 TypeError: K must be a Cone.
89 raise TypeError('K must be a Cone.')
90 if not L
.base_ring().is_exact() and not L
.base_ring() is SR
:
91 raise ValueError('The base ring of L is neither SR nor exact.')
93 if L
.base_ring().is_exact():
94 # This should be way faster than computing the dual and
95 # checking a bunch of inequalities, but it doesn't work if
96 # ``L*x`` is symbolic. For example, ``e in Cone([(1,)])``
97 # is true, but returns ``False``.
98 return all([ L
*x
in K
for x
in K
])
100 # Fall back to inequality-checking when the entries of ``L``
102 return all([ s
*(L
*x
) >= 0 for x
in K
for s
in K
.dual() ])
105 def is_cross_positive_on(L
,K
):
107 Determine whether or not ``L`` is cross-positive on ``K``.
109 We say that ``L`` is cross-positive on a closed convex cone``K`` if
110 `\left\langle L\left\lparenx\right\rparen,s\right\rangle \ge 0` for
111 all pairs `\left\langle x,s \right\rangle` in the complementarity
112 set of ``K``. This property need only be checked for generators of
115 To reliably check whether or not ``L`` is cross-positive, its base
116 ring must be either exact (for example, the rationals) or ``SR``. An
117 exact ring is more reliable, but in some cases a matrix whose
118 entries contain symbolic constants like ``e`` and ``pi`` will work.
122 - ``L`` -- A matrix over either an exact ring or ``SR``.
124 - ``K`` -- A polyhedral closed convex cone.
128 If the base ring of ``L`` is exact, then ``True`` will be returned if
129 and only if ``L`` is cross-positive on ``K``.
131 If the base ring of ``L`` is ``SR``, then the situation is more
134 - ``True`` will be returned if it can be proven that ``L``
135 is cross-positive on ``K``.
136 - ``False`` will be returned if it can be proven that ``L``
137 is not cross-positive on ``K``.
138 - ``False`` will also be returned if we can't decide; specifically
139 if we arrive at a symbolic inequality that cannot be resolved.
143 The identity operator is always cross-positive::
145 sage: set_random_seed()
146 sage: K = random_cone(max_ambient_dim=8)
147 sage: L = identity_matrix(K.lattice_dim())
148 sage: is_cross_positive_on(L,K)
151 The "zero" operator is always cross-positive::
153 sage: K = random_cone(max_ambient_dim=8)
154 sage: R = K.lattice().vector_space().base_ring()
155 sage: L = zero_matrix(R, K.lattice_dim())
156 sage: is_cross_positive_on(L,K)
161 Everything in ``K.cross_positive_operators_gens()`` should be
162 cross-positive on ``K``::
164 sage: K = random_cone(max_ambient_dim=5)
165 sage: all([ is_cross_positive_on(L,K) # long time
166 ....: for L in K.cross_positive_operators_gens() ]) # long time
168 sage: all([ is_cross_positive_on(L.change_ring(SR),K) # long time
169 ....: for L in K.cross_positive_operators_gens() ]) # long time
172 Technically we could test this, but for now only closed convex cones
173 are supported as our ``K`` argument::
175 sage: L = identity_matrix(3)
176 sage: K = [ vector([8,2,-8]), vector([5,-5,7]) ]
177 sage: is_cross_positive_on(L,K)
178 Traceback (most recent call last):
180 TypeError: K must be a Cone.
184 raise TypeError('K must be a Cone.')
185 if not L
.base_ring().is_exact() and not L
.base_ring() is SR
:
186 raise ValueError('The base ring of L is neither SR nor exact.')
188 return all([ s
*(L
*x
) >= 0
189 for (x
,s
) in K
.discrete_complementarity_set() ])
193 Determine whether or not ``L`` is a Z-operator on ``K``.
195 We say that ``L`` is a Z-operator on a closed convex cone``K`` if
196 `\left\langle L\left\lparenx\right\rparen,s\right\rangle \le 0` for
197 all pairs `\left\langle x,s \right\rangle` in the complementarity
198 set of ``K``. It is known that this property need only be checked
199 for generators of ``K`` and its dual.
201 A matrix is a Z-operator on ``K`` if and only if its negation is a
202 cross-positive operator on ``K``.
204 To reliably check whether or not ``L`` is a Z operator, its base
205 ring must be either exact (for example, the rationals) or ``SR``. An
206 exact ring is more reliable, but in some cases a matrix whose
207 entries contain symbolic constants like ``e`` and ``pi`` will work.
211 - ``L`` -- A matrix over either an exact ring or ``SR``.
213 - ``K`` -- A polyhedral closed convex cone.
217 If the base ring of ``L`` is exact, then ``True`` will be returned if
218 and only if ``L`` is a Z-operator on ``K``.
220 If the base ring of ``L`` is ``SR``, then the situation is more
223 - ``True`` will be returned if it can be proven that ``L``
224 is a Z-operator on ``K``.
225 - ``False`` will be returned if it can be proven that ``L``
226 is not a Z-operator on ``K``.
227 - ``False`` will also be returned if we can't decide; specifically
228 if we arrive at a symbolic inequality that cannot be resolved.
232 The identity operator is always a Z-operator::
234 sage: set_random_seed()
235 sage: K = random_cone(max_ambient_dim=8)
236 sage: L = identity_matrix(K.lattice_dim())
240 The "zero" operator is always a Z-operator::
242 sage: K = random_cone(max_ambient_dim=8)
243 sage: R = K.lattice().vector_space().base_ring()
244 sage: L = zero_matrix(R, K.lattice_dim())
250 Everything in ``K.Z_operators_gens()`` should be a Z-operator
253 sage: K = random_cone(max_ambient_dim=5)
254 sage: all([ is_Z_on(L,K) # long time
255 ....: for L in K.Z_operators_gens() ]) # long time
257 sage: all([ is_Z_on(L.change_ring(SR),K) # long time
258 ....: for L in K.Z_operators_gens() ]) # long time
261 Technically we could test this, but for now only closed convex cones
262 are supported as our ``K`` argument::
264 sage: L = identity_matrix(3)
265 sage: K = [ vector([-4,20,3]), vector([1,-5,2]) ]
267 Traceback (most recent call last):
269 TypeError: K must be a Cone.
272 return is_cross_positive_on(-L
,K
)
275 def is_lyapunov_like_on(L
,K
):
277 Determine whether or not ``L`` is Lyapunov-like on ``K``.
279 We say that ``L`` is Lyapunov-like on a closed convex cone ``K`` if
280 `\left\langle L\left\lparenx\right\rparen,s\right\rangle = 0` for
281 all pairs `\left\langle x,s \right\rangle` in the complementarity
282 set of ``K``. This property need only be checked for generators of
285 To reliably check whether or not ``L`` is Lyapunov-like, its base
286 ring must be either exact (for example, the rationals) or ``SR``. An
287 exact ring is more reliable, but in some cases a matrix whose
288 entries contain symbolic constants like ``e`` and ``pi`` will work.
292 - ``L`` -- A matrix over either an exact ring or ``SR``.
294 - ``K`` -- A polyhedral closed convex cone.
298 If the base ring of ``L`` is exact, then ``True`` will be returned if
299 and only if ``L`` is Lyapunov-like on ``K``.
301 If the base ring of ``L`` is ``SR``, then the situation is more
304 - ``True`` will be returned if it can be proven that ``L``
305 is Lyapunov-like on ``K``.
306 - ``False`` will be returned if it can be proven that ``L``
307 is not Lyapunov-like on ``K``.
308 - ``False`` will also be returned if we can't decide; specifically
309 if we arrive at a symbolic inequality that cannot be resolved.
313 Diagonal matrices are Lyapunov-like operators on the nonnegative
316 sage: K = Cone([(1,0,0),(0,1,0),(0,0,1)])
317 sage: L = diagonal_matrix(random_vector(QQ,3))
318 sage: is_lyapunov_like_on(L,K)
323 The identity operator is always Lyapunov-like::
325 sage: set_random_seed()
326 sage: K = random_cone(max_ambient_dim=8)
327 sage: L = identity_matrix(K.lattice_dim())
328 sage: is_lyapunov_like_on(L,K)
331 The "zero" operator is always Lyapunov-like::
333 sage: K = random_cone(max_ambient_dim=8)
334 sage: R = K.lattice().vector_space().base_ring()
335 sage: L = zero_matrix(R, K.lattice_dim())
336 sage: is_lyapunov_like_on(L,K)
339 Everything in ``K.lyapunov_like_basis()`` should be Lyapunov-like
342 sage: K = random_cone(max_ambient_dim=5)
343 sage: all([ is_lyapunov_like_on(L,K) # long time
344 ....: for L in K.lyapunov_like_basis() ]) # long time
346 sage: all([ is_lyapunov_like_on(L.change_ring(SR),K) # long time
347 ....: for L in K.lyapunov_like_basis() ]) # long time
350 Technically we could test this, but for now only closed convex cones
351 are supported as our ``K`` argument::
353 sage: L = identity_matrix(3)
354 sage: K = [ vector([2,2,-1]), vector([5,4,-3]) ]
355 sage: is_lyapunov_like_on(L,K)
356 Traceback (most recent call last):
358 TypeError: K must be a Cone.
362 raise TypeError('K must be a Cone.')
363 if not L
.base_ring().is_exact() and not L
.base_ring() is SR
:
364 raise ValueError('The base ring of L is neither SR nor exact.')
366 return all([ s
*(L
*x
) == 0
367 for (x
,s
) in K
.discrete_complementarity_set() ])
371 gens
= K
.lyapunov_like_basis()
372 L
= ToricLattice(K
.lattice_dim()**2)
373 return Cone([ g
.list() for g
in gens
], lattice
=L
, check
=False)
376 gens
= K
.cross_positive_operators_gens()
377 L
= ToricLattice(K
.lattice_dim()**2)
378 return Cone([ g
.list() for g
in gens
], lattice
=L
, check
=False)
381 gens
= K
.Z_operators_gens()
382 L
= ToricLattice(K
.lattice_dim()**2)
383 return Cone([ g
.list() for g
in gens
], lattice
=L
, check
=False)
385 def pi_cone(K1
, K2
=None):
388 gens
= K1
.positive_operators_gens(K2
)
389 L
= ToricLattice(K1
.lattice_dim()*K2
.lattice_dim())
390 return Cone([ g
.list() for g
in gens
], lattice
=L
, check
=False)