Skip to content

Commit 6531546

Browse files
committed
First version of deformation cone for pc and polyhedron
1 parent 766c7a0 commit 6531546

File tree

3 files changed

+167
-2
lines changed

3 files changed

+167
-2
lines changed

src/doc/en/reference/references/index.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ REFERENCES:
104104
graphs and isoperimetric inequalities*, The Annals of Probability
105105
32 (2004), no. 3A, 1727-1745.
106106
107+
.. [ACEP2020] Federico Ardila, Federico Castillo, Christopher Eur, Alexander Postnikov,
108+
*Coxeter submodular functions and deformations of Coxeter permutahedra*,
109+
Advances in Mathematics, Volume 365, 13 May 2020.
110+
107111
.. [ALL2002] P. Auger, G. Labelle and P. Leroux, *Combinatorial
108112
addition formulas and applications*, Advances in Applied
109113
Mathematics 28 (2002) 302-342.

src/sage/geometry/polyhedron/base5.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,56 @@ def lawrence_polytope(self):
659659
parent = self.parent().change_ring(self.base_ring(), ambient_dim=self.ambient_dim() + n)
660660
return parent.element_class(parent, [lambda_V, [], []], None)
661661

662+
def deformation_cone(self):
663+
r"""
664+
Return the deformation cone of ``self``.
665+
666+
Let `P` be a `d`-polytope in `\RR^r` with `n` facets. The deformation
667+
cone is a polyhedron in `\RR^n` who points are the right-hand side `b`
668+
in `Ax\leq b` where `A` is the matrix of facet normals of ``self``, so
669+
that the resulting polytope has a normal fan which is a coarsening of
670+
the normal fan of ``self``.
671+
672+
EXAMPLES::
673+
674+
sage: tc = Polyhedron([(1, -1), (1/3, 1), (1, 1/3), (-1, 1), (-1, -1)])
675+
sage: dc = tc.deformation_cone()
676+
sage: dc.an_element()
677+
(2, 1, 1, 0, 0)
678+
sage: [_.A() for _ in tc.Hrepresentation()]
679+
[(1, 0), (0, 1), (0, -1), (-3, -3), (-1, 0)]
680+
sage: P = Polyhedron(rays=[(1, 0, 2), (0, 1, 1), (0, -1, 1), (-3, -3, 0), (-1, 0, 0)])
681+
sage: P.rays()
682+
(A ray in the direction (-1, -1, 0),
683+
A ray in the direction (-1, 0, 0),
684+
A ray in the direction (0, -1, 1),
685+
A ray in the direction (0, 1, 1),
686+
A ray in the direction (1, 0, 2))
687+
688+
.. SEEALSO::
689+
690+
:meth:`~sage.schemes.toric.variety.Kaehler_cone`
691+
692+
REFERENCES:
693+
694+
For more information, see Section 5.4 of [DLRS2010]_ and Section
695+
2.2 of [ACEP2020].
696+
"""
697+
from .constructor import Polyhedron
698+
A = matrix([_.A() for _ in self.Hrepresentation()])
699+
A = A.transpose()
700+
A_ker = A.right_kernel_matrix(basis='computed')
701+
gale = tuple(A_ker.columns())
702+
collection = [_.ambient_H_indices() for _ in self.faces(0)]
703+
n = len(gale)
704+
K = None
705+
for cone_indices in collection:
706+
dual_cone = Polyhedron(rays=[gale[i] for i in range(n) if i not in
707+
cone_indices])
708+
K = K.intersection(dual_cone) if K is not None else dual_cone
709+
preimages = [A_ker.solve_right(r.vector()) for r in K.rays()]
710+
return Polyhedron(lines=A.rows(), rays=preimages)
711+
662712
###########################################################
663713
# Binary operations.
664714
###########################################################

src/sage/geometry/triangulation/point_configuration.py

Lines changed: 113 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2039,7 +2039,7 @@ def facets_of_simplex(simplex):
20392039
pushing_triangulation = placing_triangulation
20402040

