本文整理汇总了Python中sympy.core.basic.preorder_traversal函数的典型用法代码示例。如果您正苦于以下问题:Python preorder_traversal函数的具体用法?Python preorder_traversal怎么用?Python preorder_traversal使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了preorder_traversal函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Python代码示例。
示例1: test_preorder_traversal
def test_preorder_traversal():
expr = Basic(b21, b3)
assert list(preorder_traversal(expr)) == [expr, b21, b2, b1, b1, b3, b2, b1]
assert list(preorder_traversal(("abc", ("d", "ef")))) == [("abc", ("d", "ef")), "abc", ("d", "ef"), "d", "ef"]
result = []
pt = preorder_traversal(expr)
for i in pt:
result.append(i)
if i == b2:
pt.skip()
assert result == [expr, b21, b2, b1, b3, b2]
w, x, y, z = symbols("w:z")
expr = z + w * (x + y)
assert list(preorder_traversal([expr], key=default_sort_key)) == [
[w * (x + y) + z],
w * (x + y) + z,
z,
w * (x + y),
w,
x + y,
x,
y,
]
示例2: test_preorder_traversal
def test_preorder_traversal():
expr = Basic(b21, b3)
assert list(preorder_traversal(expr)) == [expr, b21, b2, b1, b1, b3, b2, b1]
assert list(preorder_traversal(('abc', ('d', 'ef')))) == [
('abc', ('d', 'ef')), 'abc', ('d', 'ef'), 'd', 'ef']
result = []
pt = preorder_traversal(expr)
for i in pt:
result.append(i)
if i == b2:
pt.skip()
assert result == [expr, b21, b2, b1, b3, b2]
示例3: test_preorder_traversal
def test_preorder_traversal():
expr = Basic(b21, b3)
assert list(preorder_traversal(expr)) == [expr, b21, b2, b1, b1, b3, b2, b1]
assert list(preorder_traversal(('abc', ('d', 'ef')))) == [
('abc', ('d', 'ef')), 'abc', ('d', 'ef'), 'd', 'ef']
result = []
pt = preorder_traversal(expr)
for i in pt:
result.append(i)
if i == b2:
pt.skip()
assert result == [expr, b21, b2, b1, b3, b2]
w, x, y, z = symbols('w:z')
expr = z + w*(x+y)
assert list(preorder_traversal([expr], key=default_sort_key)) == \
[[w*(x + y) + z], w*(x + y) + z, z, w*(x + y), w, x + y, x, y]
示例4: sub_post
def sub_post(e):
""" Replace Neg(x) with -x.
"""
replacements = []
for node in preorder_traversal(e):
if isinstance(node, Neg):
replacements.append((node, -node.args[0]))
for node, replacement in replacements:
e = e.xreplace({node: replacement})
return e
示例5: sub_post
def sub_post(e):
""" Replace Neg(x) with -x.
"""
replacements = []
for node in preorder_traversal(e):
if isinstance(node, Mul) and node.args[:2] is (S.One, S.NegativeOne):
replacements.append((node, -node))
for node, replacement in replacements:
e = e.xreplace({node: replacement})
return e
示例6: sub_post
def sub_post(e):
""" Replace 1*-1*x with -x.
"""
replacements = []
for node in preorder_traversal(e):
if isinstance(node, Mul) and \
node.args[0] is S.One and node.args[1] is S.NegativeOne:
replacements.append((node, -Mul._from_args(node.args[2:])))
for node, replacement in replacements:
e = e.xreplace({node: replacement})
return e
示例7: combsimp
def combsimp(expr):
r"""
Simplify combinatorial expressions.
This function takes as input an expression containing factorials,
binomials, Pochhammer symbol and other "combinatorial" functions,
and tries to minimize the number of those functions and reduce
the size of their arguments.
The algorithm works by rewriting all combinatorial functions as
gamma functions and applying gammasimp() except simplification
steps that may make an integer argument non-integer. See docstring
of gammasimp for more information.
Then it rewrites expression in terms of factorials and binomials by
rewriting gammas as factorials and converting (a+b)!/a!b! into
binomials.
If expression has gamma functions or combinatorial functions
with non-integer argument, it is automatically passed to gammasimp.
Examples
========
>>> from sympy.simplify import combsimp
>>> from sympy import factorial, binomial, symbols
>>> n, k = symbols('n k', integer = True)
>>> combsimp(factorial(n)/factorial(n - 3))
n*(n - 2)*(n - 1)
>>> combsimp(binomial(n+1, k+1)/binomial(n, k))
(n + 1)/(k + 1)
"""
expr = expr.rewrite(gamma)
if any(isinstance(node, gamma) and not node.args[0].is_integer
for node in preorder_traversal(expr)):
return gammasimp(expr);
expr = _gammasimp(expr, as_comb = True)
expr = _gamma_as_comb(expr)
return expr
示例8: apart
def apart(f, x=None, full=False, **options):
"""
Compute partial fraction decomposition of a rational function.
Given a rational function ``f`` compute partial fraction decomposition
of ``f``. Two algorithms are available: one is based on undetermined
coefficients method and the other is Bronstein's full partial fraction
decomposition algorithm.
Examples
========
>>> from sympy.polys.partfrac import apart
>>> from sympy.abc import x, y
By default, using the undetermined coefficients method:
>>> apart(y/(x + 2)/(x + 1), x)
-y/(x + 2) + y/(x + 1)
You can choose Bronstein's algorithm by setting ``full=True``:
>>> apart(y/(x**2 + x + 1), x)
y/(x**2 + x + 1)
>>> apart(y/(x**2 + x + 1), x, full=True)
RootSum(_w**2 + _w + 1, Lambda(_a, (-2*_a*y/3 - y/3)/(-_a + x)))
See Also
========
apart_list, assemble_partfrac_list
"""
allowed_flags(options, [])
f = sympify(f)
if f.is_Atom:
return f
else:
P, Q = f.as_numer_denom()
_options = options.copy()
options = set_defaults(options, extension=True)
try:
(P, Q), opt = parallel_poly_from_expr((P, Q), x, **options)
except PolynomialError as msg:
if f.is_commutative:
raise PolynomialError(msg)
# non-commutative
if f.is_Mul:
c, nc = f.args_cnc(split_1=False)
nc = Mul(*[apart(i, x=x, full=full, **_options) for i in nc])
if c:
c = apart(Mul._from_args(c), x=x, full=full, **_options)
return c*nc
else:
return nc
elif f.is_Add:
c = []
nc = []
for i in f.args:
if i.is_commutative:
c.append(i)
else:
try:
nc.append(apart(i, x=x, full=full, **_options))
except NotImplementedError:
nc.append(i)
return apart(Add(*c), x=x, full=full, **_options) + Add(*nc)
else:
reps = []
pot = preorder_traversal(f)
pot.next()
for e in pot:
try:
reps.append((e, apart(e, x=x, full=full, **_options)))
pot.skip() # this was handled successfully
except NotImplementedError:
pass
return f.xreplace(dict(reps))
if P.is_multivariate:
fc = f.cancel()
if fc != f:
return apart(fc, x=x, full=full, **_options)
raise NotImplementedError(
"multivariate partial fraction decomposition")
common, P, Q = P.cancel(Q)
poly, P = P.div(Q, auto=True)
P, Q = P.rat_clear_denoms(Q)
if Q.degree() <= 1:
partial = P/Q
else:
if not full:
partial = apart_undetermined_coeffs(P, Q)
else:
#.........这里部分代码省略.........
示例9: apart
def apart(f, x=None, full=False, **options):
"""
Compute partial fraction decomposition of a rational function.
Given a rational function ``f``, computes the partial fraction
decomposition of ``f``. Two algorithms are available: One is based on the
undertermined coefficients method, the other is Bronstein's full partial
fraction decomposition algorithm.
The undetermined coefficients method (selected by ``full=False``) uses
polynomial factorization (and therefore accepts the same options as
factor) for the denominator. Per default it works over the rational
numbers, therefore decomposition of denominators with non-rational roots
(e.g. irrational, complex roots) is not supported by default (see options
of factor).
Bronstein's algorithm can be selected by using ``full=True`` and allows a
decomposition of denominators with non-rational roots. A human-readable
result can be obtained via ``doit()`` (see examples below).
Examples
========
>>> from sympy.polys.partfrac import apart
>>> from sympy.abc import x, y
By default, using the undetermined coefficients method:
>>> apart(y/(x + 2)/(x + 1), x)
-y/(x + 2) + y/(x + 1)
The undetermined coefficients method does not provide a result when the
denominators roots are not rational:
>>> apart(y/(x**2 + x + 1), x)
y/(x**2 + x + 1)
You can choose Bronstein's algorithm by setting ``full=True``:
>>> apart(y/(x**2 + x + 1), x, full=True)
RootSum(_w**2 + _w + 1, Lambda(_a, (-2*_a*y/3 - y/3)/(-_a + x)))
Calling ``doit()`` yields a human-readable result:
>>> apart(y/(x**2 + x + 1), x, full=True).doit()
(-y/3 - 2*y*(-1/2 - sqrt(3)*I/2)/3)/(x + 1/2 + sqrt(3)*I/2) + (-y/3 -
2*y*(-1/2 + sqrt(3)*I/2)/3)/(x + 1/2 - sqrt(3)*I/2)
See Also
========
apart_list, assemble_partfrac_list
"""
allowed_flags(options, [])
f = sympify(f)
if f.is_Atom:
return f
else:
P, Q = f.as_numer_denom()
_options = options.copy()
options = set_defaults(options, extension=True)
try:
(P, Q), opt = parallel_poly_from_expr((P, Q), x, **options)
except PolynomialError as msg:
if f.is_commutative:
raise PolynomialError(msg)
# non-commutative
if f.is_Mul:
c, nc = f.args_cnc(split_1=False)
nc = f.func(*nc)
if c:
c = apart(f.func._from_args(c), x=x, full=full, **_options)
return c*nc
else:
return nc
elif f.is_Add:
c = []
nc = []
for i in f.args:
if i.is_commutative:
c.append(i)
else:
try:
nc.append(apart(i, x=x, full=full, **_options))
except NotImplementedError:
nc.append(i)
return apart(f.func(*c), x=x, full=full, **_options) + f.func(*nc)
else:
reps = []
pot = preorder_traversal(f)
next(pot)
for e in pot:
try:
reps.append((e, apart(e, x=x, full=full, **_options)))
pot.skip() # this was handled successfully
except NotImplementedError:
#.........这里部分代码省略.........
示例10: _mask_nc
def _mask_nc(eq):
"""Return ``eq`` with non-commutative objects replaced with dummy
symbols. A dictionary that can be used to restore the original
values is returned: if it is None, the expression is
noncommutative and cannot be made commutative. The third value
returned is a list of any non-commutative symbols that appear
in the returned equation.
Notes
=====
All non-commutative objects other than Symbols are replaced with
a non-commutative Symbol. Identical objects will be identified
by identical symbols.
If there is only 1 non-commutative object in an expression it will
be replaced with a commutative symbol. Otherwise, the non-commutative
entities are retained and the calling routine should handle
replacements in this case since some care must be taken to keep
track of the ordering of symbols when they occur within Muls.
Examples
========
>>> from sympy.physics.secondquant import Commutator, NO, F, Fd
>>> from sympy import Dummy, symbols, Sum, Mul, Basic
>>> from sympy.abc import x, y
>>> from sympy.core.exprtools import _mask_nc
>>> A, B, C = symbols('A,B,C', commutative=False)
>>> Dummy._count = 0 # reset for doctest purposes
One nc-symbol:
>>> _mask_nc(A**2 - x**2)
(_0**2 - x**2, {_0: A}, [])
Multiple nc-symbols:
>>> _mask_nc(A**2 - B**2)
(A**2 - B**2, None, [A, B])
An nc-object with nc-symbols but no others outside of it:
>>> _mask_nc(1 + x*Commutator(A, B))
(_1*x + 1, {_1: Commutator(A, B)}, [])
>>> _mask_nc(NO(Fd(x)*F(y)))
(_2, {_2: NO(CreateFermion(x)*AnnihilateFermion(y))}, [])
Multiple nc-objects:
>>> eq = x*Commutator(A, B) + x*Commutator(A, C)*Commutator(A, B)
>>> _mask_nc(eq)
(x*_3 + x*_4*_3, {_3: Commutator(A, B), _4: Commutator(A, C)}, [_3, _4])
Multiple nc-objects and nc-symbols:
>>> eq = A*Commutator(A, B) + B*Commutator(A, C)
>>> _mask_nc(eq)
(A*_5 + B*_6, {_5: Commutator(A, B), _6: Commutator(A, C)}, [_5, _6, A, B])
If there is an object that:
- doesn't contain nc-symbols
- but has arguments which derive from Basic, not Expr
- and doesn't define an _eval_is_commutative routine
then it will give False (or None?) for the is_commutative test. Such
objects are also removed by this routine:
>>> from sympy import Basic, Mul
>>> eq = (1 + Mul(Basic(), Basic(), evaluate=False))
>>> eq.is_commutative
False
>>> _mask_nc(eq)
(_7**2 + 1, {_7: Basic()}, [])
"""
expr = eq
if expr.is_commutative:
return eq, {}, []
# identify nc-objects; symbols and other
rep = []
nc_obj = set()
nc_syms = set()
pot = preorder_traversal(expr, keys=default_sort_key)
for i, a in enumerate(pot):
if any(a == r[0] for r in rep):
pot.skip()
elif not a.is_commutative:
if a.is_Symbol:
nc_syms.add(a)
elif not (a.is_Add or a.is_Mul or a.is_Pow):
if all(s.is_commutative for s in a.free_symbols):
rep.append((a, Dummy()))
else:
nc_obj.add(a)
pot.skip()
# If there is only one nc symbol or object, it can be factored regularly
# but polys is going to complain, so replace it with a Dummy.
if len(nc_obj) == 1 and not nc_syms:
#.........这里部分代码省略.........
示例11: minimal_polynomial
def minimal_polynomial(ex, x=None, **args):
"""
Computes the minimal polynomial of an algebraic element.
Parameters
==========
ex : algebraic element expression
x : independent variable of the minimal polynomial
Options
=======
compose : if ``True`` ``_minpoly_compose`` is used, if ``False`` the ``groebner`` algorithm
polys : if ``True`` returns a ``Poly`` object
domain : ground domain
Notes
=====
By default ``compose=True``, the minimal polynomial of the subexpressions of ``ex``
are computed, then the arithmetic operations on them are performed using the resultant
and factorization.
If ``compose=False``, a bottom-up algorithm is used with ``groebner``.
The default algorithm stalls less frequently.
If no ground domain is given, it will be generated automatically from the expression.
Examples
========
>>> from sympy import minimal_polynomial, sqrt, solve, QQ
>>> from sympy.abc import x, y
>>> minimal_polynomial(sqrt(2), x)
x**2 - 2
>>> minimal_polynomial(sqrt(2), x, domain=QQ.algebraic_field(sqrt(2)))
x - sqrt(2)
>>> minimal_polynomial(sqrt(2) + sqrt(3), x)
x**4 - 10*x**2 + 1
>>> minimal_polynomial(solve(x**3 + x + 3)[0], x)
x**3 + x + 3
>>> minimal_polynomial(sqrt(y), x)
x**2 - y
"""
from sympy.polys.polytools import degree
from sympy.polys.domains import FractionField
from sympy.core.basic import preorder_traversal
compose = args.get('compose', True)
polys = args.get('polys', False)
dom = args.get('domain', None)
ex = sympify(ex)
for expr in preorder_traversal(ex):
if expr.is_AlgebraicNumber:
compose = False
break
if x is not None:
x, cls = sympify(x), Poly
else:
x, cls = Dummy('x'), PurePoly
if not dom:
dom = FractionField(QQ, list(ex.free_symbols)) if ex.free_symbols else QQ
if hasattr(dom, 'symbols') and x in dom.symbols:
raise GeneratorsError("the variable %s is an element of the ground domain %s" % (x, dom))
if compose:
result = _minpoly_compose(ex, x, dom)
result = result.primitive()[1]
c = result.coeff(x**degree(result, x))
if c.is_negative:
result = expand_mul(-result)
return cls(result, x, field=True) if polys else result.collect(x)
if not dom.is_QQ:
raise NotImplementedError("groebner method only works for QQ")
result = _minpoly_groebner(ex, x, cls)
return cls(result, x, field=True) if polys else result.collect(x)
示例12: cse
def cse(exprs, symbols=None, optimizations=None, postprocess=None):
""" Perform common subexpression elimination on an expression.
Parameters
==========
exprs : list of sympy expressions, or a single sympy expression
The expressions to reduce.
symbols : infinite iterator yielding unique Symbols
The symbols used to label the common subexpressions which are pulled
out. The ``numbered_symbols`` generator is useful. The default is a
stream of symbols of the form "x0", "x1", etc. This must be an infinite
iterator.
optimizations : list of (callable, callable) pairs, optional
The (preprocessor, postprocessor) pairs. If not provided,
``sympy.simplify.cse.cse_optimizations`` is used.
postprocess : a function which accepts the two return values of cse and
returns the desired form of output from cse, e.g. if you want the
replacements reversed the function might be the following lambda:
lambda r, e: return reversed(r), e
Returns
=======
replacements : list of (Symbol, expression) pairs
All of the common subexpressions that were replaced. Subexpressions
earlier in this list might show up in subexpressions later in this list.
reduced_exprs : list of sympy expressions
The reduced expressions with all of the replacements above.
"""
from sympy.matrices import Matrix
from sympy.simplify.simplify import fraction
if symbols is None:
symbols = numbered_symbols()
else:
# In case we get passed an iterable with an __iter__ method instead of
# an actual iterator.
symbols = iter(symbols)
seen_subexp = set()
muls = set()
adds = set()
to_eliminate = []
to_eliminate_ops_count = []
if optimizations is None:
# Pull out the default here just in case there are some weird
# manipulations of the module-level list in some other thread.
optimizations = list(cse_optimizations)
# Handle the case if just one expression was passed.
if isinstance(exprs, Basic):
exprs = [exprs]
# Preprocess the expressions to give us better optimization opportunities.
reduced_exprs = [preprocess_for_cse(e, optimizations) for e in exprs]
# Find all of the repeated subexpressions.
def insert(subtree):
'''This helper will insert the subtree into to_eliminate while
maintaining the ordering by op count and will skip the insertion
if subtree is already present.'''
ops_count = (subtree.count_ops(), subtree.is_Mul) # prefer non-Mul to Mul
index_to_insert = bisect.bisect(to_eliminate_ops_count, ops_count)
# all i up to this index have op count <= the current op count
# so check that subtree is not yet present from this index down
# (if necessary) to zero.
for i in xrange(index_to_insert - 1, -1, -1):
if to_eliminate_ops_count[i] == ops_count and \
subtree == to_eliminate[i]:
return # already have it
to_eliminate_ops_count.insert(index_to_insert, ops_count)
to_eliminate.insert(index_to_insert, subtree)
for expr in reduced_exprs:
if not isinstance(expr, Basic):
continue
pt = preorder_traversal(expr, key=default_sort_key)
for subtree in pt:
inv = 1/subtree if subtree.is_Pow else None
if subtree.is_Atom or iterable(subtree) or inv and inv.is_Atom:
# Exclude atoms, since there is no point in renaming them.
continue
if subtree in seen_subexp:
if inv and _coeff_isneg(subtree.exp):
# save the form with positive exponent
subtree = inv
insert(subtree)
pt.skip()
continue
if inv and inv in seen_subexp:
if _coeff_isneg(subtree.exp):
# save the form with positive exponent
subtree = inv
insert(subtree)
pt.skip()
continue
#.........这里部分代码省略.........
示例13: _mask_nc
#.........这里部分代码省略.........
>>> _mask_nc(A**2 - x**2, 'd')
(_d0**2 - x**2, {_d0: A}, [])
Multiple nc-symbols:
>>> _mask_nc(A**2 - B**2, 'd')
(A**2 - B**2, None, [A, B])
An nc-object with nc-symbols but no others outside of it:
>>> _mask_nc(1 + x*Commutator(A, B), 'd')
(_d0*x + 1, {_d0: Commutator(A, B)}, [])
>>> _mask_nc(NO(Fd(x)*F(y)), 'd')
(_d0, {_d0: NO(CreateFermion(x)*AnnihilateFermion(y))}, [])
Multiple nc-objects:
>>> eq = x*Commutator(A, B) + x*Commutator(A, C)*Commutator(A, B)
>>> _mask_nc(eq, 'd')
(x*_d0 + x*_d1*_d0, {_d0: Commutator(A, B), _d1: Commutator(A, C)}, [_d0, _d1])
Multiple nc-objects and nc-symbols:
>>> eq = A*Commutator(A, B) + B*Commutator(A, C)
>>> _mask_nc(eq, 'd')
(A*_d0 + B*_d1, {_d0: Commutator(A, B), _d1: Commutator(A, C)}, [_d0, _d1, A, B])
If there is an object that:
- doesn't contain nc-symbols
- but has arguments which derive from Basic, not Expr
- and doesn't define an _eval_is_commutative routine
then it will give False (or None?) for the is_commutative test. Such
objects are also removed by this routine:
>>> from sympy import Basic
>>> eq = (1 + Mul(Basic(), Basic(), evaluate=False))
>>> eq.is_commutative
False
>>> _mask_nc(eq, 'd')
(_d0**2 + 1, {_d0: Basic()}, [])
"""
name = name or 'mask'
# Make Dummy() append sequential numbers to the name
def numbered_names():
i = 0
while True:
yield name + str(i)
i += 1
names = numbered_names()
def Dummy(*args, **kwargs):
from sympy import Dummy
return Dummy(next(names), *args, **kwargs)
expr = eq
if expr.is_commutative:
return eq, {}, []
# identify nc-objects; symbols and other
rep = []
nc_obj = set()
nc_syms = set()
pot = preorder_traversal(expr, keys=default_sort_key)
for i, a in enumerate(pot):
if any(a == r[0] for r in rep):
pot.skip()
elif not a.is_commutative:
if a.is_Symbol:
nc_syms.add(a)
elif not (a.is_Add or a.is_Mul or a.is_Pow):
if all(s.is_commutative for s in a.free_symbols):
rep.append((a, Dummy()))
else:
nc_obj.add(a)
pot.skip()
# If there is only one nc symbol or object, it can be factored regularly
# but polys is going to complain, so replace it with a Dummy.
if len(nc_obj) == 1 and not nc_syms:
rep.append((nc_obj.pop(), Dummy()))
elif len(nc_syms) == 1 and not nc_obj:
rep.append((nc_syms.pop(), Dummy()))
# Any remaining nc-objects will be replaced with an nc-Dummy and
# identified as an nc-Symbol to watch out for
nc_obj = sorted(nc_obj, key=default_sort_key)
for n in nc_obj:
nc = Dummy(commutative=False)
rep.append((n, nc))
nc_syms.add(nc)
expr = expr.subs(rep)
nc_syms = list(nc_syms)
nc_syms.sort(key=default_sort_key)
return expr, {v: k for k, v in rep} or None, nc_syms
示例14: minimal_polynomial
def minimal_polynomial(ex, x=None, compose=True, polys=False, domain=None):
"""
Computes the minimal polynomial of an algebraic element.
Parameters
==========
ex : Expr
Element or expression whose minimal polynomial is to be calculated.
x : Symbol, optional
Independent variable of the minimal polynomial
compose : boolean, optional (default=True)
Method to use for computing minimal polynomial. If ``compose=True``
(default) then ``_minpoly_compose`` is used, if ``compose=False`` then
groebner bases are used.
polys : boolean, optional (default=False)
If ``True`` returns a ``Poly`` object else an ``Expr`` object.
domain : Domain, optional
Ground domain
Notes
=====
By default ``compose=True``, the minimal polynomial of the subexpressions of ``ex``
are computed, then the arithmetic operations on them are performed using the resultant
and factorization.
If ``compose=False``, a bottom-up algorithm is used with ``groebner``.
The default algorithm stalls less frequently.
If no ground domain is given, it will be generated automatically from the expression.
Examples
========
>>> from sympy import minimal_polynomial, sqrt, solve, QQ
>>> from sympy.abc import x, y
>>> minimal_polynomial(sqrt(2), x)
x**2 - 2
>>> minimal_polynomial(sqrt(2), x, domain=QQ.algebraic_field(sqrt(2)))
x - sqrt(2)
>>> minimal_polynomial(sqrt(2) + sqrt(3), x)
x**4 - 10*x**2 + 1
>>> minimal_polynomial(solve(x**3 + x + 3)[0], x)
x**3 + x + 3
>>> minimal_polynomial(sqrt(y), x)
x**2 - y
"""
from sympy.polys.polytools import degree
from sympy.polys.domains import FractionField
from sympy.core.basic import preorder_traversal
ex = sympify(ex)
if ex.is_number:
# not sure if it's always needed but try it for numbers (issue 8354)
ex = _mexpand(ex, recursive=True)
for expr in preorder_traversal(ex):
if expr.is_AlgebraicNumber:
compose = False
break
if x is not None:
x, cls = sympify(x), Poly
else:
x, cls = Dummy('x'), PurePoly
if not domain:
if ex.free_symbols:
domain = FractionField(QQ, list(ex.free_symbols))
else:
domain = QQ
if hasattr(domain, 'symbols') and x in domain.symbols:
raise GeneratorsError("the variable %s is an element of the ground "
"domain %s" % (x, domain))
if compose:
result = _minpoly_compose(ex, x, domain)
result = result.primitive()[1]
c = result.coeff(x**degree(result, x))
if c.is_negative:
result = expand_mul(-result)
return cls(result, x, field=True) if polys else result.collect(x)
if not domain.is_QQ:
raise NotImplementedError("groebner method only works for QQ")
result = _minpoly_groebner(ex, x, cls)
return cls(result, x, field=True) if polys else result.collect(x)
示例15: minimal_polynomial
def minimal_polynomial(ex, x=None, **args):
"""
Computes the minimal polynomial of an algebraic number.
Parameters
==========
ex : algebraic number expression
x : indipendent variable of the minimal polynomial
Options
=======
compose : if ``True`` _minpoly1`` is used, else the ``groebner`` algorithm
polys : if ``True`` returns a ``Poly`` object
Notes
=====
By default ``compose=True``, the minimal polynomial of the subexpressions of ``ex``
are computed, then the arithmetic operations on them are performed using the resultant
and factorization.
If ``compose=False``, a bottom-up algorithm is used with ``groebner``.
The default algorithm stalls less frequently.
Examples
========
>>> from sympy import minimal_polynomial, sqrt, solve
>>> from sympy.abc import x
>>> minimal_polynomial(sqrt(2), x)
x**2 - 2
>>> minimal_polynomial(sqrt(2) + sqrt(3), x)
x**4 - 10*x**2 + 1
>>> minimal_polynomial(solve(x**3 + x + 3)[0], x)
x**3 + x + 3
"""
from sympy.polys.polytools import degree
from sympy.core.function import expand_multinomial
from sympy.core.basic import preorder_traversal
compose = args.get('compose', True)
polys = args.get('polys', False)
ex = sympify(ex)
for expr in preorder_traversal(ex):
if expr.is_AlgebraicNumber:
compose = False
break
if ex.is_AlgebraicNumber:
compose = False
if x is not None:
x, cls = sympify(x), Poly
else:
x, cls = Dummy('x'), PurePoly
if compose:
result = _minpoly1(ex, x)
result = result.primitive()[1]
c = result.coeff(x**degree(result, x))
if c < 0:
result = expand_mul(-result)
c = -c
return cls(result, x, field=True) if polys else result
generator = numbered_symbols('a', cls=Dummy)
mapping, symbols, replace = {}, {}, []
def update_mapping(ex, exp, base=None):
a = generator.next()
symbols[ex] = a
if base is not None:
mapping[ex] = a**exp + base
else:
mapping[ex] = exp.as_expr(a)
return a
def bottom_up_scan(ex):
if ex.is_Atom:
if ex is S.ImaginaryUnit:
if ex not in mapping:
return update_mapping(ex, 2, 1)
else:
return symbols[ex]
elif ex.is_Rational:
return ex
elif ex.is_Add:
return Add(*[ bottom_up_scan(g) for g in ex.args ])
elif ex.is_Mul:
return Mul(*[ bottom_up_scan(g) for g in ex.args ])
elif ex.is_Pow:
if ex.exp.is_Rational:
if ex.exp < 0 and ex.base.is_Add:
#.........这里部分代码省略.........