switching to high quality piper tts and added label translations
This commit is contained in:
@@ -0,0 +1,915 @@
|
||||
from sympy.core import S, sympify, NumberKind
|
||||
from sympy.utilities.iterables import sift
|
||||
from sympy.core.add import Add
|
||||
from sympy.core.containers import Tuple
|
||||
from sympy.core.operations import LatticeOp, ShortCircuit
|
||||
from sympy.core.function import (Application, Lambda,
|
||||
ArgumentIndexError, DefinedFunction)
|
||||
from sympy.core.expr import Expr
|
||||
from sympy.core.exprtools import factor_terms
|
||||
from sympy.core.mod import Mod
|
||||
from sympy.core.mul import Mul
|
||||
from sympy.core.numbers import Rational
|
||||
from sympy.core.power import Pow
|
||||
from sympy.core.relational import Eq, Relational
|
||||
from sympy.core.singleton import Singleton
|
||||
from sympy.core.sorting import ordered
|
||||
from sympy.core.symbol import Dummy
|
||||
from sympy.core.rules import Transform
|
||||
from sympy.core.logic import fuzzy_and, fuzzy_or, _torf
|
||||
from sympy.core.traversal import walk
|
||||
from sympy.core.numbers import Integer
|
||||
from sympy.logic.boolalg import And, Or
|
||||
|
||||
|
||||
def _minmax_as_Piecewise(op, *args):
|
||||
# helper for Min/Max rewrite as Piecewise
|
||||
from sympy.functions.elementary.piecewise import Piecewise
|
||||
ec = []
|
||||
for i, a in enumerate(args):
|
||||
c = [Relational(a, args[j], op) for j in range(i + 1, len(args))]
|
||||
ec.append((a, And(*c)))
|
||||
return Piecewise(*ec)
|
||||
|
||||
|
||||
class IdentityFunction(Lambda, metaclass=Singleton):
|
||||
"""
|
||||
The identity function
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
>>> from sympy import Id, Symbol
|
||||
>>> x = Symbol('x')
|
||||
>>> Id(x)
|
||||
x
|
||||
|
||||
"""
|
||||
|
||||
_symbol = Dummy('x')
|
||||
|
||||
@property
|
||||
def signature(self):
|
||||
return Tuple(self._symbol)
|
||||
|
||||
@property
|
||||
def expr(self):
|
||||
return self._symbol
|
||||
|
||||
|
||||
Id = S.IdentityFunction
|
||||
|
||||
###############################################################################
|
||||
############################# ROOT and SQUARE ROOT FUNCTION ###################
|
||||
###############################################################################
|
||||
|
||||
|
||||
def sqrt(arg, evaluate=None):
|
||||
"""Returns the principal square root.
|
||||
|
||||
Parameters
|
||||
==========
|
||||
|
||||
evaluate : bool, optional
|
||||
The parameter determines if the expression should be evaluated.
|
||||
If ``None``, its value is taken from
|
||||
``global_parameters.evaluate``.
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
>>> from sympy import sqrt, Symbol, S
|
||||
>>> x = Symbol('x')
|
||||
|
||||
>>> sqrt(x)
|
||||
sqrt(x)
|
||||
|
||||
>>> sqrt(x)**2
|
||||
x
|
||||
|
||||
Note that sqrt(x**2) does not simplify to x.
|
||||
|
||||
>>> sqrt(x**2)
|
||||
sqrt(x**2)
|
||||
|
||||
This is because the two are not equal to each other in general.
|
||||
For example, consider x == -1:
|
||||
|
||||
>>> from sympy import Eq
|
||||
>>> Eq(sqrt(x**2), x).subs(x, -1)
|
||||
False
|
||||
|
||||
This is because sqrt computes the principal square root, so the square may
|
||||
put the argument in a different branch. This identity does hold if x is
|
||||
positive:
|
||||
|
||||
>>> y = Symbol('y', positive=True)
|
||||
>>> sqrt(y**2)
|
||||
y
|
||||
|
||||
You can force this simplification by using the powdenest() function with
|
||||
the force option set to True:
|
||||
|
||||
>>> from sympy import powdenest
|
||||
>>> sqrt(x**2)
|
||||
sqrt(x**2)
|
||||
>>> powdenest(sqrt(x**2), force=True)
|
||||
x
|
||||
|
||||
To get both branches of the square root you can use the rootof function:
|
||||
|
||||
>>> from sympy import rootof
|
||||
|
||||
>>> [rootof(x**2-3,i) for i in (0,1)]
|
||||
[-sqrt(3), sqrt(3)]
|
||||
|
||||
Although ``sqrt`` is printed, there is no ``sqrt`` function so looking for
|
||||
``sqrt`` in an expression will fail:
|
||||
|
||||
>>> from sympy.utilities.misc import func_name
|
||||
>>> func_name(sqrt(x))
|
||||
'Pow'
|
||||
>>> sqrt(x).has(sqrt)
|
||||
False
|
||||
|
||||
To find ``sqrt`` look for ``Pow`` with an exponent of ``1/2``:
|
||||
|
||||
>>> (x + 1/sqrt(x)).find(lambda i: i.is_Pow and abs(i.exp) is S.Half)
|
||||
{1/sqrt(x)}
|
||||
|
||||
See Also
|
||||
========
|
||||
|
||||
sympy.polys.rootoftools.rootof, root, real_root
|
||||
|
||||
References
|
||||
==========
|
||||
|
||||
.. [1] https://en.wikipedia.org/wiki/Square_root
|
||||
.. [2] https://en.wikipedia.org/wiki/Principal_value
|
||||
"""
|
||||
# arg = sympify(arg) is handled by Pow
|
||||
return Pow(arg, S.Half, evaluate=evaluate)
|
||||
|
||||
|
||||
def cbrt(arg, evaluate=None):
|
||||
"""Returns the principal cube root.
|
||||
|
||||
Parameters
|
||||
==========
|
||||
|
||||
evaluate : bool, optional
|
||||
The parameter determines if the expression should be evaluated.
|
||||
If ``None``, its value is taken from
|
||||
``global_parameters.evaluate``.
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
>>> from sympy import cbrt, Symbol
|
||||
>>> x = Symbol('x')
|
||||
|
||||
>>> cbrt(x)
|
||||
x**(1/3)
|
||||
|
||||
>>> cbrt(x)**3
|
||||
x
|
||||
|
||||
Note that cbrt(x**3) does not simplify to x.
|
||||
|
||||
>>> cbrt(x**3)
|
||||
(x**3)**(1/3)
|
||||
|
||||
This is because the two are not equal to each other in general.
|
||||
For example, consider `x == -1`:
|
||||
|
||||
>>> from sympy import Eq
|
||||
>>> Eq(cbrt(x**3), x).subs(x, -1)
|
||||
False
|
||||
|
||||
This is because cbrt computes the principal cube root, this
|
||||
identity does hold if `x` is positive:
|
||||
|
||||
>>> y = Symbol('y', positive=True)
|
||||
>>> cbrt(y**3)
|
||||
y
|
||||
|
||||
See Also
|
||||
========
|
||||
|
||||
sympy.polys.rootoftools.rootof, root, real_root
|
||||
|
||||
References
|
||||
==========
|
||||
|
||||
.. [1] https://en.wikipedia.org/wiki/Cube_root
|
||||
.. [2] https://en.wikipedia.org/wiki/Principal_value
|
||||
|
||||
"""
|
||||
return Pow(arg, Rational(1, 3), evaluate=evaluate)
|
||||
|
||||
|
||||
def root(arg, n, k=0, evaluate=None):
|
||||
r"""Returns the *k*-th *n*-th root of ``arg``.
|
||||
|
||||
Parameters
|
||||
==========
|
||||
|
||||
k : int, optional
|
||||
Should be an integer in $\{0, 1, ..., n-1\}$.
|
||||
Defaults to the principal root if $0$.
|
||||
|
||||
evaluate : bool, optional
|
||||
The parameter determines if the expression should be evaluated.
|
||||
If ``None``, its value is taken from
|
||||
``global_parameters.evaluate``.
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
>>> from sympy import root, Rational
|
||||
>>> from sympy.abc import x, n
|
||||
|
||||
>>> root(x, 2)
|
||||
sqrt(x)
|
||||
|
||||
>>> root(x, 3)
|
||||
x**(1/3)
|
||||
|
||||
>>> root(x, n)
|
||||
x**(1/n)
|
||||
|
||||
>>> root(x, -Rational(2, 3))
|
||||
x**(-3/2)
|
||||
|
||||
To get the k-th n-th root, specify k:
|
||||
|
||||
>>> root(-2, 3, 2)
|
||||
-(-1)**(2/3)*2**(1/3)
|
||||
|
||||
To get all n n-th roots you can use the rootof function.
|
||||
The following examples show the roots of unity for n
|
||||
equal 2, 3 and 4:
|
||||
|
||||
>>> from sympy import rootof
|
||||
|
||||
>>> [rootof(x**2 - 1, i) for i in range(2)]
|
||||
[-1, 1]
|
||||
|
||||
>>> [rootof(x**3 - 1,i) for i in range(3)]
|
||||
[1, -1/2 - sqrt(3)*I/2, -1/2 + sqrt(3)*I/2]
|
||||
|
||||
>>> [rootof(x**4 - 1,i) for i in range(4)]
|
||||
[-1, 1, -I, I]
|
||||
|
||||
SymPy, like other symbolic algebra systems, returns the
|
||||
complex root of negative numbers. This is the principal
|
||||
root and differs from the text-book result that one might
|
||||
be expecting. For example, the cube root of -8 does not
|
||||
come back as -2:
|
||||
|
||||
>>> root(-8, 3)
|
||||
2*(-1)**(1/3)
|
||||
|
||||
The real_root function can be used to either make the principal
|
||||
result real (or simply to return the real root directly):
|
||||
|
||||
>>> from sympy import real_root
|
||||
>>> real_root(_)
|
||||
-2
|
||||
>>> real_root(-32, 5)
|
||||
-2
|
||||
|
||||
Alternatively, the n//2-th n-th root of a negative number can be
|
||||
computed with root:
|
||||
|
||||
>>> root(-32, 5, 5//2)
|
||||
-2
|
||||
|
||||
See Also
|
||||
========
|
||||
|
||||
sympy.polys.rootoftools.rootof
|
||||
sympy.core.intfunc.integer_nthroot
|
||||
sqrt, real_root
|
||||
|
||||
References
|
||||
==========
|
||||
|
||||
.. [1] https://en.wikipedia.org/wiki/Square_root
|
||||
.. [2] https://en.wikipedia.org/wiki/Real_root
|
||||
.. [3] https://en.wikipedia.org/wiki/Root_of_unity
|
||||
.. [4] https://en.wikipedia.org/wiki/Principal_value
|
||||
.. [5] https://mathworld.wolfram.com/CubeRoot.html
|
||||
|
||||
"""
|
||||
n = sympify(n)
|
||||
if k:
|
||||
return Mul(Pow(arg, S.One/n, evaluate=evaluate), S.NegativeOne**(2*k/n), evaluate=evaluate)
|
||||
return Pow(arg, 1/n, evaluate=evaluate)
|
||||
|
||||
|
||||
def real_root(arg, n=None, evaluate=None):
|
||||
r"""Return the real *n*'th-root of *arg* if possible.
|
||||
|
||||
Parameters
|
||||
==========
|
||||
|
||||
n : int or None, optional
|
||||
If *n* is ``None``, then all instances of
|
||||
$(-n)^{1/\text{odd}}$ will be changed to $-n^{1/\text{odd}}$.
|
||||
This will only create a real root of a principal root.
|
||||
The presence of other factors may cause the result to not be
|
||||
real.
|
||||
|
||||
evaluate : bool, optional
|
||||
The parameter determines if the expression should be evaluated.
|
||||
If ``None``, its value is taken from
|
||||
``global_parameters.evaluate``.
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
>>> from sympy import root, real_root
|
||||
|
||||
>>> real_root(-8, 3)
|
||||
-2
|
||||
>>> root(-8, 3)
|
||||
2*(-1)**(1/3)
|
||||
>>> real_root(_)
|
||||
-2
|
||||
|
||||
If one creates a non-principal root and applies real_root, the
|
||||
result will not be real (so use with caution):
|
||||
|
||||
>>> root(-8, 3, 2)
|
||||
-2*(-1)**(2/3)
|
||||
>>> real_root(_)
|
||||
-2*(-1)**(2/3)
|
||||
|
||||
See Also
|
||||
========
|
||||
|
||||
sympy.polys.rootoftools.rootof
|
||||
sympy.core.intfunc.integer_nthroot
|
||||
root, sqrt
|
||||
"""
|
||||
from sympy.functions.elementary.complexes import Abs, im, sign
|
||||
from sympy.functions.elementary.piecewise import Piecewise
|
||||
if n is not None:
|
||||
return Piecewise(
|
||||
(root(arg, n, evaluate=evaluate), Or(Eq(n, S.One), Eq(n, S.NegativeOne))),
|
||||
(Mul(sign(arg), root(Abs(arg), n, evaluate=evaluate), evaluate=evaluate),
|
||||
And(Eq(im(arg), S.Zero), Eq(Mod(n, 2), S.One))),
|
||||
(root(arg, n, evaluate=evaluate), True))
|
||||
rv = sympify(arg)
|
||||
n1pow = Transform(lambda x: -(-x.base)**x.exp,
|
||||
lambda x:
|
||||
x.is_Pow and
|
||||
x.base.is_negative and
|
||||
x.exp.is_Rational and
|
||||
x.exp.p == 1 and x.exp.q % 2)
|
||||
return rv.xreplace(n1pow)
|
||||
|
||||
###############################################################################
|
||||
############################# MINIMUM and MAXIMUM #############################
|
||||
###############################################################################
|
||||
|
||||
|
||||
class MinMaxBase(Expr, LatticeOp):
|
||||
def __new__(cls, *args, **assumptions):
|
||||
from sympy.core.parameters import global_parameters
|
||||
evaluate = assumptions.pop('evaluate', global_parameters.evaluate)
|
||||
args = (sympify(arg) for arg in args)
|
||||
|
||||
# first standard filter, for cls.zero and cls.identity
|
||||
# also reshape Max(a, Max(b, c)) to Max(a, b, c)
|
||||
|
||||
if evaluate:
|
||||
try:
|
||||
args = frozenset(cls._new_args_filter(args))
|
||||
except ShortCircuit:
|
||||
return cls.zero
|
||||
# remove redundant args that are easily identified
|
||||
args = cls._collapse_arguments(args, **assumptions)
|
||||
# find local zeros
|
||||
args = cls._find_localzeros(args, **assumptions)
|
||||
args = frozenset(args)
|
||||
|
||||
if not args:
|
||||
return cls.identity
|
||||
|
||||
if len(args) == 1:
|
||||
return list(args).pop()
|
||||
|
||||
# base creation
|
||||
obj = Expr.__new__(cls, *ordered(args), **assumptions)
|
||||
obj._argset = args
|
||||
return obj
|
||||
|
||||
@classmethod
|
||||
def _collapse_arguments(cls, args, **assumptions):
|
||||
"""Remove redundant args.
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
>>> from sympy import Min, Max
|
||||
>>> from sympy.abc import a, b, c, d, e
|
||||
|
||||
Any arg in parent that appears in any
|
||||
parent-like function in any of the flat args
|
||||
of parent can be removed from that sub-arg:
|
||||
|
||||
>>> Min(a, Max(b, Min(a, c, d)))
|
||||
Min(a, Max(b, Min(c, d)))
|
||||
|
||||
If the arg of parent appears in an opposite-than parent
|
||||
function in any of the flat args of parent that function
|
||||
can be replaced with the arg:
|
||||
|
||||
>>> Min(a, Max(b, Min(c, d, Max(a, e))))
|
||||
Min(a, Max(b, Min(a, c, d)))
|
||||
"""
|
||||
if not args:
|
||||
return args
|
||||
args = list(ordered(args))
|
||||
if cls == Min:
|
||||
other = Max
|
||||
else:
|
||||
other = Min
|
||||
|
||||
# find global comparable max of Max and min of Min if a new
|
||||
# value is being introduced in these args at position 0 of
|
||||
# the ordered args
|
||||
if args[0].is_number:
|
||||
sifted = mins, maxs = [], []
|
||||
for i in args:
|
||||
for v in walk(i, Min, Max):
|
||||
if v.args[0].is_comparable:
|
||||
sifted[isinstance(v, Max)].append(v)
|
||||
small = Min.identity
|
||||
for i in mins:
|
||||
v = i.args[0]
|
||||
if v.is_number and (v < small) == True:
|
||||
small = v
|
||||
big = Max.identity
|
||||
for i in maxs:
|
||||
v = i.args[0]
|
||||
if v.is_number and (v > big) == True:
|
||||
big = v
|
||||
# at the point when this function is called from __new__,
|
||||
# there may be more than one numeric arg present since
|
||||
# local zeros have not been handled yet, so look through
|
||||
# more than the first arg
|
||||
if cls == Min:
|
||||
for arg in args:
|
||||
if not arg.is_number:
|
||||
break
|
||||
if (arg < small) == True:
|
||||
small = arg
|
||||
elif cls == Max:
|
||||
for arg in args:
|
||||
if not arg.is_number:
|
||||
break
|
||||
if (arg > big) == True:
|
||||
big = arg
|
||||
T = None
|
||||
if cls == Min:
|
||||
if small != Min.identity:
|
||||
other = Max
|
||||
T = small
|
||||
elif big != Max.identity:
|
||||
other = Min
|
||||
T = big
|
||||
if T is not None:
|
||||
# remove numerical redundancy
|
||||
for i in range(len(args)):
|
||||
a = args[i]
|
||||
if isinstance(a, other):
|
||||
a0 = a.args[0]
|
||||
if ((a0 > T) if other == Max else (a0 < T)) == True:
|
||||
args[i] = cls.identity
|
||||
|
||||
# remove redundant symbolic args
|
||||
def do(ai, a):
|
||||
if not isinstance(ai, (Min, Max)):
|
||||
return ai
|
||||
cond = a in ai.args
|
||||
if not cond:
|
||||
return ai.func(*[do(i, a) for i in ai.args],
|
||||
evaluate=False)
|
||||
if isinstance(ai, cls):
|
||||
return ai.func(*[do(i, a) for i in ai.args if i != a],
|
||||
evaluate=False)
|
||||
return a
|
||||
for i, a in enumerate(args):
|
||||
args[i + 1:] = [do(ai, a) for ai in args[i + 1:]]
|
||||
|
||||
# factor out common elements as for
|
||||
# Min(Max(x, y), Max(x, z)) -> Max(x, Min(y, z))
|
||||
# and vice versa when swapping Min/Max -- do this only for the
|
||||
# easy case where all functions contain something in common;
|
||||
# trying to find some optimal subset of args to modify takes
|
||||
# too long
|
||||
|
||||
def factor_minmax(args):
|
||||
is_other = lambda arg: isinstance(arg, other)
|
||||
other_args, remaining_args = sift(args, is_other, binary=True)
|
||||
if not other_args:
|
||||
return args
|
||||
|
||||
# Min(Max(x, y, z), Max(x, y, u, v)) -> {x,y}, ({z}, {u,v})
|
||||
arg_sets = [set(arg.args) for arg in other_args]
|
||||
common = set.intersection(*arg_sets)
|
||||
if not common:
|
||||
return args
|
||||
|
||||
new_other_args = list(common)
|
||||
arg_sets_diff = [arg_set - common for arg_set in arg_sets]
|
||||
|
||||
# If any set is empty after removing common then all can be
|
||||
# discarded e.g. Min(Max(a, b, c), Max(a, b)) -> Max(a, b)
|
||||
if all(arg_sets_diff):
|
||||
other_args_diff = [other(*s, evaluate=False) for s in arg_sets_diff]
|
||||
new_other_args.append(cls(*other_args_diff, evaluate=False))
|
||||
|
||||
other_args_factored = other(*new_other_args, evaluate=False)
|
||||
return remaining_args + [other_args_factored]
|
||||
|
||||
if len(args) > 1:
|
||||
args = factor_minmax(args)
|
||||
|
||||
return args
|
||||
|
||||
@classmethod
|
||||
def _new_args_filter(cls, arg_sequence):
|
||||
"""
|
||||
Generator filtering args.
|
||||
|
||||
first standard filter, for cls.zero and cls.identity.
|
||||
Also reshape ``Max(a, Max(b, c))`` to ``Max(a, b, c)``,
|
||||
and check arguments for comparability
|
||||
"""
|
||||
for arg in arg_sequence:
|
||||
# pre-filter, checking comparability of arguments
|
||||
if not isinstance(arg, Expr) or arg.is_extended_real is False or (
|
||||
arg.is_number and
|
||||
not arg.is_comparable):
|
||||
raise ValueError("The argument '%s' is not comparable." % arg)
|
||||
|
||||
if arg == cls.zero:
|
||||
raise ShortCircuit(arg)
|
||||
elif arg == cls.identity:
|
||||
continue
|
||||
elif arg.func == cls:
|
||||
yield from arg.args
|
||||
else:
|
||||
yield arg
|
||||
|
||||
@classmethod
|
||||
def _find_localzeros(cls, values, **options):
|
||||
"""
|
||||
Sequentially allocate values to localzeros.
|
||||
|
||||
When a value is identified as being more extreme than another member it
|
||||
replaces that member; if this is never true, then the value is simply
|
||||
appended to the localzeros.
|
||||
"""
|
||||
localzeros = set()
|
||||
for v in values:
|
||||
is_newzero = True
|
||||
localzeros_ = list(localzeros)
|
||||
for z in localzeros_:
|
||||
if id(v) == id(z):
|
||||
is_newzero = False
|
||||
else:
|
||||
con = cls._is_connected(v, z)
|
||||
if con:
|
||||
is_newzero = False
|
||||
if con is True or con == cls:
|
||||
localzeros.remove(z)
|
||||
localzeros.update([v])
|
||||
if is_newzero:
|
||||
localzeros.update([v])
|
||||
return localzeros
|
||||
|
||||
@classmethod
|
||||
def _is_connected(cls, x, y):
|
||||
"""
|
||||
Check if x and y are connected somehow.
|
||||
"""
|
||||
for i in range(2):
|
||||
if x == y:
|
||||
return True
|
||||
t, f = Max, Min
|
||||
for op in "><":
|
||||
for j in range(2):
|
||||
try:
|
||||
if op == ">":
|
||||
v = x >= y
|
||||
else:
|
||||
v = x <= y
|
||||
except TypeError:
|
||||
return False # non-real arg
|
||||
if not v.is_Relational:
|
||||
return t if v else f
|
||||
t, f = f, t
|
||||
x, y = y, x
|
||||
x, y = y, x # run next pass with reversed order relative to start
|
||||
# simplification can be expensive, so be conservative
|
||||
# in what is attempted
|
||||
x = factor_terms(x - y)
|
||||
y = S.Zero
|
||||
|
||||
return False
|
||||
|
||||
def _eval_derivative(self, s):
|
||||
# f(x).diff(s) -> x.diff(s) * f.fdiff(1)(s)
|
||||
i = 0
|
||||
l = []
|
||||
for a in self.args:
|
||||
i += 1
|
||||
da = a.diff(s)
|
||||
if da.is_zero:
|
||||
continue
|
||||
try:
|
||||
df = self.fdiff(i)
|
||||
except ArgumentIndexError:
|
||||
df = super().fdiff(i)
|
||||
l.append(df * da)
|
||||
return Add(*l)
|
||||
|
||||
def _eval_rewrite_as_Abs(self, *args, **kwargs):
|
||||
from sympy.functions.elementary.complexes import Abs
|
||||
s = (args[0] + self.func(*args[1:]))/2
|
||||
d = abs(args[0] - self.func(*args[1:]))/2
|
||||
return (s + d if isinstance(self, Max) else s - d).rewrite(Abs)
|
||||
|
||||
def evalf(self, n=15, **options):
|
||||
return self.func(*[a.evalf(n, **options) for a in self.args])
|
||||
|
||||
def n(self, *args, **kwargs):
|
||||
return self.evalf(*args, **kwargs)
|
||||
|
||||
_eval_is_algebraic = lambda s: _torf(i.is_algebraic for i in s.args)
|
||||
_eval_is_antihermitian = lambda s: _torf(i.is_antihermitian for i in s.args)
|
||||
_eval_is_commutative = lambda s: _torf(i.is_commutative for i in s.args)
|
||||
_eval_is_complex = lambda s: _torf(i.is_complex for i in s.args)
|
||||
_eval_is_composite = lambda s: _torf(i.is_composite for i in s.args)
|
||||
_eval_is_even = lambda s: _torf(i.is_even for i in s.args)
|
||||
_eval_is_finite = lambda s: _torf(i.is_finite for i in s.args)
|
||||
_eval_is_hermitian = lambda s: _torf(i.is_hermitian for i in s.args)
|
||||
_eval_is_imaginary = lambda s: _torf(i.is_imaginary for i in s.args)
|
||||
_eval_is_infinite = lambda s: _torf(i.is_infinite for i in s.args)
|
||||
_eval_is_integer = lambda s: _torf(i.is_integer for i in s.args)
|
||||
_eval_is_irrational = lambda s: _torf(i.is_irrational for i in s.args)
|
||||
_eval_is_negative = lambda s: _torf(i.is_negative for i in s.args)
|
||||
_eval_is_noninteger = lambda s: _torf(i.is_noninteger for i in s.args)
|
||||
_eval_is_nonnegative = lambda s: _torf(i.is_nonnegative for i in s.args)
|
||||
_eval_is_nonpositive = lambda s: _torf(i.is_nonpositive for i in s.args)
|
||||
_eval_is_nonzero = lambda s: _torf(i.is_nonzero for i in s.args)
|
||||
_eval_is_odd = lambda s: _torf(i.is_odd for i in s.args)
|
||||
_eval_is_polar = lambda s: _torf(i.is_polar for i in s.args)
|
||||
_eval_is_positive = lambda s: _torf(i.is_positive for i in s.args)
|
||||
_eval_is_prime = lambda s: _torf(i.is_prime for i in s.args)
|
||||
_eval_is_rational = lambda s: _torf(i.is_rational for i in s.args)
|
||||
_eval_is_real = lambda s: _torf(i.is_real for i in s.args)
|
||||
_eval_is_extended_real = lambda s: _torf(i.is_extended_real for i in s.args)
|
||||
_eval_is_transcendental = lambda s: _torf(i.is_transcendental for i in s.args)
|
||||
_eval_is_zero = lambda s: _torf(i.is_zero for i in s.args)
|
||||
|
||||
|
||||
class Max(MinMaxBase, Application):
|
||||
r"""
|
||||
Return, if possible, the maximum value of the list.
|
||||
|
||||
When number of arguments is equal one, then
|
||||
return this argument.
|
||||
|
||||
When number of arguments is equal two, then
|
||||
return, if possible, the value from (a, b) that is $\ge$ the other.
|
||||
|
||||
In common case, when the length of list greater than 2, the task
|
||||
is more complicated. Return only the arguments, which are greater
|
||||
than others, if it is possible to determine directional relation.
|
||||
|
||||
If is not possible to determine such a relation, return a partially
|
||||
evaluated result.
|
||||
|
||||
Assumptions are used to make the decision too.
|
||||
|
||||
Also, only comparable arguments are permitted.
|
||||
|
||||
It is named ``Max`` and not ``max`` to avoid conflicts
|
||||
with the built-in function ``max``.
|
||||
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
>>> from sympy import Max, Symbol, oo
|
||||
>>> from sympy.abc import x, y, z
|
||||
>>> p = Symbol('p', positive=True)
|
||||
>>> n = Symbol('n', negative=True)
|
||||
|
||||
>>> Max(x, -2)
|
||||
Max(-2, x)
|
||||
>>> Max(x, -2).subs(x, 3)
|
||||
3
|
||||
>>> Max(p, -2)
|
||||
p
|
||||
>>> Max(x, y)
|
||||
Max(x, y)
|
||||
>>> Max(x, y) == Max(y, x)
|
||||
True
|
||||
>>> Max(x, Max(y, z))
|
||||
Max(x, y, z)
|
||||
>>> Max(n, 8, p, 7, -oo)
|
||||
Max(8, p)
|
||||
>>> Max (1, x, oo)
|
||||
oo
|
||||
|
||||
* Algorithm
|
||||
|
||||
The task can be considered as searching of supremums in the
|
||||
directed complete partial orders [1]_.
|
||||
|
||||
The source values are sequentially allocated by the isolated subsets
|
||||
in which supremums are searched and result as Max arguments.
|
||||
|
||||
If the resulted supremum is single, then it is returned.
|
||||
|
||||
The isolated subsets are the sets of values which are only the comparable
|
||||
with each other in the current set. E.g. natural numbers are comparable with
|
||||
each other, but not comparable with the `x` symbol. Another example: the
|
||||
symbol `x` with negative assumption is comparable with a natural number.
|
||||
|
||||
Also there are "least" elements, which are comparable with all others,
|
||||
and have a zero property (maximum or minimum for all elements).
|
||||
For example, in case of $\infty$, the allocation operation is terminated
|
||||
and only this value is returned.
|
||||
|
||||
Assumption:
|
||||
- if $A > B > C$ then $A > C$
|
||||
- if $A = B$ then $B$ can be removed
|
||||
|
||||
References
|
||||
==========
|
||||
|
||||
.. [1] https://en.wikipedia.org/wiki/Directed_complete_partial_order
|
||||
.. [2] https://en.wikipedia.org/wiki/Lattice_%28order%29
|
||||
|
||||
See Also
|
||||
========
|
||||
|
||||
Min : find minimum values
|
||||
"""
|
||||
zero = S.Infinity
|
||||
identity = S.NegativeInfinity
|
||||
|
||||
def fdiff( self, argindex ):
|
||||
from sympy.functions.special.delta_functions import Heaviside
|
||||
n = len(self.args)
|
||||
if 0 < argindex and argindex <= n:
|
||||
argindex -= 1
|
||||
if n == 2:
|
||||
return Heaviside(self.args[argindex] - self.args[1 - argindex])
|
||||
newargs = tuple([self.args[i] for i in range(n) if i != argindex])
|
||||
return Heaviside(self.args[argindex] - Max(*newargs))
|
||||
else:
|
||||
raise ArgumentIndexError(self, argindex)
|
||||
|
||||
def _eval_rewrite_as_Heaviside(self, *args, **kwargs):
|
||||
from sympy.functions.special.delta_functions import Heaviside
|
||||
return Add(*[j*Mul(*[Heaviside(j - i) for i in args if i!=j]) \
|
||||
for j in args])
|
||||
|
||||
def _eval_rewrite_as_Piecewise(self, *args, **kwargs):
|
||||
return _minmax_as_Piecewise('>=', *args)
|
||||
|
||||
def _eval_is_positive(self):
|
||||
return fuzzy_or(a.is_positive for a in self.args)
|
||||
|
||||
def _eval_is_nonnegative(self):
|
||||
return fuzzy_or(a.is_nonnegative for a in self.args)
|
||||
|
||||
def _eval_is_negative(self):
|
||||
return fuzzy_and(a.is_negative for a in self.args)
|
||||
|
||||
|
||||
class Min(MinMaxBase, Application):
|
||||
"""
|
||||
Return, if possible, the minimum value of the list.
|
||||
It is named ``Min`` and not ``min`` to avoid conflicts
|
||||
with the built-in function ``min``.
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
>>> from sympy import Min, Symbol, oo
|
||||
>>> from sympy.abc import x, y
|
||||
>>> p = Symbol('p', positive=True)
|
||||
>>> n = Symbol('n', negative=True)
|
||||
|
||||
>>> Min(x, -2)
|
||||
Min(-2, x)
|
||||
>>> Min(x, -2).subs(x, 3)
|
||||
-2
|
||||
>>> Min(p, -3)
|
||||
-3
|
||||
>>> Min(x, y)
|
||||
Min(x, y)
|
||||
>>> Min(n, 8, p, -7, p, oo)
|
||||
Min(-7, n)
|
||||
|
||||
See Also
|
||||
========
|
||||
|
||||
Max : find maximum values
|
||||
"""
|
||||
zero = S.NegativeInfinity
|
||||
identity = S.Infinity
|
||||
|
||||
def fdiff( self, argindex ):
|
||||
from sympy.functions.special.delta_functions import Heaviside
|
||||
n = len(self.args)
|
||||
if 0 < argindex and argindex <= n:
|
||||
argindex -= 1
|
||||
if n == 2:
|
||||
return Heaviside( self.args[1-argindex] - self.args[argindex] )
|
||||
newargs = tuple([ self.args[i] for i in range(n) if i != argindex])
|
||||
return Heaviside( Min(*newargs) - self.args[argindex] )
|
||||
else:
|
||||
raise ArgumentIndexError(self, argindex)
|
||||
|
||||
def _eval_rewrite_as_Heaviside(self, *args, **kwargs):
|
||||
from sympy.functions.special.delta_functions import Heaviside
|
||||
return Add(*[j*Mul(*[Heaviside(i-j) for i in args if i!=j]) \
|
||||
for j in args])
|
||||
|
||||
def _eval_rewrite_as_Piecewise(self, *args, **kwargs):
|
||||
return _minmax_as_Piecewise('<=', *args)
|
||||
|
||||
def _eval_is_positive(self):
|
||||
return fuzzy_and(a.is_positive for a in self.args)
|
||||
|
||||
def _eval_is_nonnegative(self):
|
||||
return fuzzy_and(a.is_nonnegative for a in self.args)
|
||||
|
||||
def _eval_is_negative(self):
|
||||
return fuzzy_or(a.is_negative for a in self.args)
|
||||
|
||||
|
||||
class Rem(DefinedFunction):
|
||||
"""Returns the remainder when ``p`` is divided by ``q`` where ``p`` is finite
|
||||
and ``q`` is not equal to zero. The result, ``p - int(p/q)*q``, has the same sign
|
||||
as the divisor.
|
||||
|
||||
Parameters
|
||||
==========
|
||||
|
||||
p : Expr
|
||||
Dividend.
|
||||
|
||||
q : Expr
|
||||
Divisor.
|
||||
|
||||
Notes
|
||||
=====
|
||||
|
||||
``Rem`` corresponds to the ``%`` operator in C.
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
>>> from sympy.abc import x, y
|
||||
>>> from sympy import Rem
|
||||
>>> Rem(x**3, y)
|
||||
Rem(x**3, y)
|
||||
>>> Rem(x**3, y).subs({x: -5, y: 3})
|
||||
-2
|
||||
|
||||
See Also
|
||||
========
|
||||
|
||||
Mod
|
||||
"""
|
||||
kind = NumberKind
|
||||
|
||||
@classmethod
|
||||
def eval(cls, p, q):
|
||||
"""Return the function remainder if both p, q are numbers and q is not
|
||||
zero.
|
||||
"""
|
||||
|
||||
if q.is_zero:
|
||||
raise ZeroDivisionError("Division by zero")
|
||||
if p is S.NaN or q is S.NaN or p.is_finite is False or q.is_finite is False:
|
||||
return S.NaN
|
||||
if p is S.Zero or p in (q, -q) or (p.is_integer and q == 1):
|
||||
return S.Zero
|
||||
|
||||
if q.is_Number:
|
||||
if p.is_Number:
|
||||
return p - Integer(p/q)*q
|
||||
Reference in New Issue
Block a user