ZhengyangZhang commited on
Commit
0e9de3d
·
verified ·
1 Parent(s): a0fa767

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. lib/python3.12/site-packages/sympy/core/__init__.py +103 -0
  2. lib/python3.12/site-packages/sympy/core/__pycache__/__init__.cpython-312.pyc +0 -0
  3. lib/python3.12/site-packages/sympy/core/__pycache__/_print_helpers.cpython-312.pyc +0 -0
  4. lib/python3.12/site-packages/sympy/core/__pycache__/add.cpython-312.pyc +0 -0
  5. lib/python3.12/site-packages/sympy/core/__pycache__/alphabets.cpython-312.pyc +0 -0
  6. lib/python3.12/site-packages/sympy/core/__pycache__/assumptions.cpython-312.pyc +0 -0
  7. lib/python3.12/site-packages/sympy/core/__pycache__/assumptions_generated.cpython-312.pyc +0 -0
  8. lib/python3.12/site-packages/sympy/core/__pycache__/backend.cpython-312.pyc +0 -0
  9. lib/python3.12/site-packages/sympy/core/__pycache__/basic.cpython-312.pyc +0 -0
  10. lib/python3.12/site-packages/sympy/core/__pycache__/cache.cpython-312.pyc +0 -0
  11. lib/python3.12/site-packages/sympy/core/__pycache__/compatibility.cpython-312.pyc +0 -0
  12. lib/python3.12/site-packages/sympy/core/__pycache__/containers.cpython-312.pyc +0 -0
  13. lib/python3.12/site-packages/sympy/core/__pycache__/core.cpython-312.pyc +0 -0
  14. lib/python3.12/site-packages/sympy/core/__pycache__/coreerrors.cpython-312.pyc +0 -0
  15. lib/python3.12/site-packages/sympy/core/__pycache__/decorators.cpython-312.pyc +0 -0
  16. lib/python3.12/site-packages/sympy/core/__pycache__/evalf.cpython-312.pyc +0 -0
  17. lib/python3.12/site-packages/sympy/core/__pycache__/exprtools.cpython-312.pyc +0 -0
  18. lib/python3.12/site-packages/sympy/core/__pycache__/facts.cpython-312.pyc +0 -0
  19. lib/python3.12/site-packages/sympy/core/__pycache__/intfunc.cpython-312.pyc +0 -0
  20. lib/python3.12/site-packages/sympy/core/__pycache__/kind.cpython-312.pyc +0 -0
  21. lib/python3.12/site-packages/sympy/core/__pycache__/logic.cpython-312.pyc +0 -0
  22. lib/python3.12/site-packages/sympy/core/__pycache__/mod.cpython-312.pyc +0 -0
  23. lib/python3.12/site-packages/sympy/core/__pycache__/mul.cpython-312.pyc +0 -0
  24. lib/python3.12/site-packages/sympy/core/__pycache__/multidimensional.cpython-312.pyc +0 -0
  25. lib/python3.12/site-packages/sympy/core/__pycache__/operations.cpython-312.pyc +0 -0
  26. lib/python3.12/site-packages/sympy/core/__pycache__/parameters.cpython-312.pyc +0 -0
  27. lib/python3.12/site-packages/sympy/core/__pycache__/power.cpython-312.pyc +0 -0
  28. lib/python3.12/site-packages/sympy/core/__pycache__/random.cpython-312.pyc +0 -0
  29. lib/python3.12/site-packages/sympy/core/__pycache__/relational.cpython-312.pyc +0 -0
  30. lib/python3.12/site-packages/sympy/core/__pycache__/rules.cpython-312.pyc +0 -0
  31. lib/python3.12/site-packages/sympy/core/__pycache__/singleton.cpython-312.pyc +0 -0
  32. lib/python3.12/site-packages/sympy/core/__pycache__/sorting.cpython-312.pyc +0 -0
  33. lib/python3.12/site-packages/sympy/core/__pycache__/symbol.cpython-312.pyc +0 -0
  34. lib/python3.12/site-packages/sympy/core/__pycache__/sympify.cpython-312.pyc +0 -0
  35. lib/python3.12/site-packages/sympy/core/__pycache__/trace.cpython-312.pyc +0 -0
  36. lib/python3.12/site-packages/sympy/core/__pycache__/traversal.cpython-312.pyc +0 -0
  37. lib/python3.12/site-packages/sympy/core/_print_helpers.py +65 -0
  38. lib/python3.12/site-packages/sympy/core/add.py +1284 -0
  39. lib/python3.12/site-packages/sympy/core/alphabets.py +4 -0
  40. lib/python3.12/site-packages/sympy/core/assumptions.py +692 -0
  41. lib/python3.12/site-packages/sympy/core/assumptions_generated.py +1615 -0
  42. lib/python3.12/site-packages/sympy/core/backend.py +120 -0
  43. lib/python3.12/site-packages/sympy/core/basic.py +2339 -0
  44. lib/python3.12/site-packages/sympy/core/cache.py +210 -0
  45. lib/python3.12/site-packages/sympy/core/compatibility.py +35 -0
  46. lib/python3.12/site-packages/sympy/core/containers.py +410 -0
  47. lib/python3.12/site-packages/sympy/core/core.py +21 -0
  48. lib/python3.12/site-packages/sympy/core/coreerrors.py +9 -0
  49. lib/python3.12/site-packages/sympy/core/decorators.py +238 -0
  50. lib/python3.12/site-packages/sympy/core/evalf.py +1802 -0
lib/python3.12/site-packages/sympy/core/__init__.py ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Core module. Provides the basic operations needed in sympy.
2
+ """
3
+
4
+ from .sympify import sympify, SympifyError
5
+ from .cache import cacheit
6
+ from .assumptions import assumptions, check_assumptions, failing_assumptions, common_assumptions
7
+ from .basic import Basic, Atom
8
+ from .singleton import S
9
+ from .expr import Expr, AtomicExpr, UnevaluatedExpr
10
+ from .symbol import Symbol, Wild, Dummy, symbols, var
11
+ from .numbers import Number, Float, Rational, Integer, NumberSymbol, \
12
+ RealNumber, igcd, ilcm, seterr, E, I, nan, oo, pi, zoo, \
13
+ AlgebraicNumber, comp, mod_inverse
14
+ from .power import Pow
15
+ from .intfunc import integer_nthroot, integer_log, num_digits, trailing
16
+ from .mul import Mul, prod
17
+ from .add import Add
18
+ from .mod import Mod
19
+ from .relational import ( Rel, Eq, Ne, Lt, Le, Gt, Ge,
20
+ Equality, GreaterThan, LessThan, Unequality, StrictGreaterThan,
21
+ StrictLessThan )
22
+ from .multidimensional import vectorize
23
+ from .function import Lambda, WildFunction, Derivative, diff, FunctionClass, \
24
+ Function, Subs, expand, PoleError, count_ops, \
25
+ expand_mul, expand_log, expand_func, \
26
+ expand_trig, expand_complex, expand_multinomial, nfloat, \
27
+ expand_power_base, expand_power_exp, arity
28
+ from .evalf import PrecisionExhausted, N
29
+ from .containers import Tuple, Dict
30
+ from .exprtools import gcd_terms, factor_terms, factor_nc
31
+ from .parameters import evaluate
32
+ from .kind import UndefinedKind, NumberKind, BooleanKind
33
+ from .traversal import preorder_traversal, bottom_up, use, postorder_traversal
34
+ from .sorting import default_sort_key, ordered
35
+
36
+ # expose singletons
37
+ Catalan = S.Catalan
38
+ EulerGamma = S.EulerGamma
39
+ GoldenRatio = S.GoldenRatio
40
+ TribonacciConstant = S.TribonacciConstant
41
+
42
+ __all__ = [
43
+ 'sympify', 'SympifyError',
44
+
45
+ 'cacheit',
46
+
47
+ 'assumptions', 'check_assumptions', 'failing_assumptions',
48
+ 'common_assumptions',
49
+
50
+ 'Basic', 'Atom',
51
+
52
+ 'S',
53
+
54
+ 'Expr', 'AtomicExpr', 'UnevaluatedExpr',
55
+
56
+ 'Symbol', 'Wild', 'Dummy', 'symbols', 'var',
57
+
58
+ 'Number', 'Float', 'Rational', 'Integer', 'NumberSymbol', 'RealNumber',
59
+ 'igcd', 'ilcm', 'seterr', 'E', 'I', 'nan', 'oo', 'pi', 'zoo',
60
+ 'AlgebraicNumber', 'comp', 'mod_inverse',
61
+
62
+ 'Pow',
63
+
64
+ 'integer_nthroot', 'integer_log', 'num_digits', 'trailing',
65
+
66
+ 'Mul', 'prod',
67
+
68
+ 'Add',
69
+
70
+ 'Mod',
71
+
72
+ 'Rel', 'Eq', 'Ne', 'Lt', 'Le', 'Gt', 'Ge', 'Equality', 'GreaterThan',
73
+ 'LessThan', 'Unequality', 'StrictGreaterThan', 'StrictLessThan',
74
+
75
+ 'vectorize',
76
+
77
+ 'Lambda', 'WildFunction', 'Derivative', 'diff', 'FunctionClass',
78
+ 'Function', 'Subs', 'expand', 'PoleError', 'count_ops', 'expand_mul',
79
+ 'expand_log', 'expand_func', 'expand_trig', 'expand_complex',
80
+ 'expand_multinomial', 'nfloat', 'expand_power_base', 'expand_power_exp',
81
+ 'arity',
82
+
83
+ 'PrecisionExhausted', 'N',
84
+
85
+ 'evalf', # The module?
86
+
87
+ 'Tuple', 'Dict',
88
+
89
+ 'gcd_terms', 'factor_terms', 'factor_nc',
90
+
91
+ 'evaluate',
92
+
93
+ 'Catalan',
94
+ 'EulerGamma',
95
+ 'GoldenRatio',
96
+ 'TribonacciConstant',
97
+
98
+ 'UndefinedKind', 'NumberKind', 'BooleanKind',
99
+
100
+ 'preorder_traversal', 'bottom_up', 'use', 'postorder_traversal',
101
+
102
+ 'default_sort_key', 'ordered',
103
+ ]
lib/python3.12/site-packages/sympy/core/__pycache__/__init__.cpython-312.pyc ADDED
Binary file (3.41 kB). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/_print_helpers.cpython-312.pyc ADDED
Binary file (2.45 kB). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/add.cpython-312.pyc ADDED
Binary file (54.6 kB). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/alphabets.cpython-312.pyc ADDED
Binary file (356 Bytes). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/assumptions.cpython-312.pyc ADDED
Binary file (21.8 kB). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/assumptions_generated.cpython-312.pyc ADDED
Binary file (15.5 kB). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/backend.cpython-312.pyc ADDED
Binary file (4.58 kB). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/basic.cpython-312.pyc ADDED
Binary file (84.2 kB). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/cache.cpython-312.pyc ADDED
Binary file (8.46 kB). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/compatibility.cpython-312.pyc ADDED
Binary file (1.35 kB). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/containers.cpython-312.pyc ADDED
Binary file (19 kB). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/core.cpython-312.pyc ADDED
Binary file (1.19 kB). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/coreerrors.cpython-312.pyc ADDED
Binary file (738 Bytes). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/decorators.cpython-312.pyc ADDED
Binary file (9.41 kB). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/evalf.cpython-312.pyc ADDED
Binary file (65 kB). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/exprtools.cpython-312.pyc ADDED
Binary file (62.3 kB). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/facts.cpython-312.pyc ADDED
Binary file (23.6 kB). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/intfunc.cpython-312.pyc ADDED
Binary file (14.4 kB). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/kind.cpython-312.pyc ADDED
Binary file (14.7 kB). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/logic.cpython-312.pyc ADDED
Binary file (14 kB). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/mod.cpython-312.pyc ADDED
Binary file (11.2 kB). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/mul.cpython-312.pyc ADDED
Binary file (86.6 kB). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/multidimensional.cpython-312.pyc ADDED
Binary file (4.92 kB). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/operations.cpython-312.pyc ADDED
Binary file (28.3 kB). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/parameters.cpython-312.pyc ADDED
Binary file (5.48 kB). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/power.cpython-312.pyc ADDED
Binary file (88.1 kB). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/random.cpython-312.pyc ADDED
Binary file (8.85 kB). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/relational.cpython-312.pyc ADDED
Binary file (59.9 kB). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/rules.cpython-312.pyc ADDED
Binary file (2.32 kB). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/singleton.cpython-312.pyc ADDED
Binary file (7.48 kB). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/sorting.cpython-312.pyc ADDED
Binary file (12.3 kB). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/symbol.cpython-312.pyc ADDED
Binary file (35.8 kB). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/sympify.cpython-312.pyc ADDED
Binary file (20 kB). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/trace.cpython-312.pyc ADDED
Binary file (544 Bytes). View file
 
lib/python3.12/site-packages/sympy/core/__pycache__/traversal.cpython-312.pyc ADDED
Binary file (10.8 kB). View file
 
lib/python3.12/site-packages/sympy/core/_print_helpers.py ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Base class to provide str and repr hooks that `init_printing` can overwrite.
3
+
4
+ This is exposed publicly in the `printing.defaults` module,
5
+ but cannot be defined there without causing circular imports.
6
+ """
7
+
8
+ class Printable:
9
+ """
10
+ The default implementation of printing for SymPy classes.
11
+
12
+ This implements a hack that allows us to print elements of built-in
13
+ Python containers in a readable way. Natively Python uses ``repr()``
14
+ even if ``str()`` was explicitly requested. Mix in this trait into
15
+ a class to get proper default printing.
16
+
17
+ This also adds support for LaTeX printing in jupyter notebooks.
18
+ """
19
+
20
+ # Since this class is used as a mixin we set empty slots. That means that
21
+ # instances of any subclasses that use slots will not need to have a
22
+ # __dict__.
23
+ __slots__ = ()
24
+
25
+ # Note, we always use the default ordering (lex) in __str__ and __repr__,
26
+ # regardless of the global setting. See issue 5487.
27
+ def __str__(self):
28
+ from sympy.printing.str import sstr
29
+ return sstr(self, order=None)
30
+
31
+ __repr__ = __str__
32
+
33
+ def _repr_disabled(self):
34
+ """
35
+ No-op repr function used to disable jupyter display hooks.
36
+
37
+ When :func:`sympy.init_printing` is used to disable certain display
38
+ formats, this function is copied into the appropriate ``_repr_*_``
39
+ attributes.
40
+
41
+ While we could just set the attributes to `None``, doing it this way
42
+ allows derived classes to call `super()`.
43
+ """
44
+ return None
45
+
46
+ # We don't implement _repr_png_ here because it would add a large amount of
47
+ # data to any notebook containing SymPy expressions, without adding
48
+ # anything useful to the notebook. It can still enabled manually, e.g.,
49
+ # for the qtconsole, with init_printing().
50
+ _repr_png_ = _repr_disabled
51
+
52
+ _repr_svg_ = _repr_disabled
53
+
54
+ def _repr_latex_(self):
55
+ """
56
+ IPython/Jupyter LaTeX printing
57
+
58
+ To change the behavior of this (e.g., pass in some settings to LaTeX),
59
+ use init_printing(). init_printing() will also enable LaTeX printing
60
+ for built in numeric types like ints and container types that contain
61
+ SymPy objects, like lists and dictionaries of expressions.
62
+ """
63
+ from sympy.printing.latex import latex
64
+ s = latex(self, mode='plain')
65
+ return "$\\displaystyle %s$" % s
lib/python3.12/site-packages/sympy/core/add.py ADDED
@@ -0,0 +1,1284 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Tuple as tTuple
2
+ from collections import defaultdict
3
+ from functools import reduce
4
+ from operator import attrgetter
5
+ from .basic import _args_sortkey
6
+ from .parameters import global_parameters
7
+ from .logic import _fuzzy_group, fuzzy_or, fuzzy_not
8
+ from .singleton import S
9
+ from .operations import AssocOp, AssocOpDispatcher
10
+ from .cache import cacheit
11
+ from .numbers import equal_valued
12
+ from .intfunc import ilcm, igcd
13
+ from .expr import Expr
14
+ from .kind import UndefinedKind
15
+ from sympy.utilities.iterables import is_sequence, sift
16
+
17
+ def _could_extract_minus_sign(expr):
18
+ # assume expr is Add-like
19
+ # We choose the one with less arguments with minus signs
20
+ negative_args = sum(1 for i in expr.args
21
+ if i.could_extract_minus_sign())
22
+ positive_args = len(expr.args) - negative_args
23
+ if positive_args > negative_args:
24
+ return False
25
+ elif positive_args < negative_args:
26
+ return True
27
+ # choose based on .sort_key() to prefer
28
+ # x - 1 instead of 1 - x and
29
+ # 3 - sqrt(2) instead of -3 + sqrt(2)
30
+ return bool(expr.sort_key() < (-expr).sort_key())
31
+
32
+
33
+ def _addsort(args):
34
+ # in-place sorting of args
35
+ args.sort(key=_args_sortkey)
36
+
37
+
38
+ def _unevaluated_Add(*args):
39
+ """Return a well-formed unevaluated Add: Numbers are collected and
40
+ put in slot 0 and args are sorted. Use this when args have changed
41
+ but you still want to return an unevaluated Add.
42
+
43
+ Examples
44
+ ========
45
+
46
+ >>> from sympy.core.add import _unevaluated_Add as uAdd
47
+ >>> from sympy import S, Add
48
+ >>> from sympy.abc import x, y
49
+ >>> a = uAdd(*[S(1.0), x, S(2)])
50
+ >>> a.args[0]
51
+ 3.00000000000000
52
+ >>> a.args[1]
53
+ x
54
+
55
+ Beyond the Number being in slot 0, there is no other assurance of
56
+ order for the arguments since they are hash sorted. So, for testing
57
+ purposes, output produced by this in some other function can only
58
+ be tested against the output of this function or as one of several
59
+ options:
60
+
61
+ >>> opts = (Add(x, y, evaluate=False), Add(y, x, evaluate=False))
62
+ >>> a = uAdd(x, y)
63
+ >>> assert a in opts and a == uAdd(x, y)
64
+ >>> uAdd(x + 1, x + 2)
65
+ x + x + 3
66
+ """
67
+ args = list(args)
68
+ newargs = []
69
+ co = S.Zero
70
+ while args:
71
+ a = args.pop()
72
+ if a.is_Add:
73
+ # this will keep nesting from building up
74
+ # so that x + (x + 1) -> x + x + 1 (3 args)
75
+ args.extend(a.args)
76
+ elif a.is_Number:
77
+ co += a
78
+ else:
79
+ newargs.append(a)
80
+ _addsort(newargs)
81
+ if co:
82
+ newargs.insert(0, co)
83
+ return Add._from_args(newargs)
84
+
85
+
86
+ class Add(Expr, AssocOp):
87
+ """
88
+ Expression representing addition operation for algebraic group.
89
+
90
+ .. deprecated:: 1.7
91
+
92
+ Using arguments that aren't subclasses of :class:`~.Expr` in core
93
+ operators (:class:`~.Mul`, :class:`~.Add`, and :class:`~.Pow`) is
94
+ deprecated. See :ref:`non-expr-args-deprecated` for details.
95
+
96
+ Every argument of ``Add()`` must be ``Expr``. Infix operator ``+``
97
+ on most scalar objects in SymPy calls this class.
98
+
99
+ Another use of ``Add()`` is to represent the structure of abstract
100
+ addition so that its arguments can be substituted to return different
101
+ class. Refer to examples section for this.
102
+
103
+ ``Add()`` evaluates the argument unless ``evaluate=False`` is passed.
104
+ The evaluation logic includes:
105
+
106
+ 1. Flattening
107
+ ``Add(x, Add(y, z))`` -> ``Add(x, y, z)``
108
+
109
+ 2. Identity removing
110
+ ``Add(x, 0, y)`` -> ``Add(x, y)``
111
+
112
+ 3. Coefficient collecting by ``.as_coeff_Mul()``
113
+ ``Add(x, 2*x)`` -> ``Mul(3, x)``
114
+
115
+ 4. Term sorting
116
+ ``Add(y, x, 2)`` -> ``Add(2, x, y)``
117
+
118
+ If no argument is passed, identity element 0 is returned. If single
119
+ element is passed, that element is returned.
120
+
121
+ Note that ``Add(*args)`` is more efficient than ``sum(args)`` because
122
+ it flattens the arguments. ``sum(a, b, c, ...)`` recursively adds the
123
+ arguments as ``a + (b + (c + ...))``, which has quadratic complexity.
124
+ On the other hand, ``Add(a, b, c, d)`` does not assume nested
125
+ structure, making the complexity linear.
126
+
127
+ Since addition is group operation, every argument should have the
128
+ same :obj:`sympy.core.kind.Kind()`.
129
+
130
+ Examples
131
+ ========
132
+
133
+ >>> from sympy import Add, I
134
+ >>> from sympy.abc import x, y
135
+ >>> Add(x, 1)
136
+ x + 1
137
+ >>> Add(x, x)
138
+ 2*x
139
+ >>> 2*x**2 + 3*x + I*y + 2*y + 2*x/5 + 1.0*y + 1
140
+ 2*x**2 + 17*x/5 + 3.0*y + I*y + 1
141
+
142
+ If ``evaluate=False`` is passed, result is not evaluated.
143
+
144
+ >>> Add(1, 2, evaluate=False)
145
+ 1 + 2
146
+ >>> Add(x, x, evaluate=False)
147
+ x + x
148
+
149
+ ``Add()`` also represents the general structure of addition operation.
150
+
151
+ >>> from sympy import MatrixSymbol
152
+ >>> A,B = MatrixSymbol('A', 2,2), MatrixSymbol('B', 2,2)
153
+ >>> expr = Add(x,y).subs({x:A, y:B})
154
+ >>> expr
155
+ A + B
156
+ >>> type(expr)
157
+ <class 'sympy.matrices.expressions.matadd.MatAdd'>
158
+
159
+ Note that the printers do not display in args order.
160
+
161
+ >>> Add(x, 1)
162
+ x + 1
163
+ >>> Add(x, 1).args
164
+ (1, x)
165
+
166
+ See Also
167
+ ========
168
+
169
+ MatAdd
170
+
171
+ """
172
+
173
+ __slots__ = ()
174
+
175
+ args: tTuple[Expr, ...]
176
+
177
+ is_Add = True
178
+
179
+ _args_type = Expr
180
+
181
+ @classmethod
182
+ def flatten(cls, seq):
183
+ """
184
+ Takes the sequence "seq" of nested Adds and returns a flatten list.
185
+
186
+ Returns: (commutative_part, noncommutative_part, order_symbols)
187
+
188
+ Applies associativity, all terms are commutable with respect to
189
+ addition.
190
+
191
+ NB: the removal of 0 is already handled by AssocOp.__new__
192
+
193
+ See Also
194
+ ========
195
+
196
+ sympy.core.mul.Mul.flatten
197
+
198
+ """
199
+ from sympy.calculus.accumulationbounds import AccumBounds
200
+ from sympy.matrices.expressions import MatrixExpr
201
+ from sympy.tensor.tensor import TensExpr
202
+ rv = None
203
+ if len(seq) == 2:
204
+ a, b = seq
205
+ if b.is_Rational:
206
+ a, b = b, a
207
+ if a.is_Rational:
208
+ if b.is_Mul:
209
+ rv = [a, b], [], None
210
+ if rv:
211
+ if all(s.is_commutative for s in rv[0]):
212
+ return rv
213
+ return [], rv[0], None
214
+
215
+ terms = {} # term -> coeff
216
+ # e.g. x**2 -> 5 for ... + 5*x**2 + ...
217
+
218
+ coeff = S.Zero # coefficient (Number or zoo) to always be in slot 0
219
+ # e.g. 3 + ...
220
+ order_factors = []
221
+
222
+ extra = []
223
+
224
+ for o in seq:
225
+
226
+ # O(x)
227
+ if o.is_Order:
228
+ if o.expr.is_zero:
229
+ continue
230
+ for o1 in order_factors:
231
+ if o1.contains(o):
232
+ o = None
233
+ break
234
+ if o is None:
235
+ continue
236
+ order_factors = [o] + [
237
+ o1 for o1 in order_factors if not o.contains(o1)]
238
+ continue
239
+
240
+ # 3 or NaN
241
+ elif o.is_Number:
242
+ if (o is S.NaN or coeff is S.ComplexInfinity and
243
+ o.is_finite is False) and not extra:
244
+ # we know for sure the result will be nan
245
+ return [S.NaN], [], None
246
+ if coeff.is_Number or isinstance(coeff, AccumBounds):
247
+ coeff += o
248
+ if coeff is S.NaN and not extra:
249
+ # we know for sure the result will be nan
250
+ return [S.NaN], [], None
251
+ continue
252
+
253
+ elif isinstance(o, AccumBounds):
254
+ coeff = o.__add__(coeff)
255
+ continue
256
+
257
+ elif isinstance(o, MatrixExpr):
258
+ # can't add 0 to Matrix so make sure coeff is not 0
259
+ extra.append(o)
260
+ continue
261
+
262
+ elif isinstance(o, TensExpr):
263
+ coeff = o.__add__(coeff) if coeff else o
264
+ continue
265
+
266
+ elif o is S.ComplexInfinity:
267
+ if coeff.is_finite is False and not extra:
268
+ # we know for sure the result will be nan
269
+ return [S.NaN], [], None
270
+ coeff = S.ComplexInfinity
271
+ continue
272
+
273
+ # Add([...])
274
+ elif o.is_Add:
275
+ # NB: here we assume Add is always commutative
276
+ seq.extend(o.args) # TODO zerocopy?
277
+ continue
278
+
279
+ # Mul([...])
280
+ elif o.is_Mul:
281
+ c, s = o.as_coeff_Mul()
282
+
283
+ # check for unevaluated Pow, e.g. 2**3 or 2**(-1/2)
284
+ elif o.is_Pow:
285
+ b, e = o.as_base_exp()
286
+ if b.is_Number and (e.is_Integer or
287
+ (e.is_Rational and e.is_negative)):
288
+ seq.append(b**e)
289
+ continue
290
+ c, s = S.One, o
291
+
292
+ else:
293
+ # everything else
294
+ c = S.One
295
+ s = o
296
+
297
+ # now we have:
298
+ # o = c*s, where
299
+ #
300
+ # c is a Number
301
+ # s is an expression with number factor extracted
302
+ # let's collect terms with the same s, so e.g.
303
+ # 2*x**2 + 3*x**2 -> 5*x**2
304
+ if s in terms:
305
+ terms[s] += c
306
+ if terms[s] is S.NaN and not extra:
307
+ # we know for sure the result will be nan
308
+ return [S.NaN], [], None
309
+ else:
310
+ terms[s] = c
311
+
312
+ # now let's construct new args:
313
+ # [2*x**2, x**3, 7*x**4, pi, ...]
314
+ newseq = []
315
+ noncommutative = False
316
+ for s, c in terms.items():
317
+ # 0*s
318
+ if c.is_zero:
319
+ continue
320
+ # 1*s
321
+ elif c is S.One:
322
+ newseq.append(s)
323
+ # c*s
324
+ else:
325
+ if s.is_Mul:
326
+ # Mul, already keeps its arguments in perfect order.
327
+ # so we can simply put c in slot0 and go the fast way.
328
+ cs = s._new_rawargs(*((c,) + s.args))
329
+ newseq.append(cs)
330
+ elif s.is_Add:
331
+ # we just re-create the unevaluated Mul
332
+ newseq.append(Mul(c, s, evaluate=False))
333
+ else:
334
+ # alternatively we have to call all Mul's machinery (slow)
335
+ newseq.append(Mul(c, s))
336
+
337
+ noncommutative = noncommutative or not s.is_commutative
338
+
339
+ # oo, -oo
340
+ if coeff is S.Infinity:
341
+ newseq = [f for f in newseq if not (f.is_extended_nonnegative or f.is_real)]
342
+
343
+ elif coeff is S.NegativeInfinity:
344
+ newseq = [f for f in newseq if not (f.is_extended_nonpositive or f.is_real)]
345
+
346
+ if coeff is S.ComplexInfinity:
347
+ # zoo might be
348
+ # infinite_real + finite_im
349
+ # finite_real + infinite_im
350
+ # infinite_real + infinite_im
351
+ # addition of a finite real or imaginary number won't be able to
352
+ # change the zoo nature; adding an infinite qualtity would result
353
+ # in a NaN condition if it had sign opposite of the infinite
354
+ # portion of zoo, e.g., infinite_real - infinite_real.
355
+ newseq = [c for c in newseq if not (c.is_finite and
356
+ c.is_extended_real is not None)]
357
+
358
+ # process O(x)
359
+ if order_factors:
360
+ newseq2 = []
361
+ for t in newseq:
362
+ for o in order_factors:
363
+ # x + O(x) -> O(x)
364
+ if o.contains(t):
365
+ t = None
366
+ break
367
+ # x + O(x**2) -> x + O(x**2)
368
+ if t is not None:
369
+ newseq2.append(t)
370
+ newseq = newseq2 + order_factors
371
+ # 1 + O(1) -> O(1)
372
+ for o in order_factors:
373
+ if o.contains(coeff):
374
+ coeff = S.Zero
375
+ break
376
+
377
+ # order args canonically
378
+ _addsort(newseq)
379
+
380
+ # current code expects coeff to be first
381
+ if coeff is not S.Zero:
382
+ newseq.insert(0, coeff)
383
+
384
+ if extra:
385
+ newseq += extra
386
+ noncommutative = True
387
+
388
+ # we are done
389
+ if noncommutative:
390
+ return [], newseq, None
391
+ else:
392
+ return newseq, [], None
393
+
394
+ @classmethod
395
+ def class_key(cls):
396
+ return 3, 1, cls.__name__
397
+
398
+ @property
399
+ def kind(self):
400
+ k = attrgetter('kind')
401
+ kinds = map(k, self.args)
402
+ kinds = frozenset(kinds)
403
+ if len(kinds) != 1:
404
+ # Since addition is group operator, kind must be same.
405
+ # We know that this is unexpected signature, so return this.
406
+ result = UndefinedKind
407
+ else:
408
+ result, = kinds
409
+ return result
410
+
411
+ def could_extract_minus_sign(self):
412
+ return _could_extract_minus_sign(self)
413
+
414
+ @cacheit
415
+ def as_coeff_add(self, *deps):
416
+ """
417
+ Returns a tuple (coeff, args) where self is treated as an Add and coeff
418
+ is the Number term and args is a tuple of all other terms.
419
+
420
+ Examples
421
+ ========
422
+
423
+ >>> from sympy.abc import x
424
+ >>> (7 + 3*x).as_coeff_add()
425
+ (7, (3*x,))
426
+ >>> (7*x).as_coeff_add()
427
+ (0, (7*x,))
428
+ """
429
+ if deps:
430
+ l1, l2 = sift(self.args, lambda x: x.has_free(*deps), binary=True)
431
+ return self._new_rawargs(*l2), tuple(l1)
432
+ coeff, notrat = self.args[0].as_coeff_add()
433
+ if coeff is not S.Zero:
434
+ return coeff, notrat + self.args[1:]
435
+ return S.Zero, self.args
436
+
437
+ def as_coeff_Add(self, rational=False, deps=None):
438
+ """
439
+ Efficiently extract the coefficient of a summation.
440
+ """
441
+ coeff, args = self.args[0], self.args[1:]
442
+
443
+ if coeff.is_Number and not rational or coeff.is_Rational:
444
+ return coeff, self._new_rawargs(*args)
445
+ return S.Zero, self
446
+
447
+ # Note, we intentionally do not implement Add.as_coeff_mul(). Rather, we
448
+ # let Expr.as_coeff_mul() just always return (S.One, self) for an Add. See
449
+ # issue 5524.
450
+
451
+ def _eval_power(self, e):
452
+ from .evalf import pure_complex
453
+ from .relational import is_eq
454
+ if len(self.args) == 2 and any(_.is_infinite for _ in self.args):
455
+ if e.is_zero is False and is_eq(e, S.One) is False:
456
+ # looking for literal a + I*b
457
+ a, b = self.args
458
+ if a.coeff(S.ImaginaryUnit):
459
+ a, b = b, a
460
+ ico = b.coeff(S.ImaginaryUnit)
461
+ if ico and ico.is_extended_real and a.is_extended_real:
462
+ if e.is_extended_negative:
463
+ return S.Zero
464
+ if e.is_extended_positive:
465
+ return S.ComplexInfinity
466
+ return
467
+ if e.is_Rational and self.is_number:
468
+ ri = pure_complex(self)
469
+ if ri:
470
+ r, i = ri
471
+ if e.q == 2:
472
+ from sympy.functions.elementary.miscellaneous import sqrt
473
+ D = sqrt(r**2 + i**2)
474
+ if D.is_Rational:
475
+ from .exprtools import factor_terms
476
+ from sympy.functions.elementary.complexes import sign
477
+ from .function import expand_multinomial
478
+ # (r, i, D) is a Pythagorean triple
479
+ root = sqrt(factor_terms((D - r)/2))**e.p
480
+ return root*expand_multinomial((
481
+ # principle value
482
+ (D + r)/abs(i) + sign(i)*S.ImaginaryUnit)**e.p)
483
+ elif e == -1:
484
+ return _unevaluated_Mul(
485
+ r - i*S.ImaginaryUnit,
486
+ 1/(r**2 + i**2))
487
+ elif e.is_Number and abs(e) != 1:
488
+ # handle the Float case: (2.0 + 4*x)**e -> 4**e*(0.5 + x)**e
489
+ c, m = zip(*[i.as_coeff_Mul() for i in self.args])
490
+ if any(i.is_Float for i in c): # XXX should this always be done?
491
+ big = -1
492
+ for i in c:
493
+ if abs(i) >= big:
494
+ big = abs(i)
495
+ if big > 0 and not equal_valued(big, 1):
496
+ from sympy.functions.elementary.complexes import sign
497
+ bigs = (big, -big)
498
+ c = [sign(i) if i in bigs else i/big for i in c]
499
+ addpow = Add(*[c*m for c, m in zip(c, m)])**e
500
+ return big**e*addpow
501
+
502
+ @cacheit
503
+ def _eval_derivative(self, s):
504
+ return self.func(*[a.diff(s) for a in self.args])
505
+
506
+ def _eval_nseries(self, x, n, logx, cdir=0):
507
+ terms = [t.nseries(x, n=n, logx=logx, cdir=cdir) for t in self.args]
508
+ return self.func(*terms)
509
+
510
+ def _matches_simple(self, expr, repl_dict):
511
+ # handle (w+3).matches('x+5') -> {w: x+2}
512
+ coeff, terms = self.as_coeff_add()
513
+ if len(terms) == 1:
514
+ return terms[0].matches(expr - coeff, repl_dict)
515
+ return
516
+
517
+ def matches(self, expr, repl_dict=None, old=False):
518
+ return self._matches_commutative(expr, repl_dict, old)
519
+
520
+ @staticmethod
521
+ def _combine_inverse(lhs, rhs):
522
+ """
523
+ Returns lhs - rhs, but treats oo like a symbol so oo - oo
524
+ returns 0, instead of a nan.
525
+ """
526
+ from sympy.simplify.simplify import signsimp
527
+ inf = (S.Infinity, S.NegativeInfinity)
528
+ if lhs.has(*inf) or rhs.has(*inf):
529
+ from .symbol import Dummy
530
+ oo = Dummy('oo')
531
+ reps = {
532
+ S.Infinity: oo,
533
+ S.NegativeInfinity: -oo}
534
+ ireps = {v: k for k, v in reps.items()}
535
+ eq = lhs.xreplace(reps) - rhs.xreplace(reps)
536
+ if eq.has(oo):
537
+ eq = eq.replace(
538
+ lambda x: x.is_Pow and x.base is oo,
539
+ lambda x: x.base)
540
+ rv = eq.xreplace(ireps)
541
+ else:
542
+ rv = lhs - rhs
543
+ srv = signsimp(rv)
544
+ return srv if srv.is_Number else rv
545
+
546
+ @cacheit
547
+ def as_two_terms(self):
548
+ """Return head and tail of self.
549
+
550
+ This is the most efficient way to get the head and tail of an
551
+ expression.
552
+
553
+ - if you want only the head, use self.args[0];
554
+ - if you want to process the arguments of the tail then use
555
+ self.as_coef_add() which gives the head and a tuple containing
556
+ the arguments of the tail when treated as an Add.
557
+ - if you want the coefficient when self is treated as a Mul
558
+ then use self.as_coeff_mul()[0]
559
+
560
+ >>> from sympy.abc import x, y
561
+ >>> (3*x - 2*y + 5).as_two_terms()
562
+ (5, 3*x - 2*y)
563
+ """
564
+ return self.args[0], self._new_rawargs(*self.args[1:])
565
+
566
+ def as_numer_denom(self):
567
+ """
568
+ Decomposes an expression to its numerator part and its
569
+ denominator part.
570
+
571
+ Examples
572
+ ========
573
+
574
+ >>> from sympy.abc import x, y, z
575
+ >>> (x*y/z).as_numer_denom()
576
+ (x*y, z)
577
+ >>> (x*(y + 1)/y**7).as_numer_denom()
578
+ (x*(y + 1), y**7)
579
+
580
+ See Also
581
+ ========
582
+
583
+ sympy.core.expr.Expr.as_numer_denom
584
+ """
585
+ # clear rational denominator
586
+ content, expr = self.primitive()
587
+ if not isinstance(expr, Add):
588
+ return Mul(content, expr, evaluate=False).as_numer_denom()
589
+ ncon, dcon = content.as_numer_denom()
590
+
591
+ # collect numerators and denominators of the terms
592
+ nd = defaultdict(list)
593
+ for f in expr.args:
594
+ ni, di = f.as_numer_denom()
595
+ nd[di].append(ni)
596
+
597
+ # check for quick exit
598
+ if len(nd) == 1:
599
+ d, n = nd.popitem()
600
+ return self.func(
601
+ *[_keep_coeff(ncon, ni) for ni in n]), _keep_coeff(dcon, d)
602
+
603
+ # sum up the terms having a common denominator
604
+ for d, n in nd.items():
605
+ if len(n) == 1:
606
+ nd[d] = n[0]
607
+ else:
608
+ nd[d] = self.func(*n)
609
+
610
+ # assemble single numerator and denominator
611
+ denoms, numers = [list(i) for i in zip(*iter(nd.items()))]
612
+ n, d = self.func(*[Mul(*(denoms[:i] + [numers[i]] + denoms[i + 1:]))
613
+ for i in range(len(numers))]), Mul(*denoms)
614
+
615
+ return _keep_coeff(ncon, n), _keep_coeff(dcon, d)
616
+
617
+ def _eval_is_polynomial(self, syms):
618
+ return all(term._eval_is_polynomial(syms) for term in self.args)
619
+
620
+ def _eval_is_rational_function(self, syms):
621
+ return all(term._eval_is_rational_function(syms) for term in self.args)
622
+
623
+ def _eval_is_meromorphic(self, x, a):
624
+ return _fuzzy_group((arg.is_meromorphic(x, a) for arg in self.args),
625
+ quick_exit=True)
626
+
627
+ def _eval_is_algebraic_expr(self, syms):
628
+ return all(term._eval_is_algebraic_expr(syms) for term in self.args)
629
+
630
+ # assumption methods
631
+ _eval_is_real = lambda self: _fuzzy_group(
632
+ (a.is_real for a in self.args), quick_exit=True)
633
+ _eval_is_extended_real = lambda self: _fuzzy_group(
634
+ (a.is_extended_real for a in self.args), quick_exit=True)
635
+ _eval_is_complex = lambda self: _fuzzy_group(
636
+ (a.is_complex for a in self.args), quick_exit=True)
637
+ _eval_is_antihermitian = lambda self: _fuzzy_group(
638
+ (a.is_antihermitian for a in self.args), quick_exit=True)
639
+ _eval_is_finite = lambda self: _fuzzy_group(
640
+ (a.is_finite for a in self.args), quick_exit=True)
641
+ _eval_is_hermitian = lambda self: _fuzzy_group(
642
+ (a.is_hermitian for a in self.args), quick_exit=True)
643
+ _eval_is_integer = lambda self: _fuzzy_group(
644
+ (a.is_integer for a in self.args), quick_exit=True)
645
+ _eval_is_rational = lambda self: _fuzzy_group(
646
+ (a.is_rational for a in self.args), quick_exit=True)
647
+ _eval_is_algebraic = lambda self: _fuzzy_group(
648
+ (a.is_algebraic for a in self.args), quick_exit=True)
649
+ _eval_is_commutative = lambda self: _fuzzy_group(
650
+ a.is_commutative for a in self.args)
651
+
652
+ def _eval_is_infinite(self):
653
+ sawinf = False
654
+ for a in self.args:
655
+ ainf = a.is_infinite
656
+ if ainf is None:
657
+ return None
658
+ elif ainf is True:
659
+ # infinite+infinite might not be infinite
660
+ if sawinf is True:
661
+ return None
662
+ sawinf = True
663
+ return sawinf
664
+
665
+ def _eval_is_imaginary(self):
666
+ nz = []
667
+ im_I = []
668
+ for a in self.args:
669
+ if a.is_extended_real:
670
+ if a.is_zero:
671
+ pass
672
+ elif a.is_zero is False:
673
+ nz.append(a)
674
+ else:
675
+ return
676
+ elif a.is_imaginary:
677
+ im_I.append(a*S.ImaginaryUnit)
678
+ elif a.is_Mul and S.ImaginaryUnit in a.args:
679
+ coeff, ai = a.as_coeff_mul(S.ImaginaryUnit)
680
+ if ai == (S.ImaginaryUnit,) and coeff.is_extended_real:
681
+ im_I.append(-coeff)
682
+ else:
683
+ return
684
+ else:
685
+ return
686
+ b = self.func(*nz)
687
+ if b != self:
688
+ if b.is_zero:
689
+ return fuzzy_not(self.func(*im_I).is_zero)
690
+ elif b.is_zero is False:
691
+ return False
692
+
693
+ def _eval_is_zero(self):
694
+ if self.is_commutative is False:
695
+ # issue 10528: there is no way to know if a nc symbol
696
+ # is zero or not
697
+ return
698
+ nz = []
699
+ z = 0
700
+ im_or_z = False
701
+ im = 0
702
+ for a in self.args:
703
+ if a.is_extended_real:
704
+ if a.is_zero:
705
+ z += 1
706
+ elif a.is_zero is False:
707
+ nz.append(a)
708
+ else:
709
+ return
710
+ elif a.is_imaginary:
711
+ im += 1
712
+ elif a.is_Mul and S.ImaginaryUnit in a.args:
713
+ coeff, ai = a.as_coeff_mul(S.ImaginaryUnit)
714
+ if ai == (S.ImaginaryUnit,) and coeff.is_extended_real:
715
+ im_or_z = True
716
+ else:
717
+ return
718
+ else:
719
+ return
720
+ if z == len(self.args):
721
+ return True
722
+ if len(nz) in [0, len(self.args)]:
723
+ return None
724
+ b = self.func(*nz)
725
+ if b.is_zero:
726
+ if not im_or_z:
727
+ if im == 0:
728
+ return True
729
+ elif im == 1:
730
+ return False
731
+ if b.is_zero is False:
732
+ return False
733
+
734
+ def _eval_is_odd(self):
735
+ l = [f for f in self.args if not (f.is_even is True)]
736
+ if not l:
737
+ return False
738
+ if l[0].is_odd:
739
+ return self._new_rawargs(*l[1:]).is_even
740
+
741
+ def _eval_is_irrational(self):
742
+ for t in self.args:
743
+ a = t.is_irrational
744
+ if a:
745
+ others = list(self.args)
746
+ others.remove(t)
747
+ if all(x.is_rational is True for x in others):
748
+ return True
749
+ return None
750
+ if a is None:
751
+ return
752
+ return False
753
+
754
+ def _all_nonneg_or_nonppos(self):
755
+ nn = np = 0
756
+ for a in self.args:
757
+ if a.is_nonnegative:
758
+ if np:
759
+ return False
760
+ nn = 1
761
+ elif a.is_nonpositive:
762
+ if nn:
763
+ return False
764
+ np = 1
765
+ else:
766
+ break
767
+ else:
768
+ return True
769
+
770
+ def _eval_is_extended_positive(self):
771
+ if self.is_number:
772
+ return super()._eval_is_extended_positive()
773
+ c, a = self.as_coeff_Add()
774
+ if not c.is_zero:
775
+ from .exprtools import _monotonic_sign
776
+ v = _monotonic_sign(a)
777
+ if v is not None:
778
+ s = v + c
779
+ if s != self and s.is_extended_positive and a.is_extended_nonnegative:
780
+ return True
781
+ if len(self.free_symbols) == 1:
782
+ v = _monotonic_sign(self)
783
+ if v is not None and v != self and v.is_extended_positive:
784
+ return True
785
+ pos = nonneg = nonpos = unknown_sign = False
786
+ saw_INF = set()
787
+ args = [a for a in self.args if not a.is_zero]
788
+ if not args:
789
+ return False
790
+ for a in args:
791
+ ispos = a.is_extended_positive
792
+ infinite = a.is_infinite
793
+ if infinite:
794
+ saw_INF.add(fuzzy_or((ispos, a.is_extended_nonnegative)))
795
+ if True in saw_INF and False in saw_INF:
796
+ return
797
+ if ispos:
798
+ pos = True
799
+ continue
800
+ elif a.is_extended_nonnegative:
801
+ nonneg = True
802
+ continue
803
+ elif a.is_extended_nonpositive:
804
+ nonpos = True
805
+ continue
806
+
807
+ if infinite is None:
808
+ return
809
+ unknown_sign = True
810
+
811
+ if saw_INF:
812
+ if len(saw_INF) > 1:
813
+ return
814
+ return saw_INF.pop()
815
+ elif unknown_sign:
816
+ return
817
+ elif not nonpos and not nonneg and pos:
818
+ return True
819
+ elif not nonpos and pos:
820
+ return True
821
+ elif not pos and not nonneg:
822
+ return False
823
+
824
+ def _eval_is_extended_nonnegative(self):
825
+ if not self.is_number:
826
+ c, a = self.as_coeff_Add()
827
+ if not c.is_zero and a.is_extended_nonnegative:
828
+ from .exprtools import _monotonic_sign
829
+ v = _monotonic_sign(a)
830
+ if v is not None:
831
+ s = v + c
832
+ if s != self and s.is_extended_nonnegative:
833
+ return True
834
+ if len(self.free_symbols) == 1:
835
+ v = _monotonic_sign(self)
836
+ if v is not None and v != self and v.is_extended_nonnegative:
837
+ return True
838
+
839
+ def _eval_is_extended_nonpositive(self):
840
+ if not self.is_number:
841
+ c, a = self.as_coeff_Add()
842
+ if not c.is_zero and a.is_extended_nonpositive:
843
+ from .exprtools import _monotonic_sign
844
+ v = _monotonic_sign(a)
845
+ if v is not None:
846
+ s = v + c
847
+ if s != self and s.is_extended_nonpositive:
848
+ return True
849
+ if len(self.free_symbols) == 1:
850
+ v = _monotonic_sign(self)
851
+ if v is not None and v != self and v.is_extended_nonpositive:
852
+ return True
853
+
854
+ def _eval_is_extended_negative(self):
855
+ if self.is_number:
856
+ return super()._eval_is_extended_negative()
857
+ c, a = self.as_coeff_Add()
858
+ if not c.is_zero:
859
+ from .exprtools import _monotonic_sign
860
+ v = _monotonic_sign(a)
861
+ if v is not None:
862
+ s = v + c
863
+ if s != self and s.is_extended_negative and a.is_extended_nonpositive:
864
+ return True
865
+ if len(self.free_symbols) == 1:
866
+ v = _monotonic_sign(self)
867
+ if v is not None and v != self and v.is_extended_negative:
868
+ return True
869
+ neg = nonpos = nonneg = unknown_sign = False
870
+ saw_INF = set()
871
+ args = [a for a in self.args if not a.is_zero]
872
+ if not args:
873
+ return False
874
+ for a in args:
875
+ isneg = a.is_extended_negative
876
+ infinite = a.is_infinite
877
+ if infinite:
878
+ saw_INF.add(fuzzy_or((isneg, a.is_extended_nonpositive)))
879
+ if True in saw_INF and False in saw_INF:
880
+ return
881
+ if isneg:
882
+ neg = True
883
+ continue
884
+ elif a.is_extended_nonpositive:
885
+ nonpos = True
886
+ continue
887
+ elif a.is_extended_nonnegative:
888
+ nonneg = True
889
+ continue
890
+
891
+ if infinite is None:
892
+ return
893
+ unknown_sign = True
894
+
895
+ if saw_INF:
896
+ if len(saw_INF) > 1:
897
+ return
898
+ return saw_INF.pop()
899
+ elif unknown_sign:
900
+ return
901
+ elif not nonneg and not nonpos and neg:
902
+ return True
903
+ elif not nonneg and neg:
904
+ return True
905
+ elif not neg and not nonpos:
906
+ return False
907
+
908
+ def _eval_subs(self, old, new):
909
+ if not old.is_Add:
910
+ if old is S.Infinity and -old in self.args:
911
+ # foo - oo is foo + (-oo) internally
912
+ return self.xreplace({-old: -new})
913
+ return None
914
+
915
+ coeff_self, terms_self = self.as_coeff_Add()
916
+ coeff_old, terms_old = old.as_coeff_Add()
917
+
918
+ if coeff_self.is_Rational and coeff_old.is_Rational:
919
+ if terms_self == terms_old: # (2 + a).subs( 3 + a, y) -> -1 + y
920
+ return self.func(new, coeff_self, -coeff_old)
921
+ if terms_self == -terms_old: # (2 + a).subs(-3 - a, y) -> -1 - y
922
+ return self.func(-new, coeff_self, coeff_old)
923
+
924
+ if coeff_self.is_Rational and coeff_old.is_Rational \
925
+ or coeff_self == coeff_old:
926
+ args_old, args_self = self.func.make_args(
927
+ terms_old), self.func.make_args(terms_self)
928
+ if len(args_old) < len(args_self): # (a+b+c).subs(b+c,x) -> a+x
929
+ self_set = set(args_self)
930
+ old_set = set(args_old)
931
+
932
+ if old_set < self_set:
933
+ ret_set = self_set - old_set
934
+ return self.func(new, coeff_self, -coeff_old,
935
+ *[s._subs(old, new) for s in ret_set])
936
+
937
+ args_old = self.func.make_args(
938
+ -terms_old) # (a+b+c+d).subs(-b-c,x) -> a-x+d
939
+ old_set = set(args_old)
940
+ if old_set < self_set:
941
+ ret_set = self_set - old_set
942
+ return self.func(-new, coeff_self, coeff_old,
943
+ *[s._subs(old, new) for s in ret_set])
944
+
945
+ def removeO(self):
946
+ args = [a for a in self.args if not a.is_Order]
947
+ return self._new_rawargs(*args)
948
+
949
+ def getO(self):
950
+ args = [a for a in self.args if a.is_Order]
951
+ if args:
952
+ return self._new_rawargs(*args)
953
+
954
+ @cacheit
955
+ def extract_leading_order(self, symbols, point=None):
956
+ """
957
+ Returns the leading term and its order.
958
+
959
+ Examples
960
+ ========
961
+
962
+ >>> from sympy.abc import x
963
+ >>> (x + 1 + 1/x**5).extract_leading_order(x)
964
+ ((x**(-5), O(x**(-5))),)
965
+ >>> (1 + x).extract_leading_order(x)
966
+ ((1, O(1)),)
967
+ >>> (x + x**2).extract_leading_order(x)
968
+ ((x, O(x)),)
969
+
970
+ """
971
+ from sympy.series.order import Order
972
+ lst = []
973
+ symbols = list(symbols if is_sequence(symbols) else [symbols])
974
+ if not point:
975
+ point = [0]*len(symbols)
976
+ seq = [(f, Order(f, *zip(symbols, point))) for f in self.args]
977
+ for ef, of in seq:
978
+ for e, o in lst:
979
+ if o.contains(of) and o != of:
980
+ of = None
981
+ break
982
+ if of is None:
983
+ continue
984
+ new_lst = [(ef, of)]
985
+ for e, o in lst:
986
+ if of.contains(o) and o != of:
987
+ continue
988
+ new_lst.append((e, o))
989
+ lst = new_lst
990
+ return tuple(lst)
991
+
992
+ def as_real_imag(self, deep=True, **hints):
993
+ """
994
+ Return a tuple representing a complex number.
995
+
996
+ Examples
997
+ ========
998
+
999
+ >>> from sympy import I
1000
+ >>> (7 + 9*I).as_real_imag()
1001
+ (7, 9)
1002
+ >>> ((1 + I)/(1 - I)).as_real_imag()
1003
+ (0, 1)
1004
+ >>> ((1 + 2*I)*(1 + 3*I)).as_real_imag()
1005
+ (-5, 5)
1006
+ """
1007
+ sargs = self.args
1008
+ re_part, im_part = [], []
1009
+ for term in sargs:
1010
+ re, im = term.as_real_imag(deep=deep)
1011
+ re_part.append(re)
1012
+ im_part.append(im)
1013
+ return (self.func(*re_part), self.func(*im_part))
1014
+
1015
+ def _eval_as_leading_term(self, x, logx=None, cdir=0):
1016
+ from sympy.core.symbol import Dummy, Symbol
1017
+ from sympy.series.order import Order
1018
+ from sympy.functions.elementary.exponential import log
1019
+ from sympy.functions.elementary.piecewise import Piecewise, piecewise_fold
1020
+ from .function import expand_mul
1021
+
1022
+ o = self.getO()
1023
+ if o is None:
1024
+ o = Order(0)
1025
+ old = self.removeO()
1026
+
1027
+ if old.has(Piecewise):
1028
+ old = piecewise_fold(old)
1029
+
1030
+ # This expansion is the last part of expand_log. expand_log also calls
1031
+ # expand_mul with factor=True, which would be more expensive
1032
+ if any(isinstance(a, log) for a in self.args):
1033
+ logflags = {"deep": True, "log": True, "mul": False, "power_exp": False,
1034
+ "power_base": False, "multinomial": False, "basic": False, "force": False,
1035
+ "factor": False}
1036
+ old = old.expand(**logflags)
1037
+ expr = expand_mul(old)
1038
+
1039
+ if not expr.is_Add:
1040
+ return expr.as_leading_term(x, logx=logx, cdir=cdir)
1041
+
1042
+ infinite = [t for t in expr.args if t.is_infinite]
1043
+
1044
+ _logx = Dummy('logx') if logx is None else logx
1045
+ leading_terms = [t.as_leading_term(x, logx=_logx, cdir=cdir) for t in expr.args]
1046
+
1047
+ min, new_expr = Order(0), 0
1048
+
1049
+ try:
1050
+ for term in leading_terms:
1051
+ order = Order(term, x)
1052
+ if not min or order not in min:
1053
+ min = order
1054
+ new_expr = term
1055
+ elif min in order:
1056
+ new_expr += term
1057
+
1058
+ except TypeError:
1059
+ return expr
1060
+
1061
+ if logx is None:
1062
+ new_expr = new_expr.subs(_logx, log(x))
1063
+
1064
+ is_zero = new_expr.is_zero
1065
+ if is_zero is None:
1066
+ new_expr = new_expr.trigsimp().cancel()
1067
+ is_zero = new_expr.is_zero
1068
+ if is_zero is True:
1069
+ # simple leading term analysis gave us cancelled terms but we have to send
1070
+ # back a term, so compute the leading term (via series)
1071
+ try:
1072
+ n0 = min.getn()
1073
+ except NotImplementedError:
1074
+ n0 = S.One
1075
+ if n0.has(Symbol):
1076
+ n0 = S.One
1077
+ res = Order(1)
1078
+ incr = S.One
1079
+ while res.is_Order:
1080
+ res = old._eval_nseries(x, n=n0+incr, logx=logx, cdir=cdir).cancel().powsimp().trigsimp()
1081
+ incr *= 2
1082
+ return res.as_leading_term(x, logx=logx, cdir=cdir)
1083
+
1084
+ elif new_expr is S.NaN:
1085
+ return old.func._from_args(infinite) + o
1086
+
1087
+ else:
1088
+ return new_expr
1089
+
1090
+ def _eval_adjoint(self):
1091
+ return self.func(*[t.adjoint() for t in self.args])
1092
+
1093
+ def _eval_conjugate(self):
1094
+ return self.func(*[t.conjugate() for t in self.args])
1095
+
1096
+ def _eval_transpose(self):
1097
+ return self.func(*[t.transpose() for t in self.args])
1098
+
1099
+ def primitive(self):
1100
+ """
1101
+ Return ``(R, self/R)`` where ``R``` is the Rational GCD of ``self```.
1102
+
1103
+ ``R`` is collected only from the leading coefficient of each term.
1104
+
1105
+ Examples
1106
+ ========
1107
+
1108
+ >>> from sympy.abc import x, y
1109
+
1110
+ >>> (2*x + 4*y).primitive()
1111
+ (2, x + 2*y)
1112
+
1113
+ >>> (2*x/3 + 4*y/9).primitive()
1114
+ (2/9, 3*x + 2*y)
1115
+
1116
+ >>> (2*x/3 + 4.2*y).primitive()
1117
+ (1/3, 2*x + 12.6*y)
1118
+
1119
+ No subprocessing of term factors is performed:
1120
+
1121
+ >>> ((2 + 2*x)*x + 2).primitive()
1122
+ (1, x*(2*x + 2) + 2)
1123
+
1124
+ Recursive processing can be done with the ``as_content_primitive()``
1125
+ method:
1126
+
1127
+ >>> ((2 + 2*x)*x + 2).as_content_primitive()
1128
+ (2, x*(x + 1) + 1)
1129
+
1130
+ See also: primitive() function in polytools.py
1131
+
1132
+ """
1133
+
1134
+ terms = []
1135
+ inf = False
1136
+ for a in self.args:
1137
+ c, m = a.as_coeff_Mul()
1138
+ if not c.is_Rational:
1139
+ c = S.One
1140
+ m = a
1141
+ inf = inf or m is S.ComplexInfinity
1142
+ terms.append((c.p, c.q, m))
1143
+
1144
+ if not inf:
1145
+ ngcd = reduce(igcd, [t[0] for t in terms], 0)
1146
+ dlcm = reduce(ilcm, [t[1] for t in terms], 1)
1147
+ else:
1148
+ ngcd = reduce(igcd, [t[0] for t in terms if t[1]], 0)
1149
+ dlcm = reduce(ilcm, [t[1] for t in terms if t[1]], 1)
1150
+
1151
+ if ngcd == dlcm == 1:
1152
+ return S.One, self
1153
+ if not inf:
1154
+ for i, (p, q, term) in enumerate(terms):
1155
+ terms[i] = _keep_coeff(Rational((p//ngcd)*(dlcm//q)), term)
1156
+ else:
1157
+ for i, (p, q, term) in enumerate(terms):
1158
+ if q:
1159
+ terms[i] = _keep_coeff(Rational((p//ngcd)*(dlcm//q)), term)
1160
+ else:
1161
+ terms[i] = _keep_coeff(Rational(p, q), term)
1162
+
1163
+ # we don't need a complete re-flattening since no new terms will join
1164
+ # so we just use the same sort as is used in Add.flatten. When the
1165
+ # coefficient changes, the ordering of terms may change, e.g.
1166
+ # (3*x, 6*y) -> (2*y, x)
1167
+ #
1168
+ # We do need to make sure that term[0] stays in position 0, however.
1169
+ #
1170
+ if terms[0].is_Number or terms[0] is S.ComplexInfinity:
1171
+ c = terms.pop(0)
1172
+ else:
1173
+ c = None
1174
+ _addsort(terms)
1175
+ if c:
1176
+ terms.insert(0, c)
1177
+ return Rational(ngcd, dlcm), self._new_rawargs(*terms)
1178
+
1179
+ def as_content_primitive(self, radical=False, clear=True):
1180
+ """Return the tuple (R, self/R) where R is the positive Rational
1181
+ extracted from self. If radical is True (default is False) then
1182
+ common radicals will be removed and included as a factor of the
1183
+ primitive expression.
1184
+
1185
+ Examples
1186
+ ========
1187
+
1188
+ >>> from sympy import sqrt
1189
+ >>> (3 + 3*sqrt(2)).as_content_primitive()
1190
+ (3, 1 + sqrt(2))
1191
+
1192
+ Radical content can also be factored out of the primitive:
1193
+
1194
+ >>> (2*sqrt(2) + 4*sqrt(10)).as_content_primitive(radical=True)
1195
+ (2, sqrt(2)*(1 + 2*sqrt(5)))
1196
+
1197
+ See docstring of Expr.as_content_primitive for more examples.
1198
+ """
1199
+ con, prim = self.func(*[_keep_coeff(*a.as_content_primitive(
1200
+ radical=radical, clear=clear)) for a in self.args]).primitive()
1201
+ if not clear and not con.is_Integer and prim.is_Add:
1202
+ con, d = con.as_numer_denom()
1203
+ _p = prim/d
1204
+ if any(a.as_coeff_Mul()[0].is_Integer for a in _p.args):
1205
+ prim = _p
1206
+ else:
1207
+ con /= d
1208
+ if radical and prim.is_Add:
1209
+ # look for common radicals that can be removed
1210
+ args = prim.args
1211
+ rads = []
1212
+ common_q = None
1213
+ for m in args:
1214
+ term_rads = defaultdict(list)
1215
+ for ai in Mul.make_args(m):
1216
+ if ai.is_Pow:
1217
+ b, e = ai.as_base_exp()
1218
+ if e.is_Rational and b.is_Integer:
1219
+ term_rads[e.q].append(abs(int(b))**e.p)
1220
+ if not term_rads:
1221
+ break
1222
+ if common_q is None:
1223
+ common_q = set(term_rads.keys())
1224
+ else:
1225
+ common_q = common_q & set(term_rads.keys())
1226
+ if not common_q:
1227
+ break
1228
+ rads.append(term_rads)
1229
+ else:
1230
+ # process rads
1231
+ # keep only those in common_q
1232
+ for r in rads:
1233
+ for q in list(r.keys()):
1234
+ if q not in common_q:
1235
+ r.pop(q)
1236
+ for q in r:
1237
+ r[q] = Mul(*r[q])
1238
+ # find the gcd of bases for each q
1239
+ G = []
1240
+ for q in common_q:
1241
+ g = reduce(igcd, [r[q] for r in rads], 0)
1242
+ if g != 1:
1243
+ G.append(g**Rational(1, q))
1244
+ if G:
1245
+ G = Mul(*G)
1246
+ args = [ai/G for ai in args]
1247
+ prim = G*prim.func(*args)
1248
+
1249
+ return con, prim
1250
+
1251
+ @property
1252
+ def _sorted_args(self):
1253
+ from .sorting import default_sort_key
1254
+ return tuple(sorted(self.args, key=default_sort_key))
1255
+
1256
+ def _eval_difference_delta(self, n, step):
1257
+ from sympy.series.limitseq import difference_delta as dd
1258
+ return self.func(*[dd(a, n, step) for a in self.args])
1259
+
1260
+ @property
1261
+ def _mpc_(self):
1262
+ """
1263
+ Convert self to an mpmath mpc if possible
1264
+ """
1265
+ from .numbers import Float
1266
+ re_part, rest = self.as_coeff_Add()
1267
+ im_part, imag_unit = rest.as_coeff_Mul()
1268
+ if not imag_unit == S.ImaginaryUnit:
1269
+ # ValueError may seem more reasonable but since it's a @property,
1270
+ # we need to use AttributeError to keep from confusing things like
1271
+ # hasattr.
1272
+ raise AttributeError("Cannot convert Add to mpc. Must be of the form Number + Number*I")
1273
+
1274
+ return (Float(re_part)._mpf_, Float(im_part)._mpf_)
1275
+
1276
+ def __neg__(self):
1277
+ if not global_parameters.distribute:
1278
+ return super().__neg__()
1279
+ return Mul(S.NegativeOne, self)
1280
+
1281
+ add = AssocOpDispatcher('add')
1282
+
1283
+ from .mul import Mul, _keep_coeff, _unevaluated_Mul
1284
+ from .numbers import Rational
lib/python3.12/site-packages/sympy/core/alphabets.py ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ greeks = ('alpha', 'beta', 'gamma', 'delta', 'epsilon', 'zeta',
2
+ 'eta', 'theta', 'iota', 'kappa', 'lambda', 'mu', 'nu',
3
+ 'xi', 'omicron', 'pi', 'rho', 'sigma', 'tau', 'upsilon',
4
+ 'phi', 'chi', 'psi', 'omega')
lib/python3.12/site-packages/sympy/core/assumptions.py ADDED
@@ -0,0 +1,692 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ This module contains the machinery handling assumptions.
3
+ Do also consider the guide :ref:`assumptions-guide`.
4
+
5
+ All symbolic objects have assumption attributes that can be accessed via
6
+ ``.is_<assumption name>`` attribute.
7
+
8
+ Assumptions determine certain properties of symbolic objects and can
9
+ have 3 possible values: ``True``, ``False``, ``None``. ``True`` is returned if the
10
+ object has the property and ``False`` is returned if it does not or cannot
11
+ (i.e. does not make sense):
12
+
13
+ >>> from sympy import I
14
+ >>> I.is_algebraic
15
+ True
16
+ >>> I.is_real
17
+ False
18
+ >>> I.is_prime
19
+ False
20
+
21
+ When the property cannot be determined (or when a method is not
22
+ implemented) ``None`` will be returned. For example, a generic symbol, ``x``,
23
+ may or may not be positive so a value of ``None`` is returned for ``x.is_positive``.
24
+
25
+ By default, all symbolic values are in the largest set in the given context
26
+ without specifying the property. For example, a symbol that has a property
27
+ being integer, is also real, complex, etc.
28
+
29
+ Here follows a list of possible assumption names:
30
+
31
+ .. glossary::
32
+
33
+ commutative
34
+ object commutes with any other object with
35
+ respect to multiplication operation. See [12]_.
36
+
37
+ complex
38
+ object can have only values from the set
39
+ of complex numbers. See [13]_.
40
+
41
+ imaginary
42
+ object value is a number that can be written as a real
43
+ number multiplied by the imaginary unit ``I``. See
44
+ [3]_. Please note that ``0`` is not considered to be an
45
+ imaginary number, see
46
+ `issue #7649 <https://github.com/sympy/sympy/issues/7649>`_.
47
+
48
+ real
49
+ object can have only values from the set
50
+ of real numbers.
51
+
52
+ extended_real
53
+ object can have only values from the set
54
+ of real numbers, ``oo`` and ``-oo``.
55
+
56
+ integer
57
+ object can have only values from the set
58
+ of integers.
59
+
60
+ odd
61
+ even
62
+ object can have only values from the set of
63
+ odd (even) integers [2]_.
64
+
65
+ prime
66
+ object is a natural number greater than 1 that has
67
+ no positive divisors other than 1 and itself. See [6]_.
68
+
69
+ composite
70
+ object is a positive integer that has at least one positive
71
+ divisor other than 1 or the number itself. See [4]_.
72
+
73
+ zero
74
+ object has the value of 0.
75
+
76
+ nonzero
77
+ object is a real number that is not zero.
78
+
79
+ rational
80
+ object can have only values from the set
81
+ of rationals.
82
+
83
+ algebraic
84
+ object can have only values from the set
85
+ of algebraic numbers [11]_.
86
+
87
+ transcendental
88
+ object can have only values from the set
89
+ of transcendental numbers [10]_.
90
+
91
+ irrational
92
+ object value cannot be represented exactly by :class:`~.Rational`, see [5]_.
93
+
94
+ finite
95
+ infinite
96
+ object absolute value is bounded (arbitrarily large).
97
+ See [7]_, [8]_, [9]_.
98
+
99
+ negative
100
+ nonnegative
101
+ object can have only negative (nonnegative)
102
+ values [1]_.
103
+
104
+ positive
105
+ nonpositive
106
+ object can have only positive (nonpositive) values.
107
+
108
+ extended_negative
109
+ extended_nonnegative
110
+ extended_positive
111
+ extended_nonpositive
112
+ extended_nonzero
113
+ as without the extended part, but also including infinity with
114
+ corresponding sign, e.g., extended_positive includes ``oo``
115
+
116
+ hermitian
117
+ antihermitian
118
+ object belongs to the field of Hermitian
119
+ (antihermitian) operators.
120
+
121
+ Examples
122
+ ========
123
+
124
+ >>> from sympy import Symbol
125
+ >>> x = Symbol('x', real=True); x
126
+ x
127
+ >>> x.is_real
128
+ True
129
+ >>> x.is_complex
130
+ True
131
+
132
+ See Also
133
+ ========
134
+
135
+ .. seealso::
136
+
137
+ :py:class:`sympy.core.numbers.ImaginaryUnit`
138
+ :py:class:`sympy.core.numbers.Zero`
139
+ :py:class:`sympy.core.numbers.One`
140
+ :py:class:`sympy.core.numbers.Infinity`
141
+ :py:class:`sympy.core.numbers.NegativeInfinity`
142
+ :py:class:`sympy.core.numbers.ComplexInfinity`
143
+
144
+ Notes
145
+ =====
146
+
147
+ The fully-resolved assumptions for any SymPy expression
148
+ can be obtained as follows:
149
+
150
+ >>> from sympy.core.assumptions import assumptions
151
+ >>> x = Symbol('x',positive=True)
152
+ >>> assumptions(x + I)
153
+ {'commutative': True, 'complex': True, 'composite': False, 'even':
154
+ False, 'extended_negative': False, 'extended_nonnegative': False,
155
+ 'extended_nonpositive': False, 'extended_nonzero': False,
156
+ 'extended_positive': False, 'extended_real': False, 'finite': True,
157
+ 'imaginary': False, 'infinite': False, 'integer': False, 'irrational':
158
+ False, 'negative': False, 'noninteger': False, 'nonnegative': False,
159
+ 'nonpositive': False, 'nonzero': False, 'odd': False, 'positive':
160
+ False, 'prime': False, 'rational': False, 'real': False, 'zero':
161
+ False}
162
+
163
+ Developers Notes
164
+ ================
165
+
166
+ The current (and possibly incomplete) values are stored
167
+ in the ``obj._assumptions dictionary``; queries to getter methods
168
+ (with property decorators) or attributes of objects/classes
169
+ will return values and update the dictionary.
170
+
171
+ >>> eq = x**2 + I
172
+ >>> eq._assumptions
173
+ {}
174
+ >>> eq.is_finite
175
+ True
176
+ >>> eq._assumptions
177
+ {'finite': True, 'infinite': False}
178
+
179
+ For a :class:`~.Symbol`, there are two locations for assumptions that may
180
+ be of interest. The ``assumptions0`` attribute gives the full set of
181
+ assumptions derived from a given set of initial assumptions. The
182
+ latter assumptions are stored as ``Symbol._assumptions_orig``
183
+
184
+ >>> Symbol('x', prime=True, even=True)._assumptions_orig
185
+ {'even': True, 'prime': True}
186
+
187
+ The ``_assumptions_orig`` are not necessarily canonical nor are they filtered
188
+ in any way: they records the assumptions used to instantiate a Symbol and (for
189
+ storage purposes) represent a more compact representation of the assumptions
190
+ needed to recreate the full set in ``Symbol.assumptions0``.
191
+
192
+
193
+ References
194
+ ==========
195
+
196
+ .. [1] https://en.wikipedia.org/wiki/Negative_number
197
+ .. [2] https://en.wikipedia.org/wiki/Parity_%28mathematics%29
198
+ .. [3] https://en.wikipedia.org/wiki/Imaginary_number
199
+ .. [4] https://en.wikipedia.org/wiki/Composite_number
200
+ .. [5] https://en.wikipedia.org/wiki/Irrational_number
201
+ .. [6] https://en.wikipedia.org/wiki/Prime_number
202
+ .. [7] https://en.wikipedia.org/wiki/Finite
203
+ .. [8] https://docs.python.org/3/library/math.html#math.isfinite
204
+ .. [9] https://numpy.org/doc/stable/reference/generated/numpy.isfinite.html
205
+ .. [10] https://en.wikipedia.org/wiki/Transcendental_number
206
+ .. [11] https://en.wikipedia.org/wiki/Algebraic_number
207
+ .. [12] https://en.wikipedia.org/wiki/Commutative_property
208
+ .. [13] https://en.wikipedia.org/wiki/Complex_number
209
+
210
+ """
211
+
212
+ from sympy.utilities.exceptions import sympy_deprecation_warning
213
+
214
+ from .facts import FactRules, FactKB
215
+ from .sympify import sympify
216
+
217
+ from sympy.core.random import _assumptions_shuffle as shuffle
218
+ from sympy.core.assumptions_generated import generated_assumptions as _assumptions
219
+
220
+ def _load_pre_generated_assumption_rules() -> FactRules:
221
+ """ Load the assumption rules from pre-generated data
222
+
223
+ To update the pre-generated data, see :method::`_generate_assumption_rules`
224
+ """
225
+ _assume_rules=FactRules._from_python(_assumptions)
226
+ return _assume_rules
227
+
228
+ def _generate_assumption_rules():
229
+ """ Generate the default assumption rules
230
+
231
+ This method should only be called to update the pre-generated
232
+ assumption rules.
233
+
234
+ To update the pre-generated assumptions run: bin/ask_update.py
235
+
236
+ """
237
+ _assume_rules = FactRules([
238
+
239
+ 'integer -> rational',
240
+ 'rational -> real',
241
+ 'rational -> algebraic',
242
+ 'algebraic -> complex',
243
+ 'transcendental == complex & !algebraic',
244
+ 'real -> hermitian',
245
+ 'imaginary -> complex',
246
+ 'imaginary -> antihermitian',
247
+ 'extended_real -> commutative',
248
+ 'complex -> commutative',
249
+ 'complex -> finite',
250
+
251
+ 'odd == integer & !even',
252
+ 'even == integer & !odd',
253
+
254
+ 'real -> complex',
255
+ 'extended_real -> real | infinite',
256
+ 'real == extended_real & finite',
257
+
258
+ 'extended_real == extended_negative | zero | extended_positive',
259
+ 'extended_negative == extended_nonpositive & extended_nonzero',
260
+ 'extended_positive == extended_nonnegative & extended_nonzero',
261
+
262
+ 'extended_nonpositive == extended_real & !extended_positive',
263
+ 'extended_nonnegative == extended_real & !extended_negative',
264
+
265
+ 'real == negative | zero | positive',
266
+ 'negative == nonpositive & nonzero',
267
+ 'positive == nonnegative & nonzero',
268
+
269
+ 'nonpositive == real & !positive',
270
+ 'nonnegative == real & !negative',
271
+
272
+ 'positive == extended_positive & finite',
273
+ 'negative == extended_negative & finite',
274
+ 'nonpositive == extended_nonpositive & finite',
275
+ 'nonnegative == extended_nonnegative & finite',
276
+ 'nonzero == extended_nonzero & finite',
277
+
278
+ 'zero -> even & finite',
279
+ 'zero == extended_nonnegative & extended_nonpositive',
280
+ 'zero == nonnegative & nonpositive',
281
+ 'nonzero -> real',
282
+
283
+ 'prime -> integer & positive',
284
+ 'composite -> integer & positive & !prime',
285
+ '!composite -> !positive | !even | prime',
286
+
287
+ 'irrational == real & !rational',
288
+
289
+ 'imaginary -> !extended_real',
290
+
291
+ 'infinite == !finite',
292
+ 'noninteger == extended_real & !integer',
293
+ 'extended_nonzero == extended_real & !zero',
294
+ ])
295
+ return _assume_rules
296
+
297
+
298
+ _assume_rules = _load_pre_generated_assumption_rules()
299
+ _assume_defined = _assume_rules.defined_facts.copy()
300
+ _assume_defined.add('polar')
301
+ _assume_defined = frozenset(_assume_defined)
302
+
303
+
304
+ def assumptions(expr, _check=None):
305
+ """return the T/F assumptions of ``expr``"""
306
+ n = sympify(expr)
307
+ if n.is_Symbol:
308
+ rv = n.assumptions0 # are any important ones missing?
309
+ if _check is not None:
310
+ rv = {k: rv[k] for k in set(rv) & set(_check)}
311
+ return rv
312
+ rv = {}
313
+ for k in _assume_defined if _check is None else _check:
314
+ v = getattr(n, 'is_{}'.format(k))
315
+ if v is not None:
316
+ rv[k] = v
317
+ return rv
318
+
319
+
320
+ def common_assumptions(exprs, check=None):
321
+ """return those assumptions which have the same True or False
322
+ value for all the given expressions.
323
+
324
+ Examples
325
+ ========
326
+
327
+ >>> from sympy.core import common_assumptions
328
+ >>> from sympy import oo, pi, sqrt
329
+ >>> common_assumptions([-4, 0, sqrt(2), 2, pi, oo])
330
+ {'commutative': True, 'composite': False,
331
+ 'extended_real': True, 'imaginary': False, 'odd': False}
332
+
333
+ By default, all assumptions are tested; pass an iterable of the
334
+ assumptions to limit those that are reported:
335
+
336
+ >>> common_assumptions([0, 1, 2], ['positive', 'integer'])
337
+ {'integer': True}
338
+ """
339
+ check = _assume_defined if check is None else set(check)
340
+ if not check or not exprs:
341
+ return {}
342
+
343
+ # get all assumptions for each
344
+ assume = [assumptions(i, _check=check) for i in sympify(exprs)]
345
+ # focus on those of interest that are True
346
+ for i, e in enumerate(assume):
347
+ assume[i] = {k: e[k] for k in set(e) & check}
348
+ # what assumptions are in common?
349
+ common = set.intersection(*[set(i) for i in assume])
350
+ # which ones hold the same value
351
+ a = assume[0]
352
+ return {k: a[k] for k in common if all(a[k] == b[k]
353
+ for b in assume)}
354
+
355
+
356
+ def failing_assumptions(expr, **assumptions):
357
+ """
358
+ Return a dictionary containing assumptions with values not
359
+ matching those of the passed assumptions.
360
+
361
+ Examples
362
+ ========
363
+
364
+ >>> from sympy import failing_assumptions, Symbol
365
+
366
+ >>> x = Symbol('x', positive=True)
367
+ >>> y = Symbol('y')
368
+ >>> failing_assumptions(6*x + y, positive=True)
369
+ {'positive': None}
370
+
371
+ >>> failing_assumptions(x**2 - 1, positive=True)
372
+ {'positive': None}
373
+
374
+ If *expr* satisfies all of the assumptions, an empty dictionary is returned.
375
+
376
+ >>> failing_assumptions(x**2, positive=True)
377
+ {}
378
+
379
+ """
380
+ expr = sympify(expr)
381
+ failed = {}
382
+ for k in assumptions:
383
+ test = getattr(expr, 'is_%s' % k, None)
384
+ if test is not assumptions[k]:
385
+ failed[k] = test
386
+ return failed # {} or {assumption: value != desired}
387
+
388
+
389
+ def check_assumptions(expr, against=None, **assume):
390
+ """
391
+ Checks whether assumptions of ``expr`` match the T/F assumptions
392
+ given (or possessed by ``against``). True is returned if all
393
+ assumptions match; False is returned if there is a mismatch and
394
+ the assumption in ``expr`` is not None; else None is returned.
395
+
396
+ Explanation
397
+ ===========
398
+
399
+ *assume* is a dict of assumptions with True or False values
400
+
401
+ Examples
402
+ ========
403
+
404
+ >>> from sympy import Symbol, pi, I, exp, check_assumptions
405
+ >>> check_assumptions(-5, integer=True)
406
+ True
407
+ >>> check_assumptions(pi, real=True, integer=False)
408
+ True
409
+ >>> check_assumptions(pi, negative=True)
410
+ False
411
+ >>> check_assumptions(exp(I*pi/7), real=False)
412
+ True
413
+ >>> x = Symbol('x', positive=True)
414
+ >>> check_assumptions(2*x + 1, positive=True)
415
+ True
416
+ >>> check_assumptions(-2*x - 5, positive=True)
417
+ False
418
+
419
+ To check assumptions of *expr* against another variable or expression,
420
+ pass the expression or variable as ``against``.
421
+
422
+ >>> check_assumptions(2*x + 1, x)
423
+ True
424
+
425
+ To see if a number matches the assumptions of an expression, pass
426
+ the number as the first argument, else its specific assumptions
427
+ may not have a non-None value in the expression:
428
+
429
+ >>> check_assumptions(x, 3)
430
+ >>> check_assumptions(3, x)
431
+ True
432
+
433
+ ``None`` is returned if ``check_assumptions()`` could not conclude.
434
+
435
+ >>> check_assumptions(2*x - 1, x)
436
+
437
+ >>> z = Symbol('z')
438
+ >>> check_assumptions(z, real=True)
439
+
440
+ See Also
441
+ ========
442
+
443
+ failing_assumptions
444
+
445
+ """
446
+ expr = sympify(expr)
447
+ if against is not None:
448
+ if assume:
449
+ raise ValueError(
450
+ 'Expecting `against` or `assume`, not both.')
451
+ assume = assumptions(against)
452
+ known = True
453
+ for k, v in assume.items():
454
+ if v is None:
455
+ continue
456
+ e = getattr(expr, 'is_' + k, None)
457
+ if e is None:
458
+ known = None
459
+ elif v != e:
460
+ return False
461
+ return known
462
+
463
+
464
+ class StdFactKB(FactKB):
465
+ """A FactKB specialized for the built-in rules
466
+
467
+ This is the only kind of FactKB that Basic objects should use.
468
+ """
469
+ def __init__(self, facts=None):
470
+ super().__init__(_assume_rules)
471
+ # save a copy of the facts dict
472
+ if not facts:
473
+ self._generator = {}
474
+ elif not isinstance(facts, FactKB):
475
+ self._generator = facts.copy()
476
+ else:
477
+ self._generator = facts.generator
478
+ if facts:
479
+ self.deduce_all_facts(facts)
480
+
481
+ def copy(self):
482
+ return self.__class__(self)
483
+
484
+ @property
485
+ def generator(self):
486
+ return self._generator.copy()
487
+
488
+
489
+ def as_property(fact):
490
+ """Convert a fact name to the name of the corresponding property"""
491
+ return 'is_%s' % fact
492
+
493
+
494
+ def make_property(fact):
495
+ """Create the automagic property corresponding to a fact."""
496
+
497
+ def getit(self):
498
+ try:
499
+ return self._assumptions[fact]
500
+ except KeyError:
501
+ if self._assumptions is self.default_assumptions:
502
+ self._assumptions = self.default_assumptions.copy()
503
+ return _ask(fact, self)
504
+
505
+ getit.func_name = as_property(fact)
506
+ return property(getit)
507
+
508
+
509
+ def _ask(fact, obj):
510
+ """
511
+ Find the truth value for a property of an object.
512
+
513
+ This function is called when a request is made to see what a fact
514
+ value is.
515
+
516
+ For this we use several techniques:
517
+
518
+ First, the fact-evaluation function is tried, if it exists (for
519
+ example _eval_is_integer). Then we try related facts. For example
520
+
521
+ rational --> integer
522
+
523
+ another example is joined rule:
524
+
525
+ integer & !odd --> even
526
+
527
+ so in the latter case if we are looking at what 'even' value is,
528
+ 'integer' and 'odd' facts will be asked.
529
+
530
+ In all cases, when we settle on some fact value, its implications are
531
+ deduced, and the result is cached in ._assumptions.
532
+ """
533
+ # FactKB which is dict-like and maps facts to their known values:
534
+ assumptions = obj._assumptions
535
+
536
+ # A dict that maps facts to their handlers:
537
+ handler_map = obj._prop_handler
538
+
539
+ # This is our queue of facts to check:
540
+ facts_to_check = [fact]
541
+ facts_queued = {fact}
542
+
543
+ # Loop over the queue as it extends
544
+ for fact_i in facts_to_check:
545
+
546
+ # If fact_i has already been determined then we don't need to rerun the
547
+ # handler. There is a potential race condition for multithreaded code
548
+ # though because it's possible that fact_i was checked in another
549
+ # thread. The main logic of the loop below would potentially skip
550
+ # checking assumptions[fact] in this case so we check it once after the
551
+ # loop to be sure.
552
+ if fact_i in assumptions:
553
+ continue
554
+
555
+ # Now we call the associated handler for fact_i if it exists.
556
+ fact_i_value = None
557
+ handler_i = handler_map.get(fact_i)
558
+ if handler_i is not None:
559
+ fact_i_value = handler_i(obj)
560
+
561
+ # If we get a new value for fact_i then we should update our knowledge
562
+ # of fact_i as well as any related facts that can be inferred using the
563
+ # inference rules connecting the fact_i and any other fact values that
564
+ # are already known.
565
+ if fact_i_value is not None:
566
+ assumptions.deduce_all_facts(((fact_i, fact_i_value),))
567
+
568
+ # Usually if assumptions[fact] is now not None then that is because of
569
+ # the call to deduce_all_facts above. The handler for fact_i returned
570
+ # True or False and knowing fact_i (which is equal to fact in the first
571
+ # iteration) implies knowing a value for fact. It is also possible
572
+ # though that independent code e.g. called indirectly by the handler or
573
+ # called in another thread in a multithreaded context might have
574
+ # resulted in assumptions[fact] being set. Either way we return it.
575
+ fact_value = assumptions.get(fact)
576
+ if fact_value is not None:
577
+ return fact_value
578
+
579
+ # Extend the queue with other facts that might determine fact_i. Here
580
+ # we randomise the order of the facts that are checked. This should not
581
+ # lead to any non-determinism if all handlers are logically consistent
582
+ # with the inference rules for the facts. Non-deterministic assumptions
583
+ # queries can result from bugs in the handlers that are exposed by this
584
+ # call to shuffle. These are pushed to the back of the queue meaning
585
+ # that the inference graph is traversed in breadth-first order.
586
+ new_facts_to_check = list(_assume_rules.prereq[fact_i] - facts_queued)
587
+ shuffle(new_facts_to_check)
588
+ facts_to_check.extend(new_facts_to_check)
589
+ facts_queued.update(new_facts_to_check)
590
+
591
+ # The above loop should be able to handle everything fine in a
592
+ # single-threaded context but in multithreaded code it is possible that
593
+ # this thread skipped computing a particular fact that was computed in
594
+ # another thread (due to the continue). In that case it is possible that
595
+ # fact was inferred and is now stored in the assumptions dict but it wasn't
596
+ # checked for in the body of the loop. This is an obscure case but to make
597
+ # sure we catch it we check once here at the end of the loop.
598
+ if fact in assumptions:
599
+ return assumptions[fact]
600
+
601
+ # This query can not be answered. It's possible that e.g. another thread
602
+ # has already stored None for fact but assumptions._tell does not mind if
603
+ # we call _tell twice setting the same value. If this raises
604
+ # InconsistentAssumptions then it probably means that another thread
605
+ # attempted to compute this and got a value of True or False rather than
606
+ # None. In that case there must be a bug in at least one of the handlers.
607
+ # If the handlers are all deterministic and are consistent with the
608
+ # inference rules then the same value should be computed for fact in all
609
+ # threads.
610
+ assumptions._tell(fact, None)
611
+ return None
612
+
613
+
614
+ def _prepare_class_assumptions(cls):
615
+ """Precompute class level assumptions and generate handlers.
616
+
617
+ This is called by Basic.__init_subclass__ each time a Basic subclass is
618
+ defined.
619
+ """
620
+
621
+ local_defs = {}
622
+ for k in _assume_defined:
623
+ attrname = as_property(k)
624
+ v = cls.__dict__.get(attrname, '')
625
+ if isinstance(v, (bool, int, type(None))):
626
+ if v is not None:
627
+ v = bool(v)
628
+ local_defs[k] = v
629
+
630
+ defs = {}
631
+ for base in reversed(cls.__bases__):
632
+ assumptions = getattr(base, '_explicit_class_assumptions', None)
633
+ if assumptions is not None:
634
+ defs.update(assumptions)
635
+ defs.update(local_defs)
636
+
637
+ cls._explicit_class_assumptions = defs
638
+ cls.default_assumptions = StdFactKB(defs)
639
+
640
+ cls._prop_handler = {}
641
+ for k in _assume_defined:
642
+ eval_is_meth = getattr(cls, '_eval_is_%s' % k, None)
643
+ if eval_is_meth is not None:
644
+ cls._prop_handler[k] = eval_is_meth
645
+
646
+ # Put definite results directly into the class dict, for speed
647
+ for k, v in cls.default_assumptions.items():
648
+ setattr(cls, as_property(k), v)
649
+
650
+ # protection e.g. for Integer.is_even=F <- (Rational.is_integer=F)
651
+ derived_from_bases = set()
652
+ for base in cls.__bases__:
653
+ default_assumptions = getattr(base, 'default_assumptions', None)
654
+ # is an assumption-aware class
655
+ if default_assumptions is not None:
656
+ derived_from_bases.update(default_assumptions)
657
+
658
+ for fact in derived_from_bases - set(cls.default_assumptions):
659
+ pname = as_property(fact)
660
+ if pname not in cls.__dict__:
661
+ setattr(cls, pname, make_property(fact))
662
+
663
+ # Finally, add any missing automagic property (e.g. for Basic)
664
+ for fact in _assume_defined:
665
+ pname = as_property(fact)
666
+ if not hasattr(cls, pname):
667
+ setattr(cls, pname, make_property(fact))
668
+
669
+
670
+ # XXX: ManagedProperties used to be the metaclass for Basic but now Basic does
671
+ # not use a metaclass. We leave this here for backwards compatibility for now
672
+ # in case someone has been using the ManagedProperties class in downstream
673
+ # code. The reason that it might have been used is that when subclassing a
674
+ # class and wanting to use a metaclass the metaclass must be a subclass of the
675
+ # metaclass for the class that is being subclassed. Anyone wanting to subclass
676
+ # Basic and use a metaclass in their subclass would have needed to subclass
677
+ # ManagedProperties. Here ManagedProperties is not the metaclass for Basic any
678
+ # more but it should still be usable as a metaclass for Basic subclasses since
679
+ # it is a subclass of type which is now the metaclass for Basic.
680
+ class ManagedProperties(type):
681
+ def __init__(cls, *args, **kwargs):
682
+ msg = ("The ManagedProperties metaclass. "
683
+ "Basic does not use metaclasses any more")
684
+ sympy_deprecation_warning(msg,
685
+ deprecated_since_version="1.12",
686
+ active_deprecations_target='managedproperties')
687
+
688
+ # Here we still call this function in case someone is using
689
+ # ManagedProperties for something that is not a Basic subclass. For
690
+ # Basic subclasses this function is now called by __init_subclass__ and
691
+ # so this metaclass is not needed any more.
692
+ _prepare_class_assumptions(cls)
lib/python3.12/site-packages/sympy/core/assumptions_generated.py ADDED
@@ -0,0 +1,1615 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Do NOT manually edit this file.
3
+ Instead, run ./bin/ask_update.py.
4
+ """
5
+
6
+ defined_facts = [
7
+ 'algebraic',
8
+ 'antihermitian',
9
+ 'commutative',
10
+ 'complex',
11
+ 'composite',
12
+ 'even',
13
+ 'extended_negative',
14
+ 'extended_nonnegative',
15
+ 'extended_nonpositive',
16
+ 'extended_nonzero',
17
+ 'extended_positive',
18
+ 'extended_real',
19
+ 'finite',
20
+ 'hermitian',
21
+ 'imaginary',
22
+ 'infinite',
23
+ 'integer',
24
+ 'irrational',
25
+ 'negative',
26
+ 'noninteger',
27
+ 'nonnegative',
28
+ 'nonpositive',
29
+ 'nonzero',
30
+ 'odd',
31
+ 'positive',
32
+ 'prime',
33
+ 'rational',
34
+ 'real',
35
+ 'transcendental',
36
+ 'zero',
37
+ ] # defined_facts
38
+
39
+
40
+ full_implications = dict( [
41
+ # Implications of algebraic = True:
42
+ (('algebraic', True), set( (
43
+ ('commutative', True),
44
+ ('complex', True),
45
+ ('finite', True),
46
+ ('infinite', False),
47
+ ('transcendental', False),
48
+ ) ),
49
+ ),
50
+ # Implications of algebraic = False:
51
+ (('algebraic', False), set( (
52
+ ('composite', False),
53
+ ('even', False),
54
+ ('integer', False),
55
+ ('odd', False),
56
+ ('prime', False),
57
+ ('rational', False),
58
+ ('zero', False),
59
+ ) ),
60
+ ),
61
+ # Implications of antihermitian = True:
62
+ (('antihermitian', True), set( (
63
+ ) ),
64
+ ),
65
+ # Implications of antihermitian = False:
66
+ (('antihermitian', False), set( (
67
+ ('imaginary', False),
68
+ ) ),
69
+ ),
70
+ # Implications of commutative = True:
71
+ (('commutative', True), set( (
72
+ ) ),
73
+ ),
74
+ # Implications of commutative = False:
75
+ (('commutative', False), set( (
76
+ ('algebraic', False),
77
+ ('complex', False),
78
+ ('composite', False),
79
+ ('even', False),
80
+ ('extended_negative', False),
81
+ ('extended_nonnegative', False),
82
+ ('extended_nonpositive', False),
83
+ ('extended_nonzero', False),
84
+ ('extended_positive', False),
85
+ ('extended_real', False),
86
+ ('imaginary', False),
87
+ ('integer', False),
88
+ ('irrational', False),
89
+ ('negative', False),
90
+ ('noninteger', False),
91
+ ('nonnegative', False),
92
+ ('nonpositive', False),
93
+ ('nonzero', False),
94
+ ('odd', False),
95
+ ('positive', False),
96
+ ('prime', False),
97
+ ('rational', False),
98
+ ('real', False),
99
+ ('transcendental', False),
100
+ ('zero', False),
101
+ ) ),
102
+ ),
103
+ # Implications of complex = True:
104
+ (('complex', True), set( (
105
+ ('commutative', True),
106
+ ('finite', True),
107
+ ('infinite', False),
108
+ ) ),
109
+ ),
110
+ # Implications of complex = False:
111
+ (('complex', False), set( (
112
+ ('algebraic', False),
113
+ ('composite', False),
114
+ ('even', False),
115
+ ('imaginary', False),
116
+ ('integer', False),
117
+ ('irrational', False),
118
+ ('negative', False),
119
+ ('nonnegative', False),
120
+ ('nonpositive', False),
121
+ ('nonzero', False),
122
+ ('odd', False),
123
+ ('positive', False),
124
+ ('prime', False),
125
+ ('rational', False),
126
+ ('real', False),
127
+ ('transcendental', False),
128
+ ('zero', False),
129
+ ) ),
130
+ ),
131
+ # Implications of composite = True:
132
+ (('composite', True), set( (
133
+ ('algebraic', True),
134
+ ('commutative', True),
135
+ ('complex', True),
136
+ ('extended_negative', False),
137
+ ('extended_nonnegative', True),
138
+ ('extended_nonpositive', False),
139
+ ('extended_nonzero', True),
140
+ ('extended_positive', True),
141
+ ('extended_real', True),
142
+ ('finite', True),
143
+ ('hermitian', True),
144
+ ('imaginary', False),
145
+ ('infinite', False),
146
+ ('integer', True),
147
+ ('irrational', False),
148
+ ('negative', False),
149
+ ('noninteger', False),
150
+ ('nonnegative', True),
151
+ ('nonpositive', False),
152
+ ('nonzero', True),
153
+ ('positive', True),
154
+ ('prime', False),
155
+ ('rational', True),
156
+ ('real', True),
157
+ ('transcendental', False),
158
+ ('zero', False),
159
+ ) ),
160
+ ),
161
+ # Implications of composite = False:
162
+ (('composite', False), set( (
163
+ ) ),
164
+ ),
165
+ # Implications of even = True:
166
+ (('even', True), set( (
167
+ ('algebraic', True),
168
+ ('commutative', True),
169
+ ('complex', True),
170
+ ('extended_real', True),
171
+ ('finite', True),
172
+ ('hermitian', True),
173
+ ('imaginary', False),
174
+ ('infinite', False),
175
+ ('integer', True),
176
+ ('irrational', False),
177
+ ('noninteger', False),
178
+ ('odd', False),
179
+ ('rational', True),
180
+ ('real', True),
181
+ ('transcendental', False),
182
+ ) ),
183
+ ),
184
+ # Implications of even = False:
185
+ (('even', False), set( (
186
+ ('zero', False),
187
+ ) ),
188
+ ),
189
+ # Implications of extended_negative = True:
190
+ (('extended_negative', True), set( (
191
+ ('commutative', True),
192
+ ('composite', False),
193
+ ('extended_nonnegative', False),
194
+ ('extended_nonpositive', True),
195
+ ('extended_nonzero', True),
196
+ ('extended_positive', False),
197
+ ('extended_real', True),
198
+ ('imaginary', False),
199
+ ('nonnegative', False),
200
+ ('positive', False),
201
+ ('prime', False),
202
+ ('zero', False),
203
+ ) ),
204
+ ),
205
+ # Implications of extended_negative = False:
206
+ (('extended_negative', False), set( (
207
+ ('negative', False),
208
+ ) ),
209
+ ),
210
+ # Implications of extended_nonnegative = True:
211
+ (('extended_nonnegative', True), set( (
212
+ ('commutative', True),
213
+ ('extended_negative', False),
214
+ ('extended_real', True),
215
+ ('imaginary', False),
216
+ ('negative', False),
217
+ ) ),
218
+ ),
219
+ # Implications of extended_nonnegative = False:
220
+ (('extended_nonnegative', False), set( (
221
+ ('composite', False),
222
+ ('extended_positive', False),
223
+ ('nonnegative', False),
224
+ ('positive', False),
225
+ ('prime', False),
226
+ ('zero', False),
227
+ ) ),
228
+ ),
229
+ # Implications of extended_nonpositive = True:
230
+ (('extended_nonpositive', True), set( (
231
+ ('commutative', True),
232
+ ('composite', False),
233
+ ('extended_positive', False),
234
+ ('extended_real', True),
235
+ ('imaginary', False),
236
+ ('positive', False),
237
+ ('prime', False),
238
+ ) ),
239
+ ),
240
+ # Implications of extended_nonpositive = False:
241
+ (('extended_nonpositive', False), set( (
242
+ ('extended_negative', False),
243
+ ('negative', False),
244
+ ('nonpositive', False),
245
+ ('zero', False),
246
+ ) ),
247
+ ),
248
+ # Implications of extended_nonzero = True:
249
+ (('extended_nonzero', True), set( (
250
+ ('commutative', True),
251
+ ('extended_real', True),
252
+ ('imaginary', False),
253
+ ('zero', False),
254
+ ) ),
255
+ ),
256
+ # Implications of extended_nonzero = False:
257
+ (('extended_nonzero', False), set( (
258
+ ('composite', False),
259
+ ('extended_negative', False),
260
+ ('extended_positive', False),
261
+ ('negative', False),
262
+ ('nonzero', False),
263
+ ('positive', False),
264
+ ('prime', False),
265
+ ) ),
266
+ ),
267
+ # Implications of extended_positive = True:
268
+ (('extended_positive', True), set( (
269
+ ('commutative', True),
270
+ ('extended_negative', False),
271
+ ('extended_nonnegative', True),
272
+ ('extended_nonpositive', False),
273
+ ('extended_nonzero', True),
274
+ ('extended_real', True),
275
+ ('imaginary', False),
276
+ ('negative', False),
277
+ ('nonpositive', False),
278
+ ('zero', False),
279
+ ) ),
280
+ ),
281
+ # Implications of extended_positive = False:
282
+ (('extended_positive', False), set( (
283
+ ('composite', False),
284
+ ('positive', False),
285
+ ('prime', False),
286
+ ) ),
287
+ ),
288
+ # Implications of extended_real = True:
289
+ (('extended_real', True), set( (
290
+ ('commutative', True),
291
+ ('imaginary', False),
292
+ ) ),
293
+ ),
294
+ # Implications of extended_real = False:
295
+ (('extended_real', False), set( (
296
+ ('composite', False),
297
+ ('even', False),
298
+ ('extended_negative', False),
299
+ ('extended_nonnegative', False),
300
+ ('extended_nonpositive', False),
301
+ ('extended_nonzero', False),
302
+ ('extended_positive', False),
303
+ ('integer', False),
304
+ ('irrational', False),
305
+ ('negative', False),
306
+ ('noninteger', False),
307
+ ('nonnegative', False),
308
+ ('nonpositive', False),
309
+ ('nonzero', False),
310
+ ('odd', False),
311
+ ('positive', False),
312
+ ('prime', False),
313
+ ('rational', False),
314
+ ('real', False),
315
+ ('zero', False),
316
+ ) ),
317
+ ),
318
+ # Implications of finite = True:
319
+ (('finite', True), set( (
320
+ ('infinite', False),
321
+ ) ),
322
+ ),
323
+ # Implications of finite = False:
324
+ (('finite', False), set( (
325
+ ('algebraic', False),
326
+ ('complex', False),
327
+ ('composite', False),
328
+ ('even', False),
329
+ ('imaginary', False),
330
+ ('infinite', True),
331
+ ('integer', False),
332
+ ('irrational', False),
333
+ ('negative', False),
334
+ ('nonnegative', False),
335
+ ('nonpositive', False),
336
+ ('nonzero', False),
337
+ ('odd', False),
338
+ ('positive', False),
339
+ ('prime', False),
340
+ ('rational', False),
341
+ ('real', False),
342
+ ('transcendental', False),
343
+ ('zero', False),
344
+ ) ),
345
+ ),
346
+ # Implications of hermitian = True:
347
+ (('hermitian', True), set( (
348
+ ) ),
349
+ ),
350
+ # Implications of hermitian = False:
351
+ (('hermitian', False), set( (
352
+ ('composite', False),
353
+ ('even', False),
354
+ ('integer', False),
355
+ ('irrational', False),
356
+ ('negative', False),
357
+ ('nonnegative', False),
358
+ ('nonpositive', False),
359
+ ('nonzero', False),
360
+ ('odd', False),
361
+ ('positive', False),
362
+ ('prime', False),
363
+ ('rational', False),
364
+ ('real', False),
365
+ ('zero', False),
366
+ ) ),
367
+ ),
368
+ # Implications of imaginary = True:
369
+ (('imaginary', True), set( (
370
+ ('antihermitian', True),
371
+ ('commutative', True),
372
+ ('complex', True),
373
+ ('composite', False),
374
+ ('even', False),
375
+ ('extended_negative', False),
376
+ ('extended_nonnegative', False),
377
+ ('extended_nonpositive', False),
378
+ ('extended_nonzero', False),
379
+ ('extended_positive', False),
380
+ ('extended_real', False),
381
+ ('finite', True),
382
+ ('infinite', False),
383
+ ('integer', False),
384
+ ('irrational', False),
385
+ ('negative', False),
386
+ ('noninteger', False),
387
+ ('nonnegative', False),
388
+ ('nonpositive', False),
389
+ ('nonzero', False),
390
+ ('odd', False),
391
+ ('positive', False),
392
+ ('prime', False),
393
+ ('rational', False),
394
+ ('real', False),
395
+ ('zero', False),
396
+ ) ),
397
+ ),
398
+ # Implications of imaginary = False:
399
+ (('imaginary', False), set( (
400
+ ) ),
401
+ ),
402
+ # Implications of infinite = True:
403
+ (('infinite', True), set( (
404
+ ('algebraic', False),
405
+ ('complex', False),
406
+ ('composite', False),
407
+ ('even', False),
408
+ ('finite', False),
409
+ ('imaginary', False),
410
+ ('integer', False),
411
+ ('irrational', False),
412
+ ('negative', False),
413
+ ('nonnegative', False),
414
+ ('nonpositive', False),
415
+ ('nonzero', False),
416
+ ('odd', False),
417
+ ('positive', False),
418
+ ('prime', False),
419
+ ('rational', False),
420
+ ('real', False),
421
+ ('transcendental', False),
422
+ ('zero', False),
423
+ ) ),
424
+ ),
425
+ # Implications of infinite = False:
426
+ (('infinite', False), set( (
427
+ ('finite', True),
428
+ ) ),
429
+ ),
430
+ # Implications of integer = True:
431
+ (('integer', True), set( (
432
+ ('algebraic', True),
433
+ ('commutative', True),
434
+ ('complex', True),
435
+ ('extended_real', True),
436
+ ('finite', True),
437
+ ('hermitian', True),
438
+ ('imaginary', False),
439
+ ('infinite', False),
440
+ ('irrational', False),
441
+ ('noninteger', False),
442
+ ('rational', True),
443
+ ('real', True),
444
+ ('transcendental', False),
445
+ ) ),
446
+ ),
447
+ # Implications of integer = False:
448
+ (('integer', False), set( (
449
+ ('composite', False),
450
+ ('even', False),
451
+ ('odd', False),
452
+ ('prime', False),
453
+ ('zero', False),
454
+ ) ),
455
+ ),
456
+ # Implications of irrational = True:
457
+ (('irrational', True), set( (
458
+ ('commutative', True),
459
+ ('complex', True),
460
+ ('composite', False),
461
+ ('even', False),
462
+ ('extended_nonzero', True),
463
+ ('extended_real', True),
464
+ ('finite', True),
465
+ ('hermitian', True),
466
+ ('imaginary', False),
467
+ ('infinite', False),
468
+ ('integer', False),
469
+ ('noninteger', True),
470
+ ('nonzero', True),
471
+ ('odd', False),
472
+ ('prime', False),
473
+ ('rational', False),
474
+ ('real', True),
475
+ ('zero', False),
476
+ ) ),
477
+ ),
478
+ # Implications of irrational = False:
479
+ (('irrational', False), set( (
480
+ ) ),
481
+ ),
482
+ # Implications of negative = True:
483
+ (('negative', True), set( (
484
+ ('commutative', True),
485
+ ('complex', True),
486
+ ('composite', False),
487
+ ('extended_negative', True),
488
+ ('extended_nonnegative', False),
489
+ ('extended_nonpositive', True),
490
+ ('extended_nonzero', True),
491
+ ('extended_positive', False),
492
+ ('extended_real', True),
493
+ ('finite', True),
494
+ ('hermitian', True),
495
+ ('imaginary', False),
496
+ ('infinite', False),
497
+ ('nonnegative', False),
498
+ ('nonpositive', True),
499
+ ('nonzero', True),
500
+ ('positive', False),
501
+ ('prime', False),
502
+ ('real', True),
503
+ ('zero', False),
504
+ ) ),
505
+ ),
506
+ # Implications of negative = False:
507
+ (('negative', False), set( (
508
+ ) ),
509
+ ),
510
+ # Implications of noninteger = True:
511
+ (('noninteger', True), set( (
512
+ ('commutative', True),
513
+ ('composite', False),
514
+ ('even', False),
515
+ ('extended_nonzero', True),
516
+ ('extended_real', True),
517
+ ('imaginary', False),
518
+ ('integer', False),
519
+ ('odd', False),
520
+ ('prime', False),
521
+ ('zero', False),
522
+ ) ),
523
+ ),
524
+ # Implications of noninteger = False:
525
+ (('noninteger', False), set( (
526
+ ) ),
527
+ ),
528
+ # Implications of nonnegative = True:
529
+ (('nonnegative', True), set( (
530
+ ('commutative', True),
531
+ ('complex', True),
532
+ ('extended_negative', False),
533
+ ('extended_nonnegative', True),
534
+ ('extended_real', True),
535
+ ('finite', True),
536
+ ('hermitian', True),
537
+ ('imaginary', False),
538
+ ('infinite', False),
539
+ ('negative', False),
540
+ ('real', True),
541
+ ) ),
542
+ ),
543
+ # Implications of nonnegative = False:
544
+ (('nonnegative', False), set( (
545
+ ('composite', False),
546
+ ('positive', False),
547
+ ('prime', False),
548
+ ('zero', False),
549
+ ) ),
550
+ ),
551
+ # Implications of nonpositive = True:
552
+ (('nonpositive', True), set( (
553
+ ('commutative', True),
554
+ ('complex', True),
555
+ ('composite', False),
556
+ ('extended_nonpositive', True),
557
+ ('extended_positive', False),
558
+ ('extended_real', True),
559
+ ('finite', True),
560
+ ('hermitian', True),
561
+ ('imaginary', False),
562
+ ('infinite', False),
563
+ ('positive', False),
564
+ ('prime', False),
565
+ ('real', True),
566
+ ) ),
567
+ ),
568
+ # Implications of nonpositive = False:
569
+ (('nonpositive', False), set( (
570
+ ('negative', False),
571
+ ('zero', False),
572
+ ) ),
573
+ ),
574
+ # Implications of nonzero = True:
575
+ (('nonzero', True), set( (
576
+ ('commutative', True),
577
+ ('complex', True),
578
+ ('extended_nonzero', True),
579
+ ('extended_real', True),
580
+ ('finite', True),
581
+ ('hermitian', True),
582
+ ('imaginary', False),
583
+ ('infinite', False),
584
+ ('real', True),
585
+ ('zero', False),
586
+ ) ),
587
+ ),
588
+ # Implications of nonzero = False:
589
+ (('nonzero', False), set( (
590
+ ('composite', False),
591
+ ('negative', False),
592
+ ('positive', False),
593
+ ('prime', False),
594
+ ) ),
595
+ ),
596
+ # Implications of odd = True:
597
+ (('odd', True), set( (
598
+ ('algebraic', True),
599
+ ('commutative', True),
600
+ ('complex', True),
601
+ ('even', False),
602
+ ('extended_nonzero', True),
603
+ ('extended_real', True),
604
+ ('finite', True),
605
+ ('hermitian', True),
606
+ ('imaginary', False),
607
+ ('infinite', False),
608
+ ('integer', True),
609
+ ('irrational', False),
610
+ ('noninteger', False),
611
+ ('nonzero', True),
612
+ ('rational', True),
613
+ ('real', True),
614
+ ('transcendental', False),
615
+ ('zero', False),
616
+ ) ),
617
+ ),
618
+ # Implications of odd = False:
619
+ (('odd', False), set( (
620
+ ) ),
621
+ ),
622
+ # Implications of positive = True:
623
+ (('positive', True), set( (
624
+ ('commutative', True),
625
+ ('complex', True),
626
+ ('extended_negative', False),
627
+ ('extended_nonnegative', True),
628
+ ('extended_nonpositive', False),
629
+ ('extended_nonzero', True),
630
+ ('extended_positive', True),
631
+ ('extended_real', True),
632
+ ('finite', True),
633
+ ('hermitian', True),
634
+ ('imaginary', False),
635
+ ('infinite', False),
636
+ ('negative', False),
637
+ ('nonnegative', True),
638
+ ('nonpositive', False),
639
+ ('nonzero', True),
640
+ ('real', True),
641
+ ('zero', False),
642
+ ) ),
643
+ ),
644
+ # Implications of positive = False:
645
+ (('positive', False), set( (
646
+ ('composite', False),
647
+ ('prime', False),
648
+ ) ),
649
+ ),
650
+ # Implications of prime = True:
651
+ (('prime', True), set( (
652
+ ('algebraic', True),
653
+ ('commutative', True),
654
+ ('complex', True),
655
+ ('composite', False),
656
+ ('extended_negative', False),
657
+ ('extended_nonnegative', True),
658
+ ('extended_nonpositive', False),
659
+ ('extended_nonzero', True),
660
+ ('extended_positive', True),
661
+ ('extended_real', True),
662
+ ('finite', True),
663
+ ('hermitian', True),
664
+ ('imaginary', False),
665
+ ('infinite', False),
666
+ ('integer', True),
667
+ ('irrational', False),
668
+ ('negative', False),
669
+ ('noninteger', False),
670
+ ('nonnegative', True),
671
+ ('nonpositive', False),
672
+ ('nonzero', True),
673
+ ('positive', True),
674
+ ('rational', True),
675
+ ('real', True),
676
+ ('transcendental', False),
677
+ ('zero', False),
678
+ ) ),
679
+ ),
680
+ # Implications of prime = False:
681
+ (('prime', False), set( (
682
+ ) ),
683
+ ),
684
+ # Implications of rational = True:
685
+ (('rational', True), set( (
686
+ ('algebraic', True),
687
+ ('commutative', True),
688
+ ('complex', True),
689
+ ('extended_real', True),
690
+ ('finite', True),
691
+ ('hermitian', True),
692
+ ('imaginary', False),
693
+ ('infinite', False),
694
+ ('irrational', False),
695
+ ('real', True),
696
+ ('transcendental', False),
697
+ ) ),
698
+ ),
699
+ # Implications of rational = False:
700
+ (('rational', False), set( (
701
+ ('composite', False),
702
+ ('even', False),
703
+ ('integer', False),
704
+ ('odd', False),
705
+ ('prime', False),
706
+ ('zero', False),
707
+ ) ),
708
+ ),
709
+ # Implications of real = True:
710
+ (('real', True), set( (
711
+ ('commutative', True),
712
+ ('complex', True),
713
+ ('extended_real', True),
714
+ ('finite', True),
715
+ ('hermitian', True),
716
+ ('imaginary', False),
717
+ ('infinite', False),
718
+ ) ),
719
+ ),
720
+ # Implications of real = False:
721
+ (('real', False), set( (
722
+ ('composite', False),
723
+ ('even', False),
724
+ ('integer', False),
725
+ ('irrational', False),
726
+ ('negative', False),
727
+ ('nonnegative', False),
728
+ ('nonpositive', False),
729
+ ('nonzero', False),
730
+ ('odd', False),
731
+ ('positive', False),
732
+ ('prime', False),
733
+ ('rational', False),
734
+ ('zero', False),
735
+ ) ),
736
+ ),
737
+ # Implications of transcendental = True:
738
+ (('transcendental', True), set( (
739
+ ('algebraic', False),
740
+ ('commutative', True),
741
+ ('complex', True),
742
+ ('composite', False),
743
+ ('even', False),
744
+ ('finite', True),
745
+ ('infinite', False),
746
+ ('integer', False),
747
+ ('odd', False),
748
+ ('prime', False),
749
+ ('rational', False),
750
+ ('zero', False),
751
+ ) ),
752
+ ),
753
+ # Implications of transcendental = False:
754
+ (('transcendental', False), set( (
755
+ ) ),
756
+ ),
757
+ # Implications of zero = True:
758
+ (('zero', True), set( (
759
+ ('algebraic', True),
760
+ ('commutative', True),
761
+ ('complex', True),
762
+ ('composite', False),
763
+ ('even', True),
764
+ ('extended_negative', False),
765
+ ('extended_nonnegative', True),
766
+ ('extended_nonpositive', True),
767
+ ('extended_nonzero', False),
768
+ ('extended_positive', False),
769
+ ('extended_real', True),
770
+ ('finite', True),
771
+ ('hermitian', True),
772
+ ('imaginary', False),
773
+ ('infinite', False),
774
+ ('integer', True),
775
+ ('irrational', False),
776
+ ('negative', False),
777
+ ('noninteger', False),
778
+ ('nonnegative', True),
779
+ ('nonpositive', True),
780
+ ('nonzero', False),
781
+ ('odd', False),
782
+ ('positive', False),
783
+ ('prime', False),
784
+ ('rational', True),
785
+ ('real', True),
786
+ ('transcendental', False),
787
+ ) ),
788
+ ),
789
+ # Implications of zero = False:
790
+ (('zero', False), set( (
791
+ ) ),
792
+ ),
793
+ ] ) # full_implications
794
+
795
+
796
+ prereq = {
797
+
798
+ # facts that could determine the value of algebraic
799
+ 'algebraic': {
800
+ 'commutative',
801
+ 'complex',
802
+ 'composite',
803
+ 'even',
804
+ 'finite',
805
+ 'infinite',
806
+ 'integer',
807
+ 'odd',
808
+ 'prime',
809
+ 'rational',
810
+ 'transcendental',
811
+ 'zero',
812
+ },
813
+
814
+ # facts that could determine the value of antihermitian
815
+ 'antihermitian': {
816
+ 'imaginary',
817
+ },
818
+
819
+ # facts that could determine the value of commutative
820
+ 'commutative': {
821
+ 'algebraic',
822
+ 'complex',
823
+ 'composite',
824
+ 'even',
825
+ 'extended_negative',
826
+ 'extended_nonnegative',
827
+ 'extended_nonpositive',
828
+ 'extended_nonzero',
829
+ 'extended_positive',
830
+ 'extended_real',
831
+ 'imaginary',
832
+ 'integer',
833
+ 'irrational',
834
+ 'negative',
835
+ 'noninteger',
836
+ 'nonnegative',
837
+ 'nonpositive',
838
+ 'nonzero',
839
+ 'odd',
840
+ 'positive',
841
+ 'prime',
842
+ 'rational',
843
+ 'real',
844
+ 'transcendental',
845
+ 'zero',
846
+ },
847
+
848
+ # facts that could determine the value of complex
849
+ 'complex': {
850
+ 'algebraic',
851
+ 'commutative',
852
+ 'composite',
853
+ 'even',
854
+ 'finite',
855
+ 'imaginary',
856
+ 'infinite',
857
+ 'integer',
858
+ 'irrational',
859
+ 'negative',
860
+ 'nonnegative',
861
+ 'nonpositive',
862
+ 'nonzero',
863
+ 'odd',
864
+ 'positive',
865
+ 'prime',
866
+ 'rational',
867
+ 'real',
868
+ 'transcendental',
869
+ 'zero',
870
+ },
871
+
872
+ # facts that could determine the value of composite
873
+ 'composite': {
874
+ 'algebraic',
875
+ 'commutative',
876
+ 'complex',
877
+ 'extended_negative',
878
+ 'extended_nonnegative',
879
+ 'extended_nonpositive',
880
+ 'extended_nonzero',
881
+ 'extended_positive',
882
+ 'extended_real',
883
+ 'finite',
884
+ 'hermitian',
885
+ 'imaginary',
886
+ 'infinite',
887
+ 'integer',
888
+ 'irrational',
889
+ 'negative',
890
+ 'noninteger',
891
+ 'nonnegative',
892
+ 'nonpositive',
893
+ 'nonzero',
894
+ 'positive',
895
+ 'prime',
896
+ 'rational',
897
+ 'real',
898
+ 'transcendental',
899
+ 'zero',
900
+ },
901
+
902
+ # facts that could determine the value of even
903
+ 'even': {
904
+ 'algebraic',
905
+ 'commutative',
906
+ 'complex',
907
+ 'extended_real',
908
+ 'finite',
909
+ 'hermitian',
910
+ 'imaginary',
911
+ 'infinite',
912
+ 'integer',
913
+ 'irrational',
914
+ 'noninteger',
915
+ 'odd',
916
+ 'rational',
917
+ 'real',
918
+ 'transcendental',
919
+ 'zero',
920
+ },
921
+
922
+ # facts that could determine the value of extended_negative
923
+ 'extended_negative': {
924
+ 'commutative',
925
+ 'composite',
926
+ 'extended_nonnegative',
927
+ 'extended_nonpositive',
928
+ 'extended_nonzero',
929
+ 'extended_positive',
930
+ 'extended_real',
931
+ 'imaginary',
932
+ 'negative',
933
+ 'nonnegative',
934
+ 'positive',
935
+ 'prime',
936
+ 'zero',
937
+ },
938
+
939
+ # facts that could determine the value of extended_nonnegative
940
+ 'extended_nonnegative': {
941
+ 'commutative',
942
+ 'composite',
943
+ 'extended_negative',
944
+ 'extended_positive',
945
+ 'extended_real',
946
+ 'imaginary',
947
+ 'negative',
948
+ 'nonnegative',
949
+ 'positive',
950
+ 'prime',
951
+ 'zero',
952
+ },
953
+
954
+ # facts that could determine the value of extended_nonpositive
955
+ 'extended_nonpositive': {
956
+ 'commutative',
957
+ 'composite',
958
+ 'extended_negative',
959
+ 'extended_positive',
960
+ 'extended_real',
961
+ 'imaginary',
962
+ 'negative',
963
+ 'nonpositive',
964
+ 'positive',
965
+ 'prime',
966
+ 'zero',
967
+ },
968
+
969
+ # facts that could determine the value of extended_nonzero
970
+ 'extended_nonzero': {
971
+ 'commutative',
972
+ 'composite',
973
+ 'extended_negative',
974
+ 'extended_positive',
975
+ 'extended_real',
976
+ 'imaginary',
977
+ 'irrational',
978
+ 'negative',
979
+ 'noninteger',
980
+ 'nonzero',
981
+ 'odd',
982
+ 'positive',
983
+ 'prime',
984
+ 'zero',
985
+ },
986
+
987
+ # facts that could determine the value of extended_positive
988
+ 'extended_positive': {
989
+ 'commutative',
990
+ 'composite',
991
+ 'extended_negative',
992
+ 'extended_nonnegative',
993
+ 'extended_nonpositive',
994
+ 'extended_nonzero',
995
+ 'extended_real',
996
+ 'imaginary',
997
+ 'negative',
998
+ 'nonpositive',
999
+ 'positive',
1000
+ 'prime',
1001
+ 'zero',
1002
+ },
1003
+
1004
+ # facts that could determine the value of extended_real
1005
+ 'extended_real': {
1006
+ 'commutative',
1007
+ 'composite',
1008
+ 'even',
1009
+ 'extended_negative',
1010
+ 'extended_nonnegative',
1011
+ 'extended_nonpositive',
1012
+ 'extended_nonzero',
1013
+ 'extended_positive',
1014
+ 'imaginary',
1015
+ 'integer',
1016
+ 'irrational',
1017
+ 'negative',
1018
+ 'noninteger',
1019
+ 'nonnegative',
1020
+ 'nonpositive',
1021
+ 'nonzero',
1022
+ 'odd',
1023
+ 'positive',
1024
+ 'prime',
1025
+ 'rational',
1026
+ 'real',
1027
+ 'zero',
1028
+ },
1029
+
1030
+ # facts that could determine the value of finite
1031
+ 'finite': {
1032
+ 'algebraic',
1033
+ 'complex',
1034
+ 'composite',
1035
+ 'even',
1036
+ 'imaginary',
1037
+ 'infinite',
1038
+ 'integer',
1039
+ 'irrational',
1040
+ 'negative',
1041
+ 'nonnegative',
1042
+ 'nonpositive',
1043
+ 'nonzero',
1044
+ 'odd',
1045
+ 'positive',
1046
+ 'prime',
1047
+ 'rational',
1048
+ 'real',
1049
+ 'transcendental',
1050
+ 'zero',
1051
+ },
1052
+
1053
+ # facts that could determine the value of hermitian
1054
+ 'hermitian': {
1055
+ 'composite',
1056
+ 'even',
1057
+ 'integer',
1058
+ 'irrational',
1059
+ 'negative',
1060
+ 'nonnegative',
1061
+ 'nonpositive',
1062
+ 'nonzero',
1063
+ 'odd',
1064
+ 'positive',
1065
+ 'prime',
1066
+ 'rational',
1067
+ 'real',
1068
+ 'zero',
1069
+ },
1070
+
1071
+ # facts that could determine the value of imaginary
1072
+ 'imaginary': {
1073
+ 'antihermitian',
1074
+ 'commutative',
1075
+ 'complex',
1076
+ 'composite',
1077
+ 'even',
1078
+ 'extended_negative',
1079
+ 'extended_nonnegative',
1080
+ 'extended_nonpositive',
1081
+ 'extended_nonzero',
1082
+ 'extended_positive',
1083
+ 'extended_real',
1084
+ 'finite',
1085
+ 'infinite',
1086
+ 'integer',
1087
+ 'irrational',
1088
+ 'negative',
1089
+ 'noninteger',
1090
+ 'nonnegative',
1091
+ 'nonpositive',
1092
+ 'nonzero',
1093
+ 'odd',
1094
+ 'positive',
1095
+ 'prime',
1096
+ 'rational',
1097
+ 'real',
1098
+ 'zero',
1099
+ },
1100
+
1101
+ # facts that could determine the value of infinite
1102
+ 'infinite': {
1103
+ 'algebraic',
1104
+ 'complex',
1105
+ 'composite',
1106
+ 'even',
1107
+ 'finite',
1108
+ 'imaginary',
1109
+ 'integer',
1110
+ 'irrational',
1111
+ 'negative',
1112
+ 'nonnegative',
1113
+ 'nonpositive',
1114
+ 'nonzero',
1115
+ 'odd',
1116
+ 'positive',
1117
+ 'prime',
1118
+ 'rational',
1119
+ 'real',
1120
+ 'transcendental',
1121
+ 'zero',
1122
+ },
1123
+
1124
+ # facts that could determine the value of integer
1125
+ 'integer': {
1126
+ 'algebraic',
1127
+ 'commutative',
1128
+ 'complex',
1129
+ 'composite',
1130
+ 'even',
1131
+ 'extended_real',
1132
+ 'finite',
1133
+ 'hermitian',
1134
+ 'imaginary',
1135
+ 'infinite',
1136
+ 'irrational',
1137
+ 'noninteger',
1138
+ 'odd',
1139
+ 'prime',
1140
+ 'rational',
1141
+ 'real',
1142
+ 'transcendental',
1143
+ 'zero',
1144
+ },
1145
+
1146
+ # facts that could determine the value of irrational
1147
+ 'irrational': {
1148
+ 'commutative',
1149
+ 'complex',
1150
+ 'composite',
1151
+ 'even',
1152
+ 'extended_real',
1153
+ 'finite',
1154
+ 'hermitian',
1155
+ 'imaginary',
1156
+ 'infinite',
1157
+ 'integer',
1158
+ 'odd',
1159
+ 'prime',
1160
+ 'rational',
1161
+ 'real',
1162
+ 'zero',
1163
+ },
1164
+
1165
+ # facts that could determine the value of negative
1166
+ 'negative': {
1167
+ 'commutative',
1168
+ 'complex',
1169
+ 'composite',
1170
+ 'extended_negative',
1171
+ 'extended_nonnegative',
1172
+ 'extended_nonpositive',
1173
+ 'extended_nonzero',
1174
+ 'extended_positive',
1175
+ 'extended_real',
1176
+ 'finite',
1177
+ 'hermitian',
1178
+ 'imaginary',
1179
+ 'infinite',
1180
+ 'nonnegative',
1181
+ 'nonpositive',
1182
+ 'nonzero',
1183
+ 'positive',
1184
+ 'prime',
1185
+ 'real',
1186
+ 'zero',
1187
+ },
1188
+
1189
+ # facts that could determine the value of noninteger
1190
+ 'noninteger': {
1191
+ 'commutative',
1192
+ 'composite',
1193
+ 'even',
1194
+ 'extended_real',
1195
+ 'imaginary',
1196
+ 'integer',
1197
+ 'irrational',
1198
+ 'odd',
1199
+ 'prime',
1200
+ 'zero',
1201
+ },
1202
+
1203
+ # facts that could determine the value of nonnegative
1204
+ 'nonnegative': {
1205
+ 'commutative',
1206
+ 'complex',
1207
+ 'composite',
1208
+ 'extended_negative',
1209
+ 'extended_nonnegative',
1210
+ 'extended_real',
1211
+ 'finite',
1212
+ 'hermitian',
1213
+ 'imaginary',
1214
+ 'infinite',
1215
+ 'negative',
1216
+ 'positive',
1217
+ 'prime',
1218
+ 'real',
1219
+ 'zero',
1220
+ },
1221
+
1222
+ # facts that could determine the value of nonpositive
1223
+ 'nonpositive': {
1224
+ 'commutative',
1225
+ 'complex',
1226
+ 'composite',
1227
+ 'extended_nonpositive',
1228
+ 'extended_positive',
1229
+ 'extended_real',
1230
+ 'finite',
1231
+ 'hermitian',
1232
+ 'imaginary',
1233
+ 'infinite',
1234
+ 'negative',
1235
+ 'positive',
1236
+ 'prime',
1237
+ 'real',
1238
+ 'zero',
1239
+ },
1240
+
1241
+ # facts that could determine the value of nonzero
1242
+ 'nonzero': {
1243
+ 'commutative',
1244
+ 'complex',
1245
+ 'composite',
1246
+ 'extended_nonzero',
1247
+ 'extended_real',
1248
+ 'finite',
1249
+ 'hermitian',
1250
+ 'imaginary',
1251
+ 'infinite',
1252
+ 'irrational',
1253
+ 'negative',
1254
+ 'odd',
1255
+ 'positive',
1256
+ 'prime',
1257
+ 'real',
1258
+ 'zero',
1259
+ },
1260
+
1261
+ # facts that could determine the value of odd
1262
+ 'odd': {
1263
+ 'algebraic',
1264
+ 'commutative',
1265
+ 'complex',
1266
+ 'even',
1267
+ 'extended_real',
1268
+ 'finite',
1269
+ 'hermitian',
1270
+ 'imaginary',
1271
+ 'infinite',
1272
+ 'integer',
1273
+ 'irrational',
1274
+ 'noninteger',
1275
+ 'rational',
1276
+ 'real',
1277
+ 'transcendental',
1278
+ 'zero',
1279
+ },
1280
+
1281
+ # facts that could determine the value of positive
1282
+ 'positive': {
1283
+ 'commutative',
1284
+ 'complex',
1285
+ 'composite',
1286
+ 'extended_negative',
1287
+ 'extended_nonnegative',
1288
+ 'extended_nonpositive',
1289
+ 'extended_nonzero',
1290
+ 'extended_positive',
1291
+ 'extended_real',
1292
+ 'finite',
1293
+ 'hermitian',
1294
+ 'imaginary',
1295
+ 'infinite',
1296
+ 'negative',
1297
+ 'nonnegative',
1298
+ 'nonpositive',
1299
+ 'nonzero',
1300
+ 'prime',
1301
+ 'real',
1302
+ 'zero',
1303
+ },
1304
+
1305
+ # facts that could determine the value of prime
1306
+ 'prime': {
1307
+ 'algebraic',
1308
+ 'commutative',
1309
+ 'complex',
1310
+ 'composite',
1311
+ 'extended_negative',
1312
+ 'extended_nonnegative',
1313
+ 'extended_nonpositive',
1314
+ 'extended_nonzero',
1315
+ 'extended_positive',
1316
+ 'extended_real',
1317
+ 'finite',
1318
+ 'hermitian',
1319
+ 'imaginary',
1320
+ 'infinite',
1321
+ 'integer',
1322
+ 'irrational',
1323
+ 'negative',
1324
+ 'noninteger',
1325
+ 'nonnegative',
1326
+ 'nonpositive',
1327
+ 'nonzero',
1328
+ 'positive',
1329
+ 'rational',
1330
+ 'real',
1331
+ 'transcendental',
1332
+ 'zero',
1333
+ },
1334
+
1335
+ # facts that could determine the value of rational
1336
+ 'rational': {
1337
+ 'algebraic',
1338
+ 'commutative',
1339
+ 'complex',
1340
+ 'composite',
1341
+ 'even',
1342
+ 'extended_real',
1343
+ 'finite',
1344
+ 'hermitian',
1345
+ 'imaginary',
1346
+ 'infinite',
1347
+ 'integer',
1348
+ 'irrational',
1349
+ 'odd',
1350
+ 'prime',
1351
+ 'real',
1352
+ 'transcendental',
1353
+ 'zero',
1354
+ },
1355
+
1356
+ # facts that could determine the value of real
1357
+ 'real': {
1358
+ 'commutative',
1359
+ 'complex',
1360
+ 'composite',
1361
+ 'even',
1362
+ 'extended_real',
1363
+ 'finite',
1364
+ 'hermitian',
1365
+ 'imaginary',
1366
+ 'infinite',
1367
+ 'integer',
1368
+ 'irrational',
1369
+ 'negative',
1370
+ 'nonnegative',
1371
+ 'nonpositive',
1372
+ 'nonzero',
1373
+ 'odd',
1374
+ 'positive',
1375
+ 'prime',
1376
+ 'rational',
1377
+ 'zero',
1378
+ },
1379
+
1380
+ # facts that could determine the value of transcendental
1381
+ 'transcendental': {
1382
+ 'algebraic',
1383
+ 'commutative',
1384
+ 'complex',
1385
+ 'composite',
1386
+ 'even',
1387
+ 'finite',
1388
+ 'infinite',
1389
+ 'integer',
1390
+ 'odd',
1391
+ 'prime',
1392
+ 'rational',
1393
+ 'zero',
1394
+ },
1395
+
1396
+ # facts that could determine the value of zero
1397
+ 'zero': {
1398
+ 'algebraic',
1399
+ 'commutative',
1400
+ 'complex',
1401
+ 'composite',
1402
+ 'even',
1403
+ 'extended_negative',
1404
+ 'extended_nonnegative',
1405
+ 'extended_nonpositive',
1406
+ 'extended_nonzero',
1407
+ 'extended_positive',
1408
+ 'extended_real',
1409
+ 'finite',
1410
+ 'hermitian',
1411
+ 'imaginary',
1412
+ 'infinite',
1413
+ 'integer',
1414
+ 'irrational',
1415
+ 'negative',
1416
+ 'noninteger',
1417
+ 'nonnegative',
1418
+ 'nonpositive',
1419
+ 'nonzero',
1420
+ 'odd',
1421
+ 'positive',
1422
+ 'prime',
1423
+ 'rational',
1424
+ 'real',
1425
+ 'transcendental',
1426
+ },
1427
+
1428
+ } # prereq
1429
+
1430
+
1431
+ # Note: the order of the beta rules is used in the beta_triggers
1432
+ beta_rules = [
1433
+
1434
+ # Rules implying composite = True
1435
+ ({('even', True), ('positive', True), ('prime', False)},
1436
+ ('composite', True)),
1437
+
1438
+ # Rules implying even = False
1439
+ ({('composite', False), ('positive', True), ('prime', False)},
1440
+ ('even', False)),
1441
+
1442
+ # Rules implying even = True
1443
+ ({('integer', True), ('odd', False)},
1444
+ ('even', True)),
1445
+
1446
+ # Rules implying extended_negative = True
1447
+ ({('extended_positive', False), ('extended_real', True), ('zero', False)},
1448
+ ('extended_negative', True)),
1449
+ ({('extended_nonpositive', True), ('extended_nonzero', True)},
1450
+ ('extended_negative', True)),
1451
+
1452
+ # Rules implying extended_nonnegative = True
1453
+ ({('extended_negative', False), ('extended_real', True)},
1454
+ ('extended_nonnegative', True)),
1455
+
1456
+ # Rules implying extended_nonpositive = True
1457
+ ({('extended_positive', False), ('extended_real', True)},
1458
+ ('extended_nonpositive', True)),
1459
+
1460
+ # Rules implying extended_nonzero = True
1461
+ ({('extended_real', True), ('zero', False)},
1462
+ ('extended_nonzero', True)),
1463
+
1464
+ # Rules implying extended_positive = True
1465
+ ({('extended_negative', False), ('extended_real', True), ('zero', False)},
1466
+ ('extended_positive', True)),
1467
+ ({('extended_nonnegative', True), ('extended_nonzero', True)},
1468
+ ('extended_positive', True)),
1469
+
1470
+ # Rules implying extended_real = False
1471
+ ({('infinite', False), ('real', False)},
1472
+ ('extended_real', False)),
1473
+ ({('extended_negative', False), ('extended_positive', False), ('zero', False)},
1474
+ ('extended_real', False)),
1475
+
1476
+ # Rules implying infinite = True
1477
+ ({('extended_real', True), ('real', False)},
1478
+ ('infinite', True)),
1479
+
1480
+ # Rules implying irrational = True
1481
+ ({('rational', False), ('real', True)},
1482
+ ('irrational', True)),
1483
+
1484
+ # Rules implying negative = True
1485
+ ({('positive', False), ('real', True), ('zero', False)},
1486
+ ('negative', True)),
1487
+ ({('nonpositive', True), ('nonzero', True)},
1488
+ ('negative', True)),
1489
+ ({('extended_negative', True), ('finite', True)},
1490
+ ('negative', True)),
1491
+
1492
+ # Rules implying noninteger = True
1493
+ ({('extended_real', True), ('integer', False)},
1494
+ ('noninteger', True)),
1495
+
1496
+ # Rules implying nonnegative = True
1497
+ ({('negative', False), ('real', True)},
1498
+ ('nonnegative', True)),
1499
+ ({('extended_nonnegative', True), ('finite', True)},
1500
+ ('nonnegative', True)),
1501
+
1502
+ # Rules implying nonpositive = True
1503
+ ({('positive', False), ('real', True)},
1504
+ ('nonpositive', True)),
1505
+ ({('extended_nonpositive', True), ('finite', True)},
1506
+ ('nonpositive', True)),
1507
+
1508
+ # Rules implying nonzero = True
1509
+ ({('extended_nonzero', True), ('finite', True)},
1510
+ ('nonzero', True)),
1511
+
1512
+ # Rules implying odd = True
1513
+ ({('even', False), ('integer', True)},
1514
+ ('odd', True)),
1515
+
1516
+ # Rules implying positive = False
1517
+ ({('composite', False), ('even', True), ('prime', False)},
1518
+ ('positive', False)),
1519
+
1520
+ # Rules implying positive = True
1521
+ ({('negative', False), ('real', True), ('zero', False)},
1522
+ ('positive', True)),
1523
+ ({('nonnegative', True), ('nonzero', True)},
1524
+ ('positive', True)),
1525
+ ({('extended_positive', True), ('finite', True)},
1526
+ ('positive', True)),
1527
+
1528
+ # Rules implying prime = True
1529
+ ({('composite', False), ('even', True), ('positive', True)},
1530
+ ('prime', True)),
1531
+
1532
+ # Rules implying real = False
1533
+ ({('negative', False), ('positive', False), ('zero', False)},
1534
+ ('real', False)),
1535
+
1536
+ # Rules implying real = True
1537
+ ({('extended_real', True), ('infinite', False)},
1538
+ ('real', True)),
1539
+ ({('extended_real', True), ('finite', True)},
1540
+ ('real', True)),
1541
+
1542
+ # Rules implying transcendental = True
1543
+ ({('algebraic', False), ('complex', True)},
1544
+ ('transcendental', True)),
1545
+
1546
+ # Rules implying zero = True
1547
+ ({('extended_negative', False), ('extended_positive', False), ('extended_real', True)},
1548
+ ('zero', True)),
1549
+ ({('negative', False), ('positive', False), ('real', True)},
1550
+ ('zero', True)),
1551
+ ({('extended_nonnegative', True), ('extended_nonpositive', True)},
1552
+ ('zero', True)),
1553
+ ({('nonnegative', True), ('nonpositive', True)},
1554
+ ('zero', True)),
1555
+
1556
+ ] # beta_rules
1557
+ beta_triggers = {
1558
+ ('algebraic', False): [32, 11, 3, 8, 29, 14, 25, 13, 17, 7],
1559
+ ('algebraic', True): [10, 30, 31, 27, 16, 21, 19, 22],
1560
+ ('antihermitian', False): [],
1561
+ ('commutative', False): [],
1562
+ ('complex', False): [10, 12, 11, 3, 8, 17, 7],
1563
+ ('complex', True): [32, 10, 30, 31, 27, 16, 21, 19, 22],
1564
+ ('composite', False): [1, 28, 24],
1565
+ ('composite', True): [23, 2],
1566
+ ('even', False): [23, 11, 3, 8, 29, 14, 25, 7],
1567
+ ('even', True): [3, 33, 8, 6, 5, 14, 34, 25, 20, 18, 27, 16, 21, 19, 22, 0, 28, 24, 7],
1568
+ ('extended_negative', False): [11, 33, 8, 5, 29, 34, 25, 18],
1569
+ ('extended_negative', True): [30, 12, 31, 29, 14, 20, 16, 21, 22, 17],
1570
+ ('extended_nonnegative', False): [11, 3, 6, 29, 14, 20, 7],
1571
+ ('extended_nonnegative', True): [30, 12, 31, 33, 8, 9, 6, 29, 34, 25, 18, 19, 35, 17, 7],
1572
+ ('extended_nonpositive', False): [11, 8, 5, 29, 25, 18, 7],
1573
+ ('extended_nonpositive', True): [30, 12, 31, 3, 33, 4, 5, 29, 14, 34, 20, 21, 35, 17, 7],
1574
+ ('extended_nonzero', False): [11, 33, 6, 5, 29, 34, 20, 18],
1575
+ ('extended_nonzero', True): [30, 12, 31, 3, 8, 4, 9, 6, 5, 29, 14, 25, 22, 17],
1576
+ ('extended_positive', False): [11, 3, 33, 6, 29, 14, 34, 20],
1577
+ ('extended_positive', True): [30, 12, 31, 29, 25, 18, 27, 19, 22, 17],
1578
+ ('extended_real', False): [],
1579
+ ('extended_real', True): [30, 12, 31, 3, 33, 8, 6, 5, 17, 7],
1580
+ ('finite', False): [11, 3, 8, 17, 7],
1581
+ ('finite', True): [10, 30, 31, 27, 16, 21, 19, 22],
1582
+ ('hermitian', False): [10, 12, 11, 3, 8, 17, 7],
1583
+ ('imaginary', True): [32],
1584
+ ('infinite', False): [10, 30, 31, 27, 16, 21, 19, 22],
1585
+ ('infinite', True): [11, 3, 8, 17, 7],
1586
+ ('integer', False): [11, 3, 8, 29, 14, 25, 17, 7],
1587
+ ('integer', True): [23, 2, 3, 33, 8, 6, 5, 14, 34, 25, 20, 18, 27, 16, 21, 19, 22, 7],
1588
+ ('irrational', True): [32, 3, 8, 4, 9, 6, 5, 14, 25, 15, 26, 20, 18, 27, 16, 21, 19],
1589
+ ('negative', False): [29, 34, 25, 18],
1590
+ ('negative', True): [32, 13, 17],
1591
+ ('noninteger', True): [30, 12, 31, 3, 8, 4, 9, 6, 5, 29, 14, 25, 22],
1592
+ ('nonnegative', False): [11, 3, 8, 29, 14, 20, 7],
1593
+ ('nonnegative', True): [32, 33, 8, 9, 6, 34, 25, 26, 20, 27, 21, 22, 35, 36, 13, 17, 7],
1594
+ ('nonpositive', False): [11, 3, 8, 29, 25, 18, 7],
1595
+ ('nonpositive', True): [32, 3, 33, 4, 5, 14, 34, 15, 18, 16, 19, 22, 35, 36, 13, 17, 7],
1596
+ ('nonzero', False): [29, 34, 20, 18],
1597
+ ('nonzero', True): [32, 3, 8, 4, 9, 6, 5, 14, 25, 15, 26, 20, 18, 27, 16, 21, 19, 13, 17],
1598
+ ('odd', False): [2],
1599
+ ('odd', True): [3, 8, 4, 9, 6, 5, 14, 25, 15, 26, 20, 18, 27, 16, 21, 19],
1600
+ ('positive', False): [29, 14, 34, 20],
1601
+ ('positive', True): [32, 0, 1, 28, 13, 17],
1602
+ ('prime', False): [0, 1, 24],
1603
+ ('prime', True): [23, 2],
1604
+ ('rational', False): [11, 3, 8, 29, 14, 25, 13, 17, 7],
1605
+ ('rational', True): [3, 33, 8, 6, 5, 14, 34, 25, 20, 18, 27, 16, 21, 19, 22, 17, 7],
1606
+ ('real', False): [10, 12, 11, 3, 8, 17, 7],
1607
+ ('real', True): [32, 3, 33, 8, 6, 5, 14, 34, 25, 20, 18, 27, 16, 21, 19, 22, 13, 17, 7],
1608
+ ('transcendental', True): [10, 30, 31, 11, 3, 8, 29, 14, 25, 27, 16, 21, 19, 22, 13, 17, 7],
1609
+ ('zero', False): [11, 3, 8, 29, 14, 25, 7],
1610
+ ('zero', True): [],
1611
+ } # beta_triggers
1612
+
1613
+
1614
+ generated_assumptions = {'defined_facts': defined_facts, 'full_implications': full_implications,
1615
+ 'prereq': prereq, 'beta_rules': beta_rules, 'beta_triggers': beta_triggers}
lib/python3.12/site-packages/sympy/core/backend.py ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ USE_SYMENGINE = os.getenv('USE_SYMENGINE', '0')
3
+ USE_SYMENGINE = USE_SYMENGINE.lower() in ('1', 't', 'true') # type: ignore
4
+
5
+ if USE_SYMENGINE:
6
+ from symengine import (Symbol, Integer, sympify as sympify_symengine, S,
7
+ SympifyError, exp, log, gamma, sqrt, I, E, pi, Matrix,
8
+ sin, cos, tan, cot, csc, sec, asin, acos, atan, acot, acsc, asec,
9
+ sinh, cosh, tanh, coth, asinh, acosh, atanh, acoth,
10
+ lambdify, symarray, diff, zeros, eye, diag, ones,
11
+ expand, Function, symbols, var, Add, Mul, Derivative,
12
+ ImmutableMatrix, MatrixBase, Rational, Basic)
13
+ from symengine.lib.symengine_wrapper import gcd as igcd
14
+ from symengine import AppliedUndef
15
+
16
+ def sympify(a, *, strict=False):
17
+ """
18
+ Notes
19
+ =====
20
+
21
+ SymEngine's ``sympify`` does not accept keyword arguments and is
22
+ therefore not compatible with SymPy's ``sympify`` with ``strict=True``
23
+ (which ensures that only the types for which an explicit conversion has
24
+ been defined are converted). This wrapper adds an addiotional parameter
25
+ ``strict`` (with default ``False``) that will raise a ``SympifyError``
26
+ if ``strict=True`` and the argument passed to the parameter ``a`` is a
27
+ string.
28
+
29
+ See Also
30
+ ========
31
+
32
+ sympify: Converts an arbitrary expression to a type that can be used
33
+ inside SymPy.
34
+
35
+ """
36
+ # The parameter ``a`` is used for this function to keep compatibility
37
+ # with the SymEngine docstring.
38
+ if strict and isinstance(a, str):
39
+ raise SympifyError(a)
40
+ return sympify_symengine(a)
41
+
42
+ # Keep the SymEngine docstring and append the additional "Notes" and "See
43
+ # Also" sections. Replacement of spaces is required to correctly format the
44
+ # indentation of the combined docstring.
45
+ sympify.__doc__ = (
46
+ sympify_symengine.__doc__
47
+ + sympify.__doc__.replace(' ', ' ') # type: ignore
48
+ )
49
+ else:
50
+ from sympy.core.add import Add
51
+ from sympy.core.basic import Basic
52
+ from sympy.core.function import (diff, Function, AppliedUndef,
53
+ expand, Derivative)
54
+ from sympy.core.mul import Mul
55
+ from sympy.core.intfunc import igcd
56
+ from sympy.core.numbers import pi, I, Integer, Rational, E
57
+ from sympy.core.singleton import S
58
+ from sympy.core.symbol import Symbol, var, symbols
59
+ from sympy.core.sympify import SympifyError, sympify
60
+ from sympy.functions.elementary.exponential import log, exp
61
+ from sympy.functions.elementary.hyperbolic import (coth, sinh,
62
+ acosh, acoth, tanh, asinh, atanh, cosh)
63
+ from sympy.functions.elementary.miscellaneous import sqrt
64
+ from sympy.functions.elementary.trigonometric import (csc,
65
+ asec, cos, atan, sec, acot, asin, tan, sin, cot, acsc, acos)
66
+ from sympy.functions.special.gamma_functions import gamma
67
+ from sympy.matrices.dense import (eye, zeros, diag, Matrix,
68
+ ones, symarray)
69
+ from sympy.matrices.immutable import ImmutableMatrix
70
+ from sympy.matrices.matrixbase import MatrixBase
71
+ from sympy.utilities.lambdify import lambdify
72
+
73
+
74
+ #
75
+ # XXX: Handling of immutable and mutable matrices in SymEngine is inconsistent
76
+ # with SymPy's matrix classes in at least SymEngine version 0.7.0. Until that
77
+ # is fixed the function below is needed for consistent behaviour when
78
+ # attempting to simplify a matrix.
79
+ #
80
+ # Expected behaviour of a SymPy mutable/immutable matrix .simplify() method:
81
+ #
82
+ # Matrix.simplify() : works in place, returns None
83
+ # ImmutableMatrix.simplify() : returns a simplified copy
84
+ #
85
+ # In SymEngine both mutable and immutable matrices simplify in place and return
86
+ # None. This is inconsistent with the matrix being "immutable" and also the
87
+ # returned None leads to problems in the mechanics module.
88
+ #
89
+ # The simplify function should not be used because simplify(M) sympifies the
90
+ # matrix M and the SymEngine matrices all sympify to SymPy matrices. If we want
91
+ # to work with SymEngine matrices then we need to use their .simplify() method
92
+ # but that method does not work correctly with immutable matrices.
93
+ #
94
+ # The _simplify_matrix function can be removed when the SymEngine bug is fixed.
95
+ # Since this should be a temporary problem we do not make this function part of
96
+ # the public API.
97
+ #
98
+ # SymEngine issue: https://github.com/symengine/symengine.py/issues/363
99
+ #
100
+
101
+ def _simplify_matrix(M):
102
+ """Return a simplified copy of the matrix M"""
103
+ if not isinstance(M, (Matrix, ImmutableMatrix)):
104
+ raise TypeError("The matrix M must be an instance of Matrix or ImmutableMatrix")
105
+ Mnew = M.as_mutable() # makes a copy if mutable
106
+ Mnew.simplify()
107
+ if isinstance(M, ImmutableMatrix):
108
+ Mnew = Mnew.as_immutable()
109
+ return Mnew
110
+
111
+
112
+ __all__ = [
113
+ 'Symbol', 'Integer', 'sympify', 'S', 'SympifyError', 'exp', 'log',
114
+ 'gamma', 'sqrt', 'I', 'E', 'pi', 'Matrix', 'sin', 'cos', 'tan', 'cot',
115
+ 'csc', 'sec', 'asin', 'acos', 'atan', 'acot', 'acsc', 'asec', 'sinh',
116
+ 'cosh', 'tanh', 'coth', 'asinh', 'acosh', 'atanh', 'acoth', 'lambdify',
117
+ 'symarray', 'diff', 'zeros', 'eye', 'diag', 'ones', 'expand', 'Function',
118
+ 'symbols', 'var', 'Add', 'Mul', 'Derivative', 'ImmutableMatrix',
119
+ 'MatrixBase', 'Rational', 'Basic', 'igcd', 'AppliedUndef',
120
+ ]
lib/python3.12/site-packages/sympy/core/basic.py ADDED
@@ -0,0 +1,2339 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Base class for all the objects in SymPy"""
2
+ from __future__ import annotations
3
+
4
+ from collections import defaultdict
5
+ from collections.abc import Mapping
6
+ from itertools import chain, zip_longest
7
+ from functools import cmp_to_key
8
+
9
+ from .assumptions import _prepare_class_assumptions
10
+ from .cache import cacheit
11
+ from .sympify import _sympify, sympify, SympifyError, _external_converter
12
+ from .sorting import ordered
13
+ from .kind import Kind, UndefinedKind
14
+ from ._print_helpers import Printable
15
+
16
+ from sympy.utilities.decorator import deprecated
17
+ from sympy.utilities.exceptions import sympy_deprecation_warning
18
+ from sympy.utilities.iterables import iterable, numbered_symbols
19
+ from sympy.utilities.misc import filldedent, func_name
20
+
21
+ from inspect import getmro
22
+
23
+
24
+ def as_Basic(expr):
25
+ """Return expr as a Basic instance using strict sympify
26
+ or raise a TypeError; this is just a wrapper to _sympify,
27
+ raising a TypeError instead of a SympifyError."""
28
+ try:
29
+ return _sympify(expr)
30
+ except SympifyError:
31
+ raise TypeError(
32
+ 'Argument must be a Basic object, not `%s`' % func_name(
33
+ expr))
34
+
35
+
36
+ # Key for sorting commutative args in canonical order
37
+ # by name. This is used for canonical ordering of the
38
+ # args for Add and Mul *if* the names of both classes
39
+ # being compared appear here. Some things in this list
40
+ # are not spelled the same as their name so they do not,
41
+ # in effect, appear here. See Basic.compare.
42
+ ordering_of_classes = [
43
+ # singleton numbers
44
+ 'Zero', 'One', 'Half', 'Infinity', 'NaN', 'NegativeOne', 'NegativeInfinity',
45
+ # numbers
46
+ 'Integer', 'Rational', 'Float',
47
+ # singleton symbols
48
+ 'Exp1', 'Pi', 'ImaginaryUnit',
49
+ # symbols
50
+ 'Symbol', 'Wild',
51
+ # arithmetic operations
52
+ 'Pow', 'Mul', 'Add',
53
+ # function values
54
+ 'Derivative', 'Integral',
55
+ # defined singleton functions
56
+ 'Abs', 'Sign', 'Sqrt',
57
+ 'Floor', 'Ceiling',
58
+ 'Re', 'Im', 'Arg',
59
+ 'Conjugate',
60
+ 'Exp', 'Log',
61
+ 'Sin', 'Cos', 'Tan', 'Cot', 'ASin', 'ACos', 'ATan', 'ACot',
62
+ 'Sinh', 'Cosh', 'Tanh', 'Coth', 'ASinh', 'ACosh', 'ATanh', 'ACoth',
63
+ 'RisingFactorial', 'FallingFactorial',
64
+ 'factorial', 'binomial',
65
+ 'Gamma', 'LowerGamma', 'UpperGamma', 'PolyGamma',
66
+ 'Erf',
67
+ # special polynomials
68
+ 'Chebyshev', 'Chebyshev2',
69
+ # undefined functions
70
+ 'Function', 'WildFunction',
71
+ # anonymous functions
72
+ 'Lambda',
73
+ # Landau O symbol
74
+ 'Order',
75
+ # relational operations
76
+ 'Equality', 'Unequality', 'StrictGreaterThan', 'StrictLessThan',
77
+ 'GreaterThan', 'LessThan',
78
+ ]
79
+
80
+ def _cmp_name(x: type, y: type) -> int:
81
+ """return -1, 0, 1 if the name of x is before that of y.
82
+ A string comparison is done if either name does not appear
83
+ in `ordering_of_classes`. This is the helper for
84
+ ``Basic.compare``
85
+
86
+ Examples
87
+ ========
88
+
89
+ >>> from sympy import cos, tan, sin
90
+ >>> from sympy.core import basic
91
+ >>> save = basic.ordering_of_classes
92
+ >>> basic.ordering_of_classes = ()
93
+ >>> basic._cmp_name(cos, tan)
94
+ -1
95
+ >>> basic.ordering_of_classes = ["tan", "sin", "cos"]
96
+ >>> basic._cmp_name(cos, tan)
97
+ 1
98
+ >>> basic._cmp_name(sin, cos)
99
+ -1
100
+ >>> basic.ordering_of_classes = save
101
+
102
+ """
103
+ # If the other object is not a Basic subclass, then we are not equal to it.
104
+ if not issubclass(y, Basic):
105
+ return -1
106
+
107
+ n1 = x.__name__
108
+ n2 = y.__name__
109
+ if n1 == n2:
110
+ return 0
111
+
112
+ UNKNOWN = len(ordering_of_classes) + 1
113
+ try:
114
+ i1 = ordering_of_classes.index(n1)
115
+ except ValueError:
116
+ i1 = UNKNOWN
117
+ try:
118
+ i2 = ordering_of_classes.index(n2)
119
+ except ValueError:
120
+ i2 = UNKNOWN
121
+ if i1 == UNKNOWN and i2 == UNKNOWN:
122
+ return (n1 > n2) - (n1 < n2)
123
+ return (i1 > i2) - (i1 < i2)
124
+
125
+
126
+ class Basic(Printable):
127
+ """
128
+ Base class for all SymPy objects.
129
+
130
+ Notes and conventions
131
+ =====================
132
+
133
+ 1) Always use ``.args``, when accessing parameters of some instance:
134
+
135
+ >>> from sympy import cot
136
+ >>> from sympy.abc import x, y
137
+
138
+ >>> cot(x).args
139
+ (x,)
140
+
141
+ >>> cot(x).args[0]
142
+ x
143
+
144
+ >>> (x*y).args
145
+ (x, y)
146
+
147
+ >>> (x*y).args[1]
148
+ y
149
+
150
+
151
+ 2) Never use internal methods or variables (the ones prefixed with ``_``):
152
+
153
+ >>> cot(x)._args # do not use this, use cot(x).args instead
154
+ (x,)
155
+
156
+
157
+ 3) By "SymPy object" we mean something that can be returned by
158
+ ``sympify``. But not all objects one encounters using SymPy are
159
+ subclasses of Basic. For example, mutable objects are not:
160
+
161
+ >>> from sympy import Basic, Matrix, sympify
162
+ >>> A = Matrix([[1, 2], [3, 4]]).as_mutable()
163
+ >>> isinstance(A, Basic)
164
+ False
165
+
166
+ >>> B = sympify(A)
167
+ >>> isinstance(B, Basic)
168
+ True
169
+ """
170
+ __slots__ = ('_mhash', # hash value
171
+ '_args', # arguments
172
+ '_assumptions'
173
+ )
174
+
175
+ _args: tuple[Basic, ...]
176
+ _mhash: int | None
177
+
178
+ @property
179
+ def __sympy__(self):
180
+ return True
181
+
182
+ def __init_subclass__(cls):
183
+ # Initialize the default_assumptions FactKB and also any assumptions
184
+ # property methods. This method will only be called for subclasses of
185
+ # Basic but not for Basic itself so we call
186
+ # _prepare_class_assumptions(Basic) below the class definition.
187
+ super().__init_subclass__()
188
+ _prepare_class_assumptions(cls)
189
+
190
+ # To be overridden with True in the appropriate subclasses
191
+ is_number = False
192
+ is_Atom = False
193
+ is_Symbol = False
194
+ is_symbol = False
195
+ is_Indexed = False
196
+ is_Dummy = False
197
+ is_Wild = False
198
+ is_Function = False
199
+ is_Add = False
200
+ is_Mul = False
201
+ is_Pow = False
202
+ is_Number = False
203
+ is_Float = False
204
+ is_Rational = False
205
+ is_Integer = False
206
+ is_NumberSymbol = False
207
+ is_Order = False
208
+ is_Derivative = False
209
+ is_Piecewise = False
210
+ is_Poly = False
211
+ is_AlgebraicNumber = False
212
+ is_Relational = False
213
+ is_Equality = False
214
+ is_Boolean = False
215
+ is_Not = False
216
+ is_Matrix = False
217
+ is_Vector = False
218
+ is_Point = False
219
+ is_MatAdd = False
220
+ is_MatMul = False
221
+ is_real: bool | None
222
+ is_extended_real: bool | None
223
+ is_zero: bool | None
224
+ is_negative: bool | None
225
+ is_commutative: bool | None
226
+
227
+ kind: Kind = UndefinedKind
228
+
229
+ def __new__(cls, *args):
230
+ obj = object.__new__(cls)
231
+ obj._assumptions = cls.default_assumptions
232
+ obj._mhash = None # will be set by __hash__ method.
233
+
234
+ obj._args = args # all items in args must be Basic objects
235
+ return obj
236
+
237
+ def copy(self):
238
+ return self.func(*self.args)
239
+
240
+ def __getnewargs__(self):
241
+ return self.args
242
+
243
+ def __getstate__(self):
244
+ return None
245
+
246
+ def __setstate__(self, state):
247
+ for name, value in state.items():
248
+ setattr(self, name, value)
249
+
250
+ def __reduce_ex__(self, protocol):
251
+ if protocol < 2:
252
+ msg = "Only pickle protocol 2 or higher is supported by SymPy"
253
+ raise NotImplementedError(msg)
254
+ return super().__reduce_ex__(protocol)
255
+
256
+ def __hash__(self) -> int:
257
+ # hash cannot be cached using cache_it because infinite recurrence
258
+ # occurs as hash is needed for setting cache dictionary keys
259
+ h = self._mhash
260
+ if h is None:
261
+ h = hash((type(self).__name__,) + self._hashable_content())
262
+ self._mhash = h
263
+ return h
264
+
265
+ def _hashable_content(self):
266
+ """Return a tuple of information about self that can be used to
267
+ compute the hash. If a class defines additional attributes,
268
+ like ``name`` in Symbol, then this method should be updated
269
+ accordingly to return such relevant attributes.
270
+
271
+ Defining more than _hashable_content is necessary if __eq__ has
272
+ been defined by a class. See note about this in Basic.__eq__."""
273
+ return self._args
274
+
275
+ @property
276
+ def assumptions0(self):
277
+ """
278
+ Return object `type` assumptions.
279
+
280
+ For example:
281
+
282
+ Symbol('x', real=True)
283
+ Symbol('x', integer=True)
284
+
285
+ are different objects. In other words, besides Python type (Symbol in
286
+ this case), the initial assumptions are also forming their typeinfo.
287
+
288
+ Examples
289
+ ========
290
+
291
+ >>> from sympy import Symbol
292
+ >>> from sympy.abc import x
293
+ >>> x.assumptions0
294
+ {'commutative': True}
295
+ >>> x = Symbol("x", positive=True)
296
+ >>> x.assumptions0
297
+ {'commutative': True, 'complex': True, 'extended_negative': False,
298
+ 'extended_nonnegative': True, 'extended_nonpositive': False,
299
+ 'extended_nonzero': True, 'extended_positive': True, 'extended_real':
300
+ True, 'finite': True, 'hermitian': True, 'imaginary': False,
301
+ 'infinite': False, 'negative': False, 'nonnegative': True,
302
+ 'nonpositive': False, 'nonzero': True, 'positive': True, 'real':
303
+ True, 'zero': False}
304
+ """
305
+ return {}
306
+
307
+ def compare(self, other):
308
+ """
309
+ Return -1, 0, 1 if the object is less than, equal,
310
+ or greater than other in a canonical sense.
311
+ Non-Basic are always greater than Basic.
312
+ If both names of the classes being compared appear
313
+ in the `ordering_of_classes` then the ordering will
314
+ depend on the appearance of the names there.
315
+ If either does not appear in that list, then the
316
+ comparison is based on the class name.
317
+ If the names are the same then a comparison is made
318
+ on the length of the hashable content.
319
+ Items of the equal-lengthed contents are then
320
+ successively compared using the same rules. If there
321
+ is never a difference then 0 is returned.
322
+
323
+ Examples
324
+ ========
325
+
326
+ >>> from sympy.abc import x, y
327
+ >>> x.compare(y)
328
+ -1
329
+ >>> x.compare(x)
330
+ 0
331
+ >>> y.compare(x)
332
+ 1
333
+
334
+ """
335
+ # all redefinitions of __cmp__ method should start with the
336
+ # following lines:
337
+ if self is other:
338
+ return 0
339
+ n1 = self.__class__
340
+ n2 = other.__class__
341
+ c = _cmp_name(n1, n2)
342
+ if c:
343
+ return c
344
+ #
345
+ st = self._hashable_content()
346
+ ot = other._hashable_content()
347
+ c = (len(st) > len(ot)) - (len(st) < len(ot))
348
+ if c:
349
+ return c
350
+ for l, r in zip(st, ot):
351
+ l = Basic(*l) if isinstance(l, frozenset) else l
352
+ r = Basic(*r) if isinstance(r, frozenset) else r
353
+ if isinstance(l, Basic):
354
+ c = l.compare(r)
355
+ else:
356
+ c = (l > r) - (l < r)
357
+ if c:
358
+ return c
359
+ return 0
360
+
361
+ @staticmethod
362
+ def _compare_pretty(a, b):
363
+ """return -1, 0, 1 if a is canonically less, equal or
364
+ greater than b. This is used when 'order=old' is selected
365
+ for printing. This puts Order last, orders Rationals
366
+ according to value, puts terms in order wrt the power of
367
+ the last power appearing in a term. Ties are broken using
368
+ Basic.compare.
369
+ """
370
+ from sympy.series.order import Order
371
+ if isinstance(a, Order) and not isinstance(b, Order):
372
+ return 1
373
+ if not isinstance(a, Order) and isinstance(b, Order):
374
+ return -1
375
+
376
+ if a.is_Rational and b.is_Rational:
377
+ l = a.p * b.q
378
+ r = b.p * a.q
379
+ return (l > r) - (l < r)
380
+ else:
381
+ from .symbol import Wild
382
+ p1, p2, p3 = Wild("p1"), Wild("p2"), Wild("p3")
383
+ r_a = a.match(p1 * p2**p3)
384
+ if r_a and p3 in r_a:
385
+ a3 = r_a[p3]
386
+ r_b = b.match(p1 * p2**p3)
387
+ if r_b and p3 in r_b:
388
+ b3 = r_b[p3]
389
+ c = Basic.compare(a3, b3)
390
+ if c != 0:
391
+ return c
392
+
393
+ # break ties
394
+ return Basic.compare(a, b)
395
+
396
+ @classmethod
397
+ def fromiter(cls, args, **assumptions):
398
+ """
399
+ Create a new object from an iterable.
400
+
401
+ This is a convenience function that allows one to create objects from
402
+ any iterable, without having to convert to a list or tuple first.
403
+
404
+ Examples
405
+ ========
406
+
407
+ >>> from sympy import Tuple
408
+ >>> Tuple.fromiter(i for i in range(5))
409
+ (0, 1, 2, 3, 4)
410
+
411
+ """
412
+ return cls(*tuple(args), **assumptions)
413
+
414
+ @classmethod
415
+ def class_key(cls):
416
+ """Nice order of classes."""
417
+ return 5, 0, cls.__name__
418
+
419
+ @cacheit
420
+ def sort_key(self, order=None):
421
+ """
422
+ Return a sort key.
423
+
424
+ Examples
425
+ ========
426
+
427
+ >>> from sympy import S, I
428
+
429
+ >>> sorted([S(1)/2, I, -I], key=lambda x: x.sort_key())
430
+ [1/2, -I, I]
431
+
432
+ >>> S("[x, 1/x, 1/x**2, x**2, x**(1/2), x**(1/4), x**(3/2)]")
433
+ [x, 1/x, x**(-2), x**2, sqrt(x), x**(1/4), x**(3/2)]
434
+ >>> sorted(_, key=lambda x: x.sort_key())
435
+ [x**(-2), 1/x, x**(1/4), sqrt(x), x, x**(3/2), x**2]
436
+
437
+ """
438
+
439
+ # XXX: remove this when issue 5169 is fixed
440
+ def inner_key(arg):
441
+ if isinstance(arg, Basic):
442
+ return arg.sort_key(order)
443
+ else:
444
+ return arg
445
+
446
+ args = self._sorted_args
447
+ args = len(args), tuple([inner_key(arg) for arg in args])
448
+ return self.class_key(), args, S.One.sort_key(), S.One
449
+
450
+ def _do_eq_sympify(self, other):
451
+ """Returns a boolean indicating whether a == b when either a
452
+ or b is not a Basic. This is only done for types that were either
453
+ added to `converter` by a 3rd party or when the object has `_sympy_`
454
+ defined. This essentially reuses the code in `_sympify` that is
455
+ specific for this use case. Non-user defined types that are meant
456
+ to work with SymPy should be handled directly in the __eq__ methods
457
+ of the `Basic` classes it could equate to and not be converted. Note
458
+ that after conversion, `==` is used again since it is not
459
+ necessarily clear whether `self` or `other`'s __eq__ method needs
460
+ to be used."""
461
+ for superclass in type(other).__mro__:
462
+ conv = _external_converter.get(superclass)
463
+ if conv is not None:
464
+ return self == conv(other)
465
+ if hasattr(other, '_sympy_'):
466
+ return self == other._sympy_()
467
+ return NotImplemented
468
+
469
+ def __eq__(self, other):
470
+ """Return a boolean indicating whether a == b on the basis of
471
+ their symbolic trees.
472
+
473
+ This is the same as a.compare(b) == 0 but faster.
474
+
475
+ Notes
476
+ =====
477
+
478
+ If a class that overrides __eq__() needs to retain the
479
+ implementation of __hash__() from a parent class, the
480
+ interpreter must be told this explicitly by setting
481
+ __hash__ : Callable[[object], int] = <ParentClass>.__hash__.
482
+ Otherwise the inheritance of __hash__() will be blocked,
483
+ just as if __hash__ had been explicitly set to None.
484
+
485
+ References
486
+ ==========
487
+
488
+ from https://docs.python.org/dev/reference/datamodel.html#object.__hash__
489
+ """
490
+ if self is other:
491
+ return True
492
+
493
+ if not isinstance(other, Basic):
494
+ return self._do_eq_sympify(other)
495
+
496
+ # check for pure number expr
497
+ if not (self.is_Number and other.is_Number) and (
498
+ type(self) != type(other)):
499
+ return False
500
+ a, b = self._hashable_content(), other._hashable_content()
501
+ if a != b:
502
+ return False
503
+ # check number *in* an expression
504
+ for a, b in zip(a, b):
505
+ if not isinstance(a, Basic):
506
+ continue
507
+ if a.is_Number and type(a) != type(b):
508
+ return False
509
+ return True
510
+
511
+ def __ne__(self, other):
512
+ """``a != b`` -> Compare two symbolic trees and see whether they are different
513
+
514
+ this is the same as:
515
+
516
+ ``a.compare(b) != 0``
517
+
518
+ but faster
519
+ """
520
+ return not self == other
521
+
522
+ def dummy_eq(self, other, symbol=None):
523
+ """
524
+ Compare two expressions and handle dummy symbols.
525
+
526
+ Examples
527
+ ========
528
+
529
+ >>> from sympy import Dummy
530
+ >>> from sympy.abc import x, y
531
+
532
+ >>> u = Dummy('u')
533
+
534
+ >>> (u**2 + 1).dummy_eq(x**2 + 1)
535
+ True
536
+ >>> (u**2 + 1) == (x**2 + 1)
537
+ False
538
+
539
+ >>> (u**2 + y).dummy_eq(x**2 + y, x)
540
+ True
541
+ >>> (u**2 + y).dummy_eq(x**2 + y, y)
542
+ False
543
+
544
+ """
545
+ s = self.as_dummy()
546
+ o = _sympify(other)
547
+ o = o.as_dummy()
548
+
549
+ dummy_symbols = [i for i in s.free_symbols if i.is_Dummy]
550
+
551
+ if len(dummy_symbols) == 1:
552
+ dummy = dummy_symbols.pop()
553
+ else:
554
+ return s == o
555
+
556
+ if symbol is None:
557
+ symbols = o.free_symbols
558
+
559
+ if len(symbols) == 1:
560
+ symbol = symbols.pop()
561
+ else:
562
+ return s == o
563
+
564
+ tmp = dummy.__class__()
565
+
566
+ return s.xreplace({dummy: tmp}) == o.xreplace({symbol: tmp})
567
+
568
+ def atoms(self, *types):
569
+ """Returns the atoms that form the current object.
570
+
571
+ By default, only objects that are truly atomic and cannot
572
+ be divided into smaller pieces are returned: symbols, numbers,
573
+ and number symbols like I and pi. It is possible to request
574
+ atoms of any type, however, as demonstrated below.
575
+
576
+ Examples
577
+ ========
578
+
579
+ >>> from sympy import I, pi, sin
580
+ >>> from sympy.abc import x, y
581
+ >>> (1 + x + 2*sin(y + I*pi)).atoms()
582
+ {1, 2, I, pi, x, y}
583
+
584
+ If one or more types are given, the results will contain only
585
+ those types of atoms.
586
+
587
+ >>> from sympy import Number, NumberSymbol, Symbol
588
+ >>> (1 + x + 2*sin(y + I*pi)).atoms(Symbol)
589
+ {x, y}
590
+
591
+ >>> (1 + x + 2*sin(y + I*pi)).atoms(Number)
592
+ {1, 2}
593
+
594
+ >>> (1 + x + 2*sin(y + I*pi)).atoms(Number, NumberSymbol)
595
+ {1, 2, pi}
596
+
597
+ >>> (1 + x + 2*sin(y + I*pi)).atoms(Number, NumberSymbol, I)
598
+ {1, 2, I, pi}
599
+
600
+ Note that I (imaginary unit) and zoo (complex infinity) are special
601
+ types of number symbols and are not part of the NumberSymbol class.
602
+
603
+ The type can be given implicitly, too:
604
+
605
+ >>> (1 + x + 2*sin(y + I*pi)).atoms(x) # x is a Symbol
606
+ {x, y}
607
+
608
+ Be careful to check your assumptions when using the implicit option
609
+ since ``S(1).is_Integer = True`` but ``type(S(1))`` is ``One``, a special type
610
+ of SymPy atom, while ``type(S(2))`` is type ``Integer`` and will find all
611
+ integers in an expression:
612
+
613
+ >>> from sympy import S
614
+ >>> (1 + x + 2*sin(y + I*pi)).atoms(S(1))
615
+ {1}
616
+
617
+ >>> (1 + x + 2*sin(y + I*pi)).atoms(S(2))
618
+ {1, 2}
619
+
620
+ Finally, arguments to atoms() can select more than atomic atoms: any
621
+ SymPy type (loaded in core/__init__.py) can be listed as an argument
622
+ and those types of "atoms" as found in scanning the arguments of the
623
+ expression recursively:
624
+
625
+ >>> from sympy import Function, Mul
626
+ >>> from sympy.core.function import AppliedUndef
627
+ >>> f = Function('f')
628
+ >>> (1 + f(x) + 2*sin(y + I*pi)).atoms(Function)
629
+ {f(x), sin(y + I*pi)}
630
+ >>> (1 + f(x) + 2*sin(y + I*pi)).atoms(AppliedUndef)
631
+ {f(x)}
632
+
633
+ >>> (1 + x + 2*sin(y + I*pi)).atoms(Mul)
634
+ {I*pi, 2*sin(y + I*pi)}
635
+
636
+ """
637
+ if types:
638
+ types = tuple(
639
+ [t if isinstance(t, type) else type(t) for t in types])
640
+ nodes = _preorder_traversal(self)
641
+ if types:
642
+ result = {node for node in nodes if isinstance(node, types)}
643
+ else:
644
+ result = {node for node in nodes if not node.args}
645
+ return result
646
+
647
+ @property
648
+ def free_symbols(self) -> set[Basic]:
649
+ """Return from the atoms of self those which are free symbols.
650
+
651
+ Not all free symbols are ``Symbol``. Eg: IndexedBase('I')[0].free_symbols
652
+
653
+ For most expressions, all symbols are free symbols. For some classes
654
+ this is not true. e.g. Integrals use Symbols for the dummy variables
655
+ which are bound variables, so Integral has a method to return all
656
+ symbols except those. Derivative keeps track of symbols with respect
657
+ to which it will perform a derivative; those are
658
+ bound variables, too, so it has its own free_symbols method.
659
+
660
+ Any other method that uses bound variables should implement a
661
+ free_symbols method."""
662
+ empty: set[Basic] = set()
663
+ return empty.union(*(a.free_symbols for a in self.args))
664
+
665
+ @property
666
+ def expr_free_symbols(self):
667
+ sympy_deprecation_warning("""
668
+ The expr_free_symbols property is deprecated. Use free_symbols to get
669
+ the free symbols of an expression.
670
+ """,
671
+ deprecated_since_version="1.9",
672
+ active_deprecations_target="deprecated-expr-free-symbols")
673
+ return set()
674
+
675
+ def as_dummy(self):
676
+ """Return the expression with any objects having structurally
677
+ bound symbols replaced with unique, canonical symbols within
678
+ the object in which they appear and having only the default
679
+ assumption for commutativity being True. When applied to a
680
+ symbol a new symbol having only the same commutativity will be
681
+ returned.
682
+
683
+ Examples
684
+ ========
685
+
686
+ >>> from sympy import Integral, Symbol
687
+ >>> from sympy.abc import x
688
+ >>> r = Symbol('r', real=True)
689
+ >>> Integral(r, (r, x)).as_dummy()
690
+ Integral(_0, (_0, x))
691
+ >>> _.variables[0].is_real is None
692
+ True
693
+ >>> r.as_dummy()
694
+ _r
695
+
696
+ Notes
697
+ =====
698
+
699
+ Any object that has structurally bound variables should have
700
+ a property, `bound_symbols` that returns those symbols
701
+ appearing in the object.
702
+ """
703
+ from .symbol import Dummy, Symbol
704
+ def can(x):
705
+ # mask free that shadow bound
706
+ free = x.free_symbols
707
+ bound = set(x.bound_symbols)
708
+ d = {i: Dummy() for i in bound & free}
709
+ x = x.subs(d)
710
+ # replace bound with canonical names
711
+ x = x.xreplace(x.canonical_variables)
712
+ # return after undoing masking
713
+ return x.xreplace({v: k for k, v in d.items()})
714
+ if not self.has(Symbol):
715
+ return self
716
+ return self.replace(
717
+ lambda x: hasattr(x, 'bound_symbols'),
718
+ can,
719
+ simultaneous=False)
720
+
721
+ @property
722
+ def canonical_variables(self):
723
+ """Return a dictionary mapping any variable defined in
724
+ ``self.bound_symbols`` to Symbols that do not clash
725
+ with any free symbols in the expression.
726
+
727
+ Examples
728
+ ========
729
+
730
+ >>> from sympy import Lambda
731
+ >>> from sympy.abc import x
732
+ >>> Lambda(x, 2*x).canonical_variables
733
+ {x: _0}
734
+ """
735
+ if not hasattr(self, 'bound_symbols'):
736
+ return {}
737
+ dums = numbered_symbols('_')
738
+ reps = {}
739
+ # watch out for free symbol that are not in bound symbols;
740
+ # those that are in bound symbols are about to get changed
741
+ bound = self.bound_symbols
742
+ names = {i.name for i in self.free_symbols - set(bound)}
743
+ for b in bound:
744
+ d = next(dums)
745
+ if b.is_Symbol:
746
+ while d.name in names:
747
+ d = next(dums)
748
+ reps[b] = d
749
+ return reps
750
+
751
+ def rcall(self, *args):
752
+ """Apply on the argument recursively through the expression tree.
753
+
754
+ This method is used to simulate a common abuse of notation for
755
+ operators. For instance, in SymPy the following will not work:
756
+
757
+ ``(x+Lambda(y, 2*y))(z) == x+2*z``,
758
+
759
+ however, you can use:
760
+
761
+ >>> from sympy import Lambda
762
+ >>> from sympy.abc import x, y, z
763
+ >>> (x + Lambda(y, 2*y)).rcall(z)
764
+ x + 2*z
765
+ """
766
+ return Basic._recursive_call(self, args)
767
+
768
+ @staticmethod
769
+ def _recursive_call(expr_to_call, on_args):
770
+ """Helper for rcall method."""
771
+ from .symbol import Symbol
772
+ def the_call_method_is_overridden(expr):
773
+ for cls in getmro(type(expr)):
774
+ if '__call__' in cls.__dict__:
775
+ return cls != Basic
776
+
777
+ if callable(expr_to_call) and the_call_method_is_overridden(expr_to_call):
778
+ if isinstance(expr_to_call, Symbol): # XXX When you call a Symbol it is
779
+ return expr_to_call # transformed into an UndefFunction
780
+ else:
781
+ return expr_to_call(*on_args)
782
+ elif expr_to_call.args:
783
+ args = [Basic._recursive_call(
784
+ sub, on_args) for sub in expr_to_call.args]
785
+ return type(expr_to_call)(*args)
786
+ else:
787
+ return expr_to_call
788
+
789
+ def is_hypergeometric(self, k):
790
+ from sympy.simplify.simplify import hypersimp
791
+ from sympy.functions.elementary.piecewise import Piecewise
792
+ if self.has(Piecewise):
793
+ return None
794
+ return hypersimp(self, k) is not None
795
+
796
+ @property
797
+ def is_comparable(self):
798
+ """Return True if self can be computed to a real number
799
+ (or already is a real number) with precision, else False.
800
+
801
+ Examples
802
+ ========
803
+
804
+ >>> from sympy import exp_polar, pi, I
805
+ >>> (I*exp_polar(I*pi/2)).is_comparable
806
+ True
807
+ >>> (I*exp_polar(I*pi*2)).is_comparable
808
+ False
809
+
810
+ A False result does not mean that `self` cannot be rewritten
811
+ into a form that would be comparable. For example, the
812
+ difference computed below is zero but without simplification
813
+ it does not evaluate to a zero with precision:
814
+
815
+ >>> e = 2**pi*(1 + 2**pi)
816
+ >>> dif = e - e.expand()
817
+ >>> dif.is_comparable
818
+ False
819
+ >>> dif.n(2)._prec
820
+ 1
821
+
822
+ """
823
+ is_extended_real = self.is_extended_real
824
+ if is_extended_real is False:
825
+ return False
826
+ if not self.is_number:
827
+ return False
828
+ # don't re-eval numbers that are already evaluated since
829
+ # this will create spurious precision
830
+ n, i = [p.evalf(2) if not p.is_Number else p
831
+ for p in self.as_real_imag()]
832
+ if not (i.is_Number and n.is_Number):
833
+ return False
834
+ if i:
835
+ # if _prec = 1 we can't decide and if not,
836
+ # the answer is False because numbers with
837
+ # imaginary parts can't be compared
838
+ # so return False
839
+ return False
840
+ else:
841
+ return n._prec != 1
842
+
843
+ @property
844
+ def func(self):
845
+ """
846
+ The top-level function in an expression.
847
+
848
+ The following should hold for all objects::
849
+
850
+ >> x == x.func(*x.args)
851
+
852
+ Examples
853
+ ========
854
+
855
+ >>> from sympy.abc import x
856
+ >>> a = 2*x
857
+ >>> a.func
858
+ <class 'sympy.core.mul.Mul'>
859
+ >>> a.args
860
+ (2, x)
861
+ >>> a.func(*a.args)
862
+ 2*x
863
+ >>> a == a.func(*a.args)
864
+ True
865
+
866
+ """
867
+ return self.__class__
868
+
869
+ @property
870
+ def args(self) -> tuple[Basic, ...]:
871
+ """Returns a tuple of arguments of 'self'.
872
+
873
+ Examples
874
+ ========
875
+
876
+ >>> from sympy import cot
877
+ >>> from sympy.abc import x, y
878
+
879
+ >>> cot(x).args
880
+ (x,)
881
+
882
+ >>> cot(x).args[0]
883
+ x
884
+
885
+ >>> (x*y).args
886
+ (x, y)
887
+
888
+ >>> (x*y).args[1]
889
+ y
890
+
891
+ Notes
892
+ =====
893
+
894
+ Never use self._args, always use self.args.
895
+ Only use _args in __new__ when creating a new function.
896
+ Do not override .args() from Basic (so that it is easy to
897
+ change the interface in the future if needed).
898
+ """
899
+ return self._args
900
+
901
+ @property
902
+ def _sorted_args(self):
903
+ """
904
+ The same as ``args``. Derived classes which do not fix an
905
+ order on their arguments should override this method to
906
+ produce the sorted representation.
907
+ """
908
+ return self.args
909
+
910
+ def as_content_primitive(self, radical=False, clear=True):
911
+ """A stub to allow Basic args (like Tuple) to be skipped when computing
912
+ the content and primitive components of an expression.
913
+
914
+ See Also
915
+ ========
916
+
917
+ sympy.core.expr.Expr.as_content_primitive
918
+ """
919
+ return S.One, self
920
+
921
+ def subs(self, *args, **kwargs):
922
+ """
923
+ Substitutes old for new in an expression after sympifying args.
924
+
925
+ `args` is either:
926
+ - two arguments, e.g. foo.subs(old, new)
927
+ - one iterable argument, e.g. foo.subs(iterable). The iterable may be
928
+ o an iterable container with (old, new) pairs. In this case the
929
+ replacements are processed in the order given with successive
930
+ patterns possibly affecting replacements already made.
931
+ o a dict or set whose key/value items correspond to old/new pairs.
932
+ In this case the old/new pairs will be sorted by op count and in
933
+ case of a tie, by number of args and the default_sort_key. The
934
+ resulting sorted list is then processed as an iterable container
935
+ (see previous).
936
+
937
+ If the keyword ``simultaneous`` is True, the subexpressions will not be
938
+ evaluated until all the substitutions have been made.
939
+
940
+ Examples
941
+ ========
942
+
943
+ >>> from sympy import pi, exp, limit, oo
944
+ >>> from sympy.abc import x, y
945
+ >>> (1 + x*y).subs(x, pi)
946
+ pi*y + 1
947
+ >>> (1 + x*y).subs({x:pi, y:2})
948
+ 1 + 2*pi
949
+ >>> (1 + x*y).subs([(x, pi), (y, 2)])
950
+ 1 + 2*pi
951
+ >>> reps = [(y, x**2), (x, 2)]
952
+ >>> (x + y).subs(reps)
953
+ 6
954
+ >>> (x + y).subs(reversed(reps))
955
+ x**2 + 2
956
+
957
+ >>> (x**2 + x**4).subs(x**2, y)
958
+ y**2 + y
959
+
960
+ To replace only the x**2 but not the x**4, use xreplace:
961
+
962
+ >>> (x**2 + x**4).xreplace({x**2: y})
963
+ x**4 + y
964
+
965
+ To delay evaluation until all substitutions have been made,
966
+ set the keyword ``simultaneous`` to True:
967
+
968
+ >>> (x/y).subs([(x, 0), (y, 0)])
969
+ 0
970
+ >>> (x/y).subs([(x, 0), (y, 0)], simultaneous=True)
971
+ nan
972
+
973
+ This has the added feature of not allowing subsequent substitutions
974
+ to affect those already made:
975
+
976
+ >>> ((x + y)/y).subs({x + y: y, y: x + y})
977
+ 1
978
+ >>> ((x + y)/y).subs({x + y: y, y: x + y}, simultaneous=True)
979
+ y/(x + y)
980
+
981
+ In order to obtain a canonical result, unordered iterables are
982
+ sorted by count_op length, number of arguments and by the
983
+ default_sort_key to break any ties. All other iterables are left
984
+ unsorted.
985
+
986
+ >>> from sympy import sqrt, sin, cos
987
+ >>> from sympy.abc import a, b, c, d, e
988
+
989
+ >>> A = (sqrt(sin(2*x)), a)
990
+ >>> B = (sin(2*x), b)
991
+ >>> C = (cos(2*x), c)
992
+ >>> D = (x, d)
993
+ >>> E = (exp(x), e)
994
+
995
+ >>> expr = sqrt(sin(2*x))*sin(exp(x)*x)*cos(2*x) + sin(2*x)
996
+
997
+ >>> expr.subs(dict([A, B, C, D, E]))
998
+ a*c*sin(d*e) + b
999
+
1000
+ The resulting expression represents a literal replacement of the
1001
+ old arguments with the new arguments. This may not reflect the
1002
+ limiting behavior of the expression:
1003
+
1004
+ >>> (x**3 - 3*x).subs({x: oo})
1005
+ nan
1006
+
1007
+ >>> limit(x**3 - 3*x, x, oo)
1008
+ oo
1009
+
1010
+ If the substitution will be followed by numerical
1011
+ evaluation, it is better to pass the substitution to
1012
+ evalf as
1013
+
1014
+ >>> (1/x).evalf(subs={x: 3.0}, n=21)
1015
+ 0.333333333333333333333
1016
+
1017
+ rather than
1018
+
1019
+ >>> (1/x).subs({x: 3.0}).evalf(21)
1020
+ 0.333333333333333314830
1021
+
1022
+ as the former will ensure that the desired level of precision is
1023
+ obtained.
1024
+
1025
+ See Also
1026
+ ========
1027
+ replace: replacement capable of doing wildcard-like matching,
1028
+ parsing of match, and conditional replacements
1029
+ xreplace: exact node replacement in expr tree; also capable of
1030
+ using matching rules
1031
+ sympy.core.evalf.EvalfMixin.evalf: calculates the given formula to a desired level of precision
1032
+
1033
+ """
1034
+ from .containers import Dict
1035
+ from .symbol import Dummy, Symbol
1036
+ from .numbers import _illegal
1037
+
1038
+ unordered = False
1039
+ if len(args) == 1:
1040
+
1041
+ sequence = args[0]
1042
+ if isinstance(sequence, set):
1043
+ unordered = True
1044
+ elif isinstance(sequence, (Dict, Mapping)):
1045
+ unordered = True
1046
+ sequence = sequence.items()
1047
+ elif not iterable(sequence):
1048
+ raise ValueError(filldedent("""
1049
+ When a single argument is passed to subs
1050
+ it should be a dictionary of old: new pairs or an iterable
1051
+ of (old, new) tuples."""))
1052
+ elif len(args) == 2:
1053
+ sequence = [args]
1054
+ else:
1055
+ raise ValueError("subs accepts either 1 or 2 arguments")
1056
+
1057
+ def sympify_old(old):
1058
+ if isinstance(old, str):
1059
+ # Use Symbol rather than parse_expr for old
1060
+ return Symbol(old)
1061
+ elif isinstance(old, type):
1062
+ # Allow a type e.g. Function('f') or sin
1063
+ return sympify(old, strict=False)
1064
+ else:
1065
+ return sympify(old, strict=True)
1066
+
1067
+ def sympify_new(new):
1068
+ if isinstance(new, (str, type)):
1069
+ # Allow a type or parse a string input
1070
+ return sympify(new, strict=False)
1071
+ else:
1072
+ return sympify(new, strict=True)
1073
+
1074
+ sequence = [(sympify_old(s1), sympify_new(s2)) for s1, s2 in sequence]
1075
+
1076
+ # skip if there is no change
1077
+ sequence = [(s1, s2) for s1, s2 in sequence if not _aresame(s1, s2)]
1078
+
1079
+ simultaneous = kwargs.pop('simultaneous', False)
1080
+
1081
+ if unordered:
1082
+ from .sorting import _nodes, default_sort_key
1083
+ sequence = dict(sequence)
1084
+ # order so more complex items are first and items
1085
+ # of identical complexity are ordered so
1086
+ # f(x) < f(y) < x < y
1087
+ # \___ 2 __/ \_1_/ <- number of nodes
1088
+ #
1089
+ # For more complex ordering use an unordered sequence.
1090
+ k = list(ordered(sequence, default=False, keys=(
1091
+ lambda x: -_nodes(x),
1092
+ default_sort_key,
1093
+ )))
1094
+ sequence = [(k, sequence[k]) for k in k]
1095
+ # do infinities first
1096
+ if not simultaneous:
1097
+ redo = [i for i, seq in enumerate(sequence) if seq[1] in _illegal]
1098
+ for i in reversed(redo):
1099
+ sequence.insert(0, sequence.pop(i))
1100
+
1101
+ if simultaneous: # XXX should this be the default for dict subs?
1102
+ reps = {}
1103
+ rv = self
1104
+ kwargs['hack2'] = True
1105
+ m = Dummy('subs_m')
1106
+ for old, new in sequence:
1107
+ com = new.is_commutative
1108
+ if com is None:
1109
+ com = True
1110
+ d = Dummy('subs_d', commutative=com)
1111
+ # using d*m so Subs will be used on dummy variables
1112
+ # in things like Derivative(f(x, y), x) in which x
1113
+ # is both free and bound
1114
+ rv = rv._subs(old, d*m, **kwargs)
1115
+ if not isinstance(rv, Basic):
1116
+ break
1117
+ reps[d] = new
1118
+ reps[m] = S.One # get rid of m
1119
+ return rv.xreplace(reps)
1120
+ else:
1121
+ rv = self
1122
+ for old, new in sequence:
1123
+ rv = rv._subs(old, new, **kwargs)
1124
+ if not isinstance(rv, Basic):
1125
+ break
1126
+ return rv
1127
+
1128
+ @cacheit
1129
+ def _subs(self, old, new, **hints):
1130
+ """Substitutes an expression old -> new.
1131
+
1132
+ If self is not equal to old then _eval_subs is called.
1133
+ If _eval_subs does not want to make any special replacement
1134
+ then a None is received which indicates that the fallback
1135
+ should be applied wherein a search for replacements is made
1136
+ amongst the arguments of self.
1137
+
1138
+ >>> from sympy import Add
1139
+ >>> from sympy.abc import x, y, z
1140
+
1141
+ Examples
1142
+ ========
1143
+
1144
+ Add's _eval_subs knows how to target x + y in the following
1145
+ so it makes the change:
1146
+
1147
+ >>> (x + y + z).subs(x + y, 1)
1148
+ z + 1
1149
+
1150
+ Add's _eval_subs does not need to know how to find x + y in
1151
+ the following:
1152
+
1153
+ >>> Add._eval_subs(z*(x + y) + 3, x + y, 1) is None
1154
+ True
1155
+
1156
+ The returned None will cause the fallback routine to traverse the args and
1157
+ pass the z*(x + y) arg to Mul where the change will take place and the
1158
+ substitution will succeed:
1159
+
1160
+ >>> (z*(x + y) + 3).subs(x + y, 1)
1161
+ z + 3
1162
+
1163
+ ** Developers Notes **
1164
+
1165
+ An _eval_subs routine for a class should be written if:
1166
+
1167
+ 1) any arguments are not instances of Basic (e.g. bool, tuple);
1168
+
1169
+ 2) some arguments should not be targeted (as in integration
1170
+ variables);
1171
+
1172
+ 3) if there is something other than a literal replacement
1173
+ that should be attempted (as in Piecewise where the condition
1174
+ may be updated without doing a replacement).
1175
+
1176
+ If it is overridden, here are some special cases that might arise:
1177
+
1178
+ 1) If it turns out that no special change was made and all
1179
+ the original sub-arguments should be checked for
1180
+ replacements then None should be returned.
1181
+
1182
+ 2) If it is necessary to do substitutions on a portion of
1183
+ the expression then _subs should be called. _subs will
1184
+ handle the case of any sub-expression being equal to old
1185
+ (which usually would not be the case) while its fallback
1186
+ will handle the recursion into the sub-arguments. For
1187
+ example, after Add's _eval_subs removes some matching terms
1188
+ it must process the remaining terms so it calls _subs
1189
+ on each of the un-matched terms and then adds them
1190
+ onto the terms previously obtained.
1191
+
1192
+ 3) If the initial expression should remain unchanged then
1193
+ the original expression should be returned. (Whenever an
1194
+ expression is returned, modified or not, no further
1195
+ substitution of old -> new is attempted.) Sum's _eval_subs
1196
+ routine uses this strategy when a substitution is attempted
1197
+ on any of its summation variables.
1198
+ """
1199
+
1200
+ def fallback(self, old, new):
1201
+ """
1202
+ Try to replace old with new in any of self's arguments.
1203
+ """
1204
+ hit = False
1205
+ args = list(self.args)
1206
+ for i, arg in enumerate(args):
1207
+ if not hasattr(arg, '_eval_subs'):
1208
+ continue
1209
+ arg = arg._subs(old, new, **hints)
1210
+ if not _aresame(arg, args[i]):
1211
+ hit = True
1212
+ args[i] = arg
1213
+ if hit:
1214
+ rv = self.func(*args)
1215
+ hack2 = hints.get('hack2', False)
1216
+ if hack2 and self.is_Mul and not rv.is_Mul: # 2-arg hack
1217
+ coeff = S.One
1218
+ nonnumber = []
1219
+ for i in args:
1220
+ if i.is_Number:
1221
+ coeff *= i
1222
+ else:
1223
+ nonnumber.append(i)
1224
+ nonnumber = self.func(*nonnumber)
1225
+ if coeff is S.One:
1226
+ return nonnumber
1227
+ else:
1228
+ return self.func(coeff, nonnumber, evaluate=False)
1229
+ return rv
1230
+ return self
1231
+
1232
+ if _aresame(self, old):
1233
+ return new
1234
+
1235
+ rv = self._eval_subs(old, new)
1236
+ if rv is None:
1237
+ rv = fallback(self, old, new)
1238
+ return rv
1239
+
1240
+ def _eval_subs(self, old, new):
1241
+ """Override this stub if you want to do anything more than
1242
+ attempt a replacement of old with new in the arguments of self.
1243
+
1244
+ See also
1245
+ ========
1246
+
1247
+ _subs
1248
+ """
1249
+ return None
1250
+
1251
+ def xreplace(self, rule):
1252
+ """
1253
+ Replace occurrences of objects within the expression.
1254
+
1255
+ Parameters
1256
+ ==========
1257
+
1258
+ rule : dict-like
1259
+ Expresses a replacement rule
1260
+
1261
+ Returns
1262
+ =======
1263
+
1264
+ xreplace : the result of the replacement
1265
+
1266
+ Examples
1267
+ ========
1268
+
1269
+ >>> from sympy import symbols, pi, exp
1270
+ >>> x, y, z = symbols('x y z')
1271
+ >>> (1 + x*y).xreplace({x: pi})
1272
+ pi*y + 1
1273
+ >>> (1 + x*y).xreplace({x: pi, y: 2})
1274
+ 1 + 2*pi
1275
+
1276
+ Replacements occur only if an entire node in the expression tree is
1277
+ matched:
1278
+
1279
+ >>> (x*y + z).xreplace({x*y: pi})
1280
+ z + pi
1281
+ >>> (x*y*z).xreplace({x*y: pi})
1282
+ x*y*z
1283
+ >>> (2*x).xreplace({2*x: y, x: z})
1284
+ y
1285
+ >>> (2*2*x).xreplace({2*x: y, x: z})
1286
+ 4*z
1287
+ >>> (x + y + 2).xreplace({x + y: 2})
1288
+ x + y + 2
1289
+ >>> (x + 2 + exp(x + 2)).xreplace({x + 2: y})
1290
+ x + exp(y) + 2
1291
+
1292
+ xreplace does not differentiate between free and bound symbols. In the
1293
+ following, subs(x, y) would not change x since it is a bound symbol,
1294
+ but xreplace does:
1295
+
1296
+ >>> from sympy import Integral
1297
+ >>> Integral(x, (x, 1, 2*x)).xreplace({x: y})
1298
+ Integral(y, (y, 1, 2*y))
1299
+
1300
+ Trying to replace x with an expression raises an error:
1301
+
1302
+ >>> Integral(x, (x, 1, 2*x)).xreplace({x: 2*y}) # doctest: +SKIP
1303
+ ValueError: Invalid limits given: ((2*y, 1, 4*y),)
1304
+
1305
+ See Also
1306
+ ========
1307
+ replace: replacement capable of doing wildcard-like matching,
1308
+ parsing of match, and conditional replacements
1309
+ subs: substitution of subexpressions as defined by the objects
1310
+ themselves.
1311
+
1312
+ """
1313
+ value, _ = self._xreplace(rule)
1314
+ return value
1315
+
1316
+ def _xreplace(self, rule):
1317
+ """
1318
+ Helper for xreplace. Tracks whether a replacement actually occurred.
1319
+ """
1320
+ if self in rule:
1321
+ return rule[self], True
1322
+ elif rule:
1323
+ args = []
1324
+ changed = False
1325
+ for a in self.args:
1326
+ _xreplace = getattr(a, '_xreplace', None)
1327
+ if _xreplace is not None:
1328
+ a_xr = _xreplace(rule)
1329
+ args.append(a_xr[0])
1330
+ changed |= a_xr[1]
1331
+ else:
1332
+ args.append(a)
1333
+ args = tuple(args)
1334
+ if changed:
1335
+ return self.func(*args), True
1336
+ return self, False
1337
+
1338
+ @cacheit
1339
+ def has(self, *patterns):
1340
+ """
1341
+ Test whether any subexpression matches any of the patterns.
1342
+
1343
+ Examples
1344
+ ========
1345
+
1346
+ >>> from sympy import sin
1347
+ >>> from sympy.abc import x, y, z
1348
+ >>> (x**2 + sin(x*y)).has(z)
1349
+ False
1350
+ >>> (x**2 + sin(x*y)).has(x, y, z)
1351
+ True
1352
+ >>> x.has(x)
1353
+ True
1354
+
1355
+ Note ``has`` is a structural algorithm with no knowledge of
1356
+ mathematics. Consider the following half-open interval:
1357
+
1358
+ >>> from sympy import Interval
1359
+ >>> i = Interval.Lopen(0, 5); i
1360
+ Interval.Lopen(0, 5)
1361
+ >>> i.args
1362
+ (0, 5, True, False)
1363
+ >>> i.has(4) # there is no "4" in the arguments
1364
+ False
1365
+ >>> i.has(0) # there *is* a "0" in the arguments
1366
+ True
1367
+
1368
+ Instead, use ``contains`` to determine whether a number is in the
1369
+ interval or not:
1370
+
1371
+ >>> i.contains(4)
1372
+ True
1373
+ >>> i.contains(0)
1374
+ False
1375
+
1376
+
1377
+ Note that ``expr.has(*patterns)`` is exactly equivalent to
1378
+ ``any(expr.has(p) for p in patterns)``. In particular, ``False`` is
1379
+ returned when the list of patterns is empty.
1380
+
1381
+ >>> x.has()
1382
+ False
1383
+
1384
+ """
1385
+ return self._has(iterargs, *patterns)
1386
+
1387
+ def has_xfree(self, s: set[Basic]):
1388
+ """Return True if self has any of the patterns in s as a
1389
+ free argument, else False. This is like `Basic.has_free`
1390
+ but this will only report exact argument matches.
1391
+
1392
+ Examples
1393
+ ========
1394
+
1395
+ >>> from sympy import Function
1396
+ >>> from sympy.abc import x, y
1397
+ >>> f = Function('f')
1398
+ >>> f(x).has_xfree({f})
1399
+ False
1400
+ >>> f(x).has_xfree({f(x)})
1401
+ True
1402
+ >>> f(x + 1).has_xfree({x})
1403
+ True
1404
+ >>> f(x + 1).has_xfree({x + 1})
1405
+ True
1406
+ >>> f(x + y + 1).has_xfree({x + 1})
1407
+ False
1408
+ """
1409
+ # protect O(1) containment check by requiring:
1410
+ if type(s) is not set:
1411
+ raise TypeError('expecting set argument')
1412
+ return any(a in s for a in iterfreeargs(self))
1413
+
1414
+ @cacheit
1415
+ def has_free(self, *patterns):
1416
+ """Return True if self has object(s) ``x`` as a free expression
1417
+ else False.
1418
+
1419
+ Examples
1420
+ ========
1421
+
1422
+ >>> from sympy import Integral, Function
1423
+ >>> from sympy.abc import x, y
1424
+ >>> f = Function('f')
1425
+ >>> g = Function('g')
1426
+ >>> expr = Integral(f(x), (f(x), 1, g(y)))
1427
+ >>> expr.free_symbols
1428
+ {y}
1429
+ >>> expr.has_free(g(y))
1430
+ True
1431
+ >>> expr.has_free(*(x, f(x)))
1432
+ False
1433
+
1434
+ This works for subexpressions and types, too:
1435
+
1436
+ >>> expr.has_free(g)
1437
+ True
1438
+ >>> (x + y + 1).has_free(y + 1)
1439
+ True
1440
+ """
1441
+ if not patterns:
1442
+ return False
1443
+ p0 = patterns[0]
1444
+ if len(patterns) == 1 and iterable(p0) and not isinstance(p0, Basic):
1445
+ # Basic can contain iterables (though not non-Basic, ideally)
1446
+ # but don't encourage mixed passing patterns
1447
+ raise TypeError(filldedent('''
1448
+ Expecting 1 or more Basic args, not a single
1449
+ non-Basic iterable. Don't forget to unpack
1450
+ iterables: `eq.has_free(*patterns)`'''))
1451
+ # try quick test first
1452
+ s = set(patterns)
1453
+ rv = self.has_xfree(s)
1454
+ if rv:
1455
+ return rv
1456
+ # now try matching through slower _has
1457
+ return self._has(iterfreeargs, *patterns)
1458
+
1459
+ def _has(self, iterargs, *patterns):
1460
+ # separate out types and unhashable objects
1461
+ type_set = set() # only types
1462
+ p_set = set() # hashable non-types
1463
+ for p in patterns:
1464
+ if isinstance(p, type) and issubclass(p, Basic):
1465
+ type_set.add(p)
1466
+ continue
1467
+ if not isinstance(p, Basic):
1468
+ try:
1469
+ p = _sympify(p)
1470
+ except SympifyError:
1471
+ continue # Basic won't have this in it
1472
+ p_set.add(p) # fails if object defines __eq__ but
1473
+ # doesn't define __hash__
1474
+ types = tuple(type_set) #
1475
+ for i in iterargs(self): #
1476
+ if i in p_set: # <--- here, too
1477
+ return True
1478
+ if isinstance(i, types):
1479
+ return True
1480
+
1481
+ # use matcher if defined, e.g. operations defines
1482
+ # matcher that checks for exact subset containment,
1483
+ # (x + y + 1).has(x + 1) -> True
1484
+ for i in p_set - type_set: # types don't have matchers
1485
+ if not hasattr(i, '_has_matcher'):
1486
+ continue
1487
+ match = i._has_matcher()
1488
+ if any(match(arg) for arg in iterargs(self)):
1489
+ return True
1490
+
1491
+ # no success
1492
+ return False
1493
+
1494
+ def replace(self, query, value, map=False, simultaneous=True, exact=None):
1495
+ """
1496
+ Replace matching subexpressions of ``self`` with ``value``.
1497
+
1498
+ If ``map = True`` then also return the mapping {old: new} where ``old``
1499
+ was a sub-expression found with query and ``new`` is the replacement
1500
+ value for it. If the expression itself does not match the query, then
1501
+ the returned value will be ``self.xreplace(map)`` otherwise it should
1502
+ be ``self.subs(ordered(map.items()))``.
1503
+
1504
+ Traverses an expression tree and performs replacement of matching
1505
+ subexpressions from the bottom to the top of the tree. The default
1506
+ approach is to do the replacement in a simultaneous fashion so
1507
+ changes made are targeted only once. If this is not desired or causes
1508
+ problems, ``simultaneous`` can be set to False.
1509
+
1510
+ In addition, if an expression containing more than one Wild symbol
1511
+ is being used to match subexpressions and the ``exact`` flag is None
1512
+ it will be set to True so the match will only succeed if all non-zero
1513
+ values are received for each Wild that appears in the match pattern.
1514
+ Setting this to False accepts a match of 0; while setting it True
1515
+ accepts all matches that have a 0 in them. See example below for
1516
+ cautions.
1517
+
1518
+ The list of possible combinations of queries and replacement values
1519
+ is listed below:
1520
+
1521
+ Examples
1522
+ ========
1523
+
1524
+ Initial setup
1525
+
1526
+ >>> from sympy import log, sin, cos, tan, Wild, Mul, Add
1527
+ >>> from sympy.abc import x, y
1528
+ >>> f = log(sin(x)) + tan(sin(x**2))
1529
+
1530
+ 1.1. type -> type
1531
+ obj.replace(type, newtype)
1532
+
1533
+ When object of type ``type`` is found, replace it with the
1534
+ result of passing its argument(s) to ``newtype``.
1535
+
1536
+ >>> f.replace(sin, cos)
1537
+ log(cos(x)) + tan(cos(x**2))
1538
+ >>> sin(x).replace(sin, cos, map=True)
1539
+ (cos(x), {sin(x): cos(x)})
1540
+ >>> (x*y).replace(Mul, Add)
1541
+ x + y
1542
+
1543
+ 1.2. type -> func
1544
+ obj.replace(type, func)
1545
+
1546
+ When object of type ``type`` is found, apply ``func`` to its
1547
+ argument(s). ``func`` must be written to handle the number
1548
+ of arguments of ``type``.
1549
+
1550
+ >>> f.replace(sin, lambda arg: sin(2*arg))
1551
+ log(sin(2*x)) + tan(sin(2*x**2))
1552
+ >>> (x*y).replace(Mul, lambda *args: sin(2*Mul(*args)))
1553
+ sin(2*x*y)
1554
+
1555
+ 2.1. pattern -> expr
1556
+ obj.replace(pattern(wild), expr(wild))
1557
+
1558
+ Replace subexpressions matching ``pattern`` with the expression
1559
+ written in terms of the Wild symbols in ``pattern``.
1560
+
1561
+ >>> a, b = map(Wild, 'ab')
1562
+ >>> f.replace(sin(a), tan(a))
1563
+ log(tan(x)) + tan(tan(x**2))
1564
+ >>> f.replace(sin(a), tan(a/2))
1565
+ log(tan(x/2)) + tan(tan(x**2/2))
1566
+ >>> f.replace(sin(a), a)
1567
+ log(x) + tan(x**2)
1568
+ >>> (x*y).replace(a*x, a)
1569
+ y
1570
+
1571
+ Matching is exact by default when more than one Wild symbol
1572
+ is used: matching fails unless the match gives non-zero
1573
+ values for all Wild symbols:
1574
+
1575
+ >>> (2*x + y).replace(a*x + b, b - a)
1576
+ y - 2
1577
+ >>> (2*x).replace(a*x + b, b - a)
1578
+ 2*x
1579
+
1580
+ When set to False, the results may be non-intuitive:
1581
+
1582
+ >>> (2*x).replace(a*x + b, b - a, exact=False)
1583
+ 2/x
1584
+
1585
+ 2.2. pattern -> func
1586
+ obj.replace(pattern(wild), lambda wild: expr(wild))
1587
+
1588
+ All behavior is the same as in 2.1 but now a function in terms of
1589
+ pattern variables is used rather than an expression:
1590
+
1591
+ >>> f.replace(sin(a), lambda a: sin(2*a))
1592
+ log(sin(2*x)) + tan(sin(2*x**2))
1593
+
1594
+ 3.1. func -> func
1595
+ obj.replace(filter, func)
1596
+
1597
+ Replace subexpression ``e`` with ``func(e)`` if ``filter(e)``
1598
+ is True.
1599
+
1600
+ >>> g = 2*sin(x**3)
1601
+ >>> g.replace(lambda expr: expr.is_Number, lambda expr: expr**2)
1602
+ 4*sin(x**9)
1603
+
1604
+ The expression itself is also targeted by the query but is done in
1605
+ such a fashion that changes are not made twice.
1606
+
1607
+ >>> e = x*(x*y + 1)
1608
+ >>> e.replace(lambda x: x.is_Mul, lambda x: 2*x)
1609
+ 2*x*(2*x*y + 1)
1610
+
1611
+ When matching a single symbol, `exact` will default to True, but
1612
+ this may or may not be the behavior that is desired:
1613
+
1614
+ Here, we want `exact=False`:
1615
+
1616
+ >>> from sympy import Function
1617
+ >>> f = Function('f')
1618
+ >>> e = f(1) + f(0)
1619
+ >>> q = f(a), lambda a: f(a + 1)
1620
+ >>> e.replace(*q, exact=False)
1621
+ f(1) + f(2)
1622
+ >>> e.replace(*q, exact=True)
1623
+ f(0) + f(2)
1624
+
1625
+ But here, the nature of matching makes selecting
1626
+ the right setting tricky:
1627
+
1628
+ >>> e = x**(1 + y)
1629
+ >>> (x**(1 + y)).replace(x**(1 + a), lambda a: x**-a, exact=False)
1630
+ x
1631
+ >>> (x**(1 + y)).replace(x**(1 + a), lambda a: x**-a, exact=True)
1632
+ x**(-x - y + 1)
1633
+ >>> (x**y).replace(x**(1 + a), lambda a: x**-a, exact=False)
1634
+ x
1635
+ >>> (x**y).replace(x**(1 + a), lambda a: x**-a, exact=True)
1636
+ x**(1 - y)
1637
+
1638
+ It is probably better to use a different form of the query
1639
+ that describes the target expression more precisely:
1640
+
1641
+ >>> (1 + x**(1 + y)).replace(
1642
+ ... lambda x: x.is_Pow and x.exp.is_Add and x.exp.args[0] == 1,
1643
+ ... lambda x: x.base**(1 - (x.exp - 1)))
1644
+ ...
1645
+ x**(1 - y) + 1
1646
+
1647
+ See Also
1648
+ ========
1649
+
1650
+ subs: substitution of subexpressions as defined by the objects
1651
+ themselves.
1652
+ xreplace: exact node replacement in expr tree; also capable of
1653
+ using matching rules
1654
+
1655
+ """
1656
+
1657
+ try:
1658
+ query = _sympify(query)
1659
+ except SympifyError:
1660
+ pass
1661
+ try:
1662
+ value = _sympify(value)
1663
+ except SympifyError:
1664
+ pass
1665
+ if isinstance(query, type):
1666
+ _query = lambda expr: isinstance(expr, query)
1667
+
1668
+ if isinstance(value, type):
1669
+ _value = lambda expr, result: value(*expr.args)
1670
+ elif callable(value):
1671
+ _value = lambda expr, result: value(*expr.args)
1672
+ else:
1673
+ raise TypeError(
1674
+ "given a type, replace() expects another "
1675
+ "type or a callable")
1676
+ elif isinstance(query, Basic):
1677
+ _query = lambda expr: expr.match(query)
1678
+ if exact is None:
1679
+ from .symbol import Wild
1680
+ exact = (len(query.atoms(Wild)) > 1)
1681
+
1682
+ if isinstance(value, Basic):
1683
+ if exact:
1684
+ _value = lambda expr, result: (value.subs(result)
1685
+ if all(result.values()) else expr)
1686
+ else:
1687
+ _value = lambda expr, result: value.subs(result)
1688
+ elif callable(value):
1689
+ # match dictionary keys get the trailing underscore stripped
1690
+ # from them and are then passed as keywords to the callable;
1691
+ # if ``exact`` is True, only accept match if there are no null
1692
+ # values amongst those matched.
1693
+ if exact:
1694
+ _value = lambda expr, result: (value(**
1695
+ {str(k)[:-1]: v for k, v in result.items()})
1696
+ if all(val for val in result.values()) else expr)
1697
+ else:
1698
+ _value = lambda expr, result: value(**
1699
+ {str(k)[:-1]: v for k, v in result.items()})
1700
+ else:
1701
+ raise TypeError(
1702
+ "given an expression, replace() expects "
1703
+ "another expression or a callable")
1704
+ elif callable(query):
1705
+ _query = query
1706
+
1707
+ if callable(value):
1708
+ _value = lambda expr, result: value(expr)
1709
+ else:
1710
+ raise TypeError(
1711
+ "given a callable, replace() expects "
1712
+ "another callable")
1713
+ else:
1714
+ raise TypeError(
1715
+ "first argument to replace() must be a "
1716
+ "type, an expression or a callable")
1717
+
1718
+ def walk(rv, F):
1719
+ """Apply ``F`` to args and then to result.
1720
+ """
1721
+ args = getattr(rv, 'args', None)
1722
+ if args is not None:
1723
+ if args:
1724
+ newargs = tuple([walk(a, F) for a in args])
1725
+ if args != newargs:
1726
+ rv = rv.func(*newargs)
1727
+ if simultaneous:
1728
+ # if rv is something that was already
1729
+ # matched (that was changed) then skip
1730
+ # applying F again
1731
+ for i, e in enumerate(args):
1732
+ if rv == e and e != newargs[i]:
1733
+ return rv
1734
+ rv = F(rv)
1735
+ return rv
1736
+
1737
+ mapping = {} # changes that took place
1738
+
1739
+ def rec_replace(expr):
1740
+ result = _query(expr)
1741
+ if result or result == {}:
1742
+ v = _value(expr, result)
1743
+ if v is not None and v != expr:
1744
+ if map:
1745
+ mapping[expr] = v
1746
+ expr = v
1747
+ return expr
1748
+
1749
+ rv = walk(self, rec_replace)
1750
+ return (rv, mapping) if map else rv
1751
+
1752
+ def find(self, query, group=False):
1753
+ """Find all subexpressions matching a query."""
1754
+ query = _make_find_query(query)
1755
+ results = list(filter(query, _preorder_traversal(self)))
1756
+
1757
+ if not group:
1758
+ return set(results)
1759
+ else:
1760
+ groups = {}
1761
+
1762
+ for result in results:
1763
+ if result in groups:
1764
+ groups[result] += 1
1765
+ else:
1766
+ groups[result] = 1
1767
+
1768
+ return groups
1769
+
1770
+ def count(self, query):
1771
+ """Count the number of matching subexpressions."""
1772
+ query = _make_find_query(query)
1773
+ return sum(bool(query(sub)) for sub in _preorder_traversal(self))
1774
+
1775
+ def matches(self, expr, repl_dict=None, old=False):
1776
+ """
1777
+ Helper method for match() that looks for a match between Wild symbols
1778
+ in self and expressions in expr.
1779
+
1780
+ Examples
1781
+ ========
1782
+
1783
+ >>> from sympy import symbols, Wild, Basic
1784
+ >>> a, b, c = symbols('a b c')
1785
+ >>> x = Wild('x')
1786
+ >>> Basic(a + x, x).matches(Basic(a + b, c)) is None
1787
+ True
1788
+ >>> Basic(a + x, x).matches(Basic(a + b + c, b + c))
1789
+ {x_: b + c}
1790
+ """
1791
+ expr = sympify(expr)
1792
+ if not isinstance(expr, self.__class__):
1793
+ return None
1794
+
1795
+ if repl_dict is None:
1796
+ repl_dict = {}
1797
+ else:
1798
+ repl_dict = repl_dict.copy()
1799
+
1800
+ if self == expr:
1801
+ return repl_dict
1802
+
1803
+ if len(self.args) != len(expr.args):
1804
+ return None
1805
+
1806
+ d = repl_dict # already a copy
1807
+ for arg, other_arg in zip(self.args, expr.args):
1808
+ if arg == other_arg:
1809
+ continue
1810
+ if arg.is_Relational:
1811
+ try:
1812
+ d = arg.xreplace(d).matches(other_arg, d, old=old)
1813
+ except TypeError: # Should be InvalidComparisonError when introduced
1814
+ d = None
1815
+ else:
1816
+ d = arg.xreplace(d).matches(other_arg, d, old=old)
1817
+ if d is None:
1818
+ return None
1819
+ return d
1820
+
1821
+ def match(self, pattern, old=False):
1822
+ """
1823
+ Pattern matching.
1824
+
1825
+ Wild symbols match all.
1826
+
1827
+ Return ``None`` when expression (self) does not match
1828
+ with pattern. Otherwise return a dictionary such that::
1829
+
1830
+ pattern.xreplace(self.match(pattern)) == self
1831
+
1832
+ Examples
1833
+ ========
1834
+
1835
+ >>> from sympy import Wild, Sum
1836
+ >>> from sympy.abc import x, y
1837
+ >>> p = Wild("p")
1838
+ >>> q = Wild("q")
1839
+ >>> r = Wild("r")
1840
+ >>> e = (x+y)**(x+y)
1841
+ >>> e.match(p**p)
1842
+ {p_: x + y}
1843
+ >>> e.match(p**q)
1844
+ {p_: x + y, q_: x + y}
1845
+ >>> e = (2*x)**2
1846
+ >>> e.match(p*q**r)
1847
+ {p_: 4, q_: x, r_: 2}
1848
+ >>> (p*q**r).xreplace(e.match(p*q**r))
1849
+ 4*x**2
1850
+
1851
+ Structurally bound symbols are ignored during matching:
1852
+
1853
+ >>> Sum(x, (x, 1, 2)).match(Sum(y, (y, 1, p)))
1854
+ {p_: 2}
1855
+
1856
+ But they can be identified if desired:
1857
+
1858
+ >>> Sum(x, (x, 1, 2)).match(Sum(q, (q, 1, p)))
1859
+ {p_: 2, q_: x}
1860
+
1861
+ The ``old`` flag will give the old-style pattern matching where
1862
+ expressions and patterns are essentially solved to give the
1863
+ match. Both of the following give None unless ``old=True``:
1864
+
1865
+ >>> (x - 2).match(p - x, old=True)
1866
+ {p_: 2*x - 2}
1867
+ >>> (2/x).match(p*x, old=True)
1868
+ {p_: 2/x**2}
1869
+
1870
+ """
1871
+ pattern = sympify(pattern)
1872
+ # match non-bound symbols
1873
+ canonical = lambda x: x if x.is_Symbol else x.as_dummy()
1874
+ m = canonical(pattern).matches(canonical(self), old=old)
1875
+ if m is None:
1876
+ return m
1877
+ from .symbol import Wild
1878
+ from .function import WildFunction
1879
+ from ..tensor.tensor import WildTensor, WildTensorIndex, WildTensorHead
1880
+ wild = pattern.atoms(Wild, WildFunction, WildTensor, WildTensorIndex, WildTensorHead)
1881
+ # sanity check
1882
+ if set(m) - wild:
1883
+ raise ValueError(filldedent('''
1884
+ Some `matches` routine did not use a copy of repl_dict
1885
+ and injected unexpected symbols. Report this as an
1886
+ error at https://github.com/sympy/sympy/issues'''))
1887
+ # now see if bound symbols were requested
1888
+ bwild = wild - set(m)
1889
+ if not bwild:
1890
+ return m
1891
+ # replace free-Wild symbols in pattern with match result
1892
+ # so they will match but not be in the next match
1893
+ wpat = pattern.xreplace(m)
1894
+ # identify remaining bound wild
1895
+ w = wpat.matches(self, old=old)
1896
+ # add them to m
1897
+ if w:
1898
+ m.update(w)
1899
+ # done
1900
+ return m
1901
+
1902
+ def count_ops(self, visual=None):
1903
+ """Wrapper for count_ops that returns the operation count."""
1904
+ from .function import count_ops
1905
+ return count_ops(self, visual)
1906
+
1907
+ def doit(self, **hints):
1908
+ """Evaluate objects that are not evaluated by default like limits,
1909
+ integrals, sums and products. All objects of this kind will be
1910
+ evaluated recursively, unless some species were excluded via 'hints'
1911
+ or unless the 'deep' hint was set to 'False'.
1912
+
1913
+ >>> from sympy import Integral
1914
+ >>> from sympy.abc import x
1915
+
1916
+ >>> 2*Integral(x, x)
1917
+ 2*Integral(x, x)
1918
+
1919
+ >>> (2*Integral(x, x)).doit()
1920
+ x**2
1921
+
1922
+ >>> (2*Integral(x, x)).doit(deep=False)
1923
+ 2*Integral(x, x)
1924
+
1925
+ """
1926
+ if hints.get('deep', True):
1927
+ terms = [term.doit(**hints) if isinstance(term, Basic) else term
1928
+ for term in self.args]
1929
+ return self.func(*terms)
1930
+ else:
1931
+ return self
1932
+
1933
+ def simplify(self, **kwargs):
1934
+ """See the simplify function in sympy.simplify"""
1935
+ from sympy.simplify.simplify import simplify
1936
+ return simplify(self, **kwargs)
1937
+
1938
+ def refine(self, assumption=True):
1939
+ """See the refine function in sympy.assumptions"""
1940
+ from sympy.assumptions.refine import refine
1941
+ return refine(self, assumption)
1942
+
1943
+ def _eval_derivative_n_times(self, s, n):
1944
+ # This is the default evaluator for derivatives (as called by `diff`
1945
+ # and `Derivative`), it will attempt a loop to derive the expression
1946
+ # `n` times by calling the corresponding `_eval_derivative` method,
1947
+ # while leaving the derivative unevaluated if `n` is symbolic. This
1948
+ # method should be overridden if the object has a closed form for its
1949
+ # symbolic n-th derivative.
1950
+ from .numbers import Integer
1951
+ if isinstance(n, (int, Integer)):
1952
+ obj = self
1953
+ for i in range(n):
1954
+ obj2 = obj._eval_derivative(s)
1955
+ if obj == obj2 or obj2 is None:
1956
+ break
1957
+ obj = obj2
1958
+ return obj2
1959
+ else:
1960
+ return None
1961
+
1962
+ def rewrite(self, *args, deep=True, **hints):
1963
+ """
1964
+ Rewrite *self* using a defined rule.
1965
+
1966
+ Rewriting transforms an expression to another, which is mathematically
1967
+ equivalent but structurally different. For example you can rewrite
1968
+ trigonometric functions as complex exponentials or combinatorial
1969
+ functions as gamma function.
1970
+
1971
+ This method takes a *pattern* and a *rule* as positional arguments.
1972
+ *pattern* is optional parameter which defines the types of expressions
1973
+ that will be transformed. If it is not passed, all possible expressions
1974
+ will be rewritten. *rule* defines how the expression will be rewritten.
1975
+
1976
+ Parameters
1977
+ ==========
1978
+
1979
+ args : Expr
1980
+ A *rule*, or *pattern* and *rule*.
1981
+ - *pattern* is a type or an iterable of types.
1982
+ - *rule* can be any object.
1983
+
1984
+ deep : bool, optional
1985
+ If ``True``, subexpressions are recursively transformed. Default is
1986
+ ``True``.
1987
+
1988
+ Examples
1989
+ ========
1990
+
1991
+ If *pattern* is unspecified, all possible expressions are transformed.
1992
+
1993
+ >>> from sympy import cos, sin, exp, I
1994
+ >>> from sympy.abc import x
1995
+ >>> expr = cos(x) + I*sin(x)
1996
+ >>> expr.rewrite(exp)
1997
+ exp(I*x)
1998
+
1999
+ Pattern can be a type or an iterable of types.
2000
+
2001
+ >>> expr.rewrite(sin, exp)
2002
+ exp(I*x)/2 + cos(x) - exp(-I*x)/2
2003
+ >>> expr.rewrite([cos,], exp)
2004
+ exp(I*x)/2 + I*sin(x) + exp(-I*x)/2
2005
+ >>> expr.rewrite([cos, sin], exp)
2006
+ exp(I*x)
2007
+
2008
+ Rewriting behavior can be implemented by defining ``_eval_rewrite()``
2009
+ method.
2010
+
2011
+ >>> from sympy import Expr, sqrt, pi
2012
+ >>> class MySin(Expr):
2013
+ ... def _eval_rewrite(self, rule, args, **hints):
2014
+ ... x, = args
2015
+ ... if rule == cos:
2016
+ ... return cos(pi/2 - x, evaluate=False)
2017
+ ... if rule == sqrt:
2018
+ ... return sqrt(1 - cos(x)**2)
2019
+ >>> MySin(MySin(x)).rewrite(cos)
2020
+ cos(-cos(-x + pi/2) + pi/2)
2021
+ >>> MySin(x).rewrite(sqrt)
2022
+ sqrt(1 - cos(x)**2)
2023
+
2024
+ Defining ``_eval_rewrite_as_[...]()`` method is supported for backwards
2025
+ compatibility reason. This may be removed in the future and using it is
2026
+ discouraged.
2027
+
2028
+ >>> class MySin(Expr):
2029
+ ... def _eval_rewrite_as_cos(self, *args, **hints):
2030
+ ... x, = args
2031
+ ... return cos(pi/2 - x, evaluate=False)
2032
+ >>> MySin(x).rewrite(cos)
2033
+ cos(-x + pi/2)
2034
+
2035
+ """
2036
+ if not args:
2037
+ return self
2038
+
2039
+ hints.update(deep=deep)
2040
+
2041
+ pattern = args[:-1]
2042
+ rule = args[-1]
2043
+
2044
+ # support old design by _eval_rewrite_as_[...] method
2045
+ if isinstance(rule, str):
2046
+ method = "_eval_rewrite_as_%s" % rule
2047
+ elif hasattr(rule, "__name__"):
2048
+ # rule is class or function
2049
+ clsname = rule.__name__
2050
+ method = "_eval_rewrite_as_%s" % clsname
2051
+ else:
2052
+ # rule is instance
2053
+ clsname = rule.__class__.__name__
2054
+ method = "_eval_rewrite_as_%s" % clsname
2055
+
2056
+ if pattern:
2057
+ if iterable(pattern[0]):
2058
+ pattern = pattern[0]
2059
+ pattern = tuple(p for p in pattern if self.has(p))
2060
+ if not pattern:
2061
+ return self
2062
+ # hereafter, empty pattern is interpreted as all pattern.
2063
+
2064
+ return self._rewrite(pattern, rule, method, **hints)
2065
+
2066
+ def _rewrite(self, pattern, rule, method, **hints):
2067
+ deep = hints.pop('deep', True)
2068
+ if deep:
2069
+ args = [a._rewrite(pattern, rule, method, **hints)
2070
+ for a in self.args]
2071
+ else:
2072
+ args = self.args
2073
+ if not pattern or any(isinstance(self, p) for p in pattern):
2074
+ meth = getattr(self, method, None)
2075
+ if meth is not None:
2076
+ rewritten = meth(*args, **hints)
2077
+ else:
2078
+ rewritten = self._eval_rewrite(rule, args, **hints)
2079
+ if rewritten is not None:
2080
+ return rewritten
2081
+ if not args:
2082
+ return self
2083
+ return self.func(*args)
2084
+
2085
+ def _eval_rewrite(self, rule, args, **hints):
2086
+ return None
2087
+
2088
+ _constructor_postprocessor_mapping = {} # type: ignore
2089
+
2090
+ @classmethod
2091
+ def _exec_constructor_postprocessors(cls, obj):
2092
+ # WARNING: This API is experimental.
2093
+
2094
+ # This is an experimental API that introduces constructor
2095
+ # postprosessors for SymPy Core elements. If an argument of a SymPy
2096
+ # expression has a `_constructor_postprocessor_mapping` attribute, it will
2097
+ # be interpreted as a dictionary containing lists of postprocessing
2098
+ # functions for matching expression node names.
2099
+
2100
+ clsname = obj.__class__.__name__
2101
+ postprocessors = defaultdict(list)
2102
+ for i in obj.args:
2103
+ try:
2104
+ postprocessor_mappings = (
2105
+ Basic._constructor_postprocessor_mapping[cls].items()
2106
+ for cls in type(i).mro()
2107
+ if cls in Basic._constructor_postprocessor_mapping
2108
+ )
2109
+ for k, v in chain.from_iterable(postprocessor_mappings):
2110
+ postprocessors[k].extend([j for j in v if j not in postprocessors[k]])
2111
+ except TypeError:
2112
+ pass
2113
+
2114
+ for f in postprocessors.get(clsname, []):
2115
+ obj = f(obj)
2116
+
2117
+ return obj
2118
+
2119
+ def _sage_(self):
2120
+ """
2121
+ Convert *self* to a symbolic expression of SageMath.
2122
+
2123
+ This version of the method is merely a placeholder.
2124
+ """
2125
+ old_method = self._sage_
2126
+ from sage.interfaces.sympy import sympy_init
2127
+ sympy_init() # may monkey-patch _sage_ method into self's class or superclasses
2128
+ if old_method == self._sage_:
2129
+ raise NotImplementedError('conversion to SageMath is not implemented')
2130
+ else:
2131
+ # call the freshly monkey-patched method
2132
+ return self._sage_()
2133
+
2134
+ def could_extract_minus_sign(self):
2135
+ return False # see Expr.could_extract_minus_sign
2136
+
2137
+ def is_same(a, b, approx=None):
2138
+ """Return True if a and b are structurally the same, else False.
2139
+ If `approx` is supplied, it will be used to test whether two
2140
+ numbers are the same or not. By default, only numbers of the
2141
+ same type will compare equal, so S.Half != Float(0.5).
2142
+
2143
+ Examples
2144
+ ========
2145
+
2146
+ In SymPy (unlike Python) two numbers do not compare the same if they are
2147
+ not of the same type:
2148
+
2149
+ >>> from sympy import S
2150
+ >>> 2.0 == S(2)
2151
+ False
2152
+ >>> 0.5 == S.Half
2153
+ False
2154
+
2155
+ By supplying a function with which to compare two numbers, such
2156
+ differences can be ignored. e.g. `equal_valued` will return True
2157
+ for decimal numbers having a denominator that is a power of 2,
2158
+ regardless of precision.
2159
+
2160
+ >>> from sympy import Float
2161
+ >>> from sympy.core.numbers import equal_valued
2162
+ >>> (S.Half/4).is_same(Float(0.125, 1), equal_valued)
2163
+ True
2164
+ >>> Float(1, 2).is_same(Float(1, 10), equal_valued)
2165
+ True
2166
+
2167
+ But decimals without a power of 2 denominator will compare
2168
+ as not being the same.
2169
+
2170
+ >>> Float(0.1, 9).is_same(Float(0.1, 10), equal_valued)
2171
+ False
2172
+
2173
+ But arbitrary differences can be ignored by supplying a function
2174
+ to test the equivalence of two numbers:
2175
+
2176
+ >>> import math
2177
+ >>> Float(0.1, 9).is_same(Float(0.1, 10), math.isclose)
2178
+ True
2179
+
2180
+ Other objects might compare the same even though types are not the
2181
+ same. This routine will only return True if two expressions are
2182
+ identical in terms of class types.
2183
+
2184
+ >>> from sympy import eye, Basic
2185
+ >>> eye(1) == S(eye(1)) # mutable vs immutable
2186
+ True
2187
+ >>> Basic.is_same(eye(1), S(eye(1)))
2188
+ False
2189
+
2190
+ """
2191
+ from .numbers import Number
2192
+ from .traversal import postorder_traversal as pot
2193
+ for t in zip_longest(pot(a), pot(b)):
2194
+ if None in t:
2195
+ return False
2196
+ a, b = t
2197
+ if isinstance(a, Number):
2198
+ if not isinstance(b, Number):
2199
+ return False
2200
+ if approx:
2201
+ return approx(a, b)
2202
+ if not (a == b and a.__class__ == b.__class__):
2203
+ return False
2204
+ return True
2205
+
2206
+ _aresame = Basic.is_same # for sake of others importing this
2207
+
2208
+ # key used by Mul and Add to make canonical args
2209
+ _args_sortkey = cmp_to_key(Basic.compare)
2210
+
2211
+ # For all Basic subclasses _prepare_class_assumptions is called by
2212
+ # Basic.__init_subclass__ but that method is not called for Basic itself so we
2213
+ # call the function here instead.
2214
+ _prepare_class_assumptions(Basic)
2215
+
2216
+
2217
+ class Atom(Basic):
2218
+ """
2219
+ A parent class for atomic things. An atom is an expression with no subexpressions.
2220
+
2221
+ Examples
2222
+ ========
2223
+
2224
+ Symbol, Number, Rational, Integer, ...
2225
+ But not: Add, Mul, Pow, ...
2226
+ """
2227
+
2228
+ is_Atom = True
2229
+
2230
+ __slots__ = ()
2231
+
2232
+ def matches(self, expr, repl_dict=None, old=False):
2233
+ if self == expr:
2234
+ if repl_dict is None:
2235
+ return {}
2236
+ return repl_dict.copy()
2237
+
2238
+ def xreplace(self, rule, hack2=False):
2239
+ return rule.get(self, self)
2240
+
2241
+ def doit(self, **hints):
2242
+ return self
2243
+
2244
+ @classmethod
2245
+ def class_key(cls):
2246
+ return 2, 0, cls.__name__
2247
+
2248
+ @cacheit
2249
+ def sort_key(self, order=None):
2250
+ return self.class_key(), (1, (str(self),)), S.One.sort_key(), S.One
2251
+
2252
+ def _eval_simplify(self, **kwargs):
2253
+ return self
2254
+
2255
+ @property
2256
+ def _sorted_args(self):
2257
+ # this is here as a safeguard against accidentally using _sorted_args
2258
+ # on Atoms -- they cannot be rebuilt as atom.func(*atom._sorted_args)
2259
+ # since there are no args. So the calling routine should be checking
2260
+ # to see that this property is not called for Atoms.
2261
+ raise AttributeError('Atoms have no args. It might be necessary'
2262
+ ' to make a check for Atoms in the calling code.')
2263
+
2264
+
2265
+ def _atomic(e, recursive=False):
2266
+ """Return atom-like quantities as far as substitution is
2267
+ concerned: Derivatives, Functions and Symbols. Do not
2268
+ return any 'atoms' that are inside such quantities unless
2269
+ they also appear outside, too, unless `recursive` is True.
2270
+
2271
+ Examples
2272
+ ========
2273
+
2274
+ >>> from sympy import Derivative, Function, cos
2275
+ >>> from sympy.abc import x, y
2276
+ >>> from sympy.core.basic import _atomic
2277
+ >>> f = Function('f')
2278
+ >>> _atomic(x + y)
2279
+ {x, y}
2280
+ >>> _atomic(x + f(y))
2281
+ {x, f(y)}
2282
+ >>> _atomic(Derivative(f(x), x) + cos(x) + y)
2283
+ {y, cos(x), Derivative(f(x), x)}
2284
+
2285
+ """
2286
+ pot = _preorder_traversal(e)
2287
+ seen = set()
2288
+ if isinstance(e, Basic):
2289
+ free = getattr(e, "free_symbols", None)
2290
+ if free is None:
2291
+ return {e}
2292
+ else:
2293
+ return set()
2294
+ from .symbol import Symbol
2295
+ from .function import Derivative, Function
2296
+ atoms = set()
2297
+ for p in pot:
2298
+ if p in seen:
2299
+ pot.skip()
2300
+ continue
2301
+ seen.add(p)
2302
+ if isinstance(p, Symbol) and p in free:
2303
+ atoms.add(p)
2304
+ elif isinstance(p, (Derivative, Function)):
2305
+ if not recursive:
2306
+ pot.skip()
2307
+ atoms.add(p)
2308
+ return atoms
2309
+
2310
+
2311
+ def _make_find_query(query):
2312
+ """Convert the argument of Basic.find() into a callable"""
2313
+ try:
2314
+ query = _sympify(query)
2315
+ except SympifyError:
2316
+ pass
2317
+ if isinstance(query, type):
2318
+ return lambda expr: isinstance(expr, query)
2319
+ elif isinstance(query, Basic):
2320
+ return lambda expr: expr.match(query) is not None
2321
+ return query
2322
+
2323
+ # Delayed to avoid cyclic import
2324
+ from .singleton import S
2325
+ from .traversal import (preorder_traversal as _preorder_traversal,
2326
+ iterargs, iterfreeargs)
2327
+
2328
+ preorder_traversal = deprecated(
2329
+ """
2330
+ Using preorder_traversal from the sympy.core.basic submodule is
2331
+ deprecated.
2332
+
2333
+ Instead, use preorder_traversal from the top-level sympy namespace, like
2334
+
2335
+ sympy.preorder_traversal
2336
+ """,
2337
+ deprecated_since_version="1.10",
2338
+ active_deprecations_target="deprecated-traversal-functions-moved",
2339
+ )(_preorder_traversal)
lib/python3.12/site-packages/sympy/core/cache.py ADDED
@@ -0,0 +1,210 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """ Caching facility for SymPy """
2
+ from importlib import import_module
3
+ from typing import Callable
4
+
5
+ class _cache(list):
6
+ """ List of cached functions """
7
+
8
+ def print_cache(self):
9
+ """print cache info"""
10
+
11
+ for item in self:
12
+ name = item.__name__
13
+ myfunc = item
14
+ while hasattr(myfunc, '__wrapped__'):
15
+ if hasattr(myfunc, 'cache_info'):
16
+ info = myfunc.cache_info()
17
+ break
18
+ else:
19
+ myfunc = myfunc.__wrapped__
20
+ else:
21
+ info = None
22
+
23
+ print(name, info)
24
+
25
+ def clear_cache(self):
26
+ """clear cache content"""
27
+ for item in self:
28
+ myfunc = item
29
+ while hasattr(myfunc, '__wrapped__'):
30
+ if hasattr(myfunc, 'cache_clear'):
31
+ myfunc.cache_clear()
32
+ break
33
+ else:
34
+ myfunc = myfunc.__wrapped__
35
+
36
+
37
+ # global cache registry:
38
+ CACHE = _cache()
39
+ # make clear and print methods available
40
+ print_cache = CACHE.print_cache
41
+ clear_cache = CACHE.clear_cache
42
+
43
+ from functools import lru_cache, wraps
44
+
45
+ def __cacheit(maxsize):
46
+ """caching decorator.
47
+
48
+ important: the result of cached function must be *immutable*
49
+
50
+
51
+ Examples
52
+ ========
53
+
54
+ >>> from sympy import cacheit
55
+ >>> @cacheit
56
+ ... def f(a, b):
57
+ ... return a+b
58
+
59
+ >>> @cacheit
60
+ ... def f(a, b): # noqa: F811
61
+ ... return [a, b] # <-- WRONG, returns mutable object
62
+
63
+ to force cacheit to check returned results mutability and consistency,
64
+ set environment variable SYMPY_USE_CACHE to 'debug'
65
+ """
66
+ def func_wrapper(func):
67
+ cfunc = lru_cache(maxsize, typed=True)(func)
68
+
69
+ @wraps(func)
70
+ def wrapper(*args, **kwargs):
71
+ try:
72
+ retval = cfunc(*args, **kwargs)
73
+ except TypeError as e:
74
+ if not e.args or not e.args[0].startswith('unhashable type:'):
75
+ raise
76
+ retval = func(*args, **kwargs)
77
+ return retval
78
+
79
+ wrapper.cache_info = cfunc.cache_info
80
+ wrapper.cache_clear = cfunc.cache_clear
81
+
82
+ CACHE.append(wrapper)
83
+ return wrapper
84
+
85
+ return func_wrapper
86
+ ########################################
87
+
88
+
89
+ def __cacheit_nocache(func):
90
+ return func
91
+
92
+
93
+ def __cacheit_debug(maxsize):
94
+ """cacheit + code to check cache consistency"""
95
+ def func_wrapper(func):
96
+ cfunc = __cacheit(maxsize)(func)
97
+
98
+ @wraps(func)
99
+ def wrapper(*args, **kw_args):
100
+ # always call function itself and compare it with cached version
101
+ r1 = func(*args, **kw_args)
102
+ r2 = cfunc(*args, **kw_args)
103
+
104
+ # try to see if the result is immutable
105
+ #
106
+ # this works because:
107
+ #
108
+ # hash([1,2,3]) -> raise TypeError
109
+ # hash({'a':1, 'b':2}) -> raise TypeError
110
+ # hash((1,[2,3])) -> raise TypeError
111
+ #
112
+ # hash((1,2,3)) -> just computes the hash
113
+ hash(r1), hash(r2)
114
+
115
+ # also see if returned values are the same
116
+ if r1 != r2:
117
+ raise RuntimeError("Returned values are not the same")
118
+ return r1
119
+ return wrapper
120
+ return func_wrapper
121
+
122
+
123
+ def _getenv(key, default=None):
124
+ from os import getenv
125
+ return getenv(key, default)
126
+
127
+ # SYMPY_USE_CACHE=yes/no/debug
128
+ USE_CACHE = _getenv('SYMPY_USE_CACHE', 'yes').lower()
129
+ # SYMPY_CACHE_SIZE=some_integer/None
130
+ # special cases :
131
+ # SYMPY_CACHE_SIZE=0 -> No caching
132
+ # SYMPY_CACHE_SIZE=None -> Unbounded caching
133
+ scs = _getenv('SYMPY_CACHE_SIZE', '1000')
134
+ if scs.lower() == 'none':
135
+ SYMPY_CACHE_SIZE = None
136
+ else:
137
+ try:
138
+ SYMPY_CACHE_SIZE = int(scs)
139
+ except ValueError:
140
+ raise RuntimeError(
141
+ 'SYMPY_CACHE_SIZE must be a valid integer or None. ' + \
142
+ 'Got: %s' % SYMPY_CACHE_SIZE)
143
+
144
+ if USE_CACHE == 'no':
145
+ cacheit = __cacheit_nocache
146
+ elif USE_CACHE == 'yes':
147
+ cacheit = __cacheit(SYMPY_CACHE_SIZE)
148
+ elif USE_CACHE == 'debug':
149
+ cacheit = __cacheit_debug(SYMPY_CACHE_SIZE) # a lot slower
150
+ else:
151
+ raise RuntimeError(
152
+ 'unrecognized value for SYMPY_USE_CACHE: %s' % USE_CACHE)
153
+
154
+
155
+ def cached_property(func):
156
+ '''Decorator to cache property method'''
157
+ attrname = '__' + func.__name__
158
+ _cached_property_sentinel = object()
159
+ def propfunc(self):
160
+ val = getattr(self, attrname, _cached_property_sentinel)
161
+ if val is _cached_property_sentinel:
162
+ val = func(self)
163
+ setattr(self, attrname, val)
164
+ return val
165
+ return property(propfunc)
166
+
167
+
168
+ def lazy_function(module : str, name : str) -> Callable:
169
+ """Create a lazy proxy for a function in a module.
170
+
171
+ The module containing the function is not imported until the function is used.
172
+
173
+ """
174
+ func = None
175
+
176
+ def _get_function():
177
+ nonlocal func
178
+ if func is None:
179
+ func = getattr(import_module(module), name)
180
+ return func
181
+
182
+ # The metaclass is needed so that help() shows the docstring
183
+ class LazyFunctionMeta(type):
184
+ @property
185
+ def __doc__(self):
186
+ docstring = _get_function().__doc__
187
+ docstring += f"\n\nNote: this is a {self.__class__.__name__} wrapper of '{module}.{name}'"
188
+ return docstring
189
+
190
+ class LazyFunction(metaclass=LazyFunctionMeta):
191
+ def __call__(self, *args, **kwargs):
192
+ # inline get of function for performance gh-23832
193
+ nonlocal func
194
+ if func is None:
195
+ func = getattr(import_module(module), name)
196
+ return func(*args, **kwargs)
197
+
198
+ @property
199
+ def __doc__(self):
200
+ docstring = _get_function().__doc__
201
+ docstring += f"\n\nNote: this is a {self.__class__.__name__} wrapper of '{module}.{name}'"
202
+ return docstring
203
+
204
+ def __str__(self):
205
+ return _get_function().__str__()
206
+
207
+ def __repr__(self):
208
+ return f"<{__class__.__name__} object at 0x{id(self):x}>: wrapping '{module}.{name}'"
209
+
210
+ return LazyFunction()
lib/python3.12/site-packages/sympy/core/compatibility.py ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ .. deprecated:: 1.10
3
+
4
+ ``sympy.core.compatibility`` is deprecated. See
5
+ :ref:`sympy-core-compatibility`.
6
+
7
+ Reimplementations of constructs introduced in later versions of Python than
8
+ we support. Also some functions that are needed SymPy-wide and are located
9
+ here for easy import.
10
+
11
+ """
12
+
13
+
14
+ from sympy.utilities.exceptions import sympy_deprecation_warning
15
+
16
+ sympy_deprecation_warning("""
17
+ The sympy.core.compatibility submodule is deprecated.
18
+
19
+ This module was only ever intended for internal use. Some of the functions
20
+ that were in this module are available from the top-level SymPy namespace,
21
+ i.e.,
22
+
23
+ from sympy import ordered, default_sort_key
24
+
25
+ The remaining were only intended for internal SymPy use and should not be used
26
+ by user code.
27
+ """,
28
+ deprecated_since_version="1.10",
29
+ active_deprecations_target="deprecated-sympy-core-compatibility",
30
+ )
31
+
32
+
33
+ from .sorting import ordered, _nodes, default_sort_key # noqa:F401
34
+ from sympy.utilities.misc import as_int as _as_int # noqa:F401
35
+ from sympy.utilities.iterables import iterable, is_sequence, NotIterable # noqa:F401
lib/python3.12/site-packages/sympy/core/containers.py ADDED
@@ -0,0 +1,410 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Module for SymPy containers
2
+
3
+ (SymPy objects that store other SymPy objects)
4
+
5
+ The containers implemented in this module are subclassed to Basic.
6
+ They are supposed to work seamlessly within the SymPy framework.
7
+ """
8
+
9
+ from collections import OrderedDict
10
+ from collections.abc import MutableSet
11
+ from typing import Any, Callable
12
+
13
+ from .basic import Basic
14
+ from .sorting import default_sort_key, ordered
15
+ from .sympify import _sympify, sympify, _sympy_converter, SympifyError
16
+ from sympy.core.kind import Kind
17
+ from sympy.utilities.iterables import iterable
18
+ from sympy.utilities.misc import as_int
19
+
20
+
21
+ class Tuple(Basic):
22
+ """
23
+ Wrapper around the builtin tuple object.
24
+
25
+ Explanation
26
+ ===========
27
+
28
+ The Tuple is a subclass of Basic, so that it works well in the
29
+ SymPy framework. The wrapped tuple is available as self.args, but
30
+ you can also access elements or slices with [:] syntax.
31
+
32
+ Parameters
33
+ ==========
34
+
35
+ sympify : bool
36
+ If ``False``, ``sympify`` is not called on ``args``. This
37
+ can be used for speedups for very large tuples where the
38
+ elements are known to already be SymPy objects.
39
+
40
+ Examples
41
+ ========
42
+
43
+ >>> from sympy import Tuple, symbols
44
+ >>> a, b, c, d = symbols('a b c d')
45
+ >>> Tuple(a, b, c)[1:]
46
+ (b, c)
47
+ >>> Tuple(a, b, c).subs(a, d)
48
+ (d, b, c)
49
+
50
+ """
51
+
52
+ def __new__(cls, *args, **kwargs):
53
+ if kwargs.get('sympify', True):
54
+ args = (sympify(arg) for arg in args)
55
+ obj = Basic.__new__(cls, *args)
56
+ return obj
57
+
58
+ def __getitem__(self, i):
59
+ if isinstance(i, slice):
60
+ indices = i.indices(len(self))
61
+ return Tuple(*(self.args[j] for j in range(*indices)))
62
+ return self.args[i]
63
+
64
+ def __len__(self):
65
+ return len(self.args)
66
+
67
+ def __contains__(self, item):
68
+ return item in self.args
69
+
70
+ def __iter__(self):
71
+ return iter(self.args)
72
+
73
+ def __add__(self, other):
74
+ if isinstance(other, Tuple):
75
+ return Tuple(*(self.args + other.args))
76
+ elif isinstance(other, tuple):
77
+ return Tuple(*(self.args + other))
78
+ else:
79
+ return NotImplemented
80
+
81
+ def __radd__(self, other):
82
+ if isinstance(other, Tuple):
83
+ return Tuple(*(other.args + self.args))
84
+ elif isinstance(other, tuple):
85
+ return Tuple(*(other + self.args))
86
+ else:
87
+ return NotImplemented
88
+
89
+ def __mul__(self, other):
90
+ try:
91
+ n = as_int(other)
92
+ except ValueError:
93
+ raise TypeError("Can't multiply sequence by non-integer of type '%s'" % type(other))
94
+ return self.func(*(self.args*n))
95
+
96
+ __rmul__ = __mul__
97
+
98
+ def __eq__(self, other):
99
+ if isinstance(other, Basic):
100
+ return super().__eq__(other)
101
+ return self.args == other
102
+
103
+ def __ne__(self, other):
104
+ if isinstance(other, Basic):
105
+ return super().__ne__(other)
106
+ return self.args != other
107
+
108
+ def __hash__(self):
109
+ return hash(self.args)
110
+
111
+ def _to_mpmath(self, prec):
112
+ return tuple(a._to_mpmath(prec) for a in self.args)
113
+
114
+ def __lt__(self, other):
115
+ return _sympify(self.args < other.args)
116
+
117
+ def __le__(self, other):
118
+ return _sympify(self.args <= other.args)
119
+
120
+ # XXX: Basic defines count() as something different, so we can't
121
+ # redefine it here. Originally this lead to cse() test failure.
122
+ def tuple_count(self, value) -> int:
123
+ """Return number of occurrences of value."""
124
+ return self.args.count(value)
125
+
126
+ def index(self, value, start=None, stop=None):
127
+ """Searches and returns the first index of the value."""
128
+ # XXX: One would expect:
129
+ #
130
+ # return self.args.index(value, start, stop)
131
+ #
132
+ # here. Any trouble with that? Yes:
133
+ #
134
+ # >>> (1,).index(1, None, None)
135
+ # Traceback (most recent call last):
136
+ # File "<stdin>", line 1, in <module>
137
+ # TypeError: slice indices must be integers or None or have an __index__ method
138
+ #
139
+ # See: http://bugs.python.org/issue13340
140
+
141
+ if start is None and stop is None:
142
+ return self.args.index(value)
143
+ elif stop is None:
144
+ return self.args.index(value, start)
145
+ else:
146
+ return self.args.index(value, start, stop)
147
+
148
+ @property
149
+ def kind(self):
150
+ """
151
+ The kind of a Tuple instance.
152
+
153
+ The kind of a Tuple is always of :class:`TupleKind` but
154
+ parametrised by the number of elements and the kind of each element.
155
+
156
+ Examples
157
+ ========
158
+
159
+ >>> from sympy import Tuple, Matrix
160
+ >>> Tuple(1, 2).kind
161
+ TupleKind(NumberKind, NumberKind)
162
+ >>> Tuple(Matrix([1, 2]), 1).kind
163
+ TupleKind(MatrixKind(NumberKind), NumberKind)
164
+ >>> Tuple(1, 2).kind.element_kind
165
+ (NumberKind, NumberKind)
166
+
167
+ See Also
168
+ ========
169
+
170
+ sympy.matrices.kind.MatrixKind
171
+ sympy.core.kind.NumberKind
172
+ """
173
+ return TupleKind(*(i.kind for i in self.args))
174
+
175
+ _sympy_converter[tuple] = lambda tup: Tuple(*tup)
176
+
177
+
178
+
179
+
180
+
181
+ def tuple_wrapper(method):
182
+ """
183
+ Decorator that converts any tuple in the function arguments into a Tuple.
184
+
185
+ Explanation
186
+ ===========
187
+
188
+ The motivation for this is to provide simple user interfaces. The user can
189
+ call a function with regular tuples in the argument, and the wrapper will
190
+ convert them to Tuples before handing them to the function.
191
+
192
+ Explanation
193
+ ===========
194
+
195
+ >>> from sympy.core.containers import tuple_wrapper
196
+ >>> def f(*args):
197
+ ... return args
198
+ >>> g = tuple_wrapper(f)
199
+
200
+ The decorated function g sees only the Tuple argument:
201
+
202
+ >>> g(0, (1, 2), 3)
203
+ (0, (1, 2), 3)
204
+
205
+ """
206
+ def wrap_tuples(*args, **kw_args):
207
+ newargs = []
208
+ for arg in args:
209
+ if isinstance(arg, tuple):
210
+ newargs.append(Tuple(*arg))
211
+ else:
212
+ newargs.append(arg)
213
+ return method(*newargs, **kw_args)
214
+ return wrap_tuples
215
+
216
+
217
+ class Dict(Basic):
218
+ """
219
+ Wrapper around the builtin dict object.
220
+
221
+ Explanation
222
+ ===========
223
+
224
+ The Dict is a subclass of Basic, so that it works well in the
225
+ SymPy framework. Because it is immutable, it may be included
226
+ in sets, but its values must all be given at instantiation and
227
+ cannot be changed afterwards. Otherwise it behaves identically
228
+ to the Python dict.
229
+
230
+ Examples
231
+ ========
232
+
233
+ >>> from sympy import Dict, Symbol
234
+
235
+ >>> D = Dict({1: 'one', 2: 'two'})
236
+ >>> for key in D:
237
+ ... if key == 1:
238
+ ... print('%s %s' % (key, D[key]))
239
+ 1 one
240
+
241
+ The args are sympified so the 1 and 2 are Integers and the values
242
+ are Symbols. Queries automatically sympify args so the following work:
243
+
244
+ >>> 1 in D
245
+ True
246
+ >>> D.has(Symbol('one')) # searches keys and values
247
+ True
248
+ >>> 'one' in D # not in the keys
249
+ False
250
+ >>> D[1]
251
+ one
252
+
253
+ """
254
+
255
+ def __new__(cls, *args):
256
+ if len(args) == 1 and isinstance(args[0], (dict, Dict)):
257
+ items = [Tuple(k, v) for k, v in args[0].items()]
258
+ elif iterable(args) and all(len(arg) == 2 for arg in args):
259
+ items = [Tuple(k, v) for k, v in args]
260
+ else:
261
+ raise TypeError('Pass Dict args as Dict((k1, v1), ...) or Dict({k1: v1, ...})')
262
+ elements = frozenset(items)
263
+ obj = Basic.__new__(cls, *ordered(items))
264
+ obj.elements = elements
265
+ obj._dict = dict(items) # In case Tuple decides it wants to sympify
266
+ return obj
267
+
268
+ def __getitem__(self, key):
269
+ """x.__getitem__(y) <==> x[y]"""
270
+ try:
271
+ key = _sympify(key)
272
+ except SympifyError:
273
+ raise KeyError(key)
274
+
275
+ return self._dict[key]
276
+
277
+ def __setitem__(self, key, value):
278
+ raise NotImplementedError("SymPy Dicts are Immutable")
279
+
280
+ def items(self):
281
+ '''Returns a set-like object providing a view on dict's items.
282
+ '''
283
+ return self._dict.items()
284
+
285
+ def keys(self):
286
+ '''Returns the list of the dict's keys.'''
287
+ return self._dict.keys()
288
+
289
+ def values(self):
290
+ '''Returns the list of the dict's values.'''
291
+ return self._dict.values()
292
+
293
+ def __iter__(self):
294
+ '''x.__iter__() <==> iter(x)'''
295
+ return iter(self._dict)
296
+
297
+ def __len__(self):
298
+ '''x.__len__() <==> len(x)'''
299
+ return self._dict.__len__()
300
+
301
+ def get(self, key, default=None):
302
+ '''Returns the value for key if the key is in the dictionary.'''
303
+ try:
304
+ key = _sympify(key)
305
+ except SympifyError:
306
+ return default
307
+ return self._dict.get(key, default)
308
+
309
+ def __contains__(self, key):
310
+ '''D.__contains__(k) -> True if D has a key k, else False'''
311
+ try:
312
+ key = _sympify(key)
313
+ except SympifyError:
314
+ return False
315
+ return key in self._dict
316
+
317
+ def __lt__(self, other):
318
+ return _sympify(self.args < other.args)
319
+
320
+ @property
321
+ def _sorted_args(self):
322
+ return tuple(sorted(self.args, key=default_sort_key))
323
+
324
+ def __eq__(self, other):
325
+ if isinstance(other, dict):
326
+ return self == Dict(other)
327
+ return super().__eq__(other)
328
+
329
+ __hash__ : Callable[[Basic], Any] = Basic.__hash__
330
+
331
+ # this handles dict, defaultdict, OrderedDict
332
+ _sympy_converter[dict] = lambda d: Dict(*d.items())
333
+
334
+ class OrderedSet(MutableSet):
335
+ def __init__(self, iterable=None):
336
+ if iterable:
337
+ self.map = OrderedDict((item, None) for item in iterable)
338
+ else:
339
+ self.map = OrderedDict()
340
+
341
+ def __len__(self):
342
+ return len(self.map)
343
+
344
+ def __contains__(self, key):
345
+ return key in self.map
346
+
347
+ def add(self, key):
348
+ self.map[key] = None
349
+
350
+ def discard(self, key):
351
+ self.map.pop(key)
352
+
353
+ def pop(self, last=True):
354
+ return self.map.popitem(last=last)[0]
355
+
356
+ def __iter__(self):
357
+ yield from self.map.keys()
358
+
359
+ def __repr__(self):
360
+ if not self.map:
361
+ return '%s()' % (self.__class__.__name__,)
362
+ return '%s(%r)' % (self.__class__.__name__, list(self.map.keys()))
363
+
364
+ def intersection(self, other):
365
+ return self.__class__([val for val in self if val in other])
366
+
367
+ def difference(self, other):
368
+ return self.__class__([val for val in self if val not in other])
369
+
370
+ def update(self, iterable):
371
+ for val in iterable:
372
+ self.add(val)
373
+
374
+ class TupleKind(Kind):
375
+ """
376
+ TupleKind is a subclass of Kind, which is used to define Kind of ``Tuple``.
377
+
378
+ Parameters of TupleKind will be kinds of all the arguments in Tuples, for
379
+ example
380
+
381
+ Parameters
382
+ ==========
383
+
384
+ args : tuple(element_kind)
385
+ element_kind is kind of element.
386
+ args is tuple of kinds of element
387
+
388
+ Examples
389
+ ========
390
+
391
+ >>> from sympy import Tuple
392
+ >>> Tuple(1, 2).kind
393
+ TupleKind(NumberKind, NumberKind)
394
+ >>> Tuple(1, 2).kind.element_kind
395
+ (NumberKind, NumberKind)
396
+
397
+ See Also
398
+ ========
399
+
400
+ sympy.core.kind.NumberKind
401
+ MatrixKind
402
+ sympy.sets.sets.SetKind
403
+ """
404
+ def __new__(cls, *args):
405
+ obj = super().__new__(cls, *args)
406
+ obj.element_kind = args
407
+ return obj
408
+
409
+ def __repr__(self):
410
+ return "TupleKind{}".format(self.element_kind)
lib/python3.12/site-packages/sympy/core/core.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """ The core's core. """
2
+ from __future__ import annotations
3
+
4
+
5
+ class Registry:
6
+ """
7
+ Base class for registry objects.
8
+
9
+ Registries map a name to an object using attribute notation. Registry
10
+ classes behave singletonically: all their instances share the same state,
11
+ which is stored in the class object.
12
+
13
+ All subclasses should set `__slots__ = ()`.
14
+ """
15
+ __slots__ = ()
16
+
17
+ def __setattr__(self, name, obj):
18
+ setattr(self.__class__, name, obj)
19
+
20
+ def __delattr__(self, name):
21
+ delattr(self.__class__, name)
lib/python3.12/site-packages/sympy/core/coreerrors.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ """Definitions of common exceptions for :mod:`sympy.core` module. """
2
+
3
+
4
+ class BaseCoreError(Exception):
5
+ """Base class for core related exceptions. """
6
+
7
+
8
+ class NonCommutativeExpression(BaseCoreError):
9
+ """Raised when expression didn't have commutative property. """
lib/python3.12/site-packages/sympy/core/decorators.py ADDED
@@ -0,0 +1,238 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ SymPy core decorators.
3
+
4
+ The purpose of this module is to expose decorators without any other
5
+ dependencies, so that they can be easily imported anywhere in sympy/core.
6
+ """
7
+
8
+ from functools import wraps
9
+ from .sympify import SympifyError, sympify
10
+
11
+
12
+ def _sympifyit(arg, retval=None):
13
+ """
14
+ decorator to smartly _sympify function arguments
15
+
16
+ Explanation
17
+ ===========
18
+
19
+ @_sympifyit('other', NotImplemented)
20
+ def add(self, other):
21
+ ...
22
+
23
+ In add, other can be thought of as already being a SymPy object.
24
+
25
+ If it is not, the code is likely to catch an exception, then other will
26
+ be explicitly _sympified, and the whole code restarted.
27
+
28
+ if _sympify(arg) fails, NotImplemented will be returned
29
+
30
+ See also
31
+ ========
32
+
33
+ __sympifyit
34
+ """
35
+ def deco(func):
36
+ return __sympifyit(func, arg, retval)
37
+
38
+ return deco
39
+
40
+
41
+ def __sympifyit(func, arg, retval=None):
42
+ """Decorator to _sympify `arg` argument for function `func`.
43
+
44
+ Do not use directly -- use _sympifyit instead.
45
+ """
46
+
47
+ # we support f(a,b) only
48
+ if not func.__code__.co_argcount:
49
+ raise LookupError("func not found")
50
+ # only b is _sympified
51
+ assert func.__code__.co_varnames[1] == arg
52
+ if retval is None:
53
+ @wraps(func)
54
+ def __sympifyit_wrapper(a, b):
55
+ return func(a, sympify(b, strict=True))
56
+
57
+ else:
58
+ @wraps(func)
59
+ def __sympifyit_wrapper(a, b):
60
+ try:
61
+ # If an external class has _op_priority, it knows how to deal
62
+ # with SymPy objects. Otherwise, it must be converted.
63
+ if not hasattr(b, '_op_priority'):
64
+ b = sympify(b, strict=True)
65
+ return func(a, b)
66
+ except SympifyError:
67
+ return retval
68
+
69
+ return __sympifyit_wrapper
70
+
71
+
72
+ def call_highest_priority(method_name):
73
+ """A decorator for binary special methods to handle _op_priority.
74
+
75
+ Explanation
76
+ ===========
77
+
78
+ Binary special methods in Expr and its subclasses use a special attribute
79
+ '_op_priority' to determine whose special method will be called to
80
+ handle the operation. In general, the object having the highest value of
81
+ '_op_priority' will handle the operation. Expr and subclasses that define
82
+ custom binary special methods (__mul__, etc.) should decorate those
83
+ methods with this decorator to add the priority logic.
84
+
85
+ The ``method_name`` argument is the name of the method of the other class
86
+ that will be called. Use this decorator in the following manner::
87
+
88
+ # Call other.__rmul__ if other._op_priority > self._op_priority
89
+ @call_highest_priority('__rmul__')
90
+ def __mul__(self, other):
91
+ ...
92
+
93
+ # Call other.__mul__ if other._op_priority > self._op_priority
94
+ @call_highest_priority('__mul__')
95
+ def __rmul__(self, other):
96
+ ...
97
+ """
98
+ def priority_decorator(func):
99
+ @wraps(func)
100
+ def binary_op_wrapper(self, other):
101
+ if hasattr(other, '_op_priority'):
102
+ if other._op_priority > self._op_priority:
103
+ f = getattr(other, method_name, None)
104
+ if f is not None:
105
+ return f(self)
106
+ return func(self, other)
107
+ return binary_op_wrapper
108
+ return priority_decorator
109
+
110
+
111
+ def sympify_method_args(cls):
112
+ '''Decorator for a class with methods that sympify arguments.
113
+
114
+ Explanation
115
+ ===========
116
+
117
+ The sympify_method_args decorator is to be used with the sympify_return
118
+ decorator for automatic sympification of method arguments. This is
119
+ intended for the common idiom of writing a class like :
120
+
121
+ Examples
122
+ ========
123
+
124
+ >>> from sympy import Basic, SympifyError, S
125
+ >>> from sympy.core.sympify import _sympify
126
+
127
+ >>> class MyTuple(Basic):
128
+ ... def __add__(self, other):
129
+ ... try:
130
+ ... other = _sympify(other)
131
+ ... except SympifyError:
132
+ ... return NotImplemented
133
+ ... if not isinstance(other, MyTuple):
134
+ ... return NotImplemented
135
+ ... return MyTuple(*(self.args + other.args))
136
+
137
+ >>> MyTuple(S(1), S(2)) + MyTuple(S(3), S(4))
138
+ MyTuple(1, 2, 3, 4)
139
+
140
+ In the above it is important that we return NotImplemented when other is
141
+ not sympifiable and also when the sympified result is not of the expected
142
+ type. This allows the MyTuple class to be used cooperatively with other
143
+ classes that overload __add__ and want to do something else in combination
144
+ with instance of Tuple.
145
+
146
+ Using this decorator the above can be written as
147
+
148
+ >>> from sympy.core.decorators import sympify_method_args, sympify_return
149
+
150
+ >>> @sympify_method_args
151
+ ... class MyTuple(Basic):
152
+ ... @sympify_return([('other', 'MyTuple')], NotImplemented)
153
+ ... def __add__(self, other):
154
+ ... return MyTuple(*(self.args + other.args))
155
+
156
+ >>> MyTuple(S(1), S(2)) + MyTuple(S(3), S(4))
157
+ MyTuple(1, 2, 3, 4)
158
+
159
+ The idea here is that the decorators take care of the boiler-plate code
160
+ for making this happen in each method that potentially needs to accept
161
+ unsympified arguments. Then the body of e.g. the __add__ method can be
162
+ written without needing to worry about calling _sympify or checking the
163
+ type of the resulting object.
164
+
165
+ The parameters for sympify_return are a list of tuples of the form
166
+ (parameter_name, expected_type) and the value to return (e.g.
167
+ NotImplemented). The expected_type parameter can be a type e.g. Tuple or a
168
+ string 'Tuple'. Using a string is useful for specifying a Type within its
169
+ class body (as in the above example).
170
+
171
+ Notes: Currently sympify_return only works for methods that take a single
172
+ argument (not including self). Specifying an expected_type as a string
173
+ only works for the class in which the method is defined.
174
+ '''
175
+ # Extract the wrapped methods from each of the wrapper objects created by
176
+ # the sympify_return decorator. Doing this here allows us to provide the
177
+ # cls argument which is used for forward string referencing.
178
+ for attrname, obj in cls.__dict__.items():
179
+ if isinstance(obj, _SympifyWrapper):
180
+ setattr(cls, attrname, obj.make_wrapped(cls))
181
+ return cls
182
+
183
+
184
+ def sympify_return(*args):
185
+ '''Function/method decorator to sympify arguments automatically
186
+
187
+ See the docstring of sympify_method_args for explanation.
188
+ '''
189
+ # Store a wrapper object for the decorated method
190
+ def wrapper(func):
191
+ return _SympifyWrapper(func, args)
192
+ return wrapper
193
+
194
+
195
+ class _SympifyWrapper:
196
+ '''Internal class used by sympify_return and sympify_method_args'''
197
+
198
+ def __init__(self, func, args):
199
+ self.func = func
200
+ self.args = args
201
+
202
+ def make_wrapped(self, cls):
203
+ func = self.func
204
+ parameters, retval = self.args
205
+
206
+ # XXX: Handle more than one parameter?
207
+ [(parameter, expectedcls)] = parameters
208
+
209
+ # Handle forward references to the current class using strings
210
+ if expectedcls == cls.__name__:
211
+ expectedcls = cls
212
+
213
+ # Raise RuntimeError since this is a failure at import time and should
214
+ # not be recoverable.
215
+ nargs = func.__code__.co_argcount
216
+ # we support f(a, b) only
217
+ if nargs != 2:
218
+ raise RuntimeError('sympify_return can only be used with 2 argument functions')
219
+ # only b is _sympified
220
+ if func.__code__.co_varnames[1] != parameter:
221
+ raise RuntimeError('parameter name mismatch "%s" in %s' %
222
+ (parameter, func.__name__))
223
+
224
+ @wraps(func)
225
+ def _func(self, other):
226
+ # XXX: The check for _op_priority here should be removed. It is
227
+ # needed to stop mutable matrices from being sympified to
228
+ # immutable matrices which breaks things in quantum...
229
+ if not hasattr(other, '_op_priority'):
230
+ try:
231
+ other = sympify(other, strict=True)
232
+ except SympifyError:
233
+ return retval
234
+ if not isinstance(other, expectedcls):
235
+ return retval
236
+ return func(self, other)
237
+
238
+ return _func
lib/python3.12/site-packages/sympy/core/evalf.py ADDED
@@ -0,0 +1,1802 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Adaptive numerical evaluation of SymPy expressions, using mpmath
3
+ for mathematical functions.
4
+ """
5
+ from __future__ import annotations
6
+ from typing import Tuple as tTuple, Optional, Union as tUnion, Callable, List, Dict as tDict, Type, TYPE_CHECKING, \
7
+ Any, overload
8
+
9
+ import math
10
+
11
+ import mpmath.libmp as libmp
12
+ from mpmath import (
13
+ make_mpc, make_mpf, mp, mpc, mpf, nsum, quadts, quadosc, workprec)
14
+ from mpmath import inf as mpmath_inf
15
+ from mpmath.libmp import (from_int, from_man_exp, from_rational, fhalf,
16
+ fnan, finf, fninf, fnone, fone, fzero, mpf_abs, mpf_add,
17
+ mpf_atan, mpf_atan2, mpf_cmp, mpf_cos, mpf_e, mpf_exp, mpf_log, mpf_lt,
18
+ mpf_mul, mpf_neg, mpf_pi, mpf_pow, mpf_pow_int, mpf_shift, mpf_sin,
19
+ mpf_sqrt, normalize, round_nearest, to_int, to_str)
20
+ from mpmath.libmp import bitcount as mpmath_bitcount
21
+ from mpmath.libmp.backend import MPZ
22
+ from mpmath.libmp.libmpc import _infs_nan
23
+ from mpmath.libmp.libmpf import dps_to_prec, prec_to_dps
24
+
25
+ from .sympify import sympify
26
+ from .singleton import S
27
+ from sympy.external.gmpy import SYMPY_INTS
28
+ from sympy.utilities.iterables import is_sequence
29
+ from sympy.utilities.lambdify import lambdify
30
+ from sympy.utilities.misc import as_int
31
+
32
+ if TYPE_CHECKING:
33
+ from sympy.core.expr import Expr
34
+ from sympy.core.add import Add
35
+ from sympy.core.mul import Mul
36
+ from sympy.core.power import Pow
37
+ from sympy.core.symbol import Symbol
38
+ from sympy.integrals.integrals import Integral
39
+ from sympy.concrete.summations import Sum
40
+ from sympy.concrete.products import Product
41
+ from sympy.functions.elementary.exponential import exp, log
42
+ from sympy.functions.elementary.complexes import Abs, re, im
43
+ from sympy.functions.elementary.integers import ceiling, floor
44
+ from sympy.functions.elementary.trigonometric import atan
45
+ from .numbers import Float, Rational, Integer, AlgebraicNumber, Number
46
+
47
+ LG10 = math.log2(10)
48
+ rnd = round_nearest
49
+
50
+
51
+ def bitcount(n):
52
+ """Return smallest integer, b, such that |n|/2**b < 1.
53
+ """
54
+ return mpmath_bitcount(abs(int(n)))
55
+
56
+ # Used in a few places as placeholder values to denote exponents and
57
+ # precision levels, e.g. of exact numbers. Must be careful to avoid
58
+ # passing these to mpmath functions or returning them in final results.
59
+ INF = float(mpmath_inf)
60
+ MINUS_INF = float(-mpmath_inf)
61
+
62
+ # ~= 100 digits. Real men set this to INF.
63
+ DEFAULT_MAXPREC = 333
64
+
65
+
66
+ class PrecisionExhausted(ArithmeticError):
67
+ pass
68
+
69
+ #----------------------------------------------------------------------------#
70
+ # #
71
+ # Helper functions for arithmetic and complex parts #
72
+ # #
73
+ #----------------------------------------------------------------------------#
74
+
75
+ """
76
+ An mpf value tuple is a tuple of integers (sign, man, exp, bc)
77
+ representing a floating-point number: [1, -1][sign]*man*2**exp where
78
+ sign is 0 or 1 and bc should correspond to the number of bits used to
79
+ represent the mantissa (man) in binary notation, e.g.
80
+ """
81
+ MPF_TUP = tTuple[int, int, int, int] # mpf value tuple
82
+
83
+ """
84
+ Explanation
85
+ ===========
86
+
87
+ >>> from sympy.core.evalf import bitcount
88
+ >>> sign, man, exp, bc = 0, 5, 1, 3
89
+ >>> n = [1, -1][sign]*man*2**exp
90
+ >>> n, bitcount(man)
91
+ (10, 3)
92
+
93
+ A temporary result is a tuple (re, im, re_acc, im_acc) where
94
+ re and im are nonzero mpf value tuples representing approximate
95
+ numbers, or None to denote exact zeros.
96
+
97
+ re_acc, im_acc are integers denoting log2(e) where e is the estimated
98
+ relative accuracy of the respective complex part, but may be anything
99
+ if the corresponding complex part is None.
100
+
101
+ """
102
+ TMP_RES = Any # temporary result, should be some variant of
103
+ # tUnion[tTuple[Optional[MPF_TUP], Optional[MPF_TUP],
104
+ # Optional[int], Optional[int]],
105
+ # 'ComplexInfinity']
106
+ # but mypy reports error because it doesn't know as we know
107
+ # 1. re and re_acc are either both None or both MPF_TUP
108
+ # 2. sometimes the result can't be zoo
109
+
110
+ # type of the "options" parameter in internal evalf functions
111
+ OPT_DICT = tDict[str, Any]
112
+
113
+
114
+ def fastlog(x: Optional[MPF_TUP]) -> tUnion[int, Any]:
115
+ """Fast approximation of log2(x) for an mpf value tuple x.
116
+
117
+ Explanation
118
+ ===========
119
+
120
+ Calculated as exponent + width of mantissa. This is an
121
+ approximation for two reasons: 1) it gives the ceil(log2(abs(x)))
122
+ value and 2) it is too high by 1 in the case that x is an exact
123
+ power of 2. Although this is easy to remedy by testing to see if
124
+ the odd mpf mantissa is 1 (indicating that one was dealing with
125
+ an exact power of 2) that would decrease the speed and is not
126
+ necessary as this is only being used as an approximation for the
127
+ number of bits in x. The correct return value could be written as
128
+ "x[2] + (x[3] if x[1] != 1 else 0)".
129
+ Since mpf tuples always have an odd mantissa, no check is done
130
+ to see if the mantissa is a multiple of 2 (in which case the
131
+ result would be too large by 1).
132
+
133
+ Examples
134
+ ========
135
+
136
+ >>> from sympy import log
137
+ >>> from sympy.core.evalf import fastlog, bitcount
138
+ >>> s, m, e = 0, 5, 1
139
+ >>> bc = bitcount(m)
140
+ >>> n = [1, -1][s]*m*2**e
141
+ >>> n, (log(n)/log(2)).evalf(2), fastlog((s, m, e, bc))
142
+ (10, 3.3, 4)
143
+ """
144
+
145
+ if not x or x == fzero:
146
+ return MINUS_INF
147
+ return x[2] + x[3]
148
+
149
+
150
+ def pure_complex(v: 'Expr', or_real=False) -> tuple['Number', 'Number'] | None:
151
+ """Return a and b if v matches a + I*b where b is not zero and
152
+ a and b are Numbers, else None. If `or_real` is True then 0 will
153
+ be returned for `b` if `v` is a real number.
154
+
155
+ Examples
156
+ ========
157
+
158
+ >>> from sympy.core.evalf import pure_complex
159
+ >>> from sympy import sqrt, I, S
160
+ >>> a, b, surd = S(2), S(3), sqrt(2)
161
+ >>> pure_complex(a)
162
+ >>> pure_complex(a, or_real=True)
163
+ (2, 0)
164
+ >>> pure_complex(surd)
165
+ >>> pure_complex(a + b*I)
166
+ (2, 3)
167
+ >>> pure_complex(I)
168
+ (0, 1)
169
+ """
170
+ h, t = v.as_coeff_Add()
171
+ if t:
172
+ c, i = t.as_coeff_Mul()
173
+ if i is S.ImaginaryUnit:
174
+ return h, c
175
+ elif or_real:
176
+ return h, S.Zero
177
+ return None
178
+
179
+
180
+ # I don't know what this is, see function scaled_zero below
181
+ SCALED_ZERO_TUP = tTuple[List[int], int, int, int]
182
+
183
+
184
+ @overload
185
+ def scaled_zero(mag: SCALED_ZERO_TUP, sign=1) -> MPF_TUP:
186
+ ...
187
+ @overload
188
+ def scaled_zero(mag: int, sign=1) -> tTuple[SCALED_ZERO_TUP, int]:
189
+ ...
190
+ def scaled_zero(mag: tUnion[SCALED_ZERO_TUP, int], sign=1) -> \
191
+ tUnion[MPF_TUP, tTuple[SCALED_ZERO_TUP, int]]:
192
+ """Return an mpf representing a power of two with magnitude ``mag``
193
+ and -1 for precision. Or, if ``mag`` is a scaled_zero tuple, then just
194
+ remove the sign from within the list that it was initially wrapped
195
+ in.
196
+
197
+ Examples
198
+ ========
199
+
200
+ >>> from sympy.core.evalf import scaled_zero
201
+ >>> from sympy import Float
202
+ >>> z, p = scaled_zero(100)
203
+ >>> z, p
204
+ (([0], 1, 100, 1), -1)
205
+ >>> ok = scaled_zero(z)
206
+ >>> ok
207
+ (0, 1, 100, 1)
208
+ >>> Float(ok)
209
+ 1.26765060022823e+30
210
+ >>> Float(ok, p)
211
+ 0.e+30
212
+ >>> ok, p = scaled_zero(100, -1)
213
+ >>> Float(scaled_zero(ok), p)
214
+ -0.e+30
215
+ """
216
+ if isinstance(mag, tuple) and len(mag) == 4 and iszero(mag, scaled=True):
217
+ return (mag[0][0],) + mag[1:]
218
+ elif isinstance(mag, SYMPY_INTS):
219
+ if sign not in [-1, 1]:
220
+ raise ValueError('sign must be +/-1')
221
+ rv, p = mpf_shift(fone, mag), -1
222
+ s = 0 if sign == 1 else 1
223
+ rv = ([s],) + rv[1:]
224
+ return rv, p
225
+ else:
226
+ raise ValueError('scaled zero expects int or scaled_zero tuple.')
227
+
228
+
229
+ def iszero(mpf: tUnion[MPF_TUP, SCALED_ZERO_TUP, None], scaled=False) -> Optional[bool]:
230
+ if not scaled:
231
+ return not mpf or not mpf[1] and not mpf[-1]
232
+ return mpf and isinstance(mpf[0], list) and mpf[1] == mpf[-1] == 1
233
+
234
+
235
+ def complex_accuracy(result: TMP_RES) -> tUnion[int, Any]:
236
+ """
237
+ Returns relative accuracy of a complex number with given accuracies
238
+ for the real and imaginary parts. The relative accuracy is defined
239
+ in the complex norm sense as ||z|+|error|| / |z| where error
240
+ is equal to (real absolute error) + (imag absolute error)*i.
241
+
242
+ The full expression for the (logarithmic) error can be approximated
243
+ easily by using the max norm to approximate the complex norm.
244
+
245
+ In the worst case (re and im equal), this is wrong by a factor
246
+ sqrt(2), or by log2(sqrt(2)) = 0.5 bit.
247
+ """
248
+ if result is S.ComplexInfinity:
249
+ return INF
250
+ re, im, re_acc, im_acc = result
251
+ if not im:
252
+ if not re:
253
+ return INF
254
+ return re_acc
255
+ if not re:
256
+ return im_acc
257
+ re_size = fastlog(re)
258
+ im_size = fastlog(im)
259
+ absolute_error = max(re_size - re_acc, im_size - im_acc)
260
+ relative_error = absolute_error - max(re_size, im_size)
261
+ return -relative_error
262
+
263
+
264
+ def get_abs(expr: 'Expr', prec: int, options: OPT_DICT) -> TMP_RES:
265
+ result = evalf(expr, prec + 2, options)
266
+ if result is S.ComplexInfinity:
267
+ return finf, None, prec, None
268
+ re, im, re_acc, im_acc = result
269
+ if not re:
270
+ re, re_acc, im, im_acc = im, im_acc, re, re_acc
271
+ if im:
272
+ if expr.is_number:
273
+ abs_expr, _, acc, _ = evalf(abs(N(expr, prec + 2)),
274
+ prec + 2, options)
275
+ return abs_expr, None, acc, None
276
+ else:
277
+ if 'subs' in options:
278
+ return libmp.mpc_abs((re, im), prec), None, re_acc, None
279
+ return abs(expr), None, prec, None
280
+ elif re:
281
+ return mpf_abs(re), None, re_acc, None
282
+ else:
283
+ return None, None, None, None
284
+
285
+
286
+ def get_complex_part(expr: 'Expr', no: int, prec: int, options: OPT_DICT) -> TMP_RES:
287
+ """no = 0 for real part, no = 1 for imaginary part"""
288
+ workprec = prec
289
+ i = 0
290
+ while 1:
291
+ res = evalf(expr, workprec, options)
292
+ if res is S.ComplexInfinity:
293
+ return fnan, None, prec, None
294
+ value, accuracy = res[no::2]
295
+ # XXX is the last one correct? Consider re((1+I)**2).n()
296
+ if (not value) or accuracy >= prec or -value[2] > prec:
297
+ return value, None, accuracy, None
298
+ workprec += max(30, 2**i)
299
+ i += 1
300
+
301
+
302
+ def evalf_abs(expr: 'Abs', prec: int, options: OPT_DICT) -> TMP_RES:
303
+ return get_abs(expr.args[0], prec, options)
304
+
305
+
306
+ def evalf_re(expr: 're', prec: int, options: OPT_DICT) -> TMP_RES:
307
+ return get_complex_part(expr.args[0], 0, prec, options)
308
+
309
+
310
+ def evalf_im(expr: 'im', prec: int, options: OPT_DICT) -> TMP_RES:
311
+ return get_complex_part(expr.args[0], 1, prec, options)
312
+
313
+
314
+ def finalize_complex(re: MPF_TUP, im: MPF_TUP, prec: int) -> TMP_RES:
315
+ if re == fzero and im == fzero:
316
+ raise ValueError("got complex zero with unknown accuracy")
317
+ elif re == fzero:
318
+ return None, im, None, prec
319
+ elif im == fzero:
320
+ return re, None, prec, None
321
+
322
+ size_re = fastlog(re)
323
+ size_im = fastlog(im)
324
+ if size_re > size_im:
325
+ re_acc = prec
326
+ im_acc = prec + min(-(size_re - size_im), 0)
327
+ else:
328
+ im_acc = prec
329
+ re_acc = prec + min(-(size_im - size_re), 0)
330
+ return re, im, re_acc, im_acc
331
+
332
+
333
+ def chop_parts(value: TMP_RES, prec: int) -> TMP_RES:
334
+ """
335
+ Chop off tiny real or complex parts.
336
+ """
337
+ if value is S.ComplexInfinity:
338
+ return value
339
+ re, im, re_acc, im_acc = value
340
+ # Method 1: chop based on absolute value
341
+ if re and re not in _infs_nan and (fastlog(re) < -prec + 4):
342
+ re, re_acc = None, None
343
+ if im and im not in _infs_nan and (fastlog(im) < -prec + 4):
344
+ im, im_acc = None, None
345
+ # Method 2: chop if inaccurate and relatively small
346
+ if re and im:
347
+ delta = fastlog(re) - fastlog(im)
348
+ if re_acc < 2 and (delta - re_acc <= -prec + 4):
349
+ re, re_acc = None, None
350
+ if im_acc < 2 and (delta - im_acc >= prec - 4):
351
+ im, im_acc = None, None
352
+ return re, im, re_acc, im_acc
353
+
354
+
355
+ def check_target(expr: 'Expr', result: TMP_RES, prec: int):
356
+ a = complex_accuracy(result)
357
+ if a < prec:
358
+ raise PrecisionExhausted("Failed to distinguish the expression: \n\n%s\n\n"
359
+ "from zero. Try simplifying the input, using chop=True, or providing "
360
+ "a higher maxn for evalf" % (expr))
361
+
362
+
363
+ def get_integer_part(expr: 'Expr', no: int, options: OPT_DICT, return_ints=False) -> \
364
+ tUnion[TMP_RES, tTuple[int, int]]:
365
+ """
366
+ With no = 1, computes ceiling(expr)
367
+ With no = -1, computes floor(expr)
368
+
369
+ Note: this function either gives the exact result or signals failure.
370
+ """
371
+ from sympy.functions.elementary.complexes import re, im
372
+ # The expression is likely less than 2^30 or so
373
+ assumed_size = 30
374
+ result = evalf(expr, assumed_size, options)
375
+ if result is S.ComplexInfinity:
376
+ raise ValueError("Cannot get integer part of Complex Infinity")
377
+ ire, iim, ire_acc, iim_acc = result
378
+
379
+ # We now know the size, so we can calculate how much extra precision
380
+ # (if any) is needed to get within the nearest integer
381
+ if ire and iim:
382
+ gap = max(fastlog(ire) - ire_acc, fastlog(iim) - iim_acc)
383
+ elif ire:
384
+ gap = fastlog(ire) - ire_acc
385
+ elif iim:
386
+ gap = fastlog(iim) - iim_acc
387
+ else:
388
+ # ... or maybe the expression was exactly zero
389
+ if return_ints:
390
+ return 0, 0
391
+ else:
392
+ return None, None, None, None
393
+
394
+ margin = 10
395
+
396
+ if gap >= -margin:
397
+ prec = margin + assumed_size + gap
398
+ ire, iim, ire_acc, iim_acc = evalf(
399
+ expr, prec, options)
400
+ else:
401
+ prec = assumed_size
402
+
403
+ # We can now easily find the nearest integer, but to find floor/ceil, we
404
+ # must also calculate whether the difference to the nearest integer is
405
+ # positive or negative (which may fail if very close).
406
+ def calc_part(re_im: 'Expr', nexpr: MPF_TUP):
407
+ from .add import Add
408
+ _, _, exponent, _ = nexpr
409
+ is_int = exponent == 0
410
+ nint = int(to_int(nexpr, rnd))
411
+ if is_int:
412
+ # make sure that we had enough precision to distinguish
413
+ # between nint and the re or im part (re_im) of expr that
414
+ # was passed to calc_part
415
+ ire, iim, ire_acc, iim_acc = evalf(
416
+ re_im - nint, 10, options) # don't need much precision
417
+ assert not iim
418
+ size = -fastlog(ire) + 2 # -ve b/c ire is less than 1
419
+ if size > prec:
420
+ ire, iim, ire_acc, iim_acc = evalf(
421
+ re_im, size, options)
422
+ assert not iim
423
+ nexpr = ire
424
+ nint = int(to_int(nexpr, rnd))
425
+ _, _, new_exp, _ = ire
426
+ is_int = new_exp == 0
427
+ if not is_int:
428
+ # if there are subs and they all contain integer re/im parts
429
+ # then we can (hopefully) safely substitute them into the
430
+ # expression
431
+ s = options.get('subs', False)
432
+ if s:
433
+ # use strict=False with as_int because we take
434
+ # 2.0 == 2
435
+ def is_int_reim(x):
436
+ """Check for integer or integer + I*integer."""
437
+ try:
438
+ as_int(x, strict=False)
439
+ return True
440
+ except ValueError:
441
+ try:
442
+ [as_int(i, strict=False) for i in x.as_real_imag()]
443
+ return True
444
+ except ValueError:
445
+ return False
446
+
447
+ if all(is_int_reim(v) for v in s.values()):
448
+ re_im = re_im.subs(s)
449
+
450
+ re_im = Add(re_im, -nint, evaluate=False)
451
+ x, _, x_acc, _ = evalf(re_im, 10, options)
452
+ try:
453
+ check_target(re_im, (x, None, x_acc, None), 3)
454
+ except PrecisionExhausted:
455
+ if not re_im.equals(0):
456
+ raise PrecisionExhausted
457
+ x = fzero
458
+ nint += int(no*(mpf_cmp(x or fzero, fzero) == no))
459
+ nint = from_int(nint)
460
+ return nint, INF
461
+
462
+ re_, im_, re_acc, im_acc = None, None, None, None
463
+
464
+ if ire:
465
+ re_, re_acc = calc_part(re(expr, evaluate=False), ire)
466
+ if iim:
467
+ im_, im_acc = calc_part(im(expr, evaluate=False), iim)
468
+
469
+ if return_ints:
470
+ return int(to_int(re_ or fzero)), int(to_int(im_ or fzero))
471
+ return re_, im_, re_acc, im_acc
472
+
473
+
474
+ def evalf_ceiling(expr: 'ceiling', prec: int, options: OPT_DICT) -> TMP_RES:
475
+ return get_integer_part(expr.args[0], 1, options)
476
+
477
+
478
+ def evalf_floor(expr: 'floor', prec: int, options: OPT_DICT) -> TMP_RES:
479
+ return get_integer_part(expr.args[0], -1, options)
480
+
481
+
482
+ def evalf_float(expr: 'Float', prec: int, options: OPT_DICT) -> TMP_RES:
483
+ return expr._mpf_, None, prec, None
484
+
485
+
486
+ def evalf_rational(expr: 'Rational', prec: int, options: OPT_DICT) -> TMP_RES:
487
+ return from_rational(expr.p, expr.q, prec), None, prec, None
488
+
489
+
490
+ def evalf_integer(expr: 'Integer', prec: int, options: OPT_DICT) -> TMP_RES:
491
+ return from_int(expr.p, prec), None, prec, None
492
+
493
+ #----------------------------------------------------------------------------#
494
+ # #
495
+ # Arithmetic operations #
496
+ # #
497
+ #----------------------------------------------------------------------------#
498
+
499
+
500
+ def add_terms(terms: list, prec: int, target_prec: int) -> \
501
+ tTuple[tUnion[MPF_TUP, SCALED_ZERO_TUP, None], Optional[int]]:
502
+ """
503
+ Helper for evalf_add. Adds a list of (mpfval, accuracy) terms.
504
+
505
+ Returns
506
+ =======
507
+
508
+ - None, None if there are no non-zero terms;
509
+ - terms[0] if there is only 1 term;
510
+ - scaled_zero if the sum of the terms produces a zero by cancellation
511
+ e.g. mpfs representing 1 and -1 would produce a scaled zero which need
512
+ special handling since they are not actually zero and they are purposely
513
+ malformed to ensure that they cannot be used in anything but accuracy
514
+ calculations;
515
+ - a tuple that is scaled to target_prec that corresponds to the
516
+ sum of the terms.
517
+
518
+ The returned mpf tuple will be normalized to target_prec; the input
519
+ prec is used to define the working precision.
520
+
521
+ XXX explain why this is needed and why one cannot just loop using mpf_add
522
+ """
523
+
524
+ terms = [t for t in terms if not iszero(t[0])]
525
+ if not terms:
526
+ return None, None
527
+ elif len(terms) == 1:
528
+ return terms[0]
529
+
530
+ # see if any argument is NaN or oo and thus warrants a special return
531
+ special = []
532
+ from .numbers import Float
533
+ for t in terms:
534
+ arg = Float._new(t[0], 1)
535
+ if arg is S.NaN or arg.is_infinite:
536
+ special.append(arg)
537
+ if special:
538
+ from .add import Add
539
+ rv = evalf(Add(*special), prec + 4, {})
540
+ return rv[0], rv[2]
541
+
542
+ working_prec = 2*prec
543
+ sum_man, sum_exp = 0, 0
544
+ absolute_err: List[int] = []
545
+
546
+ for x, accuracy in terms:
547
+ sign, man, exp, bc = x
548
+ if sign:
549
+ man = -man
550
+ absolute_err.append(bc + exp - accuracy)
551
+ delta = exp - sum_exp
552
+ if exp >= sum_exp:
553
+ # x much larger than existing sum?
554
+ # first: quick test
555
+ if ((delta > working_prec) and
556
+ ((not sum_man) or
557
+ delta - bitcount(abs(sum_man)) > working_prec)):
558
+ sum_man = man
559
+ sum_exp = exp
560
+ else:
561
+ sum_man += (man << delta)
562
+ else:
563
+ delta = -delta
564
+ # x much smaller than existing sum?
565
+ if delta - bc > working_prec:
566
+ if not sum_man:
567
+ sum_man, sum_exp = man, exp
568
+ else:
569
+ sum_man = (sum_man << delta) + man
570
+ sum_exp = exp
571
+ absolute_error = max(absolute_err)
572
+ if not sum_man:
573
+ return scaled_zero(absolute_error)
574
+ if sum_man < 0:
575
+ sum_sign = 1
576
+ sum_man = -sum_man
577
+ else:
578
+ sum_sign = 0
579
+ sum_bc = bitcount(sum_man)
580
+ sum_accuracy = sum_exp + sum_bc - absolute_error
581
+ r = normalize(sum_sign, sum_man, sum_exp, sum_bc, target_prec,
582
+ rnd), sum_accuracy
583
+ return r
584
+
585
+
586
+ def evalf_add(v: 'Add', prec: int, options: OPT_DICT) -> TMP_RES:
587
+ res = pure_complex(v)
588
+ if res:
589
+ h, c = res
590
+ re, _, re_acc, _ = evalf(h, prec, options)
591
+ im, _, im_acc, _ = evalf(c, prec, options)
592
+ return re, im, re_acc, im_acc
593
+
594
+ oldmaxprec = options.get('maxprec', DEFAULT_MAXPREC)
595
+
596
+ i = 0
597
+ target_prec = prec
598
+ while 1:
599
+ options['maxprec'] = min(oldmaxprec, 2*prec)
600
+
601
+ terms = [evalf(arg, prec + 10, options) for arg in v.args]
602
+ n = terms.count(S.ComplexInfinity)
603
+ if n >= 2:
604
+ return fnan, None, prec, None
605
+ re, re_acc = add_terms(
606
+ [a[0::2] for a in terms if isinstance(a, tuple) and a[0]], prec, target_prec)
607
+ im, im_acc = add_terms(
608
+ [a[1::2] for a in terms if isinstance(a, tuple) and a[1]], prec, target_prec)
609
+ if n == 1:
610
+ if re in (finf, fninf, fnan) or im in (finf, fninf, fnan):
611
+ return fnan, None, prec, None
612
+ return S.ComplexInfinity
613
+ acc = complex_accuracy((re, im, re_acc, im_acc))
614
+ if acc >= target_prec:
615
+ if options.get('verbose'):
616
+ print("ADD: wanted", target_prec, "accurate bits, got", re_acc, im_acc)
617
+ break
618
+ else:
619
+ if (prec - target_prec) > options['maxprec']:
620
+ break
621
+
622
+ prec = prec + max(10 + 2**i, target_prec - acc)
623
+ i += 1
624
+ if options.get('verbose'):
625
+ print("ADD: restarting with prec", prec)
626
+
627
+ options['maxprec'] = oldmaxprec
628
+ if iszero(re, scaled=True):
629
+ re = scaled_zero(re)
630
+ if iszero(im, scaled=True):
631
+ im = scaled_zero(im)
632
+ return re, im, re_acc, im_acc
633
+
634
+
635
+ def evalf_mul(v: 'Mul', prec: int, options: OPT_DICT) -> TMP_RES:
636
+ res = pure_complex(v)
637
+ if res:
638
+ # the only pure complex that is a mul is h*I
639
+ _, h = res
640
+ im, _, im_acc, _ = evalf(h, prec, options)
641
+ return None, im, None, im_acc
642
+ args = list(v.args)
643
+
644
+ # see if any argument is NaN or oo and thus warrants a special return
645
+ has_zero = False
646
+ special = []
647
+ from .numbers import Float
648
+ for arg in args:
649
+ result = evalf(arg, prec, options)
650
+ if result is S.ComplexInfinity:
651
+ special.append(result)
652
+ continue
653
+ if result[0] is None:
654
+ if result[1] is None:
655
+ has_zero = True
656
+ continue
657
+ num = Float._new(result[0], 1)
658
+ if num is S.NaN:
659
+ return fnan, None, prec, None
660
+ if num.is_infinite:
661
+ special.append(num)
662
+ if special:
663
+ if has_zero:
664
+ return fnan, None, prec, None
665
+ from .mul import Mul
666
+ return evalf(Mul(*special), prec + 4, {})
667
+ if has_zero:
668
+ return None, None, None, None
669
+
670
+ # With guard digits, multiplication in the real case does not destroy
671
+ # accuracy. This is also true in the complex case when considering the
672
+ # total accuracy; however accuracy for the real or imaginary parts
673
+ # separately may be lower.
674
+ acc = prec
675
+
676
+ # XXX: big overestimate
677
+ working_prec = prec + len(args) + 5
678
+
679
+ # Empty product is 1
680
+ start = man, exp, bc = MPZ(1), 0, 1
681
+
682
+ # First, we multiply all pure real or pure imaginary numbers.
683
+ # direction tells us that the result should be multiplied by
684
+ # I**direction; all other numbers get put into complex_factors
685
+ # to be multiplied out after the first phase.
686
+ last = len(args)
687
+ direction = 0
688
+ args.append(S.One)
689
+ complex_factors = []
690
+
691
+ for i, arg in enumerate(args):
692
+ if i != last and pure_complex(arg):
693
+ args[-1] = (args[-1]*arg).expand()
694
+ continue
695
+ elif i == last and arg is S.One:
696
+ continue
697
+ re, im, re_acc, im_acc = evalf(arg, working_prec, options)
698
+ if re and im:
699
+ complex_factors.append((re, im, re_acc, im_acc))
700
+ continue
701
+ elif re:
702
+ (s, m, e, b), w_acc = re, re_acc
703
+ elif im:
704
+ (s, m, e, b), w_acc = im, im_acc
705
+ direction += 1
706
+ else:
707
+ return None, None, None, None
708
+ direction += 2*s
709
+ man *= m
710
+ exp += e
711
+ bc += b
712
+ while bc > 3*working_prec:
713
+ man >>= working_prec
714
+ exp += working_prec
715
+ bc -= working_prec
716
+ acc = min(acc, w_acc)
717
+ sign = (direction & 2) >> 1
718
+ if not complex_factors:
719
+ v = normalize(sign, man, exp, bitcount(man), prec, rnd)
720
+ # multiply by i
721
+ if direction & 1:
722
+ return None, v, None, acc
723
+ else:
724
+ return v, None, acc, None
725
+ else:
726
+ # initialize with the first term
727
+ if (man, exp, bc) != start:
728
+ # there was a real part; give it an imaginary part
729
+ re, im = (sign, man, exp, bitcount(man)), (0, MPZ(0), 0, 0)
730
+ i0 = 0
731
+ else:
732
+ # there is no real part to start (other than the starting 1)
733
+ wre, wim, wre_acc, wim_acc = complex_factors[0]
734
+ acc = min(acc,
735
+ complex_accuracy((wre, wim, wre_acc, wim_acc)))
736
+ re = wre
737
+ im = wim
738
+ i0 = 1
739
+
740
+ for wre, wim, wre_acc, wim_acc in complex_factors[i0:]:
741
+ # acc is the overall accuracy of the product; we aren't
742
+ # computing exact accuracies of the product.
743
+ acc = min(acc,
744
+ complex_accuracy((wre, wim, wre_acc, wim_acc)))
745
+
746
+ use_prec = working_prec
747
+ A = mpf_mul(re, wre, use_prec)
748
+ B = mpf_mul(mpf_neg(im), wim, use_prec)
749
+ C = mpf_mul(re, wim, use_prec)
750
+ D = mpf_mul(im, wre, use_prec)
751
+ re = mpf_add(A, B, use_prec)
752
+ im = mpf_add(C, D, use_prec)
753
+ if options.get('verbose'):
754
+ print("MUL: wanted", prec, "accurate bits, got", acc)
755
+ # multiply by I
756
+ if direction & 1:
757
+ re, im = mpf_neg(im), re
758
+ return re, im, acc, acc
759
+
760
+
761
+ def evalf_pow(v: 'Pow', prec: int, options) -> TMP_RES:
762
+
763
+ target_prec = prec
764
+ base, exp = v.args
765
+
766
+ # We handle x**n separately. This has two purposes: 1) it is much
767
+ # faster, because we avoid calling evalf on the exponent, and 2) it
768
+ # allows better handling of real/imaginary parts that are exactly zero
769
+ if exp.is_Integer:
770
+ p: int = exp.p # type: ignore
771
+ # Exact
772
+ if not p:
773
+ return fone, None, prec, None
774
+ # Exponentiation by p magnifies relative error by |p|, so the
775
+ # base must be evaluated with increased precision if p is large
776
+ prec += int(math.log2(abs(p)))
777
+ result = evalf(base, prec + 5, options)
778
+ if result is S.ComplexInfinity:
779
+ if p < 0:
780
+ return None, None, None, None
781
+ return result
782
+ re, im, re_acc, im_acc = result
783
+ # Real to integer power
784
+ if re and not im:
785
+ return mpf_pow_int(re, p, target_prec), None, target_prec, None
786
+ # (x*I)**n = I**n * x**n
787
+ if im and not re:
788
+ z = mpf_pow_int(im, p, target_prec)
789
+ case = p % 4
790
+ if case == 0:
791
+ return z, None, target_prec, None
792
+ if case == 1:
793
+ return None, z, None, target_prec
794
+ if case == 2:
795
+ return mpf_neg(z), None, target_prec, None
796
+ if case == 3:
797
+ return None, mpf_neg(z), None, target_prec
798
+ # Zero raised to an integer power
799
+ if not re:
800
+ if p < 0:
801
+ return S.ComplexInfinity
802
+ return None, None, None, None
803
+ # General complex number to arbitrary integer power
804
+ re, im = libmp.mpc_pow_int((re, im), p, prec)
805
+ # Assumes full accuracy in input
806
+ return finalize_complex(re, im, target_prec)
807
+
808
+ result = evalf(base, prec + 5, options)
809
+ if result is S.ComplexInfinity:
810
+ if exp.is_Rational:
811
+ if exp < 0:
812
+ return None, None, None, None
813
+ return result
814
+ raise NotImplementedError
815
+
816
+ # Pure square root
817
+ if exp is S.Half:
818
+ xre, xim, _, _ = result
819
+ # General complex square root
820
+ if xim:
821
+ re, im = libmp.mpc_sqrt((xre or fzero, xim), prec)
822
+ return finalize_complex(re, im, prec)
823
+ if not xre:
824
+ return None, None, None, None
825
+ # Square root of a negative real number
826
+ if mpf_lt(xre, fzero):
827
+ return None, mpf_sqrt(mpf_neg(xre), prec), None, prec
828
+ # Positive square root
829
+ return mpf_sqrt(xre, prec), None, prec, None
830
+
831
+ # We first evaluate the exponent to find its magnitude
832
+ # This determines the working precision that must be used
833
+ prec += 10
834
+ result = evalf(exp, prec, options)
835
+ if result is S.ComplexInfinity:
836
+ return fnan, None, prec, None
837
+ yre, yim, _, _ = result
838
+ # Special cases: x**0
839
+ if not (yre or yim):
840
+ return fone, None, prec, None
841
+
842
+ ysize = fastlog(yre)
843
+ # Restart if too big
844
+ # XXX: prec + ysize might exceed maxprec
845
+ if ysize > 5:
846
+ prec += ysize
847
+ yre, yim, _, _ = evalf(exp, prec, options)
848
+
849
+ # Pure exponential function; no need to evalf the base
850
+ if base is S.Exp1:
851
+ if yim:
852
+ re, im = libmp.mpc_exp((yre or fzero, yim), prec)
853
+ return finalize_complex(re, im, target_prec)
854
+ return mpf_exp(yre, target_prec), None, target_prec, None
855
+
856
+ xre, xim, _, _ = evalf(base, prec + 5, options)
857
+ # 0**y
858
+ if not (xre or xim):
859
+ if yim:
860
+ return fnan, None, prec, None
861
+ if yre[0] == 1: # y < 0
862
+ return S.ComplexInfinity
863
+ return None, None, None, None
864
+
865
+ # (real ** complex) or (complex ** complex)
866
+ if yim:
867
+ re, im = libmp.mpc_pow(
868
+ (xre or fzero, xim or fzero), (yre or fzero, yim),
869
+ target_prec)
870
+ return finalize_complex(re, im, target_prec)
871
+ # complex ** real
872
+ if xim:
873
+ re, im = libmp.mpc_pow_mpf((xre or fzero, xim), yre, target_prec)
874
+ return finalize_complex(re, im, target_prec)
875
+ # negative ** real
876
+ elif mpf_lt(xre, fzero):
877
+ re, im = libmp.mpc_pow_mpf((xre, fzero), yre, target_prec)
878
+ return finalize_complex(re, im, target_prec)
879
+ # positive ** real
880
+ else:
881
+ return mpf_pow(xre, yre, target_prec), None, target_prec, None
882
+
883
+
884
+ #----------------------------------------------------------------------------#
885
+ # #
886
+ # Special functions #
887
+ # #
888
+ #----------------------------------------------------------------------------#
889
+
890
+
891
+ def evalf_exp(expr: 'exp', prec: int, options: OPT_DICT) -> TMP_RES:
892
+ from .power import Pow
893
+ return evalf_pow(Pow(S.Exp1, expr.exp, evaluate=False), prec, options)
894
+
895
+
896
+ def evalf_trig(v: 'Expr', prec: int, options: OPT_DICT) -> TMP_RES:
897
+ """
898
+ This function handles sin and cos of complex arguments.
899
+
900
+ TODO: should also handle tan of complex arguments.
901
+ """
902
+ from sympy.functions.elementary.trigonometric import cos, sin
903
+ if isinstance(v, cos):
904
+ func = mpf_cos
905
+ elif isinstance(v, sin):
906
+ func = mpf_sin
907
+ else:
908
+ raise NotImplementedError
909
+ arg = v.args[0]
910
+ # 20 extra bits is possibly overkill. It does make the need
911
+ # to restart very unlikely
912
+ xprec = prec + 20
913
+ re, im, re_acc, im_acc = evalf(arg, xprec, options)
914
+ if im:
915
+ if 'subs' in options:
916
+ v = v.subs(options['subs'])
917
+ return evalf(v._eval_evalf(prec), prec, options)
918
+ if not re:
919
+ if isinstance(v, cos):
920
+ return fone, None, prec, None
921
+ elif isinstance(v, sin):
922
+ return None, None, None, None
923
+ else:
924
+ raise NotImplementedError
925
+ # For trigonometric functions, we are interested in the
926
+ # fixed-point (absolute) accuracy of the argument.
927
+ xsize = fastlog(re)
928
+ # Magnitude <= 1.0. OK to compute directly, because there is no
929
+ # danger of hitting the first root of cos (with sin, magnitude
930
+ # <= 2.0 would actually be ok)
931
+ if xsize < 1:
932
+ return func(re, prec, rnd), None, prec, None
933
+ # Very large
934
+ if xsize >= 10:
935
+ xprec = prec + xsize
936
+ re, im, re_acc, im_acc = evalf(arg, xprec, options)
937
+ # Need to repeat in case the argument is very close to a
938
+ # multiple of pi (or pi/2), hitting close to a root
939
+ while 1:
940
+ y = func(re, prec, rnd)
941
+ ysize = fastlog(y)
942
+ gap = -ysize
943
+ accuracy = (xprec - xsize) - gap
944
+ if accuracy < prec:
945
+ if options.get('verbose'):
946
+ print("SIN/COS", accuracy, "wanted", prec, "gap", gap)
947
+ print(to_str(y, 10))
948
+ if xprec > options.get('maxprec', DEFAULT_MAXPREC):
949
+ return y, None, accuracy, None
950
+ xprec += gap
951
+ re, im, re_acc, im_acc = evalf(arg, xprec, options)
952
+ continue
953
+ else:
954
+ return y, None, prec, None
955
+
956
+
957
+ def evalf_log(expr: 'log', prec: int, options: OPT_DICT) -> TMP_RES:
958
+ if len(expr.args)>1:
959
+ expr = expr.doit()
960
+ return evalf(expr, prec, options)
961
+ arg = expr.args[0]
962
+ workprec = prec + 10
963
+ result = evalf(arg, workprec, options)
964
+ if result is S.ComplexInfinity:
965
+ return result
966
+ xre, xim, xacc, _ = result
967
+
968
+ # evalf can return NoneTypes if chop=True
969
+ # issue 18516, 19623
970
+ if xre is xim is None:
971
+ # Dear reviewer, I do not know what -inf is;
972
+ # it looks to be (1, 0, -789, -3)
973
+ # but I'm not sure in general,
974
+ # so we just let mpmath figure
975
+ # it out by taking log of 0 directly.
976
+ # It would be better to return -inf instead.
977
+ xre = fzero
978
+
979
+ if xim:
980
+ from sympy.functions.elementary.complexes import Abs
981
+ from sympy.functions.elementary.exponential import log
982
+
983
+ # XXX: use get_abs etc instead
984
+ re = evalf_log(
985
+ log(Abs(arg, evaluate=False), evaluate=False), prec, options)
986
+ im = mpf_atan2(xim, xre or fzero, prec)
987
+ return re[0], im, re[2], prec
988
+
989
+ imaginary_term = (mpf_cmp(xre, fzero) < 0)
990
+
991
+ re = mpf_log(mpf_abs(xre), prec, rnd)
992
+ size = fastlog(re)
993
+ if prec - size > workprec and re != fzero:
994
+ from .add import Add
995
+ # We actually need to compute 1+x accurately, not x
996
+ add = Add(S.NegativeOne, arg, evaluate=False)
997
+ xre, xim, _, _ = evalf_add(add, prec, options)
998
+ prec2 = workprec - fastlog(xre)
999
+ # xre is now x - 1 so we add 1 back here to calculate x
1000
+ re = mpf_log(mpf_abs(mpf_add(xre, fone, prec2)), prec, rnd)
1001
+
1002
+ re_acc = prec
1003
+
1004
+ if imaginary_term:
1005
+ return re, mpf_pi(prec), re_acc, prec
1006
+ else:
1007
+ return re, None, re_acc, None
1008
+
1009
+
1010
+ def evalf_atan(v: 'atan', prec: int, options: OPT_DICT) -> TMP_RES:
1011
+ arg = v.args[0]
1012
+ xre, xim, reacc, imacc = evalf(arg, prec + 5, options)
1013
+ if xre is xim is None:
1014
+ return (None,)*4
1015
+ if xim:
1016
+ raise NotImplementedError
1017
+ return mpf_atan(xre, prec, rnd), None, prec, None
1018
+
1019
+
1020
+ def evalf_subs(prec: int, subs: dict) -> dict:
1021
+ """ Change all Float entries in `subs` to have precision prec. """
1022
+ newsubs = {}
1023
+ for a, b in subs.items():
1024
+ b = S(b)
1025
+ if b.is_Float:
1026
+ b = b._eval_evalf(prec)
1027
+ newsubs[a] = b
1028
+ return newsubs
1029
+
1030
+
1031
+ def evalf_piecewise(expr: 'Expr', prec: int, options: OPT_DICT) -> TMP_RES:
1032
+ from .numbers import Float, Integer
1033
+ if 'subs' in options:
1034
+ expr = expr.subs(evalf_subs(prec, options['subs']))
1035
+ newopts = options.copy()
1036
+ del newopts['subs']
1037
+ if hasattr(expr, 'func'):
1038
+ return evalf(expr, prec, newopts)
1039
+ if isinstance(expr, float):
1040
+ return evalf(Float(expr), prec, newopts)
1041
+ if isinstance(expr, int):
1042
+ return evalf(Integer(expr), prec, newopts)
1043
+
1044
+ # We still have undefined symbols
1045
+ raise NotImplementedError
1046
+
1047
+
1048
+ def evalf_alg_num(a: 'AlgebraicNumber', prec: int, options: OPT_DICT) -> TMP_RES:
1049
+ return evalf(a.to_root(), prec, options)
1050
+
1051
+ #----------------------------------------------------------------------------#
1052
+ # #
1053
+ # High-level operations #
1054
+ # #
1055
+ #----------------------------------------------------------------------------#
1056
+
1057
+
1058
+ def as_mpmath(x: Any, prec: int, options: OPT_DICT) -> tUnion[mpc, mpf]:
1059
+ from .numbers import Infinity, NegativeInfinity, Zero
1060
+ x = sympify(x)
1061
+ if isinstance(x, Zero) or x == 0.0:
1062
+ return mpf(0)
1063
+ if isinstance(x, Infinity):
1064
+ return mpf('inf')
1065
+ if isinstance(x, NegativeInfinity):
1066
+ return mpf('-inf')
1067
+ # XXX
1068
+ result = evalf(x, prec, options)
1069
+ return quad_to_mpmath(result)
1070
+
1071
+
1072
+ def do_integral(expr: 'Integral', prec: int, options: OPT_DICT) -> TMP_RES:
1073
+ func = expr.args[0]
1074
+ x, xlow, xhigh = expr.args[1]
1075
+ if xlow == xhigh:
1076
+ xlow = xhigh = 0
1077
+ elif x not in func.free_symbols:
1078
+ # only the difference in limits matters in this case
1079
+ # so if there is a symbol in common that will cancel
1080
+ # out when taking the difference, then use that
1081
+ # difference
1082
+ if xhigh.free_symbols & xlow.free_symbols:
1083
+ diff = xhigh - xlow
1084
+ if diff.is_number:
1085
+ xlow, xhigh = 0, diff
1086
+
1087
+ oldmaxprec = options.get('maxprec', DEFAULT_MAXPREC)
1088
+ options['maxprec'] = min(oldmaxprec, 2*prec)
1089
+
1090
+ with workprec(prec + 5):
1091
+ xlow = as_mpmath(xlow, prec + 15, options)
1092
+ xhigh = as_mpmath(xhigh, prec + 15, options)
1093
+
1094
+ # Integration is like summation, and we can phone home from
1095
+ # the integrand function to update accuracy summation style
1096
+ # Note that this accuracy is inaccurate, since it fails
1097
+ # to account for the variable quadrature weights,
1098
+ # but it is better than nothing
1099
+
1100
+ from sympy.functions.elementary.trigonometric import cos, sin
1101
+ from .symbol import Wild
1102
+
1103
+ have_part = [False, False]
1104
+ max_real_term: tUnion[float, int] = MINUS_INF
1105
+ max_imag_term: tUnion[float, int] = MINUS_INF
1106
+
1107
+ def f(t: 'Expr') -> tUnion[mpc, mpf]:
1108
+ nonlocal max_real_term, max_imag_term
1109
+ re, im, re_acc, im_acc = evalf(func, mp.prec, {'subs': {x: t}})
1110
+
1111
+ have_part[0] = re or have_part[0]
1112
+ have_part[1] = im or have_part[1]
1113
+
1114
+ max_real_term = max(max_real_term, fastlog(re))
1115
+ max_imag_term = max(max_imag_term, fastlog(im))
1116
+
1117
+ if im:
1118
+ return mpc(re or fzero, im)
1119
+ return mpf(re or fzero)
1120
+
1121
+ if options.get('quad') == 'osc':
1122
+ A = Wild('A', exclude=[x])
1123
+ B = Wild('B', exclude=[x])
1124
+ D = Wild('D')
1125
+ m = func.match(cos(A*x + B)*D)
1126
+ if not m:
1127
+ m = func.match(sin(A*x + B)*D)
1128
+ if not m:
1129
+ raise ValueError("An integrand of the form sin(A*x+B)*f(x) "
1130
+ "or cos(A*x+B)*f(x) is required for oscillatory quadrature")
1131
+ period = as_mpmath(2*S.Pi/m[A], prec + 15, options)
1132
+ result = quadosc(f, [xlow, xhigh], period=period)
1133
+ # XXX: quadosc does not do error detection yet
1134
+ quadrature_error = MINUS_INF
1135
+ else:
1136
+ result, quadrature_err = quadts(f, [xlow, xhigh], error=1)
1137
+ quadrature_error = fastlog(quadrature_err._mpf_)
1138
+
1139
+ options['maxprec'] = oldmaxprec
1140
+
1141
+ if have_part[0]:
1142
+ re: Optional[MPF_TUP] = result.real._mpf_
1143
+ re_acc: Optional[int]
1144
+ if re == fzero:
1145
+ re_s, re_acc = scaled_zero(int(-max(prec, max_real_term, quadrature_error)))
1146
+ re = scaled_zero(re_s) # handled ok in evalf_integral
1147
+ else:
1148
+ re_acc = int(-max(max_real_term - fastlog(re) - prec, quadrature_error))
1149
+ else:
1150
+ re, re_acc = None, None
1151
+
1152
+ if have_part[1]:
1153
+ im: Optional[MPF_TUP] = result.imag._mpf_
1154
+ im_acc: Optional[int]
1155
+ if im == fzero:
1156
+ im_s, im_acc = scaled_zero(int(-max(prec, max_imag_term, quadrature_error)))
1157
+ im = scaled_zero(im_s) # handled ok in evalf_integral
1158
+ else:
1159
+ im_acc = int(-max(max_imag_term - fastlog(im) - prec, quadrature_error))
1160
+ else:
1161
+ im, im_acc = None, None
1162
+
1163
+ result = re, im, re_acc, im_acc
1164
+ return result
1165
+
1166
+
1167
+ def evalf_integral(expr: 'Integral', prec: int, options: OPT_DICT) -> TMP_RES:
1168
+ limits = expr.limits
1169
+ if len(limits) != 1 or len(limits[0]) != 3:
1170
+ raise NotImplementedError
1171
+ workprec = prec
1172
+ i = 0
1173
+ maxprec = options.get('maxprec', INF)
1174
+ while 1:
1175
+ result = do_integral(expr, workprec, options)
1176
+ accuracy = complex_accuracy(result)
1177
+ if accuracy >= prec: # achieved desired precision
1178
+ break
1179
+ if workprec >= maxprec: # can't increase accuracy any more
1180
+ break
1181
+ if accuracy == -1:
1182
+ # maybe the answer really is zero and maybe we just haven't increased
1183
+ # the precision enough. So increase by doubling to not take too long
1184
+ # to get to maxprec.
1185
+ workprec *= 2
1186
+ else:
1187
+ workprec += max(prec, 2**i)
1188
+ workprec = min(workprec, maxprec)
1189
+ i += 1
1190
+ return result
1191
+
1192
+
1193
+ def check_convergence(numer: 'Expr', denom: 'Expr', n: 'Symbol') -> tTuple[int, Any, Any]:
1194
+ """
1195
+ Returns
1196
+ =======
1197
+
1198
+ (h, g, p) where
1199
+ -- h is:
1200
+ > 0 for convergence of rate 1/factorial(n)**h
1201
+ < 0 for divergence of rate factorial(n)**(-h)
1202
+ = 0 for geometric or polynomial convergence or divergence
1203
+
1204
+ -- abs(g) is:
1205
+ > 1 for geometric convergence of rate 1/h**n
1206
+ < 1 for geometric divergence of rate h**n
1207
+ = 1 for polynomial convergence or divergence
1208
+
1209
+ (g < 0 indicates an alternating series)
1210
+
1211
+ -- p is:
1212
+ > 1 for polynomial convergence of rate 1/n**h
1213
+ <= 1 for polynomial divergence of rate n**(-h)
1214
+
1215
+ """
1216
+ from sympy.polys.polytools import Poly
1217
+ npol = Poly(numer, n)
1218
+ dpol = Poly(denom, n)
1219
+ p = npol.degree()
1220
+ q = dpol.degree()
1221
+ rate = q - p
1222
+ if rate:
1223
+ return rate, None, None
1224
+ constant = dpol.LC() / npol.LC()
1225
+ from .numbers import equal_valued
1226
+ if not equal_valued(abs(constant), 1):
1227
+ return rate, constant, None
1228
+ if npol.degree() == dpol.degree() == 0:
1229
+ return rate, constant, 0
1230
+ pc = npol.all_coeffs()[1]
1231
+ qc = dpol.all_coeffs()[1]
1232
+ return rate, constant, (qc - pc)/dpol.LC()
1233
+
1234
+
1235
+ def hypsum(expr: 'Expr', n: 'Symbol', start: int, prec: int) -> mpf:
1236
+ """
1237
+ Sum a rapidly convergent infinite hypergeometric series with
1238
+ given general term, e.g. e = hypsum(1/factorial(n), n). The
1239
+ quotient between successive terms must be a quotient of integer
1240
+ polynomials.
1241
+ """
1242
+ from .numbers import Float, equal_valued
1243
+ from sympy.simplify.simplify import hypersimp
1244
+
1245
+ if prec == float('inf'):
1246
+ raise NotImplementedError('does not support inf prec')
1247
+
1248
+ if start:
1249
+ expr = expr.subs(n, n + start)
1250
+ hs = hypersimp(expr, n)
1251
+ if hs is None:
1252
+ raise NotImplementedError("a hypergeometric series is required")
1253
+ num, den = hs.as_numer_denom()
1254
+
1255
+ func1 = lambdify(n, num)
1256
+ func2 = lambdify(n, den)
1257
+
1258
+ h, g, p = check_convergence(num, den, n)
1259
+
1260
+ if h < 0:
1261
+ raise ValueError("Sum diverges like (n!)^%i" % (-h))
1262
+
1263
+ term = expr.subs(n, 0)
1264
+ if not term.is_Rational:
1265
+ raise NotImplementedError("Non rational term functionality is not implemented.")
1266
+
1267
+ # Direct summation if geometric or faster
1268
+ if h > 0 or (h == 0 and abs(g) > 1):
1269
+ term = (MPZ(term.p) << prec) // term.q
1270
+ s = term
1271
+ k = 1
1272
+ while abs(term) > 5:
1273
+ term *= MPZ(func1(k - 1))
1274
+ term //= MPZ(func2(k - 1))
1275
+ s += term
1276
+ k += 1
1277
+ return from_man_exp(s, -prec)
1278
+ else:
1279
+ alt = g < 0
1280
+ if abs(g) < 1:
1281
+ raise ValueError("Sum diverges like (%i)^n" % abs(1/g))
1282
+ if p < 1 or (equal_valued(p, 1) and not alt):
1283
+ raise ValueError("Sum diverges like n^%i" % (-p))
1284
+ # We have polynomial convergence: use Richardson extrapolation
1285
+ vold = None
1286
+ ndig = prec_to_dps(prec)
1287
+ while True:
1288
+ # Need to use at least quad precision because a lot of cancellation
1289
+ # might occur in the extrapolation process; we check the answer to
1290
+ # make sure that the desired precision has been reached, too.
1291
+ prec2 = 4*prec
1292
+ term0 = (MPZ(term.p) << prec2) // term.q
1293
+
1294
+ def summand(k, _term=[term0]):
1295
+ if k:
1296
+ k = int(k)
1297
+ _term[0] *= MPZ(func1(k - 1))
1298
+ _term[0] //= MPZ(func2(k - 1))
1299
+ return make_mpf(from_man_exp(_term[0], -prec2))
1300
+
1301
+ with workprec(prec):
1302
+ v = nsum(summand, [0, mpmath_inf], method='richardson')
1303
+ vf = Float(v, ndig)
1304
+ if vold is not None and vold == vf:
1305
+ break
1306
+ prec += prec # double precision each time
1307
+ vold = vf
1308
+
1309
+ return v._mpf_
1310
+
1311
+
1312
+ def evalf_prod(expr: 'Product', prec: int, options: OPT_DICT) -> TMP_RES:
1313
+ if all((l[1] - l[2]).is_Integer for l in expr.limits):
1314
+ result = evalf(expr.doit(), prec=prec, options=options)
1315
+ else:
1316
+ from sympy.concrete.summations import Sum
1317
+ result = evalf(expr.rewrite(Sum), prec=prec, options=options)
1318
+ return result
1319
+
1320
+
1321
+ def evalf_sum(expr: 'Sum', prec: int, options: OPT_DICT) -> TMP_RES:
1322
+ from .numbers import Float
1323
+ if 'subs' in options:
1324
+ expr = expr.subs(options['subs'])
1325
+ func = expr.function
1326
+ limits = expr.limits
1327
+ if len(limits) != 1 or len(limits[0]) != 3:
1328
+ raise NotImplementedError
1329
+ if func.is_zero:
1330
+ return None, None, prec, None
1331
+ prec2 = prec + 10
1332
+ try:
1333
+ n, a, b = limits[0]
1334
+ if b is not S.Infinity or a is S.NegativeInfinity or a != int(a):
1335
+ raise NotImplementedError
1336
+ # Use fast hypergeometric summation if possible
1337
+ v = hypsum(func, n, int(a), prec2)
1338
+ delta = prec - fastlog(v)
1339
+ if fastlog(v) < -10:
1340
+ v = hypsum(func, n, int(a), delta)
1341
+ return v, None, min(prec, delta), None
1342
+ except NotImplementedError:
1343
+ # Euler-Maclaurin summation for general series
1344
+ eps = Float(2.0)**(-prec)
1345
+ for i in range(1, 5):
1346
+ m = n = 2**i * prec
1347
+ s, err = expr.euler_maclaurin(m=m, n=n, eps=eps,
1348
+ eval_integral=False)
1349
+ err = err.evalf()
1350
+ if err is S.NaN:
1351
+ raise NotImplementedError
1352
+ if err <= eps:
1353
+ break
1354
+ err = fastlog(evalf(abs(err), 20, options)[0])
1355
+ re, im, re_acc, im_acc = evalf(s, prec2, options)
1356
+ if re_acc is None:
1357
+ re_acc = -err
1358
+ if im_acc is None:
1359
+ im_acc = -err
1360
+ return re, im, re_acc, im_acc
1361
+
1362
+
1363
+ #----------------------------------------------------------------------------#
1364
+ # #
1365
+ # Symbolic interface #
1366
+ # #
1367
+ #----------------------------------------------------------------------------#
1368
+
1369
+ def evalf_symbol(x: 'Expr', prec: int, options: OPT_DICT) -> TMP_RES:
1370
+ val = options['subs'][x]
1371
+ if isinstance(val, mpf):
1372
+ if not val:
1373
+ return None, None, None, None
1374
+ return val._mpf_, None, prec, None
1375
+ else:
1376
+ if '_cache' not in options:
1377
+ options['_cache'] = {}
1378
+ cache = options['_cache']
1379
+ cached, cached_prec = cache.get(x, (None, MINUS_INF))
1380
+ if cached_prec >= prec:
1381
+ return cached
1382
+ v = evalf(sympify(val), prec, options)
1383
+ cache[x] = (v, prec)
1384
+ return v
1385
+
1386
+
1387
+ evalf_table: tDict[Type['Expr'], Callable[['Expr', int, OPT_DICT], TMP_RES]] = {}
1388
+
1389
+
1390
+ def _create_evalf_table():
1391
+ global evalf_table
1392
+ from sympy.concrete.products import Product
1393
+ from sympy.concrete.summations import Sum
1394
+ from .add import Add
1395
+ from .mul import Mul
1396
+ from .numbers import Exp1, Float, Half, ImaginaryUnit, Integer, NaN, NegativeOne, One, Pi, Rational, \
1397
+ Zero, ComplexInfinity, AlgebraicNumber
1398
+ from .power import Pow
1399
+ from .symbol import Dummy, Symbol
1400
+ from sympy.functions.elementary.complexes import Abs, im, re
1401
+ from sympy.functions.elementary.exponential import exp, log
1402
+ from sympy.functions.elementary.integers import ceiling, floor
1403
+ from sympy.functions.elementary.piecewise import Piecewise
1404
+ from sympy.functions.elementary.trigonometric import atan, cos, sin
1405
+ from sympy.integrals.integrals import Integral
1406
+ evalf_table = {
1407
+ Symbol: evalf_symbol,
1408
+ Dummy: evalf_symbol,
1409
+ Float: evalf_float,
1410
+ Rational: evalf_rational,
1411
+ Integer: evalf_integer,
1412
+ Zero: lambda x, prec, options: (None, None, prec, None),
1413
+ One: lambda x, prec, options: (fone, None, prec, None),
1414
+ Half: lambda x, prec, options: (fhalf, None, prec, None),
1415
+ Pi: lambda x, prec, options: (mpf_pi(prec), None, prec, None),
1416
+ Exp1: lambda x, prec, options: (mpf_e(prec), None, prec, None),
1417
+ ImaginaryUnit: lambda x, prec, options: (None, fone, None, prec),
1418
+ NegativeOne: lambda x, prec, options: (fnone, None, prec, None),
1419
+ ComplexInfinity: lambda x, prec, options: S.ComplexInfinity,
1420
+ NaN: lambda x, prec, options: (fnan, None, prec, None),
1421
+
1422
+ exp: evalf_exp,
1423
+
1424
+ cos: evalf_trig,
1425
+ sin: evalf_trig,
1426
+
1427
+ Add: evalf_add,
1428
+ Mul: evalf_mul,
1429
+ Pow: evalf_pow,
1430
+
1431
+ log: evalf_log,
1432
+ atan: evalf_atan,
1433
+ Abs: evalf_abs,
1434
+
1435
+ re: evalf_re,
1436
+ im: evalf_im,
1437
+ floor: evalf_floor,
1438
+ ceiling: evalf_ceiling,
1439
+
1440
+ Integral: evalf_integral,
1441
+ Sum: evalf_sum,
1442
+ Product: evalf_prod,
1443
+ Piecewise: evalf_piecewise,
1444
+
1445
+ AlgebraicNumber: evalf_alg_num,
1446
+ }
1447
+
1448
+
1449
+ def evalf(x: 'Expr', prec: int, options: OPT_DICT) -> TMP_RES:
1450
+ """
1451
+ Evaluate the ``Expr`` instance, ``x``
1452
+ to a binary precision of ``prec``. This
1453
+ function is supposed to be used internally.
1454
+
1455
+ Parameters
1456
+ ==========
1457
+
1458
+ x : Expr
1459
+ The formula to evaluate to a float.
1460
+ prec : int
1461
+ The binary precision that the output should have.
1462
+ options : dict
1463
+ A dictionary with the same entries as
1464
+ ``EvalfMixin.evalf`` and in addition,
1465
+ ``maxprec`` which is the maximum working precision.
1466
+
1467
+ Returns
1468
+ =======
1469
+
1470
+ An optional tuple, ``(re, im, re_acc, im_acc)``
1471
+ which are the real, imaginary, real accuracy
1472
+ and imaginary accuracy respectively. ``re`` is
1473
+ an mpf value tuple and so is ``im``. ``re_acc``
1474
+ and ``im_acc`` are ints.
1475
+
1476
+ NB: all these return values can be ``None``.
1477
+ If all values are ``None``, then that represents 0.
1478
+ Note that 0 is also represented as ``fzero = (0, 0, 0, 0)``.
1479
+ """
1480
+ from sympy.functions.elementary.complexes import re as re_, im as im_
1481
+ try:
1482
+ rf = evalf_table[type(x)]
1483
+ r = rf(x, prec, options)
1484
+ except KeyError:
1485
+ # Fall back to ordinary evalf if possible
1486
+ if 'subs' in options:
1487
+ x = x.subs(evalf_subs(prec, options['subs']))
1488
+ xe = x._eval_evalf(prec)
1489
+ if xe is None:
1490
+ raise NotImplementedError
1491
+ as_real_imag = getattr(xe, "as_real_imag", None)
1492
+ if as_real_imag is None:
1493
+ raise NotImplementedError # e.g. FiniteSet(-1.0, 1.0).evalf()
1494
+ re, im = as_real_imag()
1495
+ if re.has(re_) or im.has(im_):
1496
+ raise NotImplementedError
1497
+ if re == 0.0:
1498
+ re = None
1499
+ reprec = None
1500
+ elif re.is_number:
1501
+ re = re._to_mpmath(prec, allow_ints=False)._mpf_
1502
+ reprec = prec
1503
+ else:
1504
+ raise NotImplementedError
1505
+ if im == 0.0:
1506
+ im = None
1507
+ imprec = None
1508
+ elif im.is_number:
1509
+ im = im._to_mpmath(prec, allow_ints=False)._mpf_
1510
+ imprec = prec
1511
+ else:
1512
+ raise NotImplementedError
1513
+ r = re, im, reprec, imprec
1514
+
1515
+ if options.get("verbose"):
1516
+ print("### input", x)
1517
+ print("### output", to_str(r[0] or fzero, 50) if isinstance(r, tuple) else r)
1518
+ print("### raw", r) # r[0], r[2]
1519
+ print()
1520
+ chop = options.get('chop', False)
1521
+ if chop:
1522
+ if chop is True:
1523
+ chop_prec = prec
1524
+ else:
1525
+ # convert (approximately) from given tolerance;
1526
+ # the formula here will will make 1e-i rounds to 0 for
1527
+ # i in the range +/-27 while 2e-i will not be chopped
1528
+ chop_prec = int(round(-3.321*math.log10(chop) + 2.5))
1529
+ if chop_prec == 3:
1530
+ chop_prec -= 1
1531
+ r = chop_parts(r, chop_prec)
1532
+ if options.get("strict"):
1533
+ check_target(x, r, prec)
1534
+ return r
1535
+
1536
+
1537
+ def quad_to_mpmath(q, ctx=None):
1538
+ """Turn the quad returned by ``evalf`` into an ``mpf`` or ``mpc``. """
1539
+ mpc = make_mpc if ctx is None else ctx.make_mpc
1540
+ mpf = make_mpf if ctx is None else ctx.make_mpf
1541
+ if q is S.ComplexInfinity:
1542
+ raise NotImplementedError
1543
+ re, im, _, _ = q
1544
+ if im:
1545
+ if not re:
1546
+ re = fzero
1547
+ return mpc((re, im))
1548
+ elif re:
1549
+ return mpf(re)
1550
+ else:
1551
+ return mpf(fzero)
1552
+
1553
+
1554
+ class EvalfMixin:
1555
+ """Mixin class adding evalf capability."""
1556
+
1557
+ __slots__ = () # type: tTuple[str, ...]
1558
+
1559
+ def evalf(self, n=15, subs=None, maxn=100, chop=False, strict=False, quad=None, verbose=False):
1560
+ """
1561
+ Evaluate the given formula to an accuracy of *n* digits.
1562
+
1563
+ Parameters
1564
+ ==========
1565
+
1566
+ subs : dict, optional
1567
+ Substitute numerical values for symbols, e.g.
1568
+ ``subs={x:3, y:1+pi}``. The substitutions must be given as a
1569
+ dictionary.
1570
+
1571
+ maxn : int, optional
1572
+ Allow a maximum temporary working precision of maxn digits.
1573
+
1574
+ chop : bool or number, optional
1575
+ Specifies how to replace tiny real or imaginary parts in
1576
+ subresults by exact zeros.
1577
+
1578
+ When ``True`` the chop value defaults to standard precision.
1579
+
1580
+ Otherwise the chop value is used to determine the
1581
+ magnitude of "small" for purposes of chopping.
1582
+
1583
+ >>> from sympy import N
1584
+ >>> x = 1e-4
1585
+ >>> N(x, chop=True)
1586
+ 0.000100000000000000
1587
+ >>> N(x, chop=1e-5)
1588
+ 0.000100000000000000
1589
+ >>> N(x, chop=1e-4)
1590
+ 0
1591
+
1592
+ strict : bool, optional
1593
+ Raise ``PrecisionExhausted`` if any subresult fails to
1594
+ evaluate to full accuracy, given the available maxprec.
1595
+
1596
+ quad : str, optional
1597
+ Choose algorithm for numerical quadrature. By default,
1598
+ tanh-sinh quadrature is used. For oscillatory
1599
+ integrals on an infinite interval, try ``quad='osc'``.
1600
+
1601
+ verbose : bool, optional
1602
+ Print debug information.
1603
+
1604
+ Notes
1605
+ =====
1606
+
1607
+ When Floats are naively substituted into an expression,
1608
+ precision errors may adversely affect the result. For example,
1609
+ adding 1e16 (a Float) to 1 will truncate to 1e16; if 1e16 is
1610
+ then subtracted, the result will be 0.
1611
+ That is exactly what happens in the following:
1612
+
1613
+ >>> from sympy.abc import x, y, z
1614
+ >>> values = {x: 1e16, y: 1, z: 1e16}
1615
+ >>> (x + y - z).subs(values)
1616
+ 0
1617
+
1618
+ Using the subs argument for evalf is the accurate way to
1619
+ evaluate such an expression:
1620
+
1621
+ >>> (x + y - z).evalf(subs=values)
1622
+ 1.00000000000000
1623
+ """
1624
+ from .numbers import Float, Number
1625
+ n = n if n is not None else 15
1626
+
1627
+ if subs and is_sequence(subs):
1628
+ raise TypeError('subs must be given as a dictionary')
1629
+
1630
+ # for sake of sage that doesn't like evalf(1)
1631
+ if n == 1 and isinstance(self, Number):
1632
+ from .expr import _mag
1633
+ rv = self.evalf(2, subs, maxn, chop, strict, quad, verbose)
1634
+ m = _mag(rv)
1635
+ rv = rv.round(1 - m)
1636
+ return rv
1637
+
1638
+ if not evalf_table:
1639
+ _create_evalf_table()
1640
+ prec = dps_to_prec(n)
1641
+ options = {'maxprec': max(prec, int(maxn*LG10)), 'chop': chop,
1642
+ 'strict': strict, 'verbose': verbose}
1643
+ if subs is not None:
1644
+ options['subs'] = subs
1645
+ if quad is not None:
1646
+ options['quad'] = quad
1647
+ try:
1648
+ result = evalf(self, prec + 4, options)
1649
+ except NotImplementedError:
1650
+ # Fall back to the ordinary evalf
1651
+ if hasattr(self, 'subs') and subs is not None: # issue 20291
1652
+ v = self.subs(subs)._eval_evalf(prec)
1653
+ else:
1654
+ v = self._eval_evalf(prec)
1655
+ if v is None:
1656
+ return self
1657
+ elif not v.is_number:
1658
+ return v
1659
+ try:
1660
+ # If the result is numerical, normalize it
1661
+ result = evalf(v, prec, options)
1662
+ except NotImplementedError:
1663
+ # Probably contains symbols or unknown functions
1664
+ return v
1665
+ if result is S.ComplexInfinity:
1666
+ return result
1667
+ re, im, re_acc, im_acc = result
1668
+ if re is S.NaN or im is S.NaN:
1669
+ return S.NaN
1670
+ if re:
1671
+ p = max(min(prec, re_acc), 1)
1672
+ re = Float._new(re, p)
1673
+ else:
1674
+ re = S.Zero
1675
+ if im:
1676
+ p = max(min(prec, im_acc), 1)
1677
+ im = Float._new(im, p)
1678
+ return re + im*S.ImaginaryUnit
1679
+ else:
1680
+ return re
1681
+
1682
+ n = evalf
1683
+
1684
+ def _evalf(self, prec):
1685
+ """Helper for evalf. Does the same thing but takes binary precision"""
1686
+ r = self._eval_evalf(prec)
1687
+ if r is None:
1688
+ r = self
1689
+ return r
1690
+
1691
+ def _eval_evalf(self, prec):
1692
+ return
1693
+
1694
+ def _to_mpmath(self, prec, allow_ints=True):
1695
+ # mpmath functions accept ints as input
1696
+ errmsg = "cannot convert to mpmath number"
1697
+ if allow_ints and self.is_Integer:
1698
+ return self.p
1699
+ if hasattr(self, '_as_mpf_val'):
1700
+ return make_mpf(self._as_mpf_val(prec))
1701
+ try:
1702
+ result = evalf(self, prec, {})
1703
+ return quad_to_mpmath(result)
1704
+ except NotImplementedError:
1705
+ v = self._eval_evalf(prec)
1706
+ if v is None:
1707
+ raise ValueError(errmsg)
1708
+ if v.is_Float:
1709
+ return make_mpf(v._mpf_)
1710
+ # Number + Number*I is also fine
1711
+ re, im = v.as_real_imag()
1712
+ if allow_ints and re.is_Integer:
1713
+ re = from_int(re.p)
1714
+ elif re.is_Float:
1715
+ re = re._mpf_
1716
+ else:
1717
+ raise ValueError(errmsg)
1718
+ if allow_ints and im.is_Integer:
1719
+ im = from_int(im.p)
1720
+ elif im.is_Float:
1721
+ im = im._mpf_
1722
+ else:
1723
+ raise ValueError(errmsg)
1724
+ return make_mpc((re, im))
1725
+
1726
+
1727
+ def N(x, n=15, **options):
1728
+ r"""
1729
+ Calls x.evalf(n, \*\*options).
1730
+
1731
+ Explanations
1732
+ ============
1733
+
1734
+ Both .n() and N() are equivalent to .evalf(); use the one that you like better.
1735
+ See also the docstring of .evalf() for information on the options.
1736
+
1737
+ Examples
1738
+ ========
1739
+
1740
+ >>> from sympy import Sum, oo, N
1741
+ >>> from sympy.abc import k
1742
+ >>> Sum(1/k**k, (k, 1, oo))
1743
+ Sum(k**(-k), (k, 1, oo))
1744
+ >>> N(_, 4)
1745
+ 1.291
1746
+
1747
+ """
1748
+ # by using rational=True, any evaluation of a string
1749
+ # will be done using exact values for the Floats
1750
+ return sympify(x, rational=True).evalf(n, **options)
1751
+
1752
+
1753
+ def _evalf_with_bounded_error(x: 'Expr', eps: 'Optional[Expr]' = None,
1754
+ m: int = 0,
1755
+ options: Optional[OPT_DICT] = None) -> TMP_RES:
1756
+ """
1757
+ Evaluate *x* to within a bounded absolute error.
1758
+
1759
+ Parameters
1760
+ ==========
1761
+
1762
+ x : Expr
1763
+ The quantity to be evaluated.
1764
+ eps : Expr, None, optional (default=None)
1765
+ Positive real upper bound on the acceptable error.
1766
+ m : int, optional (default=0)
1767
+ If *eps* is None, then use 2**(-m) as the upper bound on the error.
1768
+ options: OPT_DICT
1769
+ As in the ``evalf`` function.
1770
+
1771
+ Returns
1772
+ =======
1773
+
1774
+ A tuple ``(re, im, re_acc, im_acc)``, as returned by ``evalf``.
1775
+
1776
+ See Also
1777
+ ========
1778
+
1779
+ evalf
1780
+
1781
+ """
1782
+ if eps is not None:
1783
+ if not (eps.is_Rational or eps.is_Float) or not eps > 0:
1784
+ raise ValueError("eps must be positive")
1785
+ r, _, _, _ = evalf(1/eps, 1, {})
1786
+ m = fastlog(r)
1787
+
1788
+ c, d, _, _ = evalf(x, 1, {})
1789
+ # Note: If x = a + b*I, then |a| <= 2|c| and |b| <= 2|d|, with equality
1790
+ # only in the zero case.
1791
+ # If a is non-zero, then |c| = 2**nc for some integer nc, and c has
1792
+ # bitcount 1. Therefore 2**fastlog(c) = 2**(nc+1) = 2|c| is an upper bound
1793
+ # on |a|. Likewise for b and d.
1794
+ nr, ni = fastlog(c), fastlog(d)
1795
+ n = max(nr, ni) + 1
1796
+ # If x is 0, then n is MINUS_INF, and p will be 1. Otherwise,
1797
+ # n - 1 bits get us past the integer parts of a and b, and +1 accounts for
1798
+ # the factor of <= sqrt(2) that is |x|/max(|a|, |b|).
1799
+ p = max(1, m + n + 1)
1800
+
1801
+ options = options or {}
1802
+ return evalf(x, p, options)