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

Commit

Permalink
Merge branch 'public/28639' of git://trac.sagemath.org/sage into publ…
Browse files Browse the repository at this point in the history
…ic/28639-reb
  • Loading branch information
Jonathan Kliem committed Dec 2, 2019
2 parents cf9673b + cc17f07 commit a54cfd9
Showing 1 changed file with 165 additions and 3 deletions.
168 changes: 165 additions & 3 deletions src/sage/geometry/polyhedron/backend_normaliz.py
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ def _init_from_normaliz_data(self, data, normaliz_field=None, verbose=False):
sage: p = Polyhedron(backend='normaliz', ambient_dim=2) # optional - pynormaliz
sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_QQ_normaliz # optional - pynormaliz
sage: data = {'inhom_inequalities': [[-1, 2, 0], [0, 0, 1], [2, -1, 0]]} # optional - pynormaliz
sage: data = {'inhom_inequalities': [[-1, 2, 0], [0, 0, 1], [2, -1, 0]]} # optional - pynormaliz
sage: Polyhedron_QQ_normaliz._init_from_normaliz_data(p, data) # optional - pynormaliz
sage: p.inequalities_list() # optional - pynormaliz
[[0, -1, 2], [0, 2, -1]]
Expand All @@ -379,7 +379,22 @@ def _init_from_normaliz_data(self, data, normaliz_field=None, verbose=False):
"""
if normaliz_field is None:
normaliz_field = QQ
cone = self._cone_from_normaliz_data(data, verbose)
self._init_from_normaliz_cone(cone, normaliz_field)

def _cone_from_normaliz_data(self, data, verbose=False):
"""
Construct a normaliz cone from ``data`` (a dictionary).
EXAMPLES::
sage: p = Polyhedron(backend='normaliz', ambient_dim=2) # optional - pynormaliz
sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_QQ_normaliz # optional - pynormaliz
sage: data = {'inhom_inequalities': [[-1, 2, 0], [0, 0, 1], [2, -1, 0]]} # optional - pynormaliz
sage: cone = Polyhedron_QQ_normaliz._cone_from_normaliz_data(p, data) # optional - pynormaliz
sage: p._nmz_result(cone,'SupportHyperplanes') # optional - pynormaliz
[[-1L, 2L, 0L], [0L, 0L, 1L], [2L, -1L, 0L]]
"""
if verbose:
import six
if isinstance(verbose, six.string_types):
Expand All @@ -401,8 +416,7 @@ def _init_from_normaliz_data(self, data, normaliz_field=None, verbose=False):
import PyNormaliz
cone = PyNormaliz.NmzCone(**data)
assert cone, "{} did not return a cone".format(_format_function_call('PyNormaliz.NmzCone', **data))

self._init_from_normaliz_cone(cone, normaliz_field)
return cone

def _is_zero(self, x):
"""
Expand Down Expand Up @@ -630,6 +644,154 @@ def nmz_ieqs_eqns_QQ(ieqs, eqns):
data["number_field"] = number_field_data
self._init_from_normaliz_data(data, normaliz_field=normaliz_field, verbose=verbose)

