Skip to content

Commit

Permalink
polys: alter construction of RootOf's with algebraic coefficients
Browse files Browse the repository at this point in the history
Now we don't canonicalize polynomial coefficients to be integers,
instead expand_func() helper does this job.
  • Loading branch information
skirpichev committed Aug 23, 2018
1 parent fdabee0 commit 1aa86fa
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 26 deletions.
38 changes: 21 additions & 17 deletions diofant/polys/rootoftools.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class RootOf(Expr):
Examples
========
>>> RootOf(x**3 + I*x + 2, 0, extension=True)
>>> expand_func(RootOf(x**3 + I*x + 2, 0, extension=True))
RootOf(x**6 + 4*x**3 + x**2 + 4, 1)
"""

Expand Down Expand Up @@ -121,22 +121,6 @@ def __new__(cls, f, x, index=None, radicals=True, expand=True,

coeff, poly = preprocess_roots(poly, extension=extension)

if poly.domain.is_AlgebraicField and extension:
if poly.domain.domain.is_AlgebraicField:
new_domain = QQ.algebraic_field(poly.domain.domain.ext,
poly.domain.ext)
poly = poly.set_domain(new_domain)
x, y = poly.gen, Dummy('y')
p = sum(Poly(c.rep, y)*x**n for (n,), c in poly.rep.terms()).inject(x)
q = poly.domain.minpoly.eval(y)
minpoly = PurePoly(resultant(p, q, y), x)
for idx, r in enumerate(minpoly.all_roots()): # pragma: no branch
if poly.as_expr().evalf(2, subs={x: r}, chop=True) == 0:
index -= 1
if index == -1:
break
poly, index = minpoly, idx

if poly.domain.is_IntegerRing or poly.domain == QQ.algebraic_field(I):
root = cls._indexed_root(poly, index)
else:
Expand Down Expand Up @@ -175,6 +159,26 @@ def args(self):
def free_symbols(self):
return self.poly.free_symbols

def _eval_expand_func(self, **hints):
poly = self.poly
index = self.index
if poly.domain.is_AlgebraicField:
if poly.domain.domain.is_AlgebraicField:
new_domain = QQ.algebraic_field(poly.domain.domain.ext,
poly.domain.ext)
poly = poly.set_domain(new_domain)
x, y = poly.gen, Dummy('y')
p = sum(Poly(c.rep, y)*x**n for (n,), c in poly.rep.terms()).inject(x)
q = poly.domain.minpoly.eval(y)
minpoly = PurePoly(resultant(p, q, y), x)
for idx, r in enumerate(minpoly.all_roots()): # pragma: no branch
if poly.as_expr().evalf(2, subs={x: r}, chop=True) == 0:
index -= 1
if index == -1:
break
poly, index = minpoly, idx
return self.func(poly.as_expr(), poly.gen, index)

def _eval_is_real(self):
try:
return self.index < len(_reals_cache[self.poly.rep])
Expand Down
20 changes: 11 additions & 9 deletions diofant/polys/tests/test_rootoftools.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import pytest

from diofant import (Eq, Float, Function, I, Lambda, Pow, Rational, Symbol,
conjugate, exp, false, legendre_poly, log, oo, root,
solve, sqrt, tan, true)
conjugate, exp, expand_func, false, legendre_poly, log,
oo, root, solve, sqrt, tan, true)
from diofant.abc import a, b, r, x, y, z
from diofant.polys.polyerrors import (GeneratorsNeeded,
MultivariatePolynomialError,
Expand Down Expand Up @@ -543,12 +543,14 @@ def test_rewrite():


@pytest.mark.slow
def test_RootOf_algebraic_domain():
assert RootOf(x**3 + I*x + 2, 0,
extension=True) == RootOf(x**6 + 4*x**3 + x**2 + 4, 1)
assert RootOf(x**3 + I*x + 2, 1,
extension=True) == RootOf(x**6 + 4*x**3 + x**2 + 4, 3)
def test_RootOf_expand_func():
r0 = RootOf(x**3 + x + 2, 0)
assert expand_func(r0) == r0
r0 = RootOf(x**3 + I*x + 2, 0, extension=True)
assert expand_func(r0) == RootOf(x**6 + 4*x**3 + x**2 + 4, 1)
r1 = RootOf(x**3 + I*x + 2, 1, extension=True)
assert expand_func(r1) == RootOf(x**6 + 4*x**3 + x**2 + 4, 3)

e = RootOf(x**4 + sqrt(2)*x**3 - I*x + 1, 0, extension=True)
assert e == RootOf(x**16 - 4*x**14 + 8*x**12 - 6*x**10 +
10*x**8 + 5*x**4 + 2*x**2 + 1, 1)
assert expand_func(e) == RootOf(x**16 - 4*x**14 + 8*x**12 - 6*x**10 +
10*x**8 + 5*x**4 + 2*x**2 + 1, 1)
1 change: 1 addition & 0 deletions docs/release/notes-0.10.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ Compatibility breaks
* Removed ``@public`` decorator, see :pull:`666`.
* Removed ``dummy_eq()`` method from :class:`~diofant.core.basic.Basic`, see :pull:`666`.
* :class:`~diofant.core.function.Subs` now support only ``Subs(expr, (var1, val1), (var2, val2), ...)`` syntax, see :pull:`667`.
* :class:`~diofant.polys.rootoftools.RootOf` don't canonicalize anymore polynomials to have integer coefficients, use :func:`~diofant.core.function.expand_func` instead, see :pull:`679`.

Minor changes
=============
Expand Down

0 comments on commit 1aa86fa

Please sign in to comment.