]>
gitweb.michael.orlitzky.com - sage.d.git/blob - mjo/cone/cone.py
3 def is_positive_on(L
,K
):
5 Determine whether or not ``L`` is positive on ``K``.
7 We say that ``L`` is positive on ``K`` if `L\left\lparen x
8 \right\rparen` belongs to ``K`` for all `x` in ``K``. This
9 property need only be checked for generators of ``K``.
13 - ``L`` -- A linear transformation or matrix.
15 - ``K`` -- A polyhedral closed convex cone.
19 ``True`` if it can be proven that ``L`` is positive on ``K``,
20 and ``False`` otherwise.
24 If this function returns ``True``, then ``L`` is positive
25 on ``K``. However, if ``False`` is returned, that could mean one
26 of two things. The first is that ``L`` is definitely not
27 positive on ``K``. The second is more of an "I don't know"
28 answer, returned (for example) if we cannot prove that an inner
29 product is nonnegative.
33 Positive operators on the nonnegative orthant are nonnegative
36 sage: K = Cone([(1,0,0),(0,1,0),(0,0,1)])
37 sage: L = random_matrix(QQ,3).apply_map(abs)
38 sage: is_positive_on(L,K)
43 The identity is always positive in a nontrivial space::
45 sage: set_random_seed()
46 sage: K = random_cone(min_ambient_dim=1, max_ambient_dim=8)
47 sage: L = identity_matrix(K.lattice_dim())
48 sage: is_positive_on(L,K)
51 As is the "zero" transformation::
53 sage: K = random_cone(min_ambient_dim=1, max_ambient_dim=8)
54 sage: R = K.lattice().vector_space().base_ring()
55 sage: L = zero_matrix(R, K.lattice_dim())
56 sage: is_positive_on(L,K)
59 Everything in ``K.positive_operators_gens()`` should be
62 sage: K = random_cone(min_ambient_dim=1, max_ambient_dim=6)
63 sage: all([ is_positive_on(L,K)
64 ....: for L in K.positive_operators_gens() ])
66 sage: all([ is_positive_on(L.change_ring(SR),K)
67 ....: for L in K.positive_operators_gens() ])
71 if L
.base_ring().is_exact():
72 # This could potentially be extended to other types of ``K``...
73 return all([ L
*x
in K
for x
in K
])
74 elif L
.base_ring() is SR
:
75 # Fall back to inequality-checking when the entries of ``L``
77 return all([ s
*(L
*x
) >= 0 for x
in K
for s
in K
.dual() ])
79 # The only inexact ring that we're willing to work with is SR,
80 # since it can still be exact when working with symbolic
81 # constants like pi and e.
82 raise ValueError('base ring of operator L is neither SR nor exact')
85 def is_cross_positive_on(L
,K
):
87 Determine whether or not ``L`` is cross-positive on ``K``.
89 We say that ``L`` is cross-positive on ``K`` if `\left\langle
90 L\left\lparenx\right\rparen,s\right\rangle \ge 0` for all pairs
91 `\left\langle x,s \right\rangle` in the complementarity set of
92 ``K``. This property need only be checked for generators of
97 - ``L`` -- A linear transformation or matrix.
99 - ``K`` -- A polyhedral closed convex cone.
103 ``True`` if it can be proven that ``L`` is cross-positive on ``K``,
104 and ``False`` otherwise.
108 If this function returns ``True``, then ``L`` is cross-positive
109 on ``K``. However, if ``False`` is returned, that could mean one
110 of two things. The first is that ``L`` is definitely not
111 cross-positive on ``K``. The second is more of an "I don't know"
112 answer, returned (for example) if we cannot prove that an inner
113 product is nonnegative.
117 The identity is always cross-positive in a nontrivial space::
119 sage: set_random_seed()
120 sage: K = random_cone(min_ambient_dim=1, max_ambient_dim=8)
121 sage: L = identity_matrix(K.lattice_dim())
122 sage: is_cross_positive_on(L,K)
125 As is the "zero" transformation::
127 sage: K = random_cone(min_ambient_dim=1, max_ambient_dim=8)
128 sage: R = K.lattice().vector_space().base_ring()
129 sage: L = zero_matrix(R, K.lattice_dim())
130 sage: is_cross_positive_on(L,K)
135 Everything in ``K.cross_positive_operators_gens()`` should be
136 cross-positive on ``K``::
138 sage: K = random_cone(min_ambient_dim=1, max_ambient_dim=6)
139 sage: all([ is_cross_positive_on(L,K)
140 ....: for L in K.cross_positive_operators_gens() ])
142 sage: all([ is_cross_positive_on(L.change_ring(SR),K)
143 ....: for L in K.cross_positive_operators_gens() ])
147 if L
.base_ring().is_exact() or L
.base_ring() is SR
:
148 return all([ s
*(L
*x
) >= 0
149 for (x
,s
) in K
.discrete_complementarity_set() ])
151 # The only inexact ring that we're willing to work with is SR,
152 # since it can still be exact when working with symbolic
153 # constants like pi and e.
154 raise ValueError('base ring of operator L is neither SR nor exact')
159 Determine whether or not ``L`` is a Z-operator on ``K``.
161 We say that ``L`` is a Z-operator on ``K`` if `\left\langle
162 L\left\lparenx\right\rparen,s\right\rangle \le 0` for all pairs
163 `\left\langle x,s \right\rangle` in the complementarity set of
164 ``K``. It is known that this property need only be
165 checked for generators of ``K`` and its dual.
167 A matrix is a Z-operator on ``K`` if and only if its negation is a
168 cross-positive operator on ``K``.
172 - ``L`` -- A linear transformation or matrix.
174 - ``K`` -- A polyhedral closed convex cone.
178 ``True`` if it can be proven that ``L`` is a Z-operator on ``K``,
179 and ``False`` otherwise.
183 If this function returns ``True``, then ``L`` is a Z-operator
184 on ``K``. However, if ``False`` is returned, that could mean one
185 of two things. The first is that ``L`` is definitely not
186 a Z-operator on ``K``. The second is more of an "I don't know"
187 answer, returned (for example) if we cannot prove that an inner
188 product is nonnegative.
192 The identity is always a Z-operator in a nontrivial space::
194 sage: set_random_seed()
195 sage: K = random_cone(min_ambient_dim=1, max_ambient_dim=8)
196 sage: L = identity_matrix(K.lattice_dim())
200 As is the "zero" transformation::
202 sage: K = random_cone(min_ambient_dim=1, max_ambient_dim=8)
203 sage: R = K.lattice().vector_space().base_ring()
204 sage: L = zero_matrix(R, K.lattice_dim())
210 Everything in ``K.Z_operators_gens()`` should be a Z-operator
213 sage: K = random_cone(min_ambient_dim=1, max_ambient_dim=6)
214 sage: all([ is_Z_on(L,K)
215 ....: for L in K.Z_operators_gens() ])
217 sage: all([ is_Z_on(L.change_ring(SR),K)
218 ....: for L in K.Z_operators_gens() ])
222 return is_cross_positive_on(-L
,K
)
225 def is_lyapunov_like_on(L
,K
):
227 Determine whether or not ``L`` is Lyapunov-like on ``K``.
229 We say that ``L`` is Lyapunov-like on ``K`` if `\left\langle
230 L\left\lparenx\right\rparen,s\right\rangle = 0` for all pairs
231 `\left\langle x,s \right\rangle` in the complementarity set of
232 ``K``. This property need only be checked for generators of
237 - ``L`` -- A linear transformation or matrix.
239 - ``K`` -- A polyhedral closed convex cone.
243 ``True`` if it can be proven that ``L`` is Lyapunov-like on ``K``,
244 and ``False`` otherwise.
248 If this function returns ``True``, then ``L`` is Lyapunov-like
249 on ``K``. However, if ``False`` is returned, that could mean one
250 of two things. The first is that ``L`` is definitely not
251 Lyapunov-like on ``K``. The second is more of an "I don't know"
252 answer, returned (for example) if we cannot prove that an inner
257 Lyapunov-like operators on the nonnegative orthant are diagonal
260 sage: K = Cone([(1,0,0),(0,1,0),(0,0,1)])
261 sage: L = diagonal_matrix(random_vector(QQ,3))
262 sage: is_lyapunov_like_on(L,K)
267 The identity is always Lyapunov-like in a nontrivial space::
269 sage: set_random_seed()
270 sage: K = random_cone(min_ambient_dim=1, max_ambient_dim=8)
271 sage: L = identity_matrix(K.lattice_dim())
272 sage: is_lyapunov_like_on(L,K)
275 As is the "zero" transformation::
277 sage: K = random_cone(min_ambient_dim=1, max_ambient_dim=8)
278 sage: R = K.lattice().vector_space().base_ring()
279 sage: L = zero_matrix(R, K.lattice_dim())
280 sage: is_lyapunov_like_on(L,K)
283 Everything in ``K.lyapunov_like_basis()`` should be Lyapunov-like
286 sage: K = random_cone(min_ambient_dim=1, max_ambient_dim=6)
287 sage: all([ is_lyapunov_like_on(L,K)
288 ....: for L in K.lyapunov_like_basis() ])
290 sage: all([ is_lyapunov_like_on(L.change_ring(SR),K)
291 ....: for L in K.lyapunov_like_basis() ])
295 if L
.base_ring().is_exact() or L
.base_ring() is SR
:
296 # The "fast method" of creating a vector space based on a
297 # ``lyapunov_like_basis`` is actually slower than this.
298 return all([ s
*(L
*x
) == 0
299 for (x
,s
) in K
.discrete_complementarity_set() ])
301 # The only inexact ring that we're willing to work with is SR,
302 # since it can still be exact when working with symbolic
303 # constants like pi and e.
304 raise ValueError('base ring of operator L is neither SR nor exact')
307 gens
= K
.lyapunov_like_basis()
308 L
= ToricLattice(K
.lattice_dim()**2)
309 return Cone([ g
.list() for g
in gens
], lattice
=L
, check
=False)
312 gens
= K
.cross_positive_operators_gens()
313 L
= ToricLattice(K
.lattice_dim()**2)
314 return Cone([ g
.list() for g
in gens
], lattice
=L
, check
=False)
317 gens
= K
.Z_operators_gens()
318 L
= ToricLattice(K
.lattice_dim()**2)
319 return Cone([ g
.list() for g
in gens
], lattice
=L
, check
=False)
321 def pi_cone(K1
, K2
=None):
324 gens
= K1
.positive_operators_gens(K2
)
325 L
= ToricLattice(K1
.lattice_dim()*K2
.lattice_dim())
326 return Cone([ g
.list() for g
in gens
], lattice
=L
, check
=False)