simplify.py 71 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150
  1. from collections import defaultdict
  2. from sympy.concrete.products import Product
  3. from sympy.concrete.summations import Sum
  4. from sympy.core import (Basic, S, Add, Mul, Pow, Symbol, sympify,
  5. expand_func, Function, Dummy, Expr, factor_terms,
  6. expand_power_exp, Eq)
  7. from sympy.core.exprtools import factor_nc
  8. from sympy.core.parameters import global_parameters
  9. from sympy.core.function import (expand_log, count_ops, _mexpand,
  10. nfloat, expand_mul, expand)
  11. from sympy.core.numbers import Float, I, pi, Rational
  12. from sympy.core.relational import Relational
  13. from sympy.core.rules import Transform
  14. from sympy.core.sorting import ordered
  15. from sympy.core.sympify import _sympify
  16. from sympy.core.traversal import bottom_up as _bottom_up, walk as _walk
  17. from sympy.functions import gamma, exp, sqrt, log, exp_polar, re
  18. from sympy.functions.combinatorial.factorials import CombinatorialFunction
  19. from sympy.functions.elementary.complexes import unpolarify, Abs, sign
  20. from sympy.functions.elementary.exponential import ExpBase
  21. from sympy.functions.elementary.hyperbolic import HyperbolicFunction
  22. from sympy.functions.elementary.integers import ceiling
  23. from sympy.functions.elementary.piecewise import (Piecewise, piecewise_fold,
  24. piecewise_simplify)
  25. from sympy.functions.elementary.trigonometric import TrigonometricFunction
  26. from sympy.functions.special.bessel import (BesselBase, besselj, besseli,
  27. besselk, bessely, jn)
  28. from sympy.functions.special.tensor_functions import KroneckerDelta
  29. from sympy.integrals.integrals import Integral
  30. from sympy.matrices.expressions import (MatrixExpr, MatAdd, MatMul,
  31. MatPow, MatrixSymbol)
  32. from sympy.polys import together, cancel, factor
  33. from sympy.polys.numberfields.minpoly import _is_sum_surds, _minimal_polynomial_sq
  34. from sympy.simplify.combsimp import combsimp
  35. from sympy.simplify.cse_opts import sub_pre, sub_post
  36. from sympy.simplify.hyperexpand import hyperexpand
  37. from sympy.simplify.powsimp import powsimp
  38. from sympy.simplify.radsimp import radsimp, fraction, collect_abs
  39. from sympy.simplify.sqrtdenest import sqrtdenest
  40. from sympy.simplify.trigsimp import trigsimp, exptrigsimp
  41. from sympy.utilities.decorator import deprecated
  42. from sympy.utilities.iterables import has_variety, sift, subsets, iterable
  43. from sympy.utilities.misc import as_int
  44. import mpmath
  45. def separatevars(expr, symbols=[], dict=False, force=False):
  46. """
  47. Separates variables in an expression, if possible. By
  48. default, it separates with respect to all symbols in an
  49. expression and collects constant coefficients that are
  50. independent of symbols.
  51. Explanation
  52. ===========
  53. If ``dict=True`` then the separated terms will be returned
  54. in a dictionary keyed to their corresponding symbols.
  55. By default, all symbols in the expression will appear as
  56. keys; if symbols are provided, then all those symbols will
  57. be used as keys, and any terms in the expression containing
  58. other symbols or non-symbols will be returned keyed to the
  59. string 'coeff'. (Passing None for symbols will return the
  60. expression in a dictionary keyed to 'coeff'.)
  61. If ``force=True``, then bases of powers will be separated regardless
  62. of assumptions on the symbols involved.
  63. Notes
  64. =====
  65. The order of the factors is determined by Mul, so that the
  66. separated expressions may not necessarily be grouped together.
  67. Although factoring is necessary to separate variables in some
  68. expressions, it is not necessary in all cases, so one should not
  69. count on the returned factors being factored.
  70. Examples
  71. ========
  72. >>> from sympy.abc import x, y, z, alpha
  73. >>> from sympy import separatevars, sin
  74. >>> separatevars((x*y)**y)
  75. (x*y)**y
  76. >>> separatevars((x*y)**y, force=True)
  77. x**y*y**y
  78. >>> e = 2*x**2*z*sin(y)+2*z*x**2
  79. >>> separatevars(e)
  80. 2*x**2*z*(sin(y) + 1)
  81. >>> separatevars(e, symbols=(x, y), dict=True)
  82. {'coeff': 2*z, x: x**2, y: sin(y) + 1}
  83. >>> separatevars(e, [x, y, alpha], dict=True)
  84. {'coeff': 2*z, alpha: 1, x: x**2, y: sin(y) + 1}
  85. If the expression is not really separable, or is only partially
  86. separable, separatevars will do the best it can to separate it
  87. by using factoring.
  88. >>> separatevars(x + x*y - 3*x**2)
  89. -x*(3*x - y - 1)
  90. If the expression is not separable then expr is returned unchanged
  91. or (if dict=True) then None is returned.
  92. >>> eq = 2*x + y*sin(x)
  93. >>> separatevars(eq) == eq
  94. True
  95. >>> separatevars(2*x + y*sin(x), symbols=(x, y), dict=True) is None
  96. True
  97. """
  98. expr = sympify(expr)
  99. if dict:
  100. return _separatevars_dict(_separatevars(expr, force), symbols)
  101. else:
  102. return _separatevars(expr, force)
  103. def _separatevars(expr, force):
  104. if isinstance(expr, Abs):
  105. arg = expr.args[0]
  106. if arg.is_Mul and not arg.is_number:
  107. s = separatevars(arg, dict=True, force=force)
  108. if s is not None:
  109. return Mul(*map(expr.func, s.values()))
  110. else:
  111. return expr
  112. if len(expr.free_symbols) < 2:
  113. return expr
  114. # don't destroy a Mul since much of the work may already be done
  115. if expr.is_Mul:
  116. args = list(expr.args)
  117. changed = False
  118. for i, a in enumerate(args):
  119. args[i] = separatevars(a, force)
  120. changed = changed or args[i] != a
  121. if changed:
  122. expr = expr.func(*args)
  123. return expr
  124. # get a Pow ready for expansion
  125. if expr.is_Pow and expr.base != S.Exp1:
  126. expr = Pow(separatevars(expr.base, force=force), expr.exp)
  127. # First try other expansion methods
  128. expr = expr.expand(mul=False, multinomial=False, force=force)
  129. _expr, reps = posify(expr) if force else (expr, {})
  130. expr = factor(_expr).subs(reps)
  131. if not expr.is_Add:
  132. return expr
  133. # Find any common coefficients to pull out
  134. args = list(expr.args)
  135. commonc = args[0].args_cnc(cset=True, warn=False)[0]
  136. for i in args[1:]:
  137. commonc &= i.args_cnc(cset=True, warn=False)[0]
  138. commonc = Mul(*commonc)
  139. commonc = commonc.as_coeff_Mul()[1] # ignore constants
  140. commonc_set = commonc.args_cnc(cset=True, warn=False)[0]
  141. # remove them
  142. for i, a in enumerate(args):
  143. c, nc = a.args_cnc(cset=True, warn=False)
  144. c = c - commonc_set
  145. args[i] = Mul(*c)*Mul(*nc)
  146. nonsepar = Add(*args)
  147. if len(nonsepar.free_symbols) > 1:
  148. _expr = nonsepar
  149. _expr, reps = posify(_expr) if force else (_expr, {})
  150. _expr = (factor(_expr)).subs(reps)
  151. if not _expr.is_Add:
  152. nonsepar = _expr
  153. return commonc*nonsepar
  154. def _separatevars_dict(expr, symbols):
  155. if symbols:
  156. if not all(t.is_Atom for t in symbols):
  157. raise ValueError("symbols must be Atoms.")
  158. symbols = list(symbols)
  159. elif symbols is None:
  160. return {'coeff': expr}
  161. else:
  162. symbols = list(expr.free_symbols)
  163. if not symbols:
  164. return None
  165. ret = {i: [] for i in symbols + ['coeff']}
  166. for i in Mul.make_args(expr):
  167. expsym = i.free_symbols
  168. intersection = set(symbols).intersection(expsym)
  169. if len(intersection) > 1:
  170. return None
  171. if len(intersection) == 0:
  172. # There are no symbols, so it is part of the coefficient
  173. ret['coeff'].append(i)
  174. else:
  175. ret[intersection.pop()].append(i)
  176. # rebuild
  177. for k, v in ret.items():
  178. ret[k] = Mul(*v)
  179. return ret
  180. def posify(eq):
  181. """Return ``eq`` (with generic symbols made positive) and a
  182. dictionary containing the mapping between the old and new
  183. symbols.
  184. Explanation
  185. ===========
  186. Any symbol that has positive=None will be replaced with a positive dummy
  187. symbol having the same name. This replacement will allow more symbolic
  188. processing of expressions, especially those involving powers and
  189. logarithms.
  190. A dictionary that can be sent to subs to restore ``eq`` to its original
  191. symbols is also returned.
  192. >>> from sympy import posify, Symbol, log, solve
  193. >>> from sympy.abc import x
  194. >>> posify(x + Symbol('p', positive=True) + Symbol('n', negative=True))
  195. (_x + n + p, {_x: x})
  196. >>> eq = 1/x
  197. >>> log(eq).expand()
  198. log(1/x)
  199. >>> log(posify(eq)[0]).expand()
  200. -log(_x)
  201. >>> p, rep = posify(eq)
  202. >>> log(p).expand().subs(rep)
  203. -log(x)
  204. It is possible to apply the same transformations to an iterable
  205. of expressions:
  206. >>> eq = x**2 - 4
  207. >>> solve(eq, x)
  208. [-2, 2]
  209. >>> eq_x, reps = posify([eq, x]); eq_x
  210. [_x**2 - 4, _x]
  211. >>> solve(*eq_x)
  212. [2]
  213. """
  214. eq = sympify(eq)
  215. if iterable(eq):
  216. f = type(eq)
  217. eq = list(eq)
  218. syms = set()
  219. for e in eq:
  220. syms = syms.union(e.atoms(Symbol))
  221. reps = {}
  222. for s in syms:
  223. reps.update({v: k for k, v in posify(s)[1].items()})
  224. for i, e in enumerate(eq):
  225. eq[i] = e.subs(reps)
  226. return f(eq), {r: s for s, r in reps.items()}
  227. reps = {s: Dummy(s.name, positive=True, **s.assumptions0)
  228. for s in eq.free_symbols if s.is_positive is None}
  229. eq = eq.subs(reps)
  230. return eq, {r: s for s, r in reps.items()}
  231. def hypersimp(f, k):
  232. """Given combinatorial term f(k) simplify its consecutive term ratio
  233. i.e. f(k+1)/f(k). The input term can be composed of functions and
  234. integer sequences which have equivalent representation in terms
  235. of gamma special function.
  236. Explanation
  237. ===========
  238. The algorithm performs three basic steps:
  239. 1. Rewrite all functions in terms of gamma, if possible.
  240. 2. Rewrite all occurrences of gamma in terms of products
  241. of gamma and rising factorial with integer, absolute
  242. constant exponent.
  243. 3. Perform simplification of nested fractions, powers
  244. and if the resulting expression is a quotient of
  245. polynomials, reduce their total degree.
  246. If f(k) is hypergeometric then as result we arrive with a
  247. quotient of polynomials of minimal degree. Otherwise None
  248. is returned.
  249. For more information on the implemented algorithm refer to:
  250. 1. W. Koepf, Algorithms for m-fold Hypergeometric Summation,
  251. Journal of Symbolic Computation (1995) 20, 399-417
  252. """
  253. f = sympify(f)
  254. g = f.subs(k, k + 1) / f
  255. g = g.rewrite(gamma)
  256. if g.has(Piecewise):
  257. g = piecewise_fold(g)
  258. g = g.args[-1][0]
  259. g = expand_func(g)
  260. g = powsimp(g, deep=True, combine='exp')
  261. if g.is_rational_function(k):
  262. return simplify(g, ratio=S.Infinity)
  263. else:
  264. return None
  265. def hypersimilar(f, g, k):
  266. """
  267. Returns True if ``f`` and ``g`` are hyper-similar.
  268. Explanation
  269. ===========
  270. Similarity in hypergeometric sense means that a quotient of
  271. f(k) and g(k) is a rational function in ``k``. This procedure
  272. is useful in solving recurrence relations.
  273. For more information see hypersimp().
  274. """
  275. f, g = list(map(sympify, (f, g)))
  276. h = (f/g).rewrite(gamma)
  277. h = h.expand(func=True, basic=False)
  278. return h.is_rational_function(k)
  279. def signsimp(expr, evaluate=None):
  280. """Make all Add sub-expressions canonical wrt sign.
  281. Explanation
  282. ===========
  283. If an Add subexpression, ``a``, can have a sign extracted,
  284. as determined by could_extract_minus_sign, it is replaced
  285. with Mul(-1, a, evaluate=False). This allows signs to be
  286. extracted from powers and products.
  287. Examples
  288. ========
  289. >>> from sympy import signsimp, exp, symbols
  290. >>> from sympy.abc import x, y
  291. >>> i = symbols('i', odd=True)
  292. >>> n = -1 + 1/x
  293. >>> n/x/(-n)**2 - 1/n/x
  294. (-1 + 1/x)/(x*(1 - 1/x)**2) - 1/(x*(-1 + 1/x))
  295. >>> signsimp(_)
  296. 0
  297. >>> x*n + x*-n
  298. x*(-1 + 1/x) + x*(1 - 1/x)
  299. >>> signsimp(_)
  300. 0
  301. Since powers automatically handle leading signs
  302. >>> (-2)**i
  303. -2**i
  304. signsimp can be used to put the base of a power with an integer
  305. exponent into canonical form:
  306. >>> n**i
  307. (-1 + 1/x)**i
  308. By default, signsimp does not leave behind any hollow simplification:
  309. if making an Add canonical wrt sign didn't change the expression, the
  310. original Add is restored. If this is not desired then the keyword
  311. ``evaluate`` can be set to False:
  312. >>> e = exp(y - x)
  313. >>> signsimp(e) == e
  314. True
  315. >>> signsimp(e, evaluate=False)
  316. exp(-(x - y))
  317. """
  318. if evaluate is None:
  319. evaluate = global_parameters.evaluate
  320. expr = sympify(expr)
  321. if not isinstance(expr, (Expr, Relational)) or expr.is_Atom:
  322. return expr
  323. # get rid of an pre-existing unevaluation regarding sign
  324. e = expr.replace(lambda x: x.is_Mul and -(-x) != x, lambda x: -(-x))
  325. e = sub_post(sub_pre(e))
  326. if not isinstance(e, (Expr, Relational)) or e.is_Atom:
  327. return e
  328. if e.is_Add:
  329. rv = e.func(*[signsimp(a) for a in e.args])
  330. if not evaluate and isinstance(rv, Add
  331. ) and rv.could_extract_minus_sign():
  332. return Mul(S.NegativeOne, -rv, evaluate=False)
  333. return rv
  334. if evaluate:
  335. e = e.replace(lambda x: x.is_Mul and -(-x) != x, lambda x: -(-x))
  336. return e
  337. def simplify(expr, ratio=1.7, measure=count_ops, rational=False, inverse=False, doit=True, **kwargs):
  338. """Simplifies the given expression.
  339. Explanation
  340. ===========
  341. Simplification is not a well defined term and the exact strategies
  342. this function tries can change in the future versions of SymPy. If
  343. your algorithm relies on "simplification" (whatever it is), try to
  344. determine what you need exactly - is it powsimp()?, radsimp()?,
  345. together()?, logcombine()?, or something else? And use this particular
  346. function directly, because those are well defined and thus your algorithm
  347. will be robust.
  348. Nonetheless, especially for interactive use, or when you do not know
  349. anything about the structure of the expression, simplify() tries to apply
  350. intelligent heuristics to make the input expression "simpler". For
  351. example:
  352. >>> from sympy import simplify, cos, sin
  353. >>> from sympy.abc import x, y
  354. >>> a = (x + x**2)/(x*sin(y)**2 + x*cos(y)**2)
  355. >>> a
  356. (x**2 + x)/(x*sin(y)**2 + x*cos(y)**2)
  357. >>> simplify(a)
  358. x + 1
  359. Note that we could have obtained the same result by using specific
  360. simplification functions:
  361. >>> from sympy import trigsimp, cancel
  362. >>> trigsimp(a)
  363. (x**2 + x)/x
  364. >>> cancel(_)
  365. x + 1
  366. In some cases, applying :func:`simplify` may actually result in some more
  367. complicated expression. The default ``ratio=1.7`` prevents more extreme
  368. cases: if (result length)/(input length) > ratio, then input is returned
  369. unmodified. The ``measure`` parameter lets you specify the function used
  370. to determine how complex an expression is. The function should take a
  371. single argument as an expression and return a number such that if
  372. expression ``a`` is more complex than expression ``b``, then
  373. ``measure(a) > measure(b)``. The default measure function is
  374. :func:`~.count_ops`, which returns the total number of operations in the
  375. expression.
  376. For example, if ``ratio=1``, ``simplify`` output cannot be longer
  377. than input.
  378. ::
  379. >>> from sympy import sqrt, simplify, count_ops, oo
  380. >>> root = 1/(sqrt(2)+3)
  381. Since ``simplify(root)`` would result in a slightly longer expression,
  382. root is returned unchanged instead::
  383. >>> simplify(root, ratio=1) == root
  384. True
  385. If ``ratio=oo``, simplify will be applied anyway::
  386. >>> count_ops(simplify(root, ratio=oo)) > count_ops(root)
  387. True
  388. Note that the shortest expression is not necessary the simplest, so
  389. setting ``ratio`` to 1 may not be a good idea.
  390. Heuristically, the default value ``ratio=1.7`` seems like a reasonable
  391. choice.
  392. You can easily define your own measure function based on what you feel
  393. should represent the "size" or "complexity" of the input expression. Note
  394. that some choices, such as ``lambda expr: len(str(expr))`` may appear to be
  395. good metrics, but have other problems (in this case, the measure function
  396. may slow down simplify too much for very large expressions). If you do not
  397. know what a good metric would be, the default, ``count_ops``, is a good
  398. one.
  399. For example:
  400. >>> from sympy import symbols, log
  401. >>> a, b = symbols('a b', positive=True)
  402. >>> g = log(a) + log(b) + log(a)*log(1/b)
  403. >>> h = simplify(g)
  404. >>> h
  405. log(a*b**(1 - log(a)))
  406. >>> count_ops(g)
  407. 8
  408. >>> count_ops(h)
  409. 5
  410. So you can see that ``h`` is simpler than ``g`` using the count_ops metric.
  411. However, we may not like how ``simplify`` (in this case, using
  412. ``logcombine``) has created the ``b**(log(1/a) + 1)`` term. A simple way
  413. to reduce this would be to give more weight to powers as operations in
  414. ``count_ops``. We can do this by using the ``visual=True`` option:
  415. >>> print(count_ops(g, visual=True))
  416. 2*ADD + DIV + 4*LOG + MUL
  417. >>> print(count_ops(h, visual=True))
  418. 2*LOG + MUL + POW + SUB
  419. >>> from sympy import Symbol, S
  420. >>> def my_measure(expr):
  421. ... POW = Symbol('POW')
  422. ... # Discourage powers by giving POW a weight of 10
  423. ... count = count_ops(expr, visual=True).subs(POW, 10)
  424. ... # Every other operation gets a weight of 1 (the default)
  425. ... count = count.replace(Symbol, type(S.One))
  426. ... return count
  427. >>> my_measure(g)
  428. 8
  429. >>> my_measure(h)
  430. 14
  431. >>> 15./8 > 1.7 # 1.7 is the default ratio
  432. True
  433. >>> simplify(g, measure=my_measure)
  434. -log(a)*log(b) + log(a) + log(b)
  435. Note that because ``simplify()`` internally tries many different
  436. simplification strategies and then compares them using the measure
  437. function, we get a completely different result that is still different
  438. from the input expression by doing this.
  439. If ``rational=True``, Floats will be recast as Rationals before simplification.
  440. If ``rational=None``, Floats will be recast as Rationals but the result will
  441. be recast as Floats. If rational=False(default) then nothing will be done
  442. to the Floats.
  443. If ``inverse=True``, it will be assumed that a composition of inverse
  444. functions, such as sin and asin, can be cancelled in any order.
  445. For example, ``asin(sin(x))`` will yield ``x`` without checking whether
  446. x belongs to the set where this relation is true. The default is
  447. False.
  448. Note that ``simplify()`` automatically calls ``doit()`` on the final
  449. expression. You can avoid this behavior by passing ``doit=False`` as
  450. an argument.
  451. Also, it should be noted that simplifying a boolean expression is not
  452. well defined. If the expression prefers automatic evaluation (such as
  453. :obj:`~.Eq()` or :obj:`~.Or()`), simplification will return ``True`` or
  454. ``False`` if truth value can be determined. If the expression is not
  455. evaluated by default (such as :obj:`~.Predicate()`), simplification will
  456. not reduce it and you should use :func:`~.refine()` or :func:`~.ask()`
  457. function. This inconsistency will be resolved in future version.
  458. See Also
  459. ========
  460. sympy.assumptions.refine.refine : Simplification using assumptions.
  461. sympy.assumptions.ask.ask : Query for boolean expressions using assumptions.
  462. """
  463. def shorter(*choices):
  464. """
  465. Return the choice that has the fewest ops. In case of a tie,
  466. the expression listed first is selected.
  467. """
  468. if not has_variety(choices):
  469. return choices[0]
  470. return min(choices, key=measure)
  471. def done(e):
  472. rv = e.doit() if doit else e
  473. return shorter(rv, collect_abs(rv))
  474. expr = sympify(expr, rational=rational)
  475. kwargs = {
  476. "ratio": kwargs.get('ratio', ratio),
  477. "measure": kwargs.get('measure', measure),
  478. "rational": kwargs.get('rational', rational),
  479. "inverse": kwargs.get('inverse', inverse),
  480. "doit": kwargs.get('doit', doit)}
  481. # no routine for Expr needs to check for is_zero
  482. if isinstance(expr, Expr) and expr.is_zero:
  483. return S.Zero if not expr.is_Number else expr
  484. _eval_simplify = getattr(expr, '_eval_simplify', None)
  485. if _eval_simplify is not None:
  486. return _eval_simplify(**kwargs)
  487. original_expr = expr = collect_abs(signsimp(expr))
  488. if not isinstance(expr, Basic) or not expr.args: # XXX: temporary hack
  489. return expr
  490. if inverse and expr.has(Function):
  491. expr = inversecombine(expr)
  492. if not expr.args: # simplified to atomic
  493. return expr
  494. # do deep simplification
  495. handled = Add, Mul, Pow, ExpBase
  496. expr = expr.replace(
  497. # here, checking for x.args is not enough because Basic has
  498. # args but Basic does not always play well with replace, e.g.
  499. # when simultaneous is True found expressions will be masked
  500. # off with a Dummy but not all Basic objects in an expression
  501. # can be replaced with a Dummy
  502. lambda x: isinstance(x, Expr) and x.args and not isinstance(
  503. x, handled),
  504. lambda x: x.func(*[simplify(i, **kwargs) for i in x.args]),
  505. simultaneous=False)
  506. if not isinstance(expr, handled):
  507. return done(expr)
  508. if not expr.is_commutative:
  509. expr = nc_simplify(expr)
  510. # TODO: Apply different strategies, considering expression pattern:
  511. # is it a purely rational function? Is there any trigonometric function?...
  512. # See also https://github.com/sympy/sympy/pull/185.
  513. # rationalize Floats
  514. floats = False
  515. if rational is not False and expr.has(Float):
  516. floats = True
  517. expr = nsimplify(expr, rational=True)
  518. expr = _bottom_up(expr, lambda w: getattr(w, 'normal', lambda: w)())
  519. expr = Mul(*powsimp(expr).as_content_primitive())
  520. _e = cancel(expr)
  521. expr1 = shorter(_e, _mexpand(_e).cancel()) # issue 6829
  522. expr2 = shorter(together(expr, deep=True), together(expr1, deep=True))
  523. if ratio is S.Infinity:
  524. expr = expr2
  525. else:
  526. expr = shorter(expr2, expr1, expr)
  527. if not isinstance(expr, Basic): # XXX: temporary hack
  528. return expr
  529. expr = factor_terms(expr, sign=False)
  530. # must come before `Piecewise` since this introduces more `Piecewise` terms
  531. if expr.has(sign):
  532. expr = expr.rewrite(Abs)
  533. # Deal with Piecewise separately to avoid recursive growth of expressions
  534. if expr.has(Piecewise):
  535. # Fold into a single Piecewise
  536. expr = piecewise_fold(expr)
  537. # Apply doit, if doit=True
  538. expr = done(expr)
  539. # Still a Piecewise?
  540. if expr.has(Piecewise):
  541. # Fold into a single Piecewise, in case doit lead to some
  542. # expressions being Piecewise
  543. expr = piecewise_fold(expr)
  544. # kroneckersimp also affects Piecewise
  545. if expr.has(KroneckerDelta):
  546. expr = kroneckersimp(expr)
  547. # Still a Piecewise?
  548. if expr.has(Piecewise):
  549. # Do not apply doit on the segments as it has already
  550. # been done above, but simplify
  551. expr = piecewise_simplify(expr, deep=True, doit=False)
  552. # Still a Piecewise?
  553. if expr.has(Piecewise):
  554. # Try factor common terms
  555. expr = shorter(expr, factor_terms(expr))
  556. # As all expressions have been simplified above with the
  557. # complete simplify, nothing more needs to be done here
  558. return expr
  559. # hyperexpand automatically only works on hypergeometric terms
  560. # Do this after the Piecewise part to avoid recursive expansion
  561. expr = hyperexpand(expr)
  562. if expr.has(KroneckerDelta):
  563. expr = kroneckersimp(expr)
  564. if expr.has(BesselBase):
  565. expr = besselsimp(expr)
  566. if expr.has(TrigonometricFunction, HyperbolicFunction):
  567. expr = trigsimp(expr, deep=True)
  568. if expr.has(log):
  569. expr = shorter(expand_log(expr, deep=True), logcombine(expr))
  570. if expr.has(CombinatorialFunction, gamma):
  571. # expression with gamma functions or non-integer arguments is
  572. # automatically passed to gammasimp
  573. expr = combsimp(expr)
  574. if expr.has(Sum):
  575. expr = sum_simplify(expr, **kwargs)
  576. if expr.has(Integral):
  577. expr = expr.xreplace({
  578. i: factor_terms(i) for i in expr.atoms(Integral)})
  579. if expr.has(Product):
  580. expr = product_simplify(expr, **kwargs)
  581. from sympy.physics.units import Quantity
  582. if expr.has(Quantity):
  583. from sympy.physics.units.util import quantity_simplify
  584. expr = quantity_simplify(expr)
  585. short = shorter(powsimp(expr, combine='exp', deep=True), powsimp(expr), expr)
  586. short = shorter(short, cancel(short))
  587. short = shorter(short, factor_terms(short), expand_power_exp(expand_mul(short)))
  588. if short.has(TrigonometricFunction, HyperbolicFunction, ExpBase, exp):
  589. short = exptrigsimp(short)
  590. # get rid of hollow 2-arg Mul factorization
  591. hollow_mul = Transform(
  592. lambda x: Mul(*x.args),
  593. lambda x:
  594. x.is_Mul and
  595. len(x.args) == 2 and
  596. x.args[0].is_Number and
  597. x.args[1].is_Add and
  598. x.is_commutative)
  599. expr = short.xreplace(hollow_mul)
  600. numer, denom = expr.as_numer_denom()
  601. if denom.is_Add:
  602. n, d = fraction(radsimp(1/denom, symbolic=False, max_terms=1))
  603. if n is not S.One:
  604. expr = (numer*n).expand()/d
  605. if expr.could_extract_minus_sign():
  606. n, d = fraction(expr)
  607. if d != 0:
  608. expr = signsimp(-n/(-d))
  609. if measure(expr) > ratio*measure(original_expr):
  610. expr = original_expr
  611. # restore floats
  612. if floats and rational is None:
  613. expr = nfloat(expr, exponent=False)
  614. return done(expr)
  615. def sum_simplify(s, **kwargs):
  616. """Main function for Sum simplification"""
  617. if not isinstance(s, Add):
  618. s = s.xreplace({a: sum_simplify(a, **kwargs)
  619. for a in s.atoms(Add) if a.has(Sum)})
  620. s = expand(s)
  621. if not isinstance(s, Add):
  622. return s
  623. terms = s.args
  624. s_t = [] # Sum Terms
  625. o_t = [] # Other Terms
  626. for term in terms:
  627. sum_terms, other = sift(Mul.make_args(term),
  628. lambda i: isinstance(i, Sum), binary=True)
  629. if not sum_terms:
  630. o_t.append(term)
  631. continue
  632. other = [Mul(*other)]
  633. s_t.append(Mul(*(other + [s._eval_simplify(**kwargs) for s in sum_terms])))
  634. result = Add(sum_combine(s_t), *o_t)
  635. return result
  636. def sum_combine(s_t):
  637. """Helper function for Sum simplification
  638. Attempts to simplify a list of sums, by combining limits / sum function's
  639. returns the simplified sum
  640. """
  641. used = [False] * len(s_t)
  642. for method in range(2):
  643. for i, s_term1 in enumerate(s_t):
  644. if not used[i]:
  645. for j, s_term2 in enumerate(s_t):
  646. if not used[j] and i != j:
  647. temp = sum_add(s_term1, s_term2, method)
  648. if isinstance(temp, (Sum, Mul)):
  649. s_t[i] = temp
  650. s_term1 = s_t[i]
  651. used[j] = True
  652. result = S.Zero
  653. for i, s_term in enumerate(s_t):
  654. if not used[i]:
  655. result = Add(result, s_term)
  656. return result
  657. def factor_sum(self, limits=None, radical=False, clear=False, fraction=False, sign=True):
  658. """Return Sum with constant factors extracted.
  659. If ``limits`` is specified then ``self`` is the summand; the other
  660. keywords are passed to ``factor_terms``.
  661. Examples
  662. ========
  663. >>> from sympy import Sum
  664. >>> from sympy.abc import x, y
  665. >>> from sympy.simplify.simplify import factor_sum
  666. >>> s = Sum(x*y, (x, 1, 3))
  667. >>> factor_sum(s)
  668. y*Sum(x, (x, 1, 3))
  669. >>> factor_sum(s.function, s.limits)
  670. y*Sum(x, (x, 1, 3))
  671. """
  672. # XXX deprecate in favor of direct call to factor_terms
  673. kwargs = {"radical": radical, "clear": clear,
  674. "fraction": fraction, "sign": sign}
  675. expr = Sum(self, *limits) if limits else self
  676. return factor_terms(expr, **kwargs)
  677. def sum_add(self, other, method=0):
  678. """Helper function for Sum simplification"""
  679. #we know this is something in terms of a constant * a sum
  680. #so we temporarily put the constants inside for simplification
  681. #then simplify the result
  682. def __refactor(val):
  683. args = Mul.make_args(val)
  684. sumv = next(x for x in args if isinstance(x, Sum))
  685. constant = Mul(*[x for x in args if x != sumv])
  686. return Sum(constant * sumv.function, *sumv.limits)
  687. if isinstance(self, Mul):
  688. rself = __refactor(self)
  689. else:
  690. rself = self
  691. if isinstance(other, Mul):
  692. rother = __refactor(other)
  693. else:
  694. rother = other
  695. if type(rself) is type(rother):
  696. if method == 0:
  697. if rself.limits == rother.limits:
  698. return factor_sum(Sum(rself.function + rother.function, *rself.limits))
  699. elif method == 1:
  700. if simplify(rself.function - rother.function) == 0:
  701. if len(rself.limits) == len(rother.limits) == 1:
  702. i = rself.limits[0][0]
  703. x1 = rself.limits[0][1]
  704. y1 = rself.limits[0][2]
  705. j = rother.limits[0][0]
  706. x2 = rother.limits[0][1]
  707. y2 = rother.limits[0][2]
  708. if i == j:
  709. if x2 == y1 + 1:
  710. return factor_sum(Sum(rself.function, (i, x1, y2)))
  711. elif x1 == y2 + 1:
  712. return factor_sum(Sum(rself.function, (i, x2, y1)))
  713. return Add(self, other)
  714. def product_simplify(s, **kwargs):
  715. """Main function for Product simplification"""
  716. terms = Mul.make_args(s)
  717. p_t = [] # Product Terms
  718. o_t = [] # Other Terms
  719. deep = kwargs.get('deep', True)
  720. for term in terms:
  721. if isinstance(term, Product):
  722. if deep:
  723. p_t.append(Product(term.function.simplify(**kwargs),
  724. *term.limits))
  725. else:
  726. p_t.append(term)
  727. else:
  728. o_t.append(term)
  729. used = [False] * len(p_t)
  730. for method in range(2):
  731. for i, p_term1 in enumerate(p_t):
  732. if not used[i]:
  733. for j, p_term2 in enumerate(p_t):
  734. if not used[j] and i != j:
  735. tmp_prod = product_mul(p_term1, p_term2, method)
  736. if isinstance(tmp_prod, Product):
  737. p_t[i] = tmp_prod
  738. used[j] = True
  739. result = Mul(*o_t)
  740. for i, p_term in enumerate(p_t):
  741. if not used[i]:
  742. result = Mul(result, p_term)
  743. return result
  744. def product_mul(self, other, method=0):
  745. """Helper function for Product simplification"""
  746. if type(self) is type(other):
  747. if method == 0:
  748. if self.limits == other.limits:
  749. return Product(self.function * other.function, *self.limits)
  750. elif method == 1:
  751. if simplify(self.function - other.function) == 0:
  752. if len(self.limits) == len(other.limits) == 1:
  753. i = self.limits[0][0]
  754. x1 = self.limits[0][1]
  755. y1 = self.limits[0][2]
  756. j = other.limits[0][0]
  757. x2 = other.limits[0][1]
  758. y2 = other.limits[0][2]
  759. if i == j:
  760. if x2 == y1 + 1:
  761. return Product(self.function, (i, x1, y2))
  762. elif x1 == y2 + 1:
  763. return Product(self.function, (i, x2, y1))
  764. return Mul(self, other)
  765. def _nthroot_solve(p, n, prec):
  766. """
  767. helper function for ``nthroot``
  768. It denests ``p**Rational(1, n)`` using its minimal polynomial
  769. """
  770. from sympy.solvers import solve
  771. while n % 2 == 0:
  772. p = sqrtdenest(sqrt(p))
  773. n = n // 2
  774. if n == 1:
  775. return p
  776. pn = p**Rational(1, n)
  777. x = Symbol('x')
  778. f = _minimal_polynomial_sq(p, n, x)
  779. if f is None:
  780. return None
  781. sols = solve(f, x)
  782. for sol in sols:
  783. if abs(sol - pn).n() < 1./10**prec:
  784. sol = sqrtdenest(sol)
  785. if _mexpand(sol**n) == p:
  786. return sol
  787. def logcombine(expr, force=False):
  788. """
  789. Takes logarithms and combines them using the following rules:
  790. - log(x) + log(y) == log(x*y) if both are positive
  791. - a*log(x) == log(x**a) if x is positive and a is real
  792. If ``force`` is ``True`` then the assumptions above will be assumed to hold if
  793. there is no assumption already in place on a quantity. For example, if
  794. ``a`` is imaginary or the argument negative, force will not perform a
  795. combination but if ``a`` is a symbol with no assumptions the change will
  796. take place.
  797. Examples
  798. ========
  799. >>> from sympy import Symbol, symbols, log, logcombine, I
  800. >>> from sympy.abc import a, x, y, z
  801. >>> logcombine(a*log(x) + log(y) - log(z))
  802. a*log(x) + log(y) - log(z)
  803. >>> logcombine(a*log(x) + log(y) - log(z), force=True)
  804. log(x**a*y/z)
  805. >>> x,y,z = symbols('x,y,z', positive=True)
  806. >>> a = Symbol('a', real=True)
  807. >>> logcombine(a*log(x) + log(y) - log(z))
  808. log(x**a*y/z)
  809. The transformation is limited to factors and/or terms that
  810. contain logs, so the result depends on the initial state of
  811. expansion:
  812. >>> eq = (2 + 3*I)*log(x)
  813. >>> logcombine(eq, force=True) == eq
  814. True
  815. >>> logcombine(eq.expand(), force=True)
  816. log(x**2) + I*log(x**3)
  817. See Also
  818. ========
  819. posify: replace all symbols with symbols having positive assumptions
  820. sympy.core.function.expand_log: expand the logarithms of products
  821. and powers; the opposite of logcombine
  822. """
  823. def f(rv):
  824. if not (rv.is_Add or rv.is_Mul):
  825. return rv
  826. def gooda(a):
  827. # bool to tell whether the leading ``a`` in ``a*log(x)``
  828. # could appear as log(x**a)
  829. return (a is not S.NegativeOne and # -1 *could* go, but we disallow
  830. (a.is_extended_real or force and a.is_extended_real is not False))
  831. def goodlog(l):
  832. # bool to tell whether log ``l``'s argument can combine with others
  833. a = l.args[0]
  834. return a.is_positive or force and a.is_nonpositive is not False
  835. other = []
  836. logs = []
  837. log1 = defaultdict(list)
  838. for a in Add.make_args(rv):
  839. if isinstance(a, log) and goodlog(a):
  840. log1[()].append(([], a))
  841. elif not a.is_Mul:
  842. other.append(a)
  843. else:
  844. ot = []
  845. co = []
  846. lo = []
  847. for ai in a.args:
  848. if ai.is_Rational and ai < 0:
  849. ot.append(S.NegativeOne)
  850. co.append(-ai)
  851. elif isinstance(ai, log) and goodlog(ai):
  852. lo.append(ai)
  853. elif gooda(ai):
  854. co.append(ai)
  855. else:
  856. ot.append(ai)
  857. if len(lo) > 1:
  858. logs.append((ot, co, lo))
  859. elif lo:
  860. log1[tuple(ot)].append((co, lo[0]))
  861. else:
  862. other.append(a)
  863. # if there is only one log in other, put it with the
  864. # good logs
  865. if len(other) == 1 and isinstance(other[0], log):
  866. log1[()].append(([], other.pop()))
  867. # if there is only one log at each coefficient and none have
  868. # an exponent to place inside the log then there is nothing to do
  869. if not logs and all(len(log1[k]) == 1 and log1[k][0] == [] for k in log1):
  870. return rv
  871. # collapse multi-logs as far as possible in a canonical way
  872. # TODO: see if x*log(a)+x*log(a)*log(b) -> x*log(a)*(1+log(b))?
  873. # -- in this case, it's unambiguous, but if it were were a log(c) in
  874. # each term then it's arbitrary whether they are grouped by log(a) or
  875. # by log(c). So for now, just leave this alone; it's probably better to
  876. # let the user decide
  877. for o, e, l in logs:
  878. l = list(ordered(l))
  879. e = log(l.pop(0).args[0]**Mul(*e))
  880. while l:
  881. li = l.pop(0)
  882. e = log(li.args[0]**e)
  883. c, l = Mul(*o), e
  884. if isinstance(l, log): # it should be, but check to be sure
  885. log1[(c,)].append(([], l))
  886. else:
  887. other.append(c*l)
  888. # logs that have the same coefficient can multiply
  889. for k in list(log1.keys()):
  890. log1[Mul(*k)] = log(logcombine(Mul(*[
  891. l.args[0]**Mul(*c) for c, l in log1.pop(k)]),
  892. force=force), evaluate=False)
  893. # logs that have oppositely signed coefficients can divide
  894. for k in ordered(list(log1.keys())):
  895. if k not in log1: # already popped as -k
  896. continue
  897. if -k in log1:
  898. # figure out which has the minus sign; the one with
  899. # more op counts should be the one
  900. num, den = k, -k
  901. if num.count_ops() > den.count_ops():
  902. num, den = den, num
  903. other.append(
  904. num*log(log1.pop(num).args[0]/log1.pop(den).args[0],
  905. evaluate=False))
  906. else:
  907. other.append(k*log1.pop(k))
  908. return Add(*other)
  909. return _bottom_up(expr, f)
  910. def inversecombine(expr):
  911. """Simplify the composition of a function and its inverse.
  912. Explanation
  913. ===========
  914. No attention is paid to whether the inverse is a left inverse or a
  915. right inverse; thus, the result will in general not be equivalent
  916. to the original expression.
  917. Examples
  918. ========
  919. >>> from sympy.simplify.simplify import inversecombine
  920. >>> from sympy import asin, sin, log, exp
  921. >>> from sympy.abc import x
  922. >>> inversecombine(asin(sin(x)))
  923. x
  924. >>> inversecombine(2*log(exp(3*x)))
  925. 6*x
  926. """
  927. def f(rv):
  928. if isinstance(rv, log):
  929. if isinstance(rv.args[0], exp) or (rv.args[0].is_Pow and rv.args[0].base == S.Exp1):
  930. rv = rv.args[0].exp
  931. elif rv.is_Function and hasattr(rv, "inverse"):
  932. if (len(rv.args) == 1 and len(rv.args[0].args) == 1 and
  933. isinstance(rv.args[0], rv.inverse(argindex=1))):
  934. rv = rv.args[0].args[0]
  935. if rv.is_Pow and rv.base == S.Exp1:
  936. if isinstance(rv.exp, log):
  937. rv = rv.exp.args[0]
  938. return rv
  939. return _bottom_up(expr, f)
  940. def kroneckersimp(expr):
  941. """
  942. Simplify expressions with KroneckerDelta.
  943. The only simplification currently attempted is to identify multiplicative cancellation:
  944. Examples
  945. ========
  946. >>> from sympy import KroneckerDelta, kroneckersimp
  947. >>> from sympy.abc import i
  948. >>> kroneckersimp(1 + KroneckerDelta(0, i) * KroneckerDelta(1, i))
  949. 1
  950. """
  951. def args_cancel(args1, args2):
  952. for i1 in range(2):
  953. for i2 in range(2):
  954. a1 = args1[i1]
  955. a2 = args2[i2]
  956. a3 = args1[(i1 + 1) % 2]
  957. a4 = args2[(i2 + 1) % 2]
  958. if Eq(a1, a2) is S.true and Eq(a3, a4) is S.false:
  959. return True
  960. return False
  961. def cancel_kronecker_mul(m):
  962. args = m.args
  963. deltas = [a for a in args if isinstance(a, KroneckerDelta)]
  964. for delta1, delta2 in subsets(deltas, 2):
  965. args1 = delta1.args
  966. args2 = delta2.args
  967. if args_cancel(args1, args2):
  968. return S.Zero * m # In case of oo etc
  969. return m
  970. if not expr.has(KroneckerDelta):
  971. return expr
  972. if expr.has(Piecewise):
  973. expr = expr.rewrite(KroneckerDelta)
  974. newexpr = expr
  975. expr = None
  976. while newexpr != expr:
  977. expr = newexpr
  978. newexpr = expr.replace(lambda e: isinstance(e, Mul), cancel_kronecker_mul)
  979. return expr
  980. def besselsimp(expr):
  981. """
  982. Simplify bessel-type functions.
  983. Explanation
  984. ===========
  985. This routine tries to simplify bessel-type functions. Currently it only
  986. works on the Bessel J and I functions, however. It works by looking at all
  987. such functions in turn, and eliminating factors of "I" and "-1" (actually
  988. their polar equivalents) in front of the argument. Then, functions of
  989. half-integer order are rewritten using strigonometric functions and
  990. functions of integer order (> 1) are rewritten using functions
  991. of low order. Finally, if the expression was changed, compute
  992. factorization of the result with factor().
  993. >>> from sympy import besselj, besseli, besselsimp, polar_lift, I, S
  994. >>> from sympy.abc import z, nu
  995. >>> besselsimp(besselj(nu, z*polar_lift(-1)))
  996. exp(I*pi*nu)*besselj(nu, z)
  997. >>> besselsimp(besseli(nu, z*polar_lift(-I)))
  998. exp(-I*pi*nu/2)*besselj(nu, z)
  999. >>> besselsimp(besseli(S(-1)/2, z))
  1000. sqrt(2)*cosh(z)/(sqrt(pi)*sqrt(z))
  1001. >>> besselsimp(z*besseli(0, z) + z*(besseli(2, z))/2 + besseli(1, z))
  1002. 3*z*besseli(0, z)/2
  1003. """
  1004. # TODO
  1005. # - better algorithm?
  1006. # - simplify (cos(pi*b)*besselj(b,z) - besselj(-b,z))/sin(pi*b) ...
  1007. # - use contiguity relations?
  1008. def replacer(fro, to, factors):
  1009. factors = set(factors)
  1010. def repl(nu, z):
  1011. if factors.intersection(Mul.make_args(z)):
  1012. return to(nu, z)
  1013. return fro(nu, z)
  1014. return repl
  1015. def torewrite(fro, to):
  1016. def tofunc(nu, z):
  1017. return fro(nu, z).rewrite(to)
  1018. return tofunc
  1019. def tominus(fro):
  1020. def tofunc(nu, z):
  1021. return exp(I*pi*nu)*fro(nu, exp_polar(-I*pi)*z)
  1022. return tofunc
  1023. orig_expr = expr
  1024. ifactors = [I, exp_polar(I*pi/2), exp_polar(-I*pi/2)]
  1025. expr = expr.replace(
  1026. besselj, replacer(besselj,
  1027. torewrite(besselj, besseli), ifactors))
  1028. expr = expr.replace(
  1029. besseli, replacer(besseli,
  1030. torewrite(besseli, besselj), ifactors))
  1031. minusfactors = [-1, exp_polar(I*pi)]
  1032. expr = expr.replace(
  1033. besselj, replacer(besselj, tominus(besselj), minusfactors))
  1034. expr = expr.replace(
  1035. besseli, replacer(besseli, tominus(besseli), minusfactors))
  1036. z0 = Dummy('z')
  1037. def expander(fro):
  1038. def repl(nu, z):
  1039. if (nu % 1) == S.Half:
  1040. return simplify(trigsimp(unpolarify(
  1041. fro(nu, z0).rewrite(besselj).rewrite(jn).expand(
  1042. func=True)).subs(z0, z)))
  1043. elif nu.is_Integer and nu > 1:
  1044. return fro(nu, z).expand(func=True)
  1045. return fro(nu, z)
  1046. return repl
  1047. expr = expr.replace(besselj, expander(besselj))
  1048. expr = expr.replace(bessely, expander(bessely))
  1049. expr = expr.replace(besseli, expander(besseli))
  1050. expr = expr.replace(besselk, expander(besselk))
  1051. def _bessel_simp_recursion(expr):
  1052. def _use_recursion(bessel, expr):
  1053. while True:
  1054. bessels = expr.find(lambda x: isinstance(x, bessel))
  1055. try:
  1056. for ba in sorted(bessels, key=lambda x: re(x.args[0])):
  1057. a, x = ba.args
  1058. bap1 = bessel(a+1, x)
  1059. bap2 = bessel(a+2, x)
  1060. if expr.has(bap1) and expr.has(bap2):
  1061. expr = expr.subs(ba, 2*(a+1)/x*bap1 - bap2)
  1062. break
  1063. else:
  1064. return expr
  1065. except (ValueError, TypeError):
  1066. return expr
  1067. if expr.has(besselj):
  1068. expr = _use_recursion(besselj, expr)
  1069. if expr.has(bessely):
  1070. expr = _use_recursion(bessely, expr)
  1071. return expr
  1072. expr = _bessel_simp_recursion(expr)
  1073. if expr != orig_expr:
  1074. expr = expr.factor()
  1075. return expr
  1076. def nthroot(expr, n, max_len=4, prec=15):
  1077. """
  1078. Compute a real nth-root of a sum of surds.
  1079. Parameters
  1080. ==========
  1081. expr : sum of surds
  1082. n : integer
  1083. max_len : maximum number of surds passed as constants to ``nsimplify``
  1084. Algorithm
  1085. =========
  1086. First ``nsimplify`` is used to get a candidate root; if it is not a
  1087. root the minimal polynomial is computed; the answer is one of its
  1088. roots.
  1089. Examples
  1090. ========
  1091. >>> from sympy.simplify.simplify import nthroot
  1092. >>> from sympy import sqrt
  1093. >>> nthroot(90 + 34*sqrt(7), 3)
  1094. sqrt(7) + 3
  1095. """
  1096. expr = sympify(expr)
  1097. n = sympify(n)
  1098. p = expr**Rational(1, n)
  1099. if not n.is_integer:
  1100. return p
  1101. if not _is_sum_surds(expr):
  1102. return p
  1103. surds = []
  1104. coeff_muls = [x.as_coeff_Mul() for x in expr.args]
  1105. for x, y in coeff_muls:
  1106. if not x.is_rational:
  1107. return p
  1108. if y is S.One:
  1109. continue
  1110. if not (y.is_Pow and y.exp == S.Half and y.base.is_integer):
  1111. return p
  1112. surds.append(y)
  1113. surds.sort()
  1114. surds = surds[:max_len]
  1115. if expr < 0 and n % 2 == 1:
  1116. p = (-expr)**Rational(1, n)
  1117. a = nsimplify(p, constants=surds)
  1118. res = a if _mexpand(a**n) == _mexpand(-expr) else p
  1119. return -res
  1120. a = nsimplify(p, constants=surds)
  1121. if _mexpand(a) is not _mexpand(p) and _mexpand(a**n) == _mexpand(expr):
  1122. return _mexpand(a)
  1123. expr = _nthroot_solve(expr, n, prec)
  1124. if expr is None:
  1125. return p
  1126. return expr
  1127. def nsimplify(expr, constants=(), tolerance=None, full=False, rational=None,
  1128. rational_conversion='base10'):
  1129. """
  1130. Find a simple representation for a number or, if there are free symbols or
  1131. if ``rational=True``, then replace Floats with their Rational equivalents. If
  1132. no change is made and rational is not False then Floats will at least be
  1133. converted to Rationals.
  1134. Explanation
  1135. ===========
  1136. For numerical expressions, a simple formula that numerically matches the
  1137. given numerical expression is sought (and the input should be possible
  1138. to evalf to a precision of at least 30 digits).
  1139. Optionally, a list of (rationally independent) constants to
  1140. include in the formula may be given.
  1141. A lower tolerance may be set to find less exact matches. If no tolerance
  1142. is given then the least precise value will set the tolerance (e.g. Floats
  1143. default to 15 digits of precision, so would be tolerance=10**-15).
  1144. With ``full=True``, a more extensive search is performed
  1145. (this is useful to find simpler numbers when the tolerance
  1146. is set low).
  1147. When converting to rational, if rational_conversion='base10' (the default), then
  1148. convert floats to rationals using their base-10 (string) representation.
  1149. When rational_conversion='exact' it uses the exact, base-2 representation.
  1150. Examples
  1151. ========
  1152. >>> from sympy import nsimplify, sqrt, GoldenRatio, exp, I, pi
  1153. >>> nsimplify(4/(1+sqrt(5)), [GoldenRatio])
  1154. -2 + 2*GoldenRatio
  1155. >>> nsimplify((1/(exp(3*pi*I/5)+1)))
  1156. 1/2 - I*sqrt(sqrt(5)/10 + 1/4)
  1157. >>> nsimplify(I**I, [pi])
  1158. exp(-pi/2)
  1159. >>> nsimplify(pi, tolerance=0.01)
  1160. 22/7
  1161. >>> nsimplify(0.333333333333333, rational=True, rational_conversion='exact')
  1162. 6004799503160655/18014398509481984
  1163. >>> nsimplify(0.333333333333333, rational=True)
  1164. 1/3
  1165. See Also
  1166. ========
  1167. sympy.core.function.nfloat
  1168. """
  1169. try:
  1170. return sympify(as_int(expr))
  1171. except (TypeError, ValueError):
  1172. pass
  1173. expr = sympify(expr).xreplace({
  1174. Float('inf'): S.Infinity,
  1175. Float('-inf'): S.NegativeInfinity,
  1176. })
  1177. if expr is S.Infinity or expr is S.NegativeInfinity:
  1178. return expr
  1179. if rational or expr.free_symbols:
  1180. return _real_to_rational(expr, tolerance, rational_conversion)
  1181. # SymPy's default tolerance for Rationals is 15; other numbers may have
  1182. # lower tolerances set, so use them to pick the largest tolerance if None
  1183. # was given
  1184. if tolerance is None:
  1185. tolerance = 10**-min([15] +
  1186. [mpmath.libmp.libmpf.prec_to_dps(n._prec)
  1187. for n in expr.atoms(Float)])
  1188. # XXX should prec be set independent of tolerance or should it be computed
  1189. # from tolerance?
  1190. prec = 30
  1191. bprec = int(prec*3.33)
  1192. constants_dict = {}
  1193. for constant in constants:
  1194. constant = sympify(constant)
  1195. v = constant.evalf(prec)
  1196. if not v.is_Float:
  1197. raise ValueError("constants must be real-valued")
  1198. constants_dict[str(constant)] = v._to_mpmath(bprec)
  1199. exprval = expr.evalf(prec, chop=True)
  1200. re, im = exprval.as_real_imag()
  1201. # safety check to make sure that this evaluated to a number
  1202. if not (re.is_Number and im.is_Number):
  1203. return expr
  1204. def nsimplify_real(x):
  1205. orig = mpmath.mp.dps
  1206. xv = x._to_mpmath(bprec)
  1207. try:
  1208. # We'll be happy with low precision if a simple fraction
  1209. if not (tolerance or full):
  1210. mpmath.mp.dps = 15
  1211. rat = mpmath.pslq([xv, 1])
  1212. if rat is not None:
  1213. return Rational(-int(rat[1]), int(rat[0]))
  1214. mpmath.mp.dps = prec
  1215. newexpr = mpmath.identify(xv, constants=constants_dict,
  1216. tol=tolerance, full=full)
  1217. if not newexpr:
  1218. raise ValueError
  1219. if full:
  1220. newexpr = newexpr[0]
  1221. expr = sympify(newexpr)
  1222. if x and not expr: # don't let x become 0
  1223. raise ValueError
  1224. if expr.is_finite is False and xv not in [mpmath.inf, mpmath.ninf]:
  1225. raise ValueError
  1226. return expr
  1227. finally:
  1228. # even though there are returns above, this is executed
  1229. # before leaving
  1230. mpmath.mp.dps = orig
  1231. try:
  1232. if re:
  1233. re = nsimplify_real(re)
  1234. if im:
  1235. im = nsimplify_real(im)
  1236. except ValueError:
  1237. if rational is None:
  1238. return _real_to_rational(expr, rational_conversion=rational_conversion)
  1239. return expr
  1240. rv = re + im*S.ImaginaryUnit
  1241. # if there was a change or rational is explicitly not wanted
  1242. # return the value, else return the Rational representation
  1243. if rv != expr or rational is False:
  1244. return rv
  1245. return _real_to_rational(expr, rational_conversion=rational_conversion)
  1246. def _real_to_rational(expr, tolerance=None, rational_conversion='base10'):
  1247. """
  1248. Replace all reals in expr with rationals.
  1249. Examples
  1250. ========
  1251. >>> from sympy.simplify.simplify import _real_to_rational
  1252. >>> from sympy.abc import x
  1253. >>> _real_to_rational(.76 + .1*x**.5)
  1254. sqrt(x)/10 + 19/25
  1255. If rational_conversion='base10', this uses the base-10 string. If
  1256. rational_conversion='exact', the exact, base-2 representation is used.
  1257. >>> _real_to_rational(0.333333333333333, rational_conversion='exact')
  1258. 6004799503160655/18014398509481984
  1259. >>> _real_to_rational(0.333333333333333)
  1260. 1/3
  1261. """
  1262. expr = _sympify(expr)
  1263. inf = Float('inf')
  1264. p = expr
  1265. reps = {}
  1266. reduce_num = None
  1267. if tolerance is not None and tolerance < 1:
  1268. reduce_num = ceiling(1/tolerance)
  1269. for fl in p.atoms(Float):
  1270. key = fl
  1271. if reduce_num is not None:
  1272. r = Rational(fl).limit_denominator(reduce_num)
  1273. elif (tolerance is not None and tolerance >= 1 and
  1274. fl.is_Integer is False):
  1275. r = Rational(tolerance*round(fl/tolerance)
  1276. ).limit_denominator(int(tolerance))
  1277. else:
  1278. if rational_conversion == 'exact':
  1279. r = Rational(fl)
  1280. reps[key] = r
  1281. continue
  1282. elif rational_conversion != 'base10':
  1283. raise ValueError("rational_conversion must be 'base10' or 'exact'")
  1284. r = nsimplify(fl, rational=False)
  1285. # e.g. log(3).n() -> log(3) instead of a Rational
  1286. if fl and not r:
  1287. r = Rational(fl)
  1288. elif not r.is_Rational:
  1289. if fl in (inf, -inf):
  1290. r = S.ComplexInfinity
  1291. elif fl < 0:
  1292. fl = -fl
  1293. d = Pow(10, int(mpmath.log(fl)/mpmath.log(10)))
  1294. r = -Rational(str(fl/d))*d
  1295. elif fl > 0:
  1296. d = Pow(10, int(mpmath.log(fl)/mpmath.log(10)))
  1297. r = Rational(str(fl/d))*d
  1298. else:
  1299. r = S.Zero
  1300. reps[key] = r
  1301. return p.subs(reps, simultaneous=True)
  1302. def clear_coefficients(expr, rhs=S.Zero):
  1303. """Return `p, r` where `p` is the expression obtained when Rational
  1304. additive and multiplicative coefficients of `expr` have been stripped
  1305. away in a naive fashion (i.e. without simplification). The operations
  1306. needed to remove the coefficients will be applied to `rhs` and returned
  1307. as `r`.
  1308. Examples
  1309. ========
  1310. >>> from sympy.simplify.simplify import clear_coefficients
  1311. >>> from sympy.abc import x, y
  1312. >>> from sympy import Dummy
  1313. >>> expr = 4*y*(6*x + 3)
  1314. >>> clear_coefficients(expr - 2)
  1315. (y*(2*x + 1), 1/6)
  1316. When solving 2 or more expressions like `expr = a`,
  1317. `expr = b`, etc..., it is advantageous to provide a Dummy symbol
  1318. for `rhs` and simply replace it with `a`, `b`, etc... in `r`.
  1319. >>> rhs = Dummy('rhs')
  1320. >>> clear_coefficients(expr, rhs)
  1321. (y*(2*x + 1), _rhs/12)
  1322. >>> _[1].subs(rhs, 2)
  1323. 1/6
  1324. """
  1325. was = None
  1326. free = expr.free_symbols
  1327. if expr.is_Rational:
  1328. return (S.Zero, rhs - expr)
  1329. while expr and was != expr:
  1330. was = expr
  1331. m, expr = (
  1332. expr.as_content_primitive()
  1333. if free else
  1334. factor_terms(expr).as_coeff_Mul(rational=True))
  1335. rhs /= m
  1336. c, expr = expr.as_coeff_Add(rational=True)
  1337. rhs -= c
  1338. expr = signsimp(expr, evaluate = False)
  1339. if expr.could_extract_minus_sign():
  1340. expr = -expr
  1341. rhs = -rhs
  1342. return expr, rhs
  1343. def nc_simplify(expr, deep=True):
  1344. '''
  1345. Simplify a non-commutative expression composed of multiplication
  1346. and raising to a power by grouping repeated subterms into one power.
  1347. Priority is given to simplifications that give the fewest number
  1348. of arguments in the end (for example, in a*b*a*b*c*a*b*c simplifying
  1349. to (a*b)**2*c*a*b*c gives 5 arguments while a*b*(a*b*c)**2 has 3).
  1350. If ``expr`` is a sum of such terms, the sum of the simplified terms
  1351. is returned.
  1352. Keyword argument ``deep`` controls whether or not subexpressions
  1353. nested deeper inside the main expression are simplified. See examples
  1354. below. Setting `deep` to `False` can save time on nested expressions
  1355. that do not need simplifying on all levels.
  1356. Examples
  1357. ========
  1358. >>> from sympy import symbols
  1359. >>> from sympy.simplify.simplify import nc_simplify
  1360. >>> a, b, c = symbols("a b c", commutative=False)
  1361. >>> nc_simplify(a*b*a*b*c*a*b*c)
  1362. a*b*(a*b*c)**2
  1363. >>> expr = a**2*b*a**4*b*a**4
  1364. >>> nc_simplify(expr)
  1365. a**2*(b*a**4)**2
  1366. >>> nc_simplify(a*b*a*b*c**2*(a*b)**2*c**2)
  1367. ((a*b)**2*c**2)**2
  1368. >>> nc_simplify(a*b*a*b + 2*a*c*a**2*c*a**2*c*a)
  1369. (a*b)**2 + 2*(a*c*a)**3
  1370. >>> nc_simplify(b**-1*a**-1*(a*b)**2)
  1371. a*b
  1372. >>> nc_simplify(a**-1*b**-1*c*a)
  1373. (b*a)**(-1)*c*a
  1374. >>> expr = (a*b*a*b)**2*a*c*a*c
  1375. >>> nc_simplify(expr)
  1376. (a*b)**4*(a*c)**2
  1377. >>> nc_simplify(expr, deep=False)
  1378. (a*b*a*b)**2*(a*c)**2
  1379. '''
  1380. if isinstance(expr, MatrixExpr):
  1381. expr = expr.doit(inv_expand=False)
  1382. _Add, _Mul, _Pow, _Symbol = MatAdd, MatMul, MatPow, MatrixSymbol
  1383. else:
  1384. _Add, _Mul, _Pow, _Symbol = Add, Mul, Pow, Symbol
  1385. # =========== Auxiliary functions ========================
  1386. def _overlaps(args):
  1387. # Calculate a list of lists m such that m[i][j] contains the lengths
  1388. # of all possible overlaps between args[:i+1] and args[i+1+j:].
  1389. # An overlap is a suffix of the prefix that matches a prefix
  1390. # of the suffix.
  1391. # For example, let expr=c*a*b*a*b*a*b*a*b. Then m[3][0] contains
  1392. # the lengths of overlaps of c*a*b*a*b with a*b*a*b. The overlaps
  1393. # are a*b*a*b, a*b and the empty word so that m[3][0]=[4,2,0].
  1394. # All overlaps rather than only the longest one are recorded
  1395. # because this information helps calculate other overlap lengths.
  1396. m = [[([1, 0] if a == args[0] else [0]) for a in args[1:]]]
  1397. for i in range(1, len(args)):
  1398. overlaps = []
  1399. j = 0
  1400. for j in range(len(args) - i - 1):
  1401. overlap = []
  1402. for v in m[i-1][j+1]:
  1403. if j + i + 1 + v < len(args) and args[i] == args[j+i+1+v]:
  1404. overlap.append(v + 1)
  1405. overlap += [0]
  1406. overlaps.append(overlap)
  1407. m.append(overlaps)
  1408. return m
  1409. def _reduce_inverses(_args):
  1410. # replace consecutive negative powers by an inverse
  1411. # of a product of positive powers, e.g. a**-1*b**-1*c
  1412. # will simplify to (a*b)**-1*c;
  1413. # return that new args list and the number of negative
  1414. # powers in it (inv_tot)
  1415. inv_tot = 0 # total number of inverses
  1416. inverses = []
  1417. args = []
  1418. for arg in _args:
  1419. if isinstance(arg, _Pow) and arg.args[1].is_extended_negative:
  1420. inverses = [arg**-1] + inverses
  1421. inv_tot += 1
  1422. else:
  1423. if len(inverses) == 1:
  1424. args.append(inverses[0]**-1)
  1425. elif len(inverses) > 1:
  1426. args.append(_Pow(_Mul(*inverses), -1))
  1427. inv_tot -= len(inverses) - 1
  1428. inverses = []
  1429. args.append(arg)
  1430. if inverses:
  1431. args.append(_Pow(_Mul(*inverses), -1))
  1432. inv_tot -= len(inverses) - 1
  1433. return inv_tot, tuple(args)
  1434. def get_score(s):
  1435. # compute the number of arguments of s
  1436. # (including in nested expressions) overall
  1437. # but ignore exponents
  1438. if isinstance(s, _Pow):
  1439. return get_score(s.args[0])
  1440. elif isinstance(s, (_Add, _Mul)):
  1441. return sum([get_score(a) for a in s.args])
  1442. return 1
  1443. def compare(s, alt_s):
  1444. # compare two possible simplifications and return a
  1445. # "better" one
  1446. if s != alt_s and get_score(alt_s) < get_score(s):
  1447. return alt_s
  1448. return s
  1449. # ========================================================
  1450. if not isinstance(expr, (_Add, _Mul, _Pow)) or expr.is_commutative:
  1451. return expr
  1452. args = expr.args[:]
  1453. if isinstance(expr, _Pow):
  1454. if deep:
  1455. return _Pow(nc_simplify(args[0]), args[1]).doit()
  1456. else:
  1457. return expr
  1458. elif isinstance(expr, _Add):
  1459. return _Add(*[nc_simplify(a, deep=deep) for a in args]).doit()
  1460. else:
  1461. # get the non-commutative part
  1462. c_args, args = expr.args_cnc()
  1463. com_coeff = Mul(*c_args)
  1464. if com_coeff != 1:
  1465. return com_coeff*nc_simplify(expr/com_coeff, deep=deep)
  1466. inv_tot, args = _reduce_inverses(args)
  1467. # if most arguments are negative, work with the inverse
  1468. # of the expression, e.g. a**-1*b*a**-1*c**-1 will become
  1469. # (c*a*b**-1*a)**-1 at the end so can work with c*a*b**-1*a
  1470. invert = False
  1471. if inv_tot > len(args)/2:
  1472. invert = True
  1473. args = [a**-1 for a in args[::-1]]
  1474. if deep:
  1475. args = tuple(nc_simplify(a) for a in args)
  1476. m = _overlaps(args)
  1477. # simps will be {subterm: end} where `end` is the ending
  1478. # index of a sequence of repetitions of subterm;
  1479. # this is for not wasting time with subterms that are part
  1480. # of longer, already considered sequences
  1481. simps = {}
  1482. post = 1
  1483. pre = 1
  1484. # the simplification coefficient is the number of
  1485. # arguments by which contracting a given sequence
  1486. # would reduce the word; e.g. in a*b*a*b*c*a*b*c,
  1487. # contracting a*b*a*b to (a*b)**2 removes 3 arguments
  1488. # while a*b*c*a*b*c to (a*b*c)**2 removes 6. It's
  1489. # better to contract the latter so simplification
  1490. # with a maximum simplification coefficient will be chosen
  1491. max_simp_coeff = 0
  1492. simp = None # information about future simplification
  1493. for i in range(1, len(args)):
  1494. simp_coeff = 0
  1495. l = 0 # length of a subterm
  1496. p = 0 # the power of a subterm
  1497. if i < len(args) - 1:
  1498. rep = m[i][0]
  1499. start = i # starting index of the repeated sequence
  1500. end = i+1 # ending index of the repeated sequence
  1501. if i == len(args)-1 or rep == [0]:
  1502. # no subterm is repeated at this stage, at least as
  1503. # far as the arguments are concerned - there may be
  1504. # a repetition if powers are taken into account
  1505. if (isinstance(args[i], _Pow) and
  1506. not isinstance(args[i].args[0], _Symbol)):
  1507. subterm = args[i].args[0].args
  1508. l = len(subterm)
  1509. if args[i-l:i] == subterm:
  1510. # e.g. a*b in a*b*(a*b)**2 is not repeated
  1511. # in args (= [a, b, (a*b)**2]) but it
  1512. # can be matched here
  1513. p += 1
  1514. start -= l
  1515. if args[i+1:i+1+l] == subterm:
  1516. # e.g. a*b in (a*b)**2*a*b
  1517. p += 1
  1518. end += l
  1519. if p:
  1520. p += args[i].args[1]
  1521. else:
  1522. continue
  1523. else:
  1524. l = rep[0] # length of the longest repeated subterm at this point
  1525. start -= l - 1
  1526. subterm = args[start:end]
  1527. p = 2
  1528. end += l
  1529. if subterm in simps and simps[subterm] >= start:
  1530. # the subterm is part of a sequence that
  1531. # has already been considered
  1532. continue
  1533. # count how many times it's repeated
  1534. while end < len(args):
  1535. if l in m[end-1][0]:
  1536. p += 1
  1537. end += l
  1538. elif isinstance(args[end], _Pow) and args[end].args[0].args == subterm:
  1539. # for cases like a*b*a*b*(a*b)**2*a*b
  1540. p += args[end].args[1]
  1541. end += 1
  1542. else:
  1543. break
  1544. # see if another match can be made, e.g.
  1545. # for b*a**2 in b*a**2*b*a**3 or a*b in
  1546. # a**2*b*a*b
  1547. pre_exp = 0
  1548. pre_arg = 1
  1549. if start - l >= 0 and args[start-l+1:start] == subterm[1:]:
  1550. if isinstance(subterm[0], _Pow):
  1551. pre_arg = subterm[0].args[0]
  1552. exp = subterm[0].args[1]
  1553. else:
  1554. pre_arg = subterm[0]
  1555. exp = 1
  1556. if isinstance(args[start-l], _Pow) and args[start-l].args[0] == pre_arg:
  1557. pre_exp = args[start-l].args[1] - exp
  1558. start -= l
  1559. p += 1
  1560. elif args[start-l] == pre_arg:
  1561. pre_exp = 1 - exp
  1562. start -= l
  1563. p += 1
  1564. post_exp = 0
  1565. post_arg = 1
  1566. if end + l - 1 < len(args) and args[end:end+l-1] == subterm[:-1]:
  1567. if isinstance(subterm[-1], _Pow):
  1568. post_arg = subterm[-1].args[0]
  1569. exp = subterm[-1].args[1]
  1570. else:
  1571. post_arg = subterm[-1]
  1572. exp = 1
  1573. if isinstance(args[end+l-1], _Pow) and args[end+l-1].args[0] == post_arg:
  1574. post_exp = args[end+l-1].args[1] - exp
  1575. end += l
  1576. p += 1
  1577. elif args[end+l-1] == post_arg:
  1578. post_exp = 1 - exp
  1579. end += l
  1580. p += 1
  1581. # Consider a*b*a**2*b*a**2*b*a:
  1582. # b*a**2 is explicitly repeated, but note
  1583. # that in this case a*b*a is also repeated
  1584. # so there are two possible simplifications:
  1585. # a*(b*a**2)**3*a**-1 or (a*b*a)**3
  1586. # The latter is obviously simpler.
  1587. # But in a*b*a**2*b**2*a**2 the simplifications are
  1588. # a*(b*a**2)**2 and (a*b*a)**3*a in which case
  1589. # it's better to stick with the shorter subterm
  1590. if post_exp and exp % 2 == 0 and start > 0:
  1591. exp = exp/2
  1592. _pre_exp = 1
  1593. _post_exp = 1
  1594. if isinstance(args[start-1], _Pow) and args[start-1].args[0] == post_arg:
  1595. _post_exp = post_exp + exp
  1596. _pre_exp = args[start-1].args[1] - exp
  1597. elif args[start-1] == post_arg:
  1598. _post_exp = post_exp + exp
  1599. _pre_exp = 1 - exp
  1600. if _pre_exp == 0 or _post_exp == 0:
  1601. if not pre_exp:
  1602. start -= 1
  1603. post_exp = _post_exp
  1604. pre_exp = _pre_exp
  1605. pre_arg = post_arg
  1606. subterm = (post_arg**exp,) + subterm[:-1] + (post_arg**exp,)
  1607. simp_coeff += end-start
  1608. if post_exp:
  1609. simp_coeff -= 1
  1610. if pre_exp:
  1611. simp_coeff -= 1
  1612. simps[subterm] = end
  1613. if simp_coeff > max_simp_coeff:
  1614. max_simp_coeff = simp_coeff
  1615. simp = (start, _Mul(*subterm), p, end, l)
  1616. pre = pre_arg**pre_exp
  1617. post = post_arg**post_exp
  1618. if simp:
  1619. subterm = _Pow(nc_simplify(simp[1], deep=deep), simp[2])
  1620. pre = nc_simplify(_Mul(*args[:simp[0]])*pre, deep=deep)
  1621. post = post*nc_simplify(_Mul(*args[simp[3]:]), deep=deep)
  1622. simp = pre*subterm*post
  1623. if pre != 1 or post != 1:
  1624. # new simplifications may be possible but no need
  1625. # to recurse over arguments
  1626. simp = nc_simplify(simp, deep=False)
  1627. else:
  1628. simp = _Mul(*args)
  1629. if invert:
  1630. simp = _Pow(simp, -1)
  1631. # see if factor_nc(expr) is simplified better
  1632. if not isinstance(expr, MatrixExpr):
  1633. f_expr = factor_nc(expr)
  1634. if f_expr != expr:
  1635. alt_simp = nc_simplify(f_expr, deep=deep)
  1636. simp = compare(simp, alt_simp)
  1637. else:
  1638. simp = simp.doit(inv_expand=False)
  1639. return simp
  1640. def dotprodsimp(expr, withsimp=False):
  1641. """Simplification for a sum of products targeted at the kind of blowup that
  1642. occurs during summation of products. Intended to reduce expression blowup
  1643. during matrix multiplication or other similar operations. Only works with
  1644. algebraic expressions and does not recurse into non.
  1645. Parameters
  1646. ==========
  1647. withsimp : bool, optional
  1648. Specifies whether a flag should be returned along with the expression
  1649. to indicate roughly whether simplification was successful. It is used
  1650. in ``MatrixArithmetic._eval_pow_by_recursion`` to avoid attempting to
  1651. simplify an expression repetitively which does not simplify.
  1652. """
  1653. def count_ops_alg(expr):
  1654. """Optimized count algebraic operations with no recursion into
  1655. non-algebraic args that ``core.function.count_ops`` does. Also returns
  1656. whether rational functions may be present according to negative
  1657. exponents of powers or non-number fractions.
  1658. Returns
  1659. =======
  1660. ops, ratfunc : int, bool
  1661. ``ops`` is the number of algebraic operations starting at the top
  1662. level expression (not recursing into non-alg children). ``ratfunc``
  1663. specifies whether the expression MAY contain rational functions
  1664. which ``cancel`` MIGHT optimize.
  1665. """
  1666. ops = 0
  1667. args = [expr]
  1668. ratfunc = False
  1669. while args:
  1670. a = args.pop()
  1671. if not isinstance(a, Basic):
  1672. continue
  1673. if a.is_Rational:
  1674. if a is not S.One: # -1/3 = NEG + DIV
  1675. ops += bool (a.p < 0) + bool (a.q != 1)
  1676. elif a.is_Mul:
  1677. if a.could_extract_minus_sign():
  1678. ops += 1
  1679. if a.args[0] is S.NegativeOne:
  1680. a = a.as_two_terms()[1]
  1681. else:
  1682. a = -a
  1683. n, d = fraction(a)
  1684. if n.is_Integer:
  1685. ops += 1 + bool (n < 0)
  1686. args.append(d) # won't be -Mul but could be Add
  1687. elif d is not S.One:
  1688. if not d.is_Integer:
  1689. args.append(d)
  1690. ratfunc=True
  1691. ops += 1
  1692. args.append(n) # could be -Mul
  1693. else:
  1694. ops += len(a.args) - 1
  1695. args.extend(a.args)
  1696. elif a.is_Add:
  1697. laargs = len(a.args)
  1698. negs = 0
  1699. for ai in a.args:
  1700. if ai.could_extract_minus_sign():
  1701. negs += 1
  1702. ai = -ai
  1703. args.append(ai)
  1704. ops += laargs - (negs != laargs) # -x - y = NEG + SUB
  1705. elif a.is_Pow:
  1706. ops += 1
  1707. args.append(a.base)
  1708. if not ratfunc:
  1709. ratfunc = a.exp.is_negative is not False
  1710. return ops, ratfunc
  1711. def nonalg_subs_dummies(expr, dummies):
  1712. """Substitute dummy variables for non-algebraic expressions to avoid
  1713. evaluation of non-algebraic terms that ``polys.polytools.cancel`` does.
  1714. """
  1715. if not expr.args:
  1716. return expr
  1717. if expr.is_Add or expr.is_Mul or expr.is_Pow:
  1718. args = None
  1719. for i, a in enumerate(expr.args):
  1720. c = nonalg_subs_dummies(a, dummies)
  1721. if c is a:
  1722. continue
  1723. if args is None:
  1724. args = list(expr.args)
  1725. args[i] = c
  1726. if args is None:
  1727. return expr
  1728. return expr.func(*args)
  1729. return dummies.setdefault(expr, Dummy())
  1730. simplified = False # doesn't really mean simplified, rather "can simplify again"
  1731. if isinstance(expr, Basic) and (expr.is_Add or expr.is_Mul or expr.is_Pow):
  1732. expr2 = expr.expand(deep=True, modulus=None, power_base=False,
  1733. power_exp=False, mul=True, log=False, multinomial=True, basic=False)
  1734. if expr2 != expr:
  1735. expr = expr2
  1736. simplified = True
  1737. exprops, ratfunc = count_ops_alg(expr)
  1738. if exprops >= 6: # empirically tested cutoff for expensive simplification
  1739. if ratfunc:
  1740. dummies = {}
  1741. expr2 = nonalg_subs_dummies(expr, dummies)
  1742. if expr2 is expr or count_ops_alg(expr2)[0] >= 6: # check again after substitution
  1743. expr3 = cancel(expr2)
  1744. if expr3 != expr2:
  1745. expr = expr3.subs([(d, e) for e, d in dummies.items()])
  1746. simplified = True
  1747. # very special case: x/(x-1) - 1/(x-1) -> 1
  1748. elif (exprops == 5 and expr.is_Add and expr.args [0].is_Mul and
  1749. expr.args [1].is_Mul and expr.args [0].args [-1].is_Pow and
  1750. expr.args [1].args [-1].is_Pow and
  1751. expr.args [0].args [-1].exp is S.NegativeOne and
  1752. expr.args [1].args [-1].exp is S.NegativeOne):
  1753. expr2 = together (expr)
  1754. expr2ops = count_ops_alg(expr2)[0]
  1755. if expr2ops < exprops:
  1756. expr = expr2
  1757. simplified = True
  1758. else:
  1759. simplified = True
  1760. return (expr, simplified) if withsimp else expr
  1761. bottom_up = deprecated(
  1762. """
  1763. Using bottom_up from the sympy.simplify.simplify submodule is
  1764. deprecated.
  1765. Instead, use bottom_up from the top-level sympy namespace, like
  1766. sympy.bottom_up
  1767. """,
  1768. deprecated_since_version="1.10",
  1769. active_deprecations_target="deprecated-traversal-functions-moved",
  1770. )(_bottom_up)
  1771. # XXX: This function really should either be private API or exported in the
  1772. # top-level sympy/__init__.py
  1773. walk = deprecated(
  1774. """
  1775. Using walk from the sympy.simplify.simplify submodule is
  1776. deprecated.
  1777. Instead, use walk from sympy.core.traversal.walk
  1778. """,
  1779. deprecated_since_version="1.10",
  1780. active_deprecations_target="deprecated-traversal-functions-moved",
  1781. )(_walk)