X-Git-Url: http://gitweb.michael.orlitzky.com/?a=blobdiff_plain;f=mjo%2Fcone%2Fcone.py;h=daeeb8936edb5416b269a131afe95c286da75598;hb=3da1b3bbfcc95758bcce3596a86b0697765bd177;hp=0209433fffb9aa6324bad379b2d5e8ae502e3c16;hpb=4b23d203e61783a9fb53f03555469f3542e16999;p=sage.d.git diff --git a/mjo/cone/cone.py b/mjo/cone/cone.py index 0209433..daeeb89 100644 --- a/mjo/cone/cone.py +++ b/mjo/cone/cone.py @@ -99,28 +99,87 @@ def random_element(K): sage: random_element(K) (0, 0, 0) + A random element of the nonnegative orthant should have all + components nonnegative:: + + sage: set_random_seed() + sage: K = Cone([(1,0,0),(0,1,0),(0,0,1)]) + sage: all([ x >= 0 for x in random_element(K) ]) + True + TESTS: - Any cone should contain an element of itself:: + Any cone should contain a random element of itself:: sage: set_random_seed() - sage: K = random_cone(max_rays = 8) + sage: K = random_cone(max_ambient_dim=8) sage: K.contains(random_element(K)) True + A strictly convex cone contains no lines, and thus no negative + multiples of any of its elements besides zero:: + + sage: set_random_seed() + sage: K = random_cone(max_ambient_dim=8, strictly_convex=True) + sage: x = random_element(K) + sage: x.is_zero() or not K.contains(-x) + True + + The sum of random elements of a cone lies in the cone:: + + sage: set_random_seed() + sage: K = random_cone(max_ambient_dim=8) + sage: K.contains(sum([random_element(K) for i in range(10)])) + True + """ V = K.lattice().vector_space() - F = V.base_ring() - coefficients = [ F.random_element().abs() for i in range(K.nrays()) ] - vector_gens = map(V, K.rays()) - scaled_gens = [ coefficients[i]*vector_gens[i] - for i in range(len(vector_gens)) ] + scaled_gens = [ V.base_field().random_element().abs()*V(r) for r in K ] # Make sure we return a vector. Without the coercion, we might # return ``0`` when ``K`` has no rays. - v = V(sum(scaled_gens)) - return v + return V(sum(scaled_gens)) + + +def pointed_decomposition(K): + """ + Every convex cone is the direct sum of a pointed cone and a linear + subspace. Return a pair ``(P,S)`` of cones such that ``P`` is + pointed, ``S`` is a subspace, and ``K`` is the direct sum of ``P`` + and ``S``. + + OUTPUT: + + An ordered pair ``(P,S)`` of closed convex polyhedral cones where + ``P`` is pointed, ``S`` is a subspace, and ``K`` is the direct sum + of ``P`` and ``S``. + + TESTS: + + A random point in the cone should belong to either the pointed + subcone ``P`` or the subspace ``S``. If the point is nonzero, it + should lie in one but not both of them:: + + sage: set_random_seed() + sage: K = random_cone(max_ambient_dim=8) + sage: (P,S) = pointed_decomposition(K) + sage: x = random_element(K) + sage: P.contains(x) or S.contains(x) + True + sage: x.is_zero() or (P.contains(x) != S.contains(x)) + True + """ + linspace_gens = [ copy(b) for b in K.linear_subspace().basis() ] + linspace_gens += [ -b for b in linspace_gens ] + + S = Cone(linspace_gens, K.lattice()) + + # Since ``S`` is a subspace, its dual is its orthogonal complement + # (albeit in the wrong lattice). + S_perp = Cone(S.dual(), K.lattice()) + P = K.intersection(S_perp) + return (P,S) def positive_operator_gens(K): r"""