exprtools.py 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569
  1. """Tools for manipulating of large commutative expressions. """
  2. from .add import Add
  3. from .mul import Mul, _keep_coeff
  4. from .power import Pow
  5. from .basic import Basic
  6. from .expr import Expr
  7. from .function import expand_power_exp
  8. from .sympify import sympify
  9. from .numbers import Rational, Integer, Number, I, equal_valued
  10. from .singleton import S
  11. from .sorting import default_sort_key, ordered
  12. from .symbol import Dummy
  13. from .traversal import preorder_traversal
  14. from .coreerrors import NonCommutativeExpression
  15. from .containers import Tuple, Dict
  16. from sympy.external.gmpy import SYMPY_INTS
  17. from sympy.utilities.iterables import (common_prefix, common_suffix,
  18. variations, iterable, is_sequence)
  19. from collections import defaultdict
  20. from typing import Tuple as tTuple
  21. _eps = Dummy(positive=True)
  22. def _isnumber(i):
  23. return isinstance(i, (SYMPY_INTS, float)) or i.is_Number
  24. def _monotonic_sign(self):
  25. """Return the value closest to 0 that ``self`` may have if all symbols
  26. are signed and the result is uniformly the same sign for all values of symbols.
  27. If a symbol is only signed but not known to be an
  28. integer or the result is 0 then a symbol representative of the sign of self
  29. will be returned. Otherwise, None is returned if a) the sign could be positive
  30. or negative or b) self is not in one of the following forms:
  31. - L(x, y, ...) + A: a function linear in all symbols x, y, ... with an
  32. additive constant; if A is zero then the function can be a monomial whose
  33. sign is monotonic over the range of the variables, e.g. (x + 1)**3 if x is
  34. nonnegative.
  35. - A/L(x, y, ...) + B: the inverse of a function linear in all symbols x, y, ...
  36. that does not have a sign change from positive to negative for any set
  37. of values for the variables.
  38. - M(x, y, ...) + A: a monomial M whose factors are all signed and a constant, A.
  39. - A/M(x, y, ...) + B: the inverse of a monomial and constants A and B.
  40. - P(x): a univariate polynomial
  41. Examples
  42. ========
  43. >>> from sympy.core.exprtools import _monotonic_sign as F
  44. >>> from sympy import Dummy
  45. >>> nn = Dummy(integer=True, nonnegative=True)
  46. >>> p = Dummy(integer=True, positive=True)
  47. >>> p2 = Dummy(integer=True, positive=True)
  48. >>> F(nn + 1)
  49. 1
  50. >>> F(p - 1)
  51. _nneg
  52. >>> F(nn*p + 1)
  53. 1
  54. >>> F(p2*p + 1)
  55. 2
  56. >>> F(nn - 1) # could be negative, zero or positive
  57. """
  58. if not self.is_extended_real:
  59. return
  60. if (-self).is_Symbol:
  61. rv = _monotonic_sign(-self)
  62. return rv if rv is None else -rv
  63. if not self.is_Add and self.as_numer_denom()[1].is_number:
  64. s = self
  65. if s.is_prime:
  66. if s.is_odd:
  67. return Integer(3)
  68. else:
  69. return Integer(2)
  70. elif s.is_composite:
  71. if s.is_odd:
  72. return Integer(9)
  73. else:
  74. return Integer(4)
  75. elif s.is_positive:
  76. if s.is_even:
  77. if s.is_prime is False:
  78. return Integer(4)
  79. else:
  80. return Integer(2)
  81. elif s.is_integer:
  82. return S.One
  83. else:
  84. return _eps
  85. elif s.is_extended_negative:
  86. if s.is_even:
  87. return Integer(-2)
  88. elif s.is_integer:
  89. return S.NegativeOne
  90. else:
  91. return -_eps
  92. if s.is_zero or s.is_extended_nonpositive or s.is_extended_nonnegative:
  93. return S.Zero
  94. return None
  95. # univariate polynomial
  96. free = self.free_symbols
  97. if len(free) == 1:
  98. if self.is_polynomial():
  99. from sympy.polys.polytools import real_roots
  100. from sympy.polys.polyroots import roots
  101. from sympy.polys.polyerrors import PolynomialError
  102. x = free.pop()
  103. x0 = _monotonic_sign(x)
  104. if x0 in (_eps, -_eps):
  105. x0 = S.Zero
  106. if x0 is not None:
  107. d = self.diff(x)
  108. if d.is_number:
  109. currentroots = []
  110. else:
  111. try:
  112. currentroots = real_roots(d)
  113. except (PolynomialError, NotImplementedError):
  114. currentroots = [r for r in roots(d, x) if r.is_extended_real]
  115. y = self.subs(x, x0)
  116. if x.is_nonnegative and all(
  117. (r - x0).is_nonpositive for r in currentroots):
  118. if y.is_nonnegative and d.is_positive:
  119. if y:
  120. return y if y.is_positive else Dummy('pos', positive=True)
  121. else:
  122. return Dummy('nneg', nonnegative=True)
  123. if y.is_nonpositive and d.is_negative:
  124. if y:
  125. return y if y.is_negative else Dummy('neg', negative=True)
  126. else:
  127. return Dummy('npos', nonpositive=True)
  128. elif x.is_nonpositive and all(
  129. (r - x0).is_nonnegative for r in currentroots):
  130. if y.is_nonnegative and d.is_negative:
  131. if y:
  132. return Dummy('pos', positive=True)
  133. else:
  134. return Dummy('nneg', nonnegative=True)
  135. if y.is_nonpositive and d.is_positive:
  136. if y:
  137. return Dummy('neg', negative=True)
  138. else:
  139. return Dummy('npos', nonpositive=True)
  140. else:
  141. n, d = self.as_numer_denom()
  142. den = None
  143. if n.is_number:
  144. den = _monotonic_sign(d)
  145. elif not d.is_number:
  146. if _monotonic_sign(n) is not None:
  147. den = _monotonic_sign(d)
  148. if den is not None and (den.is_positive or den.is_negative):
  149. v = n*den
  150. if v.is_positive:
  151. return Dummy('pos', positive=True)
  152. elif v.is_nonnegative:
  153. return Dummy('nneg', nonnegative=True)
  154. elif v.is_negative:
  155. return Dummy('neg', negative=True)
  156. elif v.is_nonpositive:
  157. return Dummy('npos', nonpositive=True)
  158. return None
  159. # multivariate
  160. c, a = self.as_coeff_Add()
  161. v = None
  162. if not a.is_polynomial():
  163. # F/A or A/F where A is a number and F is a signed, rational monomial
  164. n, d = a.as_numer_denom()
  165. if not (n.is_number or d.is_number):
  166. return
  167. if (
  168. a.is_Mul or a.is_Pow) and \
  169. a.is_rational and \
  170. all(p.exp.is_Integer for p in a.atoms(Pow) if p.is_Pow) and \
  171. (a.is_positive or a.is_negative):
  172. v = S.One
  173. for ai in Mul.make_args(a):
  174. if ai.is_number:
  175. v *= ai
  176. continue
  177. reps = {}
  178. for x in ai.free_symbols:
  179. reps[x] = _monotonic_sign(x)
  180. if reps[x] is None:
  181. return
  182. v *= ai.subs(reps)
  183. elif c:
  184. # signed linear expression
  185. if not any(p for p in a.atoms(Pow) if not p.is_number) and (a.is_nonpositive or a.is_nonnegative):
  186. free = list(a.free_symbols)
  187. p = {}
  188. for i in free:
  189. v = _monotonic_sign(i)
  190. if v is None:
  191. return
  192. p[i] = v or (_eps if i.is_nonnegative else -_eps)
  193. v = a.xreplace(p)
  194. if v is not None:
  195. rv = v + c
  196. if v.is_nonnegative and rv.is_positive:
  197. return rv.subs(_eps, 0)
  198. if v.is_nonpositive and rv.is_negative:
  199. return rv.subs(_eps, 0)
  200. def decompose_power(expr: Expr) -> tTuple[Expr, int]:
  201. """
  202. Decompose power into symbolic base and integer exponent.
  203. Examples
  204. ========
  205. >>> from sympy.core.exprtools import decompose_power
  206. >>> from sympy.abc import x, y
  207. >>> from sympy import exp
  208. >>> decompose_power(x)
  209. (x, 1)
  210. >>> decompose_power(x**2)
  211. (x, 2)
  212. >>> decompose_power(exp(2*y/3))
  213. (exp(y/3), 2)
  214. """
  215. base, exp = expr.as_base_exp()
  216. if exp.is_Number:
  217. if exp.is_Rational:
  218. if not exp.is_Integer:
  219. base = Pow(base, Rational(1, exp.q)) # type: ignore
  220. e = exp.p # type: ignore
  221. else:
  222. base, e = expr, 1
  223. else:
  224. exp, tail = exp.as_coeff_Mul(rational=True)
  225. if exp is S.NegativeOne:
  226. base, e = Pow(base, tail), -1
  227. elif exp is not S.One:
  228. # todo: after dropping python 3.7 support, use overload and Literal
  229. # in as_coeff_Mul to make exp Rational, and remove these 2 ignores
  230. tail = _keep_coeff(Rational(1, exp.q), tail) # type: ignore
  231. base, e = Pow(base, tail), exp.p # type: ignore
  232. else:
  233. base, e = expr, 1
  234. return base, e
  235. def decompose_power_rat(expr: Expr) -> tTuple[Expr, Rational]:
  236. """
  237. Decompose power into symbolic base and rational exponent;
  238. if the exponent is not a Rational, then separate only the
  239. integer coefficient.
  240. Examples
  241. ========
  242. >>> from sympy.core.exprtools import decompose_power_rat
  243. >>> from sympy.abc import x
  244. >>> from sympy import sqrt, exp
  245. >>> decompose_power_rat(sqrt(x))
  246. (x, 1/2)
  247. >>> decompose_power_rat(exp(-3*x/2))
  248. (exp(x/2), -3)
  249. """
  250. _ = base, exp = expr.as_base_exp()
  251. return _ if exp.is_Rational else decompose_power(expr)
  252. class Factors:
  253. """Efficient representation of ``f_1*f_2*...*f_n``."""
  254. __slots__ = ('factors', 'gens')
  255. def __init__(self, factors=None): # Factors
  256. """Initialize Factors from dict or expr.
  257. Examples
  258. ========
  259. >>> from sympy.core.exprtools import Factors
  260. >>> from sympy.abc import x
  261. >>> from sympy import I
  262. >>> e = 2*x**3
  263. >>> Factors(e)
  264. Factors({2: 1, x: 3})
  265. >>> Factors(e.as_powers_dict())
  266. Factors({2: 1, x: 3})
  267. >>> f = _
  268. >>> f.factors # underlying dictionary
  269. {2: 1, x: 3}
  270. >>> f.gens # base of each factor
  271. frozenset({2, x})
  272. >>> Factors(0)
  273. Factors({0: 1})
  274. >>> Factors(I)
  275. Factors({I: 1})
  276. Notes
  277. =====
  278. Although a dictionary can be passed, only minimal checking is
  279. performed: powers of -1 and I are made canonical.
  280. """
  281. if isinstance(factors, (SYMPY_INTS, float)):
  282. factors = S(factors)
  283. if isinstance(factors, Factors):
  284. factors = factors.factors.copy()
  285. elif factors in (None, S.One):
  286. factors = {}
  287. elif factors is S.Zero or factors == 0:
  288. factors = {S.Zero: S.One}
  289. elif isinstance(factors, Number):
  290. n = factors
  291. factors = {}
  292. if n < 0:
  293. factors[S.NegativeOne] = S.One
  294. n = -n
  295. if n is not S.One:
  296. if n.is_Float or n.is_Integer or n is S.Infinity:
  297. factors[n] = S.One
  298. elif n.is_Rational:
  299. # since we're processing Numbers, the denominator is
  300. # stored with a negative exponent; all other factors
  301. # are left .
  302. if n.p != 1:
  303. factors[Integer(n.p)] = S.One
  304. factors[Integer(n.q)] = S.NegativeOne
  305. else:
  306. raise ValueError('Expected Float|Rational|Integer, not %s' % n)
  307. elif isinstance(factors, Basic) and not factors.args:
  308. factors = {factors: S.One}
  309. elif isinstance(factors, Expr):
  310. c, nc = factors.args_cnc()
  311. i = c.count(I)
  312. for _ in range(i):
  313. c.remove(I)
  314. factors = dict(Mul._from_args(c).as_powers_dict())
  315. # Handle all rational Coefficients
  316. for f in list(factors.keys()):
  317. if isinstance(f, Rational) and not isinstance(f, Integer):
  318. p, q = Integer(f.p), Integer(f.q)
  319. factors[p] = (factors[p] if p in factors else S.Zero) + factors[f]
  320. factors[q] = (factors[q] if q in factors else S.Zero) - factors[f]
  321. factors.pop(f)
  322. if i:
  323. factors[I] = factors.get(I, S.Zero) + i
  324. if nc:
  325. factors[Mul(*nc, evaluate=False)] = S.One
  326. else:
  327. factors = factors.copy() # /!\ should be dict-like
  328. # tidy up -/+1 and I exponents if Rational
  329. handle = [k for k in factors if k is I or k in (-1, 1)]
  330. if handle:
  331. i1 = S.One
  332. for k in handle:
  333. if not _isnumber(factors[k]):
  334. continue
  335. i1 *= k**factors.pop(k)
  336. if i1 is not S.One:
  337. for a in i1.args if i1.is_Mul else [i1]: # at worst, -1.0*I*(-1)**e
  338. if a is S.NegativeOne:
  339. factors[a] = S.One
  340. elif a is I:
  341. factors[I] = S.One
  342. elif a.is_Pow:
  343. factors[a.base] = factors.get(a.base, S.Zero) + a.exp
  344. elif equal_valued(a, 1):
  345. factors[a] = S.One
  346. elif equal_valued(a, -1):
  347. factors[-a] = S.One
  348. factors[S.NegativeOne] = S.One
  349. else:
  350. raise ValueError('unexpected factor in i1: %s' % a)
  351. self.factors = factors
  352. keys = getattr(factors, 'keys', None)
  353. if keys is None:
  354. raise TypeError('expecting Expr or dictionary')
  355. self.gens = frozenset(keys())
  356. def __hash__(self): # Factors
  357. keys = tuple(ordered(self.factors.keys()))
  358. values = [self.factors[k] for k in keys]
  359. return hash((keys, values))
  360. def __repr__(self): # Factors
  361. return "Factors({%s})" % ', '.join(
  362. ['%s: %s' % (k, v) for k, v in ordered(self.factors.items())])
  363. @property
  364. def is_zero(self): # Factors
  365. """
  366. >>> from sympy.core.exprtools import Factors
  367. >>> Factors(0).is_zero
  368. True
  369. """
  370. f = self.factors
  371. return len(f) == 1 and S.Zero in f
  372. @property
  373. def is_one(self): # Factors
  374. """
  375. >>> from sympy.core.exprtools import Factors
  376. >>> Factors(1).is_one
  377. True
  378. """
  379. return not self.factors
  380. def as_expr(self): # Factors
  381. """Return the underlying expression.
  382. Examples
  383. ========
  384. >>> from sympy.core.exprtools import Factors
  385. >>> from sympy.abc import x, y
  386. >>> Factors((x*y**2).as_powers_dict()).as_expr()
  387. x*y**2
  388. """
  389. args = []
  390. for factor, exp in self.factors.items():
  391. if exp != 1:
  392. if isinstance(exp, Integer):
  393. b, e = factor.as_base_exp()
  394. e = _keep_coeff(exp, e)
  395. args.append(b**e)
  396. else:
  397. args.append(factor**exp)
  398. else:
  399. args.append(factor)
  400. return Mul(*args)
  401. def mul(self, other): # Factors
  402. """Return Factors of ``self * other``.
  403. Examples
  404. ========
  405. >>> from sympy.core.exprtools import Factors
  406. >>> from sympy.abc import x, y, z
  407. >>> a = Factors((x*y**2).as_powers_dict())
  408. >>> b = Factors((x*y/z).as_powers_dict())
  409. >>> a.mul(b)
  410. Factors({x: 2, y: 3, z: -1})
  411. >>> a*b
  412. Factors({x: 2, y: 3, z: -1})
  413. """
  414. if not isinstance(other, Factors):
  415. other = Factors(other)
  416. if any(f.is_zero for f in (self, other)):
  417. return Factors(S.Zero)
  418. factors = dict(self.factors)
  419. for factor, exp in other.factors.items():
  420. if factor in factors:
  421. exp = factors[factor] + exp
  422. if not exp:
  423. del factors[factor]
  424. continue
  425. factors[factor] = exp
  426. return Factors(factors)
  427. def normal(self, other):
  428. """Return ``self`` and ``other`` with ``gcd`` removed from each.
  429. The only differences between this and method ``div`` is that this
  430. is 1) optimized for the case when there are few factors in common and
  431. 2) this does not raise an error if ``other`` is zero.
  432. See Also
  433. ========
  434. div
  435. """
  436. if not isinstance(other, Factors):
  437. other = Factors(other)
  438. if other.is_zero:
  439. return (Factors(), Factors(S.Zero))
  440. if self.is_zero:
  441. return (Factors(S.Zero), Factors())
  442. self_factors = dict(self.factors)
  443. other_factors = dict(other.factors)
  444. for factor, self_exp in self.factors.items():
  445. try:
  446. other_exp = other.factors[factor]
  447. except KeyError:
  448. continue
  449. exp = self_exp - other_exp
  450. if not exp:
  451. del self_factors[factor]
  452. del other_factors[factor]
  453. elif _isnumber(exp):
  454. if exp > 0:
  455. self_factors[factor] = exp
  456. del other_factors[factor]
  457. else:
  458. del self_factors[factor]
  459. other_factors[factor] = -exp
  460. else:
  461. r = self_exp.extract_additively(other_exp)
  462. if r is not None:
  463. if r:
  464. self_factors[factor] = r
  465. del other_factors[factor]
  466. else: # should be handled already
  467. del self_factors[factor]
  468. del other_factors[factor]
  469. else:
  470. sc, sa = self_exp.as_coeff_Add()
  471. if sc:
  472. oc, oa = other_exp.as_coeff_Add()
  473. diff = sc - oc
  474. if diff > 0:
  475. self_factors[factor] -= oc
  476. other_exp = oa
  477. elif diff < 0:
  478. self_factors[factor] -= sc
  479. other_factors[factor] -= sc
  480. other_exp = oa - diff
  481. else:
  482. self_factors[factor] = sa
  483. other_exp = oa
  484. if other_exp:
  485. other_factors[factor] = other_exp
  486. else:
  487. del other_factors[factor]
  488. return Factors(self_factors), Factors(other_factors)
  489. def div(self, other): # Factors
  490. """Return ``self`` and ``other`` with ``gcd`` removed from each.
  491. This is optimized for the case when there are many factors in common.
  492. Examples
  493. ========
  494. >>> from sympy.core.exprtools import Factors
  495. >>> from sympy.abc import x, y, z
  496. >>> from sympy import S
  497. >>> a = Factors((x*y**2).as_powers_dict())
  498. >>> a.div(a)
  499. (Factors({}), Factors({}))
  500. >>> a.div(x*z)
  501. (Factors({y: 2}), Factors({z: 1}))
  502. The ``/`` operator only gives ``quo``:
  503. >>> a/x
  504. Factors({y: 2})
  505. Factors treats its factors as though they are all in the numerator, so
  506. if you violate this assumption the results will be correct but will
  507. not strictly correspond to the numerator and denominator of the ratio:
  508. >>> a.div(x/z)
  509. (Factors({y: 2}), Factors({z: -1}))
  510. Factors is also naive about bases: it does not attempt any denesting
  511. of Rational-base terms, for example the following does not become
  512. 2**(2*x)/2.
  513. >>> Factors(2**(2*x + 2)).div(S(8))
  514. (Factors({2: 2*x + 2}), Factors({8: 1}))
  515. factor_terms can clean up such Rational-bases powers:
  516. >>> from sympy import factor_terms
  517. >>> n, d = Factors(2**(2*x + 2)).div(S(8))
  518. >>> n.as_expr()/d.as_expr()
  519. 2**(2*x + 2)/8
  520. >>> factor_terms(_)
  521. 2**(2*x)/2
  522. """
  523. quo, rem = dict(self.factors), {}
  524. if not isinstance(other, Factors):
  525. other = Factors(other)
  526. if other.is_zero:
  527. raise ZeroDivisionError
  528. if self.is_zero:
  529. return (Factors(S.Zero), Factors())
  530. for factor, exp in other.factors.items():
  531. if factor in quo:
  532. d = quo[factor] - exp
  533. if _isnumber(d):
  534. if d <= 0:
  535. del quo[factor]
  536. if d >= 0:
  537. if d:
  538. quo[factor] = d
  539. continue
  540. exp = -d
  541. else:
  542. r = quo[factor].extract_additively(exp)
  543. if r is not None:
  544. if r:
  545. quo[factor] = r
  546. else: # should be handled already
  547. del quo[factor]
  548. else:
  549. other_exp = exp
  550. sc, sa = quo[factor].as_coeff_Add()
  551. if sc:
  552. oc, oa = other_exp.as_coeff_Add()
  553. diff = sc - oc
  554. if diff > 0:
  555. quo[factor] -= oc
  556. other_exp = oa
  557. elif diff < 0:
  558. quo[factor] -= sc
  559. other_exp = oa - diff
  560. else:
  561. quo[factor] = sa
  562. other_exp = oa
  563. if other_exp:
  564. rem[factor] = other_exp
  565. else:
  566. assert factor not in rem
  567. continue
  568. rem[factor] = exp
  569. return Factors(quo), Factors(rem)
  570. def quo(self, other): # Factors
  571. """Return numerator Factor of ``self / other``.
  572. Examples
  573. ========
  574. >>> from sympy.core.exprtools import Factors
  575. >>> from sympy.abc import x, y, z
  576. >>> a = Factors((x*y**2).as_powers_dict())
  577. >>> b = Factors((x*y/z).as_powers_dict())
  578. >>> a.quo(b) # same as a/b
  579. Factors({y: 1})
  580. """
  581. return self.div(other)[0]
  582. def rem(self, other): # Factors
  583. """Return denominator Factors of ``self / other``.
  584. Examples
  585. ========
  586. >>> from sympy.core.exprtools import Factors
  587. >>> from sympy.abc import x, y, z
  588. >>> a = Factors((x*y**2).as_powers_dict())
  589. >>> b = Factors((x*y/z).as_powers_dict())
  590. >>> a.rem(b)
  591. Factors({z: -1})
  592. >>> a.rem(a)
  593. Factors({})
  594. """
  595. return self.div(other)[1]
  596. def pow(self, other): # Factors
  597. """Return self raised to a non-negative integer power.
  598. Examples
  599. ========
  600. >>> from sympy.core.exprtools import Factors
  601. >>> from sympy.abc import x, y
  602. >>> a = Factors((x*y**2).as_powers_dict())
  603. >>> a**2
  604. Factors({x: 2, y: 4})
  605. """
  606. if isinstance(other, Factors):
  607. other = other.as_expr()
  608. if other.is_Integer:
  609. other = int(other)
  610. if isinstance(other, SYMPY_INTS) and other >= 0:
  611. factors = {}
  612. if other:
  613. for factor, exp in self.factors.items():
  614. factors[factor] = exp*other
  615. return Factors(factors)
  616. else:
  617. raise ValueError("expected non-negative integer, got %s" % other)
  618. def gcd(self, other): # Factors
  619. """Return Factors of ``gcd(self, other)``. The keys are
  620. the intersection of factors with the minimum exponent for
  621. each factor.
  622. Examples
  623. ========
  624. >>> from sympy.core.exprtools import Factors
  625. >>> from sympy.abc import x, y, z
  626. >>> a = Factors((x*y**2).as_powers_dict())
  627. >>> b = Factors((x*y/z).as_powers_dict())
  628. >>> a.gcd(b)
  629. Factors({x: 1, y: 1})
  630. """
  631. if not isinstance(other, Factors):
  632. other = Factors(other)
  633. if other.is_zero:
  634. return Factors(self.factors)
  635. factors = {}
  636. for factor, exp in self.factors.items():
  637. factor, exp = sympify(factor), sympify(exp)
  638. if factor in other.factors:
  639. lt = (exp - other.factors[factor]).is_negative
  640. if lt == True:
  641. factors[factor] = exp
  642. elif lt == False:
  643. factors[factor] = other.factors[factor]
  644. return Factors(factors)
  645. def lcm(self, other): # Factors
  646. """Return Factors of ``lcm(self, other)`` which are
  647. the union of factors with the maximum exponent for
  648. each factor.
  649. Examples
  650. ========
  651. >>> from sympy.core.exprtools import Factors
  652. >>> from sympy.abc import x, y, z
  653. >>> a = Factors((x*y**2).as_powers_dict())
  654. >>> b = Factors((x*y/z).as_powers_dict())
  655. >>> a.lcm(b)
  656. Factors({x: 1, y: 2, z: -1})
  657. """
  658. if not isinstance(other, Factors):
  659. other = Factors(other)
  660. if any(f.is_zero for f in (self, other)):
  661. return Factors(S.Zero)
  662. factors = dict(self.factors)
  663. for factor, exp in other.factors.items():
  664. if factor in factors:
  665. exp = max(exp, factors[factor])
  666. factors[factor] = exp
  667. return Factors(factors)
  668. def __mul__(self, other): # Factors
  669. return self.mul(other)
  670. def __divmod__(self, other): # Factors
  671. return self.div(other)
  672. def __truediv__(self, other): # Factors
  673. return self.quo(other)
  674. def __mod__(self, other): # Factors
  675. return self.rem(other)
  676. def __pow__(self, other): # Factors
  677. return self.pow(other)
  678. def __eq__(self, other): # Factors
  679. if not isinstance(other, Factors):
  680. other = Factors(other)
  681. return self.factors == other.factors
  682. def __ne__(self, other): # Factors
  683. return not self == other
  684. class Term:
  685. """Efficient representation of ``coeff*(numer/denom)``. """
  686. __slots__ = ('coeff', 'numer', 'denom')
  687. def __init__(self, term, numer=None, denom=None): # Term
  688. if numer is None and denom is None:
  689. if not term.is_commutative:
  690. raise NonCommutativeExpression(
  691. 'commutative expression expected')
  692. coeff, factors = term.as_coeff_mul()
  693. numer, denom = defaultdict(int), defaultdict(int)
  694. for factor in factors:
  695. base, exp = decompose_power(factor)
  696. if base.is_Add:
  697. cont, base = base.primitive()
  698. coeff *= cont**exp
  699. if exp > 0:
  700. numer[base] += exp
  701. else:
  702. denom[base] += -exp
  703. numer = Factors(numer)
  704. denom = Factors(denom)
  705. else:
  706. coeff = term
  707. if numer is None:
  708. numer = Factors()
  709. if denom is None:
  710. denom = Factors()
  711. self.coeff = coeff
  712. self.numer = numer
  713. self.denom = denom
  714. def __hash__(self): # Term
  715. return hash((self.coeff, self.numer, self.denom))
  716. def __repr__(self): # Term
  717. return "Term(%s, %s, %s)" % (self.coeff, self.numer, self.denom)
  718. def as_expr(self): # Term
  719. return self.coeff*(self.numer.as_expr()/self.denom.as_expr())
  720. def mul(self, other): # Term
  721. coeff = self.coeff*other.coeff
  722. numer = self.numer.mul(other.numer)
  723. denom = self.denom.mul(other.denom)
  724. numer, denom = numer.normal(denom)
  725. return Term(coeff, numer, denom)
  726. def inv(self): # Term
  727. return Term(1/self.coeff, self.denom, self.numer)
  728. def quo(self, other): # Term
  729. return self.mul(other.inv())
  730. def pow(self, other): # Term
  731. if other < 0:
  732. return self.inv().pow(-other)
  733. else:
  734. return Term(self.coeff ** other,
  735. self.numer.pow(other),
  736. self.denom.pow(other))
  737. def gcd(self, other): # Term
  738. return Term(self.coeff.gcd(other.coeff),
  739. self.numer.gcd(other.numer),
  740. self.denom.gcd(other.denom))
  741. def lcm(self, other): # Term
  742. return Term(self.coeff.lcm(other.coeff),
  743. self.numer.lcm(other.numer),
  744. self.denom.lcm(other.denom))
  745. def __mul__(self, other): # Term
  746. if isinstance(other, Term):
  747. return self.mul(other)
  748. else:
  749. return NotImplemented
  750. def __truediv__(self, other): # Term
  751. if isinstance(other, Term):
  752. return self.quo(other)
  753. else:
  754. return NotImplemented
  755. def __pow__(self, other): # Term
  756. if isinstance(other, SYMPY_INTS):
  757. return self.pow(other)
  758. else:
  759. return NotImplemented
  760. def __eq__(self, other): # Term
  761. return (self.coeff == other.coeff and
  762. self.numer == other.numer and
  763. self.denom == other.denom)
  764. def __ne__(self, other): # Term
  765. return not self == other
  766. def _gcd_terms(terms, isprimitive=False, fraction=True):
  767. """Helper function for :func:`gcd_terms`.
  768. Parameters
  769. ==========
  770. isprimitive : boolean, optional
  771. If ``isprimitive`` is True then the call to primitive
  772. for an Add will be skipped. This is useful when the
  773. content has already been extracted.
  774. fraction : boolean, optional
  775. If ``fraction`` is True then the expression will appear over a common
  776. denominator, the lcm of all term denominators.
  777. """
  778. if isinstance(terms, Basic) and not isinstance(terms, Tuple):
  779. terms = Add.make_args(terms)
  780. terms = list(map(Term, [t for t in terms if t]))
  781. # there is some simplification that may happen if we leave this
  782. # here rather than duplicate it before the mapping of Term onto
  783. # the terms
  784. if len(terms) == 0:
  785. return S.Zero, S.Zero, S.One
  786. if len(terms) == 1:
  787. cont = terms[0].coeff
  788. numer = terms[0].numer.as_expr()
  789. denom = terms[0].denom.as_expr()
  790. else:
  791. cont = terms[0]
  792. for term in terms[1:]:
  793. cont = cont.gcd(term)
  794. for i, term in enumerate(terms):
  795. terms[i] = term.quo(cont)
  796. if fraction:
  797. denom = terms[0].denom
  798. for term in terms[1:]:
  799. denom = denom.lcm(term.denom)
  800. numers = []
  801. for term in terms:
  802. numer = term.numer.mul(denom.quo(term.denom))
  803. numers.append(term.coeff*numer.as_expr())
  804. else:
  805. numers = [t.as_expr() for t in terms]
  806. denom = Term(S.One).numer
  807. cont = cont.as_expr()
  808. numer = Add(*numers)
  809. denom = denom.as_expr()
  810. if not isprimitive and numer.is_Add:
  811. _cont, numer = numer.primitive()
  812. cont *= _cont
  813. return cont, numer, denom
  814. def gcd_terms(terms, isprimitive=False, clear=True, fraction=True):
  815. """Compute the GCD of ``terms`` and put them together.
  816. Parameters
  817. ==========
  818. terms : Expr
  819. Can be an expression or a non-Basic sequence of expressions
  820. which will be handled as though they are terms from a sum.
  821. isprimitive : bool, optional
  822. If ``isprimitive`` is True the _gcd_terms will not run the primitive
  823. method on the terms.
  824. clear : bool, optional
  825. It controls the removal of integers from the denominator of an Add
  826. expression. When True (default), all numerical denominator will be cleared;
  827. when False the denominators will be cleared only if all terms had numerical
  828. denominators other than 1.
  829. fraction : bool, optional
  830. When True (default), will put the expression over a common
  831. denominator.
  832. Examples
  833. ========
  834. >>> from sympy import gcd_terms
  835. >>> from sympy.abc import x, y
  836. >>> gcd_terms((x + 1)**2*y + (x + 1)*y**2)
  837. y*(x + 1)*(x + y + 1)
  838. >>> gcd_terms(x/2 + 1)
  839. (x + 2)/2
  840. >>> gcd_terms(x/2 + 1, clear=False)
  841. x/2 + 1
  842. >>> gcd_terms(x/2 + y/2, clear=False)
  843. (x + y)/2
  844. >>> gcd_terms(x/2 + 1/x)
  845. (x**2 + 2)/(2*x)
  846. >>> gcd_terms(x/2 + 1/x, fraction=False)
  847. (x + 2/x)/2
  848. >>> gcd_terms(x/2 + 1/x, fraction=False, clear=False)
  849. x/2 + 1/x
  850. >>> gcd_terms(x/2/y + 1/x/y)
  851. (x**2 + 2)/(2*x*y)
  852. >>> gcd_terms(x/2/y + 1/x/y, clear=False)
  853. (x**2/2 + 1)/(x*y)
  854. >>> gcd_terms(x/2/y + 1/x/y, clear=False, fraction=False)
  855. (x/2 + 1/x)/y
  856. The ``clear`` flag was ignored in this case because the returned
  857. expression was a rational expression, not a simple sum.
  858. See Also
  859. ========
  860. factor_terms, sympy.polys.polytools.terms_gcd
  861. """
  862. def mask(terms):
  863. """replace nc portions of each term with a unique Dummy symbols
  864. and return the replacements to restore them"""
  865. args = [(a, []) if a.is_commutative else a.args_cnc() for a in terms]
  866. reps = []
  867. for i, (c, nc) in enumerate(args):
  868. if nc:
  869. nc = Mul(*nc)
  870. d = Dummy()
  871. reps.append((d, nc))
  872. c.append(d)
  873. args[i] = Mul(*c)
  874. else:
  875. args[i] = c
  876. return args, dict(reps)
  877. isadd = isinstance(terms, Add)
  878. addlike = isadd or not isinstance(terms, Basic) and \
  879. is_sequence(terms, include=set) and \
  880. not isinstance(terms, Dict)
  881. if addlike:
  882. if isadd: # i.e. an Add
  883. terms = list(terms.args)
  884. else:
  885. terms = sympify(terms)
  886. terms, reps = mask(terms)
  887. cont, numer, denom = _gcd_terms(terms, isprimitive, fraction)
  888. numer = numer.xreplace(reps)
  889. coeff, factors = cont.as_coeff_Mul()
  890. if not clear:
  891. c, _coeff = coeff.as_coeff_Mul()
  892. if not c.is_Integer and not clear and numer.is_Add:
  893. n, d = c.as_numer_denom()
  894. _numer = numer/d
  895. if any(a.as_coeff_Mul()[0].is_Integer
  896. for a in _numer.args):
  897. numer = _numer
  898. coeff = n*_coeff
  899. return _keep_coeff(coeff, factors*numer/denom, clear=clear)
  900. if not isinstance(terms, Basic):
  901. return terms
  902. if terms.is_Atom:
  903. return terms
  904. if terms.is_Mul:
  905. c, args = terms.as_coeff_mul()
  906. return _keep_coeff(c, Mul(*[gcd_terms(i, isprimitive, clear, fraction)
  907. for i in args]), clear=clear)
  908. def handle(a):
  909. # don't treat internal args like terms of an Add
  910. if not isinstance(a, Expr):
  911. if isinstance(a, Basic):
  912. if not a.args:
  913. return a
  914. return a.func(*[handle(i) for i in a.args])
  915. return type(a)([handle(i) for i in a])
  916. return gcd_terms(a, isprimitive, clear, fraction)
  917. if isinstance(terms, Dict):
  918. return Dict(*[(k, handle(v)) for k, v in terms.args])
  919. return terms.func(*[handle(i) for i in terms.args])
  920. def _factor_sum_int(expr, **kwargs):
  921. """Return Sum or Integral object with factors that are not
  922. in the wrt variables removed. In cases where there are additive
  923. terms in the function of the object that are independent, the
  924. object will be separated into two objects.
  925. Examples
  926. ========
  927. >>> from sympy import Sum, factor_terms
  928. >>> from sympy.abc import x, y
  929. >>> factor_terms(Sum(x + y, (x, 1, 3)))
  930. y*Sum(1, (x, 1, 3)) + Sum(x, (x, 1, 3))
  931. >>> factor_terms(Sum(x*y, (x, 1, 3)))
  932. y*Sum(x, (x, 1, 3))
  933. Notes
  934. =====
  935. If a function in the summand or integrand is replaced
  936. with a symbol, then this simplification should not be
  937. done or else an incorrect result will be obtained when
  938. the symbol is replaced with an expression that depends
  939. on the variables of summation/integration:
  940. >>> eq = Sum(y, (x, 1, 3))
  941. >>> factor_terms(eq).subs(y, x).doit()
  942. 3*x
  943. >>> eq.subs(y, x).doit()
  944. 6
  945. """
  946. result = expr.function
  947. if result == 0:
  948. return S.Zero
  949. limits = expr.limits
  950. # get the wrt variables
  951. wrt = {i.args[0] for i in limits}
  952. # factor out any common terms that are independent of wrt
  953. f = factor_terms(result, **kwargs)
  954. i, d = f.as_independent(*wrt)
  955. if isinstance(f, Add):
  956. return i * expr.func(1, *limits) + expr.func(d, *limits)
  957. else:
  958. return i * expr.func(d, *limits)
  959. def factor_terms(expr, radical=False, clear=False, fraction=False, sign=True):
  960. """Remove common factors from terms in all arguments without
  961. changing the underlying structure of the expr. No expansion or
  962. simplification (and no processing of non-commutatives) is performed.
  963. Parameters
  964. ==========
  965. radical: bool, optional
  966. If radical=True then a radical common to all terms will be factored
  967. out of any Add sub-expressions of the expr.
  968. clear : bool, optional
  969. If clear=False (default) then coefficients will not be separated
  970. from a single Add if they can be distributed to leave one or more
  971. terms with integer coefficients.
  972. fraction : bool, optional
  973. If fraction=True (default is False) then a common denominator will be
  974. constructed for the expression.
  975. sign : bool, optional
  976. If sign=True (default) then even if the only factor in common is a -1,
  977. it will be factored out of the expression.
  978. Examples
  979. ========
  980. >>> from sympy import factor_terms, Symbol
  981. >>> from sympy.abc import x, y
  982. >>> factor_terms(x + x*(2 + 4*y)**3)
  983. x*(8*(2*y + 1)**3 + 1)
  984. >>> A = Symbol('A', commutative=False)
  985. >>> factor_terms(x*A + x*A + x*y*A)
  986. x*(y*A + 2*A)
  987. When ``clear`` is False, a rational will only be factored out of an
  988. Add expression if all terms of the Add have coefficients that are
  989. fractions:
  990. >>> factor_terms(x/2 + 1, clear=False)
  991. x/2 + 1
  992. >>> factor_terms(x/2 + 1, clear=True)
  993. (x + 2)/2
  994. If a -1 is all that can be factored out, to *not* factor it out, the
  995. flag ``sign`` must be False:
  996. >>> factor_terms(-x - y)
  997. -(x + y)
  998. >>> factor_terms(-x - y, sign=False)
  999. -x - y
  1000. >>> factor_terms(-2*x - 2*y, sign=False)
  1001. -2*(x + y)
  1002. See Also
  1003. ========
  1004. gcd_terms, sympy.polys.polytools.terms_gcd
  1005. """
  1006. def do(expr):
  1007. from sympy.concrete.summations import Sum
  1008. from sympy.integrals.integrals import Integral
  1009. is_iterable = iterable(expr)
  1010. if not isinstance(expr, Basic) or expr.is_Atom:
  1011. if is_iterable:
  1012. return type(expr)([do(i) for i in expr])
  1013. return expr
  1014. if expr.is_Pow or expr.is_Function or \
  1015. is_iterable or not hasattr(expr, 'args_cnc'):
  1016. args = expr.args
  1017. newargs = tuple([do(i) for i in args])
  1018. if newargs == args:
  1019. return expr
  1020. return expr.func(*newargs)
  1021. if isinstance(expr, (Sum, Integral)):
  1022. return _factor_sum_int(expr,
  1023. radical=radical, clear=clear,
  1024. fraction=fraction, sign=sign)
  1025. cont, p = expr.as_content_primitive(radical=radical, clear=clear)
  1026. if p.is_Add:
  1027. list_args = [do(a) for a in Add.make_args(p)]
  1028. # get a common negative (if there) which gcd_terms does not remove
  1029. if not any(a.as_coeff_Mul()[0].extract_multiplicatively(-1) is None
  1030. for a in list_args):
  1031. cont = -cont
  1032. list_args = [-a for a in list_args]
  1033. # watch out for exp(-(x+2)) which gcd_terms will change to exp(-x-2)
  1034. special = {}
  1035. for i, a in enumerate(list_args):
  1036. b, e = a.as_base_exp()
  1037. if e.is_Mul and e != Mul(*e.args):
  1038. list_args[i] = Dummy()
  1039. special[list_args[i]] = a
  1040. # rebuild p not worrying about the order which gcd_terms will fix
  1041. p = Add._from_args(list_args)
  1042. p = gcd_terms(p,
  1043. isprimitive=True,
  1044. clear=clear,
  1045. fraction=fraction).xreplace(special)
  1046. elif p.args:
  1047. p = p.func(
  1048. *[do(a) for a in p.args])
  1049. rv = _keep_coeff(cont, p, clear=clear, sign=sign)
  1050. return rv
  1051. expr = sympify(expr)
  1052. return do(expr)
  1053. def _mask_nc(eq, name=None):
  1054. """
  1055. Return ``eq`` with non-commutative objects replaced with Dummy
  1056. symbols. A dictionary that can be used to restore the original
  1057. values is returned: if it is None, the expression is noncommutative
  1058. and cannot be made commutative. The third value returned is a list
  1059. of any non-commutative symbols that appear in the returned equation.
  1060. Explanation
  1061. ===========
  1062. All non-commutative objects other than Symbols are replaced with
  1063. a non-commutative Symbol. Identical objects will be identified
  1064. by identical symbols.
  1065. If there is only 1 non-commutative object in an expression it will
  1066. be replaced with a commutative symbol. Otherwise, the non-commutative
  1067. entities are retained and the calling routine should handle
  1068. replacements in this case since some care must be taken to keep
  1069. track of the ordering of symbols when they occur within Muls.
  1070. Parameters
  1071. ==========
  1072. name : str
  1073. ``name``, if given, is the name that will be used with numbered Dummy
  1074. variables that will replace the non-commutative objects and is mainly
  1075. used for doctesting purposes.
  1076. Examples
  1077. ========
  1078. >>> from sympy.physics.secondquant import Commutator, NO, F, Fd
  1079. >>> from sympy import symbols
  1080. >>> from sympy.core.exprtools import _mask_nc
  1081. >>> from sympy.abc import x, y
  1082. >>> A, B, C = symbols('A,B,C', commutative=False)
  1083. One nc-symbol:
  1084. >>> _mask_nc(A**2 - x**2, 'd')
  1085. (_d0**2 - x**2, {_d0: A}, [])
  1086. Multiple nc-symbols:
  1087. >>> _mask_nc(A**2 - B**2, 'd')
  1088. (A**2 - B**2, {}, [A, B])
  1089. An nc-object with nc-symbols but no others outside of it:
  1090. >>> _mask_nc(1 + x*Commutator(A, B), 'd')
  1091. (_d0*x + 1, {_d0: Commutator(A, B)}, [])
  1092. >>> _mask_nc(NO(Fd(x)*F(y)), 'd')
  1093. (_d0, {_d0: NO(CreateFermion(x)*AnnihilateFermion(y))}, [])
  1094. Multiple nc-objects:
  1095. >>> eq = x*Commutator(A, B) + x*Commutator(A, C)*Commutator(A, B)
  1096. >>> _mask_nc(eq, 'd')
  1097. (x*_d0 + x*_d1*_d0, {_d0: Commutator(A, B), _d1: Commutator(A, C)}, [_d0, _d1])
  1098. Multiple nc-objects and nc-symbols:
  1099. >>> eq = A*Commutator(A, B) + B*Commutator(A, C)
  1100. >>> _mask_nc(eq, 'd')
  1101. (A*_d0 + B*_d1, {_d0: Commutator(A, B), _d1: Commutator(A, C)}, [_d0, _d1, A, B])
  1102. """
  1103. name = name or 'mask'
  1104. # Make Dummy() append sequential numbers to the name
  1105. def numbered_names():
  1106. i = 0
  1107. while True:
  1108. yield name + str(i)
  1109. i += 1
  1110. names = numbered_names()
  1111. def Dummy(*args, **kwargs):
  1112. from .symbol import Dummy
  1113. return Dummy(next(names), *args, **kwargs)
  1114. expr = eq
  1115. if expr.is_commutative:
  1116. return eq, {}, []
  1117. # identify nc-objects; symbols and other
  1118. rep = []
  1119. nc_obj = set()
  1120. nc_syms = set()
  1121. pot = preorder_traversal(expr, keys=default_sort_key)
  1122. for i, a in enumerate(pot):
  1123. if any(a == r[0] for r in rep):
  1124. pot.skip()
  1125. elif not a.is_commutative:
  1126. if a.is_symbol:
  1127. nc_syms.add(a)
  1128. pot.skip()
  1129. elif not (a.is_Add or a.is_Mul or a.is_Pow):
  1130. nc_obj.add(a)
  1131. pot.skip()
  1132. # If there is only one nc symbol or object, it can be factored regularly
  1133. # but polys is going to complain, so replace it with a Dummy.
  1134. if len(nc_obj) == 1 and not nc_syms:
  1135. rep.append((nc_obj.pop(), Dummy()))
  1136. elif len(nc_syms) == 1 and not nc_obj:
  1137. rep.append((nc_syms.pop(), Dummy()))
  1138. # Any remaining nc-objects will be replaced with an nc-Dummy and
  1139. # identified as an nc-Symbol to watch out for
  1140. nc_obj = sorted(nc_obj, key=default_sort_key)
  1141. for n in nc_obj:
  1142. nc = Dummy(commutative=False)
  1143. rep.append((n, nc))
  1144. nc_syms.add(nc)
  1145. expr = expr.subs(rep)
  1146. nc_syms = list(nc_syms)
  1147. nc_syms.sort(key=default_sort_key)
  1148. return expr, {v: k for k, v in rep}, nc_syms
  1149. def factor_nc(expr):
  1150. """Return the factored form of ``expr`` while handling non-commutative
  1151. expressions.
  1152. Examples
  1153. ========
  1154. >>> from sympy import factor_nc, Symbol
  1155. >>> from sympy.abc import x
  1156. >>> A = Symbol('A', commutative=False)
  1157. >>> B = Symbol('B', commutative=False)
  1158. >>> factor_nc((x**2 + 2*A*x + A**2).expand())
  1159. (x + A)**2
  1160. >>> factor_nc(((x + A)*(x + B)).expand())
  1161. (x + A)*(x + B)
  1162. """
  1163. expr = sympify(expr)
  1164. if not isinstance(expr, Expr) or not expr.args:
  1165. return expr
  1166. if not expr.is_Add:
  1167. return expr.func(*[factor_nc(a) for a in expr.args])
  1168. expr = expr.func(*[expand_power_exp(i) for i in expr.args])
  1169. from sympy.polys.polytools import gcd, factor
  1170. expr, rep, nc_symbols = _mask_nc(expr)
  1171. if rep:
  1172. return factor(expr).subs(rep)
  1173. else:
  1174. args = [a.args_cnc() for a in Add.make_args(expr)]
  1175. c = g = l = r = S.One
  1176. hit = False
  1177. # find any commutative gcd term
  1178. for i, a in enumerate(args):
  1179. if i == 0:
  1180. c = Mul._from_args(a[0])
  1181. elif a[0]:
  1182. c = gcd(c, Mul._from_args(a[0]))
  1183. else:
  1184. c = S.One
  1185. if c is not S.One:
  1186. hit = True
  1187. c, g = c.as_coeff_Mul()
  1188. if g is not S.One:
  1189. for i, (cc, _) in enumerate(args):
  1190. cc = list(Mul.make_args(Mul._from_args(list(cc))/g))
  1191. args[i][0] = cc
  1192. for i, (cc, _) in enumerate(args):
  1193. if cc:
  1194. cc[0] = cc[0]/c
  1195. else:
  1196. cc = [1/c]
  1197. args[i][0] = cc
  1198. # find any noncommutative common prefix
  1199. for i, a in enumerate(args):
  1200. if i == 0:
  1201. n = a[1][:]
  1202. else:
  1203. n = common_prefix(n, a[1])
  1204. if not n:
  1205. # is there a power that can be extracted?
  1206. if not args[0][1]:
  1207. break
  1208. b, e = args[0][1][0].as_base_exp()
  1209. ok = False
  1210. if e.is_Integer:
  1211. for t in args:
  1212. if not t[1]:
  1213. break
  1214. bt, et = t[1][0].as_base_exp()
  1215. if et.is_Integer and bt == b:
  1216. e = min(e, et)
  1217. else:
  1218. break
  1219. else:
  1220. ok = hit = True
  1221. l = b**e
  1222. il = b**-e
  1223. for _ in args:
  1224. _[1][0] = il*_[1][0]
  1225. break
  1226. if not ok:
  1227. break
  1228. else:
  1229. hit = True
  1230. lenn = len(n)
  1231. l = Mul(*n)
  1232. for _ in args:
  1233. _[1] = _[1][lenn:]
  1234. # find any noncommutative common suffix
  1235. for i, a in enumerate(args):
  1236. if i == 0:
  1237. n = a[1][:]
  1238. else:
  1239. n = common_suffix(n, a[1])
  1240. if not n:
  1241. # is there a power that can be extracted?
  1242. if not args[0][1]:
  1243. break
  1244. b, e = args[0][1][-1].as_base_exp()
  1245. ok = False
  1246. if e.is_Integer:
  1247. for t in args:
  1248. if not t[1]:
  1249. break
  1250. bt, et = t[1][-1].as_base_exp()
  1251. if et.is_Integer and bt == b:
  1252. e = min(e, et)
  1253. else:
  1254. break
  1255. else:
  1256. ok = hit = True
  1257. r = b**e
  1258. il = b**-e
  1259. for _ in args:
  1260. _[1][-1] = _[1][-1]*il
  1261. break
  1262. if not ok:
  1263. break
  1264. else:
  1265. hit = True
  1266. lenn = len(n)
  1267. r = Mul(*n)
  1268. for _ in args:
  1269. _[1] = _[1][:len(_[1]) - lenn]
  1270. if hit:
  1271. mid = Add(*[Mul(*cc)*Mul(*nc) for cc, nc in args])
  1272. else:
  1273. mid = expr
  1274. from sympy.simplify.powsimp import powsimp
  1275. # sort the symbols so the Dummys would appear in the same
  1276. # order as the original symbols, otherwise you may introduce
  1277. # a factor of -1, e.g. A**2 - B**2) -- {A:y, B:x} --> y**2 - x**2
  1278. # and the former factors into two terms, (A - B)*(A + B) while the
  1279. # latter factors into 3 terms, (-1)*(x - y)*(x + y)
  1280. rep1 = [(n, Dummy()) for n in sorted(nc_symbols, key=default_sort_key)]
  1281. unrep1 = [(v, k) for k, v in rep1]
  1282. unrep1.reverse()
  1283. new_mid, r2, _ = _mask_nc(mid.subs(rep1))
  1284. new_mid = powsimp(factor(new_mid))
  1285. new_mid = new_mid.subs(r2).subs(unrep1)
  1286. if new_mid.is_Pow:
  1287. return _keep_coeff(c, g*l*new_mid*r)
  1288. if new_mid.is_Mul:
  1289. def _pemexpand(expr):
  1290. "Expand with the minimal set of hints necessary to check the result."
  1291. return expr.expand(deep=True, mul=True, power_exp=True,
  1292. power_base=False, basic=False, multinomial=True, log=False)
  1293. # XXX TODO there should be a way to inspect what order the terms
  1294. # must be in and just select the plausible ordering without
  1295. # checking permutations
  1296. cfac = []
  1297. ncfac = []
  1298. for f in new_mid.args:
  1299. if f.is_commutative:
  1300. cfac.append(f)
  1301. else:
  1302. b, e = f.as_base_exp()
  1303. if e.is_Integer:
  1304. ncfac.extend([b]*e)
  1305. else:
  1306. ncfac.append(f)
  1307. pre_mid = g*Mul(*cfac)*l
  1308. target = _pemexpand(expr/c)
  1309. for s in variations(ncfac, len(ncfac)):
  1310. ok = pre_mid*Mul(*s)*r
  1311. if _pemexpand(ok) == target:
  1312. return _keep_coeff(c, ok)
  1313. # mid was an Add that didn't factor successfully
  1314. return _keep_coeff(c, g*l*mid*r)