def _init_from_Vrepresentation(self, vertices, rays, lines, minimize=True, verbose=False): r""" Construct polyhedron from V-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 - ``lines`` -- list of lines; 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 = Polyhedron(backend='polymake') # optional - polymake sage: from sage.geometry.polyhedron.backend_polymake import Polyhedron_polymake # optional - polymake sage: Polyhedron_polymake._init_from_Vrepresentation(p, [], [], []) # optional - polymake """ from sage.interfaces.polymake import polymake polymake_field = polymake(self.base_ring().fraction_field()) p = polymake.new_object("Polytope<{}>".format(polymake_field), CONE_AMBIENT_DIM=1+self.parent().ambient_dim(), POINTS= [ [1] + v for v in vertices ] \ + [ [0] + r for r in rays ], INPUT_LINEALITY=[ [0] + l for l in lines ]) self._init_from_polymake_polytope(p)
def _init_from_Hrepresentation(self, ieqs, eqns, minimize=True, verbose=False): r""" Construct polyhedron from H-representation data. INPUT: - ``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 - ``minimize`` -- boolean (default: ``True``); ignored - ``verbose`` -- boolean (default: ``False``); whether to print verbose output for debugging purposes EXAMPLES:: sage: p = Polyhedron(backend='polymake') # optional - polymake sage: from sage.geometry.polyhedron.backend_polymake import Polyhedron_polymake # optional - polymake sage: Polyhedron_polymake._init_from_Hrepresentation(p, [], []) # optional - polymake """ from sage.interfaces.polymake import polymake data = self._polymake_Hrepresentation_data(ieqs, eqns) polymake_field = polymake(self.base_ring().fraction_field()) p = polymake.new_object("Polytope<{}>".format(polymake_field), **data) self._init_from_polymake_polytope(p)
def _init_from_Hrepresentation(self, ieqs, eqns, minimize=True, verbose=False): r""" Construct polyhedron from H-representation data. INPUT: - ``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 - ``minimize`` -- boolean (default: ``True``); ignored - ``verbose`` -- boolean (default: ``False``); whether to print verbose output for debugging purposes EXAMPLES:: sage: p = Polyhedron(backend='polymake') # optional - polymake sage: from sage.geometry.polyhedron.backend_polymake import Polyhedron_polymake # optional - polymake sage: Polyhedron_polymake._init_from_Hrepresentation(p, [], []) # optional - polymake """ from sage.interfaces.polymake import polymake if ieqs is None: ieqs = [] if eqns is None: eqns = [] # Polymake 3.0r2 and 3.1 crash with a segfault for a test case # using QuadraticExtension, when some all-zero inequalities are input. # https://forum.polymake.org/viewtopic.php?f=8&t=547 # Filter them out. ieqs = [v for v in ieqs if not all(self._is_zero(x) for x in v)] # We do a similar filtering for equations. # Since Polymake 3.2, we can not give all zero vectors in equations eqns = [v for v in eqns if not all(self._is_zero(x) for x in v)] if not ieqs: # Put in one trivial (all-zero) inequality. This is so that # the ambient dimension is set correctly. # Since Polymake 3.2, the constant should not be zero. ieqs.append([1] + [0] * self.ambient_dim()) polymake_field = polymake(self.base_ring().fraction_field()) p = polymake.new_object("Polytope<{}>".format(polymake_field), EQUATIONS=eqns, INEQUALITIES=ieqs) self._init_from_polymake_polytope(p)
def _init_from_Hrepresentation(self, ieqs, eqns, minimize=True, verbose=False): r""" Construct polyhedron from H-representation data. INPUT: - ``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 - ``minimize`` -- boolean (default: ``True``); ignored - ``verbose`` -- boolean (default: ``False``); whether to print verbose output for debugging purposes EXAMPLES:: sage: p = Polyhedron(backend='polymake') # optional - polymake sage: from sage.geometry.polyhedron.backend_polymake import Polyhedron_polymake # optional - polymake sage: Polyhedron_polymake._init_from_Hrepresentation(p, [], []) # optional - polymake """ from sage.interfaces.polymake import polymake if ieqs is None: ieqs = [] if eqns is None: eqns = [] # Polymake 3.0r2 and 3.1 crash with a segfault for a test case # using QuadraticExtension, when some all-zero inequalities are input. # https://forum.polymake.org/viewtopic.php?f=8&t=547 # Filter them out. ieqs = [ v for v in ieqs if not all(self._is_zero(x) for x in v) ] if not ieqs: # Put in one trivial (all-zero) inequality. This is so that # the ambient dimension is set correctly. ieqs.append([0] + [0]*self.ambient_dim()) polymake_field = polymake(self.base_ring().fraction_field()) p = polymake.new_object("Polytope<{}>".format(polymake_field), EQUATIONS=eqns, INEQUALITIES=ieqs) self._init_from_polymake_polytope(p)
def _init_from_Vrepresentation(self, vertices, rays, lines, minimize=True, verbose=False): r""" Construct polyhedron from V-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 - ``lines`` -- list of lines; 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 = Polyhedron(backend='polymake') # optional - polymake sage: from sage.geometry.polyhedron.backend_polymake import Polyhedron_polymake # optional - polymake sage: Polyhedron_polymake._init_from_Vrepresentation(p, [], [], []) # optional - polymake """ from sage.interfaces.polymake import polymake polymake_field = polymake(self.base_ring().fraction_field()) p = polymake.new_object("Polytope<{}>".format(polymake_field), CONE_AMBIENT_DIM=1+self.parent().ambient_dim(), POINTS= [ [1] + v for v in vertices ] \ + [ [0] + r for r in rays ], INPUT_LINEALITY=[ [0] + l for l in lines ]) self._init_from_polymake_polytope(p)
def _polymake_polytope_from_Vrepresentation_and_Hrepresentation( self, Vrep, Hrep): if not any(Vrep): # The empty polyhedron. return from sage.interfaces.polymake import polymake data = self._polymake_Vrepresentation_data(*Vrep, minimal=True) if any(Vrep[1:]): from sage.matrix.constructor import Matrix polymake_rays = [r for r in data['VERTICES'] if r[0] == 0] if Matrix(data['VERTICES']).rank( ) == Matrix(polymake_rays).rank() + 1: # The recession cone is full-dimensional. # In this case the homogenized inequalities # do not ensure nonnegativy in the last coordinate. # In the homogeneous cone the far face is a facet. Hrep[0] += [[1] + [0] * self.ambient_dim()] data.update(self._polymake_Hrepresentation_data(*Hrep, minimal=True)) polymake_field = polymake(self.base_ring().fraction_field()) return polymake.new_object("Polytope<{}>".format(polymake_field), **data)
def Polyhedra(ambient_space_or_base_ring=None, ambient_dim=None, backend=None, *, ambient_space=None, base_ring=None): r""" Construct a suitable parent class for polyhedra INPUT: - ``base_ring`` -- A ring. Currently there are backends for `\ZZ`, `\QQ`, and `\RDF`. - ``ambient_dim`` -- integer. The ambient space dimension. - ``ambient_space`` -- A free module. - ``backend`` -- string. The name of the backend for computations. There are several backends implemented: * ``backend="ppl"`` uses the Parma Polyhedra Library * ``backend="cdd"`` uses CDD * ``backend="normaliz"`` uses normaliz * ``backend="polymake"`` uses polymake * ``backend="field"`` a generic Sage implementation OUTPUT: A parent class for polyhedra over the given base ring if the backend supports it. If not, the parent base ring can be larger (for example, `\QQ` instead of `\ZZ`). If there is no implementation at all, a ``ValueError`` is raised. EXAMPLES:: sage: from sage.geometry.polyhedron.parent import Polyhedra sage: Polyhedra(AA, 3) Polyhedra in AA^3 sage: Polyhedra(ZZ, 3) Polyhedra in ZZ^3 sage: type(_) <class 'sage.geometry.polyhedron.parent.Polyhedra_ZZ_ppl_with_category'> sage: Polyhedra(QQ, 3, backend='cdd') Polyhedra in QQ^3 sage: type(_) <class 'sage.geometry.polyhedron.parent.Polyhedra_QQ_cdd_with_category'> CDD does not support integer polytopes directly:: sage: Polyhedra(ZZ, 3, backend='cdd') Polyhedra in QQ^3 Using a more general form of the constructor:: sage: V = VectorSpace(QQ, 3) sage: Polyhedra(V) is Polyhedra(QQ, 3) True sage: Polyhedra(V, backend='field') is Polyhedra(QQ, 3, 'field') True sage: Polyhedra(backend='field', ambient_space=V) is Polyhedra(QQ, 3, 'field') True sage: M = FreeModule(ZZ, 2) sage: Polyhedra(M, backend='ppl') is Polyhedra(ZZ, 2, 'ppl') True TESTS:: sage: Polyhedra(RR, 3, backend='field') Traceback (most recent call last): ... ValueError: the 'field' backend for polyhedron cannot be used with non-exact fields sage: Polyhedra(RR, 3) Traceback (most recent call last): ... ValueError: no default backend for computations with Real Field with 53 bits of precision sage: Polyhedra(QQ[I], 2) Traceback (most recent call last): ... ValueError: invalid base ring: Number Field in I with defining polynomial x^2 + 1 with I = 1*I cannot be coerced to a real field sage: Polyhedra(AA, 3, backend='polymake') # optional - polymake Traceback (most recent call last): ... ValueError: the 'polymake' backend for polyhedron cannot be used with Algebraic Real Field sage: Polyhedra(QQ, 2, backend='normaliz') # optional - pynormaliz Polyhedra in QQ^2 sage: Polyhedra(SR, 2, backend='normaliz') # optional - pynormaliz # optional - sage.symbolic Polyhedra in (Symbolic Ring)^2 sage: SCR = SR.subring(no_variables=True) # optional - sage.symbolic sage: Polyhedra(SCR, 2, backend='normaliz') # optional - pynormaliz # optional - sage.symbolic Polyhedra in (Symbolic Constants Subring)^2 """ if ambient_space_or_base_ring is not None: if ambient_space_or_base_ring in Rings(): base_ring = ambient_space_or_base_ring else: ambient_space = ambient_space_or_base_ring if ambient_space is not None: if ambient_space not in Modules: # There is no category of free modules, unfortunately # (see https://trac.sagemath.org/ticket/30164)... raise ValueError('ambient_space must be a free module') if base_ring is None: base_ring = ambient_space.base_ring() if ambient_dim is None: try: ambient_dim = ambient_space.rank() except AttributeError: # ... so we test whether it is free using the existence of # a rank method raise ValueError('ambient_space must be a free module') if ambient_space is not FreeModule(base_ring, ambient_dim): raise NotImplementedError( 'ambient_space must be a standard free module') if backend is None: if base_ring is ZZ or base_ring is QQ: backend = 'ppl' elif base_ring is RDF: backend = 'cdd' elif base_ring.is_exact(): # TODO: find a more robust way of checking that the coefficients are indeed # real numbers if not RDF.has_coerce_map_from(base_ring): raise ValueError( "invalid base ring: {} cannot be coerced to a real field". format(base_ring)) backend = 'field' else: raise ValueError( "no default backend for computations with {}".format( base_ring)) try: from sage.symbolic.ring import SR except ImportError: SR = None if backend == 'ppl' and base_ring is QQ: return Polyhedra_QQ_ppl(base_ring, ambient_dim, backend) elif backend == 'ppl' and base_ring is ZZ: return Polyhedra_ZZ_ppl(base_ring, ambient_dim, backend) elif backend == 'normaliz' and base_ring is QQ: return Polyhedra_QQ_normaliz(base_ring, ambient_dim, backend) elif backend == 'normaliz' and base_ring is ZZ: return Polyhedra_ZZ_normaliz(base_ring, ambient_dim, backend) elif backend == 'normaliz' and (isinstance( base_ring, sage.rings.abc.SymbolicRing) or base_ring.is_exact()): return Polyhedra_normaliz(base_ring, ambient_dim, backend) elif backend == 'cdd' and base_ring in (ZZ, QQ): return Polyhedra_QQ_cdd(QQ, ambient_dim, backend) elif backend == 'cdd' and base_ring is RDF: return Polyhedra_RDF_cdd(RDF, ambient_dim, backend) elif backend == 'polymake': base_field = base_ring.fraction_field() try: from sage.interfaces.polymake import polymake polymake_base_field = polymake(base_field) except TypeError: raise ValueError( f"the 'polymake' backend for polyhedron cannot be used with {base_field}" ) return Polyhedra_polymake(base_field, ambient_dim, backend) elif backend == 'field': if not base_ring.is_exact(): raise ValueError( "the 'field' backend for polyhedron cannot be used with non-exact fields" ) return Polyhedra_field(base_ring.fraction_field(), ambient_dim, backend) else: raise ValueError('No such backend (=' + str(backend) + ') implemented for given basering (=' + str(base_ring) + ').')