Coverage for /usr/lib/python3/dist-packages/sympy/core/basic.py: 54%
750 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
1"""Base class for all the objects in SymPy"""
2from __future__ import annotations
4from collections import defaultdict
5from collections.abc import Mapping
6from itertools import chain, zip_longest
8from .assumptions import _prepare_class_assumptions
9from .cache import cacheit
10from .core import ordering_of_classes
11from .sympify import _sympify, sympify, SympifyError, _external_converter
12from .sorting import ordered
13from .kind import Kind, UndefinedKind
14from ._print_helpers import Printable
16from sympy.utilities.decorator import deprecated
17from sympy.utilities.exceptions import sympy_deprecation_warning
18from sympy.utilities.iterables import iterable, numbered_symbols
19from sympy.utilities.misc import filldedent, func_name
21from inspect import getmro
24def 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))
36def _old_compare(x: type, y: type) -> int:
37 # If the other object is not a Basic subclass, then we are not equal to it.
38 if not issubclass(y, Basic):
39 return -1
41 n1 = x.__name__
42 n2 = y.__name__
43 if n1 == n2:
44 return 0
46 UNKNOWN = len(ordering_of_classes) + 1
47 try:
48 i1 = ordering_of_classes.index(n1)
49 except ValueError:
50 i1 = UNKNOWN
51 try:
52 i2 = ordering_of_classes.index(n2)
53 except ValueError:
54 i2 = UNKNOWN
55 if i1 == UNKNOWN and i2 == UNKNOWN:
56 return (n1 > n2) - (n1 < n2)
57 return (i1 > i2) - (i1 < i2)
60class Basic(Printable):
61 """
62 Base class for all SymPy objects.
64 Notes and conventions
65 =====================
67 1) Always use ``.args``, when accessing parameters of some instance:
69 >>> from sympy import cot
70 >>> from sympy.abc import x, y
72 >>> cot(x).args
73 (x,)
75 >>> cot(x).args[0]
76 x
78 >>> (x*y).args
79 (x, y)
81 >>> (x*y).args[1]
82 y
85 2) Never use internal methods or variables (the ones prefixed with ``_``):
87 >>> cot(x)._args # do not use this, use cot(x).args instead
88 (x,)
91 3) By "SymPy object" we mean something that can be returned by
92 ``sympify``. But not all objects one encounters using SymPy are
93 subclasses of Basic. For example, mutable objects are not:
95 >>> from sympy import Basic, Matrix, sympify
96 >>> A = Matrix([[1, 2], [3, 4]]).as_mutable()
97 >>> isinstance(A, Basic)
98 False
100 >>> B = sympify(A)
101 >>> isinstance(B, Basic)
102 True
103 """
104 __slots__ = ('_mhash', # hash value
105 '_args', # arguments
106 '_assumptions'
107 )
109 _args: tuple[Basic, ...]
110 _mhash: int | None
112 @property
113 def __sympy__(self):
114 return True
116 def __init_subclass__(cls):
117 # Initialize the default_assumptions FactKB and also any assumptions
118 # property methods. This method will only be called for subclasses of
119 # Basic but not for Basic itself so we call
120 # _prepare_class_assumptions(Basic) below the class definition.
121 _prepare_class_assumptions(cls)
123 # To be overridden with True in the appropriate subclasses
124 is_number = False
125 is_Atom = False
126 is_Symbol = False
127 is_symbol = False
128 is_Indexed = False
129 is_Dummy = False
130 is_Wild = False
131 is_Function = False
132 is_Add = False
133 is_Mul = False
134 is_Pow = False
135 is_Number = False
136 is_Float = False
137 is_Rational = False
138 is_Integer = False
139 is_NumberSymbol = False
140 is_Order = False
141 is_Derivative = False
142 is_Piecewise = False
143 is_Poly = False
144 is_AlgebraicNumber = False
145 is_Relational = False
146 is_Equality = False
147 is_Boolean = False
148 is_Not = False
149 is_Matrix = False
150 is_Vector = False
151 is_Point = False
152 is_MatAdd = False
153 is_MatMul = False
154 is_real: bool | None
155 is_extended_real: bool | None
156 is_zero: bool | None
157 is_negative: bool | None
158 is_commutative: bool | None
160 kind: Kind = UndefinedKind
162 def __new__(cls, *args):
163 obj = object.__new__(cls)
164 obj._assumptions = cls.default_assumptions
165 obj._mhash = None # will be set by __hash__ method.
167 obj._args = args # all items in args must be Basic objects
168 return obj
170 def copy(self):
171 return self.func(*self.args)
173 def __getnewargs__(self):
174 return self.args
176 def __getstate__(self):
177 return None
179 def __setstate__(self, state):
180 for name, value in state.items():
181 setattr(self, name, value)
183 def __reduce_ex__(self, protocol):
184 if protocol < 2:
185 msg = "Only pickle protocol 2 or higher is supported by SymPy"
186 raise NotImplementedError(msg)
187 return super().__reduce_ex__(protocol)
189 def __hash__(self) -> int:
190 # hash cannot be cached using cache_it because infinite recurrence
191 # occurs as hash is needed for setting cache dictionary keys
192 h = self._mhash
193 if h is None:
194 h = hash((type(self).__name__,) + self._hashable_content())
195 self._mhash = h
196 return h
198 def _hashable_content(self):
199 """Return a tuple of information about self that can be used to
200 compute the hash. If a class defines additional attributes,
201 like ``name`` in Symbol, then this method should be updated
202 accordingly to return such relevant attributes.
204 Defining more than _hashable_content is necessary if __eq__ has
205 been defined by a class. See note about this in Basic.__eq__."""
206 return self._args
208 @property
209 def assumptions0(self):
210 """
211 Return object `type` assumptions.
213 For example:
215 Symbol('x', real=True)
216 Symbol('x', integer=True)
218 are different objects. In other words, besides Python type (Symbol in
219 this case), the initial assumptions are also forming their typeinfo.
221 Examples
222 ========
224 >>> from sympy import Symbol
225 >>> from sympy.abc import x
226 >>> x.assumptions0
227 {'commutative': True}
228 >>> x = Symbol("x", positive=True)
229 >>> x.assumptions0
230 {'commutative': True, 'complex': True, 'extended_negative': False,
231 'extended_nonnegative': True, 'extended_nonpositive': False,
232 'extended_nonzero': True, 'extended_positive': True, 'extended_real':
233 True, 'finite': True, 'hermitian': True, 'imaginary': False,
234 'infinite': False, 'negative': False, 'nonnegative': True,
235 'nonpositive': False, 'nonzero': True, 'positive': True, 'real':
236 True, 'zero': False}
237 """
238 return {}
240 def compare(self, other):
241 """
242 Return -1, 0, 1 if the object is smaller, equal, or greater than other.
244 Not in the mathematical sense. If the object is of a different type
245 from the "other" then their classes are ordered according to
246 the sorted_classes list.
248 Examples
249 ========
251 >>> from sympy.abc import x, y
252 >>> x.compare(y)
253 -1
254 >>> x.compare(x)
255 0
256 >>> y.compare(x)
257 1
259 """
260 # all redefinitions of __cmp__ method should start with the
261 # following lines:
262 if self is other:
263 return 0
264 n1 = self.__class__
265 n2 = other.__class__
266 c = _old_compare(n1, n2)
267 if c:
268 return c
269 #
270 st = self._hashable_content()
271 ot = other._hashable_content()
272 c = (len(st) > len(ot)) - (len(st) < len(ot))
273 if c:
274 return c
275 for l, r in zip(st, ot):
276 l = Basic(*l) if isinstance(l, frozenset) else l
277 r = Basic(*r) if isinstance(r, frozenset) else r
278 if isinstance(l, Basic):
279 c = l.compare(r)
280 else:
281 c = (l > r) - (l < r)
282 if c:
283 return c
284 return 0
286 @staticmethod
287 def _compare_pretty(a, b):
288 from sympy.series.order import Order
289 if isinstance(a, Order) and not isinstance(b, Order):
290 return 1
291 if not isinstance(a, Order) and isinstance(b, Order):
292 return -1
294 if a.is_Rational and b.is_Rational:
295 l = a.p * b.q
296 r = b.p * a.q
297 return (l > r) - (l < r)
298 else:
299 from .symbol import Wild
300 p1, p2, p3 = Wild("p1"), Wild("p2"), Wild("p3")
301 r_a = a.match(p1 * p2**p3)
302 if r_a and p3 in r_a:
303 a3 = r_a[p3]
304 r_b = b.match(p1 * p2**p3)
305 if r_b and p3 in r_b:
306 b3 = r_b[p3]
307 c = Basic.compare(a3, b3)
308 if c != 0:
309 return c
311 return Basic.compare(a, b)
313 @classmethod
314 def fromiter(cls, args, **assumptions):
315 """
316 Create a new object from an iterable.
318 This is a convenience function that allows one to create objects from
319 any iterable, without having to convert to a list or tuple first.
321 Examples
322 ========
324 >>> from sympy import Tuple
325 >>> Tuple.fromiter(i for i in range(5))
326 (0, 1, 2, 3, 4)
328 """
329 return cls(*tuple(args), **assumptions)
331 @classmethod
332 def class_key(cls):
333 """Nice order of classes."""
334 return 5, 0, cls.__name__
336 @cacheit
337 def sort_key(self, order=None):
338 """
339 Return a sort key.
341 Examples
342 ========
344 >>> from sympy import S, I
346 >>> sorted([S(1)/2, I, -I], key=lambda x: x.sort_key())
347 [1/2, -I, I]
349 >>> S("[x, 1/x, 1/x**2, x**2, x**(1/2), x**(1/4), x**(3/2)]")
350 [x, 1/x, x**(-2), x**2, sqrt(x), x**(1/4), x**(3/2)]
351 >>> sorted(_, key=lambda x: x.sort_key())
352 [x**(-2), 1/x, x**(1/4), sqrt(x), x, x**(3/2), x**2]
354 """
356 # XXX: remove this when issue 5169 is fixed
357 def inner_key(arg):
358 if isinstance(arg, Basic):
359 return arg.sort_key(order)
360 else:
361 return arg
363 args = self._sorted_args
364 args = len(args), tuple([inner_key(arg) for arg in args])
365 return self.class_key(), args, S.One.sort_key(), S.One
367 def _do_eq_sympify(self, other):
368 """Returns a boolean indicating whether a == b when either a
369 or b is not a Basic. This is only done for types that were either
370 added to `converter` by a 3rd party or when the object has `_sympy_`
371 defined. This essentially reuses the code in `_sympify` that is
372 specific for this use case. Non-user defined types that are meant
373 to work with SymPy should be handled directly in the __eq__ methods
374 of the `Basic` classes it could equate to and not be converted. Note
375 that after conversion, `==` is used again since it is not
376 necessarily clear whether `self` or `other`'s __eq__ method needs
377 to be used."""
378 for superclass in type(other).__mro__:
379 conv = _external_converter.get(superclass)
380 if conv is not None:
381 return self == conv(other)
382 if hasattr(other, '_sympy_'):
383 return self == other._sympy_()
384 return NotImplemented
386 def __eq__(self, other):
387 """Return a boolean indicating whether a == b on the basis of
388 their symbolic trees.
390 This is the same as a.compare(b) == 0 but faster.
392 Notes
393 =====
395 If a class that overrides __eq__() needs to retain the
396 implementation of __hash__() from a parent class, the
397 interpreter must be told this explicitly by setting
398 __hash__ : Callable[[object], int] = <ParentClass>.__hash__.
399 Otherwise the inheritance of __hash__() will be blocked,
400 just as if __hash__ had been explicitly set to None.
402 References
403 ==========
405 from https://docs.python.org/dev/reference/datamodel.html#object.__hash__
406 """
407 if self is other:
408 return True
410 if not isinstance(other, Basic):
411 return self._do_eq_sympify(other)
413 # check for pure number expr
414 if not (self.is_Number and other.is_Number) and (
415 type(self) != type(other)):
416 return False
417 a, b = self._hashable_content(), other._hashable_content()
418 if a != b:
419 return False
420 # check number *in* an expression
421 for a, b in zip(a, b):
422 if not isinstance(a, Basic):
423 continue
424 if a.is_Number and type(a) != type(b):
425 return False
426 return True
428 def __ne__(self, other):
429 """``a != b`` -> Compare two symbolic trees and see whether they are different
431 this is the same as:
433 ``a.compare(b) != 0``
435 but faster
436 """
437 return not self == other
439 def dummy_eq(self, other, symbol=None):
440 """
441 Compare two expressions and handle dummy symbols.
443 Examples
444 ========
446 >>> from sympy import Dummy
447 >>> from sympy.abc import x, y
449 >>> u = Dummy('u')
451 >>> (u**2 + 1).dummy_eq(x**2 + 1)
452 True
453 >>> (u**2 + 1) == (x**2 + 1)
454 False
456 >>> (u**2 + y).dummy_eq(x**2 + y, x)
457 True
458 >>> (u**2 + y).dummy_eq(x**2 + y, y)
459 False
461 """
462 s = self.as_dummy()
463 o = _sympify(other)
464 o = o.as_dummy()
466 dummy_symbols = [i for i in s.free_symbols if i.is_Dummy]
468 if len(dummy_symbols) == 1:
469 dummy = dummy_symbols.pop()
470 else:
471 return s == o
473 if symbol is None:
474 symbols = o.free_symbols
476 if len(symbols) == 1:
477 symbol = symbols.pop()
478 else:
479 return s == o
481 tmp = dummy.__class__()
483 return s.xreplace({dummy: tmp}) == o.xreplace({symbol: tmp})
485 def atoms(self, *types):
486 """Returns the atoms that form the current object.
488 By default, only objects that are truly atomic and cannot
489 be divided into smaller pieces are returned: symbols, numbers,
490 and number symbols like I and pi. It is possible to request
491 atoms of any type, however, as demonstrated below.
493 Examples
494 ========
496 >>> from sympy import I, pi, sin
497 >>> from sympy.abc import x, y
498 >>> (1 + x + 2*sin(y + I*pi)).atoms()
499 {1, 2, I, pi, x, y}
501 If one or more types are given, the results will contain only
502 those types of atoms.
504 >>> from sympy import Number, NumberSymbol, Symbol
505 >>> (1 + x + 2*sin(y + I*pi)).atoms(Symbol)
506 {x, y}
508 >>> (1 + x + 2*sin(y + I*pi)).atoms(Number)
509 {1, 2}
511 >>> (1 + x + 2*sin(y + I*pi)).atoms(Number, NumberSymbol)
512 {1, 2, pi}
514 >>> (1 + x + 2*sin(y + I*pi)).atoms(Number, NumberSymbol, I)
515 {1, 2, I, pi}
517 Note that I (imaginary unit) and zoo (complex infinity) are special
518 types of number symbols and are not part of the NumberSymbol class.
520 The type can be given implicitly, too:
522 >>> (1 + x + 2*sin(y + I*pi)).atoms(x) # x is a Symbol
523 {x, y}
525 Be careful to check your assumptions when using the implicit option
526 since ``S(1).is_Integer = True`` but ``type(S(1))`` is ``One``, a special type
527 of SymPy atom, while ``type(S(2))`` is type ``Integer`` and will find all
528 integers in an expression:
530 >>> from sympy import S
531 >>> (1 + x + 2*sin(y + I*pi)).atoms(S(1))
532 {1}
534 >>> (1 + x + 2*sin(y + I*pi)).atoms(S(2))
535 {1, 2}
537 Finally, arguments to atoms() can select more than atomic atoms: any
538 SymPy type (loaded in core/__init__.py) can be listed as an argument
539 and those types of "atoms" as found in scanning the arguments of the
540 expression recursively:
542 >>> from sympy import Function, Mul
543 >>> from sympy.core.function import AppliedUndef
544 >>> f = Function('f')
545 >>> (1 + f(x) + 2*sin(y + I*pi)).atoms(Function)
546 {f(x), sin(y + I*pi)}
547 >>> (1 + f(x) + 2*sin(y + I*pi)).atoms(AppliedUndef)
548 {f(x)}
550 >>> (1 + x + 2*sin(y + I*pi)).atoms(Mul)
551 {I*pi, 2*sin(y + I*pi)}
553 """
554 if types:
555 types = tuple(
556 [t if isinstance(t, type) else type(t) for t in types])
557 nodes = _preorder_traversal(self)
558 if types:
559 result = {node for node in nodes if isinstance(node, types)}
560 else:
561 result = {node for node in nodes if not node.args}
562 return result
564 @property
565 def free_symbols(self) -> set[Basic]:
566 """Return from the atoms of self those which are free symbols.
568 Not all free symbols are ``Symbol``. Eg: IndexedBase('I')[0].free_symbols
570 For most expressions, all symbols are free symbols. For some classes
571 this is not true. e.g. Integrals use Symbols for the dummy variables
572 which are bound variables, so Integral has a method to return all
573 symbols except those. Derivative keeps track of symbols with respect
574 to which it will perform a derivative; those are
575 bound variables, too, so it has its own free_symbols method.
577 Any other method that uses bound variables should implement a
578 free_symbols method."""
579 empty: set[Basic] = set()
580 return empty.union(*(a.free_symbols for a in self.args))
582 @property
583 def expr_free_symbols(self):
584 sympy_deprecation_warning("""
585 The expr_free_symbols property is deprecated. Use free_symbols to get
586 the free symbols of an expression.
587 """,
588 deprecated_since_version="1.9",
589 active_deprecations_target="deprecated-expr-free-symbols")
590 return set()
592 def as_dummy(self):
593 """Return the expression with any objects having structurally
594 bound symbols replaced with unique, canonical symbols within
595 the object in which they appear and having only the default
596 assumption for commutativity being True. When applied to a
597 symbol a new symbol having only the same commutativity will be
598 returned.
600 Examples
601 ========
603 >>> from sympy import Integral, Symbol
604 >>> from sympy.abc import x
605 >>> r = Symbol('r', real=True)
606 >>> Integral(r, (r, x)).as_dummy()
607 Integral(_0, (_0, x))
608 >>> _.variables[0].is_real is None
609 True
610 >>> r.as_dummy()
611 _r
613 Notes
614 =====
616 Any object that has structurally bound variables should have
617 a property, `bound_symbols` that returns those symbols
618 appearing in the object.
619 """
620 from .symbol import Dummy, Symbol
621 def can(x):
622 # mask free that shadow bound
623 free = x.free_symbols
624 bound = set(x.bound_symbols)
625 d = {i: Dummy() for i in bound & free}
626 x = x.subs(d)
627 # replace bound with canonical names
628 x = x.xreplace(x.canonical_variables)
629 # return after undoing masking
630 return x.xreplace({v: k for k, v in d.items()})
631 if not self.has(Symbol):
632 return self
633 return self.replace(
634 lambda x: hasattr(x, 'bound_symbols'),
635 can,
636 simultaneous=False)
638 @property
639 def canonical_variables(self):
640 """Return a dictionary mapping any variable defined in
641 ``self.bound_symbols`` to Symbols that do not clash
642 with any free symbols in the expression.
644 Examples
645 ========
647 >>> from sympy import Lambda
648 >>> from sympy.abc import x
649 >>> Lambda(x, 2*x).canonical_variables
650 {x: _0}
651 """
652 if not hasattr(self, 'bound_symbols'):
653 return {}
654 dums = numbered_symbols('_')
655 reps = {}
656 # watch out for free symbol that are not in bound symbols;
657 # those that are in bound symbols are about to get changed
658 bound = self.bound_symbols
659 names = {i.name for i in self.free_symbols - set(bound)}
660 for b in bound:
661 d = next(dums)
662 if b.is_Symbol:
663 while d.name in names:
664 d = next(dums)
665 reps[b] = d
666 return reps
668 def rcall(self, *args):
669 """Apply on the argument recursively through the expression tree.
671 This method is used to simulate a common abuse of notation for
672 operators. For instance, in SymPy the following will not work:
674 ``(x+Lambda(y, 2*y))(z) == x+2*z``,
676 however, you can use:
678 >>> from sympy import Lambda
679 >>> from sympy.abc import x, y, z
680 >>> (x + Lambda(y, 2*y)).rcall(z)
681 x + 2*z
682 """
683 return Basic._recursive_call(self, args)
685 @staticmethod
686 def _recursive_call(expr_to_call, on_args):
687 """Helper for rcall method."""
688 from .symbol import Symbol
689 def the_call_method_is_overridden(expr):
690 for cls in getmro(type(expr)):
691 if '__call__' in cls.__dict__:
692 return cls != Basic
694 if callable(expr_to_call) and the_call_method_is_overridden(expr_to_call):
695 if isinstance(expr_to_call, Symbol): # XXX When you call a Symbol it is
696 return expr_to_call # transformed into an UndefFunction
697 else:
698 return expr_to_call(*on_args)
699 elif expr_to_call.args:
700 args = [Basic._recursive_call(
701 sub, on_args) for sub in expr_to_call.args]
702 return type(expr_to_call)(*args)
703 else:
704 return expr_to_call
706 def is_hypergeometric(self, k):
707 from sympy.simplify.simplify import hypersimp
708 from sympy.functions.elementary.piecewise import Piecewise
709 if self.has(Piecewise):
710 return None
711 return hypersimp(self, k) is not None
713 @property
714 def is_comparable(self):
715 """Return True if self can be computed to a real number
716 (or already is a real number) with precision, else False.
718 Examples
719 ========
721 >>> from sympy import exp_polar, pi, I
722 >>> (I*exp_polar(I*pi/2)).is_comparable
723 True
724 >>> (I*exp_polar(I*pi*2)).is_comparable
725 False
727 A False result does not mean that `self` cannot be rewritten
728 into a form that would be comparable. For example, the
729 difference computed below is zero but without simplification
730 it does not evaluate to a zero with precision:
732 >>> e = 2**pi*(1 + 2**pi)
733 >>> dif = e - e.expand()
734 >>> dif.is_comparable
735 False
736 >>> dif.n(2)._prec
737 1
739 """
740 is_extended_real = self.is_extended_real
741 if is_extended_real is False:
742 return False
743 if not self.is_number:
744 return False
745 # don't re-eval numbers that are already evaluated since
746 # this will create spurious precision
747 n, i = [p.evalf(2) if not p.is_Number else p
748 for p in self.as_real_imag()]
749 if not (i.is_Number and n.is_Number):
750 return False
751 if i:
752 # if _prec = 1 we can't decide and if not,
753 # the answer is False because numbers with
754 # imaginary parts can't be compared
755 # so return False
756 return False
757 else:
758 return n._prec != 1
760 @property
761 def func(self):
762 """
763 The top-level function in an expression.
765 The following should hold for all objects::
767 >> x == x.func(*x.args)
769 Examples
770 ========
772 >>> from sympy.abc import x
773 >>> a = 2*x
774 >>> a.func
775 <class 'sympy.core.mul.Mul'>
776 >>> a.args
777 (2, x)
778 >>> a.func(*a.args)
779 2*x
780 >>> a == a.func(*a.args)
781 True
783 """
784 return self.__class__
786 @property
787 def args(self) -> tuple[Basic, ...]:
788 """Returns a tuple of arguments of 'self'.
790 Examples
791 ========
793 >>> from sympy import cot
794 >>> from sympy.abc import x, y
796 >>> cot(x).args
797 (x,)
799 >>> cot(x).args[0]
800 x
802 >>> (x*y).args
803 (x, y)
805 >>> (x*y).args[1]
806 y
808 Notes
809 =====
811 Never use self._args, always use self.args.
812 Only use _args in __new__ when creating a new function.
813 Do not override .args() from Basic (so that it is easy to
814 change the interface in the future if needed).
815 """
816 return self._args
818 @property
819 def _sorted_args(self):
820 """
821 The same as ``args``. Derived classes which do not fix an
822 order on their arguments should override this method to
823 produce the sorted representation.
824 """
825 return self.args
827 def as_content_primitive(self, radical=False, clear=True):
828 """A stub to allow Basic args (like Tuple) to be skipped when computing
829 the content and primitive components of an expression.
831 See Also
832 ========
834 sympy.core.expr.Expr.as_content_primitive
835 """
836 return S.One, self
838 def subs(self, *args, **kwargs):
839 """
840 Substitutes old for new in an expression after sympifying args.
842 `args` is either:
843 - two arguments, e.g. foo.subs(old, new)
844 - one iterable argument, e.g. foo.subs(iterable). The iterable may be
845 o an iterable container with (old, new) pairs. In this case the
846 replacements are processed in the order given with successive
847 patterns possibly affecting replacements already made.
848 o a dict or set whose key/value items correspond to old/new pairs.
849 In this case the old/new pairs will be sorted by op count and in
850 case of a tie, by number of args and the default_sort_key. The
851 resulting sorted list is then processed as an iterable container
852 (see previous).
854 If the keyword ``simultaneous`` is True, the subexpressions will not be
855 evaluated until all the substitutions have been made.
857 Examples
858 ========
860 >>> from sympy import pi, exp, limit, oo
861 >>> from sympy.abc import x, y
862 >>> (1 + x*y).subs(x, pi)
863 pi*y + 1
864 >>> (1 + x*y).subs({x:pi, y:2})
865 1 + 2*pi
866 >>> (1 + x*y).subs([(x, pi), (y, 2)])
867 1 + 2*pi
868 >>> reps = [(y, x**2), (x, 2)]
869 >>> (x + y).subs(reps)
870 6
871 >>> (x + y).subs(reversed(reps))
872 x**2 + 2
874 >>> (x**2 + x**4).subs(x**2, y)
875 y**2 + y
877 To replace only the x**2 but not the x**4, use xreplace:
879 >>> (x**2 + x**4).xreplace({x**2: y})
880 x**4 + y
882 To delay evaluation until all substitutions have been made,
883 set the keyword ``simultaneous`` to True:
885 >>> (x/y).subs([(x, 0), (y, 0)])
886 0
887 >>> (x/y).subs([(x, 0), (y, 0)], simultaneous=True)
888 nan
890 This has the added feature of not allowing subsequent substitutions
891 to affect those already made:
893 >>> ((x + y)/y).subs({x + y: y, y: x + y})
894 1
895 >>> ((x + y)/y).subs({x + y: y, y: x + y}, simultaneous=True)
896 y/(x + y)
898 In order to obtain a canonical result, unordered iterables are
899 sorted by count_op length, number of arguments and by the
900 default_sort_key to break any ties. All other iterables are left
901 unsorted.
903 >>> from sympy import sqrt, sin, cos
904 >>> from sympy.abc import a, b, c, d, e
906 >>> A = (sqrt(sin(2*x)), a)
907 >>> B = (sin(2*x), b)
908 >>> C = (cos(2*x), c)
909 >>> D = (x, d)
910 >>> E = (exp(x), e)
912 >>> expr = sqrt(sin(2*x))*sin(exp(x)*x)*cos(2*x) + sin(2*x)
914 >>> expr.subs(dict([A, B, C, D, E]))
915 a*c*sin(d*e) + b
917 The resulting expression represents a literal replacement of the
918 old arguments with the new arguments. This may not reflect the
919 limiting behavior of the expression:
921 >>> (x**3 - 3*x).subs({x: oo})
922 nan
924 >>> limit(x**3 - 3*x, x, oo)
925 oo
927 If the substitution will be followed by numerical
928 evaluation, it is better to pass the substitution to
929 evalf as
931 >>> (1/x).evalf(subs={x: 3.0}, n=21)
932 0.333333333333333333333
934 rather than
936 >>> (1/x).subs({x: 3.0}).evalf(21)
937 0.333333333333333314830
939 as the former will ensure that the desired level of precision is
940 obtained.
942 See Also
943 ========
944 replace: replacement capable of doing wildcard-like matching,
945 parsing of match, and conditional replacements
946 xreplace: exact node replacement in expr tree; also capable of
947 using matching rules
948 sympy.core.evalf.EvalfMixin.evalf: calculates the given formula to a desired level of precision
950 """
951 from .containers import Dict
952 from .symbol import Dummy, Symbol
953 from .numbers import _illegal
955 unordered = False
956 if len(args) == 1:
958 sequence = args[0]
959 if isinstance(sequence, set):
960 unordered = True
961 elif isinstance(sequence, (Dict, Mapping)):
962 unordered = True
963 sequence = sequence.items()
964 elif not iterable(sequence):
965 raise ValueError(filldedent("""
966 When a single argument is passed to subs
967 it should be a dictionary of old: new pairs or an iterable
968 of (old, new) tuples."""))
969 elif len(args) == 2:
970 sequence = [args]
971 else:
972 raise ValueError("subs accepts either 1 or 2 arguments")
974 def sympify_old(old):
975 if isinstance(old, str):
976 # Use Symbol rather than parse_expr for old
977 return Symbol(old)
978 elif isinstance(old, type):
979 # Allow a type e.g. Function('f') or sin
980 return sympify(old, strict=False)
981 else:
982 return sympify(old, strict=True)
984 def sympify_new(new):
985 if isinstance(new, (str, type)):
986 # Allow a type or parse a string input
987 return sympify(new, strict=False)
988 else:
989 return sympify(new, strict=True)
991 sequence = [(sympify_old(s1), sympify_new(s2)) for s1, s2 in sequence]
993 # skip if there is no change
994 sequence = [(s1, s2) for s1, s2 in sequence if not _aresame(s1, s2)]
996 simultaneous = kwargs.pop('simultaneous', False)
998 if unordered:
999 from .sorting import _nodes, default_sort_key
1000 sequence = dict(sequence)
1001 # order so more complex items are first and items
1002 # of identical complexity are ordered so
1003 # f(x) < f(y) < x < y
1004 # \___ 2 __/ \_1_/ <- number of nodes
1005 #
1006 # For more complex ordering use an unordered sequence.
1007 k = list(ordered(sequence, default=False, keys=(
1008 lambda x: -_nodes(x),
1009 default_sort_key,
1010 )))
1011 sequence = [(k, sequence[k]) for k in k]
1012 # do infinities first
1013 if not simultaneous:
1014 redo = [i for i, seq in enumerate(sequence) if seq[1] in _illegal]
1015 for i in reversed(redo):
1016 sequence.insert(0, sequence.pop(i))
1018 if simultaneous: # XXX should this be the default for dict subs?
1019 reps = {}
1020 rv = self
1021 kwargs['hack2'] = True
1022 m = Dummy('subs_m')
1023 for old, new in sequence:
1024 com = new.is_commutative
1025 if com is None:
1026 com = True
1027 d = Dummy('subs_d', commutative=com)
1028 # using d*m so Subs will be used on dummy variables
1029 # in things like Derivative(f(x, y), x) in which x
1030 # is both free and bound
1031 rv = rv._subs(old, d*m, **kwargs)
1032 if not isinstance(rv, Basic):
1033 break
1034 reps[d] = new
1035 reps[m] = S.One # get rid of m
1036 return rv.xreplace(reps)
1037 else:
1038 rv = self
1039 for old, new in sequence:
1040 rv = rv._subs(old, new, **kwargs)
1041 if not isinstance(rv, Basic):
1042 break
1043 return rv
1045 @cacheit
1046 def _subs(self, old, new, **hints):
1047 """Substitutes an expression old -> new.
1049 If self is not equal to old then _eval_subs is called.
1050 If _eval_subs does not want to make any special replacement
1051 then a None is received which indicates that the fallback
1052 should be applied wherein a search for replacements is made
1053 amongst the arguments of self.
1055 >>> from sympy import Add
1056 >>> from sympy.abc import x, y, z
1058 Examples
1059 ========
1061 Add's _eval_subs knows how to target x + y in the following
1062 so it makes the change:
1064 >>> (x + y + z).subs(x + y, 1)
1065 z + 1
1067 Add's _eval_subs does not need to know how to find x + y in
1068 the following:
1070 >>> Add._eval_subs(z*(x + y) + 3, x + y, 1) is None
1071 True
1073 The returned None will cause the fallback routine to traverse the args and
1074 pass the z*(x + y) arg to Mul where the change will take place and the
1075 substitution will succeed:
1077 >>> (z*(x + y) + 3).subs(x + y, 1)
1078 z + 3
1080 ** Developers Notes **
1082 An _eval_subs routine for a class should be written if:
1084 1) any arguments are not instances of Basic (e.g. bool, tuple);
1086 2) some arguments should not be targeted (as in integration
1087 variables);
1089 3) if there is something other than a literal replacement
1090 that should be attempted (as in Piecewise where the condition
1091 may be updated without doing a replacement).
1093 If it is overridden, here are some special cases that might arise:
1095 1) If it turns out that no special change was made and all
1096 the original sub-arguments should be checked for
1097 replacements then None should be returned.
1099 2) If it is necessary to do substitutions on a portion of
1100 the expression then _subs should be called. _subs will
1101 handle the case of any sub-expression being equal to old
1102 (which usually would not be the case) while its fallback
1103 will handle the recursion into the sub-arguments. For
1104 example, after Add's _eval_subs removes some matching terms
1105 it must process the remaining terms so it calls _subs
1106 on each of the un-matched terms and then adds them
1107 onto the terms previously obtained.
1109 3) If the initial expression should remain unchanged then
1110 the original expression should be returned. (Whenever an
1111 expression is returned, modified or not, no further
1112 substitution of old -> new is attempted.) Sum's _eval_subs
1113 routine uses this strategy when a substitution is attempted
1114 on any of its summation variables.
1115 """
1117 def fallback(self, old, new):
1118 """
1119 Try to replace old with new in any of self's arguments.
1120 """
1121 hit = False
1122 args = list(self.args)
1123 for i, arg in enumerate(args):
1124 if not hasattr(arg, '_eval_subs'):
1125 continue
1126 arg = arg._subs(old, new, **hints)
1127 if not _aresame(arg, args[i]):
1128 hit = True
1129 args[i] = arg
1130 if hit:
1131 rv = self.func(*args)
1132 hack2 = hints.get('hack2', False)
1133 if hack2 and self.is_Mul and not rv.is_Mul: # 2-arg hack
1134 coeff = S.One
1135 nonnumber = []
1136 for i in args:
1137 if i.is_Number:
1138 coeff *= i
1139 else:
1140 nonnumber.append(i)
1141 nonnumber = self.func(*nonnumber)
1142 if coeff is S.One:
1143 return nonnumber
1144 else:
1145 return self.func(coeff, nonnumber, evaluate=False)
1146 return rv
1147 return self
1149 if _aresame(self, old):
1150 return new
1152 rv = self._eval_subs(old, new)
1153 if rv is None:
1154 rv = fallback(self, old, new)
1155 return rv
1157 def _eval_subs(self, old, new):
1158 """Override this stub if you want to do anything more than
1159 attempt a replacement of old with new in the arguments of self.
1161 See also
1162 ========
1164 _subs
1165 """
1166 return None
1168 def xreplace(self, rule):
1169 """
1170 Replace occurrences of objects within the expression.
1172 Parameters
1173 ==========
1175 rule : dict-like
1176 Expresses a replacement rule
1178 Returns
1179 =======
1181 xreplace : the result of the replacement
1183 Examples
1184 ========
1186 >>> from sympy import symbols, pi, exp
1187 >>> x, y, z = symbols('x y z')
1188 >>> (1 + x*y).xreplace({x: pi})
1189 pi*y + 1
1190 >>> (1 + x*y).xreplace({x: pi, y: 2})
1191 1 + 2*pi
1193 Replacements occur only if an entire node in the expression tree is
1194 matched:
1196 >>> (x*y + z).xreplace({x*y: pi})
1197 z + pi
1198 >>> (x*y*z).xreplace({x*y: pi})
1199 x*y*z
1200 >>> (2*x).xreplace({2*x: y, x: z})
1201 y
1202 >>> (2*2*x).xreplace({2*x: y, x: z})
1203 4*z
1204 >>> (x + y + 2).xreplace({x + y: 2})
1205 x + y + 2
1206 >>> (x + 2 + exp(x + 2)).xreplace({x + 2: y})
1207 x + exp(y) + 2
1209 xreplace does not differentiate between free and bound symbols. In the
1210 following, subs(x, y) would not change x since it is a bound symbol,
1211 but xreplace does:
1213 >>> from sympy import Integral
1214 >>> Integral(x, (x, 1, 2*x)).xreplace({x: y})
1215 Integral(y, (y, 1, 2*y))
1217 Trying to replace x with an expression raises an error:
1219 >>> Integral(x, (x, 1, 2*x)).xreplace({x: 2*y}) # doctest: +SKIP
1220 ValueError: Invalid limits given: ((2*y, 1, 4*y),)
1222 See Also
1223 ========
1224 replace: replacement capable of doing wildcard-like matching,
1225 parsing of match, and conditional replacements
1226 subs: substitution of subexpressions as defined by the objects
1227 themselves.
1229 """
1230 value, _ = self._xreplace(rule)
1231 return value
1233 def _xreplace(self, rule):
1234 """
1235 Helper for xreplace. Tracks whether a replacement actually occurred.
1236 """
1237 if self in rule:
1238 return rule[self], True
1239 elif rule:
1240 args = []
1241 changed = False
1242 for a in self.args:
1243 _xreplace = getattr(a, '_xreplace', None)
1244 if _xreplace is not None:
1245 a_xr = _xreplace(rule)
1246 args.append(a_xr[0])
1247 changed |= a_xr[1]
1248 else:
1249 args.append(a)
1250 args = tuple(args)
1251 if changed:
1252 return self.func(*args), True
1253 return self, False
1255 @cacheit
1256 def has(self, *patterns):
1257 """
1258 Test whether any subexpression matches any of the patterns.
1260 Examples
1261 ========
1263 >>> from sympy import sin
1264 >>> from sympy.abc import x, y, z
1265 >>> (x**2 + sin(x*y)).has(z)
1266 False
1267 >>> (x**2 + sin(x*y)).has(x, y, z)
1268 True
1269 >>> x.has(x)
1270 True
1272 Note ``has`` is a structural algorithm with no knowledge of
1273 mathematics. Consider the following half-open interval:
1275 >>> from sympy import Interval
1276 >>> i = Interval.Lopen(0, 5); i
1277 Interval.Lopen(0, 5)
1278 >>> i.args
1279 (0, 5, True, False)
1280 >>> i.has(4) # there is no "4" in the arguments
1281 False
1282 >>> i.has(0) # there *is* a "0" in the arguments
1283 True
1285 Instead, use ``contains`` to determine whether a number is in the
1286 interval or not:
1288 >>> i.contains(4)
1289 True
1290 >>> i.contains(0)
1291 False
1294 Note that ``expr.has(*patterns)`` is exactly equivalent to
1295 ``any(expr.has(p) for p in patterns)``. In particular, ``False`` is
1296 returned when the list of patterns is empty.
1298 >>> x.has()
1299 False
1301 """
1302 return self._has(iterargs, *patterns)
1304 def has_xfree(self, s: set[Basic]):
1305 """Return True if self has any of the patterns in s as a
1306 free argument, else False. This is like `Basic.has_free`
1307 but this will only report exact argument matches.
1309 Examples
1310 ========
1312 >>> from sympy import Function
1313 >>> from sympy.abc import x, y
1314 >>> f = Function('f')
1315 >>> f(x).has_xfree({f})
1316 False
1317 >>> f(x).has_xfree({f(x)})
1318 True
1319 >>> f(x + 1).has_xfree({x})
1320 True
1321 >>> f(x + 1).has_xfree({x + 1})
1322 True
1323 >>> f(x + y + 1).has_xfree({x + 1})
1324 False
1325 """
1326 # protect O(1) containment check by requiring:
1327 if type(s) is not set:
1328 raise TypeError('expecting set argument')
1329 return any(a in s for a in iterfreeargs(self))
1331 @cacheit
1332 def has_free(self, *patterns):
1333 """Return True if self has object(s) ``x`` as a free expression
1334 else False.
1336 Examples
1337 ========
1339 >>> from sympy import Integral, Function
1340 >>> from sympy.abc import x, y
1341 >>> f = Function('f')
1342 >>> g = Function('g')
1343 >>> expr = Integral(f(x), (f(x), 1, g(y)))
1344 >>> expr.free_symbols
1345 {y}
1346 >>> expr.has_free(g(y))
1347 True
1348 >>> expr.has_free(*(x, f(x)))
1349 False
1351 This works for subexpressions and types, too:
1353 >>> expr.has_free(g)
1354 True
1355 >>> (x + y + 1).has_free(y + 1)
1356 True
1357 """
1358 if not patterns:
1359 return False
1360 p0 = patterns[0]
1361 if len(patterns) == 1 and iterable(p0) and not isinstance(p0, Basic):
1362 # Basic can contain iterables (though not non-Basic, ideally)
1363 # but don't encourage mixed passing patterns
1364 raise TypeError(filldedent('''
1365 Expecting 1 or more Basic args, not a single
1366 non-Basic iterable. Don't forget to unpack
1367 iterables: `eq.has_free(*patterns)`'''))
1368 # try quick test first
1369 s = set(patterns)
1370 rv = self.has_xfree(s)
1371 if rv:
1372 return rv
1373 # now try matching through slower _has
1374 return self._has(iterfreeargs, *patterns)
1376 def _has(self, iterargs, *patterns):
1377 # separate out types and unhashable objects
1378 type_set = set() # only types
1379 p_set = set() # hashable non-types
1380 for p in patterns:
1381 if isinstance(p, type) and issubclass(p, Basic):
1382 type_set.add(p)
1383 continue
1384 if not isinstance(p, Basic):
1385 try:
1386 p = _sympify(p)
1387 except SympifyError:
1388 continue # Basic won't have this in it
1389 p_set.add(p) # fails if object defines __eq__ but
1390 # doesn't define __hash__
1391 types = tuple(type_set) #
1392 for i in iterargs(self): #
1393 if i in p_set: # <--- here, too
1394 return True
1395 if isinstance(i, types):
1396 return True
1398 # use matcher if defined, e.g. operations defines
1399 # matcher that checks for exact subset containment,
1400 # (x + y + 1).has(x + 1) -> True
1401 for i in p_set - type_set: # types don't have matchers
1402 if not hasattr(i, '_has_matcher'):
1403 continue
1404 match = i._has_matcher()
1405 if any(match(arg) for arg in iterargs(self)):
1406 return True
1408 # no success
1409 return False
1411 def replace(self, query, value, map=False, simultaneous=True, exact=None):
1412 """
1413 Replace matching subexpressions of ``self`` with ``value``.
1415 If ``map = True`` then also return the mapping {old: new} where ``old``
1416 was a sub-expression found with query and ``new`` is the replacement
1417 value for it. If the expression itself does not match the query, then
1418 the returned value will be ``self.xreplace(map)`` otherwise it should
1419 be ``self.subs(ordered(map.items()))``.
1421 Traverses an expression tree and performs replacement of matching
1422 subexpressions from the bottom to the top of the tree. The default
1423 approach is to do the replacement in a simultaneous fashion so
1424 changes made are targeted only once. If this is not desired or causes
1425 problems, ``simultaneous`` can be set to False.
1427 In addition, if an expression containing more than one Wild symbol
1428 is being used to match subexpressions and the ``exact`` flag is None
1429 it will be set to True so the match will only succeed if all non-zero
1430 values are received for each Wild that appears in the match pattern.
1431 Setting this to False accepts a match of 0; while setting it True
1432 accepts all matches that have a 0 in them. See example below for
1433 cautions.
1435 The list of possible combinations of queries and replacement values
1436 is listed below:
1438 Examples
1439 ========
1441 Initial setup
1443 >>> from sympy import log, sin, cos, tan, Wild, Mul, Add
1444 >>> from sympy.abc import x, y
1445 >>> f = log(sin(x)) + tan(sin(x**2))
1447 1.1. type -> type
1448 obj.replace(type, newtype)
1450 When object of type ``type`` is found, replace it with the
1451 result of passing its argument(s) to ``newtype``.
1453 >>> f.replace(sin, cos)
1454 log(cos(x)) + tan(cos(x**2))
1455 >>> sin(x).replace(sin, cos, map=True)
1456 (cos(x), {sin(x): cos(x)})
1457 >>> (x*y).replace(Mul, Add)
1458 x + y
1460 1.2. type -> func
1461 obj.replace(type, func)
1463 When object of type ``type`` is found, apply ``func`` to its
1464 argument(s). ``func`` must be written to handle the number
1465 of arguments of ``type``.
1467 >>> f.replace(sin, lambda arg: sin(2*arg))
1468 log(sin(2*x)) + tan(sin(2*x**2))
1469 >>> (x*y).replace(Mul, lambda *args: sin(2*Mul(*args)))
1470 sin(2*x*y)
1472 2.1. pattern -> expr
1473 obj.replace(pattern(wild), expr(wild))
1475 Replace subexpressions matching ``pattern`` with the expression
1476 written in terms of the Wild symbols in ``pattern``.
1478 >>> a, b = map(Wild, 'ab')
1479 >>> f.replace(sin(a), tan(a))
1480 log(tan(x)) + tan(tan(x**2))
1481 >>> f.replace(sin(a), tan(a/2))
1482 log(tan(x/2)) + tan(tan(x**2/2))
1483 >>> f.replace(sin(a), a)
1484 log(x) + tan(x**2)
1485 >>> (x*y).replace(a*x, a)
1486 y
1488 Matching is exact by default when more than one Wild symbol
1489 is used: matching fails unless the match gives non-zero
1490 values for all Wild symbols:
1492 >>> (2*x + y).replace(a*x + b, b - a)
1493 y - 2
1494 >>> (2*x).replace(a*x + b, b - a)
1495 2*x
1497 When set to False, the results may be non-intuitive:
1499 >>> (2*x).replace(a*x + b, b - a, exact=False)
1500 2/x
1502 2.2. pattern -> func
1503 obj.replace(pattern(wild), lambda wild: expr(wild))
1505 All behavior is the same as in 2.1 but now a function in terms of
1506 pattern variables is used rather than an expression:
1508 >>> f.replace(sin(a), lambda a: sin(2*a))
1509 log(sin(2*x)) + tan(sin(2*x**2))
1511 3.1. func -> func
1512 obj.replace(filter, func)
1514 Replace subexpression ``e`` with ``func(e)`` if ``filter(e)``
1515 is True.
1517 >>> g = 2*sin(x**3)
1518 >>> g.replace(lambda expr: expr.is_Number, lambda expr: expr**2)
1519 4*sin(x**9)
1521 The expression itself is also targeted by the query but is done in
1522 such a fashion that changes are not made twice.
1524 >>> e = x*(x*y + 1)
1525 >>> e.replace(lambda x: x.is_Mul, lambda x: 2*x)
1526 2*x*(2*x*y + 1)
1528 When matching a single symbol, `exact` will default to True, but
1529 this may or may not be the behavior that is desired:
1531 Here, we want `exact=False`:
1533 >>> from sympy import Function
1534 >>> f = Function('f')
1535 >>> e = f(1) + f(0)
1536 >>> q = f(a), lambda a: f(a + 1)
1537 >>> e.replace(*q, exact=False)
1538 f(1) + f(2)
1539 >>> e.replace(*q, exact=True)
1540 f(0) + f(2)
1542 But here, the nature of matching makes selecting
1543 the right setting tricky:
1545 >>> e = x**(1 + y)
1546 >>> (x**(1 + y)).replace(x**(1 + a), lambda a: x**-a, exact=False)
1547 x
1548 >>> (x**(1 + y)).replace(x**(1 + a), lambda a: x**-a, exact=True)
1549 x**(-x - y + 1)
1550 >>> (x**y).replace(x**(1 + a), lambda a: x**-a, exact=False)
1551 x
1552 >>> (x**y).replace(x**(1 + a), lambda a: x**-a, exact=True)
1553 x**(1 - y)
1555 It is probably better to use a different form of the query
1556 that describes the target expression more precisely:
1558 >>> (1 + x**(1 + y)).replace(
1559 ... lambda x: x.is_Pow and x.exp.is_Add and x.exp.args[0] == 1,
1560 ... lambda x: x.base**(1 - (x.exp - 1)))
1561 ...
1562 x**(1 - y) + 1
1564 See Also
1565 ========
1567 subs: substitution of subexpressions as defined by the objects
1568 themselves.
1569 xreplace: exact node replacement in expr tree; also capable of
1570 using matching rules
1572 """
1574 try:
1575 query = _sympify(query)
1576 except SympifyError:
1577 pass
1578 try:
1579 value = _sympify(value)
1580 except SympifyError:
1581 pass
1582 if isinstance(query, type):
1583 _query = lambda expr: isinstance(expr, query)
1585 if isinstance(value, type):
1586 _value = lambda expr, result: value(*expr.args)
1587 elif callable(value):
1588 _value = lambda expr, result: value(*expr.args)
1589 else:
1590 raise TypeError(
1591 "given a type, replace() expects another "
1592 "type or a callable")
1593 elif isinstance(query, Basic):
1594 _query = lambda expr: expr.match(query)
1595 if exact is None:
1596 from .symbol import Wild
1597 exact = (len(query.atoms(Wild)) > 1)
1599 if isinstance(value, Basic):
1600 if exact:
1601 _value = lambda expr, result: (value.subs(result)
1602 if all(result.values()) else expr)
1603 else:
1604 _value = lambda expr, result: value.subs(result)
1605 elif callable(value):
1606 # match dictionary keys get the trailing underscore stripped
1607 # from them and are then passed as keywords to the callable;
1608 # if ``exact`` is True, only accept match if there are no null
1609 # values amongst those matched.
1610 if exact:
1611 _value = lambda expr, result: (value(**
1612 {str(k)[:-1]: v for k, v in result.items()})
1613 if all(val for val in result.values()) else expr)
1614 else:
1615 _value = lambda expr, result: value(**
1616 {str(k)[:-1]: v for k, v in result.items()})
1617 else:
1618 raise TypeError(
1619 "given an expression, replace() expects "
1620 "another expression or a callable")
1621 elif callable(query):
1622 _query = query
1624 if callable(value):
1625 _value = lambda expr, result: value(expr)
1626 else:
1627 raise TypeError(
1628 "given a callable, replace() expects "
1629 "another callable")
1630 else:
1631 raise TypeError(
1632 "first argument to replace() must be a "
1633 "type, an expression or a callable")
1635 def walk(rv, F):
1636 """Apply ``F`` to args and then to result.
1637 """
1638 args = getattr(rv, 'args', None)
1639 if args is not None:
1640 if args:
1641 newargs = tuple([walk(a, F) for a in args])
1642 if args != newargs:
1643 rv = rv.func(*newargs)
1644 if simultaneous:
1645 # if rv is something that was already
1646 # matched (that was changed) then skip
1647 # applying F again
1648 for i, e in enumerate(args):
1649 if rv == e and e != newargs[i]:
1650 return rv
1651 rv = F(rv)
1652 return rv
1654 mapping = {} # changes that took place
1656 def rec_replace(expr):
1657 result = _query(expr)
1658 if result or result == {}:
1659 v = _value(expr, result)
1660 if v is not None and v != expr:
1661 if map:
1662 mapping[expr] = v
1663 expr = v
1664 return expr
1666 rv = walk(self, rec_replace)
1667 return (rv, mapping) if map else rv
1669 def find(self, query, group=False):
1670 """Find all subexpressions matching a query."""
1671 query = _make_find_query(query)
1672 results = list(filter(query, _preorder_traversal(self)))
1674 if not group:
1675 return set(results)
1676 else:
1677 groups = {}
1679 for result in results:
1680 if result in groups:
1681 groups[result] += 1
1682 else:
1683 groups[result] = 1
1685 return groups
1687 def count(self, query):
1688 """Count the number of matching subexpressions."""
1689 query = _make_find_query(query)
1690 return sum(bool(query(sub)) for sub in _preorder_traversal(self))
1692 def matches(self, expr, repl_dict=None, old=False):
1693 """
1694 Helper method for match() that looks for a match between Wild symbols
1695 in self and expressions in expr.
1697 Examples
1698 ========
1700 >>> from sympy import symbols, Wild, Basic
1701 >>> a, b, c = symbols('a b c')
1702 >>> x = Wild('x')
1703 >>> Basic(a + x, x).matches(Basic(a + b, c)) is None
1704 True
1705 >>> Basic(a + x, x).matches(Basic(a + b + c, b + c))
1706 {x_: b + c}
1707 """
1708 expr = sympify(expr)
1709 if not isinstance(expr, self.__class__):
1710 return None
1712 if repl_dict is None:
1713 repl_dict = {}
1714 else:
1715 repl_dict = repl_dict.copy()
1717 if self == expr:
1718 return repl_dict
1720 if len(self.args) != len(expr.args):
1721 return None
1723 d = repl_dict # already a copy
1724 for arg, other_arg in zip(self.args, expr.args):
1725 if arg == other_arg:
1726 continue
1727 if arg.is_Relational:
1728 try:
1729 d = arg.xreplace(d).matches(other_arg, d, old=old)
1730 except TypeError: # Should be InvalidComparisonError when introduced
1731 d = None
1732 else:
1733 d = arg.xreplace(d).matches(other_arg, d, old=old)
1734 if d is None:
1735 return None
1736 return d
1738 def match(self, pattern, old=False):
1739 """
1740 Pattern matching.
1742 Wild symbols match all.
1744 Return ``None`` when expression (self) does not match
1745 with pattern. Otherwise return a dictionary such that::
1747 pattern.xreplace(self.match(pattern)) == self
1749 Examples
1750 ========
1752 >>> from sympy import Wild, Sum
1753 >>> from sympy.abc import x, y
1754 >>> p = Wild("p")
1755 >>> q = Wild("q")
1756 >>> r = Wild("r")
1757 >>> e = (x+y)**(x+y)
1758 >>> e.match(p**p)
1759 {p_: x + y}
1760 >>> e.match(p**q)
1761 {p_: x + y, q_: x + y}
1762 >>> e = (2*x)**2
1763 >>> e.match(p*q**r)
1764 {p_: 4, q_: x, r_: 2}
1765 >>> (p*q**r).xreplace(e.match(p*q**r))
1766 4*x**2
1768 Structurally bound symbols are ignored during matching:
1770 >>> Sum(x, (x, 1, 2)).match(Sum(y, (y, 1, p)))
1771 {p_: 2}
1773 But they can be identified if desired:
1775 >>> Sum(x, (x, 1, 2)).match(Sum(q, (q, 1, p)))
1776 {p_: 2, q_: x}
1778 The ``old`` flag will give the old-style pattern matching where
1779 expressions and patterns are essentially solved to give the
1780 match. Both of the following give None unless ``old=True``:
1782 >>> (x - 2).match(p - x, old=True)
1783 {p_: 2*x - 2}
1784 >>> (2/x).match(p*x, old=True)
1785 {p_: 2/x**2}
1787 """
1788 pattern = sympify(pattern)
1789 # match non-bound symbols
1790 canonical = lambda x: x if x.is_Symbol else x.as_dummy()
1791 m = canonical(pattern).matches(canonical(self), old=old)
1792 if m is None:
1793 return m
1794 from .symbol import Wild
1795 from .function import WildFunction
1796 from ..tensor.tensor import WildTensor, WildTensorIndex, WildTensorHead
1797 wild = pattern.atoms(Wild, WildFunction, WildTensor, WildTensorIndex, WildTensorHead)
1798 # sanity check
1799 if set(m) - wild:
1800 raise ValueError(filldedent('''
1801 Some `matches` routine did not use a copy of repl_dict
1802 and injected unexpected symbols. Report this as an
1803 error at https://github.com/sympy/sympy/issues'''))
1804 # now see if bound symbols were requested
1805 bwild = wild - set(m)
1806 if not bwild:
1807 return m
1808 # replace free-Wild symbols in pattern with match result
1809 # so they will match but not be in the next match
1810 wpat = pattern.xreplace(m)
1811 # identify remaining bound wild
1812 w = wpat.matches(self, old=old)
1813 # add them to m
1814 if w:
1815 m.update(w)
1816 # done
1817 return m
1819 def count_ops(self, visual=None):
1820 """Wrapper for count_ops that returns the operation count."""
1821 from .function import count_ops
1822 return count_ops(self, visual)
1824 def doit(self, **hints):
1825 """Evaluate objects that are not evaluated by default like limits,
1826 integrals, sums and products. All objects of this kind will be
1827 evaluated recursively, unless some species were excluded via 'hints'
1828 or unless the 'deep' hint was set to 'False'.
1830 >>> from sympy import Integral
1831 >>> from sympy.abc import x
1833 >>> 2*Integral(x, x)
1834 2*Integral(x, x)
1836 >>> (2*Integral(x, x)).doit()
1837 x**2
1839 >>> (2*Integral(x, x)).doit(deep=False)
1840 2*Integral(x, x)
1842 """
1843 if hints.get('deep', True):
1844 terms = [term.doit(**hints) if isinstance(term, Basic) else term
1845 for term in self.args]
1846 return self.func(*terms)
1847 else:
1848 return self
1850 def simplify(self, **kwargs):
1851 """See the simplify function in sympy.simplify"""
1852 from sympy.simplify.simplify import simplify
1853 return simplify(self, **kwargs)
1855 def refine(self, assumption=True):
1856 """See the refine function in sympy.assumptions"""
1857 from sympy.assumptions.refine import refine
1858 return refine(self, assumption)
1860 def _eval_derivative_n_times(self, s, n):
1861 # This is the default evaluator for derivatives (as called by `diff`
1862 # and `Derivative`), it will attempt a loop to derive the expression
1863 # `n` times by calling the corresponding `_eval_derivative` method,
1864 # while leaving the derivative unevaluated if `n` is symbolic. This
1865 # method should be overridden if the object has a closed form for its
1866 # symbolic n-th derivative.
1867 from .numbers import Integer
1868 if isinstance(n, (int, Integer)):
1869 obj = self
1870 for i in range(n):
1871 obj2 = obj._eval_derivative(s)
1872 if obj == obj2 or obj2 is None:
1873 break
1874 obj = obj2
1875 return obj2
1876 else:
1877 return None
1879 def rewrite(self, *args, deep=True, **hints):
1880 """
1881 Rewrite *self* using a defined rule.
1883 Rewriting transforms an expression to another, which is mathematically
1884 equivalent but structurally different. For example you can rewrite
1885 trigonometric functions as complex exponentials or combinatorial
1886 functions as gamma function.
1888 This method takes a *pattern* and a *rule* as positional arguments.
1889 *pattern* is optional parameter which defines the types of expressions
1890 that will be transformed. If it is not passed, all possible expressions
1891 will be rewritten. *rule* defines how the expression will be rewritten.
1893 Parameters
1894 ==========
1896 args : Expr
1897 A *rule*, or *pattern* and *rule*.
1898 - *pattern* is a type or an iterable of types.
1899 - *rule* can be any object.
1901 deep : bool, optional
1902 If ``True``, subexpressions are recursively transformed. Default is
1903 ``True``.
1905 Examples
1906 ========
1908 If *pattern* is unspecified, all possible expressions are transformed.
1910 >>> from sympy import cos, sin, exp, I
1911 >>> from sympy.abc import x
1912 >>> expr = cos(x) + I*sin(x)
1913 >>> expr.rewrite(exp)
1914 exp(I*x)
1916 Pattern can be a type or an iterable of types.
1918 >>> expr.rewrite(sin, exp)
1919 exp(I*x)/2 + cos(x) - exp(-I*x)/2
1920 >>> expr.rewrite([cos,], exp)
1921 exp(I*x)/2 + I*sin(x) + exp(-I*x)/2
1922 >>> expr.rewrite([cos, sin], exp)
1923 exp(I*x)
1925 Rewriting behavior can be implemented by defining ``_eval_rewrite()``
1926 method.
1928 >>> from sympy import Expr, sqrt, pi
1929 >>> class MySin(Expr):
1930 ... def _eval_rewrite(self, rule, args, **hints):
1931 ... x, = args
1932 ... if rule == cos:
1933 ... return cos(pi/2 - x, evaluate=False)
1934 ... if rule == sqrt:
1935 ... return sqrt(1 - cos(x)**2)
1936 >>> MySin(MySin(x)).rewrite(cos)
1937 cos(-cos(-x + pi/2) + pi/2)
1938 >>> MySin(x).rewrite(sqrt)
1939 sqrt(1 - cos(x)**2)
1941 Defining ``_eval_rewrite_as_[...]()`` method is supported for backwards
1942 compatibility reason. This may be removed in the future and using it is
1943 discouraged.
1945 >>> class MySin(Expr):
1946 ... def _eval_rewrite_as_cos(self, *args, **hints):
1947 ... x, = args
1948 ... return cos(pi/2 - x, evaluate=False)
1949 >>> MySin(x).rewrite(cos)
1950 cos(-x + pi/2)
1952 """
1953 if not args:
1954 return self
1956 hints.update(deep=deep)
1958 pattern = args[:-1]
1959 rule = args[-1]
1961 # support old design by _eval_rewrite_as_[...] method
1962 if isinstance(rule, str):
1963 method = "_eval_rewrite_as_%s" % rule
1964 elif hasattr(rule, "__name__"):
1965 # rule is class or function
1966 clsname = rule.__name__
1967 method = "_eval_rewrite_as_%s" % clsname
1968 else:
1969 # rule is instance
1970 clsname = rule.__class__.__name__
1971 method = "_eval_rewrite_as_%s" % clsname
1973 if pattern:
1974 if iterable(pattern[0]):
1975 pattern = pattern[0]
1976 pattern = tuple(p for p in pattern if self.has(p))
1977 if not pattern:
1978 return self
1979 # hereafter, empty pattern is interpreted as all pattern.
1981 return self._rewrite(pattern, rule, method, **hints)
1983 def _rewrite(self, pattern, rule, method, **hints):
1984 deep = hints.pop('deep', True)
1985 if deep:
1986 args = [a._rewrite(pattern, rule, method, **hints)
1987 for a in self.args]
1988 else:
1989 args = self.args
1990 if not pattern or any(isinstance(self, p) for p in pattern):
1991 meth = getattr(self, method, None)
1992 if meth is not None:
1993 rewritten = meth(*args, **hints)
1994 else:
1995 rewritten = self._eval_rewrite(rule, args, **hints)
1996 if rewritten is not None:
1997 return rewritten
1998 if not args:
1999 return self
2000 return self.func(*args)
2002 def _eval_rewrite(self, rule, args, **hints):
2003 return None
2005 _constructor_postprocessor_mapping = {} # type: ignore
2007 @classmethod
2008 def _exec_constructor_postprocessors(cls, obj):
2009 # WARNING: This API is experimental.
2011 # This is an experimental API that introduces constructor
2012 # postprosessors for SymPy Core elements. If an argument of a SymPy
2013 # expression has a `_constructor_postprocessor_mapping` attribute, it will
2014 # be interpreted as a dictionary containing lists of postprocessing
2015 # functions for matching expression node names.
2017 clsname = obj.__class__.__name__
2018 postprocessors = defaultdict(list)
2019 for i in obj.args:
2020 try:
2021 postprocessor_mappings = (
2022 Basic._constructor_postprocessor_mapping[cls].items()
2023 for cls in type(i).mro()
2024 if cls in Basic._constructor_postprocessor_mapping
2025 )
2026 for k, v in chain.from_iterable(postprocessor_mappings):
2027 postprocessors[k].extend([j for j in v if j not in postprocessors[k]])
2028 except TypeError:
2029 pass
2031 for f in postprocessors.get(clsname, []):
2032 obj = f(obj)
2034 return obj
2036 def _sage_(self):
2037 """
2038 Convert *self* to a symbolic expression of SageMath.
2040 This version of the method is merely a placeholder.
2041 """
2042 old_method = self._sage_
2043 from sage.interfaces.sympy import sympy_init
2044 sympy_init() # may monkey-patch _sage_ method into self's class or superclasses
2045 if old_method == self._sage_:
2046 raise NotImplementedError('conversion to SageMath is not implemented')
2047 else:
2048 # call the freshly monkey-patched method
2049 return self._sage_()
2051 def could_extract_minus_sign(self):
2052 return False # see Expr.could_extract_minus_sign
2055# For all Basic subclasses _prepare_class_assumptions is called by
2056# Basic.__init_subclass__ but that method is not called for Basic itself so we
2057# call the function here instead.
2058_prepare_class_assumptions(Basic)
2061class Atom(Basic):
2062 """
2063 A parent class for atomic things. An atom is an expression with no subexpressions.
2065 Examples
2066 ========
2068 Symbol, Number, Rational, Integer, ...
2069 But not: Add, Mul, Pow, ...
2070 """
2072 is_Atom = True
2074 __slots__ = ()
2076 def matches(self, expr, repl_dict=None, old=False):
2077 if self == expr:
2078 if repl_dict is None:
2079 return {}
2080 return repl_dict.copy()
2082 def xreplace(self, rule, hack2=False):
2083 return rule.get(self, self)
2085 def doit(self, **hints):
2086 return self
2088 @classmethod
2089 def class_key(cls):
2090 return 2, 0, cls.__name__
2092 @cacheit
2093 def sort_key(self, order=None):
2094 return self.class_key(), (1, (str(self),)), S.One.sort_key(), S.One
2096 def _eval_simplify(self, **kwargs):
2097 return self
2099 @property
2100 def _sorted_args(self):
2101 # this is here as a safeguard against accidentally using _sorted_args
2102 # on Atoms -- they cannot be rebuilt as atom.func(*atom._sorted_args)
2103 # since there are no args. So the calling routine should be checking
2104 # to see that this property is not called for Atoms.
2105 raise AttributeError('Atoms have no args. It might be necessary'
2106 ' to make a check for Atoms in the calling code.')
2109def _aresame(a, b):
2110 """Return True if a and b are structurally the same, else False.
2112 Examples
2113 ========
2115 In SymPy (as in Python) two numbers compare the same if they
2116 have the same underlying base-2 representation even though
2117 they may not be the same type:
2119 >>> from sympy import S
2120 >>> 2.0 == S(2)
2121 True
2122 >>> 0.5 == S.Half
2123 True
2125 This routine was written to provide a query for such cases that
2126 would give false when the types do not match:
2128 >>> from sympy.core.basic import _aresame
2129 >>> _aresame(S(2.0), S(2))
2130 False
2132 """
2133 from .numbers import Number
2134 from .function import AppliedUndef, UndefinedFunction as UndefFunc
2135 if isinstance(a, Number) and isinstance(b, Number):
2136 return a == b and a.__class__ == b.__class__
2137 for i, j in zip_longest(_preorder_traversal(a), _preorder_traversal(b)):
2138 if i != j or type(i) != type(j):
2139 if ((isinstance(i, UndefFunc) and isinstance(j, UndefFunc)) or
2140 (isinstance(i, AppliedUndef) and isinstance(j, AppliedUndef))):
2141 if i.class_key() != j.class_key():
2142 return False
2143 else:
2144 return False
2145 return True
2148def _ne(a, b):
2149 # use this as a second test after `a != b` if you want to make
2150 # sure that things are truly equal, e.g.
2151 # a, b = 0.5, S.Half
2152 # a !=b or _ne(a, b) -> True
2153 from .numbers import Number
2154 # 0.5 == S.Half
2155 if isinstance(a, Number) and isinstance(b, Number):
2156 return a.__class__ != b.__class__
2159def _atomic(e, recursive=False):
2160 """Return atom-like quantities as far as substitution is
2161 concerned: Derivatives, Functions and Symbols. Do not
2162 return any 'atoms' that are inside such quantities unless
2163 they also appear outside, too, unless `recursive` is True.
2165 Examples
2166 ========
2168 >>> from sympy import Derivative, Function, cos
2169 >>> from sympy.abc import x, y
2170 >>> from sympy.core.basic import _atomic
2171 >>> f = Function('f')
2172 >>> _atomic(x + y)
2173 {x, y}
2174 >>> _atomic(x + f(y))
2175 {x, f(y)}
2176 >>> _atomic(Derivative(f(x), x) + cos(x) + y)
2177 {y, cos(x), Derivative(f(x), x)}
2179 """
2180 pot = _preorder_traversal(e)
2181 seen = set()
2182 if isinstance(e, Basic):
2183 free = getattr(e, "free_symbols", None)
2184 if free is None:
2185 return {e}
2186 else:
2187 return set()
2188 from .symbol import Symbol
2189 from .function import Derivative, Function
2190 atoms = set()
2191 for p in pot:
2192 if p in seen:
2193 pot.skip()
2194 continue
2195 seen.add(p)
2196 if isinstance(p, Symbol) and p in free:
2197 atoms.add(p)
2198 elif isinstance(p, (Derivative, Function)):
2199 if not recursive:
2200 pot.skip()
2201 atoms.add(p)
2202 return atoms
2205def _make_find_query(query):
2206 """Convert the argument of Basic.find() into a callable"""
2207 try:
2208 query = _sympify(query)
2209 except SympifyError:
2210 pass
2211 if isinstance(query, type):
2212 return lambda expr: isinstance(expr, query)
2213 elif isinstance(query, Basic):
2214 return lambda expr: expr.match(query) is not None
2215 return query
2217# Delayed to avoid cyclic import
2218from .singleton import S
2219from .traversal import (preorder_traversal as _preorder_traversal,
2220 iterargs, iterfreeargs)
2222preorder_traversal = deprecated(
2223 """
2224 Using preorder_traversal from the sympy.core.basic submodule is
2225 deprecated.
2227 Instead, use preorder_traversal from the top-level sympy namespace, like
2229 sympy.preorder_traversal
2230 """,
2231 deprecated_since_version="1.10",
2232 active_deprecations_target="deprecated-traversal-functions-moved",
2233)(_preorder_traversal)