diff --git a/build/pkgs/normaliz/checksums.ini b/build/pkgs/normaliz/checksums.ini index e92b65013a9..1840b515d2b 100644 --- a/build/pkgs/normaliz/checksums.ini +++ b/build/pkgs/normaliz/checksums.ini @@ -1,4 +1,4 @@ tarball=normaliz-VERSION.tar.gz -sha1=927f9683b615389ae06fb0b83272abffd977c4e5 -md5=f6f5f498ccd19cb1c0a819b4147aec51 -cksum=2376092445 +sha1=76e2fc02cf2eb9b2d05c9b26f64a90015fb3292b +md5=0cd4efb6d6f7177ce83955785a59dd6d +cksum=1666633916 diff --git a/build/pkgs/normaliz/package-version.txt b/build/pkgs/normaliz/package-version.txt index 444877d48fb..4a788a01dad 100644 --- a/build/pkgs/normaliz/package-version.txt +++ b/build/pkgs/normaliz/package-version.txt @@ -1 +1 @@ -3.5.3 +3.6.3 diff --git a/build/pkgs/normaliz/spkg-install b/build/pkgs/normaliz/spkg-install index 1bf6570f46c..9e6961b1307 100644 --- a/build/pkgs/normaliz/spkg-install +++ b/build/pkgs/normaliz/spkg-install @@ -7,7 +7,7 @@ die () { cd src -# Disable features that require packages SCIP and CoCoA, for which we don't have packages (yet). +# Disable features that require packages SCIP and CoCoA, both of which are experimental packages. # FLINT is a standard package. We pass --enable-flint to configure so that an error will be signalled # if FLINT cannot be found, rather than building normaliz without it. ./configure --disable-scip --disable-nmzintegrate --enable-flint --prefix=$SAGE_LOCAL || die "Error configuring normaliz" diff --git a/build/pkgs/pynormaliz/checksums.ini b/build/pkgs/pynormaliz/checksums.ini index 5b1e118dfc7..59f2ebab8b1 100644 --- a/build/pkgs/pynormaliz/checksums.ini +++ b/build/pkgs/pynormaliz/checksums.ini @@ -1,4 +1,4 @@ tarball=PyNormaliz-VERSION.tar.gz -sha1=8acc2f51ed31b1d8e965f43b82ad08b0d35111e9 -md5=1ec3419eaa061a0ee4b4f1ffca9cb44d -cksum=796575946 +sha1=17c3d327ec4497e19af3c0152b531ff510f18a3c +md5=9a752b2c94e9dd175eff5d180e3cd46e +cksum=2507406832 diff --git a/build/pkgs/pynormaliz/package-version.txt b/build/pkgs/pynormaliz/package-version.txt index 809bdcb851d..bc4493477ae 100644 --- a/build/pkgs/pynormaliz/package-version.txt +++ b/build/pkgs/pynormaliz/package-version.txt @@ -1 +1 @@ -1.12 +1.19 diff --git a/src/sage/geometry/polyhedron/backend_normaliz.py b/src/sage/geometry/polyhedron/backend_normaliz.py index 88ea909f6c1..33314c5e7a9 100644 --- a/src/sage/geometry/polyhedron/backend_normaliz.py +++ b/src/sage/geometry/polyhedron/backend_normaliz.py @@ -176,6 +176,34 @@ def _init_from_normaliz_cone(self, normaliz_cone): self._init_Vrepresentation_from_normaliz() self._init_Hrepresentation_from_normaliz() + def _init_from_normaliz_data(self, data, verbose=False): + """ + Construct polyhedron from normaliz ``data`` (a dictionary). + + TESTS:: + + sage: p = Polyhedron(backend='normaliz', ambient_dim=2) # optional - pynormaliz + sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz # optional - pynormaliz + sage: data = {'inhom_inequalities': [[-1L, 2L, 0L], [0L, 0L, 1L], [2L, -1L, 0L]]} # optional - pynormaliz + sage: Polyhedron_normaliz._init_from_normaliz_data(p, data) # optional - pynormaliz + sage: p.inequalities_list() # optional - pynormaliz + [[0, -1, 2], [0, 2, -1]] + """ + import PyNormaliz + if verbose: + print("# Calling PyNormaliz.NmzCone(**{})".format(data)) + import six + if isinstance(verbose, six.string_types): + print("# Wrote equivalent Normaliz input file to {}".format(verbose)) + self._normaliz_format(data, file_output=verbose) + else: + print("# ----8<---- Equivalent Normaliz input file ----8<----") + print(self._normaliz_format(data), end='') + print("# ----8<-------------------8<-------------------8<----") + cone = PyNormaliz.NmzCone(**data) + assert cone, "NmzCone(**{}) did not return a cone".format(data) + self._init_from_normaliz_cone(cone) + def _init_from_Vrepresentation(self, vertices, rays, lines, minimize=True, verbose=False): r""" Construct polyhedron from V-representation data. @@ -203,7 +231,6 @@ def _init_from_Vrepresentation(self, vertices, rays, lines, minimize=True, verbo sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz # optional - pynormaliz sage: Polyhedron_normaliz._init_from_Vrepresentation(p, [], [], []) # optional - pynormaliz """ - import PyNormaliz if vertices is None: vertices = [] nmz_vertices = [] @@ -230,14 +257,10 @@ def _init_from_Vrepresentation(self, vertices, rays, lines, minimize=True, verbo # All input matrices empty! self._init_empty_polyhedron() else: - data = ["vertices", nmz_vertices, - "cone", nmz_rays, - "subspace", nmz_lines] - if verbose: - print("# Calling PyNormaliz.NmzCone({})".format(data)) - cone = PyNormaliz.NmzCone(data) - assert cone, "NmzCone({}) did not return a cone".format(data) - self._init_from_normaliz_cone(cone) + data = {"vertices": nmz_vertices, + "cone": nmz_rays, + "subspace": nmz_lines} + self._init_from_normaliz_data(data, verbose=verbose) def _init_from_Hrepresentation(self, ieqs, eqns, minimize=True, verbose=False): r""" @@ -264,7 +287,6 @@ def _init_from_Hrepresentation(self, ieqs, eqns, minimize=True, verbose=False): sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz # optional - pynormaliz sage: Polyhedron_normaliz._init_from_Hrepresentation(p, [], []) # optional - pynormaliz """ - import PyNormaliz if ieqs is None: ieqs = [] nmz_ieqs = [] for ieq in ieqs: @@ -286,14 +308,9 @@ def _init_from_Hrepresentation(self, ieqs, eqns, minimize=True, verbose=False): b = deqn[0] A = deqn[1:] nmz_eqns.append(A + [b]) - data = ["inhom_equations", nmz_eqns, - "inhom_inequalities", nmz_ieqs] - self._normaliz_cone = PyNormaliz.NmzCone(data) - if verbose: - print("# Calling PyNormaliz.NmzCone({})".format(data)) - cone = PyNormaliz.NmzCone(data) - assert cone, "NmzCone({}) did not return a cone".format(data) - self._init_from_normaliz_cone(cone) + data = {"inhom_equations": nmz_eqns, + "inhom_inequalities": nmz_ieqs} + self._init_from_normaliz_data(data, verbose=verbose) def _init_Vrepresentation_from_normaliz(self): r""" @@ -374,7 +391,7 @@ def _init_empty_polyhedron(self): """ super(Polyhedron_normaliz, self)._init_empty_polyhedron() # Can't seem to set up an empty _normaliz_cone. - # For example, PyNormaliz.NmzCone(['vertices', []]) gives + # For example, PyNormaliz.NmzCone(vertices=[]) gives # error: Some error in the normaliz input data detected: All input matrices empty! self._normaliz_cone = None @@ -391,6 +408,120 @@ def _from_normaliz_cone(cls, parent, normaliz_cone): """ return cls(parent, None, None, normaliz_cone=normaliz_cone) + @staticmethod + def _make_normaliz_cone(data, verbose=False): + r""" + Returns a normaliz cone from ``data``. + + INPUT: + + - ``data`` -- a dictionary + + - ``verbose`` -- a boolean (default: ``False``) + + TESTS:: + + sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz # optional - pynormaliz + sage: data = {'inhom_inequalities': [[-1L, 2L, 0L], [0L, 0L, 1L], [2L, -1L, 0L]]} # optional - pynormaliz + sage: nmz_cone = Polyhedron_normaliz._make_normaliz_cone(data,verbose=False) # optional - pynormaliz + sage: from PyNormaliz import NmzResult # optional - pynormaliz + sage: NmzResult(nmz_cone, "ExtremeRays") # optional - pynormaliz + [[1L, 2L, 0L], [2L, 1L, 0L]] + """ + import PyNormaliz + if verbose: + print("# Calling PyNormaliz.NmzCone(**{})".format(data)) + cone = PyNormaliz.NmzCone(**data) + assert cone, "NmzCone(**{}) did not return a cone".format(data) + return cone + + def _get_nmzcone_data(self): + r""" + Get the data necessary to reproduce the normaliz cone. + + OUTPUT: + + - ``data`` -- a dictionary. + + TESTS: + + The empty polyhedron:: + + sage: P = Polyhedron(backend='normaliz') # optional - pynormaliz + sage: P._get_nmzcone_data() # optional - pynormaliz + {} + + Another simple example:: + + sage: C = Polyhedron(backend='normaliz',rays=[[1,2],[2,1]]) # optional - pynormaliz + sage: C._get_nmzcone_data() # optional - pynormaliz + {'cone': [[1L, 2L], [2L, 1L]], + 'inhom_equations': [], + 'inhom_inequalities': [[-1L, 2L, 0L], [0L, 0L, 1L], [2L, -1L, 0L]], + 'subspace': [], + 'vertices': [[0L, 0L, 1L]]} + """ + import PyNormaliz + if self.is_empty(): + return {} + + vertices = PyNormaliz.NmzResult(self._normaliz_cone, "VerticesOfPolyhedron") + # get rid of the last 0 in rays: + rays = [r[:-1] for r in PyNormaliz.NmzResult(self._normaliz_cone, "ExtremeRays")] + lines = PyNormaliz.NmzResult(self._normaliz_cone, "MaximalSubspace") + ineqs = PyNormaliz.NmzResult(self._normaliz_cone, "SupportHyperplanes") + eqs = PyNormaliz.NmzResult(self._normaliz_cone, "Equations") + + data = {'vertices': vertices, + 'cone': rays, + 'subspace': lines, + 'inhom_equations': eqs, + 'inhom_inequalities': ineqs} + + return data + + def _normaliz_format(self, data, file_output=None): + r""" + Return a string containing normaliz format. + + INPUT: + + - ``data`` -- a dictionary of PyNormaliz cone input properties + + - ``file_output`` (string; optional) -- a filename to which the + representation should be written. If set to ``None`` (default), + representation is returned as a string. + + EXAMPLES:: + + sage: P = Polyhedron(vertices=[[0, 0], [0, 1], [1, 0]], # indirect doctest; optional - pynormaliz + ....: backend='normaliz', verbose=True) + # Calling ... + # ----8<---- Equivalent Normaliz input file ----8<---- + amb_space 2 + subspace 0 + vertices 3 + 0 0 1 + 0 1 1 + 1 0 1 + cone 0 + # ----8<-------------------8<-------------------8<---- + """ + s = 'amb_space {}\n'.format(self.ambient_dim()) + for key, value in data.iteritems(): + s += '{} {}\n'.format(key, len(value)) + for e in value: + for x in e: + s += ' ' + repr(x) + s += '\n' + + if file_output is not None: + in_file = open(file_output, 'w') + in_file.write(s) + in_file.close() + else: + return s + def integral_hull(self): r""" Return the integral hull in the polyhedron.