20412041
@cached_method
2042-
def Gale_transform(self, points=None):
2042+
def Gale_transform(self, points=None, homogenize=True):
20432043
r"""
20442044
Return the Gale transform of ``self``.
20452045
@@ -2049,6 +2049,9 @@ def Gale_transform(self, points=None):
20492049
(default). A subset of points for which to compute the Gale
20502050
transform. By default, all points are used.
20512051
2052+
- ``homogenize`` -- boolean (default: ``True``); whether to add a row
2053+
of 1's before taking the transform.
2054+
20522055
OUTPUT: a matrix over :meth:`base_ring`
20532056
20542057
EXAMPLES::
@@ -2064,6 +2067,50 @@ def Gale_transform(self, points=None):
20642067
sage: points = (pc.point(0), pc.point(1), pc.point(3), pc.point(4))
20652068
sage: pc.Gale_transform(points)
20662069
[ 1 -1 1 -1]
2070+
2071+
It is possible to take the inverse of the Gale transform, by specifying
2072+
whether to homogenize or not::
2073+
2074+
sage: pc2 = PointConfiguration([[0,0],[3,0],[0,3],[3,3],[1,1]])
2075+
sage: pc2.Gale_transform(homogenize=False)
2076+
[-1 0 0 0 0]
2077+
[ 0 1 1 -1 0]
2078+
[ 0 1 1 0 -3]
2079+
sage: pc2.Gale_transform(homogenize=True)
2080+
[ 1 1 1 0 -3]
2081+
[ 0 2 2 -1 -3]
2082+
2083+
It might not affect the dimension of the result::
2084+
2085+
sage: PC = PointConfiguration([[4,0,0],[0,4,0],[0,0,4],[2,1,1],[1,2,1],[1,1,2]])
2086+
sage: GT = PC.Gale_transform(homogenize=False);GT
2087+
[ 2 1 1 -4 0 0]
2088+
[ 1 2 1 0 -4 0]
2089+
[-2 -2 -1 3 3 -1]
2090+
sage: GT = PC.Gale_transform(homogenize=True);GT
2091+
[ 1 0 0 -3 1 1]
2092+
[ 0 1 0 1 -3 1]
2093+
[ 0 0 1 1 1 -3]
2094+
2095+
The following point configuration is totally cyclic (the cone spanned
2096+
by the vectors is equal to the vector space spanned by the points),
2097+
hence its Gale dual is acyclic (there is a linear functional that is
2098+
positive in all the points of the configuration) when not homogenized::
2099+
2100+
sage: pc3 = PointConfiguration([[-1, -1, -1], [-1, 0, 0], [0, -1, 0], [0, 0, -1], [1, 0, 0], [0, 0, 1], [0, 1, 0]])
2101+
sage: g_hom = pc3.Gale_transform(homogenize=True);g_hom
2102+
[ 1 0 0 -2 1 -1 1]
2103+
[ 0 1 0 -1 1 -1 0]
2104+
[ 0 0 1 -1 0 -1 1]
2105+
sage: g_inhom = pc3.Gale_transform(homogenize=False);g_inhom
2106+
[-1 1 1 1 0 0 0]
2107+
[ 0 1 0 0 1 0 0]
2108+
[ 1 -1 -1 0 0 1 0]
2109+
[ 0 0 1 0 0 0 1]
2110+
sage: Polyhedron(rays=g_hom.columns())
2111+
A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 1 vertex and 3 lines
2112+
sage: Polyhedron(rays=g_inhom.columns())
2113+
A 4-dimensional polyhedron in ZZ^4 defined as the convex hull of 1 vertex and 4 rays
20672114
"""
20682115
self._assert_is_affine()
20692116
if points is None:
@@ -2073,9 +2120,73 @@ def Gale_transform(self, points=None):
20732120
points = [ self.point(ZZ(i)) for i in points ]
20742121
except TypeError:
20752122
pass
2076-
m = matrix([ (1,) + p.affine() for p in points])
2123+
if homogenize:
2124+
m = matrix([ (1,) + p.affine() for p in points])
2125+
else:
2126+
m = matrix([p.affine() for p in points])
20772127
return m.left_kernel().matrix()
20782128

2129+
def deformation_cone(self, collection):
2130+
r"""
2131+
Return the deformation cone for the ``collection`` of subconfigurations
2132+
of ``self``.
2133+
2134+
INPUT:
2135+
2136+
- ``collection`` -- a collection of subconfigurations of ``self``.
2137+
Subconfigurations are given as indices
2138+
2139+
OUTPUT: a polyhedron. It contains the liftings of the point configuration
2140+
making the collection a regular (or coherent, or projective)
2141+
subdivision.
2142+
2143+
EXAMPLES::
2144+
2145+
sage: PC = PointConfiguration([(-1, -1), (-1, 0), (0, -1), (1, 0), (0, 1)])
2146+
sage: coll = [(1, 4), (0, 2), (0, 1), (2, 3), (3, 4)]
2147+
sage: dc = PC.deformation_cone(coll);dc
2148+
A 5-dimensional polyhedron in QQ^5 defined as the convex hull of 1 vertex, 3 rays, 2 lines
2149+
sage: dc.rays()
2150+
(A ray in the direction (1, 0, 1, 0, 0),
2151+
A ray in the direction (1, 1, 0, 0, 0),
2152+
A ray in the direction (1, 1, 1, 0, 0))
2153+
sage: dc.lines()
2154+
(A line in the direction (1, 0, 1, 0, -1),
2155+
A line in the direction (1, 1, 0, -1, 0))
2156+
sage: dc.an_element()
2157+
(3, 2, 2, 0, 0)
2158+
2159+
We add to the interior element the first line and we verify that the
2160+
given rays are defining rays of the lower hull::
2161+
2162+
sage: P = Polyhedron(rays=[(-1, -1, 4), (-1, 0, 3), (0, -1, 2), (1, 0, -1), (0, 1, 0)])
2163+
sage: P.rays()
2164+
(A ray in the direction (-1, -1, 4),
2165+
A ray in the direction (-1, 0, 3),
2166+
A ray in the direction (0, -1, 2),
2167+
A ray in the direction (0, 1, 0),
2168+
A ray in the direction (1, 0, -1))
2169+
2170+
.. SEEALSO::
2171+
2172+
:meth:`~sage.schemes.toric.variety.Kaehler_cone`
2173+
2174+
REFERENCES:
2175+
2176+
For more information, see Section 5.4 of [DLRS2010]_ and Section
2177+
2.2 of [ACEP2020].
2178+
"""
2179+
from sage.geometry.polyhedron.constructor import Polyhedron
2180+
gale = self.Gale_transform(homogenize=False)
2181+
dual_rays = gale.columns()
2182+
n = self.n_points()
2183+
K = None
2184+
for cone_indices in collection:
2185+
dual_cone = Polyhedron(rays=[dual_rays[i] for i in range(n) if i not in cone_indices])
2186+
K = K.intersection(dual_cone) if K is not None else dual_cone
2187+
preimages = [gale.solve_right(r.vector()) for r in K.rays()]
2188+
return Polyhedron(lines=matrix(self.points()).transpose().rows(),rays=preimages)
2189+
20792190
def plot(self, **kwds):
20802191
r"""
20812192
Produce a graphical representation of the point configuration.

0 commit comments

Comments
 (0)