def _cone_from_Vrepresentation_and_Hrepresentation(self, vertices, rays, ieqs, eqns, verbose=False):
r"""
Construct cone from V-representation data and H-representation data.
INPUT:
- ``vertices`` -- list of point; each point can be specified
as any iterable container of
:meth:`~sage.geometry.polyhedron.base.base_ring` elements
- ``rays`` -- list of rays; each ray can be specified as any
iterable container of
:meth:`~sage.geometry.polyhedron.base.base_ring` elements
- ``ieqs`` -- list of inequalities; each line can be specified
as any iterable container of
:meth:`~sage.geometry.polyhedron.base.base_ring` elements
- ``eqns`` -- list of equalities; each line can be specified
as any iterable container of
:meth:`~sage.geometry.polyhedron.base.base_ring` elements
- ``verbose`` -- boolean (default: ``False``); whether to print
verbose output for debugging purposes
EXAMPLES::
sage: P = polytopes.hypercube(4,backend='normaliz') * Polyhedron(rays=[[0,1]]) * Polyhedron(lines=[[1,0]]) # optional - pynormaliz
sage: P # optional - pynormaliz
A 6-dimensional polyhedron in ZZ^8 defined as the convex hull of 16 vertices, 1 ray, 1 line
sage: cone = P._cone_from_Vrepresentation_and_Hrepresentation(P.vertices(),P.rays(),P.inequalities(),P.equations()) # optional - pynormaliz
sage: import PyNormaliz # optional - pynormaliz
sage: PyNormaliz.NmzIsComputed(cone, "VerticesOfPolyhedron") # optional - pynormaliz
True
sage: PyNormaliz.NmzIsComputed(cone, "ExtremeRays") # optional - pynormaliz
True
sage: PyNormaliz.NmzIsComputed(cone, "MaximalSubspace") # optional - pynormaliz
False
sage: PyNormaliz.NmzIsComputed(cone, "SupportHyperplanes") # optional - pynormaliz
True
sage: PyNormaliz.NmzIsComputed(cone, "Equations") # optional - pynormaliz
False
TESTS::
sage: def test_poly(P):
....: cone = P._cone_from_Vrepresentation_and_Hrepresentation(P.vertices(),P.rays(),P.inequalities(),P.equations())
....: cone2 = P._normaliz_cone
....: args = ['Equations','VerticesOfPolyhedron','ExtremeRays','SupportHyperplanes','MaximalSubspace']
....: return all(P._nmz_result(cone,arg) == P._nmz_result(cone2,arg) for arg in args)
sage: test_poly(polytopes.simplex(backend='normaliz')) # optional - pynormaliz
True
sage: test_poly(polytopes.dodecahedron(backend='normaliz')) # optional - pynormaliz
True
sage: test_poly(Polyhedron(vertices=[[1,0],[0,1]],rays=[[1,1]], backend='normaliz')) # optional - pynormaliz
True
sage: test_poly(Polyhedron(vertices=[[0,0,0],[0,1,1],[1,0,1],[-1,-1,1]],rays=[[0,0,1]], backend='normaliz')) # optional - pynormaliz
True
sage: test_poly(Polyhedron(vertices=[[-1,0],[1,0]],lines=[[0,1]], backend='normaliz')) # optional - pynormaliz
True
"""
def vert_ray_QQ(vertices, rays):
nmz_vertices = []
for v in vertices:
d = LCM_list([denominator(v_i) for v_i in v])
dv = [ d*v_i for v_i in v ]
nmz_vertices.append(dv + [d])
nmz_rays = []
for r in rays:
d = LCM_list([denominator(r_i) for r_i in r])
dr = [ d*r_i for r_i in r ]
nmz_rays.append(dr + [0])
return nmz_vertices, nmz_rays

def nmz_ieqs_eqns_QQ(ieqs, eqns):
nmz_ieqs = []
for ieq in ieqs:
d = LCM_list([denominator(ieq_i) for ieq_i in ieq])
dieq = [ ZZ(d*ieq_i) for ieq_i in ieq ]
b = dieq[0]
A = dieq[1:]
nmz_ieqs.append(A + [b])
nmz_eqns = []
for eqn in eqns:
d = LCM_list([denominator(eqn_i) for eqn_i in eqn])
deqn = [ ZZ(d*eqn_i) for eqn_i in eqn ]
b = deqn[0]
A = deqn[1:]
nmz_eqns.append(A + [b])
return nmz_ieqs, nmz_eqns

def vert_ray_NF(vertices, rays):
h_vertices = [ list(v) + [1] for v in vertices ]
h_rays = [ list(r) + [0] for r in rays ]
return h_vertices, h_rays

def nmz_ieqs_eqns_NF(ieqs, eqns):
nmz_ieqs = []
for ieq in ieqs:
b = ieq[0]
A = ieq[1:]
nmz_ieqs.append(list(A) + [b])
nmz_eqns = []
for eqn in eqns:
b = eqn[0]
A = eqn[1:]
nmz_eqns.append(list(A) + [b])
return nmz_ieqs, nmz_eqns

if vertices is None:
vertices = []
if rays is None:
rays = []
if ieqs is None:
ieqs = []
if eqns is None:
eqns = []

(nmz_vertices, nmz_rays), normaliz_field \
= self._compute_nmz_data_lists_and_field((vertices, rays),
vert_ray_QQ,
vert_ray_NF)

(nmz_ieqs, nmz_eqns), normaliz_field \
= self._compute_nmz_data_lists_and_field((ieqs, eqns),
nmz_ieqs_eqns_QQ,
nmz_ieqs_eqns_NF)

if not nmz_vertices and not nmz_rays:
# Special case to avoid:
# error: Some error in the normaliz input data detected:
# All input matrices empty!
return None
else:
data = {"extreme_rays": nmz_vertices + nmz_rays,
"equations": nmz_eqns,
"support_hyperplanes": nmz_ieqs}

ambient_dim = len(data["extreme_rays"][0])
data["dehomogenization"] = [[0]*(ambient_dim-1) + [1]]

number_field_data = self._number_field_triple(normaliz_field)
if number_field_data:
data["number_field"] = number_field_data
return self._cone_from_normaliz_data(data, verbose=verbose)

def _compute_nmz_data_lists_and_field(self, data_lists, convert_QQ, convert_NF):
r"""
Compute data lists in Normaliz format and the number field to use with Normaliz.
Expand Down

0 comments on commit a54cfd9

Please sign in to comment.