def Polyhedra(base_ring, ambient_dim, backend=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. - ``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 TESTS:: sage: Polyhedra(RR, 3, backend='field') Traceback (most recent call last): ... ValueError: the 'field' backend for polyhedron can not be used with non-exact fields sage: Polyhedra(RR, 3) Traceback (most recent call last): ... ValueError: no appropriate backend for computations with Real Field with 53 bits of precision """ 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") backend = 'field' else: raise ValueError("no appropriate backend for computations with {}".format(base_ring)) 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 == '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': return Polyhedra_polymake(base_ring.fraction_field(), ambient_dim, backend) elif backend == 'field': if not base_ring.is_exact(): raise ValueError("the 'field' backend for polyhedron can not 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)+').')
def Polyhedra(base_ring, ambient_dim, backend=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. - ``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 TESTS:: sage: Polyhedra(RR, 3, backend='field') Traceback (most recent call last): ... ValueError: the 'field' backend for polyhedron can not 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 """ 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)) from sage.symbolic.ring import SR 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 (base_ring is SR 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': return Polyhedra_polymake(base_ring.fraction_field(), ambient_dim, backend) elif backend == 'field': if not base_ring.is_exact(): raise ValueError("the 'field' backend for polyhedron can not 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)+').')
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 can not 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 """ 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)) from sage.symbolic.ring import SR 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 (base_ring is SR 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': return Polyhedra_polymake(base_ring.fraction_field(), ambient_dim, backend) elif backend == 'field': if not base_ring.is_exact(): raise ValueError( "the 'field' backend for polyhedron can not 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) + ').')