Coverage for /usr/lib/python3/dist-packages/sympy/core/function.py: 36%

1197 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-06-14 15:55 +0200

1""" 

2There are three types of functions implemented in SymPy: 

3 

4 1) defined functions (in the sense that they can be evaluated) like 

5 exp or sin; they have a name and a body: 

6 f = exp 

7 2) undefined function which have a name but no body. Undefined 

8 functions can be defined using a Function class as follows: 

9 f = Function('f') 

10 (the result will be a Function instance) 

11 3) anonymous function (or lambda function) which have a body (defined 

12 with dummy variables) but have no name: 

13 f = Lambda(x, exp(x)*x) 

14 f = Lambda((x, y), exp(x)*y) 

15 The fourth type of functions are composites, like (sin + cos)(x); these work in 

16 SymPy core, but are not yet part of SymPy. 

17 

18 Examples 

19 ======== 

20 

21 >>> import sympy 

22 >>> f = sympy.Function("f") 

23 >>> from sympy.abc import x 

24 >>> f(x) 

25 f(x) 

26 >>> print(sympy.srepr(f(x).func)) 

27 Function('f') 

28 >>> f(x).args 

29 (x,) 

30 

31""" 

32 

33from __future__ import annotations 

34from typing import Any 

35from collections.abc import Iterable 

36 

37from .add import Add 

38from .basic import Basic, _atomic 

39from .cache import cacheit 

40from .containers import Tuple, Dict 

41from .decorators import _sympifyit 

42from .evalf import pure_complex 

43from .expr import Expr, AtomicExpr 

44from .logic import fuzzy_and, fuzzy_or, fuzzy_not, FuzzyBool 

45from .mul import Mul 

46from .numbers import Rational, Float, Integer 

47from .operations import LatticeOp 

48from .parameters import global_parameters 

49from .rules import Transform 

50from .singleton import S 

51from .sympify import sympify, _sympify 

52 

53from .sorting import default_sort_key, ordered 

54from sympy.utilities.exceptions import (sympy_deprecation_warning, 

55 SymPyDeprecationWarning, ignore_warnings) 

56from sympy.utilities.iterables import (has_dups, sift, iterable, 

57 is_sequence, uniq, topological_sort) 

58from sympy.utilities.lambdify import MPMATH_TRANSLATIONS 

59from sympy.utilities.misc import as_int, filldedent, func_name 

60 

61import mpmath 

62from mpmath.libmp.libmpf import prec_to_dps 

63 

64import inspect 

65from collections import Counter 

66 

67def _coeff_isneg(a): 

68 """Return True if the leading Number is negative. 

69 

70 Examples 

71 ======== 

72 

73 >>> from sympy.core.function import _coeff_isneg 

74 >>> from sympy import S, Symbol, oo, pi 

75 >>> _coeff_isneg(-3*pi) 

76 True 

77 >>> _coeff_isneg(S(3)) 

78 False 

79 >>> _coeff_isneg(-oo) 

80 True 

81 >>> _coeff_isneg(Symbol('n', negative=True)) # coeff is 1 

82 False 

83 

84 For matrix expressions: 

85 

86 >>> from sympy import MatrixSymbol, sqrt 

87 >>> A = MatrixSymbol("A", 3, 3) 

88 >>> _coeff_isneg(-sqrt(2)*A) 

89 True 

90 >>> _coeff_isneg(sqrt(2)*A) 

91 False 

92 """ 

93 

94 if a.is_MatMul: 

95 a = a.args[0] 

96 if a.is_Mul: 

97 a = a.args[0] 

98 return a.is_Number and a.is_extended_negative 

99 

100 

101class PoleError(Exception): 

102 pass 

103 

104 

105class ArgumentIndexError(ValueError): 

106 def __str__(self): 

107 return ("Invalid operation with argument number %s for Function %s" % 

108 (self.args[1], self.args[0])) 

109 

110 

111class BadSignatureError(TypeError): 

112 '''Raised when a Lambda is created with an invalid signature''' 

113 pass 

114 

115 

116class BadArgumentsError(TypeError): 

117 '''Raised when a Lambda is called with an incorrect number of arguments''' 

118 pass 

119 

120 

121# Python 3 version that does not raise a Deprecation warning 

122def arity(cls): 

123 """Return the arity of the function if it is known, else None. 

124 

125 Explanation 

126 =========== 

127 

128 When default values are specified for some arguments, they are 

129 optional and the arity is reported as a tuple of possible values. 

130 

131 Examples 

132 ======== 

133 

134 >>> from sympy import arity, log 

135 >>> arity(lambda x: x) 

136 1 

137 >>> arity(log) 

138 (1, 2) 

139 >>> arity(lambda *x: sum(x)) is None 

140 True 

141 """ 

142 eval_ = getattr(cls, 'eval', cls) 

143 

144 parameters = inspect.signature(eval_).parameters.items() 

145 if [p for _, p in parameters if p.kind == p.VAR_POSITIONAL]: 

146 return 

147 p_or_k = [p for _, p in parameters if p.kind == p.POSITIONAL_OR_KEYWORD] 

148 # how many have no default and how many have a default value 

149 no, yes = map(len, sift(p_or_k, 

150 lambda p:p.default == p.empty, binary=True)) 

151 return no if not yes else tuple(range(no, no + yes + 1)) 

152 

153class FunctionClass(type): 

154 """ 

155 Base class for function classes. FunctionClass is a subclass of type. 

156 

157 Use Function('<function name>' [ , signature ]) to create 

158 undefined function classes. 

159 """ 

160 _new = type.__new__ 

161 

162 def __init__(cls, *args, **kwargs): 

163 # honor kwarg value or class-defined value before using 

164 # the number of arguments in the eval function (if present) 

165 nargs = kwargs.pop('nargs', cls.__dict__.get('nargs', arity(cls))) 

166 if nargs is None and 'nargs' not in cls.__dict__: 

167 for supcls in cls.__mro__: 

168 if hasattr(supcls, '_nargs'): 

169 nargs = supcls._nargs 

170 break 

171 else: 

172 continue 

173 

174 # Canonicalize nargs here; change to set in nargs. 

175 if is_sequence(nargs): 

176 if not nargs: 

177 raise ValueError(filldedent(''' 

178 Incorrectly specified nargs as %s: 

179 if there are no arguments, it should be 

180 `nargs = 0`; 

181 if there are any number of arguments, 

182 it should be 

183 `nargs = None`''' % str(nargs))) 

184 nargs = tuple(ordered(set(nargs))) 

185 elif nargs is not None: 

186 nargs = (as_int(nargs),) 

187 cls._nargs = nargs 

188 

189 # When __init__ is called from UndefinedFunction it is called with 

190 # just one arg but when it is called from subclassing Function it is 

191 # called with the usual (name, bases, namespace) type() signature. 

192 if len(args) == 3: 

193 namespace = args[2] 

194 if 'eval' in namespace and not isinstance(namespace['eval'], classmethod): 

195 raise TypeError("eval on Function subclasses should be a class method (defined with @classmethod)") 

196 

197 @property 

198 def __signature__(self): 

199 """ 

200 Allow Python 3's inspect.signature to give a useful signature for 

201 Function subclasses. 

202 """ 

203 # Python 3 only, but backports (like the one in IPython) still might 

204 # call this. 

205 try: 

206 from inspect import signature 

207 except ImportError: 

208 return None 

209 

210 # TODO: Look at nargs 

211 return signature(self.eval) 

212 

213 @property 

214 def free_symbols(self): 

215 return set() 

216 

217 @property 

218 def xreplace(self): 

219 # Function needs args so we define a property that returns 

220 # a function that takes args...and then use that function 

221 # to return the right value 

222 return lambda rule, **_: rule.get(self, self) 

223 

224 @property 

225 def nargs(self): 

226 """Return a set of the allowed number of arguments for the function. 

227 

228 Examples 

229 ======== 

230 

231 >>> from sympy import Function 

232 >>> f = Function('f') 

233 

234 If the function can take any number of arguments, the set of whole 

235 numbers is returned: 

236 

237 >>> Function('f').nargs 

238 Naturals0 

239 

240 If the function was initialized to accept one or more arguments, a 

241 corresponding set will be returned: 

242 

243 >>> Function('f', nargs=1).nargs 

244 {1} 

245 >>> Function('f', nargs=(2, 1)).nargs 

246 {1, 2} 

247 

248 The undefined function, after application, also has the nargs 

249 attribute; the actual number of arguments is always available by 

250 checking the ``args`` attribute: 

251 

252 >>> f = Function('f') 

253 >>> f(1).nargs 

254 Naturals0 

255 >>> len(f(1).args) 

256 1 

257 """ 

258 from sympy.sets.sets import FiniteSet 

259 # XXX it would be nice to handle this in __init__ but there are import 

260 # problems with trying to import FiniteSet there 

261 return FiniteSet(*self._nargs) if self._nargs else S.Naturals0 

262 

263 def _valid_nargs(self, n : int) -> bool: 

264 """ Return True if the specified integer is a valid number of arguments 

265 

266 The number of arguments n is guaranteed to be an integer and positive 

267 

268 """ 

269 if self._nargs: 

270 return n in self._nargs 

271 

272 nargs = self.nargs 

273 return nargs is S.Naturals0 or n in nargs 

274 

275 def __repr__(cls): 

276 return cls.__name__ 

277 

278 

279class Application(Basic, metaclass=FunctionClass): 

280 """ 

281 Base class for applied functions. 

282 

283 Explanation 

284 =========== 

285 

286 Instances of Application represent the result of applying an application of 

287 any type to any object. 

288 """ 

289 

290 is_Function = True 

291 

292 @cacheit 

293 def __new__(cls, *args, **options): 

294 from sympy.sets.fancysets import Naturals0 

295 from sympy.sets.sets import FiniteSet 

296 

297 args = list(map(sympify, args)) 

298 evaluate = options.pop('evaluate', global_parameters.evaluate) 

299 # WildFunction (and anything else like it) may have nargs defined 

300 # and we throw that value away here 

301 options.pop('nargs', None) 

302 

303 if options: 

304 raise ValueError("Unknown options: %s" % options) 

305 

306 if evaluate: 

307 evaluated = cls.eval(*args) 

308 if evaluated is not None: 

309 return evaluated 

310 

311 obj = super().__new__(cls, *args, **options) 

312 

313 # make nargs uniform here 

314 sentinel = object() 

315 objnargs = getattr(obj, "nargs", sentinel) 

316 if objnargs is not sentinel: 

317 # things passing through here: 

318 # - functions subclassed from Function (e.g. myfunc(1).nargs) 

319 # - functions like cos(1).nargs 

320 # - AppliedUndef with given nargs like Function('f', nargs=1)(1).nargs 

321 # Canonicalize nargs here 

322 if is_sequence(objnargs): 

323 nargs = tuple(ordered(set(objnargs))) 

324 elif objnargs is not None: 

325 nargs = (as_int(objnargs),) 

326 else: 

327 nargs = None 

328 else: 

329 # things passing through here: 

330 # - WildFunction('f').nargs 

331 # - AppliedUndef with no nargs like Function('f')(1).nargs 

332 nargs = obj._nargs # note the underscore here 

333 # convert to FiniteSet 

334 obj.nargs = FiniteSet(*nargs) if nargs else Naturals0() 

335 return obj 

336 

337 @classmethod 

338 def eval(cls, *args): 

339 """ 

340 Returns a canonical form of cls applied to arguments args. 

341 

342 Explanation 

343 =========== 

344 

345 The ``eval()`` method is called when the class ``cls`` is about to be 

346 instantiated and it should return either some simplified instance 

347 (possible of some other class), or if the class ``cls`` should be 

348 unmodified, return None. 

349 

350 Examples of ``eval()`` for the function "sign" 

351 

352 .. code-block:: python 

353 

354 @classmethod 

355 def eval(cls, arg): 

356 if arg is S.NaN: 

357 return S.NaN 

358 if arg.is_zero: return S.Zero 

359 if arg.is_positive: return S.One 

360 if arg.is_negative: return S.NegativeOne 

361 if isinstance(arg, Mul): 

362 coeff, terms = arg.as_coeff_Mul(rational=True) 

363 if coeff is not S.One: 

364 return cls(coeff) * cls(terms) 

365 

366 """ 

367 return 

368 

369 @property 

370 def func(self): 

371 return self.__class__ 

372 

373 def _eval_subs(self, old, new): 

374 if (old.is_Function and new.is_Function and 

375 callable(old) and callable(new) and 

376 old == self.func and len(self.args) in new.nargs): 

377 return new(*[i._subs(old, new) for i in self.args]) 

378 

379 

380class Function(Application, Expr): 

381 r""" 

382 Base class for applied mathematical functions. 

383 

384 It also serves as a constructor for undefined function classes. 

385 

386 See the :ref:`custom-functions` guide for details on how to subclass 

387 ``Function`` and what methods can be defined. 

388 

389 Examples 

390 ======== 

391 

392 **Undefined Functions** 

393 

394 To create an undefined function, pass a string of the function name to 

395 ``Function``. 

396 

397 >>> from sympy import Function, Symbol 

398 >>> x = Symbol('x') 

399 >>> f = Function('f') 

400 >>> g = Function('g')(x) 

401 >>> f 

402 f 

403 >>> f(x) 

404 f(x) 

405 >>> g 

406 g(x) 

407 >>> f(x).diff(x) 

408 Derivative(f(x), x) 

409 >>> g.diff(x) 

410 Derivative(g(x), x) 

411 

412 Assumptions can be passed to ``Function`` the same as with a 

413 :class:`~.Symbol`. Alternatively, you can use a ``Symbol`` with 

414 assumptions for the function name and the function will inherit the name 

415 and assumptions associated with the ``Symbol``: 

416 

417 >>> f_real = Function('f', real=True) 

418 >>> f_real(x).is_real 

419 True 

420 >>> f_real_inherit = Function(Symbol('f', real=True)) 

421 >>> f_real_inherit(x).is_real 

422 True 

423 

424 Note that assumptions on a function are unrelated to the assumptions on 

425 the variables it is called on. If you want to add a relationship, subclass 

426 ``Function`` and define custom assumptions handler methods. See the 

427 :ref:`custom-functions-assumptions` section of the :ref:`custom-functions` 

428 guide for more details. 

429 

430 **Custom Function Subclasses** 

431 

432 The :ref:`custom-functions` guide has several 

433 :ref:`custom-functions-complete-examples` of how to subclass ``Function`` 

434 to create a custom function. 

435 

436 """ 

437 

438 @property 

439 def _diff_wrt(self): 

440 return False 

441 

442 @cacheit 

443 def __new__(cls, *args, **options): 

444 # Handle calls like Function('f') 

445 if cls is Function: 

446 return UndefinedFunction(*args, **options) 

447 

448 n = len(args) 

449 

450 if not cls._valid_nargs(n): 

451 # XXX: exception message must be in exactly this format to 

452 # make it work with NumPy's functions like vectorize(). See, 

453 # for example, https://github.com/numpy/numpy/issues/1697. 

454 # The ideal solution would be just to attach metadata to 

455 # the exception and change NumPy to take advantage of this. 

456 temp = ('%(name)s takes %(qual)s %(args)s ' 

457 'argument%(plural)s (%(given)s given)') 

458 raise TypeError(temp % { 

459 'name': cls, 

460 'qual': 'exactly' if len(cls.nargs) == 1 else 'at least', 

461 'args': min(cls.nargs), 

462 'plural': 's'*(min(cls.nargs) != 1), 

463 'given': n}) 

464 

465 evaluate = options.get('evaluate', global_parameters.evaluate) 

466 result = super().__new__(cls, *args, **options) 

467 if evaluate and isinstance(result, cls) and result.args: 

468 _should_evalf = [cls._should_evalf(a) for a in result.args] 

469 pr2 = min(_should_evalf) 

470 if pr2 > 0: 

471 pr = max(_should_evalf) 

472 result = result.evalf(prec_to_dps(pr)) 

473 

474 return _sympify(result) 

475 

476 @classmethod 

477 def _should_evalf(cls, arg): 

