Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make PolyElement and DMP interfaces more compatible + misc fixes #747

Merged
merged 16 commits into from
Dec 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ language: python
dist: xenial
cache: pip
python:
- 3.6
- 3.7
- pypy3.5
env:
Expand All @@ -27,6 +26,12 @@ addons:
- liblapack-dev
- gfortran
- graphviz
- texlive-xetex
- texlive-latex-extra
- texlive-fonts-recommended
- latexmk
- lmodern
- xindy
stages:
- quality
- test
Expand All @@ -46,7 +51,8 @@ matrix:
- python -We:invalid -m compileall -f diofant -q
- travis_wait python setup.py flake8
- travis_wait 30 pylint -j1 diofant
- python setup.py build_sphinx -W -b html
- python setup.py build_sphinx -W -b html,latex
- make -C build/sphinx/latex all-pdf
- |
if [ "${TRAVIS_EVENT_TYPE}" = "cron" ]; then
rm -rf build/
Expand All @@ -59,15 +65,17 @@ matrix:
env:
-
script:
- python setup.py build_sphinx -W -b html
- python setup.py build_sphinx -W -b html,latex
- make -C build/sphinx/latex all-pdf
- git clone https://github.com/diofant/diofant.github.io.git sphinx_docs
- rm -rf sphinx_docs/.git
- rsync -a --delete build/sphinx/html/ sphinx_docs/latest/
- python setup.py sdist bdist_wheel
- VERSION=$(python -c 'import pkg_resources;print(pkg_resources.get_distribution("diofant").parsed_version.base_version)')
- cp -a build/sphinx/html "diofant-docs-html-${VERSION}"
- VERSION=$(python -c 'import diofant;print(diofant.__version__)')
- cp -a build/sphinx/html diofant-docs-html-${VERSION}
- zip -r dist/diofant-docs-html-${VERSION}.zip diofant-docs-html-${VERSION}
- SHORT_VERSION=$(echo ${VERSION}|sed 's/.0$//')
- cp -a build/sphinx/latex/diofant.pdf dist/diofant-docs-${VERSION}.pdf
- SHORT_VERSION=$(echo ${VERSION}|sed 's/\([0-9]\+\.[0-9]\+\).*$/\1/')
deploy:
- provider: pypi
user: skirpichev
Expand All @@ -94,8 +102,10 @@ matrix:
draft: true
file_glob: true
file: dist/*
name: "Diofant ${VERSION}"
body: "See [release notes](https://diofant.readthedocs.io/\
en/latest/release/notes-${SHORT_VERSION}.html)."
prerelease: true
on:
tags: true
condition: "$TRAVIS_TAG =~ ^v[0-9]+\\.[0-9]+\\.[0-9]+.*$"
Expand Down
10 changes: 7 additions & 3 deletions diofant/integrals/risch.py
Original file line number Diff line number Diff line change
Expand Up @@ -897,7 +897,9 @@ def splitfactor_sqf(p, DE, coefficientD=False, z=None, basic=False):

S = []
N = []
p_sqf = p.sqf_list_include()
p_c, p_sqf = p.sqf_list()
if p_c != 1:
p_sqf.insert(0, (Poly(p_c, DE.t), 1))
if p.is_zero:
return ((p, 1),), ()

Expand Down Expand Up @@ -1194,7 +1196,8 @@ def residue_reduce(a, d, DE, z=None, invert=True):
continue
h_lc = Poly(h.as_poly(DE.t).LC(), DE.t, field=True)

h_lc_sqf = h_lc.sqf_list_include()
h_lc_c, h_lc_sqf = h_lc.sqf_list()
h_lc_sqf.insert(0, (Poly(h_lc_c, DE.t, field=True), 1))

for a, j in h_lc_sqf:
h = Poly(h, DE.t, field=True).exquo(Poly(gcd(a, s**j, *kkinv),
Expand All @@ -1212,7 +1215,8 @@ def residue_reduce(a, d, DE, z=None, invert=True):

h = Poly(dict(zip(h.monoms(), coeffs)), DE.t)

H.append((s, h))
if not s.is_one:
H.append((s, h))

b = all(not cancel(i.as_expr()).has(DE.t, z) for i, _ in Np)

Expand Down
13 changes: 6 additions & 7 deletions diofant/polys/compatibility.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
dmp_sub_term, dup_add, dup_add_term, dup_lshift,
dup_mul, dup_mul_term, dup_pexquo, dup_rshift,
dup_sqr, dup_sub, dup_sub_term)
from .densebasic import dmp_degree_in, dmp_LC, dmp_strip, dmp_to_dict
from .densebasic import (dmp_degree_in, dmp_LC, dmp_slice_in, dmp_strip,
dmp_to_dict)
from .densetools import (dmp_clear_denoms, dmp_compose, dmp_diff_eval_in,
dmp_diff_in, dmp_eval_in, dmp_eval_tail,
dmp_ground_content, dmp_ground_extract,
Expand Down Expand Up @@ -46,8 +47,7 @@
dup_isolate_real_roots_list,
dup_isolate_real_roots_sqf, dup_refine_real_root,
dup_root_upper_bound, dup_sturm)
from .sqfreetools import (dmp_sqf_list, dmp_sqf_list_include, dmp_sqf_norm,
dmp_sqf_p, dmp_sqf_part)
from .sqfreetools import dmp_sqf_list, dmp_sqf_norm, dmp_sqf_p, dmp_sqf_part


__all__ = 'IPolys',
Expand Down Expand Up @@ -207,6 +207,9 @@ def dmp_degree_in(self, f, j):
def dmp_diff_in(self, f, m, j):
return self.from_dense(dmp_diff_in(self.to_dense(f), m, j, self.ngens-1, self.domain))

def dmp_slice_in(self, f, m, n, j=0):
return self.from_dense(dmp_slice_in(self.to_dense(f), m, n, j, self.ngens-1, self.domain))

def dmp_integrate_in(self, f, m, j):
return self.from_dense(dmp_integrate_in(self.to_dense(f), m, j, self.ngens-1, self.domain))

Expand Down Expand Up @@ -523,10 +526,6 @@ def dmp_sqf_list(self, f):
coeff, factors = dmp_sqf_list(self.to_dense(f), self.ngens-1, self.domain)
return coeff, [(self.from_dense(g), k) for g, k in factors]

def dmp_sqf_list_include(self, f):
factors = dmp_sqf_list_include(self.to_dense(f), self.ngens-1, self.domain)
return [(self.from_dense(g), k) for g, k in factors]

def dup_root_upper_bound(self, f):
return dup_root_upper_bound(self.to_dense(f), self.domain)

Expand Down
2 changes: 1 addition & 1 deletion diofant/polys/densebasic.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ def degree_in(g, v, i, j):

def dmp_degree_list(f, u):
"""
Return a list of degrees of ``f`` in ``K[X]``.
Return a tuple of degrees of ``f`` in ``K[X]``.

Examples
========
Expand Down
8 changes: 4 additions & 4 deletions diofant/polys/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -568,17 +568,17 @@ def diff(self, x):

def __call__(self, *values):
if 0 < len(values) <= self.field.ngens:
return self.evaluate(list(zip(self.field.gens, values)))
return self.eval(list(zip(self.field.gens, values)))
else:
raise ValueError("expected at least 1 and at most %s values, got %s" % (self.field.ngens, len(values)))

def evaluate(self, x, a=None):
def eval(self, x, a=None):
if isinstance(x, list) and a is None:
x = [(X.to_poly(), a) for X, a in x]
numer, denom = self.numer.evaluate(x), self.denom.evaluate(x)
numer, denom = self.numer.eval(x), self.denom.eval(x)
else:
x = x.to_poly()
numer, denom = self.numer.evaluate(x, a), self.denom.evaluate(x, a)
numer, denom = self.numer.eval(x, a), self.denom.eval(x, a)

if self._extract_ground(denom) == (1, 1, None):
return numer
Expand Down
4 changes: 2 additions & 2 deletions diofant/polys/heuristicgcd.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ def heugcd(f, g):
cofactors = domain.cofactors if ring.is_univariate else heugcd

for i in range(query('HEU_GCD_MAX')):
ff = f.evaluate(x0, x)
gg = g.evaluate(x0, x)
ff = f.eval(x0, x)
gg = g.eval(x0, x)

if ff and gg:
h, cff, cfg = cofactors(ff, gg)
Expand Down
19 changes: 9 additions & 10 deletions diofant/polys/modulargcd.py
Original file line number Diff line number Diff line change
Expand Up @@ -492,13 +492,13 @@ def _modgcd_p(f, g, p, degbound, contbound):
a = random.sample(points, 1)[0]
points.remove(a)

if not evaltest.evaluate(0, a) % p:
if not evaltest.eval(0, a) % p:
continue

deltaa = delta.evaluate(0, a) % p
deltaa = delta.eval(0, a) % p

fa = f.evaluate(k-1, a).trunc_ground(p)
ga = g.evaluate(k-1, a).trunc_ground(p)
fa = f.eval(k-1, a).trunc_ground(p)
ga = g.eval(k-1, a).trunc_ground(p)

# polynomials in Z_p[x_0, ..., x_{k-2}]
ha = _modgcd_p(fa, ga, p, degbound, contbound)
Expand Down Expand Up @@ -526,8 +526,7 @@ def _modgcd_p(f, g, p, degbound, contbound):
h = _primitive(h, p)[1] * conth.set_ring(ring)
degyh = h.degree(k-1)

if degyh > degbound[k-1]:
return
assert degyh <= degbound[k-1]
if degyh < degbound[k-1]:
degbound[k-1] = degyh
raise ModularGCDFailed
Expand Down Expand Up @@ -608,7 +607,7 @@ def modgcd(f, g):
for i in range(k):
badprimes *= ring.domain.gcd(_swap(f, i).LC, _swap(g, i).LC)

degbound = [min(fdeg, gdeg) for fdeg, gdeg in zip(f.degrees(), g.degrees())]
degbound = [min(fdeg, gdeg) for fdeg, gdeg in zip(f.degree_list(), g.degree_list())]
contbound = list(degbound)

m = 1
Expand Down Expand Up @@ -977,7 +976,7 @@ def _evaluate_ground(f, i, a):
fa = ring.zero

for monom, coeff in f.items():
fa[monom] = coeff.evaluate(i, a)
fa[monom] = coeff.eval(i, a)

return fa

Expand Down Expand Up @@ -1057,9 +1056,9 @@ def _func_field_modgcd_p(f, g, minpoly, p):
points.remove(a)

if k == 1:
test = delta.evaluate(k-1, a) % p == 0
test = delta.eval(k-1, a) % p == 0
else:
test = delta.evaluate(k-1, a).trunc_ground(p) == 0
test = delta.eval(k-1, a).trunc_ground(p) == 0

if test:
continue
Expand Down
9 changes: 8 additions & 1 deletion diofant/polys/partfrac.py
Original file line number Diff line number Diff line change
Expand Up @@ -354,9 +354,16 @@ def apart_list_full_decomposition(P, Q, dummygen):
u = Function('u')(x)
a = Dummy('a')

Q_c, Q_sqf = Q.sqf_list()
if Q_c != 1 and Q_sqf:
if Q_sqf[0][1] == 1:
Q_sqf[0] = Q_c*Q_sqf[0][0], 1
else:
Q_sqf.insert(0, (Poly(Q_c, x), 1))

partial = []

for d, n in Q.sqf_list_include():
for d, n in Q_sqf:
b = d.as_expr()
U += [ u.diff(x, n - 1) ]

Expand Down
77 changes: 17 additions & 60 deletions diofant/polys/polyclasses.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""OO layer for several polynomial representations. """

from ..core import oo
from ..core.sympify import CantSympify
from .densearith import (dmp_abs, dmp_add, dmp_div, dmp_exquo,
dmp_exquo_ground, dmp_l1_norm, dmp_max_norm, dmp_mul,
Expand All @@ -27,8 +26,7 @@
dup_isolate_all_roots, dup_isolate_all_roots_sqf,
dup_isolate_real_roots, dup_isolate_real_roots_sqf,
dup_refine_real_root, dup_sturm)
from .sqfreetools import (dmp_sqf_list, dmp_sqf_list_include, dmp_sqf_norm,
dmp_sqf_p, dmp_sqf_part)
from .sqfreetools import dmp_sqf_list, dmp_sqf_norm, dmp_sqf_p, dmp_sqf_part


class DMP(CantSympify):
Expand Down Expand Up @@ -315,41 +313,6 @@ def total_degree(self):
"""Returns the total degree of ``self``. """
return max(sum(m) for m in self.monoms())

def homogenize(self, s):
"""Return homogeneous polynomial of ``self``"""
td = self.total_degree()
result = {}
new_symbol = (s == len(self.terms()[0][0]))
for term in self.terms():
d = sum(term[0])
if d < td:
i = td - d
else:
i = 0
if new_symbol:
result[term[0] + (i,)] = term[1]
else:
l = list(term[0])
l[s] += i
result[tuple(l)] = term[1]
return DMP(result, self.domain, self.lev + int(new_symbol))

def homogeneous_order(self):
"""Returns the homogeneous order of ``self``. """
if self.is_zero:
return -oo

monoms = self.monoms()
tdeg = sum(monoms[0])

for monom in monoms:
_tdeg = sum(monom)

if _tdeg != tdeg:
return

return tdeg

def LC(self):
"""Returns the leading coefficient of ``self``. """
return dmp_ground_LC(self.rep, self.lev, self.domain)
Expand All @@ -358,12 +321,12 @@ def TC(self):
"""Returns the trailing coefficient of ``self``. """
return dmp_ground_TC(self.rep, self.lev, self.domain)

def nth(self, *N):
def coeff(self, N):
"""Returns the ``n``-th coefficient of ``self``. """
if all(isinstance(n, int) for n in N):
if isinstance(N, tuple) and all(isinstance(n, int) for n in N):
return dmp_ground_nth(self.rep, N, self.lev, self.domain)
else:
raise TypeError("a sequence of integers expected")
raise TypeError("a tuple of integers expected")

def max_norm(self):
"""Returns maximum norm of ``self``. """
Expand Down Expand Up @@ -544,11 +507,6 @@ def sqf_list(self):
coeff, factors = dmp_sqf_list(self.rep, self.lev, self.domain)
return coeff, [(self.per(g), k) for g, k in factors]

def sqf_list_include(self):
"""Returns a list of square-free factors of ``self``. """
factors = dmp_sqf_list_include(self.rep, self.lev, self.domain)
return [(self.per(g), k) for g, k in factors]

def factor_list(self):
"""Returns a list of irreducible factors of ``self``. """
coeff, factors = dmp_factor_list(self.rep, self.lev, self.domain)
Expand Down Expand Up @@ -648,7 +606,19 @@ def is_monomial(self):
@property
def is_homogeneous(self):
"""Returns ``True`` if ``self`` is a homogeneous polynomial. """
return self.homogeneous_order() is not None
if self.is_zero:
return True

monoms = self.monoms()
tdeg = sum(monoms[0])

for monom in monoms:
_tdeg = sum(monom)

if _tdeg != tdeg:
return False

return True

@property
def is_irreducible(self):
Expand Down Expand Up @@ -731,18 +701,5 @@ def __eq__(self, other):

return False

def eq(self, other, strict=False):
if not strict:
return self.__eq__(other)
else:
return self._strict_eq(other)

def ne(self, other, strict=False):
return not self.eq(other, strict=strict)

def _strict_eq(self, other):
return (isinstance(other, self.__class__) and self.lev == other.lev
and self.domain == other.domain and self.rep == other.rep)

def __bool__(self):
return not dmp_zero_p(self.rep, self.lev)
Loading