]>
gitweb.michael.orlitzky.com - sage.d.git/blob - mjo/cone/cone.py
cbbfe9b692f3bdf36f68f202deedd467c684cef0
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
79 raise TypeError('K must be a Cone')
80 if not L
.base_ring().is_exact() and not L
.base_ring() is SR
:
81 raise ValueError('base ring of operator L is neither SR nor exact')
83 if L
.base_ring().is_exact():
84 # This should be way faster than computing the dual and
85 # checking a bunch of inequalities, but it doesn't work if
86 # ``L*x`` is symbolic. For example, ``e in Cone([(1,)])``
87 # is true, but returns ``False``.
88 return all([ L
*x
in K
for x
in K
])
90 # Fall back to inequality-checking when the entries of ``L``
92 return all([ s
*(L
*x
) >= 0 for x
in K
for s
in K
.dual() ])
95 def is_cross_positive_on(L
,K
):
97 Determine whether or not ``L`` is cross-positive on ``K``.
99 We say that ``L`` is cross-positive on a closed convex cone``K`` if
100 `\left\langle L\left\lparenx\right\rparen,s\right\rangle \ge 0` for
101 all pairs `\left\langle x,s \right\rangle` in the complementarity
102 set of ``K``. This property need only be checked for generators of
105 To reliably check whether or not ``L`` is cross-positive, its base
106 ring must be either exact (for example, the rationals) or ``SR``. An
107 exact ring is more reliable, but in some cases a matrix whose
108 entries contain symbolic constants like ``e`` and ``pi`` will work.
112 - ``L`` -- A matrix over either an exact ring or ``SR``.
114 - ``K`` -- A polyhedral closed convex cone.
118 If the base ring of ``L`` is exact, then ``True`` will be returned if
119 and only if ``L`` is cross-positive on ``K``.
121 If the base ring of ``L`` is ``SR``, then the situation is more
124 - ``True`` will be returned if it can be proven that ``L``
125 is cross-positive on ``K``.
126 - ``False`` will be returned if it can be proven that ``L``
127 is not cross-positive on ``K``.
128 - ``False`` will also be returned if we can't decide; specifically
129 if we arrive at a symbolic inequality that cannot be resolved.
133 The identity operator is always cross-positive::
135 sage: set_random_seed()
136 sage: K = random_cone(max_ambient_dim=8)
137 sage: L = identity_matrix(K.lattice_dim())
138 sage: is_cross_positive_on(L,K)
141 The "zero" operator is always cross-positive::
143 sage: K = random_cone(max_ambient_dim=8)
144 sage: R = K.lattice().vector_space().base_ring()
145 sage: L = zero_matrix(R, K.lattice_dim())
146 sage: is_cross_positive_on(L,K)
151 Everything in ``K.cross_positive_operators_gens()`` should be
152 cross-positive on ``K``::
154 sage: K = random_cone(max_ambient_dim=5)
155 sage: all([ is_cross_positive_on(L,K) # long time
156 ....: for L in K.cross_positive_operators_gens() ]) # long time
158 sage: all([ is_cross_positive_on(L.change_ring(SR),K) # long time
159 ....: for L in K.cross_positive_operators_gens() ]) # long time
164 raise TypeError('K must be a Cone')
165 if not L
.base_ring().is_exact() and not L
.base_ring() is SR
:
166 raise ValueError('base ring of operator L is neither SR nor exact')
168 return all([ s
*(L
*x
) >= 0
169 for (x
,s
) in K
.discrete_complementarity_set() ])
173 Determine whether or not ``L`` is a Z-operator on ``K``.
175 We say that ``L`` is a Z-operator on a closed convex cone``K`` if
176 `\left\langle L\left\lparenx\right\rparen,s\right\rangle \le 0` for
177 all pairs `\left\langle x,s \right\rangle` in the complementarity
178 set of ``K``. It is known that this property need only be checked
179 for generators of ``K`` and its dual.
181 A matrix is a Z-operator on ``K`` if and only if its negation is a
182 cross-positive operator on ``K``.
184 To reliably check whether or not ``L`` is a Z operator, its base
185 ring must be either exact (for example, the rationals) or ``SR``. An
186 exact ring is more reliable, but in some cases a matrix whose
187 entries contain symbolic constants like ``e`` and ``pi`` will work.
191 - ``L`` -- A matrix over either an exact ring or ``SR``.
193 - ``K`` -- A polyhedral closed convex cone.
197 If the base ring of ``L`` is exact, then ``True`` will be returned if
198 and only if ``L`` is a Z-operator on ``K``.
200 If the base ring of ``L`` is ``SR``, then the situation is more
203 - ``True`` will be returned if it can be proven that ``L``
204 is a Z-operator on ``K``.
205 - ``False`` will be returned if it can be proven that ``L``
206 is not a Z-operator on ``K``.
207 - ``False`` will also be returned if we can't decide; specifically
208 if we arrive at a symbolic inequality that cannot be resolved.
212 The identity operator is always a Z-operator::
214 sage: set_random_seed()
215 sage: K = random_cone(max_ambient_dim=8)
216 sage: L = identity_matrix(K.lattice_dim())
220 The "zero" operator is always a Z-operator::
222 sage: K = random_cone(max_ambient_dim=8)
223 sage: R = K.lattice().vector_space().base_ring()
224 sage: L = zero_matrix(R, K.lattice_dim())
230 Everything in ``K.Z_operators_gens()`` should be a Z-operator
233 sage: K = random_cone(max_ambient_dim=5)
234 sage: all([ is_Z_on(L,K) # long time
235 ....: for L in K.Z_operators_gens() ]) # long time
237 sage: all([ is_Z_on(L.change_ring(SR),K) # long time
238 ....: for L in K.Z_operators_gens() ]) # long time
242 return is_cross_positive_on(-L
,K
)
245 def is_lyapunov_like_on(L
,K
):
247 Determine whether or not ``L`` is Lyapunov-like on ``K``.
249 We say that ``L`` is Lyapunov-like on a closed convex cone ``K`` if
250 `\left\langle L\left\lparenx\right\rparen,s\right\rangle = 0` for
251 all pairs `\left\langle x,s \right\rangle` in the complementarity
252 set of ``K``. This property need only be checked for generators of
255 To reliably check whether or not ``L`` is Lyapunov-like, its base
256 ring must be either exact (for example, the rationals) or ``SR``. An
257 exact ring is more reliable, but in some cases a matrix whose
258 entries contain symbolic constants like ``e`` and ``pi`` will work.
262 - ``L`` -- A matrix over either an exact ring or ``SR``.
264 - ``K`` -- A polyhedral closed convex cone.
268 If the base ring of ``L`` is exact, then ``True`` will be returned if
269 and only if ``L`` is Lyapunov-like on ``K``.
271 If the base ring of ``L`` is ``SR``, then the situation is more
274 - ``True`` will be returned if it can be proven that ``L``
275 is Lyapunov-like on ``K``.
276 - ``False`` will be returned if it can be proven that ``L``
277 is not Lyapunov-like on ``K``.
278 - ``False`` will also be returned if we can't decide; specifically
279 if we arrive at a symbolic inequality that cannot be resolved.
283 Diagonal matrices are Lyapunov-like operators on the nonnegative
286 sage: K = Cone([(1,0,0),(0,1,0),(0,0,1)])
287 sage: L = diagonal_matrix(random_vector(QQ,3))
288 sage: is_lyapunov_like_on(L,K)
293 The identity operator is always Lyapunov-like::
295 sage: set_random_seed()
296 sage: K = random_cone(max_ambient_dim=8)
297 sage: L = identity_matrix(K.lattice_dim())
298 sage: is_lyapunov_like_on(L,K)
301 The "zero" operator is always Lyapunov-like::
303 sage: K = random_cone(max_ambient_dim=8)
304 sage: R = K.lattice().vector_space().base_ring()
305 sage: L = zero_matrix(R, K.lattice_dim())
306 sage: is_lyapunov_like_on(L,K)
309 Everything in ``K.lyapunov_like_basis()`` should be Lyapunov-like
312 sage: K = random_cone(max_ambient_dim=5)
313 sage: all([ is_lyapunov_like_on(L,K) # long time
314 ....: for L in K.lyapunov_like_basis() ]) # long time
316 sage: all([ is_lyapunov_like_on(L.change_ring(SR),K) # long time
317 ....: for L in K.lyapunov_like_basis() ]) # long time
322 raise TypeError('K must be a Cone')
323 if not L
.base_ring().is_exact() and not L
.base_ring() is SR
:
324 raise ValueError('base ring of operator L is neither SR nor exact')
326 return all([ s
*(L
*x
) == 0
327 for (x
,s
) in K
.discrete_complementarity_set() ])
331 gens
= K
.lyapunov_like_basis()
332 L
= ToricLattice(K
.lattice_dim()**2)
333 return Cone([ g
.list() for g
in gens
], lattice
=L
, check
=False)
336 gens
= K
.cross_positive_operators_gens()
337 L
= ToricLattice(K
.lattice_dim()**2)
338 return Cone([ g
.list() for g
in gens
], lattice
=L
, check
=False)
341 gens
= K
.Z_operators_gens()
342 L
= ToricLattice(K
.lattice_dim()**2)
343 return Cone([ g
.list() for g
in gens
], lattice
=L
, check
=False)
345 def pi_cone(K1
, K2
=None):
348 gens
= K1
.positive_operators_gens(K2
)
349 L
= ToricLattice(K1
.lattice_dim()*K2
.lattice_dim())
350 return Cone([ g
.list() for g
in gens
], lattice
=L
, check
=False)