478 """ 

479 Decide if the function should automatically evalf(). 

480 

481 Explanation 

482 =========== 

483 

484 By default (in this implementation), this happens if (and only if) the 

485 ARG is a floating point number (including complex numbers). 

486 This function is used by __new__. 

487 

488 Returns the precision to evalf to, or -1 if it should not evalf. 

489 """ 

490 if arg.is_Float: 

491 return arg._prec 

492 if not arg.is_Add: 

493 return -1 

494 m = pure_complex(arg) 

495 if m is None: 

496 return -1 

497 # the elements of m are of type Number, so have a _prec 

498 return max(m[0]._prec, m[1]._prec) 

499 

500 @classmethod 

501 def class_key(cls): 

502 from sympy.sets.fancysets import Naturals0 

503 funcs = { 

504 'exp': 10, 

505 'log': 11, 

506 'sin': 20, 

507 'cos': 21, 

508 'tan': 22, 

509 'cot': 23, 

510 'sinh': 30, 

511 'cosh': 31, 

512 'tanh': 32, 

513 'coth': 33, 

514 'conjugate': 40, 

515 're': 41, 

516 'im': 42, 

517 'arg': 43, 

518 } 

519 name = cls.__name__ 

520 

521 try: 

522 i = funcs[name] 

523 except KeyError: 

524 i = 0 if isinstance(cls.nargs, Naturals0) else 10000 

525 

526 return 4, i, name 

527 

528 def _eval_evalf(self, prec): 

529 

530 def _get_mpmath_func(fname): 

531 """Lookup mpmath function based on name""" 

532 if isinstance(self, AppliedUndef): 

533 # Shouldn't lookup in mpmath but might have ._imp_ 

534 return None 

535 

536 if not hasattr(mpmath, fname): 

537 fname = MPMATH_TRANSLATIONS.get(fname, None) 

538 if fname is None: 

539 return None 

540 return getattr(mpmath, fname) 

541 

542 _eval_mpmath = getattr(self, '_eval_mpmath', None) 

543 if _eval_mpmath is None: 

544 func = _get_mpmath_func(self.func.__name__) 

545 args = self.args 

546 else: 

547 func, args = _eval_mpmath() 

548 

549 # Fall-back evaluation 

550 if func is None: 

551 imp = getattr(self, '_imp_', None) 

552 if imp is None: 

553 return None 

554 try: 

555 return Float(imp(*[i.evalf(prec) for i in self.args]), prec) 

556 except (TypeError, ValueError): 

557 return None 

558 

559 # Convert all args to mpf or mpc 

560 # Convert the arguments to *higher* precision than requested for the 

561 # final result. 

562 # XXX + 5 is a guess, it is similar to what is used in evalf.py. Should 

563 # we be more intelligent about it? 

564 try: 

565 args = [arg._to_mpmath(prec + 5) for arg in args] 

566 def bad(m): 

567 from mpmath import mpf, mpc 

568 # the precision of an mpf value is the last element 

569 # if that is 1 (and m[1] is not 1 which would indicate a 

570 # power of 2), then the eval failed; so check that none of 

571 # the arguments failed to compute to a finite precision. 

572 # Note: An mpc value has two parts, the re and imag tuple; 

573 # check each of those parts, too. Anything else is allowed to 

574 # pass 

575 if isinstance(m, mpf): 

576 m = m._mpf_ 

577 return m[1] !=1 and m[-1] == 1 

578 elif isinstance(m, mpc): 

579 m, n = m._mpc_ 

580 return m[1] !=1 and m[-1] == 1 and \ 

581 n[1] !=1 and n[-1] == 1 

582 else: 

583 return False 

584 if any(bad(a) for a in args): 

585 raise ValueError # one or more args failed to compute with significance 

586 except ValueError: 

587 return 

588 

589 with mpmath.workprec(prec): 

590 v = func(*args) 

591 

592 return Expr._from_mpmath(v, prec) 

593 

594 def _eval_derivative(self, s): 

595 # f(x).diff(s) -> x.diff(s) * f.fdiff(1)(s) 

596 i = 0 

597 l = [] 

598 for a in self.args: 

599 i += 1 

600 da = a.diff(s) 

601 if da.is_zero: 

602 continue 

603 try: 

604 df = self.fdiff(i) 

605 except ArgumentIndexError: 

606 df = Function.fdiff(self, i) 

607 l.append(df * da) 

608 return Add(*l) 

609 

610 def _eval_is_commutative(self): 

611 return fuzzy_and(a.is_commutative for a in self.args) 

612 

613 def _eval_is_meromorphic(self, x, a): 

614 if not self.args: 

615 return True 

616 if any(arg.has(x) for arg in self.args[1:]): 

617 return False 

618 

619 arg = self.args[0] 

620 if not arg._eval_is_meromorphic(x, a): 

621 return None 

622 

623 return fuzzy_not(type(self).is_singular(arg.subs(x, a))) 

624 

625 _singularities: FuzzyBool | tuple[Expr, ...] = None 

626 

627 @classmethod 

628 def is_singular(cls, a): 

629 """ 

630 Tests whether the argument is an essential singularity 

631 or a branch point, or the functions is non-holomorphic. 

632 """ 

633 ss = cls._singularities 

634 if ss in (True, None, False): 

635 return ss 

636 

637 return fuzzy_or(a.is_infinite if s is S.ComplexInfinity 

638 else (a - s).is_zero for s in ss) 

639 

640 def as_base_exp(self): 

641 """ 

642 Returns the method as the 2-tuple (base, exponent). 

643 """ 

644 return self, S.One 

645 

646 def _eval_aseries(self, n, args0, x, logx): 

647 """ 

648 Compute an asymptotic expansion around args0, in terms of self.args. 

649 This function is only used internally by _eval_nseries and should not 

650 be called directly; derived classes can overwrite this to implement 

651 asymptotic expansions. 

652 """ 

653 raise PoleError(filldedent(''' 

654 Asymptotic expansion of %s around %s is 

655 not implemented.''' % (type(self), args0))) 

656 

657 def _eval_nseries(self, x, n, logx, cdir=0): 

658 """ 

659 This function does compute series for multivariate functions, 

660 but the expansion is always in terms of *one* variable. 

661 

662 Examples 

663 ======== 

664 

665 >>> from sympy import atan2 

666 >>> from sympy.abc import x, y 

667 >>> atan2(x, y).series(x, n=2) 

668 atan2(0, y) + x/y + O(x**2) 

669 >>> atan2(x, y).series(y, n=2) 

670 -y/x + atan2(x, 0) + O(y**2) 

671 

672 This function also computes asymptotic expansions, if necessary 

673 and possible: 

674 

675 >>> from sympy import loggamma 

676 >>> loggamma(1/x)._eval_nseries(x,0,None) 

677 -1/x - log(x)/x + log(x)/2 + O(1) 

678 

679 """ 

680 from .symbol import uniquely_named_symbol 

681 from sympy.series.order import Order 

682 from sympy.sets.sets import FiniteSet 

683 args = self.args 

684 args0 = [t.limit(x, 0) for t in args] 

685 if any(t.is_finite is False for t in args0): 

686 from .numbers import oo, zoo, nan 

687 a = [t.as_leading_term(x, logx=logx) for t in args] 

688 a0 = [t.limit(x, 0) for t in a] 

689 if any(t.has(oo, -oo, zoo, nan) for t in a0): 

690 return self._eval_aseries(n, args0, x, logx) 

691 # Careful: the argument goes to oo, but only logarithmically so. We 

692 # are supposed to do a power series expansion "around the 

693 # logarithmic term". e.g. 

694 # f(1+x+log(x)) 

695 # -> f(1+logx) + x*f'(1+logx) + O(x**2) 

696 # where 'logx' is given in the argument 

697 a = [t._eval_nseries(x, n, logx) for t in args] 

698 z = [r - r0 for (r, r0) in zip(a, a0)] 

699 p = [Dummy() for _ in z] 

700 q = [] 

701 v = None 

702 for ai, zi, pi in zip(a0, z, p): 

703 if zi.has(x): 

704 if v is not None: 

705 raise NotImplementedError 

706 q.append(ai + pi) 

707 v = pi 

708 else: 

709 q.append(ai) 

710 e1 = self.func(*q) 

711 if v is None: 

712 return e1 

713 s = e1._eval_nseries(v, n, logx) 

714 o = s.getO() 

715 s = s.removeO() 

716 s = s.subs(v, zi).expand() + Order(o.expr.subs(v, zi), x) 

717 return s 

718 if (self.func.nargs is S.Naturals0 

719 or (self.func.nargs == FiniteSet(1) and args0[0]) 

720 or any(c > 1 for c in self.func.nargs)): 

721 e = self 

722 e1 = e.expand() 

723 if e == e1: 

724 #for example when e = sin(x+1) or e = sin(cos(x)) 

725 #let's try the general algorithm 

726 if len(e.args) == 1: 

727 # issue 14411 

728 e = e.func(e.args[0].cancel()) 

729 term = e.subs(x, S.Zero) 

730 if term.is_finite is False or term is S.NaN: 

731 raise PoleError("Cannot expand %s around 0" % (self)) 

732 series = term 

733 fact = S.One 

734 

735 _x = uniquely_named_symbol('xi', self) 

736 e = e.subs(x, _x) 

737 for i in range(1, n): 

738 fact *= Rational(i) 

739 e = e.diff(_x) 

740 subs = e.subs(_x, S.Zero) 

741 if subs is S.NaN: 

742 # try to evaluate a limit if we have to 

743 subs = e.limit(_x, S.Zero) 

744 if subs.is_finite is False: 

745 raise PoleError("Cannot expand %s around 0" % (self)) 

746 term = subs*(x**i)/fact 

747 term = term.expand() 

748 series += term 

749 return series + Order(x**n, x) 

750 return e1.nseries(x, n=n, logx=logx) 

751 arg = self.args[0] 

752 l = [] 

753 g = None 

754 # try to predict a number of terms needed 

755 nterms = n + 2 

756 cf = Order(arg.as_leading_term(x), x).getn() 

757 if cf != 0: 

758 nterms = (n/cf).ceiling() 

759 for i in range(nterms): 

760 g = self.taylor_term(i, arg, g) 

761 g = g.nseries(x, n=n, logx=logx) 

762 l.append(g) 

763 return Add(*l) + Order(x**n, x) 

764 

765 def fdiff(self, argindex=1): 

766 """ 

767 Returns the first derivative of the function. 

768 """ 

769 if not (1 <= argindex <= len(self.args)): 

770 raise ArgumentIndexError(self, argindex) 

771 ix = argindex - 1 

772 A = self.args[ix] 

773 if A._diff_wrt: 

774 if len(self.args) == 1 or not A.is_Symbol: 

775 return _derivative_dispatch(self, A) 

776 for i, v in enumerate(self.args): 

777 if i != ix and A in v.free_symbols: 

778 # it can't be in any other argument's free symbols 

779 # issue 8510 

780 break 

781 else: 

782 return _derivative_dispatch(self, A) 

783 

784 # See issue 4624 and issue 4719, 5600 and 8510 

785 D = Dummy('xi_%i' % argindex, dummy_index=hash(A)) 

786 args = self.args[:ix] + (D,) + self.args[ix + 1:] 

787 return Subs(Derivative(self.func(*args), D), D, A) 

788 

789 def _eval_as_leading_term(self, x, logx=None, cdir=0): 

790 """Stub that should be overridden by new Functions to return 

791 the first non-zero term in a series if ever an x-dependent 

792 argument whose leading term vanishes as x -> 0 might be encountered. 

793 See, for example, cos._eval_as_leading_term. 

794 """ 

795 from sympy.series.order import Order 

796 args = [a.as_leading_term(x, logx=logx) for a in self.args] 

797 o = Order(1, x) 

798 if any(x in a.free_symbols and o.contains(a) for a in args): 

799 # Whereas x and any finite number are contained in O(1, x), 

800 # expressions like 1/x are not. If any arg simplified to a 

801 # vanishing expression as x -> 0 (like x or x**2, but not 

802 # 3, 1/x, etc...) then the _eval_as_leading_term is needed 

803 # to supply the first non-zero term of the series, 

804 # 

805 # e.g. expression leading term 

806 # ---------- ------------ 

807 # cos(1/x) cos(1/x) 

808 # cos(cos(x)) cos(1) 

809 # cos(x) 1 <- _eval_as_leading_term needed 

810 # sin(x) x <- _eval_as_leading_term needed 

811 # 

812 raise NotImplementedError( 

813 '%s has no _eval_as_leading_term routine' % self.func) 

814 else: 

815 return self.func(*args) 

816 

817 

818class AppliedUndef(Function): 

819 """ 

820 Base class for expressions resulting from the application of an undefined 

821 function. 

822 """ 

823 

824 is_number = False 

825 

826 def __new__(cls, *args, **options): 

827 args = list(map(sympify, args)) 

828 u = [a.name for a in args if isinstance(a, UndefinedFunction)] 

829 if u: 

830 raise TypeError('Invalid argument: expecting an expression, not UndefinedFunction%s: %s' % ( 

831 's'*(len(u) > 1), ', '.join(u))) 

832 obj = super().__new__(cls, *args, **options) 

833 return obj 

834 

835 def _eval_as_leading_term(self, x, logx=None, cdir=0): 

836 return self 

837 

838 @property 

839 def _diff_wrt(self): 

840 """ 

841 Allow derivatives wrt to undefined functions. 

842 

843 Examples 

844 ======== 

845 

846 >>> from sympy import Function, Symbol 

847 >>> f = Function('f') 

848 >>> x = Symbol('x') 

849 >>> f(x)._diff_wrt 

850 True 

851 >>> f(x).diff(x) 

852 Derivative(f(x), x) 

853 """ 

854 return True 

855 

856 

857class UndefSageHelper: 

858 """ 

859 Helper to facilitate Sage conversion. 

860 """ 

861 def __get__(self, ins, typ): 

862 import sage.all as sage 

863 if ins is None: 

864 return lambda: sage.function(typ.__name__) 

865 else: 

866 args = [arg._sage_() for arg in ins.args] 

867 return lambda : sage.function(ins.__class__.__name__)(*args) 

868 

869_undef_sage_helper = UndefSageHelper() 

870 

871class UndefinedFunction(FunctionClass): 

872 """ 

873 The (meta)class of undefined functions. 

874 """ 

875 def __new__(mcl, name, bases=(AppliedUndef,), __dict__=None, **kwargs): 

876 from .symbol import _filter_assumptions 

877 # Allow Function('f', real=True) 

878 # and/or Function(Symbol('f', real=True)) 

879 assumptions, kwargs = _filter_assumptions(kwargs) 

880 if isinstance(name, Symbol): 

881 assumptions = name._merge(assumptions) 

882 name = name.name 

883 elif not isinstance(name, str): 

884 raise TypeError('expecting string or Symbol for name') 

885 else: 

886 commutative = assumptions.get('commutative', None) 

887 assumptions = Symbol(name, **assumptions).assumptions0 

888 if commutative is None: 

889 assumptions.pop('commutative') 

890 __dict__ = __dict__ or {} 

891 # put the `is_*` for into __dict__ 

892 __dict__.update({'is_%s' % k: v for k, v in assumptions.items()}) 

893 # You can add other attributes, although they do have to be hashable 

894 # (but seriously, if you want to add anything other than assumptions, 

895 # just subclass Function) 

896 __dict__.update(kwargs) 

897 # add back the sanitized assumptions without the is_ prefix 

898 kwargs.update(assumptions) 

899 # Save these for __eq__ 

900 __dict__.update({'_kwargs': kwargs}) 

901 # do this for pickling 

902 __dict__['__module__'] = None 

903 obj = super().__new__(mcl, name, bases, __dict__) 

904 obj.name = name 

905 obj._sage_ = _undef_sage_helper 

906 return obj 

907 

908 def __instancecheck__(cls, instance): 

909 return cls in type(instance).__mro__ 

910 

911 _kwargs: dict[str, bool | None] = {} 

912 

913 def __hash__(self): 

914 return hash((self.class_key(), frozenset(self._kwargs.items()))) 

915 

916 def __eq__(self, other): 

917 return (isinstance(other, self.__class__) and 

918 self.class_key() == other.class_key() and 

919 self._kwargs == other._kwargs) 

920 

921 def __ne__(self, other): 

922 return not self == other 

923 

924 @property 

