X-Git-Url: http://gitweb.michael.orlitzky.com/?a=blobdiff_plain;f=mjo%2Fcone%2Ffaces.py;h=a6820164999e55d6396d5d1b081419e57f5c791b;hb=924b894e3f5f11886809058fd210f124a1f3f22f;hp=cd15695b6815bd9348a59835f3d1be255e13ef1f;hpb=3a995e3f5231424718cd268c7504ad65d48cdd53;p=sage.d.git diff --git a/mjo/cone/faces.py b/mjo/cone/faces.py index cd15695..a682016 100644 --- a/mjo/cone/faces.py +++ b/mjo/cone/faces.py @@ -1,5 +1,6 @@ from sage.all import * + def face_generated_by(K,S): r""" Return the intersection of all faces of ``K`` that contain ``S``. @@ -91,6 +92,35 @@ def face_generated_by(K,S): sage: actual == expected True + If ``F`` and ``G`` are two faces of ``K``, then the join of ``F`` + and ``G`` in the face lattice is equal to the face generated by + ``F + G`` (in the Minkowski sense) [Tam]_:: + + sage: set_random_seed() + sage: K = random_cone(max_ambient_dim=8, max_rays=10) + sage: L = K.face_lattice() + sage: F = L.random_element() + sage: G = L.random_element() + sage: expected = L.join(F,G) + sage: actual = face_generated_by(K, F.rays() + G.rays()) + sage: actual == expected + True + + Combining Proposition 3.1 and Corollary 3.9 in [Tam]_ gives the + following equality for any ``y`` in ``K``:: + + sage: set_random_seed() + sage: K = random_cone(max_ambient_dim=8, max_rays=10) + sage: y = K.random_element() + sage: S = [y] + sage: phi_y = face_generated_by(K,S) + sage: points_cone_gens = list(K.rays()) + [-z for z in phi_y.rays()] + sage: points_cone = Cone(points_cone_gens, K.lattice()) + sage: actual = phi_y.span(QQ) + sage: expected = points_cone.linear_subspace() + sage: actual == expected + True + """ face_lattice = K.face_lattice() candidates = [F for F in face_lattice if all([F.contains(x) for x in S])] @@ -101,3 +131,68 @@ def face_generated_by(K,S): raise ValueError('S is not a subset of the cone') else: return face_lattice.sorted(candidates)[0] + + +def dual_face(K,F): + r""" + Return the dual face of ``F`` with respect to the cone ``K``. + + OUTPUT: + + A face of ``K.dual()``. + + REFERENCES: + + .. [Tam] Bit-Shun Tam. On the duality operator of a convex cone. Linear + Algebra and its Applications, 64:33-56, 1985, doi:10.1016/0024-3795(85) + 90265-4. + + SETUP:: + + sage: from mjo.cone.faces import dual_face + + EXAMPLES: + + The dual face of the first standard basis vector in three dimensions + is the face generated by the other two standard basis vectors:: + + sage: K = Cone([(1,0,0),(0,1,0),(0,0,1)]) + sage: F = Cone([(1,0,0)]) + sage: dual_face(K,F).rays() + M(0, 0, 1), + M(0, 1, 0) + in 3-d lattice M + + TESTS: + + The dual face of ``K`` with respect to itself should be the + lineality space of its dual [Tam]_:: + + sage: set_random_seed() + sage: K = random_cone(max_ambient_dim=8, max_rays=10) + sage: K_dual = K.dual() + sage: lKd_gens = [ dir*l for dir in [1,-1] for l in K_dual.lines() ] + sage: linspace_K_dual = Cone(lKd_gens, K_dual.lattice()) + sage: dual_face(K,K).is_equivalent(linspace_K_dual) + True + + If ``K`` is proper, then the dual face of its trivial face is the + dual of ``K`` [Tam]_:: + + sage: set_random_seed() + sage: K = random_cone(max_ambient_dim=8, + ....: max_rays=10, + ....: strictly_convex=True, + ....: solid=True) + sage: L = K.lattice() + sage: trivial_face = Cone([L.zero()], L) + sage: dual_face(K,trivial_face).is_equivalent(K.dual()) + True + + """ + # Ensure that F is actually a face of K before continuing. + if not F.is_face_of(K): + raise ValueError("%s is not a face of %s" % (F,K)) + + span_F = Cone([c*g for c in [1,-1] for g in F], F.lattice()) + return K.dual().intersection(span_F.dual())