rings.py 71 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595
  1. """Sparse polynomial rings. """
  2. from __future__ import annotations
  3. from typing import Any
  4. from operator import add, mul, lt, le, gt, ge
  5. from functools import reduce
  6. from types import GeneratorType
  7. from sympy.core.expr import Expr
  8. from sympy.core.numbers import igcd, oo
  9. from sympy.core.symbol import Symbol, symbols as _symbols
  10. from sympy.core.sympify import CantSympify, sympify
  11. from sympy.ntheory.multinomial import multinomial_coefficients
  12. from sympy.polys.compatibility import IPolys
  13. from sympy.polys.constructor import construct_domain
  14. from sympy.polys.densebasic import dmp_to_dict, dmp_from_dict
  15. from sympy.polys.domains.domainelement import DomainElement
  16. from sympy.polys.domains.polynomialring import PolynomialRing
  17. from sympy.polys.heuristicgcd import heugcd
  18. from sympy.polys.monomials import MonomialOps
  19. from sympy.polys.orderings import lex
  20. from sympy.polys.polyerrors import (
  21. CoercionFailed, GeneratorsError,
  22. ExactQuotientFailed, MultivariatePolynomialError)
  23. from sympy.polys.polyoptions import (Domain as DomainOpt,
  24. Order as OrderOpt, build_options)
  25. from sympy.polys.polyutils import (expr_from_dict, _dict_reorder,
  26. _parallel_dict_from_expr)
  27. from sympy.printing.defaults import DefaultPrinting
  28. from sympy.utilities import public, subsets
  29. from sympy.utilities.iterables import is_sequence
  30. from sympy.utilities.magic import pollute
  31. @public
  32. def ring(symbols, domain, order=lex):
  33. """Construct a polynomial ring returning ``(ring, x_1, ..., x_n)``.
  34. Parameters
  35. ==========
  36. symbols : str
  37. Symbol/Expr or sequence of str, Symbol/Expr (non-empty)
  38. domain : :class:`~.Domain` or coercible
  39. order : :class:`~.MonomialOrder` or coercible, optional, defaults to ``lex``
  40. Examples
  41. ========
  42. >>> from sympy.polys.rings import ring
  43. >>> from sympy.polys.domains import ZZ
  44. >>> from sympy.polys.orderings import lex
  45. >>> R, x, y, z = ring("x,y,z", ZZ, lex)
  46. >>> R
  47. Polynomial ring in x, y, z over ZZ with lex order
  48. >>> x + y + z
  49. x + y + z
  50. >>> type(_)
  51. <class 'sympy.polys.rings.PolyElement'>
  52. """
  53. _ring = PolyRing(symbols, domain, order)
  54. return (_ring,) + _ring.gens
  55. @public
  56. def xring(symbols, domain, order=lex):
  57. """Construct a polynomial ring returning ``(ring, (x_1, ..., x_n))``.
  58. Parameters
  59. ==========
  60. symbols : str
  61. Symbol/Expr or sequence of str, Symbol/Expr (non-empty)
  62. domain : :class:`~.Domain` or coercible
  63. order : :class:`~.MonomialOrder` or coercible, optional, defaults to ``lex``
  64. Examples
  65. ========
  66. >>> from sympy.polys.rings import xring
  67. >>> from sympy.polys.domains import ZZ
  68. >>> from sympy.polys.orderings import lex
  69. >>> R, (x, y, z) = xring("x,y,z", ZZ, lex)
  70. >>> R
  71. Polynomial ring in x, y, z over ZZ with lex order
  72. >>> x + y + z
  73. x + y + z
  74. >>> type(_)
  75. <class 'sympy.polys.rings.PolyElement'>
  76. """
  77. _ring = PolyRing(symbols, domain, order)
  78. return (_ring, _ring.gens)
  79. @public
  80. def vring(symbols, domain, order=lex):
  81. """Construct a polynomial ring and inject ``x_1, ..., x_n`` into the global namespace.
  82. Parameters
  83. ==========
  84. symbols : str
  85. Symbol/Expr or sequence of str, Symbol/Expr (non-empty)
  86. domain : :class:`~.Domain` or coercible
  87. order : :class:`~.MonomialOrder` or coercible, optional, defaults to ``lex``
  88. Examples
  89. ========
  90. >>> from sympy.polys.rings import vring
  91. >>> from sympy.polys.domains import ZZ
  92. >>> from sympy.polys.orderings import lex
  93. >>> vring("x,y,z", ZZ, lex)
  94. Polynomial ring in x, y, z over ZZ with lex order
  95. >>> x + y + z # noqa:
  96. x + y + z
  97. >>> type(_)
  98. <class 'sympy.polys.rings.PolyElement'>
  99. """
  100. _ring = PolyRing(symbols, domain, order)
  101. pollute([ sym.name for sym in _ring.symbols ], _ring.gens)
  102. return _ring
  103. @public
  104. def sring(exprs, *symbols, **options):
  105. """Construct a ring deriving generators and domain from options and input expressions.
  106. Parameters
  107. ==========
  108. exprs : :class:`~.Expr` or sequence of :class:`~.Expr` (sympifiable)
  109. symbols : sequence of :class:`~.Symbol`/:class:`~.Expr`
  110. options : keyword arguments understood by :class:`~.Options`
  111. Examples
  112. ========
  113. >>> from sympy import sring, symbols
  114. >>> x, y, z = symbols("x,y,z")
  115. >>> R, f = sring(x + 2*y + 3*z)
  116. >>> R
  117. Polynomial ring in x, y, z over ZZ with lex order
  118. >>> f
  119. x + 2*y + 3*z
  120. >>> type(_)
  121. <class 'sympy.polys.rings.PolyElement'>
  122. """
  123. single = False
  124. if not is_sequence(exprs):
  125. exprs, single = [exprs], True
  126. exprs = list(map(sympify, exprs))
  127. opt = build_options(symbols, options)
  128. # TODO: rewrite this so that it doesn't use expand() (see poly()).
  129. reps, opt = _parallel_dict_from_expr(exprs, opt)
  130. if opt.domain is None:
  131. coeffs = sum([ list(rep.values()) for rep in reps ], [])
  132. opt.domain, coeffs_dom = construct_domain(coeffs, opt=opt)
  133. coeff_map = dict(zip(coeffs, coeffs_dom))
  134. reps = [{m: coeff_map[c] for m, c in rep.items()} for rep in reps]
  135. _ring = PolyRing(opt.gens, opt.domain, opt.order)
  136. polys = list(map(_ring.from_dict, reps))
  137. if single:
  138. return (_ring, polys[0])
  139. else:
  140. return (_ring, polys)
  141. def _parse_symbols(symbols):
  142. if isinstance(symbols, str):
  143. return _symbols(symbols, seq=True) if symbols else ()
  144. elif isinstance(symbols, Expr):
  145. return (symbols,)
  146. elif is_sequence(symbols):
  147. if all(isinstance(s, str) for s in symbols):
  148. return _symbols(symbols)
  149. elif all(isinstance(s, Expr) for s in symbols):
  150. return symbols
  151. raise GeneratorsError("expected a string, Symbol or expression or a non-empty sequence of strings, Symbols or expressions")
  152. _ring_cache: dict[Any, Any] = {}
  153. class PolyRing(DefaultPrinting, IPolys):
  154. """Multivariate distributed polynomial ring. """
  155. def __new__(cls, symbols, domain, order=lex):
  156. symbols = tuple(_parse_symbols(symbols))
  157. ngens = len(symbols)
  158. domain = DomainOpt.preprocess(domain)
  159. order = OrderOpt.preprocess(order)
  160. _hash_tuple = (cls.__name__, symbols, ngens, domain, order)
  161. obj = _ring_cache.get(_hash_tuple)
  162. if obj is None:
  163. if domain.is_Composite and set(symbols) & set(domain.symbols):
  164. raise GeneratorsError("polynomial ring and it's ground domain share generators")
  165. obj = object.__new__(cls)
  166. obj._hash_tuple = _hash_tuple
  167. obj._hash = hash(_hash_tuple)
  168. obj.dtype = type("PolyElement", (PolyElement,), {"ring": obj})
  169. obj.symbols = symbols
  170. obj.ngens = ngens
  171. obj.domain = domain
  172. obj.order = order
  173. obj.zero_monom = (0,)*ngens
  174. obj.gens = obj._gens()
  175. obj._gens_set = set(obj.gens)
  176. obj._one = [(obj.zero_monom, domain.one)]
  177. if ngens:
  178. # These expect monomials in at least one variable
  179. codegen = MonomialOps(ngens)
  180. obj.monomial_mul = codegen.mul()
  181. obj.monomial_pow = codegen.pow()
  182. obj.monomial_mulpow = codegen.mulpow()
  183. obj.monomial_ldiv = codegen.ldiv()
  184. obj.monomial_div = codegen.div()
  185. obj.monomial_lcm = codegen.lcm()
  186. obj.monomial_gcd = codegen.gcd()
  187. else:
  188. monunit = lambda a, b: ()
  189. obj.monomial_mul = monunit
  190. obj.monomial_pow = monunit
  191. obj.monomial_mulpow = lambda a, b, c: ()
  192. obj.monomial_ldiv = monunit
  193. obj.monomial_div = monunit
  194. obj.monomial_lcm = monunit
  195. obj.monomial_gcd = monunit
  196. if order is lex:
  197. obj.leading_expv = max
  198. else:
  199. obj.leading_expv = lambda f: max(f, key=order)
  200. for symbol, generator in zip(obj.symbols, obj.gens):
  201. if isinstance(symbol, Symbol):
  202. name = symbol.name
  203. if not hasattr(obj, name):
  204. setattr(obj, name, generator)
  205. _ring_cache[_hash_tuple] = obj
  206. return obj
  207. def _gens(self):
  208. """Return a list of polynomial generators. """
  209. one = self.domain.one
  210. _gens = []
  211. for i in range(self.ngens):
  212. expv = self.monomial_basis(i)
  213. poly = self.zero
  214. poly[expv] = one
  215. _gens.append(poly)
  216. return tuple(_gens)
  217. def __getnewargs__(self):
  218. return (self.symbols, self.domain, self.order)
  219. def __getstate__(self):
  220. state = self.__dict__.copy()
  221. del state["leading_expv"]
  222. for key, value in state.items():
  223. if key.startswith("monomial_"):
  224. del state[key]
  225. return state
  226. def __hash__(self):
  227. return self._hash
  228. def __eq__(self, other):
  229. return isinstance(other, PolyRing) and \
  230. (self.symbols, self.domain, self.ngens, self.order) == \
  231. (other.symbols, other.domain, other.ngens, other.order)
  232. def __ne__(self, other):
  233. return not self == other
  234. def clone(self, symbols=None, domain=None, order=None):
  235. return self.__class__(symbols or self.symbols, domain or self.domain, order or self.order)
  236. def monomial_basis(self, i):
  237. """Return the ith-basis element. """
  238. basis = [0]*self.ngens
  239. basis[i] = 1
  240. return tuple(basis)
  241. @property
  242. def zero(self):
  243. return self.dtype()
  244. @property
  245. def one(self):
  246. return self.dtype(self._one)
  247. def domain_new(self, element, orig_domain=None):
  248. return self.domain.convert(element, orig_domain)
  249. def ground_new(self, coeff):
  250. return self.term_new(self.zero_monom, coeff)
  251. def term_new(self, monom, coeff):
  252. coeff = self.domain_new(coeff)
  253. poly = self.zero
  254. if coeff:
  255. poly[monom] = coeff
  256. return poly
  257. def ring_new(self, element):
  258. if isinstance(element, PolyElement):
  259. if self == element.ring:
  260. return element
  261. elif isinstance(self.domain, PolynomialRing) and self.domain.ring == element.ring:
  262. return self.ground_new(element)
  263. else:
  264. raise NotImplementedError("conversion")
  265. elif isinstance(element, str):
  266. raise NotImplementedError("parsing")
  267. elif isinstance(element, dict):
  268. return self.from_dict(element)
  269. elif isinstance(element, list):
  270. try:
  271. return self.from_terms(element)
  272. except ValueError:
  273. return self.from_list(element)
  274. elif isinstance(element, Expr):
  275. return self.from_expr(element)
  276. else:
  277. return self.ground_new(element)
  278. __call__ = ring_new
  279. def from_dict(self, element, orig_domain=None):
  280. domain_new = self.domain_new
  281. poly = self.zero
  282. for monom, coeff in element.items():
  283. coeff = domain_new(coeff, orig_domain)
  284. if coeff:
  285. poly[monom] = coeff
  286. return poly
  287. def from_terms(self, element, orig_domain=None):
  288. return self.from_dict(dict(element), orig_domain)
  289. def from_list(self, element):
  290. return self.from_dict(dmp_to_dict(element, self.ngens-1, self.domain))
  291. def _rebuild_expr(self, expr, mapping):
  292. domain = self.domain
  293. def _rebuild(expr):
  294. generator = mapping.get(expr)
  295. if generator is not None:
  296. return generator
  297. elif expr.is_Add:
  298. return reduce(add, list(map(_rebuild, expr.args)))
  299. elif expr.is_Mul:
  300. return reduce(mul, list(map(_rebuild, expr.args)))
  301. else:
  302. # XXX: Use as_base_exp() to handle Pow(x, n) and also exp(n)
  303. # XXX: E can be a generator e.g. sring([exp(2)]) -> ZZ[E]
  304. base, exp = expr.as_base_exp()
  305. if exp.is_Integer and exp > 1:
  306. return _rebuild(base)**int(exp)
  307. else:
  308. return self.ground_new(domain.convert(expr))
  309. return _rebuild(sympify(expr))
  310. def from_expr(self, expr):
  311. mapping = dict(list(zip(self.symbols, self.gens)))
  312. try:
  313. poly = self._rebuild_expr(expr, mapping)
  314. except CoercionFailed:
  315. raise ValueError("expected an expression convertible to a polynomial in %s, got %s" % (self, expr))
  316. else:
  317. return self.ring_new(poly)
  318. def index(self, gen):
  319. """Compute index of ``gen`` in ``self.gens``. """
  320. if gen is None:
  321. if self.ngens:
  322. i = 0
  323. else:
  324. i = -1 # indicate impossible choice
  325. elif isinstance(gen, int):
  326. i = gen
  327. if 0 <= i and i < self.ngens:
  328. pass
  329. elif -self.ngens <= i and i <= -1:
  330. i = -i - 1
  331. else:
  332. raise ValueError("invalid generator index: %s" % gen)
  333. elif isinstance(gen, self.dtype):
  334. try:
  335. i = self.gens.index(gen)
  336. except ValueError:
  337. raise ValueError("invalid generator: %s" % gen)
  338. elif isinstance(gen, str):
  339. try:
  340. i = self.symbols.index(gen)
  341. except ValueError:
  342. raise ValueError("invalid generator: %s" % gen)
  343. else:
  344. raise ValueError("expected a polynomial generator, an integer, a string or None, got %s" % gen)
  345. return i
  346. def drop(self, *gens):
  347. """Remove specified generators from this ring. """
  348. indices = set(map(self.index, gens))
  349. symbols = [ s for i, s in enumerate(self.symbols) if i not in indices ]
  350. if not symbols:
  351. return self.domain
  352. else:
  353. return self.clone(symbols=symbols)
  354. def __getitem__(self, key):
  355. symbols = self.symbols[key]
  356. if not symbols:
  357. return self.domain
  358. else:
  359. return self.clone(symbols=symbols)
  360. def to_ground(self):
  361. # TODO: should AlgebraicField be a Composite domain?
  362. if self.domain.is_Composite or hasattr(self.domain, 'domain'):
  363. return self.clone(domain=self.domain.domain)
  364. else:
  365. raise ValueError("%s is not a composite domain" % self.domain)
  366. def to_domain(self):
  367. return PolynomialRing(self)
  368. def to_field(self):
  369. from sympy.polys.fields import FracField
  370. return FracField(self.symbols, self.domain, self.order)
  371. @property
  372. def is_univariate(self):
  373. return len(self.gens) == 1
  374. @property
  375. def is_multivariate(self):
  376. return len(self.gens) > 1
  377. def add(self, *objs):
  378. """
  379. Add a sequence of polynomials or containers of polynomials.
  380. Examples
  381. ========
  382. >>> from sympy.polys.rings import ring
  383. >>> from sympy.polys.domains import ZZ
  384. >>> R, x = ring("x", ZZ)
  385. >>> R.add([ x**2 + 2*i + 3 for i in range(4) ])
  386. 4*x**2 + 24
  387. >>> _.factor_list()
  388. (4, [(x**2 + 6, 1)])
  389. """
  390. p = self.zero
  391. for obj in objs:
  392. if is_sequence(obj, include=GeneratorType):
  393. p += self.add(*obj)
  394. else:
  395. p += obj
  396. return p
  397. def mul(self, *objs):
  398. """
  399. Multiply a sequence of polynomials or containers of polynomials.
  400. Examples
  401. ========
  402. >>> from sympy.polys.rings import ring
  403. >>> from sympy.polys.domains import ZZ
  404. >>> R, x = ring("x", ZZ)
  405. >>> R.mul([ x**2 + 2*i + 3 for i in range(4) ])
  406. x**8 + 24*x**6 + 206*x**4 + 744*x**2 + 945
  407. >>> _.factor_list()
  408. (1, [(x**2 + 3, 1), (x**2 + 5, 1), (x**2 + 7, 1), (x**2 + 9, 1)])
  409. """
  410. p = self.one
  411. for obj in objs:
  412. if is_sequence(obj, include=GeneratorType):
  413. p *= self.mul(*obj)
  414. else:
  415. p *= obj
  416. return p
  417. def drop_to_ground(self, *gens):
  418. r"""
  419. Remove specified generators from the ring and inject them into
  420. its domain.
  421. """
  422. indices = set(map(self.index, gens))
  423. symbols = [s for i, s in enumerate(self.symbols) if i not in indices]
  424. gens = [gen for i, gen in enumerate(self.gens) if i not in indices]
  425. if not symbols:
  426. return self
  427. else:
  428. return self.clone(symbols=symbols, domain=self.drop(*gens))
  429. def compose(self, other):
  430. """Add the generators of ``other`` to ``self``"""
  431. if self != other:
  432. syms = set(self.symbols).union(set(other.symbols))
  433. return self.clone(symbols=list(syms))
  434. else:
  435. return self
  436. def add_gens(self, symbols):
  437. """Add the elements of ``symbols`` as generators to ``self``"""
  438. syms = set(self.symbols).union(set(symbols))
  439. return self.clone(symbols=list(syms))
  440. def symmetric_poly(self, n):
  441. """
  442. Return the elementary symmetric polynomial of degree *n* over
  443. this ring's generators.
  444. """
  445. if n < 0 or n > self.ngens:
  446. raise ValueError("Cannot generate symmetric polynomial of order %s for %s" % (n, self.gens))
  447. elif not n:
  448. return self.one
  449. else:
  450. poly = self.zero
  451. for s in subsets(range(self.ngens), int(n)):
  452. monom = tuple(int(i in s) for i in range(self.ngens))
  453. poly += self.term_new(monom, self.domain.one)
  454. return poly
  455. class PolyElement(DomainElement, DefaultPrinting, CantSympify, dict):
  456. """Element of multivariate distributed polynomial ring. """
  457. def new(self, init):
  458. return self.__class__(init)
  459. def parent(self):
  460. return self.ring.to_domain()
  461. def __getnewargs__(self):
  462. return (self.ring, list(self.iterterms()))
  463. _hash = None
  464. def __hash__(self):
  465. # XXX: This computes a hash of a dictionary, but currently we don't
  466. # protect dictionary from being changed so any use site modifications
  467. # will make hashing go wrong. Use this feature with caution until we
  468. # figure out how to make a safe API without compromising speed of this
  469. # low-level class.
  470. _hash = self._hash
  471. if _hash is None:
  472. self._hash = _hash = hash((self.ring, frozenset(self.items())))
  473. return _hash
  474. def copy(self):
  475. """Return a copy of polynomial self.
  476. Polynomials are mutable; if one is interested in preserving
  477. a polynomial, and one plans to use inplace operations, one
  478. can copy the polynomial. This method makes a shallow copy.
  479. Examples
  480. ========
  481. >>> from sympy.polys.domains import ZZ
  482. >>> from sympy.polys.rings import ring
  483. >>> R, x, y = ring('x, y', ZZ)
  484. >>> p = (x + y)**2
  485. >>> p1 = p.copy()
  486. >>> p2 = p
  487. >>> p[R.zero_monom] = 3
  488. >>> p
  489. x**2 + 2*x*y + y**2 + 3
  490. >>> p1
  491. x**2 + 2*x*y + y**2
  492. >>> p2
  493. x**2 + 2*x*y + y**2 + 3
  494. """
  495. return self.new(self)
  496. def set_ring(self, new_ring):
  497. if self.ring == new_ring:
  498. return self
  499. elif self.ring.symbols != new_ring.symbols:
  500. terms = list(zip(*_dict_reorder(self, self.ring.symbols, new_ring.symbols)))
  501. return new_ring.from_terms(terms, self.ring.domain)
  502. else:
  503. return new_ring.from_dict(self, self.ring.domain)
  504. def as_expr(self, *symbols):
  505. if not symbols:
  506. symbols = self.ring.symbols
  507. elif len(symbols) != self.ring.ngens:
  508. raise ValueError(
  509. "Wrong number of symbols, expected %s got %s" %
  510. (self.ring.ngens, len(symbols))
  511. )
  512. return expr_from_dict(self.as_expr_dict(), *symbols)
  513. def as_expr_dict(self):
  514. to_sympy = self.ring.domain.to_sympy
  515. return {monom: to_sympy(coeff) for monom, coeff in self.iterterms()}
  516. def clear_denoms(self):
  517. domain = self.ring.domain
  518. if not domain.is_Field or not domain.has_assoc_Ring:
  519. return domain.one, self
  520. ground_ring = domain.get_ring()
  521. common = ground_ring.one
  522. lcm = ground_ring.lcm
  523. denom = domain.denom
  524. for coeff in self.values():
  525. common = lcm(common, denom(coeff))
  526. poly = self.new([ (k, v*common) for k, v in self.items() ])
  527. return common, poly
  528. def strip_zero(self):
  529. """Eliminate monomials with zero coefficient. """
  530. for k, v in list(self.items()):
  531. if not v:
  532. del self[k]
  533. def __eq__(p1, p2):
  534. """Equality test for polynomials.
  535. Examples
  536. ========
  537. >>> from sympy.polys.domains import ZZ
  538. >>> from sympy.polys.rings import ring
  539. >>> _, x, y = ring('x, y', ZZ)
  540. >>> p1 = (x + y)**2 + (x - y)**2
  541. >>> p1 == 4*x*y
  542. False
  543. >>> p1 == 2*(x**2 + y**2)
  544. True
  545. """
  546. if not p2:
  547. return not p1
  548. elif isinstance(p2, PolyElement) and p2.ring == p1.ring:
  549. return dict.__eq__(p1, p2)
  550. elif len(p1) > 1:
  551. return False
  552. else:
  553. return p1.get(p1.ring.zero_monom) == p2
  554. def __ne__(p1, p2):
  555. return not p1 == p2
  556. def almosteq(p1, p2, tolerance=None):
  557. """Approximate equality test for polynomials. """
  558. ring = p1.ring
  559. if isinstance(p2, ring.dtype):
  560. if set(p1.keys()) != set(p2.keys()):
  561. return False
  562. almosteq = ring.domain.almosteq
  563. for k in p1.keys():
  564. if not almosteq(p1[k], p2[k], tolerance):
  565. return False
  566. return True
  567. elif len(p1) > 1:
  568. return False
  569. else:
  570. try:
  571. p2 = ring.domain.convert(p2)
  572. except CoercionFailed:
  573. return False
  574. else:
  575. return ring.domain.almosteq(p1.const(), p2, tolerance)
  576. def sort_key(self):
  577. return (len(self), self.terms())
  578. def _cmp(p1, p2, op):
  579. if isinstance(p2, p1.ring.dtype):
  580. return op(p1.sort_key(), p2.sort_key())
  581. else:
  582. return NotImplemented
  583. def __lt__(p1, p2):
  584. return p1._cmp(p2, lt)
  585. def __le__(p1, p2):
  586. return p1._cmp(p2, le)
  587. def __gt__(p1, p2):
  588. return p1._cmp(p2, gt)
  589. def __ge__(p1, p2):
  590. return p1._cmp(p2, ge)
  591. def _drop(self, gen):
  592. ring = self.ring
  593. i = ring.index(gen)
  594. if ring.ngens == 1:
  595. return i, ring.domain
  596. else:
  597. symbols = list(ring.symbols)
  598. del symbols[i]
  599. return i, ring.clone(symbols=symbols)
  600. def drop(self, gen):
  601. i, ring = self._drop(gen)
  602. if self.ring.ngens == 1:
  603. if self.is_ground:
  604. return self.coeff(1)
  605. else:
  606. raise ValueError("Cannot drop %s" % gen)
  607. else:
  608. poly = ring.zero
  609. for k, v in self.items():
  610. if k[i] == 0:
  611. K = list(k)
  612. del K[i]
  613. poly[tuple(K)] = v
  614. else:
  615. raise ValueError("Cannot drop %s" % gen)
  616. return poly
  617. def _drop_to_ground(self, gen):
  618. ring = self.ring
  619. i = ring.index(gen)
  620. symbols = list(ring.symbols)
  621. del symbols[i]
  622. return i, ring.clone(symbols=symbols, domain=ring[i])
  623. def drop_to_ground(self, gen):
  624. if self.ring.ngens == 1:
  625. raise ValueError("Cannot drop only generator to ground")
  626. i, ring = self._drop_to_ground(gen)
  627. poly = ring.zero
  628. gen = ring.domain.gens[0]
  629. for monom, coeff in self.iterterms():
  630. mon = monom[:i] + monom[i+1:]
  631. if mon not in poly:
  632. poly[mon] = (gen**monom[i]).mul_ground(coeff)
  633. else:
  634. poly[mon] += (gen**monom[i]).mul_ground(coeff)
  635. return poly
  636. def to_dense(self):
  637. return dmp_from_dict(self, self.ring.ngens-1, self.ring.domain)
  638. def to_dict(self):
  639. return dict(self)
  640. def str(self, printer, precedence, exp_pattern, mul_symbol):
  641. if not self:
  642. return printer._print(self.ring.domain.zero)
  643. prec_mul = precedence["Mul"]
  644. prec_atom = precedence["Atom"]
  645. ring = self.ring
  646. symbols = ring.symbols
  647. ngens = ring.ngens
  648. zm = ring.zero_monom
  649. sexpvs = []
  650. for expv, coeff in self.terms():
  651. negative = ring.domain.is_negative(coeff)
  652. sign = " - " if negative else " + "
  653. sexpvs.append(sign)
  654. if expv == zm:
  655. scoeff = printer._print(coeff)
  656. if negative and scoeff.startswith("-"):
  657. scoeff = scoeff[1:]
  658. else:
  659. if negative:
  660. coeff = -coeff
  661. if coeff != self.ring.domain.one:
  662. scoeff = printer.parenthesize(coeff, prec_mul, strict=True)
  663. else:
  664. scoeff = ''
  665. sexpv = []
  666. for i in range(ngens):
  667. exp = expv[i]
  668. if not exp:
  669. continue
  670. symbol = printer.parenthesize(symbols[i], prec_atom, strict=True)
  671. if exp != 1:
  672. if exp != int(exp) or exp < 0:
  673. sexp = printer.parenthesize(exp, prec_atom, strict=False)
  674. else:
  675. sexp = exp
  676. sexpv.append(exp_pattern % (symbol, sexp))
  677. else:
  678. sexpv.append('%s' % symbol)
  679. if scoeff:
  680. sexpv = [scoeff] + sexpv
  681. sexpvs.append(mul_symbol.join(sexpv))
  682. if sexpvs[0] in [" + ", " - "]:
  683. head = sexpvs.pop(0)
  684. if head == " - ":
  685. sexpvs.insert(0, "-")
  686. return "".join(sexpvs)
  687. @property
  688. def is_generator(self):
  689. return self in self.ring._gens_set
  690. @property
  691. def is_ground(self):
  692. return not self or (len(self) == 1 and self.ring.zero_monom in self)
  693. @property
  694. def is_monomial(self):
  695. return not self or (len(self) == 1 and self.LC == 1)
  696. @property
  697. def is_term(self):
  698. return len(self) <= 1
  699. @property
  700. def is_negative(self):
  701. return self.ring.domain.is_negative(self.LC)
  702. @property
  703. def is_positive(self):
  704. return self.ring.domain.is_positive(self.LC)
  705. @property
  706. def is_nonnegative(self):
  707. return self.ring.domain.is_nonnegative(self.LC)
  708. @property
  709. def is_nonpositive(self):
  710. return self.ring.domain.is_nonpositive(self.LC)
  711. @property
  712. def is_zero(f):
  713. return not f
  714. @property
  715. def is_one(f):
  716. return f == f.ring.one
  717. @property
  718. def is_monic(f):
  719. return f.ring.domain.is_one(f.LC)
  720. @property
  721. def is_primitive(f):
  722. return f.ring.domain.is_one(f.content())
  723. @property
  724. def is_linear(f):
  725. return all(sum(monom) <= 1 for monom in f.itermonoms())
  726. @property
  727. def is_quadratic(f):
  728. return all(sum(monom) <= 2 for monom in f.itermonoms())
  729. @property
  730. def is_squarefree(f):
  731. if not f.ring.ngens:
  732. return True
  733. return f.ring.dmp_sqf_p(f)
  734. @property
  735. def is_irreducible(f):
  736. if not f.ring.ngens:
  737. return True
  738. return f.ring.dmp_irreducible_p(f)
  739. @property
  740. def is_cyclotomic(f):
  741. if f.ring.is_univariate:
  742. return f.ring.dup_cyclotomic_p(f)
  743. else:
  744. raise MultivariatePolynomialError("cyclotomic polynomial")
  745. def __neg__(self):
  746. return self.new([ (monom, -coeff) for monom, coeff in self.iterterms() ])
  747. def __pos__(self):
  748. return self
  749. def __add__(p1, p2):
  750. """Add two polynomials.
  751. Examples
  752. ========
  753. >>> from sympy.polys.domains import ZZ
  754. >>> from sympy.polys.rings import ring
  755. >>> _, x, y = ring('x, y', ZZ)
  756. >>> (x + y)**2 + (x - y)**2
  757. 2*x**2 + 2*y**2
  758. """
  759. if not p2:
  760. return p1.copy()
  761. ring = p1.ring
  762. if isinstance(p2, ring.dtype):
  763. p = p1.copy()
  764. get = p.get
  765. zero = ring.domain.zero
  766. for k, v in p2.items():
  767. v = get(k, zero) + v
  768. if v:
  769. p[k] = v
  770. else:
  771. del p[k]
  772. return p
  773. elif isinstance(p2, PolyElement):
  774. if isinstance(ring.domain, PolynomialRing) and ring.domain.ring == p2.ring:
  775. pass
  776. elif isinstance(p2.ring.domain, PolynomialRing) and p2.ring.domain.ring == ring:
  777. return p2.__radd__(p1)
  778. else:
  779. return NotImplemented
  780. try:
  781. cp2 = ring.domain_new(p2)
  782. except CoercionFailed:
  783. return NotImplemented
  784. else:
  785. p = p1.copy()
  786. if not cp2:
  787. return p
  788. zm = ring.zero_monom
  789. if zm not in p1.keys():
  790. p[zm] = cp2
  791. else:
  792. if p2 == -p[zm]:
  793. del p[zm]
  794. else:
  795. p[zm] += cp2
  796. return p
  797. def __radd__(p1, n):
  798. p = p1.copy()
  799. if not n:
  800. return p
  801. ring = p1.ring
  802. try:
  803. n = ring.domain_new(n)
  804. except CoercionFailed:
  805. return NotImplemented
  806. else:
  807. zm = ring.zero_monom
  808. if zm not in p1.keys():
  809. p[zm] = n
  810. else:
  811. if n == -p[zm]:
  812. del p[zm]
  813. else:
  814. p[zm] += n
  815. return p
  816. def __sub__(p1, p2):
  817. """Subtract polynomial p2 from p1.
  818. Examples
  819. ========
  820. >>> from sympy.polys.domains import ZZ
  821. >>> from sympy.polys.rings import ring
  822. >>> _, x, y = ring('x, y', ZZ)
  823. >>> p1 = x + y**2
  824. >>> p2 = x*y + y**2
  825. >>> p1 - p2
  826. -x*y + x
  827. """
  828. if not p2:
  829. return p1.copy()
  830. ring = p1.ring
  831. if isinstance(p2, ring.dtype):
  832. p = p1.copy()
  833. get = p.get
  834. zero = ring.domain.zero
  835. for k, v in p2.items():
  836. v = get(k, zero) - v
  837. if v:
  838. p[k] = v
  839. else:
  840. del p[k]
  841. return p
  842. elif isinstance(p2, PolyElement):
  843. if isinstance(ring.domain, PolynomialRing) and ring.domain.ring == p2.ring:
  844. pass
  845. elif isinstance(p2.ring.domain, PolynomialRing) and p2.ring.domain.ring == ring:
  846. return p2.__rsub__(p1)
  847. else:
  848. return NotImplemented
  849. try:
  850. p2 = ring.domain_new(p2)
  851. except CoercionFailed:
  852. return NotImplemented
  853. else:
  854. p = p1.copy()
  855. zm = ring.zero_monom
  856. if zm not in p1.keys():
  857. p[zm] = -p2
  858. else:
  859. if p2 == p[zm]:
  860. del p[zm]
  861. else:
  862. p[zm] -= p2
  863. return p
  864. def __rsub__(p1, n):
  865. """n - p1 with n convertible to the coefficient domain.
  866. Examples
  867. ========
  868. >>> from sympy.polys.domains import ZZ
  869. >>> from sympy.polys.rings import ring
  870. >>> _, x, y = ring('x, y', ZZ)
  871. >>> p = x + y
  872. >>> 4 - p
  873. -x - y + 4
  874. """
  875. ring = p1.ring
  876. try:
  877. n = ring.domain_new(n)
  878. except CoercionFailed:
  879. return NotImplemented
  880. else:
  881. p = ring.zero
  882. for expv in p1:
  883. p[expv] = -p1[expv]
  884. p += n
  885. return p
  886. def __mul__(p1, p2):
  887. """Multiply two polynomials.
  888. Examples
  889. ========
  890. >>> from sympy.polys.domains import QQ
  891. >>> from sympy.polys.rings import ring
  892. >>> _, x, y = ring('x, y', QQ)
  893. >>> p1 = x + y
  894. >>> p2 = x - y
  895. >>> p1*p2
  896. x**2 - y**2
  897. """
  898. ring = p1.ring
  899. p = ring.zero
  900. if not p1 or not p2:
  901. return p
  902. elif isinstance(p2, ring.dtype):
  903. get = p.get
  904. zero = ring.domain.zero
  905. monomial_mul = ring.monomial_mul
  906. p2it = list(p2.items())
  907. for exp1, v1 in p1.items():
  908. for exp2, v2 in p2it:
  909. exp = monomial_mul(exp1, exp2)
  910. p[exp] = get(exp, zero) + v1*v2
  911. p.strip_zero()
  912. return p
  913. elif isinstance(p2, PolyElement):
  914. if isinstance(ring.domain, PolynomialRing) and ring.domain.ring == p2.ring:
  915. pass
  916. elif isinstance(p2.ring.domain, PolynomialRing) and p2.ring.domain.ring == ring:
  917. return p2.__rmul__(p1)
  918. else:
  919. return NotImplemented
  920. try:
  921. p2 = ring.domain_new(p2)
  922. except CoercionFailed:
  923. return NotImplemented
  924. else:
  925. for exp1, v1 in p1.items():
  926. v = v1*p2
  927. if v:
  928. p[exp1] = v
  929. return p
  930. def __rmul__(p1, p2):
  931. """p2 * p1 with p2 in the coefficient domain of p1.
  932. Examples
  933. ========
  934. >>> from sympy.polys.domains import ZZ
  935. >>> from sympy.polys.rings import ring
  936. >>> _, x, y = ring('x, y', ZZ)
  937. >>> p = x + y
  938. >>> 4 * p
  939. 4*x + 4*y
  940. """
  941. p = p1.ring.zero
  942. if not p2:
  943. return p
  944. try:
  945. p2 = p.ring.domain_new(p2)
  946. except CoercionFailed:
  947. return NotImplemented
  948. else:
  949. for exp1, v1 in p1.items():
  950. v = p2*v1
  951. if v:
  952. p[exp1] = v
  953. return p
  954. def __pow__(self, n):
  955. """raise polynomial to power `n`
  956. Examples
  957. ========
  958. >>> from sympy.polys.domains import ZZ
  959. >>> from sympy.polys.rings import ring
  960. >>> _, x, y = ring('x, y', ZZ)
  961. >>> p = x + y**2
  962. >>> p**3
  963. x**3 + 3*x**2*y**2 + 3*x*y**4 + y**6
  964. """
  965. ring = self.ring
  966. if not n:
  967. if self:
  968. return ring.one
  969. else:
  970. raise ValueError("0**0")
  971. elif len(self) == 1:
  972. monom, coeff = list(self.items())[0]
  973. p = ring.zero
  974. if coeff == ring.domain.one:
  975. p[ring.monomial_pow(monom, n)] = coeff
  976. else:
  977. p[ring.monomial_pow(monom, n)] = coeff**n
  978. return p
  979. # For ring series, we need negative and rational exponent support only
  980. # with monomials.
  981. n = int(n)
  982. if n < 0:
  983. raise ValueError("Negative exponent")
  984. elif n == 1:
  985. return self.copy()
  986. elif n == 2:
  987. return self.square()
  988. elif n == 3:
  989. return self*self.square()
  990. elif len(self) <= 5: # TODO: use an actual density measure
  991. return self._pow_multinomial(n)
  992. else:
  993. return self._pow_generic(n)
  994. def _pow_generic(self, n):
  995. p = self.ring.one
  996. c = self
  997. while True:
  998. if n & 1:
  999. p = p*c
  1000. n -= 1
  1001. if not n:
  1002. break
  1003. c = c.square()
  1004. n = n // 2
  1005. return p
  1006. def _pow_multinomial(self, n):
  1007. multinomials = multinomial_coefficients(len(self), n).items()
  1008. monomial_mulpow = self.ring.monomial_mulpow
  1009. zero_monom = self.ring.zero_monom
  1010. terms = self.items()
  1011. zero = self.ring.domain.zero
  1012. poly = self.ring.zero
  1013. for multinomial, multinomial_coeff in multinomials:
  1014. product_monom = zero_monom
  1015. product_coeff = multinomial_coeff
  1016. for exp, (monom, coeff) in zip(multinomial, terms):
  1017. if exp:
  1018. product_monom = monomial_mulpow(product_monom, monom, exp)
  1019. product_coeff *= coeff**exp
  1020. monom = tuple(product_monom)
  1021. coeff = product_coeff
  1022. coeff = poly.get(monom, zero) + coeff
  1023. if coeff:
  1024. poly[monom] = coeff
  1025. elif monom in poly:
  1026. del poly[monom]
  1027. return poly
  1028. def square(self):
  1029. """square of a polynomial
  1030. Examples
  1031. ========
  1032. >>> from sympy.polys.rings import ring
  1033. >>> from sympy.polys.domains import ZZ
  1034. >>> _, x, y = ring('x, y', ZZ)
  1035. >>> p = x + y**2
  1036. >>> p.square()
  1037. x**2 + 2*x*y**2 + y**4
  1038. """
  1039. ring = self.ring
  1040. p = ring.zero
  1041. get = p.get
  1042. keys = list(self.keys())
  1043. zero = ring.domain.zero
  1044. monomial_mul = ring.monomial_mul
  1045. for i in range(len(keys)):
  1046. k1 = keys[i]
  1047. pk = self[k1]
  1048. for j in range(i):
  1049. k2 = keys[j]
  1050. exp = monomial_mul(k1, k2)
  1051. p[exp] = get(exp, zero) + pk*self[k2]
  1052. p = p.imul_num(2)
  1053. get = p.get
  1054. for k, v in self.items():
  1055. k2 = monomial_mul(k, k)
  1056. p[k2] = get(k2, zero) + v**2
  1057. p.strip_zero()
  1058. return p
  1059. def __divmod__(p1, p2):
  1060. ring = p1.ring
  1061. if not p2:
  1062. raise ZeroDivisionError("polynomial division")
  1063. elif isinstance(p2, ring.dtype):
  1064. return p1.div(p2)
  1065. elif isinstance(p2, PolyElement):
  1066. if isinstance(ring.domain, PolynomialRing) and ring.domain.ring == p2.ring:
  1067. pass
  1068. elif isinstance(p2.ring.domain, PolynomialRing) and p2.ring.domain.ring == ring:
  1069. return p2.__rdivmod__(p1)
  1070. else:
  1071. return NotImplemented
  1072. try:
  1073. p2 = ring.domain_new(p2)
  1074. except CoercionFailed:
  1075. return NotImplemented
  1076. else:
  1077. return (p1.quo_ground(p2), p1.rem_ground(p2))
  1078. def __rdivmod__(p1, p2):
  1079. return NotImplemented
  1080. def __mod__(p1, p2):
  1081. ring = p1.ring
  1082. if not p2:
  1083. raise ZeroDivisionError("polynomial division")
  1084. elif isinstance(p2, ring.dtype):
  1085. return p1.rem(p2)
  1086. elif isinstance(p2, PolyElement):
  1087. if isinstance(ring.domain, PolynomialRing) and ring.domain.ring == p2.ring:
  1088. pass
  1089. elif isinstance(p2.ring.domain, PolynomialRing) and p2.ring.domain.ring == ring:
  1090. return p2.__rmod__(p1)
  1091. else:
  1092. return NotImplemented
  1093. try:
  1094. p2 = ring.domain_new(p2)
  1095. except CoercionFailed:
  1096. return NotImplemented
  1097. else:
  1098. return p1.rem_ground(p2)
  1099. def __rmod__(p1, p2):
  1100. return NotImplemented
  1101. def __truediv__(p1, p2):
  1102. ring = p1.ring
  1103. if not p2:
  1104. raise ZeroDivisionError("polynomial division")
  1105. elif isinstance(p2, ring.dtype):
  1106. if p2.is_monomial:
  1107. return p1*(p2**(-1))
  1108. else:
  1109. return p1.quo(p2)
  1110. elif isinstance(p2, PolyElement):
  1111. if isinstance(ring.domain, PolynomialRing) and ring.domain.ring == p2.ring:
  1112. pass
  1113. elif isinstance(p2.ring.domain, PolynomialRing) and p2.ring.domain.ring == ring:
  1114. return p2.__rtruediv__(p1)
  1115. else:
  1116. return NotImplemented
  1117. try:
  1118. p2 = ring.domain_new(p2)
  1119. except CoercionFailed:
  1120. return NotImplemented
  1121. else:
  1122. return p1.quo_ground(p2)
  1123. def __rtruediv__(p1, p2):
  1124. return NotImplemented
  1125. __floordiv__ = __truediv__
  1126. __rfloordiv__ = __rtruediv__
  1127. # TODO: use // (__floordiv__) for exquo()?
  1128. def _term_div(self):
  1129. zm = self.ring.zero_monom
  1130. domain = self.ring.domain
  1131. domain_quo = domain.quo
  1132. monomial_div = self.ring.monomial_div
  1133. if domain.is_Field:
  1134. def term_div(a_lm_a_lc, b_lm_b_lc):
  1135. a_lm, a_lc = a_lm_a_lc
  1136. b_lm, b_lc = b_lm_b_lc
  1137. if b_lm == zm: # apparently this is a very common case
  1138. monom = a_lm
  1139. else:
  1140. monom = monomial_div(a_lm, b_lm)
  1141. if monom is not None:
  1142. return monom, domain_quo(a_lc, b_lc)
  1143. else:
  1144. return None
  1145. else:
  1146. def term_div(a_lm_a_lc, b_lm_b_lc):
  1147. a_lm, a_lc = a_lm_a_lc
  1148. b_lm, b_lc = b_lm_b_lc
  1149. if b_lm == zm: # apparently this is a very common case
  1150. monom = a_lm
  1151. else:
  1152. monom = monomial_div(a_lm, b_lm)
  1153. if not (monom is None or a_lc % b_lc):
  1154. return monom, domain_quo(a_lc, b_lc)
  1155. else:
  1156. return None
  1157. return term_div
  1158. def div(self, fv):
  1159. """Division algorithm, see [CLO] p64.
  1160. fv array of polynomials
  1161. return qv, r such that
  1162. self = sum(fv[i]*qv[i]) + r
  1163. All polynomials are required not to be Laurent polynomials.
  1164. Examples
  1165. ========
  1166. >>> from sympy.polys.rings import ring
  1167. >>> from sympy.polys.domains import ZZ
  1168. >>> _, x, y = ring('x, y', ZZ)
  1169. >>> f = x**3
  1170. >>> f0 = x - y**2
  1171. >>> f1 = x - y
  1172. >>> qv, r = f.div((f0, f1))
  1173. >>> qv[0]
  1174. x**2 + x*y**2 + y**4
  1175. >>> qv[1]
  1176. 0
  1177. >>> r
  1178. y**6
  1179. """
  1180. ring = self.ring
  1181. ret_single = False
  1182. if isinstance(fv, PolyElement):
  1183. ret_single = True
  1184. fv = [fv]
  1185. if not all(fv):
  1186. raise ZeroDivisionError("polynomial division")
  1187. if not self:
  1188. if ret_single:
  1189. return ring.zero, ring.zero
  1190. else:
  1191. return [], ring.zero
  1192. for f in fv:
  1193. if f.ring != ring:
  1194. raise ValueError('self and f must have the same ring')
  1195. s = len(fv)
  1196. qv = [ring.zero for i in range(s)]
  1197. p = self.copy()
  1198. r = ring.zero
  1199. term_div = self._term_div()
  1200. expvs = [fx.leading_expv() for fx in fv]
  1201. while p:
  1202. i = 0
  1203. divoccurred = 0
  1204. while i < s and divoccurred == 0:
  1205. expv = p.leading_expv()
  1206. term = term_div((expv, p[expv]), (expvs[i], fv[i][expvs[i]]))
  1207. if term is not None:
  1208. expv1, c = term
  1209. qv[i] = qv[i]._iadd_monom((expv1, c))
  1210. p = p._iadd_poly_monom(fv[i], (expv1, -c))
  1211. divoccurred = 1
  1212. else:
  1213. i += 1
  1214. if not divoccurred:
  1215. expv = p.leading_expv()
  1216. r = r._iadd_monom((expv, p[expv]))
  1217. del p[expv]
  1218. if expv == ring.zero_monom:
  1219. r += p
  1220. if ret_single:
  1221. if not qv:
  1222. return ring.zero, r
  1223. else:
  1224. return qv[0], r
  1225. else:
  1226. return qv, r
  1227. def rem(self, G):
  1228. f = self
  1229. if isinstance(G, PolyElement):
  1230. G = [G]
  1231. if not all(G):
  1232. raise ZeroDivisionError("polynomial division")
  1233. ring = f.ring
  1234. domain = ring.domain
  1235. zero = domain.zero
  1236. monomial_mul = ring.monomial_mul
  1237. r = ring.zero
  1238. term_div = f._term_div()
  1239. ltf = f.LT
  1240. f = f.copy()
  1241. get = f.get
  1242. while f:
  1243. for g in G:
  1244. tq = term_div(ltf, g.LT)
  1245. if tq is not None:
  1246. m, c = tq
  1247. for mg, cg in g.iterterms():
  1248. m1 = monomial_mul(mg, m)
  1249. c1 = get(m1, zero) - c*cg
  1250. if not c1:
  1251. del f[m1]
  1252. else:
  1253. f[m1] = c1
  1254. ltm = f.leading_expv()
  1255. if ltm is not None:
  1256. ltf = ltm, f[ltm]
  1257. break
  1258. else:
  1259. ltm, ltc = ltf
  1260. if ltm in r:
  1261. r[ltm] += ltc
  1262. else:
  1263. r[ltm] = ltc
  1264. del f[ltm]
  1265. ltm = f.leading_expv()
  1266. if ltm is not None:
  1267. ltf = ltm, f[ltm]
  1268. return r
  1269. def quo(f, G):
  1270. return f.div(G)[0]
  1271. def exquo(f, G):
  1272. q, r = f.div(G)
  1273. if not r:
  1274. return q
  1275. else:
  1276. raise ExactQuotientFailed(f, G)
  1277. def _iadd_monom(self, mc):
  1278. """add to self the monomial coeff*x0**i0*x1**i1*...
  1279. unless self is a generator -- then just return the sum of the two.
  1280. mc is a tuple, (monom, coeff), where monomial is (i0, i1, ...)
  1281. Examples
  1282. ========
  1283. >>> from sympy.polys.rings import ring
  1284. >>> from sympy.polys.domains import ZZ
  1285. >>> _, x, y = ring('x, y', ZZ)
  1286. >>> p = x**4 + 2*y
  1287. >>> m = (1, 2)
  1288. >>> p1 = p._iadd_monom((m, 5))
  1289. >>> p1
  1290. x**4 + 5*x*y**2 + 2*y
  1291. >>> p1 is p
  1292. True
  1293. >>> p = x
  1294. >>> p1 = p._iadd_monom((m, 5))
  1295. >>> p1
  1296. 5*x*y**2 + x
  1297. >>> p1 is p
  1298. False
  1299. """
  1300. if self in self.ring._gens_set:
  1301. cpself = self.copy()
  1302. else:
  1303. cpself = self
  1304. expv, coeff = mc
  1305. c = cpself.get(expv)
  1306. if c is None:
  1307. cpself[expv] = coeff
  1308. else:
  1309. c += coeff
  1310. if c:
  1311. cpself[expv] = c
  1312. else:
  1313. del cpself[expv]
  1314. return cpself
  1315. def _iadd_poly_monom(self, p2, mc):
  1316. """add to self the product of (p)*(coeff*x0**i0*x1**i1*...)
  1317. unless self is a generator -- then just return the sum of the two.
  1318. mc is a tuple, (monom, coeff), where monomial is (i0, i1, ...)
  1319. Examples
  1320. ========
  1321. >>> from sympy.polys.rings import ring
  1322. >>> from sympy.polys.domains import ZZ
  1323. >>> _, x, y, z = ring('x, y, z', ZZ)
  1324. >>> p1 = x**4 + 2*y
  1325. >>> p2 = y + z
  1326. >>> m = (1, 2, 3)
  1327. >>> p1 = p1._iadd_poly_monom(p2, (m, 3))
  1328. >>> p1
  1329. x**4 + 3*x*y**3*z**3 + 3*x*y**2*z**4 + 2*y
  1330. """
  1331. p1 = self
  1332. if p1 in p1.ring._gens_set:
  1333. p1 = p1.copy()
  1334. (m, c) = mc
  1335. get = p1.get
  1336. zero = p1.ring.domain.zero
  1337. monomial_mul = p1.ring.monomial_mul
  1338. for k, v in p2.items():
  1339. ka = monomial_mul(k, m)
  1340. coeff = get(ka, zero) + v*c
  1341. if coeff:
  1342. p1[ka] = coeff
  1343. else:
  1344. del p1[ka]
  1345. return p1
  1346. def degree(f, x=None):
  1347. """
  1348. The leading degree in ``x`` or the main variable.
  1349. Note that the degree of 0 is negative infinity (the SymPy object -oo).
  1350. """
  1351. i = f.ring.index(x)
  1352. if not f:
  1353. return -oo
  1354. elif i < 0:
  1355. return 0
  1356. else:
  1357. return max([ monom[i] for monom in f.itermonoms() ])
  1358. def degrees(f):
  1359. """
  1360. A tuple containing leading degrees in all variables.
  1361. Note that the degree of 0 is negative infinity (the SymPy object -oo)
  1362. """
  1363. if not f:
  1364. return (-oo,)*f.ring.ngens
  1365. else:
  1366. return tuple(map(max, list(zip(*f.itermonoms()))))
  1367. def tail_degree(f, x=None):
  1368. """
  1369. The tail degree in ``x`` or the main variable.
  1370. Note that the degree of 0 is negative infinity (the SymPy object -oo)
  1371. """
  1372. i = f.ring.index(x)
  1373. if not f:
  1374. return -oo
  1375. elif i < 0:
  1376. return 0
  1377. else:
  1378. return min([ monom[i] for monom in f.itermonoms() ])
  1379. def tail_degrees(f):
  1380. """
  1381. A tuple containing tail degrees in all variables.
  1382. Note that the degree of 0 is negative infinity (the SymPy object -oo)
  1383. """
  1384. if not f:
  1385. return (-oo,)*f.ring.ngens
  1386. else:
  1387. return tuple(map(min, list(zip(*f.itermonoms()))))
  1388. def leading_expv(self):
  1389. """Leading monomial tuple according to the monomial ordering.
  1390. Examples
  1391. ========
  1392. >>> from sympy.polys.rings import ring
  1393. >>> from sympy.polys.domains import ZZ
  1394. >>> _, x, y, z = ring('x, y, z', ZZ)
  1395. >>> p = x**4 + x**3*y + x**2*z**2 + z**7
  1396. >>> p.leading_expv()
  1397. (4, 0, 0)
  1398. """
  1399. if self:
  1400. return self.ring.leading_expv(self)
  1401. else:
  1402. return None
  1403. def _get_coeff(self, expv):
  1404. return self.get(expv, self.ring.domain.zero)
  1405. def coeff(self, element):
  1406. """
  1407. Returns the coefficient that stands next to the given monomial.
  1408. Parameters
  1409. ==========
  1410. element : PolyElement (with ``is_monomial = True``) or 1
  1411. Examples
  1412. ========
  1413. >>> from sympy.polys.rings import ring
  1414. >>> from sympy.polys.domains import ZZ
  1415. >>> _, x, y, z = ring("x,y,z", ZZ)
  1416. >>> f = 3*x**2*y - x*y*z + 7*z**3 + 23
  1417. >>> f.coeff(x**2*y)
  1418. 3
  1419. >>> f.coeff(x*y)
  1420. 0
  1421. >>> f.coeff(1)
  1422. 23
  1423. """
  1424. if element == 1:
  1425. return self._get_coeff(self.ring.zero_monom)
  1426. elif isinstance(element, self.ring.dtype):
  1427. terms = list(element.iterterms())
  1428. if len(terms) == 1:
  1429. monom, coeff = terms[0]
  1430. if coeff == self.ring.domain.one:
  1431. return self._get_coeff(monom)
  1432. raise ValueError("expected a monomial, got %s" % element)
  1433. def const(self):
  1434. """Returns the constant coefficient. """
  1435. return self._get_coeff(self.ring.zero_monom)
  1436. @property
  1437. def LC(self):
  1438. return self._get_coeff(self.leading_expv())
  1439. @property
  1440. def LM(self):
  1441. expv = self.leading_expv()
  1442. if expv is None:
  1443. return self.ring.zero_monom
  1444. else:
  1445. return expv
  1446. def leading_monom(self):
  1447. """
  1448. Leading monomial as a polynomial element.
  1449. Examples
  1450. ========
  1451. >>> from sympy.polys.rings import ring
  1452. >>> from sympy.polys.domains import ZZ
  1453. >>> _, x, y = ring('x, y', ZZ)
  1454. >>> (3*x*y + y**2).leading_monom()
  1455. x*y
  1456. """
  1457. p = self.ring.zero
  1458. expv = self.leading_expv()
  1459. if expv:
  1460. p[expv] = self.ring.domain.one
  1461. return p
  1462. @property
  1463. def LT(self):
  1464. expv = self.leading_expv()
  1465. if expv is None:
  1466. return (self.ring.zero_monom, self.ring.domain.zero)
  1467. else:
  1468. return (expv, self._get_coeff(expv))
  1469. def leading_term(self):
  1470. """Leading term as a polynomial element.
  1471. Examples
  1472. ========
  1473. >>> from sympy.polys.rings import ring
  1474. >>> from sympy.polys.domains import ZZ
  1475. >>> _, x, y = ring('x, y', ZZ)
  1476. >>> (3*x*y + y**2).leading_term()
  1477. 3*x*y
  1478. """
  1479. p = self.ring.zero
  1480. expv = self.leading_expv()
  1481. if expv is not None:
  1482. p[expv] = self[expv]
  1483. return p
  1484. def _sorted(self, seq, order):
  1485. if order is None:
  1486. order = self.ring.order
  1487. else:
  1488. order = OrderOpt.preprocess(order)
  1489. if order is lex:
  1490. return sorted(seq, key=lambda monom: monom[0], reverse=True)
  1491. else:
  1492. return sorted(seq, key=lambda monom: order(monom[0]), reverse=True)
  1493. def coeffs(self, order=None):
  1494. """Ordered list of polynomial coefficients.
  1495. Parameters
  1496. ==========
  1497. order : :class:`~.MonomialOrder` or coercible, optional
  1498. Examples
  1499. ========
  1500. >>> from sympy.polys.rings import ring
  1501. >>> from sympy.polys.domains import ZZ
  1502. >>> from sympy.polys.orderings import lex, grlex
  1503. >>> _, x, y = ring("x, y", ZZ, lex)
  1504. >>> f = x*y**7 + 2*x**2*y**3
  1505. >>> f.coeffs()
  1506. [2, 1]
  1507. >>> f.coeffs(grlex)
  1508. [1, 2]
  1509. """
  1510. return [ coeff for _, coeff in self.terms(order) ]
  1511. def monoms(self, order=None):
  1512. """Ordered list of polynomial monomials.
  1513. Parameters
  1514. ==========
  1515. order : :class:`~.MonomialOrder` or coercible, optional
  1516. Examples
  1517. ========
  1518. >>> from sympy.polys.rings import ring
  1519. >>> from sympy.polys.domains import ZZ
  1520. >>> from sympy.polys.orderings import lex, grlex
  1521. >>> _, x, y = ring("x, y", ZZ, lex)
  1522. >>> f = x*y**7 + 2*x**2*y**3
  1523. >>> f.monoms()
  1524. [(2, 3), (1, 7)]
  1525. >>> f.monoms(grlex)
  1526. [(1, 7), (2, 3)]
  1527. """
  1528. return [ monom for monom, _ in self.terms(order) ]
  1529. def terms(self, order=None):
  1530. """Ordered list of polynomial terms.
  1531. Parameters
  1532. ==========
  1533. order : :class:`~.MonomialOrder` or coercible, optional
  1534. Examples
  1535. ========
  1536. >>> from sympy.polys.rings import ring
  1537. >>> from sympy.polys.domains import ZZ
  1538. >>> from sympy.polys.orderings import lex, grlex
  1539. >>> _, x, y = ring("x, y", ZZ, lex)
  1540. >>> f = x*y**7 + 2*x**2*y**3
  1541. >>> f.terms()
  1542. [((2, 3), 2), ((1, 7), 1)]
  1543. >>> f.terms(grlex)
  1544. [((1, 7), 1), ((2, 3), 2)]
  1545. """
  1546. return self._sorted(list(self.items()), order)
  1547. def itercoeffs(self):
  1548. """Iterator over coefficients of a polynomial. """
  1549. return iter(self.values())
  1550. def itermonoms(self):
  1551. """Iterator over monomials of a polynomial. """
  1552. return iter(self.keys())
  1553. def iterterms(self):
  1554. """Iterator over terms of a polynomial. """
  1555. return iter(self.items())
  1556. def listcoeffs(self):
  1557. """Unordered list of polynomial coefficients. """
  1558. return list(self.values())
  1559. def listmonoms(self):
  1560. """Unordered list of polynomial monomials. """
  1561. return list(self.keys())
  1562. def listterms(self):
  1563. """Unordered list of polynomial terms. """
  1564. return list(self.items())
  1565. def imul_num(p, c):
  1566. """multiply inplace the polynomial p by an element in the
  1567. coefficient ring, provided p is not one of the generators;
  1568. else multiply not inplace
  1569. Examples
  1570. ========
  1571. >>> from sympy.polys.rings import ring
  1572. >>> from sympy.polys.domains import ZZ
  1573. >>> _, x, y = ring('x, y', ZZ)
  1574. >>> p = x + y**2
  1575. >>> p1 = p.imul_num(3)
  1576. >>> p1
  1577. 3*x + 3*y**2
  1578. >>> p1 is p
  1579. True
  1580. >>> p = x
  1581. >>> p1 = p.imul_num(3)
  1582. >>> p1
  1583. 3*x
  1584. >>> p1 is p
  1585. False
  1586. """
  1587. if p in p.ring._gens_set:
  1588. return p*c
  1589. if not c:
  1590. p.clear()
  1591. return
  1592. for exp in p:
  1593. p[exp] *= c
  1594. return p
  1595. def content(f):
  1596. """Returns GCD of polynomial's coefficients. """
  1597. domain = f.ring.domain
  1598. cont = domain.zero
  1599. gcd = domain.gcd
  1600. for coeff in f.itercoeffs():
  1601. cont = gcd(cont, coeff)
  1602. return cont
  1603. def primitive(f):
  1604. """Returns content and a primitive polynomial. """
  1605. cont = f.content()
  1606. return cont, f.quo_ground(cont)
  1607. def monic(f):
  1608. """Divides all coefficients by the leading coefficient. """
  1609. if not f:
  1610. return f
  1611. else:
  1612. return f.quo_ground(f.LC)
  1613. def mul_ground(f, x):
  1614. if not x:
  1615. return f.ring.zero
  1616. terms = [ (monom, coeff*x) for monom, coeff in f.iterterms() ]
  1617. return f.new(terms)
  1618. def mul_monom(f, monom):
  1619. monomial_mul = f.ring.monomial_mul
  1620. terms = [ (monomial_mul(f_monom, monom), f_coeff) for f_monom, f_coeff in f.items() ]
  1621. return f.new(terms)
  1622. def mul_term(f, term):
  1623. monom, coeff = term
  1624. if not f or not coeff:
  1625. return f.ring.zero
  1626. elif monom == f.ring.zero_monom:
  1627. return f.mul_ground(coeff)
  1628. monomial_mul = f.ring.monomial_mul
  1629. terms = [ (monomial_mul(f_monom, monom), f_coeff*coeff) for f_monom, f_coeff in f.items() ]
  1630. return f.new(terms)
  1631. def quo_ground(f, x):
  1632. domain = f.ring.domain
  1633. if not x:
  1634. raise ZeroDivisionError('polynomial division')
  1635. if not f or x == domain.one:
  1636. return f
  1637. if domain.is_Field:
  1638. quo = domain.quo
  1639. terms = [ (monom, quo(coeff, x)) for monom, coeff in f.iterterms() ]
  1640. else:
  1641. terms = [ (monom, coeff // x) for monom, coeff in f.iterterms() if not (coeff % x) ]
  1642. return f.new(terms)
  1643. def quo_term(f, term):
  1644. monom, coeff = term
  1645. if not coeff:
  1646. raise ZeroDivisionError("polynomial division")
  1647. elif not f:
  1648. return f.ring.zero
  1649. elif monom == f.ring.zero_monom:
  1650. return f.quo_ground(coeff)
  1651. term_div = f._term_div()
  1652. terms = [ term_div(t, term) for t in f.iterterms() ]
  1653. return f.new([ t for t in terms if t is not None ])
  1654. def trunc_ground(f, p):
  1655. if f.ring.domain.is_ZZ:
  1656. terms = []
  1657. for monom, coeff in f.iterterms():
  1658. coeff = coeff % p
  1659. if coeff > p // 2:
  1660. coeff = coeff - p
  1661. terms.append((monom, coeff))
  1662. else:
  1663. terms = [ (monom, coeff % p) for monom, coeff in f.iterterms() ]
  1664. poly = f.new(terms)
  1665. poly.strip_zero()
  1666. return poly
  1667. rem_ground = trunc_ground
  1668. def extract_ground(self, g):
  1669. f = self
  1670. fc = f.content()
  1671. gc = g.content()
  1672. gcd = f.ring.domain.gcd(fc, gc)
  1673. f = f.quo_ground(gcd)
  1674. g = g.quo_ground(gcd)
  1675. return gcd, f, g
  1676. def _norm(f, norm_func):
  1677. if not f:
  1678. return f.ring.domain.zero
  1679. else:
  1680. ground_abs = f.ring.domain.abs
  1681. return norm_func([ ground_abs(coeff) for coeff in f.itercoeffs() ])
  1682. def max_norm(f):
  1683. return f._norm(max)
  1684. def l1_norm(f):
  1685. return f._norm(sum)
  1686. def deflate(f, *G):
  1687. ring = f.ring
  1688. polys = [f] + list(G)
  1689. J = [0]*ring.ngens
  1690. for p in polys:
  1691. for monom in p.itermonoms():
  1692. for i, m in enumerate(monom):
  1693. J[i] = igcd(J[i], m)
  1694. for i, b in enumerate(J):
  1695. if not b:
  1696. J[i] = 1
  1697. J = tuple(J)
  1698. if all(b == 1 for b in J):
  1699. return J, polys
  1700. H = []
  1701. for p in polys:
  1702. h = ring.zero
  1703. for I, coeff in p.iterterms():
  1704. N = [ i // j for i, j in zip(I, J) ]
  1705. h[tuple(N)] = coeff
  1706. H.append(h)
  1707. return J, H
  1708. def inflate(f, J):
  1709. poly = f.ring.zero
  1710. for I, coeff in f.iterterms():
  1711. N = [ i*j for i, j in zip(I, J) ]
  1712. poly[tuple(N)] = coeff
  1713. return poly
  1714. def lcm(self, g):
  1715. f = self
  1716. domain = f.ring.domain
  1717. if not domain.is_Field:
  1718. fc, f = f.primitive()
  1719. gc, g = g.primitive()
  1720. c = domain.lcm(fc, gc)
  1721. h = (f*g).quo(f.gcd(g))
  1722. if not domain.is_Field:
  1723. return h.mul_ground(c)
  1724. else:
  1725. return h.monic()
  1726. def gcd(f, g):
  1727. return f.cofactors(g)[0]
  1728. def cofactors(f, g):
  1729. if not f and not g:
  1730. zero = f.ring.zero
  1731. return zero, zero, zero
  1732. elif not f:
  1733. h, cff, cfg = f._gcd_zero(g)
  1734. return h, cff, cfg
  1735. elif not g:
  1736. h, cfg, cff = g._gcd_zero(f)
  1737. return h, cff, cfg
  1738. elif len(f) == 1:
  1739. h, cff, cfg = f._gcd_monom(g)
  1740. return h, cff, cfg
  1741. elif len(g) == 1:
  1742. h, cfg, cff = g._gcd_monom(f)
  1743. return h, cff, cfg
  1744. J, (f, g) = f.deflate(g)
  1745. h, cff, cfg = f._gcd(g)
  1746. return (h.inflate(J), cff.inflate(J), cfg.inflate(J))
  1747. def _gcd_zero(f, g):
  1748. one, zero = f.ring.one, f.ring.zero
  1749. if g.is_nonnegative:
  1750. return g, zero, one
  1751. else:
  1752. return -g, zero, -one
  1753. def _gcd_monom(f, g):
  1754. ring = f.ring
  1755. ground_gcd = ring.domain.gcd
  1756. ground_quo = ring.domain.quo
  1757. monomial_gcd = ring.monomial_gcd
  1758. monomial_ldiv = ring.monomial_ldiv
  1759. mf, cf = list(f.iterterms())[0]
  1760. _mgcd, _cgcd = mf, cf
  1761. for mg, cg in g.iterterms():
  1762. _mgcd = monomial_gcd(_mgcd, mg)
  1763. _cgcd = ground_gcd(_cgcd, cg)
  1764. h = f.new([(_mgcd, _cgcd)])
  1765. cff = f.new([(monomial_ldiv(mf, _mgcd), ground_quo(cf, _cgcd))])
  1766. cfg = f.new([(monomial_ldiv(mg, _mgcd), ground_quo(cg, _cgcd)) for mg, cg in g.iterterms()])
  1767. return h, cff, cfg
  1768. def _gcd(f, g):
  1769. ring = f.ring
  1770. if ring.domain.is_QQ:
  1771. return f._gcd_QQ(g)
  1772. elif ring.domain.is_ZZ:
  1773. return f._gcd_ZZ(g)
  1774. else: # TODO: don't use dense representation (port PRS algorithms)
  1775. return ring.dmp_inner_gcd(f, g)
  1776. def _gcd_ZZ(f, g):
  1777. return heugcd(f, g)
  1778. def _gcd_QQ(self, g):
  1779. f = self
  1780. ring = f.ring
  1781. new_ring = ring.clone(domain=ring.domain.get_ring())
  1782. cf, f = f.clear_denoms()
  1783. cg, g = g.clear_denoms()
  1784. f = f.set_ring(new_ring)
  1785. g = g.set_ring(new_ring)
  1786. h, cff, cfg = f._gcd_ZZ(g)
  1787. h = h.set_ring(ring)
  1788. c, h = h.LC, h.monic()
  1789. cff = cff.set_ring(ring).mul_ground(ring.domain.quo(c, cf))
  1790. cfg = cfg.set_ring(ring).mul_ground(ring.domain.quo(c, cg))
  1791. return h, cff, cfg
  1792. def cancel(self, g):
  1793. """
  1794. Cancel common factors in a rational function ``f/g``.
  1795. Examples
  1796. ========
  1797. >>> from sympy.polys import ring, ZZ
  1798. >>> R, x,y = ring("x,y", ZZ)
  1799. >>> (2*x**2 - 2).cancel(x**2 - 2*x + 1)
  1800. (2*x + 2, x - 1)
  1801. """
  1802. f = self
  1803. ring = f.ring
  1804. if not f:
  1805. return f, ring.one
  1806. domain = ring.domain
  1807. if not (domain.is_Field and domain.has_assoc_Ring):
  1808. _, p, q = f.cofactors(g)
  1809. else:
  1810. new_ring = ring.clone(domain=domain.get_ring())
  1811. cq, f = f.clear_denoms()
  1812. cp, g = g.clear_denoms()
  1813. f = f.set_ring(new_ring)
  1814. g = g.set_ring(new_ring)
  1815. _, p, q = f.cofactors(g)
  1816. _, cp, cq = new_ring.domain.cofactors(cp, cq)
  1817. p = p.set_ring(ring)
  1818. q = q.set_ring(ring)
  1819. p = p.mul_ground(cp)
  1820. q = q.mul_ground(cq)
  1821. # Make canonical with respect to sign or quadrant in the case of ZZ_I
  1822. # or QQ_I. This ensures that the LC of the denominator is canonical by
  1823. # multiplying top and bottom by a unit of the ring.
  1824. u = q.canonical_unit()
  1825. if u == domain.one:
  1826. p, q = p, q
  1827. elif u == -domain.one:
  1828. p, q = -p, -q
  1829. else:
  1830. p = p.mul_ground(u)
  1831. q = q.mul_ground(u)
  1832. return p, q
  1833. def canonical_unit(f):
  1834. domain = f.ring.domain
  1835. return domain.canonical_unit(f.LC)
  1836. def diff(f, x):
  1837. """Computes partial derivative in ``x``.
  1838. Examples
  1839. ========
  1840. >>> from sympy.polys.rings import ring
  1841. >>> from sympy.polys.domains import ZZ
  1842. >>> _, x, y = ring("x,y", ZZ)
  1843. >>> p = x + x**2*y**3
  1844. >>> p.diff(x)
  1845. 2*x*y**3 + 1
  1846. """
  1847. ring = f.ring
  1848. i = ring.index(x)
  1849. m = ring.monomial_basis(i)
  1850. g = ring.zero
  1851. for expv, coeff in f.iterterms():
  1852. if expv[i]:
  1853. e = ring.monomial_ldiv(expv, m)
  1854. g[e] = ring.domain_new(coeff*expv[i])
  1855. return g
  1856. def __call__(f, *values):
  1857. if 0 < len(values) <= f.ring.ngens:
  1858. return f.evaluate(list(zip(f.ring.gens, values)))
  1859. else:
  1860. raise ValueError("expected at least 1 and at most %s values, got %s" % (f.ring.ngens, len(values)))
  1861. def evaluate(self, x, a=None):
  1862. f = self
  1863. if isinstance(x, list) and a is None:
  1864. (X, a), x = x[0], x[1:]
  1865. f = f.evaluate(X, a)
  1866. if not x:
  1867. return f
  1868. else:
  1869. x = [ (Y.drop(X), a) for (Y, a) in x ]
  1870. return f.evaluate(x)
  1871. ring = f.ring
  1872. i = ring.index(x)
  1873. a = ring.domain.convert(a)
  1874. if ring.ngens == 1:
  1875. result = ring.domain.zero
  1876. for (n,), coeff in f.iterterms():
  1877. result += coeff*a**n
  1878. return result
  1879. else:
  1880. poly = ring.drop(x).zero
  1881. for monom, coeff in f.iterterms():
  1882. n, monom = monom[i], monom[:i] + monom[i+1:]
  1883. coeff = coeff*a**n
  1884. if monom in poly:
  1885. coeff = coeff + poly[monom]
  1886. if coeff:
  1887. poly[monom] = coeff
  1888. else:
  1889. del poly[monom]
  1890. else:
  1891. if coeff:
  1892. poly[monom] = coeff
  1893. return poly
  1894. def subs(self, x, a=None):
  1895. f = self
  1896. if isinstance(x, list) and a is None:
  1897. for X, a in x:
  1898. f = f.subs(X, a)
  1899. return f
  1900. ring = f.ring
  1901. i = ring.index(x)
  1902. a = ring.domain.convert(a)
  1903. if ring.ngens == 1:
  1904. result = ring.domain.zero
  1905. for (n,), coeff in f.iterterms():
  1906. result += coeff*a**n
  1907. return ring.ground_new(result)
  1908. else:
  1909. poly = ring.zero
  1910. for monom, coeff in f.iterterms():
  1911. n, monom = monom[i], monom[:i] + (0,) + monom[i+1:]
  1912. coeff = coeff*a**n
  1913. if monom in poly:
  1914. coeff = coeff + poly[monom]
  1915. if coeff:
  1916. poly[monom] = coeff
  1917. else:
  1918. del poly[monom]
  1919. else:
  1920. if coeff:
  1921. poly[monom] = coeff
  1922. return poly
  1923. def symmetrize(self):
  1924. r"""
  1925. Rewrite *self* in terms of elementary symmetric polynomials.
  1926. Explanation
  1927. ===========
  1928. If this :py:class:`~.PolyElement` belongs to a ring of $n$ variables,
  1929. we can try to write it as a function of the elementary symmetric
  1930. polynomials on $n$ variables. We compute a symmetric part, and a
  1931. remainder for any part we were not able to symmetrize.
  1932. Examples
  1933. ========
  1934. >>> from sympy.polys.rings import ring
  1935. >>> from sympy.polys.domains import ZZ
  1936. >>> R, x, y = ring("x,y", ZZ)
  1937. >>> f = x**2 + y**2
  1938. >>> f.symmetrize()
  1939. (x**2 - 2*y, 0, [(x, x + y), (y, x*y)])
  1940. >>> f = x**2 - y**2
  1941. >>> f.symmetrize()
  1942. (x**2 - 2*y, -2*y**2, [(x, x + y), (y, x*y)])
  1943. Returns
  1944. =======
  1945. Triple ``(p, r, m)``
  1946. ``p`` is a :py:class:`~.PolyElement` that represents our attempt
  1947. to express *self* as a function of elementary symmetric
  1948. polynomials. Each variable in ``p`` stands for one of the
  1949. elementary symmetric polynomials. The correspondence is given
  1950. by ``m``.
  1951. ``r`` is the remainder.
  1952. ``m`` is a list of pairs, giving the mapping from variables in
  1953. ``p`` to elementary symmetric polynomials.
  1954. The triple satisfies the equation ``p.compose(m) + r == self``.
  1955. If the remainder ``r`` is zero, *self* is symmetric. If it is
  1956. nonzero, we were not able to represent *self* as symmetric.
  1957. See Also
  1958. ========
  1959. sympy.polys.polyfuncs.symmetrize
  1960. References
  1961. ==========
  1962. .. [1] Lauer, E. Algorithms for symmetrical polynomials, Proc. 1976
  1963. ACM Symp. on Symbolic and Algebraic Computing, NY 242-247.
  1964. https://dl.acm.org/doi/pdf/10.1145/800205.806342
  1965. """
  1966. f = self.copy()
  1967. ring = f.ring
  1968. n = ring.ngens
  1969. if not n:
  1970. return f, ring.zero, []
  1971. polys = [ring.symmetric_poly(i+1) for i in range(n)]
  1972. poly_powers = {}
  1973. def get_poly_power(i, n):
  1974. if (i, n) not in poly_powers:
  1975. poly_powers[(i, n)] = polys[i]**n
  1976. return poly_powers[(i, n)]
  1977. indices = list(range(n - 1))
  1978. weights = list(range(n, 0, -1))
  1979. symmetric = ring.zero
  1980. while f:
  1981. _height, _monom, _coeff = -1, None, None
  1982. for i, (monom, coeff) in enumerate(f.terms()):
  1983. if all(monom[i] >= monom[i + 1] for i in indices):
  1984. height = max([n*m for n, m in zip(weights, monom)])
  1985. if height > _height:
  1986. _height, _monom, _coeff = height, monom, coeff
  1987. if _height != -1:
  1988. monom, coeff = _monom, _coeff
  1989. else:
  1990. break
  1991. exponents = []
  1992. for m1, m2 in zip(monom, monom[1:] + (0,)):
  1993. exponents.append(m1 - m2)
  1994. symmetric += ring.term_new(tuple(exponents), coeff)
  1995. product = coeff
  1996. for i, n in enumerate(exponents):
  1997. product *= get_poly_power(i, n)
  1998. f -= product
  1999. mapping = list(zip(ring.gens, polys))
  2000. return symmetric, f, mapping
  2001. def compose(f, x, a=None):
  2002. ring = f.ring
  2003. poly = ring.zero
  2004. gens_map = dict(zip(ring.gens, range(ring.ngens)))
  2005. if a is not None:
  2006. replacements = [(x, a)]
  2007. else:
  2008. if isinstance(x, list):
  2009. replacements = list(x)
  2010. elif isinstance(x, dict):
  2011. replacements = sorted(x.items(), key=lambda k: gens_map[k[0]])
  2012. else:
  2013. raise ValueError("expected a generator, value pair a sequence of such pairs")
  2014. for k, (x, g) in enumerate(replacements):
  2015. replacements[k] = (gens_map[x], ring.ring_new(g))
  2016. for monom, coeff in f.iterterms():
  2017. monom = list(monom)
  2018. subpoly = ring.one
  2019. for i, g in replacements:
  2020. n, monom[i] = monom[i], 0
  2021. if n:
  2022. subpoly *= g**n
  2023. subpoly = subpoly.mul_term((tuple(monom), coeff))
  2024. poly += subpoly
  2025. return poly
  2026. # TODO: following methods should point to polynomial
  2027. # representation independent algorithm implementations.
  2028. def pdiv(f, g):
  2029. return f.ring.dmp_pdiv(f, g)
  2030. def prem(f, g):
  2031. return f.ring.dmp_prem(f, g)
  2032. def pquo(f, g):
  2033. return f.ring.dmp_quo(f, g)
  2034. def pexquo(f, g):
  2035. return f.ring.dmp_exquo(f, g)
  2036. def half_gcdex(f, g):
  2037. return f.ring.dmp_half_gcdex(f, g)
  2038. def gcdex(f, g):
  2039. return f.ring.dmp_gcdex(f, g)
  2040. def subresultants(f, g):
  2041. return f.ring.dmp_subresultants(f, g)
  2042. def resultant(f, g):
  2043. return f.ring.dmp_resultant(f, g)
  2044. def discriminant(f):
  2045. return f.ring.dmp_discriminant(f)
  2046. def decompose(f):
  2047. if f.ring.is_univariate:
  2048. return f.ring.dup_decompose(f)
  2049. else:
  2050. raise MultivariatePolynomialError("polynomial decomposition")
  2051. def shift(f, a):
  2052. if f.ring.is_univariate:
  2053. return f.ring.dup_shift(f, a)
  2054. else:
  2055. raise MultivariatePolynomialError("polynomial shift")
  2056. def sturm(f):
  2057. if f.ring.is_univariate:
  2058. return f.ring.dup_sturm(f)
  2059. else:
  2060. raise MultivariatePolynomialError("sturm sequence")
  2061. def gff_list(f):
  2062. return f.ring.dmp_gff_list(f)
  2063. def sqf_norm(f):
  2064. return f.ring.dmp_sqf_norm(f)
  2065. def sqf_part(f):
  2066. return f.ring.dmp_sqf_part(f)
  2067. def sqf_list(f, all=False):
  2068. return f.ring.dmp_sqf_list(f, all=all)
  2069. def factor_list(f):
  2070. return f.ring.dmp_factor_list(f)