925 def _diff_wrt(self): 

926 return False 

927 

928 

929# XXX: The type: ignore on WildFunction is because mypy complains: 

930# 

931# sympy/core/function.py:939: error: Cannot determine type of 'sort_key' in 

932# base class 'Expr' 

933# 

934# Somehow this is because of the @cacheit decorator but it is not clear how to 

935# fix it. 

936 

937 

938class WildFunction(Function, AtomicExpr): # type: ignore 

939 """ 

940 A WildFunction function matches any function (with its arguments). 

941 

942 Examples 

943 ======== 

944 

945 >>> from sympy import WildFunction, Function, cos 

946 >>> from sympy.abc import x, y 

947 >>> F = WildFunction('F') 

948 >>> f = Function('f') 

949 >>> F.nargs 

950 Naturals0 

951 >>> x.match(F) 

952 >>> F.match(F) 

953 {F_: F_} 

954 >>> f(x).match(F) 

955 {F_: f(x)} 

956 >>> cos(x).match(F) 

957 {F_: cos(x)} 

958 >>> f(x, y).match(F) 

959 {F_: f(x, y)} 

960 

961 To match functions with a given number of arguments, set ``nargs`` to the 

962 desired value at instantiation: 

963 

964 >>> F = WildFunction('F', nargs=2) 

965 >>> F.nargs 

966 {2} 

967 >>> f(x).match(F) 

968 >>> f(x, y).match(F) 

969 {F_: f(x, y)} 

970 

971 To match functions with a range of arguments, set ``nargs`` to a tuple 

972 containing the desired number of arguments, e.g. if ``nargs = (1, 2)`` 

973 then functions with 1 or 2 arguments will be matched. 

974 

975 >>> F = WildFunction('F', nargs=(1, 2)) 

976 >>> F.nargs 

977 {1, 2} 

978 >>> f(x).match(F) 

979 {F_: f(x)} 

980 >>> f(x, y).match(F) 

981 {F_: f(x, y)} 

982 >>> f(x, y, 1).match(F) 

983 

984 """ 

985 

986 # XXX: What is this class attribute used for? 

987 include: set[Any] = set() 

988 

989 def __init__(cls, name, **assumptions): 

990 from sympy.sets.sets import Set, FiniteSet 

991 cls.name = name 

992 nargs = assumptions.pop('nargs', S.Naturals0) 

993 if not isinstance(nargs, Set): 

994 # Canonicalize nargs here. See also FunctionClass. 

995 if is_sequence(nargs): 

996 nargs = tuple(ordered(set(nargs))) 

997 elif nargs is not None: 

998 nargs = (as_int(nargs),) 

999 nargs = FiniteSet(*nargs) 

1000 cls.nargs = nargs 

1001 

1002 def matches(self, expr, repl_dict=None, old=False): 

1003 if not isinstance(expr, (AppliedUndef, Function)): 

1004 return None 

1005 if len(expr.args) not in self.nargs: 

1006 return None 

1007 

1008 if repl_dict is None: 

1009 repl_dict = {} 

1010 else: 

1011 repl_dict = repl_dict.copy() 

1012 

1013 repl_dict[self] = expr 

1014 return repl_dict 

1015 

1016 

1017class Derivative(Expr): 

1018 """ 

1019 Carries out differentiation of the given expression with respect to symbols. 

1020 

1021 Examples 

1022 ======== 

1023 

1024 >>> from sympy import Derivative, Function, symbols, Subs 

1025 >>> from sympy.abc import x, y 

1026 >>> f, g = symbols('f g', cls=Function) 

1027 

1028 >>> Derivative(x**2, x, evaluate=True) 

1029 2*x 

1030 

1031 Denesting of derivatives retains the ordering of variables: 

1032 

1033 >>> Derivative(Derivative(f(x, y), y), x) 

1034 Derivative(f(x, y), y, x) 

1035 

1036 Contiguously identical symbols are merged into a tuple giving 

1037 the symbol and the count: 

1038 

1039 >>> Derivative(f(x), x, x, y, x) 

1040 Derivative(f(x), (x, 2), y, x) 

1041 

1042 If the derivative cannot be performed, and evaluate is True, the 

1043 order of the variables of differentiation will be made canonical: 

1044 

1045 >>> Derivative(f(x, y), y, x, evaluate=True) 

1046 Derivative(f(x, y), x, y) 

1047 

1048 Derivatives with respect to undefined functions can be calculated: 

1049 

1050 >>> Derivative(f(x)**2, f(x), evaluate=True) 

1051 2*f(x) 

1052 

1053 Such derivatives will show up when the chain rule is used to 

1054 evalulate a derivative: 

1055 

1056 >>> f(g(x)).diff(x) 

1057 Derivative(f(g(x)), g(x))*Derivative(g(x), x) 

1058 

1059 Substitution is used to represent derivatives of functions with 

1060 arguments that are not symbols or functions: 

1061 

1062 >>> f(2*x + 3).diff(x) == 2*Subs(f(y).diff(y), y, 2*x + 3) 

1063 True 

1064 

1065 Notes 

1066 ===== 

1067 

1068 Simplification of high-order derivatives: 

1069 

1070 Because there can be a significant amount of simplification that can be 

1071 done when multiple differentiations are performed, results will be 

1072 automatically simplified in a fairly conservative fashion unless the 

1073 keyword ``simplify`` is set to False. 

1074 

1075 >>> from sympy import sqrt, diff, Function, symbols 

1076 >>> from sympy.abc import x, y, z 

1077 >>> f, g = symbols('f,g', cls=Function) 

1078 

1079 >>> e = sqrt((x + 1)**2 + x) 

1080 >>> diff(e, (x, 5), simplify=False).count_ops() 

1081 136 

1082 >>> diff(e, (x, 5)).count_ops() 

1083 30 

1084 

1085 Ordering of variables: 

1086 

1087 If evaluate is set to True and the expression cannot be evaluated, the 

1088 list of differentiation symbols will be sorted, that is, the expression is 

1089 assumed to have continuous derivatives up to the order asked. 

1090 

1091 Derivative wrt non-Symbols: 

1092 

1093 For the most part, one may not differentiate wrt non-symbols. 

1094 For example, we do not allow differentiation wrt `x*y` because 

1095 there are multiple ways of structurally defining where x*y appears 

1096 in an expression: a very strict definition would make 

1097 (x*y*z).diff(x*y) == 0. Derivatives wrt defined functions (like 

1098 cos(x)) are not allowed, either: 

1099 

1100 >>> (x*y*z).diff(x*y) 

1101 Traceback (most recent call last): 

1102 ... 

1103 ValueError: Can't calculate derivative wrt x*y. 

1104 

1105 To make it easier to work with variational calculus, however, 

1106 derivatives wrt AppliedUndef and Derivatives are allowed. 

1107 For example, in the Euler-Lagrange method one may write 

1108 F(t, u, v) where u = f(t) and v = f'(t). These variables can be 

1109 written explicitly as functions of time:: 

1110 

1111 >>> from sympy.abc import t 

1112 >>> F = Function('F') 

1113 >>> U = f(t) 

1114 >>> V = U.diff(t) 

1115 

1116 The derivative wrt f(t) can be obtained directly: 

1117 

1118 >>> direct = F(t, U, V).diff(U) 

1119 

1120 When differentiation wrt a non-Symbol is attempted, the non-Symbol 

1121 is temporarily converted to a Symbol while the differentiation 

1122 is performed and the same answer is obtained: 

1123 

1124 >>> indirect = F(t, U, V).subs(U, x).diff(x).subs(x, U) 

1125 >>> assert direct == indirect 

1126 

1127 The implication of this non-symbol replacement is that all 

1128 functions are treated as independent of other functions and the 

1129 symbols are independent of the functions that contain them:: 

1130 

1131 >>> x.diff(f(x)) 

1132 0 

1133 >>> g(x).diff(f(x)) 

1134 0 

1135 

1136 It also means that derivatives are assumed to depend only 

1137 on the variables of differentiation, not on anything contained 

1138 within the expression being differentiated:: 

1139 

1140 >>> F = f(x) 

1141 >>> Fx = F.diff(x) 

1142 >>> Fx.diff(F) # derivative depends on x, not F 

1143 0 

1144 >>> Fxx = Fx.diff(x) 

1145 >>> Fxx.diff(Fx) # derivative depends on x, not Fx 

1146 0 

1147 

1148 The last example can be made explicit by showing the replacement 

1149 of Fx in Fxx with y: 

1150 

1151 >>> Fxx.subs(Fx, y) 

1152 Derivative(y, x) 

1153 

1154 Since that in itself will evaluate to zero, differentiating 

1155 wrt Fx will also be zero: 

1156 

1157 >>> _.doit() 

1158 0 

1159 

1160 Replacing undefined functions with concrete expressions 

1161 

1162 One must be careful to replace undefined functions with expressions 

1163 that contain variables consistent with the function definition and 

1164 the variables of differentiation or else insconsistent result will 

1165 be obtained. Consider the following example: 

1166 

1167 >>> eq = f(x)*g(y) 

1168 >>> eq.subs(f(x), x*y).diff(x, y).doit() 

1169 y*Derivative(g(y), y) + g(y) 

1170 >>> eq.diff(x, y).subs(f(x), x*y).doit() 

1171 y*Derivative(g(y), y) 

1172 

1173 The results differ because `f(x)` was replaced with an expression 

1174 that involved both variables of differentiation. In the abstract 

1175 case, differentiation of `f(x)` by `y` is 0; in the concrete case, 

1176 the presence of `y` made that derivative nonvanishing and produced 

1177 the extra `g(y)` term. 

1178 

1179 Defining differentiation for an object 

1180 

1181 An object must define ._eval_derivative(symbol) method that returns 

1182 the differentiation result. This function only needs to consider the 

1183 non-trivial case where expr contains symbol and it should call the diff() 

1184 method internally (not _eval_derivative); Derivative should be the only 

1185 one to call _eval_derivative. 

1186 

1187 Any class can allow derivatives to be taken with respect to 

1188 itself (while indicating its scalar nature). See the 

1189 docstring of Expr._diff_wrt. 

1190 

1191 See Also 

1192 ======== 

1193 _sort_variable_count 

1194 """ 

1195 

1196 is_Derivative = True 

1197 

1198 @property 

1199 def _diff_wrt(self): 

1200 """An expression may be differentiated wrt a Derivative if 

1201 it is in elementary form. 

1202 

1203 Examples 

1204 ======== 

1205 

1206 >>> from sympy import Function, Derivative, cos 

1207 >>> from sympy.abc import x 

1208 >>> f = Function('f') 

1209 

1210 >>> Derivative(f(x), x)._diff_wrt 

1211 True 

1212 >>> Derivative(cos(x), x)._diff_wrt 

1213 False 

1214 >>> Derivative(x + 1, x)._diff_wrt 

1215 False 

1216 

1217 A Derivative might be an unevaluated form of what will not be 

1218 a valid variable of differentiation if evaluated. For example, 

1219 

1220 >>> Derivative(f(f(x)), x).doit() 

1221 Derivative(f(x), x)*Derivative(f(f(x)), f(x)) 

1222 

1223 Such an expression will present the same ambiguities as arise 

1224 when dealing with any other product, like ``2*x``, so ``_diff_wrt`` 

1225 is False: 

1226 

1227 >>> Derivative(f(f(x)), x)._diff_wrt 

1228 False 

1229 """ 

1230 return self.expr._diff_wrt and isinstance(self.doit(), Derivative) 

1231 

1232 def __new__(cls, expr, *variables, **kwargs): 

1233 expr = sympify(expr) 

1234 symbols_or_none = getattr(expr, "free_symbols", None) 

1235 has_symbol_set = isinstance(symbols_or_none, set) 

1236 

1237 if not has_symbol_set: 

1238 raise ValueError(filldedent(''' 

1239 Since there are no variables in the expression %s, 

1240 it cannot be differentiated.''' % expr)) 

1241 

1242 # determine value for variables if it wasn't given 

1243 if not variables: 

1244 variables = expr.free_symbols 

1245 if len(variables) != 1: 

1246 if expr.is_number: 

1247 return S.Zero 

1248 if len(variables) == 0: 

1249 raise ValueError(filldedent(''' 

1250 Since there are no variables in the expression, 

1251 the variable(s) of differentiation must be supplied 

1252 to differentiate %s''' % expr)) 

1253 else: 

1254 raise ValueError(filldedent(''' 

1255 Since there is more than one variable in the 

1256 expression, the variable(s) of differentiation 

1257 must be supplied to differentiate %s''' % expr)) 

1258 

1259 # Split the list of variables into a list of the variables we are diff 

1260 # wrt, where each element of the list has the form (s, count) where 

1261 # s is the entity to diff wrt and count is the order of the 

1262 # derivative. 

1263 variable_count = [] 

1264 array_likes = (tuple, list, Tuple) 

1265 

1266 from sympy.tensor.array import Array, NDimArray 

1267 

1268 for i, v in enumerate(variables): 

1269 if isinstance(v, UndefinedFunction): 

1270 raise TypeError( 

1271 "cannot differentiate wrt " 

1272 "UndefinedFunction: %s" % v) 

1273 

1274 if isinstance(v, array_likes): 

1275 if len(v) == 0: 

1276 # Ignore empty tuples: Derivative(expr, ... , (), ... ) 

1277 continue 

1278 if isinstance(v[0], array_likes): 

1279 # Derive by array: Derivative(expr, ... , [[x, y, z]], ... ) 

1280 if len(v) == 1: 

1281 v = Array(v[0]) 

1282 count = 1 

1283 else: 

1284 v, count = v 

1285 v = Array(v) 

1286 else: 

1287 v, count = v 

1288 if count == 0: 

1289 continue 

1290 variable_count.append(Tuple(v, count)) 

1291 continue 

1292 

1293 v = sympify(v) 

1294 if isinstance(v, Integer): 

1295 if i == 0: 

1296 raise ValueError("First variable cannot be a number: %i" % v) 

1297 count = v 

1298 prev, prevcount = variable_count[-1] 

1299 if prevcount != 1: 

1300 raise TypeError("tuple {} followed by number {}".format((prev, prevcount), v)) 

1301 if count == 0: 

1302 variable_count.pop() 

1303 else: 

1304 variable_count[-1] = Tuple(prev, count) 

1305 else: 

1306 count = 1 

1307 variable_count.append(Tuple(v, count)) 

1308 

1309 # light evaluation of contiguous, identical 

1310 # items: (x, 1), (x, 1) -> (x, 2) 

1311 merged = [] 

1312 for t in variable_count: 

1313 v, c = t 

1314 if c.is_negative: 

1315 raise ValueError( 

1316 'order of differentiation must be nonnegative') 

1317 if merged and merged[-1][0] == v: 

1318 c += merged[-1][1] 

1319 if not c: 

1320 merged.pop() 

1321 else: 

1322 merged[-1] = Tuple(v, c) 

1323 else: 

1324 merged.append(t) 

1325 variable_count = merged 

1326 

1327 # sanity check of variables of differentation; we waited 

1328 # until the counts were computed since some variables may 

1329 # have been removed because the count was 0 

1330 for v, c in variable_count: 

1331 # v must have _diff_wrt True 

1332 if not v._diff_wrt: 

1333 __ = '' # filler to make error message neater 

1334 raise ValueError(filldedent(''' 

1335 Can't calculate derivative wrt %s.%s''' % (v, 

1336 __))) 

1337 

1338 # We make a special case for 0th derivative, because there is no 

1339 # good way to unambiguously print this. 

1340 if len(variable_count) == 0: 

1341 return expr 

1342 

1343 evaluate = kwargs.get('evaluate', False) 

1344 

1345 if evaluate: 

1346 if isinstance(expr, Derivative): 

1347 expr = expr.canonical 

1348 variable_count = [ 

1349 (v.canonical if isinstance(v, Derivative) else v, c) 

1350 for v, c in variable_count] 

1351 

1352 # Look for a quick exit if there are symbols that don't appear in 

1353 # expression at all. Note, this cannot check non-symbols like 

1354 # Derivatives as those can be created by intermediate 

1355 # derivatives. 

1356 zero = False 

1357 free = expr.free_symbols 

1358 from sympy.matrices.expressions.matexpr import MatrixExpr 

