- def random_min_max(l,u):
- r"""
- We need to handle four cases to prevent us from doing
- something stupid like having an upper bound that's lower than
- our lower bound. And we would need to repeat all of that logic
- for the dimension/rays, so we consolidate it here.
- """
- if l is None and u is None:
- # They're both random, just return a random nonnegative
- # integer.
- return ZZ.random_element().abs()
-
- if l is not None and u is not None:
- # Both were specified. Again, just make up a number and
- # return it. If the user wants to give us u < l then he
- # can have an exception.
- return ZZ.random_element(l,u)
-
- if l is not None and u is None:
- # In this case, we're generating the upper bound randomly
- # GIVEN A LOWER BOUND. So we add a random nonnegative
- # integer to the given lower bound.
- u = l + ZZ.random_element().abs()
- return ZZ.random_element(l,u)
-
- # Here we must be in the only remaining case, where we are
- # given an upper bound but no lower bound. We might as well
- # use zero.
- return ZZ.random_element(0,u)
-
- d = random_min_max(min_dim, max_dim)
- r = random_min_max(min_rays, max_rays)
-
- L = ToricLattice(d)
- rays = [L.random_element() for i in range(0,r)]
-
- # We pass the lattice in case there are no rays.
- return Cone(rays, lattice=L)
-
-
-def discrete_complementarity_set(K):
+ sage: K = random_cone(max_ambient_dim=5)
+ sage: all([ is_positive_on(L,K) # long time
+ ....: for L in K.positive_operators_gens() ]) # long time
+ True
+ sage: all([ is_positive_on(L.change_ring(SR),K) # long time
+ ....: for L in K.positive_operators_gens() ]) # long time
+ True
+
+ """
+ if not is_Cone(K):
+ raise TypeError('K must be a Cone')
+ if not L.base_ring().is_exact() and not L.base_ring() is SR:
+ raise ValueError('base ring of operator L is neither SR nor exact')
+
+ if L.base_ring().is_exact():
+ # This should be way faster than computing the dual and
+ # checking a bunch of inequalities, but it doesn't work if
+ # ``L*x`` is symbolic. For example, ``e in Cone([(1,)])``
+ # is true, but returns ``False``.
+ return all([ L*x in K for x in K ])
+ else:
+ # Fall back to inequality-checking when the entries of ``L``
+ # might be symbolic.
+ return all([ s*(L*x) >= 0 for x in K for s in K.dual() ])
+
+
+def is_cross_positive_on(L,K):