Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
r""" Multivariate Polynomials via libSINGULAR
This module implements specialized and optimized implementations for multivariate polynomials over many coefficient rings, via a shared library interface to SINGULAR. In particular, the following coefficient rings are supported by this implementation:
- the rational numbers `\QQ`,
- the ring of integers `\ZZ`,
- `\ZZ/n\ZZ` for any integer `n`,
- finite fields `\GF{p^n}` for `p` prime and `n > 0`,
- and absolute number fields `\QQ(a)`.
AUTHORS:
The libSINGULAR interface was implemented by
- Martin Albrecht (2007-01): initial implementation
- Joel Mohler (2008-01): misc improvements, polishing
- Martin Albrecht (2008-08): added `\QQ(a)` and `\ZZ` support
- Simon King (2009-04): improved coercion
- Martin Albrecht (2009-05): added `\ZZ/n\ZZ` support, refactoring
- Martin Albrecht (2009-06): refactored the code to allow better re-use
- Simon King (2011-03): Use a faster way of conversion from the base ring.
- Volker Braun (2011-06): Major cleanup, refcount singular rings, bugfixes.
.. TODO::
Implement Real, Complex coefficient rings via libSINGULAR
EXAMPLES:
We show how to construct various multivariate polynomial rings::
sage: P.<x,y,z> = QQ[] sage: P Multivariate Polynomial Ring in x, y, z over Rational Field
sage: f = 27/113 * x^2 + y*z + 1/2; f 27/113*x^2 + y*z + 1/2
sage: P.term_order() Degree reverse lexicographic term order
sage: P = PolynomialRing(GF(127),3,names='abc', order='lex') sage: P Multivariate Polynomial Ring in a, b, c over Finite Field of size 127
sage: a,b,c = P.gens() sage: f = 57 * a^2*b + 43 * c + 1; f 57*a^2*b + 43*c + 1
sage: P.term_order() Lexicographic term order
sage: z = QQ['z'].0 sage: K.<s> = NumberField(z^2 - 2) sage: P.<x,y> = PolynomialRing(K, 2) sage: 1/2*s*x^2 + 3/4*s (1/2*s)*x^2 + (3/4*s)
sage: P.<x,y,z> = ZZ[]; P Multivariate Polynomial Ring in x, y, z over Integer Ring
sage: P.<x,y,z> = Zmod(2^10)[]; P Multivariate Polynomial Ring in x, y, z over Ring of integers modulo 1024
sage: P.<x,y,z> = Zmod(3^10)[]; P Multivariate Polynomial Ring in x, y, z over Ring of integers modulo 59049
sage: P.<x,y,z> = Zmod(2^100)[]; P Multivariate Polynomial Ring in x, y, z over Ring of integers modulo 1267650600228229401496703205376
sage: P.<x,y,z> = Zmod(2521352)[]; P Multivariate Polynomial Ring in x, y, z over Ring of integers modulo 2521352 sage: type(P) <type 'sage.rings.polynomial.multi_polynomial_libsingular.MPolynomialRing_libsingular'>
sage: P.<x,y,z> = Zmod(25213521351515232)[]; P Multivariate Polynomial Ring in x, y, z over Ring of integers modulo 25213521351515232 sage: type(P) <class 'sage.rings.polynomial.multi_polynomial_ring.MPolynomialRing_polydict_with_category'>
We construct the Frobenius morphism on `\GF{5}[x,y,z]` over `\GF{5}`::
sage: R.<x,y,z> = PolynomialRing(GF(5), 3) sage: frob = R.hom([x^5, y^5, z^5]) sage: frob(x^2 + 2*y - z^4) -z^20 + x^10 + 2*y^5 sage: frob((x + 2*y)^3) x^15 + x^10*y^5 + 2*x^5*y^10 - 2*y^15 sage: (x^5 + 2*y^5)^3 x^15 + x^10*y^5 + 2*x^5*y^10 - 2*y^15
We make a polynomial ring in one variable over a polynomial ring in two variables::
sage: R.<x, y> = PolynomialRing(QQ, 2) sage: S.<t> = PowerSeriesRing(R) sage: t*(x+y) (x + y)*t
TESTS::
sage: P.<x,y,z> = QQ[] sage: loads(dumps(P)) == P True sage: loads(dumps(x)) == x True sage: P.<x,y,z> = GF(2^8,'a')[] sage: loads(dumps(P)) == P True sage: loads(dumps(x)) == x True sage: P.<x,y,z> = GF(127)[] sage: loads(dumps(P)) == P True sage: loads(dumps(x)) == x True sage: P.<x,y,z> = GF(127)[] sage: loads(dumps(P)) == P True sage: loads(dumps(x)) == x True
sage: Rt.<t> = PolynomialRing(QQ, implementation="singular") sage: p = 1+t sage: R.<u,v> = PolynomialRing(QQ, 2) sage: p(u/v) (u + v)/v
Check if :trac:`6160` is fixed::
sage: x=var('x') sage: K.<j> = NumberField(x-1728) sage: R.<b,c> = K[] sage: b-j*c b - 1728*c """
#***************************************************************************** # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # http://www.gnu.org/licenses/ #*****************************************************************************
from __future__ import absolute_import, print_function
# The Singular API is as follows: # # pXXX does assume the currRing to be set # p_XXX does not. # # However, sometimes there are bugs, i.e. you call p_XXX and it # crashes unless currRing is set. # # Notable exceptions: # * pNext and pIter don't need currRing # * p_Normalize apparently needs currRing
from cpython.object cimport Py_NE from cysignals.memory cimport sig_malloc, sig_free from cysignals.signals cimport sig_on, sig_off
from sage.cpython.string cimport char_to_str, str_to_bytes
# singular types from sage.libs.singular.decl cimport ring, poly, ideal, intvec, number, currRing from sage.libs.singular.decl cimport n_unknown, n_Zp, n_Q, n_R, n_GF, n_long_R, n_algExt,n_transExt,n_long_C, n_Z, n_Zn, n_Znm, n_Z2m, n_CF
# singular functions from sage.libs.singular.decl cimport ( errorreported, n_IsUnit, n_Invers, p_ISet, rChangeCurrRing, p_Copy, p_Init, p_SetCoeff, p_Setm, p_SetExp, p_Add_q, p_NSet, p_GetCoeff, p_Delete, p_GetExp, pNext, rRingVar, omAlloc0, omStrDup, omFree, pDivide, p_SetCoeff0, n_Init, p_DivisibleBy, pLcm, p_LmDivisibleBy, pDivide, p_IsConstant, p_ExpVectorEqual, p_String, p_LmInit, n_Copy, p_IsUnit, p_Series, p_Head, idInit, fast_map_common_subexp, id_Delete, p_IsHomogeneous, p_Homogen, p_Totaldegree,pLDeg1_Totaldegree, singclap_pdivide, singclap_factorize, idLift, IDELEMS, On, Off, SW_USE_CHINREM_GCD, SW_USE_EZGCD, p_LmIsConstant, pTakeOutComp1, singclap_gcd, pp_Mult_qq, p_GetMaxExp, pLength, kNF, p_Neg, p_Minus_mm_Mult_qq, p_Plus_mm_Mult_qq, pDiff, singclap_resultant, p_Normalize, prCopyR, prCopyR_NoSort )
# singular conversion routines from sage.libs.singular.singular cimport si2sa, sa2si, overflow_check
# singular poly arith from sage.libs.singular.polynomial cimport ( singular_polynomial_call, singular_polynomial_cmp, singular_polynomial_add, singular_polynomial_sub, singular_polynomial_neg, singular_polynomial_rmul, singular_polynomial_mul, singular_polynomial_div_coeff, singular_polynomial_pow, singular_polynomial_str, singular_polynomial_latex, singular_polynomial_str_with_changed_varnames, singular_polynomial_deg, singular_polynomial_length_bounded, singular_polynomial_subst )
# singular rings from sage.libs.singular.ring cimport singular_ring_new, singular_ring_reference, singular_ring_delete
# polynomial imports from sage.rings.polynomial.multi_polynomial_ring import MPolynomialRing_polydict, MPolynomialRing_polydict_domain from sage.rings.polynomial.multi_polynomial_element import MPolynomial_polydict from sage.rings.polynomial.multi_polynomial_ideal import MPolynomialIdeal from sage.rings.polynomial.polydict import ETuple from sage.rings.polynomial.polynomial_ring import is_PolynomialRing
# base ring imports from sage.rings.finite_rings.finite_field_prime_modn import FiniteField_prime_modn from sage.rings.rational cimport Rational from sage.rings.rational_field import RationalField from sage.rings.complex_field import is_ComplexField from sage.rings.real_mpfr import is_RealField from sage.rings.integer_ring import is_IntegerRing, ZZ from sage.rings.integer cimport Integer from sage.rings.integer import GCD_list from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing from sage.rings.number_field.number_field_base cimport NumberField
from sage.structure.element import coerce_binop
from sage.structure.parent cimport Parent from sage.structure.parent_base cimport ParentWithBase from sage.structure.parent_gens cimport ParentWithGens from sage.structure.category_object cimport CategoryObject
from sage.structure.element cimport EuclideanDomainElement from sage.structure.element cimport RingElement from sage.structure.element cimport ModuleElement from sage.structure.element cimport Element from sage.structure.element cimport CommutativeRingElement from sage.structure.element cimport coercion_model
from sage.structure.richcmp cimport rich_to_bool, richcmp from sage.structure.factorization import Factorization from sage.structure.sequence import Sequence
from sage.interfaces.all import macaulay2 from sage.interfaces.singular import singular as singular_default, is_SingularElement, SingularElement from sage.interfaces.macaulay2 import macaulay2 as macaulay2_default, is_Macaulay2Element
from sage.misc.all import prod as mul from sage.misc.sage_eval import sage_eval
cimport cypari2.gen from . import polynomial_element
permstore=[] cdef class MPolynomialRing_libsingular(MPolynomialRing_generic):
def __cinit__(self): """ The Cython constructor.
EXAMPLES::
sage: from sage.rings.polynomial.multi_polynomial_libsingular import MPolynomialRing_libsingular sage: MPolynomialRing_libsingular(QQ, 3, ('x', 'y', 'z'), TermOrder('degrevlex', 3)) Multivariate Polynomial Ring in x, y, z over Rational Field sage: type(_) <type 'sage.rings.polynomial.multi_polynomial_libsingular.MPolynomialRing_libsingular'>
sage: P.<x,y,z> = QQ[]; P Multivariate Polynomial Ring in x, y, z over Rational Field sage: type(P) <type 'sage.rings.polynomial.multi_polynomial_libsingular.MPolynomialRing_libsingular'> """
def __init__(self, base_ring, n, names, order='degrevlex'): """ Construct a multivariate polynomial ring subject to the following conditions:
INPUT:
- ``base_ring`` - base ring (must be either GF(q), ZZ, ZZ/nZZ, QQ or absolute number field)
- ``n`` - number of variables (must be at least 1)
- ``names`` - names of ring variables, may be string of list/tuple
- ``order`` - term order (default: ``degrevlex``)
EXAMPLES::
sage: P.<x,y,z> = QQ[] sage: P Multivariate Polynomial Ring in x, y, z over Rational Field
sage: f = 27/113 * x^2 + y*z + 1/2; f 27/113*x^2 + y*z + 1/2
sage: P.term_order() Degree reverse lexicographic term order
sage: P = PolynomialRing(GF(127),3,names='abc', order='lex') sage: P Multivariate Polynomial Ring in a, b, c over Finite Field of size 127
sage: a,b,c = P.gens() sage: f = 57 * a^2*b + 43 * c + 1; f 57*a^2*b + 43*c + 1
sage: P.term_order() Lexicographic term order
sage: z = QQ['z'].0 sage: K.<s> = NumberField(z^2 - 2) sage: P.<x,y> = PolynomialRing(K, 2) sage: 1/2*s*x^2 + 3/4*s (1/2*s)*x^2 + (3/4*s)
sage: P.<x,y,z> = ZZ[]; P Multivariate Polynomial Ring in x, y, z over Integer Ring
sage: P.<x,y,z> = Zmod(2^10)[]; P Multivariate Polynomial Ring in x, y, z over Ring of integers modulo 1024
sage: P.<x,y,z> = Zmod(3^10)[]; P Multivariate Polynomial Ring in x, y, z over Ring of integers modulo 59049
sage: P.<x,y,z> = Zmod(2^100)[]; P Multivariate Polynomial Ring in x, y, z over Ring of integers modulo 1267650600228229401496703205376
sage: P.<x,y,z> = Zmod(2521352)[]; P Multivariate Polynomial Ring in x, y, z over Ring of integers modulo 2521352 sage: type(P) <type 'sage.rings.polynomial.multi_polynomial_libsingular.MPolynomialRing_libsingular'>
sage: P.<x,y,z> = Zmod(25213521351515232)[]; P Multivariate Polynomial Ring in x, y, z over Ring of integers modulo 25213521351515232 sage: type(P) <class 'sage.rings.polynomial.multi_polynomial_ring.MPolynomialRing_polydict_with_category'>
sage: P.<x,y,z> = PolynomialRing(Integers(2^32),order='lex') sage: P(2^32-1) 4294967295
TESTS:
Make sure that a faster coercion map from the base ring is used; see :trac:`9944`::
sage: R.<x,y> = PolynomialRing(ZZ) sage: R.coerce_map_from(R.base_ring()) Polynomial base injection morphism: From: Integer Ring To: Multivariate Polynomial Ring in x, y over Integer Ring
Check some invalid input::
sage: from sage.rings.polynomial.multi_polynomial_libsingular import MPolynomialRing_libsingular sage: MPolynomialRing_libsingular(Zmod(1), 1, ["x"], "lex") Traceback (most recent call last): ... NotImplementedError: polynomials over Ring of integers modulo 1 are not supported in Singular sage: MPolynomialRing_libsingular(SR, 1, ["x"], "lex") Traceback (most recent call last): ... NotImplementedError: polynomials over Symbolic Ring are not supported in Singular sage: MPolynomialRing_libsingular(QQ, 0, [], "lex") Traceback (most recent call last): ... NotImplementedError: polynomials in 0 variables are not supported in Singular sage: MPolynomialRing_libsingular(QQ, -1, [], "lex") Traceback (most recent call last): ... ValueError: Multivariate Polynomial Rings must have more than 0 variables. """ # 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. #permanently store a reference to this ring until deallocation works reliably
def __dealloc__(self): r""" Deallocate the ring without changing ``currRing``
TESTS:
This example caused a segmentation fault with a previous version of this method::
sage: import gc sage: from sage.rings.polynomial.multi_polynomial_libsingular import MPolynomialRing_libsingular sage: R1 = MPolynomialRing_libsingular(GF(5), 2, ('x', 'y'), TermOrder('degrevlex', 2)) sage: R2 = MPolynomialRing_libsingular(GF(11), 2, ('x', 'y'), TermOrder('degrevlex', 2)) sage: R3 = MPolynomialRing_libsingular(GF(13), 2, ('x', 'y'), TermOrder('degrevlex', 2)) sage: _ = gc.collect() sage: foo = R1.gen(0) sage: del foo sage: del R1 sage: _ = gc.collect() sage: del R2 sage: _ = gc.collect() sage: del R3 sage: _ = gc.collect() """
def __copy__(self): """ Copy ``self``.
The ring is unique and immutable, so we do not copy.
TESTS::
sage: import gc sage: from sage.rings.polynomial.multi_polynomial_libsingular import MPolynomialRing_libsingular sage: from sage.libs.singular.ring import ring_refcount_dict sage: gc.collect() # random output sage: n = len(ring_refcount_dict) sage: R = MPolynomialRing_libsingular(GF(547), 2, ('x', 'y'), TermOrder('degrevlex', 2)) sage: len(ring_refcount_dict) == n + 1 True
sage: Q = copy(R) # indirect doctest sage: p = R.gen(0) ^2+R.gen(1)^2 sage: q = copy(p) sage: del R sage: del Q sage: del p sage: del q sage: gc.collect() # random output sage: len(ring_refcount_dict) == n False """
def __deepcopy__(self, memo): """ Deep copy ``self``.
The ring should be immutable, so we do not copy.
TESTS::
sage: R.<x,y> = GF(547)[] sage: R is deepcopy(R) # indirect doctest True """
cpdef _coerce_map_from_(self, other): """ Return True if and only if there exists a coercion map from ``other`` to ``self``.
TESTS::
sage: R.<x,y> = QQ[] sage: type(R) <type 'sage.rings.polynomial.multi_polynomial_libsingular.MPolynomialRing_libsingular'> sage: R.has_coerce_map_from(ZZ['t']) False sage: R.coerce_map_from(ZZ['x']) Coercion map: From: Univariate Polynomial Ring in x over Integer Ring To: Multivariate Polynomial Ring in x, y over Rational Field
"""
return True self.variable_names()[:n] == other.variable_names()): return True return True
Element = MPolynomial_libsingular
def _element_constructor_(self, element): """ Construct a new element in this polynomial ring by converting ``element`` into ``self`` if possible.
INPUT:
- ``element`` -- several types are supported, see below
EXAMPLES::
sage: P.<x,y,z> = QQ[]
We can coerce elements of self to self::
sage: P._coerce_(x*y + 1/2) x*y + 1/2
We can coerce elements for a ring with the same algebraic properties::
sage: from sage.rings.polynomial.multi_polynomial_libsingular import MPolynomialRing_libsingular sage: R.<x,y,z> = MPolynomialRing_libsingular(QQ,3) sage: P == R True
sage: P is R False
sage: P._coerce_(x*y + 1) x*y + 1
We can coerce base ring elements::
sage: P._coerce_(3/2) 3/2
and all kinds of integers::
sage: P._coerce_(ZZ(1)) 1
sage: P._coerce_(int(1)) 1
sage: k.<a> = GF(2^8) sage: P.<x,y> = PolynomialRing(k,2) sage: P._coerce_(a) (a)
sage: z = QQ['z'].0 sage: K.<s> = NumberField(z^2 - 2) sage: P.<x,y> = PolynomialRing(K, 2) sage: P._coerce_(1/2*s) (1/2*s)
TESTS::
sage: P.<x,y> = PolynomialRing(GF(127)) sage: P("111111111111111111111111111111111111111111111111111111111") 21 sage: P.<x,y> = PolynomialRing(QQ) sage: P("111111111111111111111111111111111111111111111111111111111") 111111111111111111111111111111111111111111111111111111111 sage: P("31367566080") 31367566080
Check if :trac:`7582` is fixed::
sage: R.<x,y,z> = PolynomialRing(CyclotomicField(2),3) sage: R.coerce(1) 1
Check if :trac:`6160` is fixed::
sage: x=var('x') sage: K.<j> = NumberField(x-1728) sage: R.<b,c> = K[] sage: R.coerce(1) 1
Check if coercion from zero variable polynomial rings work (:trac:`7951`)::
sage: P = PolynomialRing(QQ,0,'') sage: R.<x,y> = QQ[] sage: P(5)*x 5*x sage: P = PolynomialRing(ZZ,0,'') sage: R.<x,y> = GF(127)[] sage: R.coerce(P(5)) 5
Conversion from strings::
sage: P.<x,y,z> = QQ[] sage: P('x+y + 1/4') x + y + 1/4
Coercion from SINGULAR elements::
sage: P._singular_() polynomial ring, over a field, global ordering // coefficients: QQ // number of vars : 3 // block 1 : ordering dp // : names x y z // block 2 : ordering C
sage: P._singular_().set_ring() sage: P(singular('x + 3/4')) x + 3/4
Coercion from symbolic variables::
sage: R = QQ['x,y,z'] sage: var('x') x sage: R(x) x
Coercion from 'similar' rings, which maps by index::
sage: P.<x,y,z> = QQ[] sage: R.<a,b,c> = ZZ[] sage: P(a) x
::
sage: P.<x,y> = QQ[] sage: R.<a,b,c> = QQ[] sage: R(x) a
Coercion from PARI objects::
sage: P.<x,y,z> = QQ[] sage: P(pari('x^2 + y')) x^2 + y sage: P(pari('x*y')) x*y
Coercion from boolean polynomials, also by index::
sage: B.<x,y,z> = BooleanPolynomialRing(3) sage: P.<x,y,z> = QQ[] sage: P(B.gen(0)) x
If everything else fails, we try to coerce to the base ring::
sage: R.<x,y,z> = GF(3)[] sage: R(1/2) -1
Finally, conversions from other polynomial rings which are not coercions are provided. Variables are mapped as follows. Say, we are mapping an element from `P` to `Q` (this ring). If the variables of `P` are a subset of `Q`, we perform a name preserving conversion::
sage: P.<y_2, y_1, z_3, z_2, z_1> = GF(3)[] sage: Q = GF(3)['y_4', 'y_3', 'y_2', 'y_1', 'z_5', 'z_4', 'z_3', 'z_2', 'z_1'] sage: Q(y_1*z_2^2*z_1) y_1*z_2^2*z_1
Otherwise, if `P` has less than or equal the number of variables as `Q`, we perform a conversion by index::
sage: P.<a,b,c> = GF(2)[] sage: Q = GF(2)['c','b','d','e'] sage: f = Q.convert_map_from(P) sage: f(a), f(b), f(c) (c, b, d)
::
sage: P.<a,b,c> = GF(2)[] sage: Q = GF(2)['c','b','d'] sage: f = Q.convert_map_from(P) sage: f(a),f(b),f(c) (c, b, d)
In all other cases, we fail::
sage: P.<a,b,c,f> = GF(2)[] sage: Q = GF(2)['c','d','e'] sage: f = Q.convert_map_from(P) sage: f(a) Traceback (most recent call last): ... TypeError: Could not find a mapping of the passed element to this ring.
Coerce in a polydict where a coefficient reduces to 0 but isn't 0. ::
sage: R.<x,y> = QQ[]; S.<xx,yy> = GF(5)[]; S( (5*x*y + x + 17*y)._mpoly_dict_recursive() ) xx + 2*yy
Coerce in a polynomial one of whose coefficients reduces to 0. ::
sage: R.<x,y> = QQ[]; S.<xx,yy> = GF(5)[]; S(5*x*y + x + 17*y) xx + 2*yy
Some other examples that illustrate the same coercion idea::
sage: R.<x,y> = ZZ[] sage: S.<xx,yy> = GF(25,'a')[] sage: S(5*x*y + x + 17*y) xx + 2*yy
sage: S.<xx,yy> = Integers(5)[] sage: S(5*x*y + x + 17*y) xx + 2*yy
See :trac:`5292`::
sage: R.<x> = QQ[]; S.<q,t> = QQ[]; F = FractionField(S); sage: x in S False sage: x in F False
Check if :trac:`8228` is fixed::
sage: P.<x,y> = Zmod(10)[]; P(0) 0 sage: P.<x,y> = Zmod(2^10)[]; P(0) 0
And :trac:`7597` is fixed if this does not segfault::
sage: F2 = GF(2) sage: F.<x> = GF(2^8) sage: R4.<a,b> = PolynomialRing(F) sage: R.<u,v> = PolynomialRing(F2) sage: P = a sage: (P(0,0).polynomial()[0])*u 0 sage: P(a,b) a
Check that :trac:`15746` is fixed::
sage: R.<x,y> = GF(7)[] sage: R(2^31) 2
Check that :trac:`17964` is fixed::
sage: K.<a> = QuadraticField(17) sage: Q.<x,y> = K[] sage: f = (-3*a)*y + (5*a) sage: p = K.primes_above(5)[0] sage: R = K.residue_field(p) sage: S = R['x','y'] sage: S(f) (2*abar)*y
""" cdef poly *_p cdef poly *mon cdef poly *El_poly cdef number *_n cdef ring *El_ring cdef long mpos cdef MPolynomial_libsingular Element cdef MPolynomialRing_libsingular El_parent cdef int i, j cdef int e
return element (<MPolynomial_libsingular>element)._parent_ring, _ring) else:
_p = p_ISet(0, _ring) for (m,c) in element.element().dict().iteritems(): mon = p_Init(_ring) p_SetCoeff(mon, sa2si(c, _ring), _ring) for pos in m.nonzero_positions(): overflow_check(m[pos], _ring) p_SetExp(mon, pos+1, m[pos], _ring) p_Setm(mon, _ring) _p = p_Add_q(_p, mon, _ring) return new_MP(self, _p) # zero variable polynomials
# base ring elements # shortcut for GF(p) if isinstance(base_ring, FiniteField_prime_modn): _p = p_ISet(int(element) % _ring.cf.ch, _ring) else: _n = sa2si(element,_ring) _p = p_NSet(_n, _ring) return new_MP(self, _p) # also accepting ZZ _p = p_ISet(int(element),_ring) else: # fall back to base ring pass
_p = p_ISet(element % _ring.cf.ch, _ring) else:
else:
# Map the variables by indices
else:
# Map variables by indices except TypeError: p_Delete(&_p, _ring) raise
else: return self._zero_element
elif element.parent().ngens() <= self.ngens(): Q = element.parent() gens_map = dict(zip(Q.variable_names(),self.gens()[:Q.ngens()])) return eval(str(element),gens_map)
# let python do the parsing else:
# we need to do this, to make sure that we actually get an # element in self.
except TypeError: p_Delete(&_p, _ring) raise raise TypeError("tuple key must have same length as ngens")
# SymbolicVariable pass
return self(element.external_string()) pass
# now try calling the base ring's __call__ methods
def _repr_(self): """ EXAMPLES::
sage: P.<x,y> = QQ[] sage: P # indirect doctest Multivariate Polynomial Ring in x, y over Rational Field """
def ngens(self): """ Returns the number of variables in this multivariate polynomial ring.
EXAMPLES::
sage: P.<x,y> = QQ[] sage: P.ngens() 2
sage: k.<a> = GF(2^16) sage: P = PolynomialRing(k,1000,'x') sage: P.ngens() 1000 """
def gen(self, int n=0): """ Returns the ``n``-th generator of this multivariate polynomial ring.
INPUT:
- ``n`` -- an integer ``>= 0``
EXAMPLES::
sage: P.<x,y,z> = QQ[] sage: P.gen(),P.gen(1) (x, y)
sage: P = PolynomialRing(GF(127),1000,'x') sage: P.gen(500) x500
sage: P.<SAGE,SINGULAR> = QQ[] # weird names sage: P.gen(1) SINGULAR """ cdef poly *_p
raise ValueError("Generator not defined.")
def ideal(self, *gens, **kwds): """ Create an ideal in this polynomial ring.
INPUT:
- ``*gens`` - list or tuple of generators (or several input arguments)
- ``coerce`` - bool (default: ``True``); this must be a keyword argument. Only set it to ``False`` if you are certain that each generator is already in the ring.
EXAMPLES::
sage: P.<x,y,z> = QQ[] sage: sage.rings.ideal.Katsura(P) Ideal (x + 2*y + 2*z - 1, x^2 + 2*y^2 + 2*z^2 - x, 2*x*y + 2*y*z - y) of Multivariate Polynomial Ring in x, y, z over Rational Field
sage: P.ideal([x + 2*y + 2*z-1, 2*x*y + 2*y*z-y, x^2 + 2*y^2 + 2*z^2-x]) Ideal (x + 2*y + 2*z - 1, 2*x*y + 2*y*z - y, x^2 + 2*y^2 + 2*z^2 - x) of Multivariate Polynomial Ring in x, y, z over Rational Field """ gens = list(gens) coerce = True
def _macaulay2_(self, macaulay2=macaulay2_default): """ Create an M2 representation of this polynomial ring if Macaulay2 is installed.
INPUT:
- ``macaulay2`` - M2 interpreter (default: ``macaulay2_default``)
EXAMPLES::
sage: R.<x,y> = ZZ[] sage: macaulay2(R) # optional - macaulay2 ZZ [x, y, MonomialOrder => GRevLex, MonomialSize => 16]
sage: R.<x,y> = QQ[] sage: macaulay2(R) # optional - macaulay2, indirect doctest QQ [x, y, MonomialOrder => GRevLex, MonomialSize => 16]
sage: R.<x,y> = GF(17)[] sage: print(macaulay2(R)) # optional - macaulay2 ZZ -- [x, y, MonomialOrder => GRevLex, MonomialSize => 16] 17 """ try: R = self.__macaulay2 if R is None or not (R.parent() is macaulay2): raise ValueError R._check_valid() return R except (AttributeError, ValueError): self.__macaulay2 = self._macaulay2_set_ring(macaulay2) return self.__macaulay2
def _macaulay2_set_ring(self, macaulay2=macaulay2_default): """ Set the associated M2 ring.
INPUT:
- ``macaulay2`` - M2 instance
EXAMPLES::
sage: P.<x,y> = PolynomialRing(QQ) sage: M2 = P._macaulay2_set_ring() # optional - macaulay2 """ if not self.__m2_set_ring_cache is None: base_str, gens, order = self.__m2_set_ring_cache else: if self.base_ring().is_prime_field(): if self.characteristic() == 0: base_str = "QQ" else: base_str = "ZZ/" + str(self.characteristic()) elif is_IntegerRing(self.base_ring()): base_str = "ZZ" else: raise TypeError("no conversion of to a Macaulay2 ring defined") gens = str(self.gens()) order = self.term_order().macaulay2_str() self.__m2_set_ring_cache = (base_str, gens, order) return macaulay2.ring(base_str, gens, order)
def _singular_(self, singular=singular_default): """ Create a SINGULAR (as in the computer algebra system) representation of this polynomial ring. The result is cached.
INPUT:
- ``singular`` - SINGULAR interpreter (default: ``singular_default``)
EXAMPLES::
sage: P.<x,y,z> = QQ[] sage: P._singular_() polynomial ring, over a field, global ordering // coefficients: QQ // number of vars : 3 // block 1 : ordering dp // : names x y z // block 2 : ordering C
sage: P._singular_() is P._singular_() True
sage: P._singular_().name() == P._singular_().name() True
sage: k.<a> = GF(3^3) sage: P.<x,y,z> = PolynomialRing(k,3) sage: P._singular_() polynomial ring, over a field, global ordering // coefficients: ZZ/3[a]/(a^3-a+1) // number of vars : 3 // block 1 : ordering dp // : names x y z // block 2 : ordering C
sage: P._singular_() is P._singular_() True
sage: P._singular_().name() == P._singular_().name() True
TESTS: sage: P.<x> = QQ[] sage: P._singular_() polynomial ring, over a field, global ordering // coefficients: QQ // number of vars : 1 // block 1 : ordering lp // : names x // block 2 : ordering C """ return R singular.eval("minpoly=%s"%(self.__minpoly)) self.__minpoly = singular.eval('minpoly')[1:-1] # store in correct format
def _singular_init_(self, singular=singular_default): """ Create a SINGULAR (as in the computer algebra system) representation of this polynomial ring. The result is NOT cached.
INPUT:
- ``singular`` - SINGULAR interpreter (default: ``singular_default``)
EXAMPLES::
sage: P.<x,y,z> = QQ[] sage: P._singular_init_() polynomial ring, over a field, global ordering // coefficients: QQ // number of vars : 3 // block 1 : ordering dp // : names x y z // block 2 : ordering C sage: P._singular_init_() is P._singular_init_() False
sage: P._singular_init_().name() == P._singular_init_().name() False
sage: w = var('w') sage: R.<x,y> = PolynomialRing(NumberField(w^2+1,'s')) sage: singular(R) polynomial ring, over a field, global ordering // coefficients: QQ[s]/(s^2+1) // number of vars : 2 // block 1 : ordering dp // : names x y // block 2 : ordering C
sage: R = PolynomialRing(GF(2**8,'a'),10,'x', order='invlex') sage: singular(R) polynomial ring, over a field, global ordering // coefficients: ZZ/2[a]/(a^8+a^4+a^3+a^2+1) // number of vars : 10 // block 1 : ordering rp // : names x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 // block 2 : ordering C
sage: R = PolynomialRing(GF(127),2,'x', order='invlex') sage: singular(R) polynomial ring, over a field, global ordering // coefficients: ZZ/127 // number of vars : 2 // block 1 : ordering rp // : names x0 x1 // block 2 : ordering C
sage: R = PolynomialRing(QQ,2,'x', order='invlex') sage: singular(R) polynomial ring, over a field, global ordering // coefficients: QQ // number of vars : 2 // block 1 : ordering rp // : names x0 x1 // block 2 : ordering C
sage: R = PolynomialRing(QQ,2,'x', order='degneglex') sage: singular(R) polynomial ring, over a field, global ordering // coefficients: QQ // number of vars : 2 // block 1 : ordering a // : names x0 x1 // : weights 1 1 // block 2 : ordering ls // : names x0 x1 // block 3 : ordering C
sage: R = PolynomialRing(QQ,'x') sage: singular(R) polynomial ring, over a field, global ordering // coefficients: QQ // number of vars : 1 // block 1 : ordering lp // : names x // block 2 : ordering C
sage: R = PolynomialRing(GF(127),'x') sage: singular(R) polynomial ring, over a field, global ordering // coefficients: ZZ/127 // number of vars : 1 // block 1 : ordering lp // : names x // block 2 : ordering C
sage: R = ZZ['x,y'] sage: singular(R) polynomial ring, over a domain, global ordering // coefficients: ZZ // number of vars : 2 // block 1 : ordering dp // : names x y // block 2 : ordering C
sage: R = IntegerModRing(1024)['x,y'] sage: singular(R) polynomial ring, over a ring (with zero-divisors), global ordering // coefficients: ZZ/(2^10) // number of vars : 2 // block 1 : ordering dp // : names x y // block 2 : ordering C
sage: R = IntegerModRing(15)['x,y'] sage: singular(R) polynomial ring, over a ring (with zero-divisors), global ordering // coefficients: ZZ/bigint(15) // number of vars : 2 // block 1 : ordering dp // : names x y // block 2 : ordering C
TESTS::
sage: P.<x> = QQ[] sage: P._singular_init_() polynomial ring, over a field, global ordering // coefficients: QQ // number of vars : 1 // block 1 : ordering lp // : names x // block 2 : ordering C
"""
_vars = _vars.split("*")[1] else:
# singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); precision = base_ring.precision() digits = ceil((2*precision - 2)/7.0) self.__singular = singular.ring("(real,%d,0)"%digits, _vars, order=order)
# singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); precision = base_ring.precision() digits = ceil((2*precision - 2)/7.0) self.__singular = singular.ring("(complex,%d,0,I)"%digits, _vars, order=order)
else:
else: raise TypeError("no conversion to a Singular ring defined")
# It is required in cython to redefine __hash__ when __richcmp__ is # overloaded. Also just writing # __hash__ = CategoryObject.__hash__ # doesn't work. def __hash__(self): """ Return a hash for this ring, that is, a hash of the string representation of this polynomial ring.
EXAMPLES::
sage: P.<x,y,z> = QQ[] sage: hash(P) # somewhat random output 967902441410893180 # 64-bit -1767675994 # 32-bit """
def __richcmp__(left, right, int op): r""" Multivariate polynomial rings are said to be equal if:
- their base rings match, - their generator names match and - their term orderings match.
EXAMPLES::
sage: P.<x,y,z> = QQ[] sage: R.<x,y,z> = QQ[] sage: P == R True
sage: R.<x,y,z> = GF(127)[] sage: P == R False
sage: R.<x,y> = QQ[] sage: P == R False
sage: R.<x,y,z> = PolynomialRing(QQ,order='invlex') sage: P == R False
TESTS::
sage: R = QQ['x', 'y']; R Multivariate Polynomial Ring in x, y over Rational Field sage: R == R True sage: R == QQ['x','z'] False """
# One is not a parent -- not equal and not ordered
def __reduce__(self): """ Serializes self.
EXAMPLES: sage: P.<x,y,z> = PolynomialRing(QQ, order='degrevlex') sage: P == loads(dumps(P)) True
sage: P.<x,y,z> = PolynomialRing(ZZ, order='degrevlex') sage: P == loads(dumps(P)) True
sage: P = PolynomialRing(GF(127), names='abc') sage: P == loads(dumps(P)) True
sage: P = PolynomialRing(GF(2^8,'F'), names='abc') sage: P == loads(dumps(P)) True
sage: P = PolynomialRing(GF(2^16,'B'), names='abc') sage: P == loads(dumps(P)) True sage: z = QQ['z'].0 sage: P = PolynomialRing(NumberField(z^2 + 3,'B'), names='abc') sage: P == loads(dumps(P)) True """
def __temporarily_change_names(self, names, latex_names): """ This is used by the variable names context manager.
EXAMPLES::
sage: R.<x,y> = QQ[] # indirect doctest sage: with localvars(R, 'z,w'): ....: print(x^3 + y^3 - x*y) z^3 + w^3 - z*w """ cdef char **_names cdef char **_orig_names cdef int i
raise TypeError("len(names) doesn't equal self.ngens()")
### The following methods are handy for implementing Groebner ### basis algorithms. They do only superficial type/sanity checks ### and should be called carefully.
def monomial_quotient(self, MPolynomial_libsingular f, MPolynomial_libsingular g, coeff=False): r""" Return ``f/g``, where both ``f`` and`` ``g`` are treated as monomials.
Coefficients are ignored by default.
INPUT:
- ``f`` - monomial - ``g`` - monomial - ``coeff`` - divide coefficients as well (default: ``False``)
EXAMPLES::
sage: P.<x,y,z> = QQ[] sage: P.monomial_quotient(3/2*x*y,x) y
sage: P.monomial_quotient(3/2*x*y,x,coeff=True) 3/2*y
Note, that `\ZZ` behaves different if ``coeff=True``::
sage: P.monomial_quotient(2*x,3*x) 1
sage: P.<x,y> = PolynomialRing(ZZ) sage: P.monomial_quotient(2*x,3*x,coeff=True) Traceback (most recent call last): ... ArithmeticError: Cannot divide these coefficients.
TESTS::
sage: R.<x,y,z> = QQ[] sage: P.<x,y,z> = QQ[] sage: P.monomial_quotient(x*y,x) y
sage: P.monomial_quotient(x*y,R.gen()) y
sage: P.monomial_quotient(P(0),P(1)) 0
sage: P.monomial_quotient(P(1),P(0)) Traceback (most recent call last): ... ZeroDivisionError
sage: P.monomial_quotient(P(3/2),P(2/3), coeff=True) 9/4
sage: P.monomial_quotient(x,y) # Note the wrong result x*y^65535*z^65535
sage: P.monomial_quotient(x,P(1)) x
.. warning::
Assumes that the head term of f is a multiple of the head term of g and return the multiplicant m. If this rule is violated, funny things may happen. """ cdef poly *res cdef number *n cdef number *denom
f = self._coerce_c(f) g = self._coerce_c(g)
else: else:
def monomial_divides(self, MPolynomial_libsingular a, MPolynomial_libsingular b): """ Return ``False`` if a does not divide b and ``True`` otherwise.
Coefficients are ignored.
INPUT:
- ``a`` -- monomial
- ``b`` -- monomial
EXAMPLES::
sage: P.<x,y,z> = QQ[] sage: P.monomial_divides(x*y*z, x^3*y^2*z^4) True sage: P.monomial_divides(x^3*y^2*z^4, x*y*z) False
TESTS::
sage: P.<x,y,z> = QQ[] sage: P.monomial_divides(P(1), P(0)) True sage: P.monomial_divides(P(1), x) True """ cdef poly *_a cdef poly *_b cdef ring *_r b = a._parent._coerce_c(b)
raise ZeroDivisionError
else:
def monomial_lcm(self, MPolynomial_libsingular f, MPolynomial_libsingular g): """ LCM for monomials. Coefficients are ignored.
INPUT:
- ``f`` - monomial
- ``g`` - monomial
EXAMPLES::
sage: P.<x,y,z> = QQ[] sage: P.monomial_lcm(3/2*x*y,x) x*y
TESTS::
sage: R.<x,y,z> = QQ[] sage: P.<x,y,z> = QQ[] sage: P.monomial_lcm(x*y,R.gen()) x*y
sage: P.monomial_lcm(P(3/2),P(2/3)) 1
sage: P.monomial_lcm(x,P(1)) x """
f = self._coerce_c(f) g = self._coerce_c(g)
if g._poly == NULL: return self._zero_element else: raise ArithmeticError("Cannot compute LCM of zero and nonzero element.") raise ArithmeticError("Cannot compute LCM of zero and nonzero element.")
def monomial_reduce(self, MPolynomial_libsingular f, G): """ Try to find a ``g`` in ``G`` where ``g.lm()`` divides ``f``. If found ``(flt,g)`` is returned, ``(0,0)`` otherwise, where ``flt`` is ``f/g.lm()``.
It is assumed that ``G`` is iterable and contains *only* elements in this polynomial ring.
Coefficients are ignored.
INPUT:
- ``f`` - monomial - ``G`` - list/set of mpolynomials
EXAMPLES::
sage: P.<x,y,z> = QQ[] sage: f = x*y^2 sage: G = [ 3/2*x^3 + y^2 + 1/2, 1/4*x*y + 2/7, 1/2 ] sage: P.monomial_reduce(f,G) (y, 1/4*x*y + 2/7)
TESTS::
sage: P.<x,y,z> = QQ[] sage: f = x*y^2 sage: G = [ 3/2*x^3 + y^2 + 1/2, 1/4*x*y + 2/7, 1/2 ]
sage: P.monomial_reduce(P(0),G) (0, 0)
sage: P.monomial_reduce(f,[P(0)]) (0, 0) """ cdef poly *flt
#p_SetCoeff(flt, n_Div( p_GetCoeff(f._poly, r) , p_GetCoeff((<MPolynomial_libsingular>g)._poly, r), r), r)
def monomial_pairwise_prime(self, MPolynomial_libsingular g, MPolynomial_libsingular h): """ Return ``True`` if ``h`` and ``g`` are pairwise prime. Both are treated as monomials.
Coefficients are ignored.
INPUT:
- ``h`` - monomial - ``g`` - monomial
EXAMPLES::
sage: P.<x,y,z> = QQ[] sage: P.monomial_pairwise_prime(x^2*z^3, y^4) True
sage: P.monomial_pairwise_prime(1/2*x^3*y^2, 3/4*y^3) False
TESTS::
sage: Q.<x,y,z> = QQ[] sage: P.<x,y,z> = QQ[] sage: P.monomial_pairwise_prime(x^2*z^3, Q('y^4')) True
sage: P.monomial_pairwise_prime(1/2*x^3*y^2, Q(0)) True
sage: P.monomial_pairwise_prime(P(1/2),x) False """ cdef int i cdef ring *r cdef poly *p cdef poly *q
g = h._parent._coerce_c(g)
if q == NULL: return False #GCD(0,0) = 0 else: return True #GCD(x,0) = 1
def monomial_all_divisors(self, MPolynomial_libsingular t): """ Return a list of all monomials that divide ``t``.
Coefficients are ignored.
INPUT:
- ``t`` - a monomial
OUTPUT: a list of monomials
EXAMPLES::
sage: P.<x,y,z> = QQ[] sage: P.monomial_all_divisors(x^2*z^3) [x, x^2, z, x*z, x^2*z, z^2, x*z^2, x^2*z^2, z^3, x*z^3, x^2*z^3]
ALGORITHM: addwithcarry idea by Toon Segers """
def unpickle_MPolynomialRing_libsingular(base_ring, names, term_order): """ inverse function for ``MPolynomialRing_libsingular.__reduce__``
EXAMPLES::
sage: P.<x,y> = PolynomialRing(QQ) sage: loads(dumps(P)) is P # indirect doctest True """ # If libsingular would be replaced by a different implementation in future # sage version, the unpickled ring will belong the new implementation.
cdef class MPolynomial_libsingular(MPolynomial): """ A multivariate polynomial implemented using libSINGULAR. """ def __init__(self, MPolynomialRing_libsingular parent): """ Construct a zero element in parent.
EXAMPLES::
sage: from sage.rings.polynomial.multi_polynomial_libsingular import MPolynomial_libsingular sage: P = PolynomialRing(GF(32003),3,'x') sage: MPolynomial_libsingular(P) 0 """
def __dealloc__(self): # WARNING: the Cython class self._parent is now no longer accessible! # e.g. MPolynomialRing_libsingular._zero_element
def __copy__(self): """ Copy ``self``.
OUTPUT:
A copy.
EXAMPLES::
sage: F.<a> = GF(7^2) sage: R.<x,y> = F[] sage: p = a*x^2 + y + a^3; p (a)*x^2 + y + (-2*a - 3) sage: q = copy(p) sage: p == q True sage: p is q False sage: lst = [p,q]; sage: matrix(ZZ, 2, 2, lambda i,j: bool(lst[i]==lst[j])) [1 1] [1 1] sage: matrix(ZZ, 2, 2, lambda i,j: bool(lst[i] is lst[j])) [1 0] [0 1] """
def __deepcopy__(self, memo={}): """ Deep copy ``self``
TESTS::
sage: R.<x,y> = QQ[] sage: p = x^2 + y^2 sage: p is deepcopy(p) False sage: p == deepcopy(p) True sage: p.parent() is deepcopy(p).parent() True """
cpdef MPolynomial_libsingular _new_constant_poly(self, x, MPolynomialRing_libsingular P): r""" Quickly create a new constant polynomial with value x in the parent P.
ASSUMPTION:
The value x must be an element of the base ring. That assumption is not verified.
EXAMPLES::
sage: R.<x,y> = QQ[] sage: x._new_constant_poly(2/1,R) 2
""" cdef poly *_p
def __call__(self, *x, **kwds): """ Evaluate this multi-variate polynomial at ``x``, where ``x`` is either the tuple of values to substitute in, or one can use functional notation ``f(a_0,a_1,a_2, \ldots)`` to evaluate ``f`` with the ith variable replaced by ``a_i``.
INPUT:
- ``x`` - a list of elements in ``self.parent()`` - or ``**kwds`` - a dictionary of ``variable-name:value`` pairs.
EXAMPLES::
sage: P.<x,y,z> = QQ[] sage: f = 3/2*x^2*y + 1/7 * y^2 + 13/27 sage: f(0,0,0) 13/27
sage: f(1,1,1) 803/378 sage: 3/2 + 1/7 + 13/27 803/378
sage: f(45/2,19/3,1) 7281167/1512
sage: f(1,2,3).parent() Rational Field
TESTS::
sage: P.<x,y,z> = QQ[] sage: P(0)(1,2,3) 0 sage: P(3/2)(1,2,3) 3/2
sage: R.<a,b,y> = QQ[] sage: f = a*y^3 + b*y - 3*a*b*y sage: f(a=5,b=3,y=10) 4580 sage: f(5,3,10) 4580
See :trac:`8502`::
sage: x = polygen(QQ) sage: K.<t> = NumberField(x^2+47) sage: R.<X,Y,Z> = K[] sage: f = X+Y+Z sage: a = f(t,t,t); a 3*t sage: a.parent() is K True
sage: R.<X,Y,Z> = QQ[] sage: f = X+Y+Z sage: a = f(2,3,4); a 9 sage: a.parent() is QQ True """ return f(*x) else:
# Attempt evaluation via singular. # give up, evaluate functional
cdef poly *res # ownership will be transferred to us in the next line
else:
def __hash__(self): """ This hash incorporates the variable name in an effort to respect the obvious inclusions into multi-variable polynomial rings.
The tuple algorithm is borrowed from http://effbot.org/zone/python-hash.htm.
EXAMPLES::
sage: R.<x>=QQ[] sage: S.<x,y>=QQ[] sage: hash(S(1/2))==hash(1/2) # respect inclusions of the rationals True sage: hash(S.0)==hash(R.0) # respect inclusions into mpoly rings True sage: # the point is to make for more flexible dictionary look ups sage: d={S.0:12} sage: d[R.0] 12 """
cpdef int _cmp_(left, right) except -2: """ Compare left and right and return -1, 0, and 1 for <,==, and > respectively.
EXAMPLES::
sage: P.<x,y,z> = PolynomialRing(QQ,order='degrevlex') sage: x == x True
sage: x > y True sage: y^2 > x True
sage: (2/3*x^2 + 1/2*y + 3) > (2/3*x^2 + 1/4*y + 10) True
TESTS::
sage: P.<x,y,z> = PolynomialRing(QQ, order='degrevlex') sage: x > P(0) True
sage: P(0) == P(0) True
sage: P(0) < P(1) True
sage: x > P(1) True
sage: 1/2*x < 3/4*x True
sage: (x+1) > x True
sage: f = 3/4*x^2*y + 1/2*x + 2/7 sage: f > f False sage: f < f False sage: f == f True
sage: P.<x,y,z> = PolynomialRing(GF(127), order='degrevlex') sage: (66*x^2 + 23) > (66*x^2 + 2) True """ return 0
cpdef _add_(left, right): """ Add left and right.
EXAMPLES::
sage: P.<x,y,z>=PolynomialRing(QQ,3) sage: 3/2*x + 1/2*y + 1 #indirect doctest 3/2*x + 1/2*y + 1 """ cdef poly *_p (<MPolynomial_libsingular>right)._poly, r)
cpdef _sub_(left, right): """ Subtract left and right.
EXAMPLES::
sage: P.<x,y,z>=PolynomialRing(QQ,3) sage: 3/2*x - 1/2*y - 1 #indirect doctest 3/2*x - 1/2*y - 1 """ cdef poly *_p (<MPolynomial_libsingular>right)._poly, _ring)
cpdef _lmul_(self, Element left): """ Multiply self with a base ring element.
EXAMPLES::
sage: P.<x,y,z>=PolynomialRing(QQ,3) sage: 3/2*x # indirect doctest 3/2*x
::
sage: P.<x,y,z>=PolynomialRing(QQ,3) sage: (3/2*x - 1/2*y - 1) * (3/2) # indirect doctest 9/4*x - 3/4*y - 3/2 """
cdef poly *_p
cpdef _mul_(left, right): """ Multiply left and right.
EXAMPLES::
sage: P.<x,y,z>=PolynomialRing(QQ,3) sage: (3/2*x - 1/2*y - 1) * (3/2*x + 1/2*y + 1) # indirect doctest 9/4*x^2 - 1/4*y^2 - y - 1
sage: P.<x,y> = PolynomialRing(QQ,order='lex') sage: (x^2^15) * x^2^15 Traceback (most recent call last): ... OverflowError: exponent overflow (...) """ # all currently implemented rings are commutative cdef poly *_p (<MPolynomial_libsingular>right)._poly, (<MPolynomial_libsingular>left)._parent_ring)
cpdef _div_(left, right_ringelement): """ Divide left by right
EXAMPLES::
sage: R.<x,y>=PolynomialRing(QQ,2) sage: f = (x + y)/3 # indirect doctest sage: f.parent() Multivariate Polynomial Ring in x, y over Rational Field
Note that / is still a constructor for elements of the fraction field in all cases as long as both arguments have the same parent and right is not constant. ::
sage: R.<x,y>=PolynomialRing(QQ,2) sage: f = x^3 + y sage: g = x sage: h = f/g; h (x^3 + y)/x sage: h.parent() Fraction Field of Multivariate Polynomial Ring in x, y over Rational Field
If we divide over `\ZZ` the result is the same as multiplying by 1/3 (i.e. base extension). ::
sage: R.<x,y> = ZZ[] sage: f = (x + y)/3 sage: f.parent() Multivariate Polynomial Ring in x, y over Rational Field sage: f = (x + y) * 1/3 sage: f.parent() Multivariate Polynomial Ring in x, y over Rational Field
But we get a true fraction field if the denominator is not in the fraction field of the base ring.""
sage: f = x/y sage: f.parent() Fraction Field of Multivariate Polynomial Ring in x, y over Integer Ring
Division will fail for non-integral domains::
sage: P.<x,y> = Zmod(1024)[] sage: x/P(3) Traceback (most recent call last): ... TypeError: self must be an integral domain.
sage: x/3 Traceback (most recent call last): ... TypeError: self must be an integral domain.
TESTS::
sage: R.<x,y>=PolynomialRing(QQ,2) sage: x/0 Traceback (most recent call last): ... ZeroDivisionError: rational division by zero """ cdef poly *p else: else:
def __pow__(MPolynomial_libsingular self, exp, ignored): """ Return ``self**(exp)``.
The exponent must be an integer or a rational such that the result lies in the same polynomial ring.
EXAMPLES::
sage: R.<x,y> = PolynomialRing(QQ,2) sage: f = x^3 + y sage: f^2 x^6 + 2*x^3*y + y^2 sage: g = f^(-1); g 1/(x^3 + y) sage: type(g) <type 'sage.rings.fraction_field_element.FractionFieldElement'>
sage: P.<x,y> = PolynomialRing(ZZ) sage: P(2)**(-1) 1/2
sage: P.<u,v> = PolynomialRing(QQ, 2) sage: u^(1/2) Traceback (most recent call last): ... ValueError: (u)^(1/2) does not lie in Multivariate Polynomial Ring in u, v over Rational Field
sage: P.<x,y> = PolynomialRing(QQ,order='lex') sage: (x+y^2^15)^10 Traceback (most recent call last): .... OverflowError: exponent overflow (...)
Test fractional powers (:trac:`22329`)::
sage: P.<R, S> = ZZ[] sage: (R^3 + 6*R^2*S + 12*R*S^2 + 8*S^3)^(1/3) R + 2*S sage: _.parent() Multivariate Polynomial Ring in R, S over Integer Ring sage: P(4)^(1/2) 2 sage: _.parent() Multivariate Polynomial Ring in R, S over Integer Ring
sage: (R^2 + 3)^(1/2) Traceback (most recent call last): ... ValueError: (R^2 + 3)^(1/2) does not lie in Multivariate Polynomial Ring in R, S over Integer Ring sage: P(2)^P(2) 4 sage: (R + 1)^P(2) R^2 + 2*R + 1 sage: (R + 1)^R Traceback (most recent call last): ... TypeError: R is neither an integer nor a rational sage: 2^R Traceback (most recent call last): ... TypeError: R is neither an integer nor a rational """
return self.parent()( self.constant_coefficient().nth_root(den) ** num)
cdef poly *_p
def __neg__(self): """ Return ``-self``.
EXAMPLES::
sage: R.<x,y>=PolynomialRing(QQ,2) sage: f = x^3 + y sage: -f -x^3 - y """
cdef poly *p
def _repr_(self): """ EXAMPLES::
sage: R.<x,y>=PolynomialRing(QQ,2) sage: f = x^3 + y sage: f # indirect doctest x^3 + y """
cpdef _repr_short_(self): """ This is a faster but less pretty way to print polynomials. If available it uses the short SINGULAR notation.
EXAMPLES::
sage: R.<x,y>=PolynomialRing(QQ,2) sage: f = x^3 + y sage: f._repr_short_() 'x3+y' """ else:
def _latex_(self): """ Return a polynomial LaTeX representation of this polynomial.
EXAMPLES::
sage: P.<x,y,z> = QQ[] sage: f = - 1*x^2*y - 25/27 * y^3 - z^2 sage: latex(f) # indirect doctest - x^{2} y - \frac{25}{27} y^{3} - z^{2} """
def _repr_with_changed_varnames(self, varnames): """ Return string representing this polynomial but change the variable names to ``varnames``.
EXAMPLES::
sage: P.<x,y,z> = QQ[] sage: f = - 1*x^2*y - 25/27 * y^3 - z^2 sage: print(f._repr_with_changed_varnames(['FOO', 'BAR', 'FOOBAR'])) -FOO^2*BAR - 25/27*BAR^3 - FOOBAR^2 """
def degree(self, MPolynomial_libsingular x=None, int std_grading=False): """ Return the maximal degree of this polynomial in ``x``, where ``x`` must be one of the generators for the parent of this polynomial.
INPUT:
- ``x`` - (default: ``None``) a multivariate polynomial which is (or coerces to) a generator of the parent of self. If ``x`` is ``None``, return the total degree, which is the maximum degree of any monomial. Note that a matrix term ordering alters the grading of the generators of the ring; see the tests below. To avoid this behavior, use either ``exponents()`` for the exponents themselves, or the optional argument ``std_grading=False``.
OUTPUT: integer
EXAMPLES::
sage: R.<x, y> = QQ[] sage: f = y^2 - x^9 - x sage: f.degree(x) 9 sage: f.degree(y) 2 sage: (y^10*x - 7*x^2*y^5 + 5*x^3).degree(x) 3 sage: (y^10*x - 7*x^2*y^5 + 5*x^3).degree(y) 10
TESTS::
sage: P.<x, y> = QQ[] sage: P(0).degree(x) -1 sage: P(1).degree(x) 0
With a matrix term ordering, the grading of the generators is determined by the first row of the matrix. This affects the behavior of ``degree()`` when no variable is specified. To evaluate the degree with a standard grading, use the optional argument ``std_grading=True``.
sage: tord = TermOrder(matrix([3,0,1,1,1,0,1,0,0])) sage: R.<x,y,z> = PolynomialRing(QQ,3,order=tord) sage: (x^3*y+x*z^4).degree() 9 sage: (x^3*y+x*z^4).degree(std_grading=True) 5 sage: x.degree(x), y.degree(y), z.degree(z) (1, 1, 1)
The following example is inspired by :trac:`11652`::
sage: R.<p,q,t> = ZZ[] sage: poly = p+q^2+t^3 sage: poly = poly.polynomial(t)[0] sage: poly q^2 + p
There is no canonical coercion from ``R`` to the parent of ``poly``, so this doesn't work::
sage: poly.degree(q) Traceback (most recent call last): ... TypeError: argument must canonically coerce to parent
Using a non-canonical coercion does work, but we require this to be done explicitly, since it can lead to confusing results if done automatically::
sage: poly.degree(poly.parent()(q)) 2 sage: poly.degree(poly.parent()(p)) 1 sage: T.<x,y> = ZZ[] sage: poly.degree(poly.parent()(x)) # noncanonical coercions can be confusing 1
The argument to degree has to be a generator::
sage: pp = poly.parent().gen(0) sage: poly.degree(pp) 1 sage: poly.degree(pp+1) Traceback (most recent call last): ... TypeError: argument must be a generator
Canonical coercions are used::
sage: S = ZZ['p,q'] sage: poly.degree(S.0) 1 sage: poly.degree(S.1) 2 """ else:
def total_degree(self, int std_grading=False): """ Return the total degree of ``self``, which is the maximum degree of all monomials in ``self``.
EXAMPLES::
sage: R.<x,y,z> = QQ[] sage: f=2*x*y^3*z^2 sage: f.total_degree() 6 sage: f=4*x^2*y^2*z^3 sage: f.total_degree() 7 sage: f=99*x^6*y^3*z^9 sage: f.total_degree() 18 sage: f=x*y^3*z^6+3*x^2 sage: f.total_degree() 10 sage: f=z^3+8*x^4*y^5*z sage: f.total_degree() 10 sage: f=z^9+10*x^4+y^8*x^2 sage: f.total_degree() 10
TESTS::
sage: R.<x,y,z> = QQ[] sage: R(0).total_degree() -1 sage: R(1).total_degree() 0
With a matrix term ordering, the grading changes. To evaluate the total degree using the standard grading, use the optional argument``std_grading=True``::
sage: tord=TermOrder(matrix([3,0,1,1,1,0,1,0,0])) sage: R.<x,y,z> = PolynomialRing(QQ,3,order=tord) sage: (x^2*y).total_degree() 6 sage: (x^2*y).total_degree(std_grading=True) 3 """ cdef int i, result
else:
def degrees(self): """ Returns a tuple with the maximal degree of each variable in this polynomial. The list of degrees is ordered by the order of the generators.
EXAMPLES::
sage: R.<y0,y1,y2> = PolynomialRing(QQ,3) sage: q = 3*y0*y1*y1*y2; q 3*y0*y1^2*y2 sage: q.degrees() (1, 2, 1) sage: (q + y0^5).degrees() (5, 2, 1) """ cdef int i
def coefficient(self, degrees): """ Return the coefficient of the variables with the degrees specified in the python dictionary ``degrees``. Mathematically, this is the coefficient in the base ring adjoined by the variables of this ring not listed in ``degrees``. However, the result has the same parent as this polynomial.
This function contrasts with the function ``monomial_coefficient`` which returns the coefficient in the base ring of a monomial.
INPUT:
- ``degrees`` - Can be any of: - a dictionary of degree restrictions - a list of degree restrictions (with None in the unrestricted variables) - a monomial (very fast, but not as flexible)
OUTPUT: element of the parent of this element.
.. NOTE::
For coefficients of specific monomials, look at :meth:`monomial_coefficient`.
EXAMPLES::
sage: R.<x,y> = QQ[] sage: f=x*y+y+5 sage: f.coefficient({x:0,y:1}) 1 sage: f.coefficient({x:0}) y + 5 sage: f=(1+y+y^2)*(1+x+x^2) sage: f.coefficient({x:0}) y^2 + y + 1 sage: f.coefficient([0,None]) y^2 + y + 1 sage: f.coefficient(x) y^2 + y + 1
Be aware that this may not be what you think! The physical appearance of the variable x is deceiving -- particularly if the exponent would be a variable. ::
sage: f.coefficient(x^0) # outputs the full polynomial x^2*y^2 + x^2*y + x*y^2 + x^2 + x*y + y^2 + x + y + 1 sage: R.<x,y> = GF(389)[] sage: f=x*y+5 sage: c=f.coefficient({x:0,y:0}); c 5 sage: parent(c) Multivariate Polynomial Ring in x, y over Finite Field of size 389
AUTHOR:
- Joel B. Mohler (2007.10.31) """ cdef poly *newptemp cdef int i cdef int flag
raise TypeError("degrees must be a monomial") else: # Extract the ordered list of degree specifications from the dictionary pass else: raise TypeError("The input degrees must be a dictionary of variables to exponents.")
# Extract the monomials that match the specifications
def monomial_coefficient(self, MPolynomial_libsingular mon): """ Return the coefficient in the base ring of the monomial mon in ``self``, where mon must have the same parent as self.
This function contrasts with the function ``coefficient`` which returns the coefficient of a monomial viewing this polynomial in a polynomial ring over a base ring having fewer variables.
INPUT:
- ``mon`` - a monomial
OUTPUT:
coefficient in base ring
.. SEEALSO::
For coefficients in a base ring of fewer variables, look at ``coefficient``.
EXAMPLES::
sage: P.<x,y> = QQ[]
The parent of the return is a member of the base ring. sage: f = 2 * x * y sage: c = f.monomial_coefficient(x*y); c 2 sage: c.parent() Rational Field
sage: f = y^2 + y^2*x - x^9 - 7*x + 5*x*y sage: f.monomial_coefficient(y^2) 1 sage: f.monomial_coefficient(x*y) 5 sage: f.monomial_coefficient(x^9) -1 sage: f.monomial_coefficient(x^10) 0 """
raise TypeError("mon must have same parent as self.")
def dict(self): """ Return a dictionary representing self. This dictionary is in the same format as the generic MPolynomial: The dictionary consists of ``ETuple:coefficient`` pairs.
EXAMPLES::
sage: R.<x,y,z> = QQ[] sage: f=2*x*y^3*z^2 + 1/7*x^2 + 2/3 sage: f.dict() {(0, 0, 0): 2/3, (1, 3, 2): 2, (2, 0, 0): 1/7} """ cdef poly *p cdef int n cdef int v
cpdef long number_of_terms(self): """ Return the number of non-zero coefficients of this polynomial.
This is also called weight, :meth:`hamming_weight` or sparsity.
EXAMPLES::
sage: R.<x, y> = ZZ[] sage: f = x^3 - y sage: f.number_of_terms() 2 sage: R(0).number_of_terms() 0 sage: f = (x+y)^100 sage: f.number_of_terms() 101
The method :meth:`hamming_weight` is an alias::
sage: f.hamming_weight() 101 """
hamming_weight = number_of_terms
cdef long _hash_c(self) except -1: """ See ``self.__hash__`` """ cdef int n cdef int v cdef long result_mon cdef long c_hash # Hash (self[i], gen_a, exp_a, gen_b, exp_b, gen_c, exp_c, ...) as a tuple according to the algorithm. # I omit gen,exp pairs where the exponent is zero.
return -2
def __getitem__(self,x): """ Same as ``self.monomial_coefficient`` but for exponent vectors.
INPUT:
- ``x`` - a tuple or, in case of a single-variable MPolynomial ring x can also be an integer.
EXAMPLES::
sage: R.<x, y> = QQ[] sage: f = -10*x^3*y + 17*x*y sage: f[3,1] -10 sage: f[1,1] 17 sage: f[0,1] 0
sage: R.<x> = PolynomialRing(GF(7), implementation="singular"); R Multivariate Polynomial Ring in x over Finite Field of size 7 sage: f = 5*x^2 + 3; f -2*x^2 + 3 sage: f[2] 5 """ cdef poly *m cdef int i
raise TypeError("x must have length self.ngens()")
def exponents(self, as_ETuples=True): """ Return the exponents of the monomials appearing in this polynomial.
INPUT:
- ``as_ETuples`` - (default: ``True``) if true returns the result as an list of ETuples otherwise returns a list of tuples
EXAMPLES::
sage: R.<a,b,c> = QQ[] sage: f = a^3 + b + 2*b^2 sage: f.exponents() [(3, 0, 0), (0, 2, 0), (0, 1, 0)] sage: f.exponents(as_ETuples=False) [(3, 0, 0), (0, 2, 0), (0, 1, 0)] """ cdef int v cdef list pl, ml
else:
def inverse_of_unit(self): """ Return the inverse of this polynomial if it is a unit.
EXAMPLES::
sage: R.<x,y> = QQ[] sage: x.inverse_of_unit() Traceback (most recent call last): ... ArithmeticError: Element is not a unit.
sage: R(1/2).inverse_of_unit() 2 """
def is_homogeneous(self): """ Return ``True`` if this polynomial is homogeneous.
EXAMPLES::
sage: P.<x,y> = PolynomialRing(RationalField(), 2) sage: (x+y).is_homogeneous() True sage: (x.parent()(0)).is_homogeneous() True sage: (x+y^2).is_homogeneous() False sage: (x^2 + y^2).is_homogeneous() True sage: (x^2 + y^2*x).is_homogeneous() False sage: (x^2*y + y^2*x).is_homogeneous() True """
cpdef _homogenize(self, int var): """ Return ``self`` if ``self`` is homogeneous. Otherwise return a homogenized polynomial constructed by modifying the degree of the variable with index ``var``.
INPUT:
- ``var`` - an integer indicating which variable to use to homogenize (``0 <= var < parent(self).ngens()``)
OUTPUT: a multivariate polynomial
EXAMPLES::
sage: P.<x,y> = QQ[] sage: f = x^2 + y + 1 + 5*x*y^10 sage: g = f.homogenize('z'); g # indirect doctest 5*x*y^10 + x^2*z^9 + y*z^10 + z^11 sage: g.parent() Multivariate Polynomial Ring in x, y, z over Rational Field sage: f._homogenize(0) 2*x^11 + x^10*y + 5*x*y^10
SEE: ``self.homogenize`` """ cdef MPolynomial_libsingular f
return self
else: raise TypeError("var must be < self.parent().ngens()")
def is_monomial(self): """ Return ``True`` if this polynomial is a monomial. A monomial is defined to be a product of generators with coefficient 1.
EXAMPLES::
sage: P.<x,y,z> = PolynomialRing(QQ) sage: x.is_monomial() True sage: (2*x).is_monomial() False sage: (x*y).is_monomial() True sage: (x*y + x).is_monomial() False """ cdef poly *_p cdef ring *_ring cdef number *_n
return True
def subs(self, fixed=None, **kw): """ Fixes some given variables in a given multivariate polynomial and returns the changed multivariate polynomials. The polynomial itself is not affected. The variable,value pairs for fixing are to be provided as dictionary of the form ``{variable:value}``.
This is a special case of evaluating the polynomial with some of the variables constants and the others the original variables, but should be much faster if only few variables are to be fixed.
INPUT:
- ``fixed`` - (optional) dict with variable:value pairs - ``**kw`` - names parameters
OUTPUT: a new multivariate polynomial
EXAMPLES::
sage: R.<x,y> = QQ[] sage: f = x^2 + y + x^2*y^2 + 5 sage: f(5,y) 25*y^2 + y + 30 sage: f.subs({x:5}) 25*y^2 + y + 30 sage: f.subs(x=5) 25*y^2 + y + 30
sage: P.<x,y,z> = PolynomialRing(GF(2),3) sage: f = x + y + 1 sage: f.subs({x:y+1}) 0 sage: f.subs(x=y) 1 sage: f.subs(x=x) x + y + 1 sage: f.subs({x:z}) y + z + 1 sage: f.subs(x=z+1) y + z
sage: f.subs(x=1/y) (y^2 + y + 1)/y sage: f.subs({x:1/y}) (y^2 + y + 1)/y
The parameters are subsituted in order and without side effects::
sage: R.<x,y>=QQ[] sage: g=x+y sage: g.subs({x:x+1,y:x*y}) x*y + x + 1 sage: g.subs({x:x+1}).subs({y:x*y}) x*y + x + 1 sage: g.subs({y:x*y}).subs({x:x+1}) x*y + x + y + 1
::
sage: R.<x,y> = QQ[] sage: f = x + 2*y sage: f.subs(x=y,y=x) 2*x + y
TESTS::
sage: P.<x,y,z> = QQ[] sage: f = y sage: f.subs({y:x}).subs({x:z}) z
We test that we change the ring even if there is nothing to do::
sage: P = QQ['x,y'] sage: x = var('x') sage: parent(P.zero() / x) Symbolic Ring
We are catching overflows::
sage: R.<x,y> = QQ[] sage: n=100; f = x^n sage: try: ....: f.subs(x = x^n) ....: print("no overflow") ....: except OverflowError: ....: print("overflow") x^10000 no overflow
sage: n=1000; sage: try: ....: f = x^n ....: f.subs(x = x^n) ....: print("no overflow") ....: except OverflowError: ....: print("overflow") overflow
Check that there is no more segmentation fault if the polynomial gets 0 in the middle of a substitution (:trac:`17785`)::
sage: R.<x,y,z> = QQ[] sage: for vx in [0,x,y,z]: ....: for vy in [0,x,y,z]: ....: for vz in [0,x,y,z]: ....: d = {x:vx, y:vy, z:vz} ....: ds = {'x': vx, 'y': vy, 'z': vz} ....: assert x.subs(d) == x.subs(**ds) == vx ....: assert y.subs(d) == y.subs(**ds) == vy ....: assert z.subs(d) == z.subs(**ds) == vz ....: assert (x+y).subs(d) == (x+y).subs(**ds) == vx+vy """ cdef int mi, i, need_map, try_symbolic
cdef poly *_f
cdef ideal *from_id cdef ideal *res_id
# the polynomial is 0. There is nothing to do except to change the # ring
mi = m+1 id_Delete(&to_id, _ring) p_Delete(&_p, _ring) raise TypeError("key does not match") else: id_Delete(&to_id, _ring) p_Delete(&_p, _ring) raise TypeError("keys do not match self's parent") else: id_Delete(&to_id, _ring) p_Delete(&_p, _ring) raise OverflowError("exponent overflow (%d)"%(degree))
# polynomial becomes 0 after some substitution
cdef dict gd
id_Delete(&to_id, _ring) p_Delete(&_p, _ring) raise TypeError("key does not match") else: p_Delete(&to_id.m[mi-1],_ring)
# the polynomial is 0
# now as everything else failed, try to do it symbolically with call
mi = m+1 raise TypeError("key does not match") else: raise TypeError("keys do not match self's parent")
raise TypeError("key does not match")
def monomials(self): """ Return the list of monomials in self. The returned list is decreasingly ordered by the term ordering of ``self.parent()``.
EXAMPLES::
sage: P.<x,y,z> = QQ[] sage: f = x + 3/2*y*z^2 + 2/3 sage: f.monomials() [y*z^2, x, 1] sage: f = P(3/2) sage: f.monomials() [1]
TESTS::
sage: P.<x,y,z> = QQ[] sage: f = x sage: f.monomials() [x]
Check if :trac:`12706` is fixed::
sage: f = P(0) sage: f.monomials() []
Check if :trac:`7152` is fixed::
sage: x=var('x') sage: K.<rho> = NumberField(x**2 + 1) sage: R.<x,y> = QQ[] sage: p = rho*x sage: q = x sage: p.monomials() [x] sage: q.monomials() [x] sage: p.monomials() [x] """ cdef poly *t
def constant_coefficient(self): """ Return the constant coefficient of this multivariate polynomial.
EXAMPLES::
sage: P.<x, y> = QQ[] sage: f = 3*x^2 - 2*y + 7*x^2*y^2 + 5 sage: f.constant_coefficient() 5 sage: f = 3*x^2 sage: f.constant_coefficient() 0 """
else:
def univariate_polynomial(self, R=None): """ Returns a univariate polynomial associated to this multivariate polynomial.
INPUT:
- ``R`` - (default: ``None``) PolynomialRing
If this polynomial is not in at most one variable, then a ``ValueError`` exception is raised. This is checked using the :meth:`is_univariate()` method. The new Polynomial is over the same base ring as the given ``MPolynomial`` and in the variable ``x`` if no ring ``R`` is provided.
EXAMPLES::
sage: R.<x, y> = QQ[] sage: f = 3*x^2 - 2*y + 7*x^2*y^2 + 5 sage: f.univariate_polynomial() Traceback (most recent call last): ... TypeError: polynomial must involve at most one variable sage: g = f.subs({x:10}); g 700*y^2 - 2*y + 305 sage: g.univariate_polynomial () 700*y^2 - 2*y + 305 sage: g.univariate_polynomial(PolynomialRing(QQ,'z')) 700*z^2 - 2*z + 305
Here's an example with a constant multivariate polynomial::
sage: g = R(1) sage: h = g.univariate_polynomial(); h 1 sage: h.parent() Univariate Polynomial Ring in x over Rational Field """ cdef long pTotDegMax
#construct ring if none else:
raise IndexError("list index("+str(pTotDeg)+" out of range(0-"+str(len(coefficients))+")")
def is_univariate(self): """ Return ``True`` if self is a univariate polynomial, that is if self contains only one variable.
EXAMPLES::
sage: P.<x,y,z> = GF(2)[] sage: f = x^2 + 1 sage: f.is_univariate() True sage: f = y*x^2 + 1 sage: f.is_univariate() False sage: f = P(0) sage: f.is_univariate() True """
def _variable_indices_(self, sort=True): """ Return the indices of all variables occurring in self. This index is the index as Sage uses them (starting at zero), not as SINGULAR uses them (starting at one).
INPUT:
- ``sort`` - specifies whether the indices shall be sorted
EXAMPLES::
sage: P.<x,y,z> = GF(2)[] sage: f = x*z^2 + z + 1 sage: f._variable_indices_() [0, 2]
""" cdef poly *p cdef int i else:
def variables(self): """ Return a tuple of all variables occurring in self.
EXAMPLES::
sage: P.<x,y,z> = GF(2)[] sage: f = x*z^2 + z + 1 sage: f.variables() (x, z) """ cdef poly *p cdef poly *v cdef int i
def variable(self, i=0): """
Return the i-th variable occurring in self. The index i is the index in ``self.variables()``.
EXAMPLES::
sage: P.<x,y,z> = GF(2)[] sage: f = x*z^2 + z + 1 sage: f.variables() (x, z) sage: f.variable(1) z """
def nvariables(self): """ Return the number variables in this polynomial.
EXAMPLES::
sage: P.<x,y,z> = PolynomialRing(GF(127)) sage: f = x*y + z sage: f.nvariables() 3 sage: f = x + y sage: f.nvariables() 2 """
cpdef is_constant(self): """ Return ``True`` if this polynomial is constant.
EXAMPLES::
sage: P.<x,y,z> = PolynomialRing(GF(127)) sage: x.is_constant() False sage: P(1).is_constant() True """
def lm(MPolynomial_libsingular self): """ Returns the lead monomial of self with respect to the term order of ``self.parent()``. In Sage a monomial is a product of variables in some power without a coefficient.
EXAMPLES::
sage: R.<x,y,z>=PolynomialRing(GF(7),3,order='lex') sage: f = x^1*y^2 + y^3*z^4 sage: f.lm() x*y^2 sage: f = x^3*y^2*z^4 + x^3*y^2*z^1 sage: f.lm() x^3*y^2*z^4
sage: R.<x,y,z>=PolynomialRing(QQ,3,order='deglex') sage: f = x^1*y^2*z^3 + x^3*y^2*z^0 sage: f.lm() x*y^2*z^3 sage: f = x^1*y^2*z^4 + x^1*y^1*z^5 sage: f.lm() x*y^2*z^4
sage: R.<x,y,z>=PolynomialRing(GF(127),3,order='degrevlex') sage: f = x^1*y^5*z^2 + x^4*y^1*z^3 sage: f.lm() x*y^5*z^2 sage: f = x^4*y^7*z^1 + x^4*y^2*z^3 sage: f.lm() x^4*y^7*z
""" cdef poly *_p
def lc(MPolynomial_libsingular self): """ Leading coefficient of this polynomial with respect to the term order of ``self.parent()``.
EXAMPLES::
sage: R.<x,y,z>=PolynomialRing(GF(7),3,order='lex') sage: f = 3*x^1*y^2 + 2*y^3*z^4 sage: f.lc() 3
sage: f = 5*x^3*y^2*z^4 + 4*x^3*y^2*z^1 sage: f.lc() 5 """
cdef poly *_p cdef number *_n
def lt(MPolynomial_libsingular self): """ Leading term of this polynomial. In Sage a term is a product of variables in some power and a coefficient.
EXAMPLES::
sage: R.<x,y,z>=PolynomialRing(GF(7),3,order='lex') sage: f = 3*x^1*y^2 + 2*y^3*z^4 sage: f.lt() 3*x*y^2
sage: f = 5*x^3*y^2*z^4 + 4*x^3*y^2*z^1 sage: f.lt() -2*x^3*y^2*z^4 """
def is_zero(self): """ Return ``True`` if this polynomial is zero.
EXAMPLES::
sage: P.<x,y> = PolynomialRing(QQ) sage: x.is_zero() False sage: (x-x).is_zero() True """ else:
def __nonzero__(self): """ EXAMPLES::
sage: P.<x,y> = PolynomialRing(QQ) sage: bool(x) # indirect doctest True sage: bool(x-x) False """ else:
cpdef _floordiv_(self, right): """ Perform division with remainder and return the quotient.
INPUT:
- ``right`` - something coercible to an MPolynomial_libsingular in ``self.parent()``
EXAMPLES::
sage: R.<x,y,z> = GF(32003)[] sage: f = y*x^2 + x + 1 sage: f//x x*y + 1 sage: f//y x^2
sage: P.<x,y> = ZZ[] sage: x//y 0 sage: (x+y)//y 1
sage: P.<x,y> = QQ[] sage: (x+y)//y 1 sage: (x)//y 0
sage: P.<x,y> = Zmod(1024)[] sage: (x+y)//x 1 sage: (x+y)//(2*x) Traceback (most recent call last): ... NotImplementedError: Division of multivariate polynomials over non fields by non-monomials not implemented. """ cdef MPolynomial_libsingular _self, _right cdef poly *quo cdef poly *temp cdef poly *p
raise ZeroDivisionError
raise NotImplementedError("Division of multivariate polynomials over prime fields with characteristic > 2^29 is not implemented.")
def factor(self, proof=True): """ Return the factorization of this polynomial.
INPUT:
- ``proof`` - ignored.
EXAMPLES::
sage: R.<x, y> = QQ[] sage: f = (x^3 + 2*y^2*x) * (x^2 + x + 1); f x^5 + 2*x^3*y^2 + x^4 + 2*x^2*y^2 + x^3 + 2*x*y^2 sage: F = f.factor() sage: F x * (x^2 + x + 1) * (x^2 + 2*y^2)
Next we factor the same polynomial, but over the finite field of order 3.::
sage: R.<x, y> = GF(3)[] sage: f = (x^3 + 2*y^2*x) * (x^2 + x + 1); f x^5 - x^3*y^2 + x^4 - x^2*y^2 + x^3 - x*y^2 sage: F = f.factor() sage: F # order is somewhat random (-1) * x * (-x + y) * (x + y) * (x - 1)^2
Next we factor a polynomial, but over a finite field of order 9.::
sage: K.<a> = GF(3^2) sage: R.<x, y> = K[] sage: f = (x^3 + 2*a*y^2*x) * (x^2 + x + 1); f x^5 + (-a)*x^3*y^2 + x^4 + (-a)*x^2*y^2 + x^3 + (-a)*x*y^2 sage: F = f.factor() sage: F ((-a)) * x * (x - 1)^2 * ((-a + 1)*x^2 + y^2) sage: f - F 0
Next we factor a polynomial over a number field.::
sage: p = var('p') sage: K.<s> = NumberField(p^3-2) sage: KXY.<x,y> = K[] sage: factor(x^3 - 2*y^3) (x + (-s)*y) * (x^2 + (s)*x*y + (s^2)*y^2) sage: k = (x^3-2*y^3)^5*(x+s*y)^2*(2/3 + s^2) sage: k.factor() ((s^2 + 2/3)) * (x + (s)*y)^2 * (x + (-s)*y)^5 * (x^2 + (s)*x*y + (s^2)*y^2)^5
This shows that ticket :trac:`2780` is fixed, i.e. that the unit part of the factorization is set correctly::
sage: x = var('x') sage: K.<a> = NumberField(x^2 + 1) sage: R.<y, z> = PolynomialRing(K) sage: f = 2*y^2 + 2*z^2 sage: F = f.factor(); F.unit() 2
Another example::
sage: R.<x,y,z> = GF(32003)[] sage: f = 9*(x-1)^2*(y+z) sage: f.factor() (9) * (y + z) * (x - 1)^2
sage: R.<x,w,v,u> = QQ['x','w','v','u'] sage: p = (4*v^4*u^2 - 16*v^2*u^4 + 16*u^6 - 4*v^4*u + 8*v^2*u^3 + v^4) sage: p.factor() (-2*v^2*u + 4*u^3 + v^2)^2 sage: R.<a,b,c,d> = QQ[] sage: f = (-2) * (a - d) * (-a + b) * (b - d) * (a - c) * (b - c) * (c - d) sage: F = f.factor(); F (-2) * (c - d) * (-b + c) * (b - d) * (-a + c) * (-a + b) * (a - d) sage: F[0][0] c - d sage: F.unit() -2
Constant elements are factorized in the base rings. ::
sage: P.<x,y> = ZZ[] sage: P(2^3*7).factor() 2^3 * 7 sage: P.<x,y> = GF(2)[] sage: P(1).factor() 1
Factorization for finite prime fields with characteristic `> 2^{29}` is not supported ::
sage: q = 1073741789 sage: T.<aa, bb> = PolynomialRing(GF(q)) sage: f = aa^2 + 12124343*bb*aa + 32434598*bb^2 sage: f.factor() Traceback (most recent call last): ... NotImplementedError: Factorization of multivariate polynomials over prime fields with characteristic > 2^29 is not implemented.
Factorization over the integers is now supported, see :trac:`17840`::
sage: P.<x,y> = PolynomialRing(ZZ) sage: f = 12 * (3*x*y + 4) * (5*x - 2) * (2*y + 7)^2 sage: f.factor() 2^2 * 3 * (2*y + 7)^2 * (5*x - 2) * (3*x*y + 4) sage: g = -12 * (x^2 - y^2) sage: g.factor() (-1) * 2^2 * 3 * (x - y) * (x + y) sage: factor(-4*x*y - 2*x + 2*y + 1) (-1) * (2*y + 1) * (2*x - 1)
Factorization over non-integral domains is not supported ::
sage: R.<x,y> = PolynomialRing(Zmod(4)) sage: f = (2*x + 1) * (x^2 + x + 1) sage: f.factor() Traceback (most recent call last): ... NotImplementedError: Factorization of multivariate polynomials over Ring of integers modulo 4 is not implemented.
TESTS:
This shows that :trac:`10270` is fixed::
sage: R.<x,y,z> = GF(3)[] sage: f = x^2*z^2+x*y*z-y^2 sage: f.factor() x^2*z^2 + x*y*z - y^2
This checks that :trac:`11838` is fixed::
sage: K = GF(4,'a') sage: a = K.gens()[0] sage: R.<x,y> = K[] sage: p=x^8*y^3 + x^2*y^9 + a*x^9 + a*x*y^4 sage: q=y^11 + (a)*y^10 + (a + 1)*x*y^3 sage: f = p*q sage: f.factor() x * y^3 * (y^8 + (a)*y^7 + (a + 1)*x) * (x^7*y^3 + x*y^9 + (a)*x^8 + (a)*y^4)
We test several examples which were known to return wrong results in the past (see :trac:`10902`)::
sage: R.<x,y> = GF(2)[] sage: p = x^3*y^7 + x^2*y^6 + x^2*y^3 sage: q = x^3*y^5 sage: f = p*q sage: p.factor()*q.factor() x^5 * y^8 * (x*y^4 + y^3 + 1) sage: f.factor() x^5 * y^8 * (x*y^4 + y^3 + 1) sage: f.factor().expand() == f True
::
sage: R.<x,y> = GF(2)[] sage: p=x^8 + y^8; q=x^2*y^4 + x sage: f=p*q sage: lf = f.factor() sage: f-lf 0
::
sage: R.<x,y> = GF(3)[] sage: p = -x*y^9 + x sage: q = -x^8*y^2 sage: f = p*q sage: f x^9*y^11 - x^9*y^2 sage: f.factor() y^2 * (y - 1)^9 * x^9 sage: f - f.factor() 0
::
sage: R.<x,y> = GF(5)[] sage: p=x^27*y^9 + x^32*y^3 + 2*x^20*y^10 - x^4*y^24 - 2*x^17*y sage: q=-2*x^10*y^24 + x^9*y^24 - 2*x^3*y^30 sage: f=p*q; f-f.factor() 0
::
sage: R.<x,y> = GF(7)[] sage: p=-3*x^47*y^24 sage: q=-3*x^47*y^37 - 3*x^24*y^49 + 2*x^56*y^8 + 3*x^29*y^15 - x^2*y^33 sage: f=p*q sage: f-f.factor() 0
The following examples used to give a Segmentation Fault, see :trac:`12918` and :trac:`13129`::
sage: R.<x,y> = GF(2)[] sage: f = x^6 + x^5 + y^5 + y^4 sage: f.factor() x^6 + x^5 + y^5 + y^4 sage: f = x^16*y + x^10*y + x^9*y + x^6*y + x^5 + x*y + y^2 sage: f.factor() x^16*y + x^10*y + x^9*y + x^6*y + x^5 + x*y + y^2
Test :trac:`12928`::
sage: R.<x,y> = GF(2)[] sage: p = x^2 + y^2 + x + 1 sage: q = x^4 + x^2*y^2 + y^4 + x*y^2 + x^2 + y^2 + 1 sage: factor(p*q) (x^2 + y^2 + x + 1) * (x^4 + x^2*y^2 + y^4 + x*y^2 + x^2 + y^2 + 1)
Check that :trac:`13770` is fixed::
sage: U.<y,t> = GF(2)[] sage: f = y*t^8 + y^5*t^2 + y*t^6 + t^7 + y^6 + y^5*t + y^2*t^4 + y^2*t^2 + y^2*t + t^3 + y^2 + t^2 sage: l = f.factor() sage: l[0][0]==t^2 + y + t + 1 or l[1][0]==t^2 + y + t + 1 True
The following used to sometimes take a very long time or get stuck, see :trac:`12846`. These 100 iterations should take less than 1 second::
sage: K.<a> = GF(4) sage: R.<x,y> = K[] sage: f = (a + 1)*x^145*y^84 + (a + 1)*x^205*y^17 + x^32*y^112 + x^92*y^45 sage: for i in range(100): ....: assert len(f.factor()) == 4
Test for :trac:`20435`::
sage: x,y = polygen(ZZ,'x,y') sage: p = x**2-y**2 sage: z = factor(p); z (x - y) * (x + y) sage: z[0][0].parent() Multivariate Polynomial Ring in x, y over Integer Ring
Test for :trac:`17680`::
sage: R.<a,r,v,n,g,f,h,o> = QQ[] sage: f = 248301045*a^2*r^10*n^2*o^10+570807000*a^2*r^9*n*o^9-137945025*a^2*r^8*n^2*o^8+328050000*a^2*r^8*o^8-253692000*a^2*r^7*n*o^7+30654450*a^2*r^6*n^2*o^6-109350000*a^2*r^6*o^6+42282000*a^2*r^5*n*o^5-3406050*a^2*r^4*n^2*o^4-22457088*a*r^2*v*n^2*o^6+12150000*a^2*r^4*o^4-3132000*a^2*r^3*n*o^3+189225*a^2*r^2*n^2*o^2+2495232*a*v*n^2*o^4-450000*a^2*r^2*o^2+87000*a^2*r*n*o-4205*a^2*n^2 sage: len(factor(f)) 4
Test for :trac:`17251`::
sage: R.<z,a,b> = PolynomialRing(QQ) sage: N = -a^4*z^8 + 2*a^2*b^2*z^8 - b^4*z^8 - 16*a^3*b*z^7 + 16*a*b^3*z^7 + 28*a^4*z^6 - 56*a^2*b^2*z^6 + 28*b^4*z^6 + 112*a^3*b*z^5 - 112*a*b^3*z^5 - 70*a^4*z^4 + 140*a^2*b^2*z^4 - 70*b^4*z^4 - 112*a^3*b*z^3 + 112*a*b^3*z^3 + 28*a^4*z^2 - 56*a^2*b^2*z^2 + 28*b^4*z^2 + 16*a^3*b*z - 16*a*b^3*z - a^4 + 2*a^2*b^2 - b^4 sage: N.factor() (-1) * (-a + b) * (a + b) * (-z^4*a + z^4*b - 4*z^3*a - 4*z^3*b + 6*z^2*a - 6*z^2*b + 4*z*a + 4*z*b - a + b) * (z^4*a + z^4*b - 4*z^3*a + 4*z^3*b - 6*z^2*a - 6*z^2*b + 4*z*a - 4*z*b + a + b) """ cdef poly *ptemp cdef intvec *iv cdef int *ivv cdef ideal *I cdef int i
# I make a temporary copy of the poly in self because singclap_factorize appears to modify it's parameter
def lift(self, I): """ given an ideal ``I = (f_1,...,f_r)`` and some ``g (== self)`` in ``I``, find ``s_1,...,s_r`` such that ``g = s_1 f_1 + ... + s_r f_r``.
A ``ValueError`` exception is raised if ``g (== self)`` does not belong to ``I``.
EXAMPLES::
sage: A.<x,y> = PolynomialRing(QQ,2,order='degrevlex') sage: I = A.ideal([x^10 + x^9*y^2, y^8 - x^2*y^7 ]) sage: f = x*y^13 + y^12 sage: M = f.lift(I) sage: M [y^7, x^7*y^2 + x^8 + x^5*y^3 + x^6*y + x^3*y^4 + x^4*y^2 + x*y^5 + x^2*y^3 + y^4] sage: sum( map( mul , zip( M, I.gens() ) ) ) == f True
Check that :trac:`13671` is fixed::
sage: R.<x1,x2> = QQ[] sage: I = R.ideal(x2**2 + x1 - 2, x1**2 - 1) sage: f = I.gen(0) + x2*I.gen(1) sage: f.lift(I) [1, x2] sage: (f+1).lift(I) Traceback (most recent call last): ... ValueError: polynomial is not in the ideal sage: f.lift(I) [1, x2]
TESTS:
Check that :trac:`13714` is fixed::
sage: R.<x1,x2> = QQ[] sage: I = R.ideal(x2**2 + x1 - 2, x1**2 - 1) sage: R.one().lift(I) Traceback (most recent call last): ... ValueError: polynomial is not in the ideal sage: foo = I.complete_primary_decomposition() # indirect doctest sage: foo[0][0] Ideal (x1 + 1, x2^2 - 3) of Multivariate Polynomial Ring in x1, x2 over Rational Field
""" global errorreported raise NotImplementedError("Lifting of multivariate polynomials over non-fields is not implemented.")
cdef ideal *_I cdef int j cdef ideal *res
try: f = parent._coerce_c(f) except TypeError as msg: id_Delete(&fI,r) id_Delete(&_I,r) raise TypeError(msg)
raise RuntimeError
def reduce(self,I): """ Return a remainder of this polynomial modulo the polynomials in ``I``.
INPUT:
- ``I`` - an ideal or a list/set/iterable of polynomials.
OUTPUT:
A polynomial ``r`` such that:
- ``self`` - ``r`` is in the ideal generated by ``I``.
- No term in ``r`` is divisible by any of the leading monomials of ``I``.
The result ``r`` is canonical if:
- ``I`` is an ideal, and Sage can compute a Groebner basis of it.
- ``I`` is a list/set/iterable that is a (strong) Groebner basis for the term order of ``self``. (A strong Groebner basis is such that for every leading term ``t`` of the ideal generated by ``I``, there exists an element ``g`` of ``I`` such that the leading term of ``g`` divides ``t``.)
The result ``r`` is implementation-dependent (and possibly order-dependent) otherwise. If ``I`` is an ideal and no Groebner basis can be computed, its list of generators ``I.gens()`` is used for the reduction.
EXAMPLES::
sage: P.<x,y,z> = QQ[] sage: f1 = -2 * x^2 + x^3 sage: f2 = -2 * y + x* y sage: f3 = -x^2 + y^2 sage: F = Ideal([f1,f2,f3]) sage: g = x*y - 3*x*y^2 sage: g.reduce(F) -6*y^2 + 2*y sage: g.reduce(F.gens()) -6*y^2 + 2*y
`\ZZ` is also supported. ::
sage: P.<x,y,z> = ZZ[] sage: f1 = -2 * x^2 + x^3 sage: f2 = -2 * y + x* y sage: f3 = -x^2 + y^2 sage: F = Ideal([f1,f2,f3]) sage: g = x*y - 3*x*y^2 sage: g.reduce(F) -6*y^2 + 2*y sage: g.reduce(F.gens()) -6*y^2 + 2*y
sage: f = 3*x sage: f.reduce([2*x,y]) 3*x
The reduction is not canonical when ``I`` is not a Groebner basis::
sage: A.<x,y> = QQ[] sage: (x+y).reduce([x+y, x-y]) 2*y sage: (x+y).reduce([x-y, x+y]) 0
""" cdef ideal *_I cdef poly *res
pass
try: f = parent._coerce_c(f) except TypeError as msg: id_Delete(&_I,r) raise TypeError(msg)
#the second parameter would be qring!
def divides(self, other): """ Return ``True`` if this polynomial divides ``other``.
EXAMPLES::
sage: R.<x,y,z> = QQ[] sage: p = 3*x*y + 2*y*z + x*z sage: q = x + y + z + 1 sage: r = p * q sage: p.divides(r) True sage: q.divides(p) False sage: r.divides(0) True sage: R.zero().divides(r) False sage: R.zero().divides(0) True """ cdef ideal *_I cdef poly *rem
except TypeError as msg: id_Delete(&_I,r) raise TypeError(msg)
rChangeCurrRing(r)
@coerce_binop def gcd(self, right, algorithm=None, **kwds): """ Return the greatest common divisor of self and right.
INPUT:
- ``right`` - polynomial - ``algorithm`` - ``ezgcd`` - EZGCD algorithm - ``modular`` - multi-modular algorithm (default) - ``**kwds`` - ignored
EXAMPLES::
sage: P.<x,y,z> = QQ[] sage: f = (x*y*z)^6 - 1 sage: g = (x*y*z)^4 - 1 sage: f.gcd(g) x^2*y^2*z^2 - 1 sage: GCD([x^3 - 3*x + 2, x^4 - 1, x^6 -1]) x - 1
sage: R.<x,y> = QQ[] sage: f = (x^3 + 2*y^2*x)^2 sage: g = x^2*y^2 sage: f.gcd(g) x^2
We compute a gcd over a finite field::
sage: F.<u> = GF(31^2) sage: R.<x,y,z> = F[] sage: p = x^3 + (1+u)*y^3 + z^3 sage: q = p^3 * (x - y + z*u) sage: gcd(p,q) x^3 + (u + 1)*y^3 + z^3 sage: gcd(p,q) # yes, twice -- tests that singular ring is properly set. x^3 + (u + 1)*y^3 + z^3
We compute a gcd over a number field::
sage: x = polygen(QQ) sage: F.<u> = NumberField(x^3 - 2) sage: R.<x,y,z> = F[] sage: p = x^3 + (1+u)*y^3 + z^3 sage: q = p^3 * (x - y + z*u) sage: gcd(p,q) x^3 + (u + 1)*y^3 + z^3
TESTS::
sage: Q.<x,y,z> = QQ[] sage: P.<x,y,z> = QQ[] sage: P(0).gcd(Q(0)) 0 sage: x.gcd(1) 1
sage: k.<a> = GF(9) sage: R.<x,y> = PolynomialRing(k) sage: f = R.change_ring(GF(3)).gen() sage: g = x+y sage: g.gcd(f) 1 sage: x.gcd(R.change_ring(GF(3)).gen()) x """ cdef MPolynomial_libsingular _right cdef poly *_res
Off(SW_USE_CHINREM_GCD) On(SW_USE_EZGCD) else:
#TODO: #raise NotImplementedError("GCD over rings not implemented.")
_right = self._parent._coerce_c(right) else:
cdef int count = singular_polynomial_length_bounded(self._poly,20) \
@coerce_binop def lcm(self, MPolynomial_libsingular g): """ Return the least common multiple of ``self`` and `g`.
EXAMPLES::
sage: P.<x,y,z> = QQ[] sage: p = (x+y)*(y+z) sage: q = (z^4+2)*(y+z) sage: lcm(p,q) x*y*z^4 + y^2*z^4 + x*z^5 + y*z^5 + 2*x*y + 2*y^2 + 2*x*z + 2*y*z
sage: P.<x,y,z> = ZZ[] sage: p = 2*(x+y)*(y+z) sage: q = 3*(z^4+2)*(y+z) sage: lcm(p,q) 6*x*y*z^4 + 6*y^2*z^4 + 6*x*z^5 + 6*y*z^5 + 12*x*y + 12*y^2 + 12*x*z + 12*y*z
sage: r.<x,y> = PolynomialRing(GF(2**8, 'a'), 2) sage: a = r.base_ring().0 sage: f = (a^2+a)*x^2*y + (a^4+a^3+a)*y + a^5 sage: f.lcm(x^4) (a^2 + a)*x^6*y + (a^4 + a^3 + a)*x^4*y + (a^5)*x^4
sage: w = var('w') sage: r.<x,y> = PolynomialRing(NumberField(w^4 + 1, 'a'), 2) sage: a = r.base_ring().0 sage: f = (a^2+a)*x^2*y + (a^4+a^3+a)*y + a^5 sage: f.lcm(x^4) (a^2 + a)*x^6*y + (a^3 + a - 1)*x^4*y + (-a)*x^4 """ cdef poly *ret cdef poly *prod cdef poly *gcd cdef MPolynomial_libsingular _g
else: raise TypeError("LCM over non-integral domains not available.")
_g = self._parent._coerce_c(g) else:
raise NotImplementedError("LCM of multivariate polynomials over prime fields with characteristic > 2^29 is not implemented.")
cdef int count = singular_polynomial_length_bounded(self._poly,20) \ sig_on() sig_off()
def is_squarefree(self): """ Return ``True`` if this polynomial is square free.
EXAMPLES::
sage: P.<x,y,z> = PolynomialRing(QQ) sage: f= x^2 + 2*x*y + 1/2*z sage: f.is_squarefree() True sage: h = f^2 sage: h.is_squarefree() False """ # TODO: Use Singular (4.x) intrinsics. (Temporary solution from #17254.)
@coerce_binop def quo_rem(self, MPolynomial_libsingular right): """ Returns quotient and remainder of self and right.
EXAMPLES::
sage: R.<x,y> = QQ[] sage: f = y*x^2 + x + 1 sage: f.quo_rem(x) (x*y + 1, 1) sage: f.quo_rem(y) (x^2, x + 1)
sage: R.<x,y> = ZZ[] sage: f = 2*y*x^2 + x + 1 sage: f.quo_rem(x) (2*x*y + 1, 1) sage: f.quo_rem(y) (2*x^2, x + 1) sage: f.quo_rem(3*x) (2*x*y + 1, -4*x^2*y - 2*x + 1)
TESTS::
sage: R.<x,y> = QQ[] sage: R(0).quo_rem(R(1)) (0, 0) sage: R(1).quo_rem(R(0)) Traceback (most recent call last): ... ZeroDivisionError
""" cdef poly *quo cdef poly *rem
py_quo = self//right py_rem = self - right*py_quo return py_quo, py_rem
raise NotImplementedError("Division of multivariate polynomials over prime fields with characteristic > 2^29 is not implemented.")
def _singular_init_(self, singular=singular_default): """ Return a SINGULAR (as in the computer algebra system) string representation for this element.
INPUT:
- ``singular`` - interpreter (default: ``singular_default``)
- ``have_ring`` - should the correct ring not be set in SINGULAR first (default: ``False``)
EXAMPLES::
sage: P.<x,y,z> = PolynomialRing(GF(127),3) sage: x._singular_init_() 'x' sage: (x^2+37*y+128)._singular_init_() 'x2+37y+1'
TESTS::
sage: P(0)._singular_init_() '0' """
def sub_m_mul_q(self, MPolynomial_libsingular m, MPolynomial_libsingular q): """ Return ``self - m*q``, where ``m`` must be a monomial and ``q`` a polynomial.
INPUT:
- ``m`` - a monomial - ``q`` - a polynomial
EXAMPLES::
sage: P.<x,y,z>=PolynomialRing(QQ,3) sage: x.sub_m_mul_q(y,z) -y*z + x
TESTS::
sage: Q.<x,y,z>=PolynomialRing(QQ,3) sage: P.<x,y,z>=PolynomialRing(QQ,3) sage: P(0).sub_m_mul_q(P(0),P(1)) 0 sage: x.sub_m_mul_q(Q.gen(1),Q.gen(2)) -y*z + x """
m = self._parent._coerce_c(m) q = self._parent._coerce_c(q)
raise ArithmeticError("m must be a monomial.")
def _macaulay2_(self, macaulay2=macaulay2): """ Return a Macaulay2 string representation of this polynomial.
.. NOTE::
Two identical rings are not canonically isomorphic in M2, so we require the user to explicitly set the ring, since there is no way to know if the ring has been set or not, and setting it twice screws everything up.
EXAMPLES::
sage: R.<x,y> = PolynomialRing(GF(7), 2) sage: f = (x^3 + 2*y^2*x)^7; f # indirect doctest x^21 + 2*x^7*y^14
sage: h = macaulay2(f); h # optional - macaulay2 21 7 14 x + 2x y sage: k = macaulay2(x+y); k # optional - macaulay2 x + y sage: k + h # optional - macaulay2 21 7 14 x + 2x y + x + y sage: R(h) # optional - macaulay2 x^21 + 2*x^7*y^14 sage: R(h^20) == f^20 # optional - macaulay2 True """ m2_parent = macaulay2(self.parent()) macaulay2.use(m2_parent) return macaulay2(repr(self))
def add_m_mul_q(self, MPolynomial_libsingular m, MPolynomial_libsingular q): """ Return ``self + m*q``, where ``m`` must be a monomial and ``q`` a polynomial.
INPUT:
- ``m`` - a monomial - ``q`` - a polynomial
EXAMPLES::
sage: P.<x,y,z>=PolynomialRing(QQ,3) sage: x.add_m_mul_q(y,z) y*z + x
TESTS::
sage: R.<x,y,z>=PolynomialRing(QQ,3) sage: P.<x,y,z>=PolynomialRing(QQ,3) sage: P(0).add_m_mul_q(P(0),P(1)) 0 sage: x.add_m_mul_q(R.gen(),R.gen(1)) x*y + x """
m = self._parent._coerce_c(m) q = self._parent._coerce_c(q)
raise ArithmeticError("m must be a monomial.")
def __reduce__(self): """ Serialize this polynomial.
EXAMPLES::
sage: P.<x,y,z> = PolynomialRing(QQ,3, order='degrevlex') sage: f = 27/113 * x^2 + y*z + 1/2 sage: f == loads(dumps(f)) True
sage: P = PolynomialRing(GF(127),3,names='abc') sage: a,b,c = P.gens() sage: f = 57 * a^2*b + 43 * c + 1 sage: f == loads(dumps(f)) True
TESTS:
Verify that :trac:`9220` is fixed.
sage: R=QQ['x'] sage: S=QQ['x','y'] sage: h=S.0^2 sage: parent(h(R.0,0)) Univariate Polynomial Ring in x over Rational Field """
def _im_gens_(self, codomain, im_gens): """ INPUT:
- ``codomain`` - ``im_gens``
EXAMPLES::
sage: R.<x,y> = PolynomialRing(QQ, 2) sage: f = R.hom([y,x], R) sage: f(x^2 + 3*y^5) 3*x^5 + y^2
sage: R.<a,b,c,d> = QQ[] sage: S.<u> = QQ[] sage: h = R.hom([0,0,0,u], S) # indirect doctest sage: h((a+d)^3) u^3 """ #TODO: very slow return codomain._coerce_(self)
def _derivative(self, MPolynomial_libsingular var): """ Differentiates this polynomial with respect to the provided variable. This is completely symbolic so it is also defined over finite fields.
INPUT:
- ``variable`` - the derivative is taken with respect to variable
- ``have_ring`` - ignored, accepted for compatibility reasons
.. NOTE:: See also :meth:`derivative`
EXAMPLES::
sage: R.<x,y> = PolynomialRing(QQ,2) sage: f = 3*x^3*y^2 + 5*y^2 + 3*x + 2 sage: f._derivative(x) 9*x^2*y^2 + 3 sage: f._derivative(y) 6*x^3*y + 10*y
The derivative is also defined over finite fields::
sage: R.<x,y> = PolynomialRing(GF(2**8, 'a'),2) sage: f = x^3*y^2 + y^2 + x + 2 sage: f._derivative(x) x^2*y^2 + 1
""" raise ValueError("you must specify which variable with respect to which to differentiate")
cdef int i, var_i
cdef poly *p raise TypeError("provided variable is not in same ring as self")
else: raise TypeError("provided variable is not univariate")
raise TypeError("provided variable is constant")
def integral(self, MPolynomial_libsingular var): """ Integrates this polynomial with respect to the provided variable.
One requires that `\QQ` is contained in the ring.
INPUT:
- ``variable`` - the integral is taken with respect to variable
EXAMPLES::
sage: R.<x, y> = PolynomialRing(QQ, 2) sage: f = 3*x^3*y^2 + 5*y^2 + 3*x + 2 sage: f.integral(x) 3/4*x^4*y^2 + 5*x*y^2 + 3/2*x^2 + 2*x sage: f.integral(y) x^3*y^3 + 5/3*y^3 + 3*x*y + 2*y
Check that :trac:`15896` is solved::
sage: s = x+y sage: s.integral(x)+x 1/2*x^2 + x*y + x sage: s.integral(x)*s 1/2*x^3 + 3/2*x^2*y + x*y^2
TESTS::
sage: z, w = polygen(QQ, 'z, w') sage: f.integral(z) Traceback (most recent call last): ... TypeError: the variable is not in the same ring as self
sage: f.integral(y**2) Traceback (most recent call last): ... TypeError: not a variable in the same ring as self
sage: x,y = polygen(ZZ,'x,y') sage: y.integral(x) Traceback (most recent call last): ... TypeError: the ring must contain the rational numbers """ cdef int index
cdef poly *_p cdef poly *mon rChangeCurrRing(_ring)
def resultant(self, MPolynomial_libsingular other, variable=None): """ Compute the resultant of this polynomial and the first argument with respect to the variable given as the second argument.
If a second argument is not provide the first variable of the parent is chosen.
INPUT:
- ``other`` - polynomial
- ``variable`` - optional variable (default: ``None``)
EXAMPLES::
sage: P.<x,y> = PolynomialRing(QQ,2) sage: a = x+y sage: b = x^3-y^3 sage: c = a.resultant(b); c -2*y^3 sage: d = a.resultant(b,y); d 2*x^3
The SINGULAR example::
sage: R.<x,y,z> = PolynomialRing(GF(32003),3) sage: f = 3 * (x+2)^3 + y sage: g = x+y+z sage: f.resultant(g,x) 3*y^3 + 9*y^2*z + 9*y*z^2 + 3*z^3 - 18*y^2 - 36*y*z - 18*z^2 + 35*y + 36*z - 24
Resultants are also supported over the Integers::
sage: R.<x,y,a,b,u>=PolynomialRing(ZZ, 5, order='lex') sage: r = (x^4*y^2+x^2*y-y).resultant(x*y-y*a-x*b+a*b+u,x) sage: r y^6*a^4 - 4*y^5*a^4*b - 4*y^5*a^3*u + y^5*a^2 - y^5 + 6*y^4*a^4*b^2 + 12*y^4*a^3*b*u - 4*y^4*a^2*b + 6*y^4*a^2*u^2 - 2*y^4*a*u + 4*y^4*b - 4*y^3*a^4*b^3 - 12*y^3*a^3*b^2*u + 6*y^3*a^2*b^2 - 12*y^3*a^2*b*u^2 + 6*y^3*a*b*u - 4*y^3*a*u^3 - 6*y^3*b^2 + y^3*u^2 + y^2*a^4*b^4 + 4*y^2*a^3*b^3*u - 4*y^2*a^2*b^3 + 6*y^2*a^2*b^2*u^2 - 6*y^2*a*b^2*u + 4*y^2*a*b*u^3 + 4*y^2*b^3 - 2*y^2*b*u^2 + y^2*u^4 + y*a^2*b^4 + 2*y*a*b^3*u - y*b^4 + y*b^2*u^2
TESTS::
sage: P.<x,y> = PolynomialRing(QQ, order='degrevlex') sage: a = x+y sage: b = x^3-y^3 sage: c = a.resultant(b); c -2*y^3 sage: d = a.resultant(b,y); d 2*x^3
sage: P.<x,y> = PolynomialRing(ZZ,2) sage: f = x+y sage: g=y^2+x sage: f.resultant(g,y) x^2 + x """ cdef poly *rt
raise TypeError("first parameter needs to be an element of self.parent()")
raise TypeError("second parameter needs to be an element of self.parent() or None")
raise NotImplementedError("Resultants of multivariate polynomials over prime fields with characteristic > 2^29 is not implemented.")
raise ValueError("Resultants require base fields or integer base ring.")
cdef int count = singular_polynomial_length_bounded(self._poly,20) \
def discriminant(self,variable): """ Returns the discriminant of self with respect to the given variable.
INPUT:
- ``variable`` - The variable with respect to which we compute the discriminant
OUTPUT:
- An element of the base ring of the polynomial ring.
EXAMPLES::
sage: R.<x,y,z>=QQ[] sage: f=4*x*y^2 + 1/4*x*y*z + 3/2*x*z^2 - 1/2*z^2 sage: f.discriminant(x) 1 sage: f.discriminant(y) -383/16*x^2*z^2 + 8*x*z^2 sage: f.discriminant(z) -383/16*x^2*y^2 + 8*x*y^2
Note that, unlike the univariate case, the result lives in the same ring as the polynomial::
sage: R.<x,y>=QQ[] sage: f=x^5*y+3*x^2*y^2-2*x+y-1 sage: f.discriminant(y) x^10 + 2*x^5 + 24*x^3 + 12*x^2 + 1 sage: f.polynomial(y).discriminant() x^10 + 2*x^5 + 24*x^3 + 12*x^2 + 1 sage: f.discriminant(y).parent()==f.polynomial(y).discriminant().parent() False
AUTHOR: Miguel Marco """ return self.parent().zero()
def coefficients(self): """ Return the nonzero coefficients of this polynomial in a list. The returned list is decreasingly ordered by the term ordering of the parent.
EXAMPLES::
sage: R.<x,y,z> = PolynomialRing(QQ, order='degrevlex') sage: f=23*x^6*y^7 + x^3*y+6*x^7*z sage: f.coefficients() [23, 6, 1]
sage: R.<x,y,z> = PolynomialRing(QQ, order='lex') sage: f=23*x^6*y^7 + x^3*y+6*x^7*z sage: f.coefficients() [6, 23, 1]
AUTHOR:
- Didier Deshommes """ cdef poly *p
def gradient(self): """ Return a list of partial derivatives of this polynomial, ordered by the variables of the parent.
EXAMPLES::
sage: P.<x,y,z> = PolynomialRing(QQ,3) sage: f= x*y + 1 sage: f.gradient() [y, x, 0] """ cdef int k
def numerator(self): """ Return a numerator of self computed as self * self.denominator()
If the base_field of self is the Rational Field then the numerator is a polynomial whose base_ring is the Integer Ring, this is done for compatibility to the univariate case.
.. warning::
This is not the numerator of the rational function defined by self, which would always be self since self is a polynomial.
EXAMPLES:
First we compute the numerator of a polynomial with integer coefficients, which is of course self.
::
sage: R.<x, y> = ZZ[] sage: f = x^3 + 17*y + 1 sage: f.numerator() x^3 + 17*y + 1 sage: f == f.numerator() True
Next we compute the numerator of a polynomial with rational coefficients.
::
sage: R.<x,y> = PolynomialRing(QQ) sage: f = (1/17)*x^19 - (2/3)*y + 1/3; f 1/17*x^19 - 2/3*y + 1/3 sage: f.numerator() 3*x^19 - 34*y + 17 sage: f == f.numerator() False sage: f.numerator().base_ring() Integer Ring
We check that the computation of numerator and denominator is valid.
::
sage: K=QQ['x,y'] sage: f=K.random_element() sage: f.numerator() / f.denominator() == f True
The following tests against a bug fixed in :trac:`11780`::
sage: P.<foo,bar> = ZZ[] sage: Q.<foo,bar> = QQ[] sage: f = Q.random_element() sage: f.numerator().parent() is P True """ #This part is for compatibility with the univariate case, #where the numerator of a polynomial over RationalField #is a polynomial over IntegerRing # # Trac ticket #11780: Create the polynomial ring over # the integers using the (cached) polynomial ring constructor: else:
def unpickle_MPolynomial_libsingular(MPolynomialRing_libsingular R, d): """ Deserialize an ``MPolynomial_libsingular`` object
INPUT:
- ``R`` - the base ring - ``d`` - a Python dictionary as returned by :meth:`MPolynomial_libsingular.dict`
EXAMPLES::
sage: P.<x,y> = PolynomialRing(QQ) sage: loads(dumps(x)) == x # indirect doctest True """ cdef poly *m cdef poly *p cdef int _i, _e p_Delete(&p, r) p_Delete(&m, r) raise TypeError("variable index too big") p_Delete(&p, r) p_Delete(&m, r) raise TypeError("exponent too small")
cdef inline poly *addwithcarry(poly *tempvector, poly *maxvector, int pos, ring *_ring): else:
cdef inline MPolynomial_libsingular new_MP(MPolynomialRing_libsingular parent, poly *juice): """ Construct MPolynomial_libsingular from parent and SINGULAR poly.
INPUT:
- ``parent`` -- a :class:`MPolynomialRing_libsingular`` instance. The parent of the polynomial to create.
- ``juice`` -- a pointer to a Singular ``poly`` C struct.
OUTPUT:
A Python object :class:`MPolynomial_libsingular`.
The ownership of ``juice`` will be transferred to the Python object. You must not free it yourself. Singular will modify the polynomial, so it is your responsibility to make a copy if the Singular data structure is used elsewhere. """
cdef poly *MPolynomial_libsingular_get_element(object self): |