1359 

1360 for v, c in variable_count: 

1361 vfree = v.free_symbols 

1362 if c.is_positive and vfree: 

1363 if isinstance(v, AppliedUndef): 

1364 # these match exactly since 

1365 # x.diff(f(x)) == g(x).diff(f(x)) == 0 

1366 # and are not created by differentiation 

1367 D = Dummy() 

1368 if not expr.xreplace({v: D}).has(D): 

1369 zero = True 

1370 break 

1371 elif isinstance(v, MatrixExpr): 

1372 zero = False 

1373 break 

1374 elif isinstance(v, Symbol) and v not in free: 

1375 zero = True 

1376 break 

1377 else: 

1378 if not free & vfree: 

1379 # e.g. v is IndexedBase or Matrix 

1380 zero = True 

1381 break 

1382 if zero: 

1383 return cls._get_zero_with_shape_like(expr) 

1384 

1385 # make the order of symbols canonical 

1386 #TODO: check if assumption of discontinuous derivatives exist 

1387 variable_count = cls._sort_variable_count(variable_count) 

1388 

1389 # denest 

1390 if isinstance(expr, Derivative): 

1391 variable_count = list(expr.variable_count) + variable_count 

1392 expr = expr.expr 

1393 return _derivative_dispatch(expr, *variable_count, **kwargs) 

1394 

1395 # we return here if evaluate is False or if there is no 

1396 # _eval_derivative method 

1397 if not evaluate or not hasattr(expr, '_eval_derivative'): 

1398 # return an unevaluated Derivative 

1399 if evaluate and variable_count == [(expr, 1)] and expr.is_scalar: 

1400 # special hack providing evaluation for classes 

1401 # that have defined is_scalar=True but have no 

1402 # _eval_derivative defined 

1403 return S.One 

1404 return Expr.__new__(cls, expr, *variable_count) 

1405 

1406 # evaluate the derivative by calling _eval_derivative method 

1407 # of expr for each variable 

1408 # ------------------------------------------------------------- 

1409 nderivs = 0 # how many derivatives were performed 

1410 unhandled = [] 

1411 from sympy.matrices.common import MatrixCommon 

1412 for i, (v, count) in enumerate(variable_count): 

1413 

1414 old_expr = expr 

1415 old_v = None 

1416 

1417 is_symbol = v.is_symbol or isinstance(v, 

1418 (Iterable, Tuple, MatrixCommon, NDimArray)) 

1419 

1420 if not is_symbol: 

1421 old_v = v 

1422 v = Dummy('xi') 

1423 expr = expr.xreplace({old_v: v}) 

1424 # Derivatives and UndefinedFunctions are independent 

1425 # of all others 

1426 clashing = not (isinstance(old_v, Derivative) or \ 

1427 isinstance(old_v, AppliedUndef)) 

1428 if v not in expr.free_symbols and not clashing: 

1429 return expr.diff(v) # expr's version of 0 

1430 if not old_v.is_scalar and not hasattr( 

1431 old_v, '_eval_derivative'): 

1432 # special hack providing evaluation for classes 

1433 # that have defined is_scalar=True but have no 

1434 # _eval_derivative defined 

1435 expr *= old_v.diff(old_v) 

1436 

1437 obj = cls._dispatch_eval_derivative_n_times(expr, v, count) 

1438 if obj is not None and obj.is_zero: 

1439 return obj 

1440 

1441 nderivs += count 

1442 

1443 if old_v is not None: 

1444 if obj is not None: 

1445 # remove the dummy that was used 

1446 obj = obj.subs(v, old_v) 

1447 # restore expr 

1448 expr = old_expr 

1449 

1450 if obj is None: 

1451 # we've already checked for quick-exit conditions 

1452 # that give 0 so the remaining variables 

1453 # are contained in the expression but the expression 

1454 # did not compute a derivative so we stop taking 

1455 # derivatives 

1456 unhandled = variable_count[i:] 

1457 break 

1458 

1459 expr = obj 

1460 

1461 # what we have so far can be made canonical 

1462 expr = expr.replace( 

1463 lambda x: isinstance(x, Derivative), 

1464 lambda x: x.canonical) 

1465 

1466 if unhandled: 

1467 if isinstance(expr, Derivative): 

1468 unhandled = list(expr.variable_count) + unhandled 

1469 expr = expr.expr 

1470 expr = Expr.__new__(cls, expr, *unhandled) 

1471 

1472 if (nderivs > 1) == True and kwargs.get('simplify', True): 

1473 from .exprtools import factor_terms 

1474 from sympy.simplify.simplify import signsimp 

1475 expr = factor_terms(signsimp(expr)) 

1476 return expr 

1477 

1478 @property 

1479 def canonical(cls): 

1480 return cls.func(cls.expr, 

1481 *Derivative._sort_variable_count(cls.variable_count)) 

1482 

1483 @classmethod 

1484 def _sort_variable_count(cls, vc): 

1485 """ 

1486 Sort (variable, count) pairs into canonical order while 

1487 retaining order of variables that do not commute during 

1488 differentiation: 

1489 

1490 * symbols and functions commute with each other 

1491 * derivatives commute with each other 

1492 * a derivative does not commute with anything it contains 

1493 * any other object is not allowed to commute if it has 

1494 free symbols in common with another object 

1495 

1496 Examples 

1497 ======== 

1498 

1499 >>> from sympy import Derivative, Function, symbols 

1500 >>> vsort = Derivative._sort_variable_count 

1501 >>> x, y, z = symbols('x y z') 

1502 >>> f, g, h = symbols('f g h', cls=Function) 

1503 

1504 Contiguous items are collapsed into one pair: 

1505 

1506 >>> vsort([(x, 1), (x, 1)]) 

1507 [(x, 2)] 

1508 >>> vsort([(y, 1), (f(x), 1), (y, 1), (f(x), 1)]) 

1509 [(y, 2), (f(x), 2)] 

1510 

1511 Ordering is canonical. 

1512 

1513 >>> def vsort0(*v): 

1514 ... # docstring helper to 

1515 ... # change vi -> (vi, 0), sort, and return vi vals 

1516 ... return [i[0] for i in vsort([(i, 0) for i in v])] 

1517 

1518 >>> vsort0(y, x) 

1519 [x, y] 

1520 >>> vsort0(g(y), g(x), f(y)) 

1521 [f(y), g(x), g(y)] 

1522 

1523 Symbols are sorted as far to the left as possible but never 

1524 move to the left of a derivative having the same symbol in 

1525 its variables; the same applies to AppliedUndef which are 

1526 always sorted after Symbols: 

1527 

1528 >>> dfx = f(x).diff(x) 

1529 >>> assert vsort0(dfx, y) == [y, dfx] 

1530 >>> assert vsort0(dfx, x) == [dfx, x] 

1531 """ 

1532 if not vc: 

1533 return [] 

1534 vc = list(vc) 

1535 if len(vc) == 1: 

1536 return [Tuple(*vc[0])] 

1537 V = list(range(len(vc))) 

1538 E = [] 

1539 v = lambda i: vc[i][0] 

1540 D = Dummy() 

1541 def _block(d, v, wrt=False): 

1542 # return True if v should not come before d else False 

1543 if d == v: 

1544 return wrt 

1545 if d.is_Symbol: 

1546 return False 

1547 if isinstance(d, Derivative): 

1548 # a derivative blocks if any of it's variables contain 

1549 # v; the wrt flag will return True for an exact match 

1550 # and will cause an AppliedUndef to block if v is in 

1551 # the arguments 

1552 if any(_block(k, v, wrt=True) 

1553 for k in d._wrt_variables): 

1554 return True 

1555 return False 

1556 if not wrt and isinstance(d, AppliedUndef): 

1557 return False 

1558 if v.is_Symbol: 

1559 return v in d.free_symbols 

1560 if isinstance(v, AppliedUndef): 

1561 return _block(d.xreplace({v: D}), D) 

1562 return d.free_symbols & v.free_symbols 

1563 for i in range(len(vc)): 

1564 for j in range(i): 

1565 if _block(v(j), v(i)): 

1566 E.append((j,i)) 

1567 # this is the default ordering to use in case of ties 

1568 O = dict(zip(ordered(uniq([i for i, c in vc])), range(len(vc)))) 

1569 ix = topological_sort((V, E), key=lambda i: O[v(i)]) 

1570 # merge counts of contiguously identical items 

1571 merged = [] 

1572 for v, c in [vc[i] for i in ix]: 

1573 if merged and merged[-1][0] == v: 

1574 merged[-1][1] += c 

1575 else: 

1576 merged.append([v, c]) 

1577 return [Tuple(*i) for i in merged] 

1578 

1579 def _eval_is_commutative(self): 

1580 return self.expr.is_commutative 

1581 

1582 def _eval_derivative(self, v): 

1583 # If v (the variable of differentiation) is not in 

1584 # self.variables, we might be able to take the derivative. 

1585 if v not in self._wrt_variables: 

1586 dedv = self.expr.diff(v) 

1587 if isinstance(dedv, Derivative): 

1588 return dedv.func(dedv.expr, *(self.variable_count + dedv.variable_count)) 

1589 # dedv (d(self.expr)/dv) could have simplified things such that the 

1590 # derivative wrt things in self.variables can now be done. Thus, 

1591 # we set evaluate=True to see if there are any other derivatives 

1592 # that can be done. The most common case is when dedv is a simple 

1593 # number so that the derivative wrt anything else will vanish. 

1594 return self.func(dedv, *self.variables, evaluate=True) 

1595 # In this case v was in self.variables so the derivative wrt v has 

1596 # already been attempted and was not computed, either because it 

1597 # couldn't be or evaluate=False originally. 

1598 variable_count = list(self.variable_count) 

1599 variable_count.append((v, 1)) 

1600 return self.func(self.expr, *variable_count, evaluate=False) 

1601 

1602 def doit(self, **hints): 

1603 expr = self.expr 

1604 if hints.get('deep', True): 

1605 expr = expr.doit(**hints) 

1606 hints['evaluate'] = True 

1607 rv = self.func(expr, *self.variable_count, **hints) 

1608 if rv!= self and rv.has(Derivative): 

1609 rv = rv.doit(**hints) 

1610 return rv 

1611 

1612 @_sympifyit('z0', NotImplementedError) 

1613 def doit_numerically(self, z0): 

1614 """ 

1615 Evaluate the derivative at z numerically. 

1616 

1617 When we can represent derivatives at a point, this should be folded 

1618 into the normal evalf. For now, we need a special method. 

1619 """ 

1620 if len(self.free_symbols) != 1 or len(self.variables) != 1: 

1621 raise NotImplementedError('partials and higher order derivatives') 

1622 z = list(self.free_symbols)[0] 

1623 

1624 def eval(x): 

1625 f0 = self.expr.subs(z, Expr._from_mpmath(x, prec=mpmath.mp.prec)) 

1626 f0 = f0.evalf(prec_to_dps(mpmath.mp.prec)) 

1627 return f0._to_mpmath(mpmath.mp.prec) 

1628 return Expr._from_mpmath(mpmath.diff(eval, 

1629 z0._to_mpmath(mpmath.mp.prec)), 

1630 mpmath.mp.prec) 

1631 

1632 @property 

1633 def expr(self): 

1634 return self._args[0] 

1635 

1636 @property 

1637 def _wrt_variables(self): 

1638 # return the variables of differentiation without 

1639 # respect to the type of count (int or symbolic) 

1640 return [i[0] for i in self.variable_count] 

1641 

1642 @property 

1643 def variables(self): 

1644 # TODO: deprecate? YES, make this 'enumerated_variables' and 

1645 # name _wrt_variables as variables 

1646 # TODO: support for `d^n`? 

1647 rv = [] 

1648 for v, count in self.variable_count: 

1649 if not count.is_Integer: 

1650 raise TypeError(filldedent(''' 

1651 Cannot give expansion for symbolic count. If you just 

1652 want a list of all variables of differentiation, use 

1653 _wrt_variables.''')) 

1654 rv.extend([v]*count) 

1655 return tuple(rv) 

1656 

1657 @property 

1658 def variable_count(self): 

1659 return self._args[1:] 

1660 

1661 @property 

1662 def derivative_count(self): 

1663 return sum([count for _, count in self.variable_count], 0) 

1664 

1665 @property 

1666 def free_symbols(self): 

1667 ret = self.expr.free_symbols 

1668 # Add symbolic counts to free_symbols 

1669 for _, count in self.variable_count: 

1670 ret.update(count.free_symbols) 

1671 return ret 

1672 

1673 @property 

1674 def kind(self): 

1675 return self.args[0].kind 

1676 

1677 def _eval_subs(self, old, new): 

1678 # The substitution (old, new) cannot be done inside 

1679 # Derivative(expr, vars) for a variety of reasons 

1680 # as handled below. 

1681 if old in self._wrt_variables: 

1682 # first handle the counts 

1683 expr = self.func(self.expr, *[(v, c.subs(old, new)) 

1684 for v, c in self.variable_count]) 

1685 if expr != self: 

1686 return expr._eval_subs(old, new) 

1687 # quick exit case 

1688 if not getattr(new, '_diff_wrt', False): 

1689 # case (0): new is not a valid variable of 

1690 # differentiation 

1691 if isinstance(old, Symbol): 

1692 # don't introduce a new symbol if the old will do 

1693 return Subs(self, old, new) 

1694 else: 

1695 xi = Dummy('xi') 

1696 return Subs(self.xreplace({old: xi}), xi, new) 

1697 

1698 # If both are Derivatives with the same expr, check if old is 

1699 # equivalent to self or if old is a subderivative of self. 

1700 if old.is_Derivative and old.expr == self.expr: 

1701 if self.canonical == old.canonical: 

1702 return new 

1703 

1704 # collections.Counter doesn't have __le__ 

1705 def _subset(a, b): 

1706 return all((a[i] <= b[i]) == True for i in a) 

1707 

1708 old_vars = Counter(dict(reversed(old.variable_count))) 

1709 self_vars = Counter(dict(reversed(self.variable_count))) 

1710 if _subset(old_vars, self_vars): 

1711 return _derivative_dispatch(new, *(self_vars - old_vars).items()).canonical 

1712 

1713 args = list(self.args) 

1714 newargs = [x._subs(old, new) for x in args] 

1715 if args[0] == old: 

1716 # complete replacement of self.expr 

1717 # we already checked that the new is valid so we know 

1718 # it won't be a problem should it appear in variables 

1719 return _derivative_dispatch(*newargs) 

1720 

1721 if newargs[0] != args[0]: 

1722 # case (1) can't change expr by introducing something that is in 

1723 # the _wrt_variables if it was already in the expr 

1724 # e.g. 

1725 # for Derivative(f(x, g(y)), y), x cannot be replaced with 

1726 # anything that has y in it; for f(g(x), g(y)).diff(g(y)) 

1727 # g(x) cannot be replaced with anything that has g(y) 

1728 syms = {vi: Dummy() for vi in self._wrt_variables 

1729 if not vi.is_Symbol} 

1730 wrt = {syms.get(vi, vi) for vi in self._wrt_variables} 

1731 forbidden = args[0].xreplace(syms).free_symbols & wrt 

1732 nfree = new.xreplace(syms).free_symbols 

1733 ofree = old.xreplace(syms).free_symbols 

1734 if (nfree - ofree) & forbidden: 

1735 return Subs(self, old, new) 

1736 

1737 viter = ((i, j) for ((i, _), (j, _)) in zip(newargs[1:], args[1:])) 

1738 if any(i != j for i, j in viter): # a wrt-variable change 

1739 # case (2) can't change vars by introducing a variable 

1740 # that is contained in expr, e.g. 

1741 # for Derivative(f(z, g(h(x), y)), y), y cannot be changed to 

1742 # x, h(x), or g(h(x), y) 

1743 for a in _atomic(self.expr, recursive=True): 

1744 for i in range(1, len(newargs)): 

1745 vi, _ = newargs[i] 

1746 if a == vi and vi != args[i][0]: 

1747 return Subs(self, old, new) 

1748 # more arg-wise checks 

1749 vc = newargs[1:] 

1750 oldv = self._wrt_variables 

1751 newe = self.expr 

1752 subs = [] 

