def eliminate(polys, elim_variables, **kwds): r""" Compute a Groebner basis with respect to an elimination order defined by the given variables. INPUT: - ``polys`` -- an ideal or a polynomial sequence. - ``elim_variables`` -- the variables to eliminate. - ``force_elim`` -- integer (default: `1`). - ``kwds`` -- same as in :func:`groebner_basis`. OUTPUT: a Groebner basis of the elimination ideal. EXAMPLES:: sage: R.<x,y,t,s,z> = PolynomialRing(QQ,5) sage: I = R * [x-t,y-t^2,z-t^3,s-x+y^3] sage: import fgb_sage # optional - fgb_sage sage: gb = fgb_sage.eliminate(I, [t,s], verbosity=0) # optional - fgb_sage, random open simulation sage: gb # optional - fgb_sage [x^2 - y, x*y - z, y^2 - x*z] sage: gb.is_groebner() # optional - fgb_sage True sage: gb.ideal() == I.elimination_ideal([t,s]) # optional - fgb_sage True .. NOTE:: In some cases, this function fails to set the correct elimination order, see :trac:`24981`. This was fixed in Sage 8.7. """ kwds.setdefault('force_elim', 1) polyseq = PolynomialSequence(polys) ring = polyseq.ring() elim_variables = set(elim_variables) block1 = [x for x in ring.gens() if x in elim_variables] block2 = [x for x in ring.gens() if x not in elim_variables] from sage.rings.polynomial.term_order import TermOrder if len(block1) == 0 or len(block2) == 0: t = TermOrder("degrevlex", ring.ngens()) else: t = TermOrder("degrevlex", len(block1)) + TermOrder( "degrevlex", len(block2)) if t == ring.term_order() and set( ring.gens()[:len(block1)]) == elim_variables: return groebner_basis(polyseq, **kwds) else: block_ring = ring.change_ring(names=block1 + block2, order=t) gb = groebner_basis(PolynomialSequence(block_ring, polyseq), **kwds) return PolynomialSequence(ring, gb, immutable=True)
def __init__(self, base_ring, n, names, order): from sage.rings.polynomial.polynomial_singular_interface import can_convert_to_singular order = TermOrder(order, n) MPolynomialRing_generic.__init__(self, base_ring, n, names, order) # Construct the generators v = [0 for _ in xrange(n)] one = base_ring(1) self._gens = [] C = self._poly_class() for i in xrange(n): v[i] = 1 # int's! self._gens.append(C(self, {tuple(v): one})) v[i] = 0 self._gens = tuple(self._gens) self._zero_tuple = tuple(v) self._has_singular = can_convert_to_singular(self) # This polynomial ring should belong to Algebras(base_ring). # Algebras(...).parent_class, which was called from MPolynomialRing_generic.__init__, # tries to provide a conversion from the base ring, if it does not exist. # This is for algebras that only do the generic stuff in their initialisation. # But here, we want to use PolynomialBaseringInjection. Hence, we need to # wipe the memory and construct the conversion from scratch. if n: from sage.rings.polynomial.polynomial_element import PolynomialBaseringInjection base_inject = PolynomialBaseringInjection(base_ring, self) self.register_coercion(base_inject)
def _multi_variate(base_ring, names, n, sparse, order, implementation): # if not sparse: # raise ValueError, "A dense representation of multivariate polynomials is not supported" sparse = False # "True" would be correct, since there is no dense implementation of # multivariate polynomials. However, traditionally, "False" is used in the key, # even though it is meaningless. if implementation is not None: raise ValueError( "The %s implementation is not known for multivariate polynomial rings" % implementation) names = normalize_names(n, names) n = len(names) import sage.rings.polynomial.multi_polynomial_ring as m from sage.rings.polynomial.term_order import TermOrder order = TermOrder(order, n) key = (base_ring, names, n, sparse, order) R = _get_from_cache(key) if not R is None: return R from sage.rings.polynomial.multi_polynomial_libsingular import MPolynomialRing_libsingular if isinstance(base_ring, ring.IntegralDomain): if n < 1: R = m.MPolynomialRing_polydict_domain(base_ring, n, names, order) else: try: R = MPolynomialRing_libsingular(base_ring, n, names, order) except (TypeError, NotImplementedError): R = m.MPolynomialRing_polydict_domain(base_ring, n, names, order) else: if not base_ring.is_zero(): try: R = MPolynomialRing_libsingular(base_ring, n, names, order) except (TypeError, NotImplementedError): R = m.MPolynomialRing_polydict(base_ring, n, names, order) else: R = m.MPolynomialRing_polydict(base_ring, n, names, order) _save_in_cache(key, R) return R
def polynomial_ring(self, names, gens=None): r""" Return a polynomial ring of which ``self`` is a quotient. INPUT: - ``names`` -- a list or tuple of names (strings), or a comma separated string - ``gens`` (default: None) -- (list) a list of generator of ``self``. If ``gens`` is ``None`` then the generators returned by :meth:`~sage.modular.modform.find_generator.ModularFormsRing.gen_forms` is used instead. OUTPUT: A multivariate polynomial ring in the variable ``names``. Each variable of the polynomial ring correspond to a generator given in gens (following the ordering of the list). EXAMPLES:: sage: M = ModularFormsRing(1) sage: gens = M.gen_forms() sage: M.polynomial_ring('E4, E6', gens) Multivariate Polynomial Ring in E4, E6 over Rational Field sage: M = ModularFormsRing(Gamma0(8)) sage: gens = M.gen_forms() sage: M.polynomial_ring('g', gens) Multivariate Polynomial Ring in g0, g1, g2 over Rational Field The degrees of the variables are the weights of the corresponding forms:: sage: M = ModularFormsRing(1) sage: P.<E4, E6> = M.polynomial_ring() sage: E4.degree() 4 sage: E6.degree() 6 sage: (E4*E6).degree() 10 """ if gens is None: gens = self.gen_forms() degs = [f.weight() for f in gens] return PolynomialRing( self.base_ring(), len(gens), names, order=TermOrder( 'wdeglex', degs)) # Should we remove the deg lexicographic ordering here?
def __classcall__(cls, base_ring, num_gens, name_list, order='negdeglex', default_prec=10, sparse=False): """ Preprocessing of arguments: The term order can be given as string or as a :class:`~sage.rings.polynomial.term_order.TermOrder` instance. TESTS:: sage: P1 = PowerSeriesRing(QQ, ['f0','f1','f2','f3'], order = TermOrder('degrevlex')) sage: P2 = PowerSeriesRing(QQ,4,'f', order='degrevlex') sage: P1 is P2 # indirect doctest True """ order = TermOrder(order,num_gens) return super(MPowerSeriesRing_generic,cls).__classcall__(cls, base_ring, num_gens, name_list, order, default_prec, sparse)
def _multi_variate(base_ring, names, sparse=None, order="degrevlex", implementation=None): # if not sparse: # raise ValueError("a dense representation of multivariate polynomials is not supported") sparse = False if implementation is None: force_singular = False elif implementation == "singular": force_singular = True else: raise ValueError( "unknown implementation %r for multivariate polynomial rings" % (implementation, )) n = len(names) from sage.rings.polynomial.term_order import TermOrder order = TermOrder(order, n) key = (base_ring, names, n, sparse, order) R = _get_from_cache(key) if not R is None: return R from sage.rings.polynomial.multi_polynomial_libsingular import MPolynomialRing_libsingular try: R = MPolynomialRing_libsingular(base_ring, n, names, order) except (TypeError, NotImplementedError): if force_singular: raise import sage.rings.polynomial.multi_polynomial_ring as m if isinstance(base_ring, ring.IntegralDomain): R = m.MPolynomialRing_polydict_domain(base_ring, n, names, order) else: R = m.MPolynomialRing_polydict(base_ring, n, names, order) _save_in_cache(key, R) return R
def __init__(self, base_ring, n, names, order): from sage.rings.polynomial.polynomial_singular_interface import can_convert_to_singular order = TermOrder(order, n) # MPolynomialRing_base.__init__() normally initialises the base ring, # but it also needs the generators to construct a coercion map from the # base ring, and the base ring must be set to initialise the generators. # We set the base ring manually to break this circular dependency. self._base = base_ring # Construct the generators v = [0] * n one = base_ring.one() self._gens = [] for i in range(n): v[i] = 1 # int's! self._gens.append(self.Element_hidden(self, {tuple(v): one})) v[i] = 0 self._gens = tuple(self._gens) self._zero_tuple = tuple(v) MPolynomialRing_base.__init__(self, base_ring, n, names, order) self._has_singular = can_convert_to_singular(self)
def polynomial_ring(self, names='E2, E4, E6'): r""" Return a multivariate polynomial ring isomorphic to the given graded quasimodular forms ring. In the case of the full modular group, this ring is `R[E_2, E_4, E_6]` where `E_2`, `E_4` and `E_6` have degrees 2, 4 and 6 respectively. INPUT: - ``names`` (str, default: ``'E2, E4, E6'``) -- a list or tuple of names (strings), or a comma separated string. Correspond to the names of the variables. OUTPUT: A multivariate polynomial ring in the variables ``names`` EXAMPLES: sage: QM = QuasiModularForms(1) sage: P.<E2, E4, E6> = QM.polynomial_ring(); P Multivariate Polynomial Ring in E2, E4, E6 over Rational Field sage: E2.degree() 2 sage: E4.degree() 4 sage: E6.degree() 6 sage: P.<x, y, z, w> = QQ[] sage: QM.from_polynomial(x+y+z+w) Traceback (most recent call last): ... ValueError: the number of variables (4) of the given polynomial cannot exceed the number of generators (3) of the quasimodular forms ring """ return PolynomialRing( self.base_ring(), 3, names, order=TermOrder('wdeglex', [ZZ(2), ZZ(4), ZZ(6)]))
def __init__(self, base_ring, num_gens, name_list, order='negdeglex', default_prec=10, sparse=False): """ Initializes a multivariate power series ring. See PowerSeriesRing for complete documentation. INPUT - ``base_ring`` - a commutative ring - ``num_gens`` - number of generators - ``name_list`` - List of indeterminate names or a single name. If a single name is given, indeterminates will be this name followed by a number from 0 to num_gens - 1. If a list is given, these will be the indeterminate names and the length of the list must be equal to num_gens. - ``order`` - ordering of variables; default is negative degree lexicographic - ``default_prec`` - The default total-degree precision for elements. The default value of default_prec is 10. - ``sparse`` - whether or not power series are sparse EXAMPLES:: sage: R.<t,u,v> = PowerSeriesRing(QQ) sage: g = 1 + v + 3*u*t^2 - 2*v^2*t^2 sage: g = g.add_bigoh(5); g 1 + v + 3*t^2*u - 2*t^2*v^2 + O(t, u, v)^5 sage: g in R True TESTS: By :trac:`14084`, the multi-variate power series ring belongs to the category of integral domains, if the base ring does:: sage: P = ZZ[['x','y']] sage: P.category() Category of integral domains sage: TestSuite(P).run() Otherwise, it belongs to the category of commutative rings:: sage: P = Integers(15)[['x','y']] sage: P.category() Category of commutative rings sage: TestSuite(P).run() """ order = TermOrder(order, num_gens) self._term_order = order if not base_ring.is_commutative(): raise TypeError("Base ring must be a commutative ring.") n = int(num_gens) if n < 0: raise ValueError( "Multivariate Polynomial Rings must have more than 0 variables." ) self._ngens = n self._has_singular = False #cannot convert to Singular by default # Multivariate power series rings inherit from power series rings. But # apparently we can not call their initialisation. Instead, initialise # CommutativeRing and Nonexact: CommutativeRing.__init__(self, base_ring, name_list, category=_IntegralDomains if base_ring in _IntegralDomains else _CommutativeRings) Nonexact.__init__(self, default_prec) # underlying polynomial ring in which to represent elements self._poly_ring_ = PolynomialRing(base_ring, self.variable_names(), sparse=sparse, order=order) # because sometimes PowerSeriesRing_generic calls self.__poly_ring self._PowerSeriesRing_generic__poly_ring = self._poly_ring() # background univariate power series ring self._bg_power_series_ring = PowerSeriesRing(self._poly_ring_, 'Tbg', sparse=sparse, default_prec=default_prec) self._bg_indeterminate = self._bg_power_series_ring.gen() self._is_sparse = sparse self._params = (base_ring, num_gens, name_list, order, default_prec, sparse) self._populate_coercion_lists_()
def BooleanPolynomialRing_constructor(n=None, names=None, order="lex"): """ Construct a boolean polynomial ring with the following parameters: INPUT: - ``n`` -- number of variables (an integer > 1) - ``names`` -- names of ring variables, may be a string or list/tuple of strings - ``order`` -- term order (default: lex) EXAMPLES:: sage: R.<x, y, z> = BooleanPolynomialRing() # indirect doctest sage: R Boolean PolynomialRing in x, y, z sage: p = x*y + x*z + y*z sage: x*p x*y*z + x*y + x*z sage: R.term_order() Lexicographic term order sage: R = BooleanPolynomialRing(5,'x',order='deglex(3),deglex(2)') sage: R.term_order() Block term order with blocks: (Degree lexicographic term order of length 3, Degree lexicographic term order of length 2) sage: R = BooleanPolynomialRing(3,'x',order='degneglex') sage: R.term_order() Degree negative lexicographic term order sage: BooleanPolynomialRing(names=('x','y')) Boolean PolynomialRing in x, y sage: BooleanPolynomialRing(names='x,y') Boolean PolynomialRing in x, y TESTS:: sage: P.<x,y> = BooleanPolynomialRing(2,order='deglex') sage: x > y True sage: P.<x0, x1, x2, x3> = BooleanPolynomialRing(4,order='deglex(2),deglex(2)') sage: x0 > x1 True sage: x2 > x3 True """ if isinstance(n, str): names = n n = -1 elif n is None: n = -1 names = normalize_names(n, names) n = len(names) from sage.rings.polynomial.term_order import TermOrder order = TermOrder(order, n) key = ("pbori", names, n, order) R = _get_from_cache(key) if not R is None: return R from sage.rings.polynomial.pbori import BooleanPolynomialRing R = BooleanPolynomialRing(n, names, order) _save_in_cache(key, R) return R
def create_key(self, base, prec=None, log_radii=ZZ(0), names=None, order='degrevlex'): """ Create a key from the input paramaters. INPUT: - ``base`` -- a `p`-adic ring or field - ``prec`` -- an integer or ``None`` (default: ``None``) - ``log_radii`` -- an integer or a list or a tuple of integers (default: ``0``) - ``names`` -- names of the indeterminates - ``order`` - a monomial ordering (default: ``degrevlex``) EXAMPLES:: sage: TateAlgebra.create_key(Zp(2), names=['x','y']) (2-adic Field with capped relative precision 20, 20, (0, 0), ('x', 'y'), Degree reverse lexicographic term order) TESTS:: sage: TateAlgebra.create_key(Zp(2)) Traceback (most recent call last): ... ValueError: you must specify the names of the variables sage: TateAlgebra.create_key(ZZ) Traceback (most recent call last): ... TypeError: the base ring must be a p-adic ring or a p-adic field sage: TateAlgebra.create_key(Zp(2), names=['x','y'], log_radii=[1]) Traceback (most recent call last): ... ValueError: the number of radii does not match the number of variables sage: TateAlgebra.create_key(Zp(2), names=['x','y'], log_radii=[0, 1/2]) Traceback (most recent call last): ... NotImplementedError: only integral log_radii are implemented sage: TateAlgebra.create_key(Zp(2), names=['x','y'], order='myorder') Traceback (most recent call last): ... ValueError: unknown term order 'myorder' """ if not isinstance(base, pAdicGeneric): raise TypeError( "the base ring must be a p-adic ring or a p-adic field") # TODO: allow for arbitrary CDVF base = base.fraction_field() if names is None: raise ValueError("you must specify the names of the variables") names = normalize_names(-1, names) ngens = len(names) if not isinstance(log_radii, (list, tuple)): try: log_radii = [ZZ(log_radii)] * ngens except TypeError: raise NotImplementedError( "only integral log_radii are implemented") elif len(log_radii) != ngens: raise ValueError( "the number of radii does not match the number of variables") else: try: log_radii = [ZZ(r) for r in log_radii] except TypeError: raise NotImplementedError( "only integral log_radii are implemented") order = TermOrder(order, ngens) if prec is None: prec = base.precision_cap() key = (base, prec, tuple(log_radii), names, order) return key
def _multi_variate(base_ring, names, sparse=None, order="degrevlex", implementation=None): if sparse is None: sparse = True if not sparse: raise NotImplementedError( "a dense representation of multivariate polynomials is not supported" ) from sage.rings.polynomial.term_order import TermOrder n = len(names) order = TermOrder(order, n) # "implementation" must be last key = [base_ring, names, n, order, implementation] R = _get_from_cache(key) if R is not None: return R # Multiple arguments for the "implementation" keyword which actually # yield the same implementation. We need this for caching. implementation_names = set([implementation]) if implementation is None or implementation == "singular": from sage.rings.polynomial.multi_polynomial_libsingular import MPolynomialRing_libsingular try: R = MPolynomialRing_libsingular(base_ring, n, names, order) except (TypeError, NotImplementedError): if implementation is not None: raise else: implementation_names.update([None, "singular"]) if R is None and implementation is None: # Interpret implementation=None as implementation="generic" implementation = "generic" implementation_names.add(implementation) key[-1] = implementation R = _get_from_cache(key) if R is None and implementation == "generic": from . import multi_polynomial_ring if isinstance(base_ring, ring.IntegralDomain): constructor = multi_polynomial_ring.MPolynomialRing_polydict_domain else: constructor = multi_polynomial_ring.MPolynomialRing_polydict R = constructor(base_ring, n, names, order) if R is None: raise ValueError( "unknown implementation %r for multivariate polynomial rings" % (implementation, )) for impl in implementation_names: key[-1] = impl _save_in_cache(key, R) return R
def __init__(self, base_ring, n, names, order): order = TermOrder(order, n) MPolynomialRing_polydict.__init__(self, base_ring, n, names, order)
def __init__(self, base_ring, num_gens, name_list, order='negdeglex', default_prec=10, sparse=False): """ Initializes a multivariate power series ring. See PowerSeriesRing for complete documentation. INPUT - ``base_ring`` - a commutative ring - ``num_gens`` - number of generators - ``name_list`` - List of indeterminate names or a single name. If a single name is given, indeterminates will be this name followed by a number from 0 to num_gens - 1. If a list is given, these will be the indeterminate names and the length of the list must be equal to num_gens. - ``order`` - ordering of variables; default is negative degree lexicographic - ``default_prec`` - The default total-degree precision for elements. The default value of default_prec is 10. - ``sparse`` - whether or not power series are sparse EXAMPLES:: sage: R.<t,u,v> = PowerSeriesRing(QQ) sage: g = 1 + v + 3*u*t^2 - 2*v^2*t^2 sage: g = g.add_bigoh(5); g 1 + v + 3*t^2*u - 2*t^2*v^2 + O(t, u, v)^5 sage: g in R True """ order = TermOrder(order, num_gens) self._term_order = order if not base_ring.is_commutative(): raise TypeError("Base ring must be a commutative ring.") n = int(num_gens) if n < 0: raise ValueError( "Multivariate Polynomial Rings must have more than 0 variables." ) self._ngens = n self._has_singular = False #cannot convert to Singular by default ParentWithGens.__init__(self, base_ring, name_list) Nonexact.__init__(self, default_prec) # underlying polynomial ring in which to represent elements self._poly_ring_ = PolynomialRing(base_ring, self.variable_names(), sparse=sparse, order=order) # because sometimes PowerSeriesRing_generic calls self.__poly_ring self._PowerSeriesRing_generic__poly_ring = self._poly_ring() # background univariate power series ring self._bg_power_series_ring = PowerSeriesRing(self._poly_ring_, 'Tbg', sparse=sparse, default_prec=default_prec) self._bg_indeterminate = self._bg_power_series_ring.gen() ## use the following in PowerSeriesRing_generic.__call__ self._PowerSeriesRing_generic__power_series_class = MPowerSeries self._is_sparse = sparse self._params = (base_ring, num_gens, name_list, order, default_prec, sparse) self._populate_coercion_lists_()