Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
implement ambient volume using normaliz
Browse files Browse the repository at this point in the history
  • Loading branch information
Jonathan Kliem committed Mar 27, 2020
2 parents be1e22c + add61a5 commit 0797f5a
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 8 deletions.
58 changes: 52 additions & 6 deletions src/sage/geometry/polyhedron/backend_normaliz.py
Original file line number Diff line number Diff line change
Expand Up @@ -1319,14 +1319,17 @@ def _volume_normaliz(self, measure='euclidean'):
INPUT:
- ``measure`` -- (default: 'euclidean') the measure to take. 'euclidean'
correspond to ``EuclideanVolume`` in normaliz and 'induced_lattice'
correspond to ``Volume`` in normaliz.
- ``measure`` -- string. The measure to use. Allowed values are:
* ``'euclidean'`` (default): corresponds to ``'EuclideanVolume`` in normaliz
* ``'induced_lattice'``: corresponds to ``'Volume'`` in normaliz
* ``'ambient'``: Lebesgue measure of ambient space (volume)
OUTPUT:
A float value (when ``measure`` is 'euclidean') or a rational number
(when ``measure`` is 'induced_lattice').
A float value (when ``measure`` is 'euclidean'),
a rational number (when ``measure`` is 'induced_lattice'),
a rational number or symbolic number otherwise (dependent on base ring).
.. NOTE::
Expand All @@ -1342,7 +1345,7 @@ def _volume_normaliz(self, measure='euclidean'):
sage: s._volume_normaliz() # optional - pynormaliz
0.3333333333333333
The other possibility is to compute the scaled volume where a unimodual
One other possibility is to compute the scaled volume where a unimodual
simplex has volume 1::
sage: s._volume_normaliz(measure='induced_lattice') # optional - pynormaliz
Expand All @@ -1354,13 +1357,42 @@ def _volume_normaliz(self, measure='euclidean'):
sage: cube._volume_normaliz(measure='induced_lattice') # optional - pynormaliz
6
Or one can can calculate the ambient volume, which is the above multiplied by the
volume of the unimodal simplex (or zero if not full-dimensional)::
sage: cube._volume_normaliz(measure='ambient') # optional - pynormaliz
1
sage: s._volume_normaliz(measure='ambient') # optional - pynormaliz
0
TESTS:
Check that :trac:`28872` is fixed::
sage: P = polytopes.dodecahedron(backend='normaliz') # optional - pynormaliz
sage: P.volume(measure='induced_lattice') # optional - pynormaliz
-1056*sqrt5 + 2400
Some sanity checks that the ambient volume works correctly::
sage: (2*cube)._volume_normaliz(measure='ambient') # optional - pynormaliz
8
sage: (1/2*cube)._volume_normaliz(measure='ambient') # optional - pynormaliz
1/8
sage: s._volume_normaliz(measure='ambient') # optional - pynormaliz
0
sage: P = polytopes.regular_polygon(3, backend='normaliz') # optional - pynormaliz
sage: P._volume_normaliz('ambient') == P.volume(engine='internal') # optional - pynormaliz
True
sage: P = polytopes.dodecahedron(backend='normaliz') # optional - pynormaliz
sage: P._volume_normaliz('ambient') == P.volume(engine='internal') # optional - pynormaliz
True
sage: P = Polyhedron(rays=[[1]], backend='normaliz') # optional - pynormaliz
sage: P.volume() # optional - pynormaliz
+Infinity
"""
cone = self._normaliz_cone
assert cone
Expand All @@ -1371,6 +1403,20 @@ def _volume_normaliz(self, measure='euclidean'):
return self._nmz_result(cone, 'Volume')
else:
return self._nmz_result(cone, 'RenfVolume')
elif measure == 'ambient':
if self.dim() < self.ambient_dim():
return self.base_ring().zero()
if not self.is_compact():
from sage.rings.infinity import infinity
return infinity

from sage.functions.other import factorial
volume = self._volume_normaliz('induced_lattice')/factorial(self.dim())

return volume

else:
raise TypeError("the measure should be `ambient`, `euclidean`, or `induced_lattice`")

def _triangulate_normaliz(self):
r"""
Expand Down
5 changes: 4 additions & 1 deletion src/sage/geometry/polyhedron/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -7088,6 +7088,9 @@ def volume(self, measure='ambient', engine='auto', **kwds):
except FeatureNotPresentError:
raise RuntimeError("the induced rational measure can only be computed with the optional packages `latte_int`, or `pynormaliz`")

if engine == 'auto' and measure == 'ambient' and self.backend() == 'normaliz':
engine = 'normaliz'

if measure == 'ambient':
if self.dim() < self.ambient_dim():
return self.base_ring().zero()
Expand All @@ -7102,7 +7105,7 @@ def volume(self, measure='ambient', engine='auto', **kwds):
elif engine == 'latte':
return self._volume_latte(**kwds)
elif engine == 'normaliz':
return self._volume_normaliz(measure='euclidean')
return self._volume_normaliz(measure='ambient')

triangulation = self.triangulate(engine=engine, **kwds)
pc = triangulation.point_configuration()
Expand Down
2 changes: 1 addition & 1 deletion src/sage/geometry/polyhedron/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ def regular_polygon(self, n, exact=True, base_ring=None, backend=None):
sage: octagon.n_vertices() # optional - pynormaliz
8
sage: octagon.volume() # optional - pynormaliz
2.828427124746190?
2*a
"""
n = ZZ(n)
if n <= 2:
Expand Down

0 comments on commit 0797f5a

Please sign in to comment.