1753 for i, (vi, ci) in enumerate(vc): 

1754 if not vi._diff_wrt: 

1755 # case (3) invalid differentiation expression so 

1756 # create a replacement dummy 

1757 xi = Dummy('xi_%i' % i) 

1758 # replace the old valid variable with the dummy 

1759 # in the expression 

1760 newe = newe.xreplace({oldv[i]: xi}) 

1761 # and replace the bad variable with the dummy 

1762 vc[i] = (xi, ci) 

1763 # and record the dummy with the new (invalid) 

1764 # differentiation expression 

1765 subs.append((xi, vi)) 

1766 

1767 if subs: 

1768 # handle any residual substitution in the expression 

1769 newe = newe._subs(old, new) 

1770 # return the Subs-wrapped derivative 

1771 return Subs(Derivative(newe, *vc), *zip(*subs)) 

1772 

1773 # everything was ok 

1774 return _derivative_dispatch(*newargs) 

1775 

1776 def _eval_lseries(self, x, logx, cdir=0): 

1777 dx = self.variables 

1778 for term in self.expr.lseries(x, logx=logx, cdir=cdir): 

1779 yield self.func(term, *dx) 

1780 

1781 def _eval_nseries(self, x, n, logx, cdir=0): 

1782 arg = self.expr.nseries(x, n=n, logx=logx) 

1783 o = arg.getO() 

1784 dx = self.variables 

1785 rv = [self.func(a, *dx) for a in Add.make_args(arg.removeO())] 

1786 if o: 

1787 rv.append(o/x) 

1788 return Add(*rv) 

1789 

1790 def _eval_as_leading_term(self, x, logx=None, cdir=0): 

1791 series_gen = self.expr.lseries(x) 

1792 d = S.Zero 

1793 for leading_term in series_gen: 

1794 d = diff(leading_term, *self.variables) 

1795 if d != 0: 

1796 break 

1797 return d 

1798 

1799 def as_finite_difference(self, points=1, x0=None, wrt=None): 

1800 """ Expresses a Derivative instance as a finite difference. 

1801 

1802 Parameters 

1803 ========== 

1804 

1805 points : sequence or coefficient, optional 

1806 If sequence: discrete values (length >= order+1) of the 

1807 independent variable used for generating the finite 

1808 difference weights. 

1809 If it is a coefficient, it will be used as the step-size 

1810 for generating an equidistant sequence of length order+1 

1811 centered around ``x0``. Default: 1 (step-size 1) 

1812 

1813 x0 : number or Symbol, optional 

1814 the value of the independent variable (``wrt``) at which the 

1815 derivative is to be approximated. Default: same as ``wrt``. 

1816 

1817 wrt : Symbol, optional 

1818 "with respect to" the variable for which the (partial) 

1819 derivative is to be approximated for. If not provided it 

1820 is required that the derivative is ordinary. Default: ``None``. 

1821 

1822 

1823 Examples 

1824 ======== 

1825 

1826 >>> from sympy import symbols, Function, exp, sqrt, Symbol 

1827 >>> x, h = symbols('x h') 

1828 >>> f = Function('f') 

1829 >>> f(x).diff(x).as_finite_difference() 

1830 -f(x - 1/2) + f(x + 1/2) 

1831 

1832 The default step size and number of points are 1 and 

1833 ``order + 1`` respectively. We can change the step size by 

1834 passing a symbol as a parameter: 

1835 

1836 >>> f(x).diff(x).as_finite_difference(h) 

1837 -f(-h/2 + x)/h + f(h/2 + x)/h 

1838 

1839 We can also specify the discretized values to be used in a 

1840 sequence: 

1841 

1842 >>> f(x).diff(x).as_finite_difference([x, x+h, x+2*h]) 

1843 -3*f(x)/(2*h) + 2*f(h + x)/h - f(2*h + x)/(2*h) 

1844 

1845 The algorithm is not restricted to use equidistant spacing, nor 

1846 do we need to make the approximation around ``x0``, but we can get 

1847 an expression estimating the derivative at an offset: 

1848 

1849 >>> e, sq2 = exp(1), sqrt(2) 

1850 >>> xl = [x-h, x+h, x+e*h] 

1851 >>> f(x).diff(x, 1).as_finite_difference(xl, x+h*sq2) # doctest: +ELLIPSIS 

1852 2*h*((h + sqrt(2)*h)/(2*h) - (-sqrt(2)*h + h)/(2*h))*f(E*h + x)/... 

1853 

1854 To approximate ``Derivative`` around ``x0`` using a non-equidistant 

1855 spacing step, the algorithm supports assignment of undefined 

1856 functions to ``points``: 

1857 

1858 >>> dx = Function('dx') 

1859 >>> f(x).diff(x).as_finite_difference(points=dx(x), x0=x-h) 

1860 -f(-h + x - dx(-h + x)/2)/dx(-h + x) + f(-h + x + dx(-h + x)/2)/dx(-h + x) 

1861 

1862 Partial derivatives are also supported: 

1863 

1864 >>> y = Symbol('y') 

1865 >>> d2fdxdy=f(x,y).diff(x,y) 

1866 >>> d2fdxdy.as_finite_difference(wrt=x) 

1867 -Derivative(f(x - 1/2, y), y) + Derivative(f(x + 1/2, y), y) 

1868 

1869 We can apply ``as_finite_difference`` to ``Derivative`` instances in 

1870 compound expressions using ``replace``: 

1871 

1872 >>> (1 + 42**f(x).diff(x)).replace(lambda arg: arg.is_Derivative, 

1873 ... lambda arg: arg.as_finite_difference()) 

1874 42**(-f(x - 1/2) + f(x + 1/2)) + 1 

1875 

1876 

1877 See also 

1878 ======== 

1879 

1880 sympy.calculus.finite_diff.apply_finite_diff 

1881 sympy.calculus.finite_diff.differentiate_finite 

1882 sympy.calculus.finite_diff.finite_diff_weights 

1883 

1884 """ 

1885 from sympy.calculus.finite_diff import _as_finite_diff 

1886 return _as_finite_diff(self, points, x0, wrt) 

1887 

1888 @classmethod 

1889 def _get_zero_with_shape_like(cls, expr): 

1890 return S.Zero 

1891 

1892 @classmethod 

1893 def _dispatch_eval_derivative_n_times(cls, expr, v, count): 

1894 # Evaluate the derivative `n` times. If 

1895 # `_eval_derivative_n_times` is not overridden by the current 

1896 # object, the default in `Basic` will call a loop over 

1897 # `_eval_derivative`: 

1898 return expr._eval_derivative_n_times(v, count) 

1899 

1900 

1901def _derivative_dispatch(expr, *variables, **kwargs): 

1902 from sympy.matrices.common import MatrixCommon 

1903 from sympy.matrices.expressions.matexpr import MatrixExpr 

1904 from sympy.tensor.array import NDimArray 

1905 array_types = (MatrixCommon, MatrixExpr, NDimArray, list, tuple, Tuple) 

1906 if isinstance(expr, array_types) or any(isinstance(i[0], array_types) if isinstance(i, (tuple, list, Tuple)) else isinstance(i, array_types) for i in variables): 

1907 from sympy.tensor.array.array_derivatives import ArrayDerivative 

1908 return ArrayDerivative(expr, *variables, **kwargs) 

1909 return Derivative(expr, *variables, **kwargs) 

1910 

1911 

1912class Lambda(Expr): 

1913 """ 

1914 Lambda(x, expr) represents a lambda function similar to Python's 

1915 'lambda x: expr'. A function of several variables is written as 

1916 Lambda((x, y, ...), expr). 

1917 

1918 Examples 

1919 ======== 

1920 

1921 A simple example: 

1922 

1923 >>> from sympy import Lambda 

1924 >>> from sympy.abc import x 

1925 >>> f = Lambda(x, x**2) 

1926 >>> f(4) 

1927 16 

1928 

1929 For multivariate functions, use: 

1930 

1931 >>> from sympy.abc import y, z, t 

1932 >>> f2 = Lambda((x, y, z, t), x + y**z + t**z) 

1933 >>> f2(1, 2, 3, 4) 

1934 73 

1935 

1936 It is also possible to unpack tuple arguments: 

1937 

1938 >>> f = Lambda(((x, y), z), x + y + z) 

1939 >>> f((1, 2), 3) 

1940 6 

1941 

1942 A handy shortcut for lots of arguments: 

1943 

1944 >>> p = x, y, z 

1945 >>> f = Lambda(p, x + y*z) 

1946 >>> f(*p) 

1947 x + y*z 

1948 

1949 """ 

1950 is_Function = True 

1951 

1952 def __new__(cls, signature, expr): 

1953 if iterable(signature) and not isinstance(signature, (tuple, Tuple)): 

1954 sympy_deprecation_warning( 

1955 """ 

1956 Using a non-tuple iterable as the first argument to Lambda 

1957 is deprecated. Use Lambda(tuple(args), expr) instead. 

1958 """, 

1959 deprecated_since_version="1.5", 

1960 active_deprecations_target="deprecated-non-tuple-lambda", 

1961 ) 

1962 signature = tuple(signature) 

1963 sig = signature if iterable(signature) else (signature,) 

1964 sig = sympify(sig) 

1965 cls._check_signature(sig) 

1966 

1967 if len(sig) == 1 and sig[0] == expr: 

1968 return S.IdentityFunction 

1969 

1970 return Expr.__new__(cls, sig, sympify(expr)) 

1971 

1972 @classmethod 

1973 def _check_signature(cls, sig): 

1974 syms = set() 

1975 

1976 def rcheck(args): 

1977 for a in args: 

1978 if a.is_symbol: 

1979 if a in syms: 

1980 raise BadSignatureError("Duplicate symbol %s" % a) 

1981 syms.add(a) 

1982 elif isinstance(a, Tuple): 

1983 rcheck(a) 

1984 else: 

1985 raise BadSignatureError("Lambda signature should be only tuples" 

1986 " and symbols, not %s" % a) 

1987 

1988 if not isinstance(sig, Tuple): 

1989 raise BadSignatureError("Lambda signature should be a tuple not %s" % sig) 

1990 # Recurse through the signature: 

1991 rcheck(sig) 

1992 

1993 @property 

1994 def signature(self): 

1995 """The expected form of the arguments to be unpacked into variables""" 

1996 return self._args[0] 

1997 

1998 @property 

1999 def expr(self): 

2000 """The return value of the function""" 

2001 return self._args[1] 

2002 

2003 @property 

2004 def variables(self): 

2005 """The variables used in the internal representation of the function""" 

2006 def _variables(args): 

2007 if isinstance(args, Tuple): 

2008 for arg in args: 

2009 yield from _variables(arg) 

2010 else: 

2011 yield args 

2012 return tuple(_variables(self.signature)) 

2013 

2014 @property 

2015 def nargs(self): 

2016 from sympy.sets.sets import FiniteSet 

2017 return FiniteSet(len(self.signature)) 

2018 

2019 bound_symbols = variables 

2020 

2021 @property 

2022 def free_symbols(self): 

2023 return self.expr.free_symbols - set(self.variables) 

2024 

2025 def __call__(self, *args): 

2026 n = len(args) 

2027 if n not in self.nargs: # Lambda only ever has 1 value in nargs 

2028 # XXX: exception message must be in exactly this format to 

2029 # make it work with NumPy's functions like vectorize(). See, 

2030 # for example, https://github.com/numpy/numpy/issues/1697. 

2031 # The ideal solution would be just to attach metadata to 

2032 # the exception and change NumPy to take advantage of this. 

2033 ## XXX does this apply to Lambda? If not, remove this comment. 

2034 temp = ('%(name)s takes exactly %(args)s ' 

2035 'argument%(plural)s (%(given)s given)') 

2036 raise BadArgumentsError(temp % { 

2037 'name': self, 

2038 'args': list(self.nargs)[0], 

2039 'plural': 's'*(list(self.nargs)[0] != 1), 

2040 'given': n}) 

2041 

2042 d = self._match_signature(self.signature, args) 

2043 

2044 return self.expr.xreplace(d) 

2045 

2046 def _match_signature(self, sig, args): 

2047 

2048 symargmap = {} 

2049 

2050 def rmatch(pars, args): 

2051 for par, arg in zip(pars, args): 

2052 if par.is_symbol: 

2053 symargmap[par] = arg 

2054 elif isinstance(par, Tuple): 

2055 if not isinstance(arg, (tuple, Tuple)) or len(args) != len(pars): 

2056 raise BadArgumentsError("Can't match %s and %s" % (args, pars)) 

2057 rmatch(par, arg) 

2058 

2059 rmatch(sig, args) 

2060 

2061 return symargmap 

2062 

2063 @property 

2064 def is_identity(self): 

2065 """Return ``True`` if this ``Lambda`` is an identity function. """ 

2066 return self.signature == self.expr 

2067 

2068 def _eval_evalf(self, prec): 

2069 return self.func(self.args[0], self.args[1].evalf(n=prec_to_dps(prec))) 

2070 

2071 

2072class Subs(Expr): 

2073 """ 

2074 Represents unevaluated substitutions of an expression. 

2075 

2076 ``Subs(expr, x, x0)`` represents the expression resulting 

2077 from substituting x with x0 in expr. 

2078 

2079 Parameters 

2080 ========== 

2081 

2082 expr : Expr 

2083 An expression. 

2084 

2085 x : tuple, variable 

2086 A variable or list of distinct variables. 

2087 

2088 x0 : tuple or list of tuples 

2089 A point or list of evaluation points 

2090 corresponding to those variables. 

2091 

2092 Examples 

2093 ======== 

2094 

2095 >>> from sympy import Subs, Function, sin, cos 

2096 >>> from sympy.abc import x, y, z 

2097 >>> f = Function('f') 

2098 

2099 Subs are created when a particular substitution cannot be made. The 

2100 x in the derivative cannot be replaced with 0 because 0 is not a 

2101 valid variables of differentiation: 

2102 

2103 >>> f(x).diff(x).subs(x, 0) 

2104 Subs(Derivative(f(x), x), x, 0) 

2105 

2106 Once f is known, the derivative and evaluation at 0 can be done: 

2107 

2108 >>> _.subs(f, sin).doit() == sin(x).diff(x).subs(x, 0) == cos(0) 

2109 True 

2110 

2111 Subs can also be created directly with one or more variables: 

2112 

2113 >>> Subs(f(x)*sin(y) + z, (x, y), (0, 1)) 

2114 Subs(z + f(x)*sin(y), (x, y), (0, 1)) 

2115 >>> _.doit() 

2116 z + f(0)*sin(1) 

2117 

2118 Notes 

2119 ===== 

2120 

2121 ``Subs`` objects are generally useful to represent unevaluated derivatives 

2122 calculated at a point. 

2123 

2124 The variables may be expressions, but they are subjected to the limitations 

2125 of subs(), so it is usually a good practice to use only symbols for 

2126 variables, since in that case there can be no ambiguity. 

2127 

2128 There's no automatic expansion - use the method .doit() to effect all 

2129 possible substitutions of the object and also of objects inside the 

2130 expression. 

2131 

2132 When evaluating derivatives at a point that is not a symbol, a Subs object 

2133 is returned. One is also able to calculate derivatives of Subs objects - in 

2134 this case the expression is always expanded (for the unevaluated form, use 

2135 Derivative()). 

2136 

2137 In order to allow expressions to combine before doit is done, a 

2138 representation of the Subs expression is used internally to make 

2139 expressions that are superficially different compare the same: 

2140 

2141 >>> a, b = Subs(x, x, 0), Subs(y, y, 0) 

2142 >>> a + b 

2143 2*Subs(x, x, 0) 

2144 

2145 This can lead to unexpected consequences when using methods 

2146 like `has` that are cached: 

2147 

2148 >>> s = Subs(x, x, 0) 

2149 >>> s.has(x), s.has(y) 

2150 (True, False) 

2151 >>> ss = s.subs(x, y) 

2152 >>> ss.has(x), ss.has(y) 

2153 (True, False) 

2154 >>> s, ss 

2155 (Subs(x, x, 0), Subs(y, y, 0)) 

2156 """ 

2157 def __new__(cls, expr, variables, point, **assumptions): 

2158 if not is_sequence(variables, Tuple): 

2159 variables = [variables] 

