Skip to content

Commit

Permalink
Refactored polynomials manipulation functions (#1899)
Browse files Browse the repository at this point in the history
In [1]: factor(3 + x - x*(1 + x) + x**2)
Out[1]: 3

In [2]: factor(3 + x - x*(1 + x) + x**2, frac=True)
Out[2]: 3

In [3]: factor(3 + x - x*(1 + x) + x**2, xfrac=True)
(...)
OptionError: 'xfrac' is not a valid option

In [4]: factor(3 + x - x*(1 + x) + x**2, all=True)
(...)
FlagError: 'all' flag is not allowed in this context
  • Loading branch information
mattpap authored and rlamy committed Apr 21, 2011
1 parent 12ac617 commit 7eb81c9
Show file tree
Hide file tree
Showing 11 changed files with 630 additions and 452 deletions.
1 change: 1 addition & 0 deletions sympy/polys/__init__.py
Expand Up @@ -2,6 +2,7 @@

from polytools import (
Poly, poly,
poly_from_expr,
parallel_poly_from_expr,
degree, degree_list,
LC, LM, LT,
Expand Down
2 changes: 1 addition & 1 deletion sympy/polys/constructor.py
Expand Up @@ -180,7 +180,7 @@ def _construct_expression(coeffs, opt):

def construct_domain(obj, **args):
"""Construct a minimal domain for the list of coefficients. """
opt = build_options(**args)
opt = build_options(args)

if isinstance(obj, dict):
monoms, coeffs = zip(*obj.items())
Expand Down
3 changes: 2 additions & 1 deletion sympy/polys/domains/domain.py
Expand Up @@ -190,7 +190,8 @@ def unify(K0, K1, gens=None):
if gens is not None:
if (K0.is_Composite and (set(K0.gens) & set(gens))) or (K1.is_Composite and (set(K1.gens) & set(gens))):
raise UnificationFailed("can't unify %s with %s, given %s generators" % (K0, K1, tuple(gens)))
elif K0 == K1:

if K0 == K1:
return K0

if not K0.has_CharacteristicZero:
Expand Down
3 changes: 2 additions & 1 deletion sympy/polys/numberfields.py
Expand Up @@ -74,7 +74,8 @@ def bottom_up_scan(ex):

alg = ex.base - coeff

inverse = invert(elt.gen + coeff, elt)
# XXX: turn this into eval()
inverse = invert(elt.gen + coeff, elt).as_basic()
base = inverse.subs(elt.gen, alg).expand()

if ex.exp == -1:
Expand Down
13 changes: 7 additions & 6 deletions sympy/polys/partfrac.py
@@ -1,11 +1,9 @@
"""Algorithms for partial fraction decomposition of rational functions. """

from sympy.core import S, Symbol, Function, Lambda
from sympy.polys import Poly, RootSum, cancel
from sympy.core import S, sympify, Symbol, Function, Lambda
from sympy.polys import Poly, RootSum, cancel, parallel_poly_from_expr
from sympy.utilities import numbered_symbols, take, threaded

from sympy.polys.polytools import _polify_basic

@threaded
def apart(f, x=None, full=False):
"""Compute partial fraction decomposition of a rational function.
Expand All @@ -25,16 +23,19 @@ def apart(f, x=None, full=False):
y/(1 + x) - y/(2 + x)
"""
f = sympify(f)

if f.is_Atom:
return f
else:
P, Q = f.as_numer_denom()

if x is None:
gens = ()
else:
gens = (x,)

P, Q = f.as_numer_denom()
P, Q = _polify_basic(P, Q, *gens)
(P, Q), opt = parallel_poly_from_expr((P, Q), *gens)

if P.is_multivariate:
raise NotImplementedError("multivariate partial fraction decomposition")
Expand Down
32 changes: 28 additions & 4 deletions sympy/polys/polyerrors.py
Expand Up @@ -54,6 +54,16 @@ class UnificationFailed(Exception):
class GeneratorsNeeded(Exception):
pass

class ComputationFailed(Exception):

def __init__(self, func, nargs, exc):
self.func = func
self.nargs = nargs
self.exc = exc

def __str__(self):
return "%s(%s) failed without generators" % (self.func, ', '.join(map(str, self.exc.exprs[:self.nargs])))

class GeneratorsError(Exception):
pass

Expand All @@ -66,11 +76,25 @@ class MultivariatePolynomialError(PolynomialError):
class OptionError(Exception):
pass

class FlagError(OptionError):
pass

class PolificationFailed(PolynomialError):

def __init__(self, origs, exprs):
self.origs = tuple(origs)
self.exprs = tuple(exprs)
def __init__(self, origs, exprs, seq=False):
if not seq:
self.orig = origs
self.expr = exprs
self.origs = [origs]
self.exprs = [exprs]
else:
self.origs = origs
self.exprs = exprs

self.seq = seq

def __str__(self): # pragma: no cover
return "can't construct polynomials from %s" % ', '.join(map(str, self.origs))
if not self.seq:
return "can't construct a polynomial from %s" % str(self.orig)
else:
return "can't construct polynomials from %s" % ', '.join(map(str, self.origs))
54 changes: 46 additions & 8 deletions sympy/polys/polyoptions.py
Expand Up @@ -6,6 +6,7 @@
PolynomialError,
GeneratorsError,
OptionError,
FlagError,
)

from sympy.polys.monomialtools import monomial_key
Expand All @@ -21,6 +22,8 @@ class Option(object):

option = None

is_Flag = False

requires = []
excludes = []

Expand All @@ -39,6 +42,11 @@ def postprocess(cls, options):
""" """
pass

class Flag(Option):
""" """

is_Flag = True

class BooleanOption(Option):
""" """

Expand All @@ -64,9 +72,6 @@ def getter(self):
setattr(Options, cls.option, getter)
Options.__options__[cls.option] = cls

class Flag(object):
""" """

class Options(dict):
""" """

Expand Down Expand Up @@ -153,6 +158,10 @@ class Expand(BooleanOption):
requires = []
excludes = []

@classmethod
def default(cls):
return True

class Gens(Option):
""" """

Expand Down Expand Up @@ -507,7 +516,18 @@ class Monic(BooleanOption, Flag):
def default(cls):
return True

class Gen(Option, Flag):
class All(BooleanOption, Flag):
""" """

__metaclass__ = OptionType

option = 'all'

@classmethod
def default(cls):
return False

class Gen(Flag):
""" """

__metaclass__ = OptionType
Expand All @@ -517,16 +537,34 @@ class Gen(Option, Flag):
requires = []
excludes = []

@classmethod
def default(cls):
return 0

@classmethod
def preprocess(cls, gen):
if isinstance(gen, Basic):
if isinstance(gen, (Basic, int)):
return gen
else:
raise OptionError("invalid argument for 'gen' option")

def build_options(**args):
def build_options(gens, args=None):
"""Construct options from keyword arguments or ... options. """
if len(args) != 1 or 'opt' not in args:
return Options((), args)
if args is None:
gens, args = (), gens

if len(args) != 1 or 'opt' not in args or gens:
return Options(gens, args)
else:
return args['opt']

def allowed_flags(args, flags):
""" """
flags = set(flags)

for arg in args.iterkeys():
try:
if Options.__options__[arg].is_Flag and not arg in flags:
raise FlagError("'%s' flag is not allowed in this context" % arg)
except KeyError:
raise OptionError("'%s' is not a valid option" % arg)

0 comments on commit 7eb81c9

Please sign in to comment.