2160 variables = Tuple(*variables) 

2161 

2162 if has_dups(variables): 

2163 repeated = [str(v) for v, i in Counter(variables).items() if i > 1] 

2164 __ = ', '.join(repeated) 

2165 raise ValueError(filldedent(''' 

2166 The following expressions appear more than once: %s 

2167 ''' % __)) 

2168 

2169 point = Tuple(*(point if is_sequence(point, Tuple) else [point])) 

2170 

2171 if len(point) != len(variables): 

2172 raise ValueError('Number of point values must be the same as ' 

2173 'the number of variables.') 

2174 

2175 if not point: 

2176 return sympify(expr) 

2177 

2178 # denest 

2179 if isinstance(expr, Subs): 

2180 variables = expr.variables + variables 

2181 point = expr.point + point 

2182 expr = expr.expr 

2183 else: 

2184 expr = sympify(expr) 

2185 

2186 # use symbols with names equal to the point value (with prepended _) 

2187 # to give a variable-independent expression 

2188 pre = "_" 

2189 pts = sorted(set(point), key=default_sort_key) 

2190 from sympy.printing.str import StrPrinter 

2191 class CustomStrPrinter(StrPrinter): 

2192 def _print_Dummy(self, expr): 

2193 return str(expr) + str(expr.dummy_index) 

2194 def mystr(expr, **settings): 

2195 p = CustomStrPrinter(settings) 

2196 return p.doprint(expr) 

2197 while 1: 

2198 s_pts = {p: Symbol(pre + mystr(p)) for p in pts} 

2199 reps = [(v, s_pts[p]) 

2200 for v, p in zip(variables, point)] 

2201 # if any underscore-prepended symbol is already a free symbol 

2202 # and is a variable with a different point value, then there 

2203 # is a clash, e.g. _0 clashes in Subs(_0 + _1, (_0, _1), (1, 0)) 

2204 # because the new symbol that would be created is _1 but _1 

2205 # is already mapped to 0 so __0 and __1 are used for the new 

2206 # symbols 

2207 if any(r in expr.free_symbols and 

2208 r in variables and 

2209 Symbol(pre + mystr(point[variables.index(r)])) != r 

2210 for _, r in reps): 

2211 pre += "_" 

2212 continue 

2213 break 

2214 

2215 obj = Expr.__new__(cls, expr, Tuple(*variables), point) 

2216 obj._expr = expr.xreplace(dict(reps)) 

2217 return obj 

2218 

2219 def _eval_is_commutative(self): 

2220 return self.expr.is_commutative 

2221 

2222 def doit(self, **hints): 

2223 e, v, p = self.args 

2224 

2225 # remove self mappings 

2226 for i, (vi, pi) in enumerate(zip(v, p)): 

2227 if vi == pi: 

2228 v = v[:i] + v[i + 1:] 

2229 p = p[:i] + p[i + 1:] 

2230 if not v: 

2231 return self.expr 

2232 

2233 if isinstance(e, Derivative): 

2234 # apply functions first, e.g. f -> cos 

2235 undone = [] 

2236 for i, vi in enumerate(v): 

2237 if isinstance(vi, FunctionClass): 

2238 e = e.subs(vi, p[i]) 

2239 else: 

2240 undone.append((vi, p[i])) 

2241 if not isinstance(e, Derivative): 

2242 e = e.doit() 

2243 if isinstance(e, Derivative): 

2244 # do Subs that aren't related to differentiation 

2245 undone2 = [] 

2246 D = Dummy() 

2247 arg = e.args[0] 

2248 for vi, pi in undone: 

2249 if D not in e.xreplace({vi: D}).free_symbols: 

2250 if arg.has(vi): 

2251 e = e.subs(vi, pi) 

2252 else: 

2253 undone2.append((vi, pi)) 

2254 undone = undone2 

2255 # differentiate wrt variables that are present 

2256 wrt = [] 

2257 D = Dummy() 

2258 expr = e.expr 

2259 free = expr.free_symbols 

2260 for vi, ci in e.variable_count: 

2261 if isinstance(vi, Symbol) and vi in free: 

2262 expr = expr.diff((vi, ci)) 

2263 elif D in expr.subs(vi, D).free_symbols: 

2264 expr = expr.diff((vi, ci)) 

2265 else: 

2266 wrt.append((vi, ci)) 

2267 # inject remaining subs 

2268 rv = expr.subs(undone) 

2269 # do remaining differentiation *in order given* 

2270 for vc in wrt: 

2271 rv = rv.diff(vc) 

2272 else: 

2273 # inject remaining subs 

2274 rv = e.subs(undone) 

2275 else: 

2276 rv = e.doit(**hints).subs(list(zip(v, p))) 

2277 

2278 if hints.get('deep', True) and rv != self: 

2279 rv = rv.doit(**hints) 

2280 return rv 

2281 

2282 def evalf(self, prec=None, **options): 

2283 return self.doit().evalf(prec, **options) 

2284 

2285 n = evalf # type:ignore 

2286 

2287 @property 

2288 def variables(self): 

2289 """The variables to be evaluated""" 

2290 return self._args[1] 

2291 

2292 bound_symbols = variables 

2293 

2294 @property 

2295 def expr(self): 

2296 """The expression on which the substitution operates""" 

2297 return self._args[0] 

2298 

2299 @property 

2300 def point(self): 

2301 """The values for which the variables are to be substituted""" 

2302 return self._args[2] 

2303 

2304 @property 

2305 def free_symbols(self): 

2306 return (self.expr.free_symbols - set(self.variables) | 

2307 set(self.point.free_symbols)) 

2308 

2309 @property 

2310 def expr_free_symbols(self): 

2311 sympy_deprecation_warning(""" 

2312 The expr_free_symbols property is deprecated. Use free_symbols to get 

2313 the free symbols of an expression. 

2314 """, 

2315 deprecated_since_version="1.9", 

2316 active_deprecations_target="deprecated-expr-free-symbols") 

2317 # Don't show the warning twice from the recursive call 

2318 with ignore_warnings(SymPyDeprecationWarning): 

2319 return (self.expr.expr_free_symbols - set(self.variables) | 

2320 set(self.point.expr_free_symbols)) 

2321 

2322 def __eq__(self, other): 

2323 if not isinstance(other, Subs): 

2324 return False 

2325 return self._hashable_content() == other._hashable_content() 

2326 

2327 def __ne__(self, other): 

2328 return not(self == other) 

2329 

2330 def __hash__(self): 

2331 return super().__hash__() 

2332 

2333 def _hashable_content(self): 

2334 return (self._expr.xreplace(self.canonical_variables), 

2335 ) + tuple(ordered([(v, p) for v, p in 

2336 zip(self.variables, self.point) if not self.expr.has(v)])) 

2337 

2338 def _eval_subs(self, old, new): 

2339 # Subs doit will do the variables in order; the semantics 

2340 # of subs for Subs is have the following invariant for 

2341 # Subs object foo: 

2342 # foo.doit().subs(reps) == foo.subs(reps).doit() 

2343 pt = list(self.point) 

2344 if old in self.variables: 

2345 if _atomic(new) == {new} and not any( 

2346 i.has(new) for i in self.args): 

2347 # the substitution is neutral 

2348 return self.xreplace({old: new}) 

2349 # any occurrence of old before this point will get 

2350 # handled by replacements from here on 

2351 i = self.variables.index(old) 

2352 for j in range(i, len(self.variables)): 

2353 pt[j] = pt[j]._subs(old, new) 

2354 return self.func(self.expr, self.variables, pt) 

2355 v = [i._subs(old, new) for i in self.variables] 

2356 if v != list(self.variables): 

2357 return self.func(self.expr, self.variables + (old,), pt + [new]) 

2358 expr = self.expr._subs(old, new) 

2359 pt = [i._subs(old, new) for i in self.point] 

2360 return self.func(expr, v, pt) 

2361 

2362 def _eval_derivative(self, s): 

2363 # Apply the chain rule of the derivative on the substitution variables: 

2364 f = self.expr 

2365 vp = V, P = self.variables, self.point 

2366 val = Add.fromiter(p.diff(s)*Subs(f.diff(v), *vp).doit() 

2367 for v, p in zip(V, P)) 

2368 

2369 # these are all the free symbols in the expr 

2370 efree = f.free_symbols 

2371 # some symbols like IndexedBase include themselves and args 

2372 # as free symbols 

2373 compound = {i for i in efree if len(i.free_symbols) > 1} 

2374 # hide them and see what independent free symbols remain 

2375 dums = {Dummy() for i in compound} 

2376 masked = f.xreplace(dict(zip(compound, dums))) 

2377 ifree = masked.free_symbols - dums 

2378 # include the compound symbols 

2379 free = ifree | compound 

2380 # remove the variables already handled 

2381 free -= set(V) 

2382 # add back any free symbols of remaining compound symbols 

2383 free |= {i for j in free & compound for i in j.free_symbols} 

2384 # if symbols of s are in free then there is more to do 

2385 if free & s.free_symbols: 

2386 val += Subs(f.diff(s), self.variables, self.point).doit() 

2387 return val 

2388 

2389 def _eval_nseries(self, x, n, logx, cdir=0): 

2390 if x in self.point: 

2391 # x is the variable being substituted into 

2392 apos = self.point.index(x) 

2393 other = self.variables[apos] 

2394 else: 

2395 other = x 

2396 arg = self.expr.nseries(other, n=n, logx=logx) 

2397 o = arg.getO() 

2398 terms = Add.make_args(arg.removeO()) 

2399 rv = Add(*[self.func(a, *self.args[1:]) for a in terms]) 

2400 if o: 

2401 rv += o.subs(other, x) 

2402 return rv 

2403 

2404 def _eval_as_leading_term(self, x, logx=None, cdir=0): 

2405 if x in self.point: 

2406 ipos = self.point.index(x) 

2407 xvar = self.variables[ipos] 

2408 return self.expr.as_leading_term(xvar) 

2409 if x in self.variables: 

2410 # if `x` is a dummy variable, it means it won't exist after the 

2411 # substitution has been performed: 

2412 return self 

2413 # The variable is independent of the substitution: 

2414 return self.expr.as_leading_term(x) 

2415 

2416 

2417def diff(f, *symbols, **kwargs): 

2418 """ 

2419 Differentiate f with respect to symbols. 

2420 

2421 Explanation 

2422 =========== 

2423 

2424 This is just a wrapper to unify .diff() and the Derivative class; its 

2425 interface is similar to that of integrate(). You can use the same 

2426 shortcuts for multiple variables as with Derivative. For example, 

2427 diff(f(x), x, x, x) and diff(f(x), x, 3) both return the third derivative 

2428 of f(x). 

2429 

2430 You can pass evaluate=False to get an unevaluated Derivative class. Note 

2431 that if there are 0 symbols (such as diff(f(x), x, 0), then the result will 

2432 be the function (the zeroth derivative), even if evaluate=False. 

2433 

2434 Examples 

2435 ======== 

2436 

2437 >>> from sympy import sin, cos, Function, diff 

2438 >>> from sympy.abc import x, y 

2439 >>> f = Function('f') 

2440 

2441 >>> diff(sin(x), x) 

2442 cos(x) 

2443 >>> diff(f(x), x, x, x) 

2444 Derivative(f(x), (x, 3)) 

2445 >>> diff(f(x), x, 3) 

2446 Derivative(f(x), (x, 3)) 

2447 >>> diff(sin(x)*cos(y), x, 2, y, 2) 

2448 sin(x)*cos(y) 

2449 

2450 >>> type(diff(sin(x), x)) 

2451 cos 

2452 >>> type(diff(sin(x), x, evaluate=False)) 

2453 <class 'sympy.core.function.Derivative'> 

2454 >>> type(diff(sin(x), x, 0)) 

2455 sin 

2456 >>> type(diff(sin(x), x, 0, evaluate=False)) 

2457 sin 

2458 

2459 >>> diff(sin(x)) 

2460 cos(x) 

2461 >>> diff(sin(x*y)) 

2462 Traceback (most recent call last): 

2463 ... 

2464 ValueError: specify differentiation variables to differentiate sin(x*y) 

2465 

2466 Note that ``diff(sin(x))`` syntax is meant only for convenience 

2467 in interactive sessions and should be avoided in library code. 

2468 

2469 References 

2470 ========== 

2471 

2472 .. [1] https://reference.wolfram.com/legacy/v5_2/Built-inFunctions/AlgebraicComputation/Calculus/D.html 

2473 

2474 See Also 

2475 ======== 

2476 

2477 Derivative 

2478 idiff: computes the derivative implicitly 

2479 

2480 """ 

2481 if hasattr(f, 'diff'): 

2482 return f.diff(*symbols, **kwargs) 

2483 kwargs.setdefault('evaluate', True) 

2484 return _derivative_dispatch(f, *symbols, **kwargs) 

2485 

2486 

2487def expand(e, deep=True, modulus=None, power_base=True, power_exp=True, 

2488 mul=True, log=True, multinomial=True, basic=True, **hints): 

2489 r""" 

2490 Expand an expression using methods given as hints. 

2491 

2492 Explanation 

2493 =========== 

2494 

2495 Hints evaluated unless explicitly set to False are: ``basic``, ``log``, 

2496 ``multinomial``, ``mul``, ``power_base``, and ``power_exp`` The following 

2497 hints are supported but not applied unless set to True: ``complex``, 

2498 ``func``, and ``trig``. In addition, the following meta-hints are 

2499 supported by some or all of the other hints: ``frac``, ``numer``, 

2500 ``denom``, ``modulus``, and ``force``. ``deep`` is supported by all 

2501 hints. Additionally, subclasses of Expr may define their own hints or 

2502 meta-hints. 

2503 

2504 The ``basic`` hint is used for any special rewriting of an object that 

2505 should be done automatically (along with the other hints like ``mul``) 

2506 when expand is called. This is a catch-all hint to handle any sort of 

2507 expansion that may not be described by the existing hint names. To use 

2508 this hint an object should override the ``_eval_expand_basic`` method. 

2509 Objects may also define their own expand methods, which are not run by 

2510 default. See the API section below. 

2511 

2512 If ``deep`` is set to ``True`` (the default), things like arguments of 

2513 functions are recursively expanded. Use ``deep=False`` to only expand on 

2514 the top level. 

2515 

2516 If the ``force`` hint is used, assumptions about variables will be ignored 

2517 in making the expansion. 

2518 

2519 Hints 

2520 ===== 

2521 

2522 These hints are run by default 

2523 

2524 mul 

2525 --- 

2526 

2527 Distributes multiplication over addition: 

2528 

2529 >>> from sympy import cos, exp, sin 

2530 >>> from sympy.abc import x, y, z 

2531 >>> (y*(x + z)).expand(mul=True) 

2532 x*y + y*z 

2533 

2534 multinomial 

2535 ----------- 

2536 

2537 Expand (x + y + ...)**n where n is a positive integer. 

2538 

2539 >>> ((x + y + z)**2).expand(multinomial=True) 

2540 x**2 + 2*x*y + 2*x*z + y**2 + 2*y*z + z**2 

2541 

2542 power_exp 

2543 --------- 

2544 

2545 Expand addition in exponents into multiplied bases. 

2546 

2547 >>> exp(x + y).expand(power_exp=True) 

2548 exp(x)*exp(y) 

2549 >>> (2**(x + y)).expand(power_exp=True) 

2550 2**x*2**y 

2551 

2552 power_base 

2553 ---------- 

2554 

2555 Split powers of multiplied bases. 

2556 

2557 This only happens by default if assumptions allow, or if the 

2558 ``force`` meta-hint is used: 

2559 

2560 >>> ((x*y)**z).expand(power_base=True) 

2561 (x*y)**z 

2562 >>> ((x*y)**z).expand(power_base=True, force=True) 

2563 x**z*y**z 

2564 >>> ((2*y)**z).expand(power_base=True) 

2565 2**z*y**z 

2566 

2567 Note that in some cases where this expansion always holds, SymPy performs 

2568 it automatically: 

2569 

2570 >>> (x*y)**2 

2571 x**2*y**2 

2572 

2573 log 

2574 --- 

2575 

2576 Pull out power of an argument as a coefficient and split logs products 

2577 into sums of logs. 

2578 

2579 Note that these only work if the arguments of the log function have the 

2580 proper assumptions--the arguments must be positive and the exponents must 

2581 be real--or else the ``force`` hint must be True: 

2582 

2583 >>> from sympy import log, symbols 

2584 >>> log(x**2*y).expand(log=True) 

2585 log(x**2*y) 

2586 >>> log(x**2*y).expand(log=True, force=True) 

2587 2*log(x) + log(y) 

2588 >>> x, y = symbols('x,y', positive=True) 

2589 >>> log(x**2*y).expand(log=True) 

2590 2*log(x) + log(y) 

2591 

2592 basic 

2593 ----- 

2594 

2595 This hint is intended primarily as a way for custom subclasses to enable 

2596 expansion by default. 

2597 

2598 These hints are not run by default: 

2599 

2600 complex 

2601 ------- 

2602 

2603 Split an expression into real and imaginary parts. 

2604 

2605 >>> x, y = symbols('x,y') 

2606 >>> (x + y).expand(complex=True) 

2607 re(x) + re(y) + I*im(x) + I*im(y) 

2608 >>> cos(x).expand(complex=True) 

2609 -I*sin(re(x))*sinh(im(x)) + cos(re(x))*cosh(im(x)) 

2610 

2611 Note that this is just a wrapper around ``as_real_imag()``. Most objects 

2612 that wish to redefine ``_eval_expand_complex()`` should consider 

2613 redefining ``as_real_imag()`` instead. 

2614 

2615 func 

2616 ---- 

2617 

2618 Expand other functions. 

2619 

2620 >>> from sympy import gamma 

2621 >>> gamma(x + 1).expand(func=True) 

2622 x*gamma(x) 

2623 

2624 trig 

2625 ---- 

2626 

2627 Do trigonometric expansions. 

2628 

2629 >>> cos(x + y).expand(trig=True) 

2630 -sin(x)*sin(y) + cos(x)*cos(y) 

2631 >>> sin(2*x).expand(trig=True) 

2632 2*sin(x)*cos(x) 

2633 

2634 Note that the forms of ``sin(n*x)`` and ``cos(n*x)`` in terms of ``sin(x)`` 

2635 and ``cos(x)`` are not unique, due to the identity `\sin^2(x) + \cos^2(x) 

2636 = 1`. The current implementation uses the form obtained from Chebyshev 

2637 polynomials, but this may change. See `this MathWorld article 

2638 <https://mathworld.wolfram.com/Multiple-AngleFormulas.html>`_ for more 

2639 information. 

2640 

2641 Notes 

2642 ===== 

2643 

2644 - You can shut off unwanted methods:: 

2645 

2646 >>> (exp(x + y)*(x + y)).expand() 

2647 x*exp(x)*exp(y) + y*exp(x)*exp(y) 

2648 >>> (exp(x + y)*(x + y)).expand(power_exp=False) 

2649 x*exp(x + y) + y*exp(x + y) 

2650 >>> (exp(x + y)*(x + y)).expand(mul=False) 

2651 (x + y)*exp(x)*exp(y) 

2652 

2653 - Use deep=False to only expand on the top level:: 

2654 

2655 >>> exp(x + exp(x + y)).expand() 

2656 exp(x)*exp(exp(x)*exp(y)) 

2657 >>> exp(x + exp(x + y)).expand(deep=False) 

2658 exp(x)*exp(exp(x + y)) 

2659 

2660 - Hints are applied in an arbitrary, but consistent order (in the current 

2661 implementation, they are applied in alphabetical order, except 

2662 multinomial comes before mul, but this may change). Because of this, 

2663 some hints may prevent expansion by other hints if they are applied 

2664 first. For example, ``mul`` may distribute multiplications and prevent 

2665 ``log`` and ``power_base`` from expanding them. Also, if ``mul`` is 

2666 applied before ``multinomial`, the expression might not be fully 

2667 distributed. The solution is to use the various ``expand_hint`` helper 

2668 functions or to use ``hint=False`` to this function to finely control 

2669 which hints are applied. Here are some examples:: 

2670 

2671 >>> from sympy import expand, expand_mul, expand_power_base 

2672 >>> x, y, z = symbols('x,y,z', positive=True) 

2673 

2674 >>> expand(log(x*(y + z))) 

2675 log(x) + log(y + z) 

2676 

2677 Here, we see that ``log`` was applied before ``mul``. To get the mul 

2678 expanded form, either of the following will work:: 

2679 

2680 >>> expand_mul(log(x*(y + z))) 

2681 log(x*y + x*z) 

2682 >>> expand(log(x*(y + z)), log=False) 

2683 log(x*y + x*z) 

2684 

2685 A similar thing can happen with the ``power_base`` hint:: 

2686 

2687 >>> expand((x*(y + z))**x) 

2688 (x*y + x*z)**x 

2689 

2690 To get the ``power_base`` expanded form, either of the following will 

2691 work:: 

2692 

2693 >>> expand((x*(y + z))**x, mul=False) 

2694 x**x*(y + z)**x 

2695 >>> expand_power_base((x*(y + z))**x) 

2696 x**x*(y + z)**x 

2697 

2698 >>> expand((x + y)*y/x) 

2699 y + y**2/x 

2700 

2701 The parts of a rational expression can be targeted:: 

2702 

2703 >>> expand((x + y)*y/x/(x + 1), frac=True) 

2704 (x*y + y**2)/(x**2 + x) 

2705 >>> expand((x + y)*y/x/(x + 1), numer=True) 

2706 (x*y + y**2)/(x*(x + 1)) 

2707 >>> expand((x + y)*y/x/(x + 1), denom=True) 

2708 y*(x + y)/(x**2 + x) 

2709 

2710 - The ``modulus`` meta-hint can be used to reduce the coefficients of an 

2711 expression post-expansion:: 

2712 

2713 >>> expand((3*x + 1)**2) 

2714 9*x**2 + 6*x + 1 

2715 >>> expand((3*x + 1)**2, modulus=5) 

2716 4*x**2 + x + 1 

2717 

2718 - Either ``expand()`` the function or ``.expand()`` the method can be 

2719 used. Both are equivalent:: 

2720 

2721 >>> expand((x + 1)**2) 

2722 x**2 + 2*x + 1 

2723 >>> ((x + 1)**2).expand() 

2724 x**2 + 2*x + 1 

2725 

2726 API 

2727 === 

2728 

2729 Objects can define their own expand hints by defining 

2730 ``_eval_expand_hint()``. The function should take the form:: 

2731 

2732 def _eval_expand_hint(self, **hints): 

2733 # Only apply the method to the top-level expression 

2734 ... 

2735 

2736 See also the example below. Objects should define ``_eval_expand_hint()`` 

2737 methods only if ``hint`` applies to that specific object. The generic 

2738 ``_eval_expand_hint()`` method defined in Expr will handle the no-op case. 

2739 

2740 Each hint should be responsible for expanding that hint only. 

2741 Furthermore, the expansion should be applied to the top-level expression 

2742 only. ``expand()`` takes care of the recursion that happens when 

2743 ``deep=True``. 

2744 

2745 You should only call ``_eval_expand_hint()`` methods directly if you are 

2746 100% sure that the object has the method, as otherwise you are liable to 

2747 get unexpected ``AttributeError``s. Note, again, that you do not need to 

2748 recursively apply the hint to args of your object: this is handled 

2749 automatically by ``expand()``. ``_eval_expand_hint()`` should 

2750 generally not be used at all outside of an ``_eval_expand_hint()`` method. 

2751 If you want to apply a specific expansion from within another method, use 

2752 the public ``expand()`` function, method, or ``expand_hint()`` functions. 

2753 

2754 In order for expand to work, objects must be rebuildable by their args, 

2755 i.e., ``obj.func(*obj.args) == obj`` must hold. 

2756 

2757 Expand methods are passed ``**hints`` so that expand hints may use 

2758 'metahints'--hints that control how different expand methods are applied. 

2759 For example, the ``force=True`` hint described above that causes 

2760 ``expand(log=True)`` to ignore assumptions is such a metahint. The 

2761 ``deep`` meta-hint is handled exclusively by ``expand()`` and is not 

2762 passed to ``_eval_expand_hint()`` methods. 

2763 

2764 Note that expansion hints should generally be methods that perform some 

2765 kind of 'expansion'. For hints that simply rewrite an expression, use the 

2766 .rewrite() API. 

2767 

2768 Examples 

2769 ======== 

2770 

2771 >>> from sympy import Expr, sympify 

2772 >>> class MyClass(Expr): 

2773 ... def __new__(cls, *args): 

2774 ... args = sympify(args) 

2775 ... return Expr.__new__(cls, *args) 

2776 ... 

2777 ... def _eval_expand_double(self, *, force=False, **hints): 

2778 ... ''' 

2779 ... Doubles the args of MyClass. 

2780 ... 

2781 ... If there more than four args, doubling is not performed, 

2782 ... unless force=True is also used (False by default). 

2783 ... ''' 

2784 ... if not force and len(self.args) > 4: 

2785 ... return self 

2786 ... return self.func(*(self.args + self.args)) 

2787 ... 

2788 >>> a = MyClass(1, 2, MyClass(3, 4)) 

2789 >>> a 

2790 MyClass(1, 2, MyClass(3, 4)) 

2791 >>> a.expand(double=True) 

2792 MyClass(1, 2, MyClass(3, 4, 3, 4), 1, 2, MyClass(3, 4, 3, 4)) 

2793 >>> a.expand(double=True, deep=False) 

2794 MyClass(1, 2, MyClass(3, 4), 1, 2, MyClass(3, 4)) 

2795 

2796 >>> b = MyClass(1, 2, 3, 4, 5) 

2797 >>> b.expand(double=True) 

2798 MyClass(1, 2, 3, 4, 5) 

2799 >>> b.expand(double=True, force=True) 

2800 MyClass(1, 2, 3, 4, 5, 1, 2, 3, 4, 5) 

2801 

2802 See Also 

2803 ======== 

2804 

2805 expand_log, expand_mul, expand_multinomial, expand_complex, expand_trig, 

2806 expand_power_base, expand_power_exp, expand_func, sympy.simplify.hyperexpand.hyperexpand 

2807 

2808 """ 

2809 # don't modify this; modify the Expr.expand method 

2810 hints['power_base'] = power_base 

2811 hints['power_exp'] = power_exp 

2812 hints['mul'] = mul 

2813 hints['log'] = log 

2814 hints['multinomial'] = multinomial 

2815 hints['basic'] = basic 

2816 return sympify(e).expand(deep=deep, modulus=modulus, **hints) 

2817 

2818# This is a special application of two hints 

2819 

2820def _mexpand(expr, recursive=False): 

2821 # expand multinomials and then expand products; this may not always 

2822 # be sufficient to give a fully expanded expression (see 

2823 # test_issue_8247_8354 in test_arit) 

2824 if expr is None: 

2825 return 

2826 was = None 

2827 while was != expr: 

2828 was, expr = expr, expand_mul(expand_multinomial(expr)) 

2829 if not recursive: 

2830 break 

2831 return expr 

2832 

2833 

2834# These are simple wrappers around single hints. 

2835 

2836 

2837def expand_mul(expr, deep=True): 

2838 """ 

2839 Wrapper around expand that only uses the mul hint. See the expand 

2840 docstring for more information. 

2841 

2842 Examples 

2843 ======== 

2844 

2845 >>> from sympy import symbols, expand_mul, exp, log 

2846 >>> x, y = symbols('x,y', positive=True) 

2847 >>> expand_mul(exp(x+y)*(x+y)*log(x*y**2)) 

2848 x*exp(x + y)*log(x*y**2) + y*exp(x + y)*log(x*y**2) 

2849 

2850 """ 

2851 return sympify(expr).expand(deep=deep, mul=True, power_exp=False, 

2852 power_base=False, basic=False, multinomial=False, log=False) 

2853 

2854 

2855def expand_multinomial(expr, deep=True): 

2856 """ 

2857 Wrapper around expand that only uses the multinomial hint. See the expand 

2858 docstring for more information. 

2859 

2860 Examples 

2861 ======== 

2862 

2863 >>> from sympy import symbols, expand_multinomial, exp 

2864 >>> x, y = symbols('x y', positive=True) 

2865 >>> expand_multinomial((x + exp(x + 1))**2) 

2866 x**2 + 2*x*exp(x + 1) + exp(2*x + 2) 

2867 

2868 """ 

2869 return sympify(expr).expand(deep=deep, mul=False, power_exp=False, 

2870 power_base=False, basic=False, multinomial=True, log=False) 

2871 

2872 

2873def expand_log(expr, deep=True, force=False, factor=False): 

2874 """ 

2875 Wrapper around expand that only uses the log hint. See the expand 

2876 docstring for more information. 

2877 

2878 Examples 

2879 ======== 

2880 

2881 >>> from sympy import symbols, expand_log, exp, log 

2882 >>> x, y = symbols('x,y', positive=True) 

2883 >>> expand_log(exp(x+y)*(x+y)*log(x*y**2)) 

2884 (x + y)*(log(x) + 2*log(y))*exp(x + y) 

2885 

2886 """ 

2887 from sympy.functions.elementary.exponential import log 

2888 if factor is False: 

2889 def _handle(x): 

2890 x1 = expand_mul(expand_log(x, deep=deep, force=force, factor=True)) 

2891 if x1.count(log) <= x.count(log): 

2892 return x1 

2893 return x 

2894 

2895 expr = expr.replace( 

2896 lambda x: x.is_Mul and all(any(isinstance(i, log) and i.args[0].is_Rational 

2897 for i in Mul.make_args(j)) for j in x.as_numer_denom()), 

2898 _handle) 

2899 

2900 return sympify(expr).expand(deep=deep, log=True, mul=False, 

2901 power_exp=False, power_base=False, multinomial=False, 

2902 basic=False, force=force, factor=factor) 

2903 

2904 

2905def expand_func(expr, deep=True): 

2906 """ 

2907 Wrapper around expand that only uses the func hint. See the expand 

2908 docstring for more information. 

2909 

2910 Examples 

2911 ======== 

2912 

2913 >>> from sympy import expand_func, gamma 

2914 >>> from sympy.abc import x 

2915 >>> expand_func(gamma(x + 2)) 

2916 x*(x + 1)*gamma(x) 

2917 

2918 """ 

2919 return sympify(expr).expand(deep=deep, func=True, basic=False, 

2920 log=False, mul=False, power_exp=False, power_base=False, multinomial=False) 

2921 

2922 

2923def expand_trig(expr, deep=True): 

2924 """ 

2925 Wrapper around expand that only uses the trig hint. See the expand 

2926 docstring for more information. 

2927 

2928 Examples 

2929 ======== 

2930 

2931 >>> from sympy import expand_trig, sin 

2932 >>> from sympy.abc import x, y 

2933 >>> expand_trig(sin(x+y)*(x+y)) 

2934 (x + y)*(sin(x)*cos(y) + sin(y)*cos(x)) 

2935 

2936 """ 

2937 return sympify(expr).expand(deep=deep, trig=True, basic=False, 

2938 log=False, mul=False, power_exp=False, power_base=False, multinomial=False) 

2939 

2940 

2941def expand_complex(expr, deep=True): 

2942 """ 

2943 Wrapper around expand that only uses the complex hint. See the expand 

2944 docstring for more information. 

2945 

2946 Examples 

2947 ======== 

2948 

2949 >>> from sympy import expand_complex, exp, sqrt, I 

2950 >>> from sympy.abc import z 

2951 >>> expand_complex(exp(z)) 

2952 I*exp(re(z))*sin(im(z)) + exp(re(z))*cos(im(z)) 

2953 >>> expand_complex(sqrt(I)) 

2954 sqrt(2)/2 + sqrt(2)*I/2 

2955 

2956 See Also 

2957 ======== 

2958 

2959 sympy.core.expr.Expr.as_real_imag 

2960 """ 

2961 return sympify(expr).expand(deep=deep, complex=True, basic=False, 

2962 log=False, mul=False, power_exp=False, power_base=False, multinomial=False) 

2963 

2964 

2965def expand_power_base(expr, deep=True, force=False): 

2966 """ 

2967 Wrapper around expand that only uses the power_base hint. 

2968 

2969 A wrapper to expand(power_base=True) which separates a power with a base 

2970 that is a Mul into a product of powers, without performing any other 

2971 expansions, provided that assumptions about the power's base and exponent 

2972 allow. 

2973 

2974 deep=False (default is True) will only apply to the top-level expression. 

2975 

2976 force=True (default is False) will cause the expansion to ignore 

2977 assumptions about the base and exponent. When False, the expansion will 

2978 only happen if the base is non-negative or the exponent is an integer. 

2979 

2980 >>> from sympy.abc import x, y, z 

2981 >>> from sympy import expand_power_base, sin, cos, exp, Symbol 

2982 

2983 >>> (x*y)**2 

2984 x**2*y**2 

2985 

2986 >>> (2*x)**y 

2987 (2*x)**y 

2988 >>> expand_power_base(_) 

2989 2**y*x**y 

2990 

2991 >>> expand_power_base((x*y)**z) 

2992 (x*y)**z 

2993 >>> expand_power_base((x*y)**z, force=True) 

2994 x**z*y**z 

2995 >>> expand_power_base(sin((x*y)**z), deep=False) 

2996 sin((x*y)**z) 

2997 >>> expand_power_base(sin((x*y)**z), force=True) 

2998 sin(x**z*y**z) 

2999 

3000 >>> expand_power_base((2*sin(x))**y + (2*cos(x))**y) 

3001 2**y*sin(x)**y + 2**y*cos(x)**y 

3002 

3003 >>> expand_power_base((2*exp(y))**x) 

3004 2**x*exp(y)**x 

3005 

3006 >>> expand_power_base((2*cos(x))**y) 

3007 2**y*cos(x)**y 

3008 

3009 Notice that sums are left untouched. If this is not the desired behavior, 

3010 apply full ``expand()`` to the expression: 

3011 

3012 >>> expand_power_base(((x+y)*z)**2) 

3013 z**2*(x + y)**2 

3014 >>> (((x+y)*z)**2).expand() 

3015 x**2*z**2 + 2*x*y*z**2 + y**2*z**2 

3016 

3017 >>> expand_power_base((2*y)**(1+z)) 

3018 2**(z + 1)*y**(z + 1) 

3019 >>> ((2*y)**(1+z)).expand() 

3020 2*2**z*y**(z + 1) 

3021 

3022 The power that is unexpanded can be expanded safely when 

3023 ``y != 0``, otherwise different values might be obtained for the expression: 

3024 

3025 >>> prev = _ 

3026 

3027 If we indicate that ``y`` is positive but then replace it with 

3028 a value of 0 after expansion, the expression becomes 0: 

3029 

3030 >>> p = Symbol('p', positive=True) 

3031 >>> prev.subs(y, p).expand().subs(p, 0) 

3032 0 

3033 

3034 But if ``z = -1`` the expression would not be zero: 

3035 

3036 >>> prev.subs(y, 0).subs(z, -1) 

3037 1 

3038 

3039 See Also 

3040 ======== 

3041 

3042 expand 

3043 

3044 """ 

3045 return sympify(expr).expand(deep=deep, log=False, mul=False, 

3046 power_exp=False, power_base=True, multinomial=False, 

3047 basic=False, force=force) 

3048 

3049 

3050def expand_power_exp(expr, deep=True): 

3051 """ 

3052 Wrapper around expand that only uses the power_exp hint. 

3053 

3054 See the expand docstring for more information. 

3055 

3056 Examples 

3057 ======== 

3058 

3059 >>> from sympy import expand_power_exp, Symbol 

3060 >>> from sympy.abc import x, y 

3061 >>> expand_power_exp(3**(y + 2)) 

3062 9*3**y 

3063 >>> expand_power_exp(x**(y + 2)) 

3064 x**(y + 2) 

3065 

3066 If ``x = 0`` the value of the expression depends on the 

3067 value of ``y``; if the expression were expanded the result 

3068 would be 0. So expansion is only done if ``x != 0``: 

3069 

3070 >>> expand_power_exp(Symbol('x', zero=False)**(y + 2)) 

3071 x**2*x**y 

3072 """ 

3073 return sympify(expr).expand(deep=deep, complex=False, basic=False, 

3074 log=False, mul=False, power_exp=True, power_base=False, multinomial=False) 

3075 

3076 

3077def count_ops(expr, visual=False): 

3078 """ 

3079 Return a representation (integer or expression) of the operations in expr. 

3080 

3081 Parameters 

3082 ========== 

3083 

3084 expr : Expr 

3085 If expr is an iterable, the sum of the op counts of the 

3086 items will be returned. 

3087 

3088 visual : bool, optional 

3089 If ``False`` (default) then the sum of the coefficients of the 

3090 visual expression will be returned. 

3091 If ``True`` then the number of each type of operation is shown 

3092 with the core class types (or their virtual equivalent) multiplied by the 

3093 number of times they occur. 

3094 

3095 Examples 

3096 ======== 

3097 

3098 >>> from sympy.abc import a, b, x, y 

3099 >>> from sympy import sin, count_ops 

3100 

3101 Although there is not a SUB object, minus signs are interpreted as 

3102 either negations or subtractions: 

3103 

3104 >>> (x - y).count_ops(visual=True) 

3105 SUB 

3106 >>> (-x).count_ops(visual=True) 

3107 NEG 

3108 

3109 Here, there are two Adds and a Pow: 

3110 

3111 >>> (1 + a + b**2).count_ops(visual=True) 

3112 2*ADD + POW 

3113 

3114 In the following, an Add, Mul, Pow and two functions: 

3115 

3116 >>> (sin(x)*x + sin(x)**2).count_ops(visual=True) 

3117 ADD + MUL + POW + 2*SIN 

3118 

3119 for a total of 5: 

3120 

3121 >>> (sin(x)*x + sin(x)**2).count_ops(visual=False) 

3122 5 

3123 

3124 Note that "what you type" is not always what you get. The expression 

3125 1/x/y is translated by sympy into 1/(x*y) so it gives a DIV and MUL rather 

3126 than two DIVs: 

3127 

3128 >>> (1/x/y).count_ops(visual=True) 

3129 DIV + MUL 

3130 

3131 The visual option can be used to demonstrate the difference in 

3132 operations for expressions in different forms. Here, the Horner 

3133 representation is compared with the expanded form of a polynomial: 

3134 

3135 >>> eq=x*(1 + x*(2 + x*(3 + x))) 

3136 >>> count_ops(eq.expand(), visual=True) - count_ops(eq, visual=True) 

3137 -MUL + 3*POW 

3138 

3139 The count_ops function also handles iterables: 

3140 

3141 >>> count_ops([x, sin(x), None, True, x + 2], visual=False) 

3142 2 

3143 >>> count_ops([x, sin(x), None, True, x + 2], visual=True) 

3144 ADD + SIN 

3145 >>> count_ops({x: sin(x), x + 2: y + 1}, visual=True) 

3146 2*ADD + SIN 

3147 

3148 """ 

3149 from .relational import Relational 

3150 from sympy.concrete.summations import Sum 

3151 from sympy.integrals.integrals import Integral 

3152 from sympy.logic.boolalg import BooleanFunction 

3153 from sympy.simplify.radsimp import fraction 

3154 

3155 expr = sympify(expr) 

3156 if isinstance(expr, Expr) and not expr.is_Relational: 

3157 

3158 ops = [] 

3159 args = [expr] 

3160 NEG = Symbol('NEG') 

3161 DIV = Symbol('DIV') 

3162 SUB = Symbol('SUB') 

3163 ADD = Symbol('ADD') 

3164 EXP = Symbol('EXP') 

3165 while args: 

3166 a = args.pop() 

3167 

3168 # if the following fails because the object is 

3169 # not Basic type, then the object should be fixed 

3170 # since it is the intention that all args of Basic 

3171 # should themselves be Basic 

3172 if a.is_Rational: 

3173 #-1/3 = NEG + DIV 

3174 if a is not S.One: 

3175 if a.p < 0: 

3176 ops.append(NEG) 

3177 if a.q != 1: 

3178 ops.append(DIV) 

3179 continue 

3180 elif a.is_Mul or a.is_MatMul: 

3181 if _coeff_isneg(a): 

3182 ops.append(NEG) 

3183 if a.args[0] is S.NegativeOne: 

3184 a = a.as_two_terms()[1] 

3185 else: 

3186 a = -a 

3187 n, d = fraction(a) 

3188 if n.is_Integer: 

3189 ops.append(DIV) 

3190 if n < 0: 

3191 ops.append(NEG) 

3192 args.append(d) 

3193 continue # won't be -Mul but could be Add 

3194 elif d is not S.One: 

3195 if not d.is_Integer: 

3196 args.append(d) 

3197 ops.append(DIV) 

3198 args.append(n) 

3199 continue # could be -Mul 

3200 elif a.is_Add or a.is_MatAdd: 

3201 aargs = list(a.args) 

3202 negs = 0 

3203 for i, ai in enumerate(aargs): 

3204 if _coeff_isneg(ai): 

3205 negs += 1 

3206 args.append(-ai) 

3207 if i > 0: 

3208 ops.append(SUB) 

3209 else: 

3210 args.append(ai) 

3211 if i > 0: 

3212 ops.append(ADD) 

3213 if negs == len(aargs): # -x - y = NEG + SUB 

3214 ops.append(NEG) 

3215 elif _coeff_isneg(aargs[0]): # -x + y = SUB, but already recorded ADD 

3216 ops.append(SUB - ADD) 

3217 continue 

3218 if a.is_Pow and a.exp is S.NegativeOne: 

3219 ops.append(DIV) 

3220 args.append(a.base) # won't be -Mul but could be Add 

3221 continue 

3222 if a == S.Exp1: 

3223 ops.append(EXP) 

3224 continue 

3225 if a.is_Pow and a.base == S.Exp1: 

3226 ops.append(EXP) 

3227 args.append(a.exp) 

3228 continue 

3229 if a.is_Mul or isinstance(a, LatticeOp): 

3230 o = Symbol(a.func.__name__.upper()) 

3231 # count the args 

3232 ops.append(o*(len(a.args) - 1)) 

3233 elif a.args and ( 

3234 a.is_Pow or 

3235 a.is_Function or 

3236 isinstance(a, Derivative) or 

3237 isinstance(a, Integral) or 

3238 isinstance(a, Sum)): 

3239 # if it's not in the list above we don't 

3240 # consider a.func something to count, e.g. 

3241 # Tuple, MatrixSymbol, etc... 

3242 if isinstance(a.func, UndefinedFunction): 

3243 o = Symbol("FUNC_" + a.func.__name__.upper()) 

3244 else: 

3245 o = Symbol(a.func.__name__.upper()) 

3246 ops.append(o) 

3247 

3248 if not a.is_Symbol: 

3249 args.extend(a.args) 

3250 

3251 elif isinstance(expr, Dict): 

3252 ops = [count_ops(k, visual=visual) + 

3253 count_ops(v, visual=visual) for k, v in expr.items()] 

3254 elif iterable(expr): 

3255 ops = [count_ops(i, visual=visual) for i in expr] 

3256 elif isinstance(expr, (Relational, BooleanFunction)): 

3257 ops = [] 

3258 for arg in expr.args: 

3259 ops.append(count_ops(arg, visual=True)) 

3260 o = Symbol(func_name(expr, short=True).upper()) 

3261 ops.append(o) 

3262 elif not isinstance(expr, Basic): 

3263 ops = [] 

3264 else: # it's Basic not isinstance(expr, Expr): 

3265 if not isinstance(expr, Basic): 

3266 raise TypeError("Invalid type of expr") 

3267 else: 

3268 ops = [] 

3269 args = [expr] 

3270 while args: 

3271 a = args.pop() 

3272 

3273 if a.args: 

3274 o = Symbol(type(a).__name__.upper()) 

3275 if a.is_Boolean: 

3276 ops.append(o*(len(a.args)-1)) 

3277 else: 

3278 ops.append(o) 

3279 args.extend(a.args) 

3280 

3281 if not ops: 

3282 if visual: 

3283 return S.Zero 

3284 return 0 

3285 

3286 ops = Add(*ops) 

3287 

3288 if visual: 

3289 return ops 

3290 

3291 if ops.is_Number: 

3292 return int(ops) 

3293 

3294 return sum(int((a.args or [1])[0]) for a in Add.make_args(ops)) 

3295 

3296 

3297def nfloat(expr, n=15, exponent=False, dkeys=False): 

3298 """Make all Rationals in expr Floats except those in exponents 

3299 (unless the exponents flag is set to True) and those in undefined 

3300 functions. When processing dictionaries, do not modify the keys 

3301 unless ``dkeys=True``. 

3302 

3303 Examples 

3304 ======== 

3305 

3306 >>> from sympy import nfloat, cos, pi, sqrt 

3307 >>> from sympy.abc import x, y 

3308 >>> nfloat(x**4 + x/2 + cos(pi/3) + 1 + sqrt(y)) 

3309 x**4 + 0.5*x + sqrt(y) + 1.5 

3310 >>> nfloat(x**4 + sqrt(y), exponent=True) 

3311 x**4.0 + y**0.5 

3312 

3313 Container types are not modified: 

3314 

3315 >>> type(nfloat((1, 2))) is tuple 

3316 True 

3317 """ 

3318 from sympy.matrices.matrices import MatrixBase 

3319 

3320 kw = {"n": n, "exponent": exponent, "dkeys": dkeys} 

3321 

3322 if isinstance(expr, MatrixBase): 

3323 return expr.applyfunc(lambda e: nfloat(e, **kw)) 

3324 

3325 # handling of iterable containers 

3326 if iterable(expr, exclude=str): 

3327 if isinstance(expr, (dict, Dict)): 

3328 if dkeys: 

3329 args = [tuple((nfloat(i, **kw) for i in a)) 

3330 for a in expr.items()] 

3331 else: 

3332 args = [(k, nfloat(v, **kw)) for k, v in expr.items()] 

3333 if isinstance(expr, dict): 

3334 return type(expr)(args) 

3335 else: 

3336 return expr.func(*args) 

3337 elif isinstance(expr, Basic): 

3338 return expr.func(*[nfloat(a, **kw) for a in expr.args]) 

3339 return type(expr)([nfloat(a, **kw) for a in expr]) 

3340 

3341 rv = sympify(expr) 

3342 

3343 if rv.is_Number: 

3344 return Float(rv, n) 

3345 elif rv.is_number: 

3346 # evalf doesn't always set the precision 

3347 rv = rv.n(n) 

3348 if rv.is_Number: 

3349 rv = Float(rv.n(n), n) 

3350 else: 

3351 pass # pure_complex(rv) is likely True 

3352 return rv 

3353 elif rv.is_Atom: 

3354 return rv 

3355 elif rv.is_Relational: 

3356 args_nfloat = (nfloat(arg, **kw) for arg in rv.args) 

3357 return rv.func(*args_nfloat) 

3358 

3359 

3360 # watch out for RootOf instances that don't like to have 

3361 # their exponents replaced with Dummies and also sometimes have 

3362 # problems with evaluating at low precision (issue 6393) 

3363 from sympy.polys.rootoftools import RootOf 

3364 rv = rv.xreplace({ro: ro.n(n) for ro in rv.atoms(RootOf)}) 

3365 

3366 from .power import Pow 

3367 if not exponent: 

3368 reps = [(p, Pow(p.base, Dummy())) for p in rv.atoms(Pow)] 

3369 rv = rv.xreplace(dict(reps)) 

3370 rv = rv.n(n) 

3371 if not exponent: 

3372 rv = rv.xreplace({d.exp: p.exp for p, d in reps}) 

3373 else: 

3374 # Pow._eval_evalf special cases Integer exponents so if 

3375 # exponent is suppose to be handled we have to do so here 

3376 rv = rv.xreplace(Transform( 

3377 lambda x: Pow(x.base, Float(x.exp, n)), 

3378 lambda x: x.is_Pow and x.exp.is_Integer)) 

3379 

3380 return rv.xreplace(Transform( 

3381 lambda x: x.func(*nfloat(x.args, n, exponent)), 

3382 lambda x: isinstance(x, Function) and not isinstance(x, AppliedUndef))) 

3383 

3384 

3385from .symbol import Dummy, Symbol