solvers.py 135 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674
  1. """
  2. This module contain solvers for all kinds of equations:
  3. - algebraic or transcendental, use solve()
  4. - recurrence, use rsolve()
  5. - differential, use dsolve()
  6. - nonlinear (numerically), use nsolve()
  7. (you will need a good starting point)
  8. """
  9. from __future__ import annotations
  10. from sympy.core import (S, Add, Symbol, Dummy, Expr, Mul)
  11. from sympy.core.assumptions import check_assumptions
  12. from sympy.core.exprtools import factor_terms
  13. from sympy.core.function import (expand_mul, expand_log, Derivative,
  14. AppliedUndef, UndefinedFunction, nfloat,
  15. Function, expand_power_exp, _mexpand, expand,
  16. expand_func)
  17. from sympy.core.logic import fuzzy_not, fuzzy_and
  18. from sympy.core.numbers import Float, Rational, _illegal
  19. from sympy.core.intfunc import integer_log, ilcm
  20. from sympy.core.power import Pow
  21. from sympy.core.relational import Eq, Ne
  22. from sympy.core.sorting import ordered, default_sort_key
  23. from sympy.core.sympify import sympify, _sympify
  24. from sympy.core.traversal import preorder_traversal
  25. from sympy.logic.boolalg import And, BooleanAtom
  26. from sympy.functions import (log, exp, LambertW, cos, sin, tan, acos, asin, atan,
  27. Abs, re, im, arg, sqrt, atan2)
  28. from sympy.functions.combinatorial.factorials import binomial
  29. from sympy.functions.elementary.hyperbolic import HyperbolicFunction
  30. from sympy.functions.elementary.piecewise import piecewise_fold, Piecewise
  31. from sympy.functions.elementary.trigonometric import TrigonometricFunction
  32. from sympy.integrals.integrals import Integral
  33. from sympy.ntheory.factor_ import divisors
  34. from sympy.simplify import (simplify, collect, powsimp, posify, # type: ignore
  35. powdenest, nsimplify, denom, logcombine, sqrtdenest, fraction,
  36. separatevars)
  37. from sympy.simplify.sqrtdenest import sqrt_depth
  38. from sympy.simplify.fu import TR1, TR2i, TR10, TR11
  39. from sympy.strategies.rl import rebuild
  40. from sympy.matrices.exceptions import NonInvertibleMatrixError
  41. from sympy.matrices import Matrix, zeros
  42. from sympy.polys import roots, cancel, factor, Poly
  43. from sympy.polys.solvers import sympy_eqs_to_ring, solve_lin_sys
  44. from sympy.polys.polyerrors import GeneratorsNeeded, PolynomialError
  45. from sympy.polys.polytools import gcd
  46. from sympy.utilities.lambdify import lambdify
  47. from sympy.utilities.misc import filldedent, debugf
  48. from sympy.utilities.iterables import (connected_components,
  49. generate_bell, uniq, iterable, is_sequence, subsets, flatten, sift)
  50. from sympy.utilities.decorator import conserve_mpmath_dps
  51. from mpmath import findroot
  52. from sympy.solvers.polysys import solve_poly_system
  53. from types import GeneratorType
  54. from collections import defaultdict
  55. from itertools import combinations, product
  56. import warnings
  57. def recast_to_symbols(eqs, symbols):
  58. """
  59. Return (e, s, d) where e and s are versions of *eqs* and
  60. *symbols* in which any non-Symbol objects in *symbols* have
  61. been replaced with generic Dummy symbols and d is a dictionary
  62. that can be used to restore the original expressions.
  63. Examples
  64. ========
  65. >>> from sympy.solvers.solvers import recast_to_symbols
  66. >>> from sympy import symbols, Function
  67. >>> x, y = symbols('x y')
  68. >>> fx = Function('f')(x)
  69. >>> eqs, syms = [fx + 1, x, y], [fx, y]
  70. >>> e, s, d = recast_to_symbols(eqs, syms); (e, s, d)
  71. ([_X0 + 1, x, y], [_X0, y], {_X0: f(x)})
  72. The original equations and symbols can be restored using d:
  73. >>> assert [i.xreplace(d) for i in eqs] == eqs
  74. >>> assert [d.get(i, i) for i in s] == syms
  75. """
  76. if not iterable(eqs) and iterable(symbols):
  77. raise ValueError('Both eqs and symbols must be iterable')
  78. orig = list(symbols)
  79. symbols = list(ordered(symbols))
  80. swap_sym = {}
  81. i = 0
  82. for s in symbols:
  83. if not isinstance(s, Symbol) and s not in swap_sym:
  84. swap_sym[s] = Dummy('X%d' % i)
  85. i += 1
  86. new_f = []
  87. for i in eqs:
  88. isubs = getattr(i, 'subs', None)
  89. if isubs is not None:
  90. new_f.append(isubs(swap_sym))
  91. else:
  92. new_f.append(i)
  93. restore = {v: k for k, v in swap_sym.items()}
  94. return new_f, [swap_sym.get(i, i) for i in orig], restore
  95. def _ispow(e):
  96. """Return True if e is a Pow or is exp."""
  97. return isinstance(e, Expr) and (e.is_Pow or isinstance(e, exp))
  98. def _simple_dens(f, symbols):
  99. # when checking if a denominator is zero, we can just check the
  100. # base of powers with nonzero exponents since if the base is zero
  101. # the power will be zero, too. To keep it simple and fast, we
  102. # limit simplification to exponents that are Numbers
  103. dens = set()
  104. for d in denoms(f, symbols):
  105. if d.is_Pow and d.exp.is_Number:
  106. if d.exp.is_zero:
  107. continue # foo**0 is never 0
  108. d = d.base
  109. dens.add(d)
  110. return dens
  111. def denoms(eq, *symbols):
  112. """
  113. Return (recursively) set of all denominators that appear in *eq*
  114. that contain any symbol in *symbols*; if *symbols* are not
  115. provided then all denominators will be returned.
  116. Examples
  117. ========
  118. >>> from sympy.solvers.solvers import denoms
  119. >>> from sympy.abc import x, y, z
  120. >>> denoms(x/y)
  121. {y}
  122. >>> denoms(x/(y*z))
  123. {y, z}
  124. >>> denoms(3/x + y/z)
  125. {x, z}
  126. >>> denoms(x/2 + y/z)
  127. {2, z}
  128. If *symbols* are provided then only denominators containing
  129. those symbols will be returned:
  130. >>> denoms(1/x + 1/y + 1/z, y, z)
  131. {y, z}
  132. """
  133. pot = preorder_traversal(eq)
  134. dens = set()
  135. for p in pot:
  136. # Here p might be Tuple or Relational
  137. # Expr subtrees (e.g. lhs and rhs) will be traversed after by pot
  138. if not isinstance(p, Expr):
  139. continue
  140. den = denom(p)
  141. if den is S.One:
  142. continue
  143. dens.update(Mul.make_args(den))
  144. if not symbols:
  145. return dens
  146. elif len(symbols) == 1:
  147. if iterable(symbols[0]):
  148. symbols = symbols[0]
  149. return {d for d in dens if any(s in d.free_symbols for s in symbols)}
  150. def checksol(f, symbol, sol=None, **flags):
  151. """
  152. Checks whether sol is a solution of equation f == 0.
  153. Explanation
  154. ===========
  155. Input can be either a single symbol and corresponding value
  156. or a dictionary of symbols and values. When given as a dictionary
  157. and flag ``simplify=True``, the values in the dictionary will be
  158. simplified. *f* can be a single equation or an iterable of equations.
  159. A solution must satisfy all equations in *f* to be considered valid;
  160. if a solution does not satisfy any equation, False is returned; if one or
  161. more checks are inconclusive (and none are False) then None is returned.
  162. Examples
  163. ========
  164. >>> from sympy import checksol, symbols
  165. >>> x, y = symbols('x,y')
  166. >>> checksol(x**4 - 1, x, 1)
  167. True
  168. >>> checksol(x**4 - 1, x, 0)
  169. False
  170. >>> checksol(x**2 + y**2 - 5**2, {x: 3, y: 4})
  171. True
  172. To check if an expression is zero using ``checksol()``, pass it
  173. as *f* and send an empty dictionary for *symbol*:
  174. >>> checksol(x**2 + x - x*(x + 1), {})
  175. True
  176. None is returned if ``checksol()`` could not conclude.
  177. flags:
  178. 'numerical=True (default)'
  179. do a fast numerical check if ``f`` has only one symbol.
  180. 'minimal=True (default is False)'
  181. a very fast, minimal testing.
  182. 'warn=True (default is False)'
  183. show a warning if checksol() could not conclude.
  184. 'simplify=True (default)'
  185. simplify solution before substituting into function and
  186. simplify the function before trying specific simplifications
  187. 'force=True (default is False)'
  188. make positive all symbols without assumptions regarding sign.
  189. """
  190. from sympy.physics.units import Unit
  191. minimal = flags.get('minimal', False)
  192. if sol is not None:
  193. sol = {symbol: sol}
  194. elif isinstance(symbol, dict):
  195. sol = symbol
  196. else:
  197. msg = 'Expecting (sym, val) or ({sym: val}, None) but got (%s, %s)'
  198. raise ValueError(msg % (symbol, sol))
  199. if iterable(f):
  200. if not f:
  201. raise ValueError('no functions to check')
  202. return fuzzy_and(checksol(fi, sol, **flags) for fi in f)
  203. f = _sympify(f)
  204. if f.is_number:
  205. return f.is_zero
  206. if isinstance(f, Poly):
  207. f = f.as_expr()
  208. elif isinstance(f, (Eq, Ne)):
  209. if f.rhs in (S.true, S.false):
  210. f = f.reversed
  211. B, E = f.args
  212. if isinstance(B, BooleanAtom):
  213. f = f.subs(sol)
  214. if not f.is_Boolean:
  215. return
  216. elif isinstance(f, Eq):
  217. f = Add(f.lhs, -f.rhs, evaluate=False)
  218. if isinstance(f, BooleanAtom):
  219. return bool(f)
  220. elif not f.is_Relational and not f:
  221. return True
  222. illegal = set(_illegal)
  223. if any(sympify(v).atoms() & illegal for k, v in sol.items()):
  224. return False
  225. attempt = -1
  226. numerical = flags.get('numerical', True)
  227. while 1:
  228. attempt += 1
  229. if attempt == 0:
  230. val = f.subs(sol)
  231. if isinstance(val, Mul):
  232. val = val.as_independent(Unit)[0]
  233. if val.atoms() & illegal:
  234. return False
  235. elif attempt == 1:
  236. if not val.is_number:
  237. if not val.is_constant(*list(sol.keys()), simplify=not minimal):
  238. return False
  239. # there are free symbols -- simple expansion might work
  240. _, val = val.as_content_primitive()
  241. val = _mexpand(val.as_numer_denom()[0], recursive=True)
  242. elif attempt == 2:
  243. if minimal:
  244. return
  245. if flags.get('simplify', True):
  246. for k in sol:
  247. sol[k] = simplify(sol[k])
  248. # start over without the failed expanded form, possibly
  249. # with a simplified solution
  250. val = simplify(f.subs(sol))
  251. if flags.get('force', True):
  252. val, reps = posify(val)
  253. # expansion may work now, so try again and check
  254. exval = _mexpand(val, recursive=True)
  255. if exval.is_number:
  256. # we can decide now
  257. val = exval
  258. else:
  259. # if there are no radicals and no functions then this can't be
  260. # zero anymore -- can it?
  261. pot = preorder_traversal(expand_mul(val))
  262. seen = set()
  263. saw_pow_func = False
  264. for p in pot:
  265. if p in seen:
  266. continue
  267. seen.add(p)
  268. if p.is_Pow and not p.exp.is_Integer:
  269. saw_pow_func = True
  270. elif p.is_Function:
  271. saw_pow_func = True
  272. elif isinstance(p, UndefinedFunction):
  273. saw_pow_func = True
  274. if saw_pow_func:
  275. break
  276. if saw_pow_func is False:
  277. return False
  278. if flags.get('force', True):
  279. # don't do a zero check with the positive assumptions in place
  280. val = val.subs(reps)
  281. nz = fuzzy_not(val.is_zero)
  282. if nz is not None:
  283. # issue 5673: nz may be True even when False
  284. # so these are just hacks to keep a false positive
  285. # from being returned
  286. # HACK 1: LambertW (issue 5673)
  287. if val.is_number and val.has(LambertW):
  288. # don't eval this to verify solution since if we got here,
  289. # numerical must be False
  290. return None
  291. # add other HACKs here if necessary, otherwise we assume
  292. # the nz value is correct
  293. return not nz
  294. break
  295. if val.is_Rational:
  296. return val == 0
  297. if numerical and val.is_number:
  298. return (abs(val.n(18).n(12, chop=True)) < 1e-9) is S.true
  299. if flags.get('warn', False):
  300. warnings.warn("\n\tWarning: could not verify solution %s." % sol)
  301. # returns None if it can't conclude
  302. # TODO: improve solution testing
  303. def solve(f, *symbols, **flags):
  304. r"""
  305. Algebraically solves equations and systems of equations.
  306. Explanation
  307. ===========
  308. Currently supported:
  309. - polynomial
  310. - transcendental
  311. - piecewise combinations of the above
  312. - systems of linear and polynomial equations
  313. - systems containing relational expressions
  314. - systems implied by undetermined coefficients
  315. Examples
  316. ========
  317. The default output varies according to the input and might
  318. be a list (possibly empty), a dictionary, a list of
  319. dictionaries or tuples, or an expression involving relationals.
  320. For specifics regarding different forms of output that may appear, see :ref:`solve_output`.
  321. Let it suffice here to say that to obtain a uniform output from
  322. `solve` use ``dict=True`` or ``set=True`` (see below).
  323. >>> from sympy import solve, Poly, Eq, Matrix, Symbol
  324. >>> from sympy.abc import x, y, z, a, b
  325. The expressions that are passed can be Expr, Equality, or Poly
  326. classes (or lists of the same); a Matrix is considered to be a
  327. list of all the elements of the matrix:
  328. >>> solve(x - 3, x)
  329. [3]
  330. >>> solve(Eq(x, 3), x)
  331. [3]
  332. >>> solve(Poly(x - 3), x)
  333. [3]
  334. >>> solve(Matrix([[x, x + y]]), x, y) == solve([x, x + y], x, y)
  335. True
  336. If no symbols are indicated to be of interest and the equation is
  337. univariate, a list of values is returned; otherwise, the keys in
  338. a dictionary will indicate which (of all the variables used in
  339. the expression(s)) variables and solutions were found:
  340. >>> solve(x**2 - 4)
  341. [-2, 2]
  342. >>> solve((x - a)*(y - b))
  343. [{a: x}, {b: y}]
  344. >>> solve([x - 3, y - 1])
  345. {x: 3, y: 1}
  346. >>> solve([x - 3, y**2 - 1])
  347. [{x: 3, y: -1}, {x: 3, y: 1}]
  348. If you pass symbols for which solutions are sought, the output will vary
  349. depending on the number of symbols you passed, whether you are passing
  350. a list of expressions or not, and whether a linear system was solved.
  351. Uniform output is attained by using ``dict=True`` or ``set=True``.
  352. >>> #### *** feel free to skip to the stars below *** ####
  353. >>> from sympy import TableForm
  354. >>> h = [None, ';|;'.join(['e', 's', 'solve(e, s)', 'solve(e, s, dict=True)',
  355. ... 'solve(e, s, set=True)']).split(';')]
  356. >>> t = []
  357. >>> for e, s in [
  358. ... (x - y, y),
  359. ... (x - y, [x, y]),
  360. ... (x**2 - y, [x, y]),
  361. ... ([x - 3, y -1], [x, y]),
  362. ... ]:
  363. ... how = [{}, dict(dict=True), dict(set=True)]
  364. ... res = [solve(e, s, **f) for f in how]
  365. ... t.append([e, '|', s, '|'] + [res[0], '|', res[1], '|', res[2]])
  366. ...
  367. >>> # ******************************************************* #
  368. >>> TableForm(t, headings=h, alignments="<")
  369. e | s | solve(e, s) | solve(e, s, dict=True) | solve(e, s, set=True)
  370. ---------------------------------------------------------------------------------------
  371. x - y | y | [x] | [{y: x}] | ([y], {(x,)})
  372. x - y | [x, y] | [(y, y)] | [{x: y}] | ([x, y], {(y, y)})
  373. x**2 - y | [x, y] | [(x, x**2)] | [{y: x**2}] | ([x, y], {(x, x**2)})
  374. [x - 3, y - 1] | [x, y] | {x: 3, y: 1} | [{x: 3, y: 1}] | ([x, y], {(3, 1)})
  375. * If any equation does not depend on the symbol(s) given, it will be
  376. eliminated from the equation set and an answer may be given
  377. implicitly in terms of variables that were not of interest:
  378. >>> solve([x - y, y - 3], x)
  379. {x: y}
  380. When you pass all but one of the free symbols, an attempt
  381. is made to find a single solution based on the method of
  382. undetermined coefficients. If it succeeds, a dictionary of values
  383. is returned. If you want an algebraic solutions for one
  384. or more of the symbols, pass the expression to be solved in a list:
  385. >>> e = a*x + b - 2*x - 3
  386. >>> solve(e, [a, b])
  387. {a: 2, b: 3}
  388. >>> solve([e], [a, b])
  389. {a: -b/x + (2*x + 3)/x}
  390. When there is no solution for any given symbol which will make all
  391. expressions zero, the empty list is returned (or an empty set in
  392. the tuple when ``set=True``):
  393. >>> from sympy import sqrt
  394. >>> solve(3, x)
  395. []
  396. >>> solve(x - 3, y)
  397. []
  398. >>> solve(sqrt(x) + 1, x, set=True)
  399. ([x], set())
  400. When an object other than a Symbol is given as a symbol, it is
  401. isolated algebraically and an implicit solution may be obtained.
  402. This is mostly provided as a convenience to save you from replacing
  403. the object with a Symbol and solving for that Symbol. It will only
  404. work if the specified object can be replaced with a Symbol using the
  405. subs method:
  406. >>> from sympy import exp, Function
  407. >>> f = Function('f')
  408. >>> solve(f(x) - x, f(x))
  409. [x]
  410. >>> solve(f(x).diff(x) - f(x) - x, f(x).diff(x))
  411. [x + f(x)]
  412. >>> solve(f(x).diff(x) - f(x) - x, f(x))
  413. [-x + Derivative(f(x), x)]
  414. >>> solve(x + exp(x)**2, exp(x), set=True)
  415. ([exp(x)], {(-sqrt(-x),), (sqrt(-x),)})
  416. >>> from sympy import Indexed, IndexedBase, Tuple
  417. >>> A = IndexedBase('A')
  418. >>> eqs = Tuple(A[1] + A[2] - 3, A[1] - A[2] + 1)
  419. >>> solve(eqs, eqs.atoms(Indexed))
  420. {A[1]: 1, A[2]: 2}
  421. * To solve for a function within a derivative, use :func:`~.dsolve`.
  422. To solve for a symbol implicitly, use implicit=True:
  423. >>> solve(x + exp(x), x)
  424. [-LambertW(1)]
  425. >>> solve(x + exp(x), x, implicit=True)
  426. [-exp(x)]
  427. It is possible to solve for anything in an expression that can be
  428. replaced with a symbol using :obj:`~sympy.core.basic.Basic.subs`:
  429. >>> solve(x + 2 + sqrt(3), x + 2)
  430. [-sqrt(3)]
  431. >>> solve((x + 2 + sqrt(3), x + 4 + y), y, x + 2)
  432. {y: -2 + sqrt(3), x + 2: -sqrt(3)}
  433. * Nothing heroic is done in this implicit solving so you may end up
  434. with a symbol still in the solution:
  435. >>> eqs = (x*y + 3*y + sqrt(3), x + 4 + y)
  436. >>> solve(eqs, y, x + 2)
  437. {y: -sqrt(3)/(x + 3), x + 2: -2*x/(x + 3) - 6/(x + 3) + sqrt(3)/(x + 3)}
  438. >>> solve(eqs, y*x, x)
  439. {x: -y - 4, x*y: -3*y - sqrt(3)}
  440. * If you attempt to solve for a number, remember that the number
  441. you have obtained does not necessarily mean that the value is
  442. equivalent to the expression obtained:
  443. >>> solve(sqrt(2) - 1, 1)
  444. [sqrt(2)]
  445. >>> solve(x - y + 1, 1) # /!\ -1 is targeted, too
  446. [x/(y - 1)]
  447. >>> [_.subs(z, -1) for _ in solve((x - y + 1).subs(-1, z), 1)]
  448. [-x + y]
  449. **Additional Examples**
  450. ``solve()`` with check=True (default) will run through the symbol tags to
  451. eliminate unwanted solutions. If no assumptions are included, all possible
  452. solutions will be returned:
  453. >>> x = Symbol("x")
  454. >>> solve(x**2 - 1)
  455. [-1, 1]
  456. By setting the ``positive`` flag, only one solution will be returned:
  457. >>> pos = Symbol("pos", positive=True)
  458. >>> solve(pos**2 - 1)
  459. [1]
  460. When the solutions are checked, those that make any denominator zero
  461. are automatically excluded. If you do not want to exclude such solutions,
  462. then use the check=False option:
  463. >>> from sympy import sin, limit
  464. >>> solve(sin(x)/x) # 0 is excluded
  465. [pi]
  466. If ``check=False``, then a solution to the numerator being zero is found
  467. but the value of $x = 0$ is a spurious solution since $\sin(x)/x$ has the well
  468. known limit (without discontinuity) of 1 at $x = 0$:
  469. >>> solve(sin(x)/x, check=False)
  470. [0, pi]
  471. In the following case, however, the limit exists and is equal to the
  472. value of $x = 0$ that is excluded when check=True:
  473. >>> eq = x**2*(1/x - z**2/x)
  474. >>> solve(eq, x)
  475. []
  476. >>> solve(eq, x, check=False)
  477. [0]
  478. >>> limit(eq, x, 0, '-')
  479. 0
  480. >>> limit(eq, x, 0, '+')
  481. 0
  482. **Solving Relationships**
  483. When one or more expressions passed to ``solve`` is a relational,
  484. a relational result is returned (and the ``dict`` and ``set`` flags
  485. are ignored):
  486. >>> solve(x < 3)
  487. (-oo < x) & (x < 3)
  488. >>> solve([x < 3, x**2 > 4], x)
  489. ((-oo < x) & (x < -2)) | ((2 < x) & (x < 3))
  490. >>> solve([x + y - 3, x > 3], x)
  491. (3 < x) & (x < oo) & Eq(x, 3 - y)
  492. Although checking of assumptions on symbols in relationals
  493. is not done, setting assumptions will affect how certain
  494. relationals might automatically simplify:
  495. >>> solve(x**2 > 4)
  496. ((-oo < x) & (x < -2)) | ((2 < x) & (x < oo))
  497. >>> r = Symbol('r', real=True)
  498. >>> solve(r**2 > 4)
  499. (2 < r) | (r < -2)
  500. There is currently no algorithm in SymPy that allows you to use
  501. relationships to resolve more than one variable. So the following
  502. does not determine that ``q < 0`` (and trying to solve for ``r``
  503. and ``q`` will raise an error):
  504. >>> from sympy import symbols
  505. >>> r, q = symbols('r, q', real=True)
  506. >>> solve([r + q - 3, r > 3], r)
  507. (3 < r) & Eq(r, 3 - q)
  508. You can directly call the routine that ``solve`` calls
  509. when it encounters a relational: :func:`~.reduce_inequalities`.
  510. It treats Expr like Equality.
  511. >>> from sympy import reduce_inequalities
  512. >>> reduce_inequalities([x**2 - 4])
  513. Eq(x, -2) | Eq(x, 2)
  514. If each relationship contains only one symbol of interest,
  515. the expressions can be processed for multiple symbols:
  516. >>> reduce_inequalities([0 <= x - 1, y < 3], [x, y])
  517. (-oo < y) & (1 <= x) & (x < oo) & (y < 3)
  518. But an error is raised if any relationship has more than one
  519. symbol of interest:
  520. >>> reduce_inequalities([0 <= x*y - 1, y < 3], [x, y])
  521. Traceback (most recent call last):
  522. ...
  523. NotImplementedError:
  524. inequality has more than one symbol of interest.
  525. **Disabling High-Order Explicit Solutions**
  526. When solving polynomial expressions, you might not want explicit solutions
  527. (which can be quite long). If the expression is univariate, ``CRootOf``
  528. instances will be returned instead:
  529. >>> solve(x**3 - x + 1)
  530. [-1/((-1/2 - sqrt(3)*I/2)*(3*sqrt(69)/2 + 27/2)**(1/3)) -
  531. (-1/2 - sqrt(3)*I/2)*(3*sqrt(69)/2 + 27/2)**(1/3)/3,
  532. -(-1/2 + sqrt(3)*I/2)*(3*sqrt(69)/2 + 27/2)**(1/3)/3 -
  533. 1/((-1/2 + sqrt(3)*I/2)*(3*sqrt(69)/2 + 27/2)**(1/3)),
  534. -(3*sqrt(69)/2 + 27/2)**(1/3)/3 -
  535. 1/(3*sqrt(69)/2 + 27/2)**(1/3)]
  536. >>> solve(x**3 - x + 1, cubics=False)
  537. [CRootOf(x**3 - x + 1, 0),
  538. CRootOf(x**3 - x + 1, 1),
  539. CRootOf(x**3 - x + 1, 2)]
  540. If the expression is multivariate, no solution might be returned:
  541. >>> solve(x**3 - x + a, x, cubics=False)
  542. []
  543. Sometimes solutions will be obtained even when a flag is False because the
  544. expression could be factored. In the following example, the equation can
  545. be factored as the product of a linear and a quadratic factor so explicit
  546. solutions (which did not require solving a cubic expression) are obtained:
  547. >>> eq = x**3 + 3*x**2 + x - 1
  548. >>> solve(eq, cubics=False)
  549. [-1, -1 + sqrt(2), -sqrt(2) - 1]
  550. **Solving Equations Involving Radicals**
  551. Because of SymPy's use of the principle root, some solutions
  552. to radical equations will be missed unless check=False:
  553. >>> from sympy import root
  554. >>> eq = root(x**3 - 3*x**2, 3) + 1 - x
  555. >>> solve(eq)
  556. []
  557. >>> solve(eq, check=False)
  558. [1/3]
  559. In the above example, there is only a single solution to the
  560. equation. Other expressions will yield spurious roots which
  561. must be checked manually; roots which give a negative argument
  562. to odd-powered radicals will also need special checking:
  563. >>> from sympy import real_root, S
  564. >>> eq = root(x, 3) - root(x, 5) + S(1)/7
  565. >>> solve(eq) # this gives 2 solutions but misses a 3rd
  566. [CRootOf(7*x**5 - 7*x**3 + 1, 1)**15,
  567. CRootOf(7*x**5 - 7*x**3 + 1, 2)**15]
  568. >>> sol = solve(eq, check=False)
  569. >>> [abs(eq.subs(x,i).n(2)) for i in sol]
  570. [0.48, 0.e-110, 0.e-110, 0.052, 0.052]
  571. The first solution is negative so ``real_root`` must be used to see that it
  572. satisfies the expression:
  573. >>> abs(real_root(eq.subs(x, sol[0])).n(2))
  574. 0.e-110
  575. If the roots of the equation are not real then more care will be
  576. necessary to find the roots, especially for higher order equations.
  577. Consider the following expression:
  578. >>> expr = root(x, 3) - root(x, 5)
  579. We will construct a known value for this expression at x = 3 by selecting
  580. the 1-th root for each radical:
  581. >>> expr1 = root(x, 3, 1) - root(x, 5, 1)
  582. >>> v = expr1.subs(x, -3)
  583. The ``solve`` function is unable to find any exact roots to this equation:
  584. >>> eq = Eq(expr, v); eq1 = Eq(expr1, v)
  585. >>> solve(eq, check=False), solve(eq1, check=False)
  586. ([], [])
  587. The function ``unrad``, however, can be used to get a form of the equation
  588. for which numerical roots can be found:
  589. >>> from sympy.solvers.solvers import unrad
  590. >>> from sympy import nroots
  591. >>> e, (p, cov) = unrad(eq)
  592. >>> pvals = nroots(e)
  593. >>> inversion = solve(cov, x)[0]
  594. >>> xvals = [inversion.subs(p, i) for i in pvals]
  595. Although ``eq`` or ``eq1`` could have been used to find ``xvals``, the
  596. solution can only be verified with ``expr1``:
  597. >>> z = expr - v
  598. >>> [xi.n(chop=1e-9) for xi in xvals if abs(z.subs(x, xi).n()) < 1e-9]
  599. []
  600. >>> z1 = expr1 - v
  601. >>> [xi.n(chop=1e-9) for xi in xvals if abs(z1.subs(x, xi).n()) < 1e-9]
  602. [-3.0]
  603. Parameters
  604. ==========
  605. f :
  606. - a single Expr or Poly that must be zero
  607. - an Equality
  608. - a Relational expression
  609. - a Boolean
  610. - iterable of one or more of the above
  611. symbols : (object(s) to solve for) specified as
  612. - none given (other non-numeric objects will be used)
  613. - single symbol
  614. - denested list of symbols
  615. (e.g., ``solve(f, x, y)``)
  616. - ordered iterable of symbols
  617. (e.g., ``solve(f, [x, y])``)
  618. flags :
  619. dict=True (default is False)
  620. Return list (perhaps empty) of solution mappings.
  621. set=True (default is False)
  622. Return list of symbols and set of tuple(s) of solution(s).
  623. exclude=[] (default)
  624. Do not try to solve for any of the free symbols in exclude;
  625. if expressions are given, the free symbols in them will
  626. be extracted automatically.
  627. check=True (default)
  628. If False, do not do any testing of solutions. This can be
  629. useful if you want to include solutions that make any
  630. denominator zero.
  631. numerical=True (default)
  632. Do a fast numerical check if *f* has only one symbol.
  633. minimal=True (default is False)
  634. A very fast, minimal testing.
  635. warn=True (default is False)
  636. Show a warning if ``checksol()`` could not conclude.
  637. simplify=True (default)
  638. Simplify all but polynomials of order 3 or greater before
  639. returning them and (if check is not False) use the
  640. general simplify function on the solutions and the
  641. expression obtained when they are substituted into the
  642. function which should be zero.
  643. force=True (default is False)
  644. Make positive all symbols without assumptions regarding sign.
  645. rational=True (default)
  646. Recast Floats as Rational; if this option is not used, the
  647. system containing Floats may fail to solve because of issues
  648. with polys. If rational=None, Floats will be recast as
  649. rationals but the answer will be recast as Floats. If the
  650. flag is False then nothing will be done to the Floats.
  651. manual=True (default is False)
  652. Do not use the polys/matrix method to solve a system of
  653. equations, solve them one at a time as you might "manually."
  654. implicit=True (default is False)
  655. Allows ``solve`` to return a solution for a pattern in terms of
  656. other functions that contain that pattern; this is only
  657. needed if the pattern is inside of some invertible function
  658. like cos, exp, etc.
  659. particular=True (default is False)
  660. Instructs ``solve`` to try to find a particular solution to
  661. a linear system with as many zeros as possible; this is very
  662. expensive.
  663. quick=True (default is False; ``particular`` must be True)
  664. Selects a fast heuristic to find a solution with many zeros
  665. whereas a value of False uses the very slow method guaranteed
  666. to find the largest number of zeros possible.
  667. cubics=True (default)
  668. Return explicit solutions when cubic expressions are encountered.
  669. When False, quartics and quintics are disabled, too.
  670. quartics=True (default)
  671. Return explicit solutions when quartic expressions are encountered.
  672. When False, quintics are disabled, too.
  673. quintics=True (default)
  674. Return explicit solutions (if possible) when quintic expressions
  675. are encountered.
  676. See Also
  677. ========
  678. rsolve: For solving recurrence relationships
  679. sympy.solvers.ode.dsolve: For solving differential equations
  680. """
  681. from .inequalities import reduce_inequalities
  682. # checking/recording flags
  683. ###########################################################################
  684. # set solver types explicitly; as soon as one is False
  685. # all the rest will be False
  686. hints = ('cubics', 'quartics', 'quintics')
  687. default = True
  688. for k in hints:
  689. default = flags.setdefault(k, bool(flags.get(k, default)))
  690. # allow solution to contain symbol if True:
  691. implicit = flags.get('implicit', False)
  692. # record desire to see warnings
  693. warn = flags.get('warn', False)
  694. # this flag will be needed for quick exits below, so record
  695. # now -- but don't record `dict` yet since it might change
  696. as_set = flags.get('set', False)
  697. # keeping track of how f was passed
  698. bare_f = not iterable(f)
  699. # check flag usage for particular/quick which should only be used
  700. # with systems of equations
  701. if flags.get('quick', None) is not None:
  702. if not flags.get('particular', None):
  703. raise ValueError('when using `quick`, `particular` should be True')
  704. if flags.get('particular', False) and bare_f:
  705. raise ValueError(filldedent("""
  706. The 'particular/quick' flag is usually used with systems of
  707. equations. Either pass your equation in a list or
  708. consider using a solver like `diophantine` if you are
  709. looking for a solution in integers."""))
  710. # sympify everything, creating list of expressions and list of symbols
  711. ###########################################################################
  712. def _sympified_list(w):
  713. return list(map(sympify, w if iterable(w) else [w]))
  714. f, symbols = (_sympified_list(w) for w in [f, symbols])
  715. # preprocess symbol(s)
  716. ###########################################################################
  717. ordered_symbols = None # were the symbols in a well defined order?
  718. if not symbols:
  719. # get symbols from equations
  720. symbols = set().union(*[fi.free_symbols for fi in f])
  721. if len(symbols) < len(f):
  722. for fi in f:
  723. pot = preorder_traversal(fi)
  724. for p in pot:
  725. if isinstance(p, AppliedUndef):
  726. if not as_set:
  727. flags['dict'] = True # better show symbols
  728. symbols.add(p)
  729. pot.skip() # don't go any deeper
  730. ordered_symbols = False
  731. symbols = list(ordered(symbols)) # to make it canonical
  732. else:
  733. if len(symbols) == 1 and iterable(symbols[0]):
  734. symbols = symbols[0]
  735. ordered_symbols = symbols and is_sequence(symbols,
  736. include=GeneratorType)
  737. _symbols = list(uniq(symbols))
  738. if len(_symbols) != len(symbols):
  739. ordered_symbols = False
  740. symbols = list(ordered(symbols))
  741. else:
  742. symbols = _symbols
  743. # check for duplicates
  744. if len(symbols) != len(set(symbols)):
  745. raise ValueError('duplicate symbols given')
  746. # remove those not of interest
  747. exclude = flags.pop('exclude', set())
  748. if exclude:
  749. if isinstance(exclude, Expr):
  750. exclude = [exclude]
  751. exclude = set().union(*[e.free_symbols for e in sympify(exclude)])
  752. symbols = [s for s in symbols if s not in exclude]
  753. # preprocess equation(s)
  754. ###########################################################################
  755. # automatically ignore True values
  756. if isinstance(f, list):
  757. f = [s for s in f if s is not S.true]
  758. # handle canonicalization of equation types
  759. for i, fi in enumerate(f):
  760. if isinstance(fi, (Eq, Ne)):
  761. if 'ImmutableDenseMatrix' in [type(a).__name__ for a in fi.args]:
  762. fi = fi.lhs - fi.rhs
  763. else:
  764. L, R = fi.args
  765. if isinstance(R, BooleanAtom):
  766. L, R = R, L
  767. if isinstance(L, BooleanAtom):
  768. if isinstance(fi, Ne):
  769. L = ~L
  770. if R.is_Relational:
  771. fi = ~R if L is S.false else R
  772. elif R.is_Symbol:
  773. return L
  774. elif R.is_Boolean and (~R).is_Symbol:
  775. return ~L
  776. else:
  777. raise NotImplementedError(filldedent('''
  778. Unanticipated argument of Eq when other arg
  779. is True or False.
  780. '''))
  781. elif isinstance(fi, Eq):
  782. fi = Add(fi.lhs, -fi.rhs, evaluate=False)
  783. f[i] = fi
  784. # *** dispatch and handle as a system of relationals
  785. # **************************************************
  786. if fi.is_Relational:
  787. if len(symbols) != 1:
  788. raise ValueError("can only solve for one symbol at a time")
  789. if warn and symbols[0].assumptions0:
  790. warnings.warn(filldedent("""
  791. \tWarning: assumptions about variable '%s' are
  792. not handled currently.""" % symbols[0]))
  793. return reduce_inequalities(f, symbols=symbols)
  794. # convert Poly to expression
  795. if isinstance(fi, Poly):
  796. f[i] = fi.as_expr()
  797. # rewrite hyperbolics in terms of exp if they have symbols of
  798. # interest
  799. f[i] = f[i].replace(lambda w: isinstance(w, HyperbolicFunction) and \
  800. w.has_free(*symbols), lambda w: w.rewrite(exp))
  801. # if we have a Matrix, we need to iterate over its elements again
  802. if f[i].is_Matrix:
  803. try:
  804. f[i] = f[i].as_explicit()
  805. except ValueError:
  806. raise ValueError(
  807. "solve cannot handle matrices with symbolic shape."
  808. )
  809. bare_f = False
  810. f.extend(list(f[i]))
  811. f[i] = S.Zero
  812. # if we can split it into real and imaginary parts then do so
  813. freei = f[i].free_symbols
  814. if freei and all(s.is_extended_real or s.is_imaginary for s in freei):
  815. fr, fi = f[i].as_real_imag()
  816. # accept as long as new re, im, arg or atan2 are not introduced
  817. had = f[i].atoms(re, im, arg, atan2)
  818. if fr and fi and fr != fi and not any(
  819. i.atoms(re, im, arg, atan2) - had for i in (fr, fi)):
  820. if bare_f:
  821. bare_f = False
  822. f[i: i + 1] = [fr, fi]
  823. # real/imag handling -----------------------------
  824. if any(isinstance(fi, (bool, BooleanAtom)) for fi in f):
  825. if as_set:
  826. return [], set()
  827. return []
  828. for i, fi in enumerate(f):
  829. # Abs
  830. while True:
  831. was = fi
  832. fi = fi.replace(Abs, lambda arg:
  833. separatevars(Abs(arg)).rewrite(Piecewise) if arg.has(*symbols)
  834. else Abs(arg))
  835. if was == fi:
  836. break
  837. for e in fi.find(Abs):
  838. if e.has(*symbols):
  839. raise NotImplementedError('solving %s when the argument '
  840. 'is not real or imaginary.' % e)
  841. # arg
  842. fi = fi.replace(arg, lambda a: arg(a).rewrite(atan2).rewrite(atan))
  843. # save changes
  844. f[i] = fi
  845. # see if re(s) or im(s) appear
  846. freim = [fi for fi in f if fi.has(re, im)]
  847. if freim:
  848. irf = []
  849. for s in symbols:
  850. if s.is_real or s.is_imaginary:
  851. continue # neither re(x) nor im(x) will appear
  852. # if re(s) or im(s) appear, the auxiliary equation must be present
  853. if any(fi.has(re(s), im(s)) for fi in freim):
  854. irf.append((s, re(s) + S.ImaginaryUnit*im(s)))
  855. if irf:
  856. for s, rhs in irf:
  857. f = [fi.xreplace({s: rhs}) for fi in f] + [s - rhs]
  858. symbols.extend([re(s), im(s)])
  859. if bare_f:
  860. bare_f = False
  861. flags['dict'] = True
  862. # end of real/imag handling -----------------------------
  863. # we can solve for non-symbol entities by replacing them with Dummy symbols
  864. f, symbols, swap_sym = recast_to_symbols(f, symbols)
  865. # this set of symbols (perhaps recast) is needed below
  866. symset = set(symbols)
  867. # get rid of equations that have no symbols of interest; we don't
  868. # try to solve them because the user didn't ask and they might be
  869. # hard to solve; this means that solutions may be given in terms
  870. # of the eliminated equations e.g. solve((x-y, y-3), x) -> {x: y}
  871. newf = []
  872. for fi in f:
  873. # let the solver handle equations that..
  874. # - have no symbols but are expressions
  875. # - have symbols of interest
  876. # - have no symbols of interest but are constant
  877. # but when an expression is not constant and has no symbols of
  878. # interest, it can't change what we obtain for a solution from
  879. # the remaining equations so we don't include it; and if it's
  880. # zero it can be removed and if it's not zero, there is no
  881. # solution for the equation set as a whole
  882. #
  883. # The reason for doing this filtering is to allow an answer
  884. # to be obtained to queries like solve((x - y, y), x); without
  885. # this mod the return value is []
  886. ok = False
  887. if fi.free_symbols & symset:
  888. ok = True
  889. else:
  890. if fi.is_number:
  891. if fi.is_Number:
  892. if fi.is_zero:
  893. continue
  894. return []
  895. ok = True
  896. else:
  897. if fi.is_constant():
  898. ok = True
  899. if ok:
  900. newf.append(fi)
  901. if not newf:
  902. if as_set:
  903. return symbols, set()
  904. return []
  905. f = newf
  906. del newf
  907. # mask off any Object that we aren't going to invert: Derivative,
  908. # Integral, etc... so that solving for anything that they contain will
  909. # give an implicit solution
  910. seen = set()
  911. non_inverts = set()
  912. for fi in f:
  913. pot = preorder_traversal(fi)
  914. for p in pot:
  915. if not isinstance(p, Expr) or isinstance(p, Piecewise):
  916. pass
  917. elif (isinstance(p, bool) or
  918. not p.args or
  919. p in symset or
  920. p.is_Add or p.is_Mul or
  921. p.is_Pow and not implicit or
  922. p.is_Function and not implicit) and p.func not in (re, im):
  923. continue
  924. elif p not in seen:
  925. seen.add(p)
  926. if p.free_symbols & symset:
  927. non_inverts.add(p)
  928. else:
  929. continue
  930. pot.skip()
  931. del seen
  932. non_inverts = dict(list(zip(non_inverts, [Dummy() for _ in non_inverts])))
  933. f = [fi.subs(non_inverts) for fi in f]
  934. # Both xreplace and subs are needed below: xreplace to force substitution
  935. # inside Derivative, subs to handle non-straightforward substitutions
  936. non_inverts = [(v, k.xreplace(swap_sym).subs(swap_sym)) for k, v in non_inverts.items()]
  937. # rationalize Floats
  938. floats = False
  939. if flags.get('rational', True) is not False:
  940. for i, fi in enumerate(f):
  941. if fi.has(Float):
  942. floats = True
  943. f[i] = nsimplify(fi, rational=True)
  944. # capture any denominators before rewriting since
  945. # they may disappear after the rewrite, e.g. issue 14779
  946. flags['_denominators'] = _simple_dens(f[0], symbols)
  947. # Any embedded piecewise functions need to be brought out to the
  948. # top level so that the appropriate strategy gets selected.
  949. # However, this is necessary only if one of the piecewise
  950. # functions depends on one of the symbols we are solving for.
  951. def _has_piecewise(e):
  952. if e.is_Piecewise:
  953. return e.has(*symbols)
  954. return any(_has_piecewise(a) for a in e.args)
  955. for i, fi in enumerate(f):
  956. if _has_piecewise(fi):
  957. f[i] = piecewise_fold(fi)
  958. # expand angles of sums; in general, expand_trig will allow
  959. # more roots to be found but this is not a great solultion
  960. # to not returning a parametric solution, otherwise
  961. # many values can be returned that have a simple
  962. # relationship between values
  963. targs = {t for fi in f for t in fi.atoms(TrigonometricFunction)}
  964. if len(targs) > 1:
  965. add, other = sift(targs, lambda x: x.args[0].is_Add, binary=True)
  966. add, other = [[i for i in l if i.has_free(*symbols)] for l in (add, other)]
  967. trep = {}
  968. for t in add:
  969. a = t.args[0]
  970. ind, dep = a.as_independent(*symbols)
  971. if dep in symbols or -dep in symbols:
  972. # don't let expansion expand wrt anything in ind
  973. n = Dummy() if not ind.is_Number else ind
  974. trep[t] = TR10(t.func(dep + n)).xreplace({n: ind})
  975. if other and len(other) <= 2:
  976. base = gcd(*[i.args[0] for i in other]) if len(other) > 1 else other[0].args[0]
  977. for i in other:
  978. trep[i] = TR11(i, base)
  979. f = [fi.xreplace(trep) for fi in f]
  980. #
  981. # try to get a solution
  982. ###########################################################################
  983. if bare_f:
  984. solution = None
  985. if len(symbols) != 1:
  986. solution = _solve_undetermined(f[0], symbols, flags)
  987. if not solution:
  988. solution = _solve(f[0], *symbols, **flags)
  989. else:
  990. linear, solution = _solve_system(f, symbols, **flags)
  991. assert type(solution) is list
  992. assert not solution or type(solution[0]) is dict, solution
  993. #
  994. # postprocessing
  995. ###########################################################################
  996. # capture as_dict flag now (as_set already captured)
  997. as_dict = flags.get('dict', False)
  998. # define how solution will get unpacked
  999. tuple_format = lambda s: [tuple([i.get(x, x) for x in symbols]) for i in s]
  1000. if as_dict or as_set:
  1001. unpack = None
  1002. elif bare_f:
  1003. if len(symbols) == 1:
  1004. unpack = lambda s: [i[symbols[0]] for i in s]
  1005. elif len(solution) == 1 and len(solution[0]) == len(symbols):
  1006. # undetermined linear coeffs solution
  1007. unpack = lambda s: s[0]
  1008. elif ordered_symbols:
  1009. unpack = tuple_format
  1010. else:
  1011. unpack = lambda s: s
  1012. else:
  1013. if solution:
  1014. if linear and len(solution) == 1:
  1015. # if you want the tuple solution for the linear
  1016. # case, use `set=True`
  1017. unpack = lambda s: s[0]
  1018. elif ordered_symbols:
  1019. unpack = tuple_format
  1020. else:
  1021. unpack = lambda s: s
  1022. else:
  1023. unpack = None
  1024. # Restore masked-off objects
  1025. if non_inverts and type(solution) is list:
  1026. solution = [{k: v.subs(non_inverts) for k, v in s.items()}
  1027. for s in solution]
  1028. # Restore original "symbols" if a dictionary is returned.
  1029. # This is not necessary for
  1030. # - the single univariate equation case
  1031. # since the symbol will have been removed from the solution;
  1032. # - the nonlinear poly_system since that only supports zero-dimensional
  1033. # systems and those results come back as a list
  1034. #
  1035. # ** unless there were Derivatives with the symbols, but those were handled
  1036. # above.
  1037. if swap_sym:
  1038. symbols = [swap_sym.get(k, k) for k in symbols]
  1039. for i, sol in enumerate(solution):
  1040. solution[i] = {swap_sym.get(k, k): v.subs(swap_sym)
  1041. for k, v in sol.items()}
  1042. # Get assumptions about symbols, to filter solutions.
  1043. # Note that if assumptions about a solution can't be verified, it is still
  1044. # returned.
  1045. check = flags.get('check', True)
  1046. # restore floats
  1047. if floats and solution and flags.get('rational', None) is None:
  1048. solution = nfloat(solution, exponent=False)
  1049. # nfloat might reveal more duplicates
  1050. solution = _remove_duplicate_solutions(solution)
  1051. if check and solution: # assumption checking
  1052. warn = flags.get('warn', False)
  1053. got_None = [] # solutions for which one or more symbols gave None
  1054. no_False = [] # solutions for which no symbols gave False
  1055. for sol in solution:
  1056. v = fuzzy_and(check_assumptions(val, **symb.assumptions0)
  1057. for symb, val in sol.items())
  1058. if v is False:
  1059. continue
  1060. no_False.append(sol)
  1061. if v is None:
  1062. got_None.append(sol)
  1063. solution = no_False
  1064. if warn and got_None:
  1065. warnings.warn(filldedent("""
  1066. \tWarning: assumptions concerning following solution(s)
  1067. cannot be checked:""" + '\n\t' +
  1068. ', '.join(str(s) for s in got_None)))
  1069. #
  1070. # done
  1071. ###########################################################################
  1072. if not solution:
  1073. if as_set:
  1074. return symbols, set()
  1075. return []
  1076. # make orderings canonical for list of dictionaries
  1077. if not as_set: # for set, no point in ordering
  1078. solution = [{k: s[k] for k in ordered(s)} for s in solution]
  1079. solution.sort(key=default_sort_key)
  1080. if not (as_set or as_dict):
  1081. return unpack(solution)
  1082. if as_dict:
  1083. return solution
  1084. # set output: (symbols, {t1, t2, ...}) from list of dictionaries;
  1085. # include all symbols for those that like a verbose solution
  1086. # and to resolve any differences in dictionary keys.
  1087. #
  1088. # The set results can easily be used to make a verbose dict as
  1089. # k, v = solve(eqs, syms, set=True)
  1090. # sol = [dict(zip(k,i)) for i in v]
  1091. #
  1092. if ordered_symbols:
  1093. k = symbols # keep preferred order
  1094. else:
  1095. # just unify the symbols for which solutions were found
  1096. k = list(ordered(set(flatten(tuple(i.keys()) for i in solution))))
  1097. return k, {tuple([s.get(ki, ki) for ki in k]) for s in solution}
  1098. def _solve_undetermined(g, symbols, flags):
  1099. """solve helper to return a list with one dict (solution) else None
  1100. A direct call to solve_undetermined_coeffs is more flexible and
  1101. can return both multiple solutions and handle more than one independent
  1102. variable. Here, we have to be more cautious to keep from solving
  1103. something that does not look like an undetermined coeffs system --
  1104. to minimize the surprise factor since singularities that cancel are not
  1105. prohibited in solve_undetermined_coeffs.
  1106. """
  1107. if g.free_symbols - set(symbols):
  1108. sol = solve_undetermined_coeffs(g, symbols, **dict(flags, dict=True, set=None))
  1109. if len(sol) == 1:
  1110. return sol
  1111. def _solve(f, *symbols, **flags):
  1112. """Return a checked solution for *f* in terms of one or more of the
  1113. symbols in the form of a list of dictionaries.
  1114. If no method is implemented to solve the equation, a NotImplementedError
  1115. will be raised. In the case that conversion of an expression to a Poly
  1116. gives None a ValueError will be raised.
  1117. """
  1118. not_impl_msg = "No algorithms are implemented to solve equation %s"
  1119. if len(symbols) != 1:
  1120. # look for solutions for desired symbols that are independent
  1121. # of symbols already solved for, e.g. if we solve for x = y
  1122. # then no symbol having x in its solution will be returned.
  1123. # First solve for linear symbols (since that is easier and limits
  1124. # solution size) and then proceed with symbols appearing
  1125. # in a non-linear fashion. Ideally, if one is solving a single
  1126. # expression for several symbols, they would have to be
  1127. # appear in factors of an expression, but we do not here
  1128. # attempt factorization. XXX perhaps handling a Mul
  1129. # should come first in this routine whether there is
  1130. # one or several symbols.
  1131. nonlin_s = []
  1132. got_s = set()
  1133. rhs_s = set()
  1134. result = []
  1135. for s in symbols:
  1136. xi, v = solve_linear(f, symbols=[s])
  1137. if xi == s:
  1138. # no need to check but we should simplify if desired
  1139. if flags.get('simplify', True):
  1140. v = simplify(v)
  1141. vfree = v.free_symbols
  1142. if vfree & got_s:
  1143. # was linear, but has redundant relationship
  1144. # e.g. x - y = 0 has y == x is redundant for x == y
  1145. # so ignore
  1146. continue
  1147. rhs_s |= vfree
  1148. got_s.add(xi)
  1149. result.append({xi: v})
  1150. elif xi: # there might be a non-linear solution if xi is not 0
  1151. nonlin_s.append(s)
  1152. if not nonlin_s:
  1153. return result
  1154. for s in nonlin_s:
  1155. try:
  1156. soln = _solve(f, s, **flags)
  1157. for sol in soln:
  1158. if sol[s].free_symbols & got_s:
  1159. # depends on previously solved symbols: ignore
  1160. continue
  1161. got_s.add(s)
  1162. result.append(sol)
  1163. except NotImplementedError:
  1164. continue
  1165. if got_s:
  1166. return result
  1167. else:
  1168. raise NotImplementedError(not_impl_msg % f)
  1169. # solve f for a single variable
  1170. symbol = symbols[0]
  1171. # expand binomials only if it has the unknown symbol
  1172. f = f.replace(lambda e: isinstance(e, binomial) and e.has(symbol),
  1173. lambda e: expand_func(e))
  1174. # checking will be done unless it is turned off before making a
  1175. # recursive call; the variables `checkdens` and `check` are
  1176. # captured here (for reference below) in case flag value changes
  1177. flags['check'] = checkdens = check = flags.pop('check', True)
  1178. # build up solutions if f is a Mul
  1179. if f.is_Mul:
  1180. result = set()
  1181. for m in f.args:
  1182. if m in {S.NegativeInfinity, S.ComplexInfinity, S.Infinity}:
  1183. result = set()
  1184. break
  1185. soln = _vsolve(m, symbol, **flags)
  1186. result.update(set(soln))
  1187. result = [{symbol: v} for v in result]
  1188. if check:
  1189. # all solutions have been checked but now we must
  1190. # check that the solutions do not set denominators
  1191. # in any factor to zero
  1192. dens = flags.get('_denominators', _simple_dens(f, symbols))
  1193. result = [s for s in result if
  1194. not any(checksol(den, s, **flags) for den in
  1195. dens)]
  1196. # set flags for quick exit at end; solutions for each
  1197. # factor were already checked and simplified
  1198. check = False
  1199. flags['simplify'] = False
  1200. elif f.is_Piecewise:
  1201. result = set()
  1202. if any(e.is_zero for e, c in f.args):
  1203. f = f.simplify() # failure imminent w/o help
  1204. cond = neg = True
  1205. for expr, cnd in f.args:
  1206. # the explicit condition for this expr is the current cond
  1207. # and none of the previous conditions
  1208. cond = And(neg, cnd)
  1209. neg = And(neg, ~cond)
  1210. if expr.is_zero and cond.simplify() != False:
  1211. raise NotImplementedError(filldedent('''
  1212. An expression is already zero when %s.
  1213. This means that in this *region* the solution
  1214. is zero but solve can only represent discrete,
  1215. not interval, solutions. If this is a spurious
  1216. interval it might be resolved with simplification
  1217. of the Piecewise conditions.''' % cond))
  1218. candidates = _vsolve(expr, symbol, **flags)
  1219. for candidate in candidates:
  1220. if candidate in result:
  1221. # an unconditional value was already there
  1222. continue
  1223. try:
  1224. v = cond.subs(symbol, candidate)
  1225. _eval_simplify = getattr(v, '_eval_simplify', None)
  1226. if _eval_simplify is not None:
  1227. # unconditionally take the simplification of v
  1228. v = _eval_simplify(ratio=2, measure=lambda x: 1)
  1229. except TypeError:
  1230. # incompatible type with condition(s)
  1231. continue
  1232. if v == False:
  1233. continue
  1234. if v == True:
  1235. result.add(candidate)
  1236. else:
  1237. result.add(Piecewise(
  1238. (candidate, v),
  1239. (S.NaN, True)))
  1240. # solutions already checked and simplified
  1241. # ****************************************
  1242. return [{symbol: r} for r in result]
  1243. else:
  1244. # first see if it really depends on symbol and whether there
  1245. # is only a linear solution
  1246. f_num, sol = solve_linear(f, symbols=symbols)
  1247. if f_num.is_zero or sol is S.NaN:
  1248. return []
  1249. elif f_num.is_Symbol:
  1250. # no need to check but simplify if desired
  1251. if flags.get('simplify', True):
  1252. sol = simplify(sol)
  1253. return [{f_num: sol}]
  1254. poly = None
  1255. # check for a single Add generator
  1256. if not f_num.is_Add:
  1257. add_args = [i for i in f_num.atoms(Add)
  1258. if symbol in i.free_symbols]
  1259. if len(add_args) == 1:
  1260. gen = add_args[0]
  1261. spart = gen.as_independent(symbol)[1].as_base_exp()[0]
  1262. if spart == symbol:
  1263. try:
  1264. poly = Poly(f_num, spart)
  1265. except PolynomialError:
  1266. pass
  1267. result = False # no solution was obtained
  1268. msg = '' # there is no failure message
  1269. # Poly is generally robust enough to convert anything to
  1270. # a polynomial and tell us the different generators that it
  1271. # contains, so we will inspect the generators identified by
  1272. # polys to figure out what to do.
  1273. # try to identify a single generator that will allow us to solve this
  1274. # as a polynomial, followed (perhaps) by a change of variables if the
  1275. # generator is not a symbol
  1276. try:
  1277. if poly is None:
  1278. poly = Poly(f_num)
  1279. if poly is None:
  1280. raise ValueError('could not convert %s to Poly' % f_num)
  1281. except GeneratorsNeeded:
  1282. simplified_f = simplify(f_num)
  1283. if simplified_f != f_num:
  1284. return _solve(simplified_f, symbol, **flags)
  1285. raise ValueError('expression appears to be a constant')
  1286. gens = [g for g in poly.gens if g.has(symbol)]
  1287. def _as_base_q(x):
  1288. """Return (b**e, q) for x = b**(p*e/q) where p/q is the leading
  1289. Rational of the exponent of x, e.g. exp(-2*x/3) -> (exp(x), 3)
  1290. """
  1291. b, e = x.as_base_exp()
  1292. if e.is_Rational:
  1293. return b, e.q
  1294. if not e.is_Mul:
  1295. return x, 1
  1296. c, ee = e.as_coeff_Mul()
  1297. if c.is_Rational and c is not S.One: # c could be a Float
  1298. return b**ee, c.q
  1299. return x, 1
  1300. if len(gens) > 1:
  1301. # If there is more than one generator, it could be that the
  1302. # generators have the same base but different powers, e.g.
  1303. # >>> Poly(exp(x) + 1/exp(x))
  1304. # Poly(exp(-x) + exp(x), exp(-x), exp(x), domain='ZZ')
  1305. #
  1306. # If unrad was not disabled then there should be no rational
  1307. # exponents appearing as in
  1308. # >>> Poly(sqrt(x) + sqrt(sqrt(x)))
  1309. # Poly(sqrt(x) + x**(1/4), sqrt(x), x**(1/4), domain='ZZ')
  1310. bases, qs = list(zip(*[_as_base_q(g) for g in gens]))
  1311. bases = set(bases)
  1312. if len(bases) > 1 or not all(q == 1 for q in qs):
  1313. funcs = {b for b in bases if b.is_Function}
  1314. trig = {_ for _ in funcs if
  1315. isinstance(_, TrigonometricFunction)}
  1316. other = funcs - trig
  1317. if not other and len(funcs.intersection(trig)) > 1:
  1318. newf = None
  1319. if f_num.is_Add and len(f_num.args) == 2:
  1320. # check for sin(x)**p = cos(x)**p
  1321. _args = f_num.args
  1322. t = a, b = [i.atoms(Function).intersection(
  1323. trig) for i in _args]
  1324. if all(len(i) == 1 for i in t):
  1325. a, b = [i.pop() for i in t]
  1326. if isinstance(a, cos):
  1327. a, b = b, a
  1328. _args = _args[::-1]
  1329. if isinstance(a, sin) and isinstance(b, cos
  1330. ) and a.args[0] == b.args[0]:
  1331. # sin(x) + cos(x) = 0 -> tan(x) + 1 = 0
  1332. newf, _d = (TR2i(_args[0]/_args[1]) + 1
  1333. ).as_numer_denom()
  1334. if not _d.is_Number:
  1335. newf = None
  1336. if newf is None:
  1337. newf = TR1(f_num).rewrite(tan)
  1338. if newf != f_num:
  1339. # don't check the rewritten form --check
  1340. # solutions in the un-rewritten form below
  1341. flags['check'] = False
  1342. result = _solve(newf, symbol, **flags)
  1343. flags['check'] = check
  1344. # just a simple case - see if replacement of single function
  1345. # clears all symbol-dependent functions, e.g.
  1346. # log(x) - log(log(x) - 1) - 3 can be solved even though it has
  1347. # two generators.
  1348. if result is False and funcs:
  1349. funcs = list(ordered(funcs)) # put shallowest function first
  1350. f1 = funcs[0]
  1351. t = Dummy('t')
  1352. # perform the substitution
  1353. ftry = f_num.subs(f1, t)
  1354. # if no Functions left, we can proceed with usual solve
  1355. if not ftry.has(symbol):
  1356. cv_sols = _solve(ftry, t, **flags)
  1357. cv_inv = list(ordered(_vsolve(t - f1, symbol, **flags)))[0]
  1358. result = [{symbol: cv_inv.subs(sol)} for sol in cv_sols]
  1359. if result is False:
  1360. msg = 'multiple generators %s' % gens
  1361. else:
  1362. # e.g. case where gens are exp(x), exp(-x)
  1363. u = bases.pop()
  1364. t = Dummy('t')
  1365. inv = _vsolve(u - t, symbol, **flags)
  1366. if isinstance(u, (Pow, exp)):
  1367. # this will be resolved by factor in _tsolve but we might
  1368. # as well try a simple expansion here to get things in
  1369. # order so something like the following will work now without
  1370. # having to factor:
  1371. #
  1372. # >>> eq = (exp(I*(-x-2))+exp(I*(x+2)))
  1373. # >>> eq.subs(exp(x),y) # fails
  1374. # exp(I*(-x - 2)) + exp(I*(x + 2))
  1375. # >>> eq.expand().subs(exp(x),y) # works
  1376. # y**I*exp(2*I) + y**(-I)*exp(-2*I)
  1377. def _expand(p):
  1378. b, e = p.as_base_exp()
  1379. e = expand_mul(e)
  1380. return expand_power_exp(b**e)
  1381. ftry = f_num.replace(
  1382. lambda w: w.is_Pow or isinstance(w, exp),
  1383. _expand).subs(u, t)
  1384. if not ftry.has(symbol):
  1385. soln = _solve(ftry, t, **flags)
  1386. result = [{symbol: i.subs(s)} for i in inv for s in soln]
  1387. elif len(gens) == 1:
  1388. # There is only one generator that we are interested in, but
  1389. # there may have been more than one generator identified by
  1390. # polys (e.g. for symbols other than the one we are interested
  1391. # in) so recast the poly in terms of our generator of interest.
  1392. # Also use composite=True with f_num since Poly won't update
  1393. # poly as documented in issue 8810.
  1394. poly = Poly(f_num, gens[0], composite=True)
  1395. # if we aren't on the tsolve-pass, use roots
  1396. if not flags.pop('tsolve', False):
  1397. soln = None
  1398. deg = poly.degree()
  1399. flags['tsolve'] = True
  1400. hints = ('cubics', 'quartics', 'quintics')
  1401. solvers = {h: flags.get(h) for h in hints}
  1402. soln = roots(poly, **solvers)
  1403. if sum(soln.values()) < deg:
  1404. # e.g. roots(32*x**5 + 400*x**4 + 2032*x**3 +
  1405. # 5000*x**2 + 6250*x + 3189) -> {}
  1406. # so all_roots is used and RootOf instances are
  1407. # returned *unless* the system is multivariate
  1408. # or high-order EX domain.
  1409. try:
  1410. soln = poly.all_roots()
  1411. except NotImplementedError:
  1412. if not flags.get('incomplete', True):
  1413. raise NotImplementedError(
  1414. filldedent('''
  1415. Neither high-order multivariate polynomials
  1416. nor sorting of EX-domain polynomials is supported.
  1417. If you want to see any results, pass keyword incomplete=True to
  1418. solve; to see numerical values of roots
  1419. for univariate expressions, use nroots.
  1420. '''))
  1421. else:
  1422. pass
  1423. else:
  1424. soln = list(soln.keys())
  1425. if soln is not None:
  1426. u = poly.gen
  1427. if u != symbol:
  1428. try:
  1429. t = Dummy('t')
  1430. inv = _vsolve(u - t, symbol, **flags)
  1431. soln = {i.subs(t, s) for i in inv for s in soln}
  1432. except NotImplementedError:
  1433. # perhaps _tsolve can handle f_num
  1434. soln = None
  1435. else:
  1436. check = False # only dens need to be checked
  1437. if soln is not None:
  1438. if len(soln) > 2:
  1439. # if the flag wasn't set then unset it since high-order
  1440. # results are quite long. Perhaps one could base this
  1441. # decision on a certain critical length of the
  1442. # roots. In addition, wester test M2 has an expression
  1443. # whose roots can be shown to be real with the
  1444. # unsimplified form of the solution whereas only one of
  1445. # the simplified forms appears to be real.
  1446. flags['simplify'] = flags.get('simplify', False)
  1447. if soln is not None:
  1448. result = [{symbol: v} for v in soln]
  1449. # fallback if above fails
  1450. # -----------------------
  1451. if result is False:
  1452. # try unrad
  1453. if flags.pop('_unrad', True):
  1454. try:
  1455. u = unrad(f_num, symbol)
  1456. except (ValueError, NotImplementedError):
  1457. u = False
  1458. if u:
  1459. eq, cov = u
  1460. if cov:
  1461. isym, ieq = cov
  1462. inv = _vsolve(ieq, symbol, **flags)[0]
  1463. rv = {inv.subs(xi) for xi in _solve(eq, isym, **flags)}
  1464. else:
  1465. try:
  1466. rv = set(_vsolve(eq, symbol, **flags))
  1467. except NotImplementedError:
  1468. rv = None
  1469. if rv is not None:
  1470. result = [{symbol: v} for v in rv]
  1471. # if the flag wasn't set then unset it since unrad results
  1472. # can be quite long or of very high order
  1473. flags['simplify'] = flags.get('simplify', False)
  1474. else:
  1475. pass # for coverage
  1476. # try _tsolve
  1477. if result is False:
  1478. flags.pop('tsolve', None) # allow tsolve to be used on next pass
  1479. try:
  1480. soln = _tsolve(f_num, symbol, **flags)
  1481. if soln is not None:
  1482. result = [{symbol: v} for v in soln]
  1483. except PolynomialError:
  1484. pass
  1485. # ----------- end of fallback ----------------------------
  1486. if result is False:
  1487. raise NotImplementedError('\n'.join([msg, not_impl_msg % f]))
  1488. result = _remove_duplicate_solutions(result)
  1489. if flags.get('simplify', True):
  1490. result = [{k: d[k].simplify() for k in d} for d in result]
  1491. # Simplification might reveal more duplicates
  1492. result = _remove_duplicate_solutions(result)
  1493. # we just simplified the solution so we now set the flag to
  1494. # False so the simplification doesn't happen again in checksol()
  1495. flags['simplify'] = False
  1496. if checkdens:
  1497. # reject any result that makes any denom. affirmatively 0;
  1498. # if in doubt, keep it
  1499. dens = _simple_dens(f, symbols)
  1500. result = [r for r in result if
  1501. not any(checksol(d, r, **flags)
  1502. for d in dens)]
  1503. if check:
  1504. # keep only results if the check is not False
  1505. result = [r for r in result if
  1506. checksol(f_num, r, **flags) is not False]
  1507. return result
  1508. def _remove_duplicate_solutions(solutions: list[dict[Expr, Expr]]
  1509. ) -> list[dict[Expr, Expr]]:
  1510. """Remove duplicates from a list of dicts"""
  1511. solutions_set = set()
  1512. solutions_new = []
  1513. for sol in solutions:
  1514. solset = frozenset(sol.items())
  1515. if solset not in solutions_set:
  1516. solutions_new.append(sol)
  1517. solutions_set.add(solset)
  1518. return solutions_new
  1519. def _solve_system(exprs, symbols, **flags):
  1520. """return ``(linear, solution)`` where ``linear`` is True
  1521. if the system was linear, else False; ``solution``
  1522. is a list of dictionaries giving solutions for the symbols
  1523. """
  1524. if not exprs:
  1525. return False, []
  1526. if flags.pop('_split', True):
  1527. # Split the system into connected components
  1528. V = exprs
  1529. symsset = set(symbols)
  1530. exprsyms = {e: e.free_symbols & symsset for e in exprs}
  1531. E = []
  1532. sym_indices = {sym: i for i, sym in enumerate(symbols)}
  1533. for n, e1 in enumerate(exprs):
  1534. for e2 in exprs[:n]:
  1535. # Equations are connected if they share a symbol
  1536. if exprsyms[e1] & exprsyms[e2]:
  1537. E.append((e1, e2))
  1538. G = V, E
  1539. subexprs = connected_components(G)
  1540. if len(subexprs) > 1:
  1541. subsols = []
  1542. linear = True
  1543. for subexpr in subexprs:
  1544. subsyms = set()
  1545. for e in subexpr:
  1546. subsyms |= exprsyms[e]
  1547. subsyms = sorted(subsyms, key = lambda x: sym_indices[x])
  1548. flags['_split'] = False # skip split step
  1549. _linear, subsol = _solve_system(subexpr, subsyms, **flags)
  1550. if linear:
  1551. linear = linear and _linear
  1552. if not isinstance(subsol, list):
  1553. subsol = [subsol]
  1554. subsols.append(subsol)
  1555. # Full solution is cartesian product of subsystems
  1556. sols = []
  1557. for soldicts in product(*subsols):
  1558. sols.append(dict(item for sd in soldicts
  1559. for item in sd.items()))
  1560. return linear, sols
  1561. polys = []
  1562. dens = set()
  1563. failed = []
  1564. result = []
  1565. solved_syms = []
  1566. linear = True
  1567. manual = flags.get('manual', False)
  1568. checkdens = check = flags.get('check', True)
  1569. for j, g in enumerate(exprs):
  1570. dens.update(_simple_dens(g, symbols))
  1571. i, d = _invert(g, *symbols)
  1572. if d in symbols:
  1573. if linear:
  1574. linear = solve_linear(g, 0, [d])[0] == d
  1575. g = d - i
  1576. g = g.as_numer_denom()[0]
  1577. if manual:
  1578. failed.append(g)
  1579. continue
  1580. poly = g.as_poly(*symbols, extension=True)
  1581. if poly is not None:
  1582. polys.append(poly)
  1583. else:
  1584. failed.append(g)
  1585. if polys:
  1586. if all(p.is_linear for p in polys):
  1587. n, m = len(polys), len(symbols)
  1588. matrix = zeros(n, m + 1)
  1589. for i, poly in enumerate(polys):
  1590. for monom, coeff in poly.terms():
  1591. try:
  1592. j = monom.index(1)
  1593. matrix[i, j] = coeff
  1594. except ValueError:
  1595. matrix[i, m] = -coeff
  1596. # returns a dictionary ({symbols: values}) or None
  1597. if flags.pop('particular', False):
  1598. result = minsolve_linear_system(matrix, *symbols, **flags)
  1599. else:
  1600. result = solve_linear_system(matrix, *symbols, **flags)
  1601. result = [result] if result else []
  1602. if failed:
  1603. if result:
  1604. solved_syms = list(result[0].keys()) # there is only one result dict
  1605. else:
  1606. solved_syms = []
  1607. # linear doesn't change
  1608. else:
  1609. linear = False
  1610. if len(symbols) > len(polys):
  1611. free = set().union(*[p.free_symbols for p in polys])
  1612. free = list(ordered(free.intersection(symbols)))
  1613. got_s = set()
  1614. result = []
  1615. for syms in subsets(free, min(len(free), len(polys))):
  1616. try:
  1617. # returns [], None or list of tuples
  1618. res = solve_poly_system(polys, *syms)
  1619. if res:
  1620. for r in set(res):
  1621. skip = False
  1622. for r1 in r:
  1623. if got_s and any(ss in r1.free_symbols
  1624. for ss in got_s):
  1625. # sol depends on previously
  1626. # solved symbols: discard it
  1627. skip = True
  1628. if not skip:
  1629. got_s.update(syms)
  1630. result.append(dict(list(zip(syms, r))))
  1631. except NotImplementedError:
  1632. pass
  1633. if got_s:
  1634. solved_syms = list(got_s)
  1635. else:
  1636. failed.extend([g.as_expr() for g in polys])
  1637. else:
  1638. try:
  1639. result = solve_poly_system(polys, *symbols)
  1640. if result:
  1641. solved_syms = symbols
  1642. result = [dict(list(zip(solved_syms, r))) for r in set(result)]
  1643. except NotImplementedError:
  1644. failed.extend([g.as_expr() for g in polys])
  1645. solved_syms = []
  1646. # convert None or [] to [{}]
  1647. result = result or [{}]
  1648. if failed:
  1649. linear = False
  1650. # For each failed equation, see if we can solve for one of the
  1651. # remaining symbols from that equation. If so, we update the
  1652. # solution set and continue with the next failed equation,
  1653. # repeating until we are done or we get an equation that can't
  1654. # be solved.
  1655. def _ok_syms(e, sort=False):
  1656. rv = e.free_symbols & legal
  1657. # Solve first for symbols that have lower degree in the equation.
  1658. # Ideally we want to solve firstly for symbols that appear linearly
  1659. # with rational coefficients e.g. if e = x*y + z then we should
  1660. # solve for z first.
  1661. def key(sym):
  1662. ep = e.as_poly(sym)
  1663. if ep is None:
  1664. complexity = (S.Infinity, S.Infinity, S.Infinity)
  1665. else:
  1666. coeff_syms = ep.LC().free_symbols
  1667. complexity = (ep.degree(), len(coeff_syms & rv), len(coeff_syms))
  1668. return complexity + (default_sort_key(sym),)
  1669. if sort:
  1670. rv = sorted(rv, key=key)
  1671. return rv
  1672. legal = set(symbols) # what we are interested in
  1673. # sort so equation with the fewest potential symbols is first
  1674. u = Dummy() # used in solution checking
  1675. for eq in ordered(failed, lambda _: len(_ok_syms(_))):
  1676. newresult = []
  1677. bad_results = []
  1678. hit = False
  1679. for r in result:
  1680. got_s = set()
  1681. # update eq with everything that is known so far
  1682. eq2 = eq.subs(r)
  1683. # if check is True then we see if it satisfies this
  1684. # equation, otherwise we just accept it
  1685. if check and r:
  1686. b = checksol(u, u, eq2, minimal=True)
  1687. if b is not None:
  1688. # this solution is sufficient to know whether
  1689. # it is valid or not so we either accept or
  1690. # reject it, then continue
  1691. if b:
  1692. newresult.append(r)
  1693. else:
  1694. bad_results.append(r)
  1695. continue
  1696. # search for a symbol amongst those available that
  1697. # can be solved for
  1698. ok_syms = _ok_syms(eq2, sort=True)
  1699. if not ok_syms:
  1700. if r:
  1701. newresult.append(r)
  1702. break # skip as it's independent of desired symbols
  1703. for s in ok_syms:
  1704. try:
  1705. soln = _vsolve(eq2, s, **flags)
  1706. except NotImplementedError:
  1707. continue
  1708. # put each solution in r and append the now-expanded
  1709. # result in the new result list; use copy since the
  1710. # solution for s is being added in-place
  1711. for sol in soln:
  1712. if got_s and any(ss in sol.free_symbols for ss in got_s):
  1713. # sol depends on previously solved symbols: discard it
  1714. continue
  1715. rnew = r.copy()
  1716. for k, v in r.items():
  1717. rnew[k] = v.subs(s, sol)
  1718. # and add this new solution
  1719. rnew[s] = sol
  1720. # check that it is independent of previous solutions
  1721. iset = set(rnew.items())
  1722. for i in newresult:
  1723. if len(i) < len(iset):
  1724. # update i with what is known
  1725. i_items_updated = {(k, v.xreplace(rnew)) for k, v in i.items()}
  1726. if not i_items_updated - iset:
  1727. # this is a superset of a known solution that
  1728. # is smaller
  1729. break
  1730. else:
  1731. # keep it
  1732. newresult.append(rnew)
  1733. hit = True
  1734. got_s.add(s)
  1735. if not hit:
  1736. raise NotImplementedError('could not solve %s' % eq2)
  1737. else:
  1738. result = newresult
  1739. for b in bad_results:
  1740. if b in result:
  1741. result.remove(b)
  1742. if not result:
  1743. return False, []
  1744. # rely on linear/polynomial system solvers to simplify
  1745. # XXX the following tests show that the expressions
  1746. # returned are not the same as they would be if simplify
  1747. # were applied to this:
  1748. # sympy/solvers/ode/tests/test_systems/test__classify_linear_system
  1749. # sympy/solvers/tests/test_solvers/test_issue_4886
  1750. # so the docs should be updated to reflect that or else
  1751. # the following should be `bool(failed) or not linear`
  1752. default_simplify = bool(failed)
  1753. if flags.get('simplify', default_simplify):
  1754. for r in result:
  1755. for k in r:
  1756. r[k] = simplify(r[k])
  1757. flags['simplify'] = False # don't need to do so in checksol now
  1758. if checkdens:
  1759. result = [r for r in result
  1760. if not any(checksol(d, r, **flags) for d in dens)]
  1761. if check and not linear:
  1762. result = [r for r in result
  1763. if not any(checksol(e, r, **flags) is False for e in exprs)]
  1764. result = [r for r in result if r]
  1765. return linear, result
  1766. def solve_linear(lhs, rhs=0, symbols=[], exclude=[]):
  1767. r"""
  1768. Return a tuple derived from ``f = lhs - rhs`` that is one of
  1769. the following: ``(0, 1)``, ``(0, 0)``, ``(symbol, solution)``, ``(n, d)``.
  1770. Explanation
  1771. ===========
  1772. ``(0, 1)`` meaning that ``f`` is independent of the symbols in *symbols*
  1773. that are not in *exclude*.
  1774. ``(0, 0)`` meaning that there is no solution to the equation amongst the
  1775. symbols given. If the first element of the tuple is not zero, then the
  1776. function is guaranteed to be dependent on a symbol in *symbols*.
  1777. ``(symbol, solution)`` where symbol appears linearly in the numerator of
  1778. ``f``, is in *symbols* (if given), and is not in *exclude* (if given). No
  1779. simplification is done to ``f`` other than a ``mul=True`` expansion, so the
  1780. solution will correspond strictly to a unique solution.
  1781. ``(n, d)`` where ``n`` and ``d`` are the numerator and denominator of ``f``
  1782. when the numerator was not linear in any symbol of interest; ``n`` will
  1783. never be a symbol unless a solution for that symbol was found (in which case
  1784. the second element is the solution, not the denominator).
  1785. Examples
  1786. ========
  1787. >>> from sympy import cancel, Pow
  1788. ``f`` is independent of the symbols in *symbols* that are not in
  1789. *exclude*:
  1790. >>> from sympy import cos, sin, solve_linear
  1791. >>> from sympy.abc import x, y, z
  1792. >>> eq = y*cos(x)**2 + y*sin(x)**2 - y # = y*(1 - 1) = 0
  1793. >>> solve_linear(eq)
  1794. (0, 1)
  1795. >>> eq = cos(x)**2 + sin(x)**2 # = 1
  1796. >>> solve_linear(eq)
  1797. (0, 1)
  1798. >>> solve_linear(x, exclude=[x])
  1799. (0, 1)
  1800. The variable ``x`` appears as a linear variable in each of the
  1801. following:
  1802. >>> solve_linear(x + y**2)
  1803. (x, -y**2)
  1804. >>> solve_linear(1/x - y**2)
  1805. (x, y**(-2))
  1806. When not linear in ``x`` or ``y`` then the numerator and denominator are
  1807. returned:
  1808. >>> solve_linear(x**2/y**2 - 3)
  1809. (x**2 - 3*y**2, y**2)
  1810. If the numerator of the expression is a symbol, then ``(0, 0)`` is
  1811. returned if the solution for that symbol would have set any
  1812. denominator to 0:
  1813. >>> eq = 1/(1/x - 2)
  1814. >>> eq.as_numer_denom()
  1815. (x, 1 - 2*x)
  1816. >>> solve_linear(eq)
  1817. (0, 0)
  1818. But automatic rewriting may cause a symbol in the denominator to
  1819. appear in the numerator so a solution will be returned:
  1820. >>> (1/x)**-1
  1821. x
  1822. >>> solve_linear((1/x)**-1)
  1823. (x, 0)
  1824. Use an unevaluated expression to avoid this:
  1825. >>> solve_linear(Pow(1/x, -1, evaluate=False))
  1826. (0, 0)
  1827. If ``x`` is allowed to cancel in the following expression, then it
  1828. appears to be linear in ``x``, but this sort of cancellation is not
  1829. done by ``solve_linear`` so the solution will always satisfy the
  1830. original expression without causing a division by zero error.
  1831. >>> eq = x**2*(1/x - z**2/x)
  1832. >>> solve_linear(cancel(eq))
  1833. (x, 0)
  1834. >>> solve_linear(eq)
  1835. (x**2*(1 - z**2), x)
  1836. A list of symbols for which a solution is desired may be given:
  1837. >>> solve_linear(x + y + z, symbols=[y])
  1838. (y, -x - z)
  1839. A list of symbols to ignore may also be given:
  1840. >>> solve_linear(x + y + z, exclude=[x])
  1841. (y, -x - z)
  1842. (A solution for ``y`` is obtained because it is the first variable
  1843. from the canonically sorted list of symbols that had a linear
  1844. solution.)
  1845. """
  1846. if isinstance(lhs, Eq):
  1847. if rhs:
  1848. raise ValueError(filldedent('''
  1849. If lhs is an Equality, rhs must be 0 but was %s''' % rhs))
  1850. rhs = lhs.rhs
  1851. lhs = lhs.lhs
  1852. dens = None
  1853. eq = lhs - rhs
  1854. n, d = eq.as_numer_denom()
  1855. if not n:
  1856. return S.Zero, S.One
  1857. free = n.free_symbols
  1858. if not symbols:
  1859. symbols = free
  1860. else:
  1861. bad = [s for s in symbols if not s.is_Symbol]
  1862. if bad:
  1863. if len(bad) == 1:
  1864. bad = bad[0]
  1865. if len(symbols) == 1:
  1866. eg = 'solve(%s, %s)' % (eq, symbols[0])
  1867. else:
  1868. eg = 'solve(%s, *%s)' % (eq, list(symbols))
  1869. raise ValueError(filldedent('''
  1870. solve_linear only handles symbols, not %s. To isolate
  1871. non-symbols use solve, e.g. >>> %s <<<.
  1872. ''' % (bad, eg)))
  1873. symbols = free.intersection(symbols)
  1874. symbols = symbols.difference(exclude)
  1875. if not symbols:
  1876. return S.Zero, S.One
  1877. # derivatives are easy to do but tricky to analyze to see if they
  1878. # are going to disallow a linear solution, so for simplicity we
  1879. # just evaluate the ones that have the symbols of interest
  1880. derivs = defaultdict(list)
  1881. for der in n.atoms(Derivative):
  1882. csym = der.free_symbols & symbols
  1883. for c in csym:
  1884. derivs[c].append(der)
  1885. all_zero = True
  1886. for xi in sorted(symbols, key=default_sort_key): # canonical order
  1887. # if there are derivatives in this var, calculate them now
  1888. if isinstance(derivs[xi], list):
  1889. derivs[xi] = {der: der.doit() for der in derivs[xi]}
  1890. newn = n.subs(derivs[xi])
  1891. dnewn_dxi = newn.diff(xi)
  1892. # dnewn_dxi can be nonzero if it survives differentation by any
  1893. # of its free symbols
  1894. free = dnewn_dxi.free_symbols
  1895. if dnewn_dxi and (not free or any(dnewn_dxi.diff(s) for s in free) or free == symbols):
  1896. all_zero = False
  1897. if dnewn_dxi is S.NaN:
  1898. break
  1899. if xi not in dnewn_dxi.free_symbols:
  1900. vi = -1/dnewn_dxi*(newn.subs(xi, 0))
  1901. if dens is None:
  1902. dens = _simple_dens(eq, symbols)
  1903. if not any(checksol(di, {xi: vi}, minimal=True) is True
  1904. for di in dens):
  1905. # simplify any trivial integral
  1906. irep = [(i, i.doit()) for i in vi.atoms(Integral) if
  1907. i.function.is_number]
  1908. # do a slight bit of simplification
  1909. vi = expand_mul(vi.subs(irep))
  1910. return xi, vi
  1911. if all_zero:
  1912. return S.Zero, S.One
  1913. if n.is_Symbol: # no solution for this symbol was found
  1914. return S.Zero, S.Zero
  1915. return n, d
  1916. def minsolve_linear_system(system, *symbols, **flags):
  1917. r"""
  1918. Find a particular solution to a linear system.
  1919. Explanation
  1920. ===========
  1921. In particular, try to find a solution with the minimal possible number
  1922. of non-zero variables using a naive algorithm with exponential complexity.
  1923. If ``quick=True``, a heuristic is used.
  1924. """
  1925. quick = flags.get('quick', False)
  1926. # Check if there are any non-zero solutions at all
  1927. s0 = solve_linear_system(system, *symbols, **flags)
  1928. if not s0 or all(v == 0 for v in s0.values()):
  1929. return s0
  1930. if quick:
  1931. # We just solve the system and try to heuristically find a nice
  1932. # solution.
  1933. s = solve_linear_system(system, *symbols)
  1934. def update(determined, solution):
  1935. delete = []
  1936. for k, v in solution.items():
  1937. solution[k] = v.subs(determined)
  1938. if not solution[k].free_symbols:
  1939. delete.append(k)
  1940. determined[k] = solution[k]
  1941. for k in delete:
  1942. del solution[k]
  1943. determined = {}
  1944. update(determined, s)
  1945. while s:
  1946. # NOTE sort by default_sort_key to get deterministic result
  1947. k = max((k for k in s.values()),
  1948. key=lambda x: (len(x.free_symbols), default_sort_key(x)))
  1949. kfree = k.free_symbols
  1950. x = next(reversed(list(ordered(kfree))))
  1951. if len(kfree) != 1:
  1952. determined[x] = S.Zero
  1953. else:
  1954. val = _vsolve(k, x, check=False)[0]
  1955. if not val and not any(v.subs(x, val) for v in s.values()):
  1956. determined[x] = S.One
  1957. else:
  1958. determined[x] = val
  1959. update(determined, s)
  1960. return determined
  1961. else:
  1962. # We try to select n variables which we want to be non-zero.
  1963. # All others will be assumed zero. We try to solve the modified system.
  1964. # If there is a non-trivial solution, just set the free variables to
  1965. # one. If we do this for increasing n, trying all combinations of
  1966. # variables, we will find an optimal solution.
  1967. # We speed up slightly by starting at one less than the number of
  1968. # variables the quick method manages.
  1969. N = len(symbols)
  1970. bestsol = minsolve_linear_system(system, *symbols, quick=True)
  1971. n0 = len([x for x in bestsol.values() if x != 0])
  1972. for n in range(n0 - 1, 1, -1):
  1973. debugf('minsolve: %s', n)
  1974. thissol = None
  1975. for nonzeros in combinations(range(N), n):
  1976. subm = Matrix([system.col(i).T for i in nonzeros] + [system.col(-1).T]).T
  1977. s = solve_linear_system(subm, *[symbols[i] for i in nonzeros])
  1978. if s and not all(v == 0 for v in s.values()):
  1979. subs = [(symbols[v], S.One) for v in nonzeros]
  1980. for k, v in s.items():
  1981. s[k] = v.subs(subs)
  1982. for sym in symbols:
  1983. if sym not in s:
  1984. if symbols.index(sym) in nonzeros:
  1985. s[sym] = S.One
  1986. else:
  1987. s[sym] = S.Zero
  1988. thissol = s
  1989. break
  1990. if thissol is None:
  1991. break
  1992. bestsol = thissol
  1993. return bestsol
  1994. def solve_linear_system(system, *symbols, **flags):
  1995. r"""
  1996. Solve system of $N$ linear equations with $M$ variables, which means
  1997. both under- and overdetermined systems are supported.
  1998. Explanation
  1999. ===========
  2000. The possible number of solutions is zero, one, or infinite. Respectively,
  2001. this procedure will return None or a dictionary with solutions. In the
  2002. case of underdetermined systems, all arbitrary parameters are skipped.
  2003. This may cause a situation in which an empty dictionary is returned.
  2004. In that case, all symbols can be assigned arbitrary values.
  2005. Input to this function is a $N\times M + 1$ matrix, which means it has
  2006. to be in augmented form. If you prefer to enter $N$ equations and $M$
  2007. unknowns then use ``solve(Neqs, *Msymbols)`` instead. Note: a local
  2008. copy of the matrix is made by this routine so the matrix that is
  2009. passed will not be modified.
  2010. The algorithm used here is fraction-free Gaussian elimination,
  2011. which results, after elimination, in an upper-triangular matrix.
  2012. Then solutions are found using back-substitution. This approach
  2013. is more efficient and compact than the Gauss-Jordan method.
  2014. Examples
  2015. ========
  2016. >>> from sympy import Matrix, solve_linear_system
  2017. >>> from sympy.abc import x, y
  2018. Solve the following system::
  2019. x + 4 y == 2
  2020. -2 x + y == 14
  2021. >>> system = Matrix(( (1, 4, 2), (-2, 1, 14)))
  2022. >>> solve_linear_system(system, x, y)
  2023. {x: -6, y: 2}
  2024. A degenerate system returns an empty dictionary:
  2025. >>> system = Matrix(( (0,0,0), (0,0,0) ))
  2026. >>> solve_linear_system(system, x, y)
  2027. {}
  2028. """
  2029. assert system.shape[1] == len(symbols) + 1
  2030. # This is just a wrapper for solve_lin_sys
  2031. eqs = list(system * Matrix(symbols + (-1,)))
  2032. eqs, ring = sympy_eqs_to_ring(eqs, symbols)
  2033. sol = solve_lin_sys(eqs, ring, _raw=False)
  2034. if sol is not None:
  2035. sol = {sym:val for sym, val in sol.items() if sym != val}
  2036. return sol
  2037. def solve_undetermined_coeffs(equ, coeffs, *syms, **flags):
  2038. r"""
  2039. Solve a system of equations in $k$ parameters that is formed by
  2040. matching coefficients in variables ``coeffs`` that are on
  2041. factors dependent on the remaining variables (or those given
  2042. explicitly by ``syms``.
  2043. Explanation
  2044. ===========
  2045. The result of this function is a dictionary with symbolic values of those
  2046. parameters with respect to coefficients in $q$ -- empty if there
  2047. is no solution or coefficients do not appear in the equation -- else
  2048. None (if the system was not recognized). If there is more than one
  2049. solution, the solutions are passed as a list. The output can be modified using
  2050. the same semantics as for `solve` since the flags that are passed are sent
  2051. directly to `solve` so, for example the flag ``dict=True`` will always return a list
  2052. of solutions as dictionaries.
  2053. This function accepts both Equality and Expr class instances.
  2054. The solving process is most efficient when symbols are specified
  2055. in addition to parameters to be determined, but an attempt to
  2056. determine them (if absent) will be made. If an expected solution is not
  2057. obtained (and symbols were not specified) try specifying them.
  2058. Examples
  2059. ========
  2060. >>> from sympy import Eq, solve_undetermined_coeffs
  2061. >>> from sympy.abc import a, b, c, h, p, k, x, y
  2062. >>> solve_undetermined_coeffs(Eq(a*x + a + b, x/2), [a, b], x)
  2063. {a: 1/2, b: -1/2}
  2064. >>> solve_undetermined_coeffs(a - 2, [a])
  2065. {a: 2}
  2066. The equation can be nonlinear in the symbols:
  2067. >>> X, Y, Z = y, x**y, y*x**y
  2068. >>> eq = a*X + b*Y + c*Z - X - 2*Y - 3*Z
  2069. >>> coeffs = a, b, c
  2070. >>> syms = x, y
  2071. >>> solve_undetermined_coeffs(eq, coeffs, syms)
  2072. {a: 1, b: 2, c: 3}
  2073. And the system can be nonlinear in coefficients, too, but if
  2074. there is only a single solution, it will be returned as a
  2075. dictionary:
  2076. >>> eq = a*x**2 + b*x + c - ((x - h)**2 + 4*p*k)/4/p
  2077. >>> solve_undetermined_coeffs(eq, (h, p, k), x)
  2078. {h: -b/(2*a), k: (4*a*c - b**2)/(4*a), p: 1/(4*a)}
  2079. Multiple solutions are always returned in a list:
  2080. >>> solve_undetermined_coeffs(a**2*x + b - x, [a, b], x)
  2081. [{a: -1, b: 0}, {a: 1, b: 0}]
  2082. Using flag ``dict=True`` (in keeping with semantics in :func:`~.solve`)
  2083. will force the result to always be a list with any solutions
  2084. as elements in that list.
  2085. >>> solve_undetermined_coeffs(a*x - 2*x, [a], dict=True)
  2086. [{a: 2}]
  2087. """
  2088. if not (coeffs and all(i.is_Symbol for i in coeffs)):
  2089. raise ValueError('must provide symbols for coeffs')
  2090. if isinstance(equ, Eq):
  2091. eq = equ.lhs - equ.rhs
  2092. else:
  2093. eq = equ
  2094. ceq = cancel(eq)
  2095. xeq = _mexpand(ceq.as_numer_denom()[0], recursive=True)
  2096. free = xeq.free_symbols
  2097. coeffs = free & set(coeffs)
  2098. if not coeffs:
  2099. return ([], {}) if flags.get('set', None) else [] # solve(0, x) -> []
  2100. if not syms:
  2101. # e.g. A*exp(x) + B - (exp(x) + y) separated into parts that
  2102. # don't/do depend on coeffs gives
  2103. # -(exp(x) + y), A*exp(x) + B
  2104. # then see what symbols are common to both
  2105. # {x} = {x, A, B} - {x, y}
  2106. ind, dep = xeq.as_independent(*coeffs, as_Add=True)
  2107. dfree = dep.free_symbols
  2108. syms = dfree & ind.free_symbols
  2109. if not syms:
  2110. # but if the system looks like (a + b)*x + b - c
  2111. # then {} = {a, b, x} - c
  2112. # so calculate {x} = {a, b, x} - {a, b}
  2113. syms = dfree - set(coeffs)
  2114. if not syms:
  2115. syms = [Dummy()]
  2116. else:
  2117. if len(syms) == 1 and iterable(syms[0]):
  2118. syms = syms[0]
  2119. e, s, _ = recast_to_symbols([xeq], syms)
  2120. xeq = e[0]
  2121. syms = s
  2122. # find the functional forms in which symbols appear
  2123. gens = set(xeq.as_coefficients_dict(*syms).keys()) - {1}
  2124. cset = set(coeffs)
  2125. if any(g.has_xfree(cset) for g in gens):
  2126. return # a generator contained a coefficient symbol
  2127. # make sure we are working with symbols for generators
  2128. e, gens, _ = recast_to_symbols([xeq], list(gens))
  2129. xeq = e[0]
  2130. # collect coefficients in front of generators
  2131. system = list(collect(xeq, gens, evaluate=False).values())
  2132. # get a solution
  2133. soln = solve(system, coeffs, **flags)
  2134. # unpack unless told otherwise if length is 1
  2135. settings = flags.get('dict', None) or flags.get('set', None)
  2136. if type(soln) is dict or settings or len(soln) != 1:
  2137. return soln
  2138. return soln[0]
  2139. def solve_linear_system_LU(matrix, syms):
  2140. """
  2141. Solves the augmented matrix system using ``LUsolve`` and returns a
  2142. dictionary in which solutions are keyed to the symbols of *syms* as ordered.
  2143. Explanation
  2144. ===========
  2145. The matrix must be invertible.
  2146. Examples
  2147. ========
  2148. >>> from sympy import Matrix, solve_linear_system_LU
  2149. >>> from sympy.abc import x, y, z
  2150. >>> solve_linear_system_LU(Matrix([
  2151. ... [1, 2, 0, 1],
  2152. ... [3, 2, 2, 1],
  2153. ... [2, 0, 0, 1]]), [x, y, z])
  2154. {x: 1/2, y: 1/4, z: -1/2}
  2155. See Also
  2156. ========
  2157. LUsolve
  2158. """
  2159. if matrix.rows != matrix.cols - 1:
  2160. raise ValueError("Rows should be equal to columns - 1")
  2161. A = matrix[:matrix.rows, :matrix.rows]
  2162. b = matrix[:, matrix.cols - 1:]
  2163. soln = A.LUsolve(b)
  2164. solutions = {}
  2165. for i in range(soln.rows):
  2166. solutions[syms[i]] = soln[i, 0]
  2167. return solutions
  2168. def det_perm(M):
  2169. """
  2170. Return the determinant of *M* by using permutations to select factors.
  2171. Explanation
  2172. ===========
  2173. For sizes larger than 8 the number of permutations becomes prohibitively
  2174. large, or if there are no symbols in the matrix, it is better to use the
  2175. standard determinant routines (e.g., ``M.det()``.)
  2176. See Also
  2177. ========
  2178. det_minor
  2179. det_quick
  2180. """
  2181. args = []
  2182. s = True
  2183. n = M.rows
  2184. list_ = M.flat()
  2185. for perm in generate_bell(n):
  2186. fac = []
  2187. idx = 0
  2188. for j in perm:
  2189. fac.append(list_[idx + j])
  2190. idx += n
  2191. term = Mul(*fac) # disaster with unevaluated Mul -- takes forever for n=7
  2192. args.append(term if s else -term)
  2193. s = not s
  2194. return Add(*args)
  2195. def det_minor(M):
  2196. """
  2197. Return the ``det(M)`` computed from minors without
  2198. introducing new nesting in products.
  2199. See Also
  2200. ========
  2201. det_perm
  2202. det_quick
  2203. """
  2204. n = M.rows
  2205. if n == 2:
  2206. return M[0, 0]*M[1, 1] - M[1, 0]*M[0, 1]
  2207. else:
  2208. return sum((1, -1)[i % 2]*Add(*[M[0, i]*d for d in
  2209. Add.make_args(det_minor(M.minor_submatrix(0, i)))])
  2210. if M[0, i] else S.Zero for i in range(n))
  2211. def det_quick(M, method=None):
  2212. """
  2213. Return ``det(M)`` assuming that either
  2214. there are lots of zeros or the size of the matrix
  2215. is small. If this assumption is not met, then the normal
  2216. Matrix.det function will be used with method = ``method``.
  2217. See Also
  2218. ========
  2219. det_minor
  2220. det_perm
  2221. """
  2222. if any(i.has(Symbol) for i in M):
  2223. if M.rows < 8 and all(i.has(Symbol) for i in M):
  2224. return det_perm(M)
  2225. return det_minor(M)
  2226. else:
  2227. return M.det(method=method) if method else M.det()
  2228. def inv_quick(M):
  2229. """Return the inverse of ``M``, assuming that either
  2230. there are lots of zeros or the size of the matrix
  2231. is small.
  2232. """
  2233. if not all(i.is_Number for i in M):
  2234. if not any(i.is_Number for i in M):
  2235. det = lambda _: det_perm(_)
  2236. else:
  2237. det = lambda _: det_minor(_)
  2238. else:
  2239. return M.inv()
  2240. n = M.rows
  2241. d = det(M)
  2242. if d == S.Zero:
  2243. raise NonInvertibleMatrixError("Matrix det == 0; not invertible")
  2244. ret = zeros(n)
  2245. s1 = -1
  2246. for i in range(n):
  2247. s = s1 = -s1
  2248. for j in range(n):
  2249. di = det(M.minor_submatrix(i, j))
  2250. ret[j, i] = s*di/d
  2251. s = -s
  2252. return ret
  2253. # these are functions that have multiple inverse values per period
  2254. multi_inverses = {
  2255. sin: lambda x: (asin(x), S.Pi - asin(x)),
  2256. cos: lambda x: (acos(x), 2*S.Pi - acos(x)),
  2257. }
  2258. def _vsolve(e, s, **flags):
  2259. """return list of scalar values for the solution of e for symbol s"""
  2260. return [i[s] for i in _solve(e, s, **flags)]
  2261. def _tsolve(eq, sym, **flags):
  2262. """
  2263. Helper for ``_solve`` that solves a transcendental equation with respect
  2264. to the given symbol. Various equations containing powers and logarithms,
  2265. can be solved.
  2266. There is currently no guarantee that all solutions will be returned or
  2267. that a real solution will be favored over a complex one.
  2268. Either a list of potential solutions will be returned or None will be
  2269. returned (in the case that no method was known to get a solution
  2270. for the equation). All other errors (like the inability to cast an
  2271. expression as a Poly) are unhandled.
  2272. Examples
  2273. ========
  2274. >>> from sympy import log, ordered
  2275. >>> from sympy.solvers.solvers import _tsolve as tsolve
  2276. >>> from sympy.abc import x
  2277. >>> list(ordered(tsolve(3**(2*x + 5) - 4, x)))
  2278. [-5/2 + log(2)/log(3), (-5*log(3)/2 + log(2) + I*pi)/log(3)]
  2279. >>> tsolve(log(x) + 2*x, x)
  2280. [LambertW(2)/2]
  2281. """
  2282. if 'tsolve_saw' not in flags:
  2283. flags['tsolve_saw'] = []
  2284. if eq in flags['tsolve_saw']:
  2285. return None
  2286. else:
  2287. flags['tsolve_saw'].append(eq)
  2288. rhs, lhs = _invert(eq, sym)
  2289. if lhs == sym:
  2290. return [rhs]
  2291. try:
  2292. if lhs.is_Add:
  2293. # it's time to try factoring; powdenest is used
  2294. # to try get powers in standard form for better factoring
  2295. f = factor(powdenest(lhs - rhs))
  2296. if f.is_Mul:
  2297. return _vsolve(f, sym, **flags)
  2298. if rhs:
  2299. f = logcombine(lhs, force=flags.get('force', True))
  2300. if f.count(log) != lhs.count(log):
  2301. if isinstance(f, log):
  2302. return _vsolve(f.args[0] - exp(rhs), sym, **flags)
  2303. return _tsolve(f - rhs, sym, **flags)
  2304. elif lhs.is_Pow:
  2305. if lhs.exp.is_Integer:
  2306. if lhs - rhs != eq:
  2307. return _vsolve(lhs - rhs, sym, **flags)
  2308. if sym not in lhs.exp.free_symbols:
  2309. return _vsolve(lhs.base - rhs**(1/lhs.exp), sym, **flags)
  2310. # _tsolve calls this with Dummy before passing the actual number in.
  2311. if any(t.is_Dummy for t in rhs.free_symbols):
  2312. raise NotImplementedError # _tsolve will call here again...
  2313. # a ** g(x) == 0
  2314. if not rhs:
  2315. # f(x)**g(x) only has solutions where f(x) == 0 and g(x) != 0 at
  2316. # the same place
  2317. sol_base = _vsolve(lhs.base, sym, **flags)
  2318. return [s for s in sol_base if lhs.exp.subs(sym, s) != 0] # XXX use checksol here?
  2319. # a ** g(x) == b
  2320. if not lhs.base.has(sym):
  2321. if lhs.base == 0:
  2322. return _vsolve(lhs.exp, sym, **flags) if rhs != 0 else []
  2323. # Gets most solutions...
  2324. if lhs.base == rhs.as_base_exp()[0]:
  2325. # handles case when bases are equal
  2326. sol = _vsolve(lhs.exp - rhs.as_base_exp()[1], sym, **flags)
  2327. else:
  2328. # handles cases when bases are not equal and exp
  2329. # may or may not be equal
  2330. f = exp(log(lhs.base)*lhs.exp) - exp(log(rhs))
  2331. sol = _vsolve(f, sym, **flags)
  2332. # Check for duplicate solutions
  2333. def equal(expr1, expr2):
  2334. _ = Dummy()
  2335. eq = checksol(expr1 - _, _, expr2)
  2336. if eq is None:
  2337. if nsimplify(expr1) != nsimplify(expr2):
  2338. return False
  2339. # they might be coincidentally the same
  2340. # so check more rigorously
  2341. eq = expr1.equals(expr2) # XXX expensive but necessary?
  2342. return eq
  2343. # Guess a rational exponent
  2344. e_rat = nsimplify(log(abs(rhs))/log(abs(lhs.base)))
  2345. e_rat = simplify(posify(e_rat)[0])
  2346. n, d = fraction(e_rat)
  2347. if expand(lhs.base**n - rhs**d) == 0:
  2348. sol = [s for s in sol if not equal(lhs.exp.subs(sym, s), e_rat)]
  2349. sol.extend(_vsolve(lhs.exp - e_rat, sym, **flags))
  2350. return list(set(sol))
  2351. # f(x) ** g(x) == c
  2352. else:
  2353. sol = []
  2354. logform = lhs.exp*log(lhs.base) - log(rhs)
  2355. if logform != lhs - rhs:
  2356. try:
  2357. sol.extend(_vsolve(logform, sym, **flags))
  2358. except NotImplementedError:
  2359. pass
  2360. # Collect possible solutions and check with substitution later.
  2361. check = []
  2362. if rhs == 1:
  2363. # f(x) ** g(x) = 1 -- g(x)=0 or f(x)=+-1
  2364. check.extend(_vsolve(lhs.exp, sym, **flags))
  2365. check.extend(_vsolve(lhs.base - 1, sym, **flags))
  2366. check.extend(_vsolve(lhs.base + 1, sym, **flags))
  2367. elif rhs.is_Rational:
  2368. for d in (i for i in divisors(abs(rhs.p)) if i != 1):
  2369. e, t = integer_log(rhs.p, d)
  2370. if not t:
  2371. continue # rhs.p != d**b
  2372. for s in divisors(abs(rhs.q)):
  2373. if s**e== rhs.q:
  2374. r = Rational(d, s)
  2375. check.extend(_vsolve(lhs.base - r, sym, **flags))
  2376. check.extend(_vsolve(lhs.base + r, sym, **flags))
  2377. check.extend(_vsolve(lhs.exp - e, sym, **flags))
  2378. elif rhs.is_irrational:
  2379. b_l, e_l = lhs.base.as_base_exp()
  2380. n, d = (e_l*lhs.exp).as_numer_denom()
  2381. b, e = sqrtdenest(rhs).as_base_exp()
  2382. check = [sqrtdenest(i) for i in (_vsolve(lhs.base - b, sym, **flags))]
  2383. check.extend([sqrtdenest(i) for i in (_vsolve(lhs.exp - e, sym, **flags))])
  2384. if e_l*d != 1:
  2385. check.extend(_vsolve(b_l**n - rhs**(e_l*d), sym, **flags))
  2386. for s in check:
  2387. ok = checksol(eq, sym, s)
  2388. if ok is None:
  2389. ok = eq.subs(sym, s).equals(0)
  2390. if ok:
  2391. sol.append(s)
  2392. return list(set(sol))
  2393. elif lhs.is_Function and len(lhs.args) == 1:
  2394. if lhs.func in multi_inverses:
  2395. # sin(x) = 1/3 -> x - asin(1/3) & x - (pi - asin(1/3))
  2396. soln = []
  2397. for i in multi_inverses[type(lhs)](rhs):
  2398. soln.extend(_vsolve(lhs.args[0] - i, sym, **flags))
  2399. return list(set(soln))
  2400. elif lhs.func == LambertW:
  2401. return _vsolve(lhs.args[0] - rhs*exp(rhs), sym, **flags)
  2402. rewrite = lhs.rewrite(exp)
  2403. rewrite = rebuild(rewrite) # avoid rewrites involving evaluate=False
  2404. if rewrite != lhs:
  2405. return _vsolve(rewrite - rhs, sym, **flags)
  2406. except NotImplementedError:
  2407. pass
  2408. # maybe it is a lambert pattern
  2409. if flags.pop('bivariate', True):
  2410. # lambert forms may need some help being recognized, e.g. changing
  2411. # 2**(3*x) + x**3*log(2)**3 + 3*x**2*log(2)**2 + 3*x*log(2) + 1
  2412. # to 2**(3*x) + (x*log(2) + 1)**3
  2413. # make generator in log have exponent of 1
  2414. logs = eq.atoms(log)
  2415. spow = min(
  2416. {i.exp for j in logs for i in j.atoms(Pow)
  2417. if i.base == sym} or {1})
  2418. if spow != 1:
  2419. p = sym**spow
  2420. u = Dummy('bivariate-cov')
  2421. ueq = eq.subs(p, u)
  2422. if not ueq.has_free(sym):
  2423. sol = _vsolve(ueq, u, **flags)
  2424. inv = _vsolve(p - u, sym)
  2425. return [i.subs(u, s) for i in inv for s in sol]
  2426. g = _filtered_gens(eq.as_poly(), sym)
  2427. up_or_log = set()
  2428. for gi in g:
  2429. if isinstance(gi, (exp, log)) or (gi.is_Pow and gi.base == S.Exp1):
  2430. up_or_log.add(gi)
  2431. elif gi.is_Pow:
  2432. gisimp = powdenest(expand_power_exp(gi))
  2433. if gisimp.is_Pow and sym in gisimp.exp.free_symbols:
  2434. up_or_log.add(gi)
  2435. eq_down = expand_log(expand_power_exp(eq)).subs(
  2436. dict(list(zip(up_or_log, [0]*len(up_or_log)))))
  2437. eq = expand_power_exp(factor(eq_down, deep=True) + (eq - eq_down))
  2438. rhs, lhs = _invert(eq, sym)
  2439. if lhs.has(sym):
  2440. try:
  2441. poly = lhs.as_poly()
  2442. g = _filtered_gens(poly, sym)
  2443. _eq = lhs - rhs
  2444. sols = _solve_lambert(_eq, sym, g)
  2445. # use a simplified form if it satisfies eq
  2446. # and has fewer operations
  2447. for n, s in enumerate(sols):
  2448. ns = nsimplify(s)
  2449. if ns != s and ns.count_ops() <= s.count_ops():
  2450. ok = checksol(_eq, sym, ns)
  2451. if ok is None:
  2452. ok = _eq.subs(sym, ns).equals(0)
  2453. if ok:
  2454. sols[n] = ns
  2455. return sols
  2456. except NotImplementedError:
  2457. # maybe it's a convoluted function
  2458. if len(g) == 2:
  2459. try:
  2460. gpu = bivariate_type(lhs - rhs, *g)
  2461. if gpu is None:
  2462. raise NotImplementedError
  2463. g, p, u = gpu
  2464. flags['bivariate'] = False
  2465. inversion = _tsolve(g - u, sym, **flags)
  2466. if inversion:
  2467. sol = _vsolve(p, u, **flags)
  2468. return list({i.subs(u, s)
  2469. for i in inversion for s in sol})
  2470. except NotImplementedError:
  2471. pass
  2472. else:
  2473. pass
  2474. if flags.pop('force', True):
  2475. flags['force'] = False
  2476. pos, reps = posify(lhs - rhs)
  2477. if rhs == S.ComplexInfinity:
  2478. return []
  2479. for u, s in reps.items():
  2480. if s == sym:
  2481. break
  2482. else:
  2483. u = sym
  2484. if pos.has(u):
  2485. try:
  2486. soln = _vsolve(pos, u, **flags)
  2487. return [s.subs(reps) for s in soln]
  2488. except NotImplementedError:
  2489. pass
  2490. else:
  2491. pass # here for coverage
  2492. return # here for coverage
  2493. # TODO: option for calculating J numerically
  2494. @conserve_mpmath_dps
  2495. def nsolve(*args, dict=False, **kwargs):
  2496. r"""
  2497. Solve a nonlinear equation system numerically: ``nsolve(f, [args,] x0,
  2498. modules=['mpmath'], **kwargs)``.
  2499. Explanation
  2500. ===========
  2501. ``f`` is a vector function of symbolic expressions representing the system.
  2502. *args* are the variables. If there is only one variable, this argument can
  2503. be omitted. ``x0`` is a starting vector close to a solution.
  2504. Use the modules keyword to specify which modules should be used to
  2505. evaluate the function and the Jacobian matrix. Make sure to use a module
  2506. that supports matrices. For more information on the syntax, please see the
  2507. docstring of ``lambdify``.
  2508. If the keyword arguments contain ``dict=True`` (default is False) ``nsolve``
  2509. will return a list (perhaps empty) of solution mappings. This might be
  2510. especially useful if you want to use ``nsolve`` as a fallback to solve since
  2511. using the dict argument for both methods produces return values of
  2512. consistent type structure. Please note: to keep this consistent with
  2513. ``solve``, the solution will be returned in a list even though ``nsolve``
  2514. (currently at least) only finds one solution at a time.
  2515. Overdetermined systems are supported.
  2516. Examples
  2517. ========
  2518. >>> from sympy import Symbol, nsolve
  2519. >>> import mpmath
  2520. >>> mpmath.mp.dps = 15
  2521. >>> x1 = Symbol('x1')
  2522. >>> x2 = Symbol('x2')
  2523. >>> f1 = 3 * x1**2 - 2 * x2**2 - 1
  2524. >>> f2 = x1**2 - 2 * x1 + x2**2 + 2 * x2 - 8
  2525. >>> print(nsolve((f1, f2), (x1, x2), (-1, 1)))
  2526. Matrix([[-1.19287309935246], [1.27844411169911]])
  2527. For one-dimensional functions the syntax is simplified:
  2528. >>> from sympy import sin, nsolve
  2529. >>> from sympy.abc import x
  2530. >>> nsolve(sin(x), x, 2)
  2531. 3.14159265358979
  2532. >>> nsolve(sin(x), 2)
  2533. 3.14159265358979
  2534. To solve with higher precision than the default, use the prec argument:
  2535. >>> from sympy import cos
  2536. >>> nsolve(cos(x) - x, 1)
  2537. 0.739085133215161
  2538. >>> nsolve(cos(x) - x, 1, prec=50)
  2539. 0.73908513321516064165531208767387340401341175890076
  2540. >>> cos(_)
  2541. 0.73908513321516064165531208767387340401341175890076
  2542. To solve for complex roots of real functions, a nonreal initial point
  2543. must be specified:
  2544. >>> from sympy import I
  2545. >>> nsolve(x**2 + 2, I)
  2546. 1.4142135623731*I
  2547. ``mpmath.findroot`` is used and you can find their more extensive
  2548. documentation, especially concerning keyword parameters and
  2549. available solvers. Note, however, that functions which are very
  2550. steep near the root, the verification of the solution may fail. In
  2551. this case you should use the flag ``verify=False`` and
  2552. independently verify the solution.
  2553. >>> from sympy import cos, cosh
  2554. >>> f = cos(x)*cosh(x) - 1
  2555. >>> nsolve(f, 3.14*100)
  2556. Traceback (most recent call last):
  2557. ...
  2558. ValueError: Could not find root within given tolerance. (1.39267e+230 > 2.1684e-19)
  2559. >>> ans = nsolve(f, 3.14*100, verify=False); ans
  2560. 312.588469032184
  2561. >>> f.subs(x, ans).n(2)
  2562. 2.1e+121
  2563. >>> (f/f.diff(x)).subs(x, ans).n(2)
  2564. 7.4e-15
  2565. One might safely skip the verification if bounds of the root are known
  2566. and a bisection method is used:
  2567. >>> bounds = lambda i: (3.14*i, 3.14*(i + 1))
  2568. >>> nsolve(f, bounds(100), solver='bisect', verify=False)
  2569. 315.730061685774
  2570. Alternatively, a function may be better behaved when the
  2571. denominator is ignored. Since this is not always the case, however,
  2572. the decision of what function to use is left to the discretion of
  2573. the user.
  2574. >>> eq = x**2/(1 - x)/(1 - 2*x)**2 - 100
  2575. >>> nsolve(eq, 0.46)
  2576. Traceback (most recent call last):
  2577. ...
  2578. ValueError: Could not find root within given tolerance. (10000 > 2.1684e-19)
  2579. Try another starting point or tweak arguments.
  2580. >>> nsolve(eq.as_numer_denom()[0], 0.46)
  2581. 0.46792545969349058
  2582. """
  2583. # there are several other SymPy functions that use method= so
  2584. # guard against that here
  2585. if 'method' in kwargs:
  2586. raise ValueError(filldedent('''
  2587. Keyword "method" should not be used in this context. When using
  2588. some mpmath solvers directly, the keyword "method" is
  2589. used, but when using nsolve (and findroot) the keyword to use is
  2590. "solver".'''))
  2591. if 'prec' in kwargs:
  2592. import mpmath
  2593. mpmath.mp.dps = kwargs.pop('prec')
  2594. # keyword argument to return result as a dictionary
  2595. as_dict = dict
  2596. from builtins import dict # to unhide the builtin
  2597. # interpret arguments
  2598. if len(args) == 3:
  2599. f = args[0]
  2600. fargs = args[1]
  2601. x0 = args[2]
  2602. if iterable(fargs) and iterable(x0):
  2603. if len(x0) != len(fargs):
  2604. raise TypeError('nsolve expected exactly %i guess vectors, got %i'
  2605. % (len(fargs), len(x0)))
  2606. elif len(args) == 2:
  2607. f = args[0]
  2608. fargs = None
  2609. x0 = args[1]
  2610. if iterable(f):
  2611. raise TypeError('nsolve expected 3 arguments, got 2')
  2612. elif len(args) < 2:
  2613. raise TypeError('nsolve expected at least 2 arguments, got %i'
  2614. % len(args))
  2615. else:
  2616. raise TypeError('nsolve expected at most 3 arguments, got %i'
  2617. % len(args))
  2618. modules = kwargs.get('modules', ['mpmath'])
  2619. if iterable(f):
  2620. f = list(f)
  2621. for i, fi in enumerate(f):
  2622. if isinstance(fi, Eq):
  2623. f[i] = fi.lhs - fi.rhs
  2624. f = Matrix(f).T
  2625. if iterable(x0):
  2626. x0 = list(x0)
  2627. if not isinstance(f, Matrix):
  2628. # assume it's a SymPy expression
  2629. if isinstance(f, Eq):
  2630. f = f.lhs - f.rhs
  2631. elif f.is_Relational:
  2632. raise TypeError('nsolve cannot accept inequalities')
  2633. syms = f.free_symbols
  2634. if fargs is None:
  2635. fargs = syms.copy().pop()
  2636. if not (len(syms) == 1 and (fargs in syms or fargs[0] in syms)):
  2637. raise ValueError(filldedent('''
  2638. expected a one-dimensional and numerical function'''))
  2639. # the function is much better behaved if there is no denominator
  2640. # but sending the numerator is left to the user since sometimes
  2641. # the function is better behaved when the denominator is present
  2642. # e.g., issue 11768
  2643. f = lambdify(fargs, f, modules)
  2644. x = sympify(findroot(f, x0, **kwargs))
  2645. if as_dict:
  2646. return [{fargs: x}]
  2647. return x
  2648. if len(fargs) > f.cols:
  2649. raise NotImplementedError(filldedent('''
  2650. need at least as many equations as variables'''))
  2651. verbose = kwargs.get('verbose', False)
  2652. if verbose:
  2653. print('f(x):')
  2654. print(f)
  2655. # derive Jacobian
  2656. J = f.jacobian(fargs)
  2657. if verbose:
  2658. print('J(x):')
  2659. print(J)
  2660. # create functions
  2661. f = lambdify(fargs, f.T, modules)
  2662. J = lambdify(fargs, J, modules)
  2663. # solve the system numerically
  2664. x = findroot(f, x0, J=J, **kwargs)
  2665. if as_dict:
  2666. return [dict(zip(fargs, [sympify(xi) for xi in x]))]
  2667. return Matrix(x)
  2668. def _invert(eq, *symbols, **kwargs):
  2669. """
  2670. Return tuple (i, d) where ``i`` is independent of *symbols* and ``d``
  2671. contains symbols.
  2672. Explanation
  2673. ===========
  2674. ``i`` and ``d`` are obtained after recursively using algebraic inversion
  2675. until an uninvertible ``d`` remains. If there are no free symbols then
  2676. ``d`` will be zero. Some (but not necessarily all) solutions to the
  2677. expression ``i - d`` will be related to the solutions of the original
  2678. expression.
  2679. Examples
  2680. ========
  2681. >>> from sympy.solvers.solvers import _invert as invert
  2682. >>> from sympy import sqrt, cos
  2683. >>> from sympy.abc import x, y
  2684. >>> invert(x - 3)
  2685. (3, x)
  2686. >>> invert(3)
  2687. (3, 0)
  2688. >>> invert(2*cos(x) - 1)
  2689. (1/2, cos(x))
  2690. >>> invert(sqrt(x) - 3)
  2691. (3, sqrt(x))
  2692. >>> invert(sqrt(x) + y, x)
  2693. (-y, sqrt(x))
  2694. >>> invert(sqrt(x) + y, y)
  2695. (-sqrt(x), y)
  2696. >>> invert(sqrt(x) + y, x, y)
  2697. (0, sqrt(x) + y)
  2698. If there is more than one symbol in a power's base and the exponent
  2699. is not an Integer, then the principal root will be used for the
  2700. inversion:
  2701. >>> invert(sqrt(x + y) - 2)
  2702. (4, x + y)
  2703. >>> invert(sqrt(x + y) + 2) # note +2 instead of -2
  2704. (4, x + y)
  2705. If the exponent is an Integer, setting ``integer_power`` to True
  2706. will force the principal root to be selected:
  2707. >>> invert(x**2 - 4, integer_power=True)
  2708. (2, x)
  2709. """
  2710. eq = sympify(eq)
  2711. if eq.args:
  2712. # make sure we are working with flat eq
  2713. eq = eq.func(*eq.args)
  2714. free = eq.free_symbols
  2715. if not symbols:
  2716. symbols = free
  2717. if not free & set(symbols):
  2718. return eq, S.Zero
  2719. dointpow = bool(kwargs.get('integer_power', False))
  2720. lhs = eq
  2721. rhs = S.Zero
  2722. while True:
  2723. was = lhs
  2724. while True:
  2725. indep, dep = lhs.as_independent(*symbols)
  2726. # dep + indep == rhs
  2727. if lhs.is_Add:
  2728. # this indicates we have done it all
  2729. if indep.is_zero:
  2730. break
  2731. lhs = dep
  2732. rhs -= indep
  2733. # dep * indep == rhs
  2734. else:
  2735. # this indicates we have done it all
  2736. if indep is S.One:
  2737. break
  2738. lhs = dep
  2739. rhs /= indep
  2740. # collect like-terms in symbols
  2741. if lhs.is_Add:
  2742. terms = {}
  2743. for a in lhs.args:
  2744. i, d = a.as_independent(*symbols)
  2745. terms.setdefault(d, []).append(i)
  2746. if any(len(v) > 1 for v in terms.values()):
  2747. args = []
  2748. for d, i in terms.items():
  2749. if len(i) > 1:
  2750. args.append(Add(*i)*d)
  2751. else:
  2752. args.append(i[0]*d)
  2753. lhs = Add(*args)
  2754. # if it's a two-term Add with rhs = 0 and two powers we can get the
  2755. # dependent terms together, e.g. 3*f(x) + 2*g(x) -> f(x)/g(x) = -2/3
  2756. if lhs.is_Add and not rhs and len(lhs.args) == 2 and \
  2757. not lhs.is_polynomial(*symbols):
  2758. a, b = ordered(lhs.args)
  2759. ai, ad = a.as_independent(*symbols)
  2760. bi, bd = b.as_independent(*symbols)
  2761. if any(_ispow(i) for i in (ad, bd)):
  2762. a_base, a_exp = ad.as_base_exp()
  2763. b_base, b_exp = bd.as_base_exp()
  2764. if a_base == b_base and a_exp.extract_additively(b_exp) is None:
  2765. # a = -b and exponents do not have canceling terms/factors
  2766. # e.g. if exponents were 3*x and x then the ratio would have
  2767. # an exponent of 2*x: one of the roots would be lost
  2768. rat = powsimp(powdenest(ad/bd))
  2769. lhs = rat
  2770. rhs = -bi/ai
  2771. else:
  2772. rat = ad/bd
  2773. _lhs = powsimp(ad/bd)
  2774. if _lhs != rat:
  2775. lhs = _lhs
  2776. rhs = -bi/ai
  2777. elif ai == -bi:
  2778. if isinstance(ad, Function) and ad.func == bd.func:
  2779. if len(ad.args) == len(bd.args) == 1:
  2780. lhs = ad.args[0] - bd.args[0]
  2781. elif len(ad.args) == len(bd.args):
  2782. # should be able to solve
  2783. # f(x, y) - f(2 - x, 0) == 0 -> x == 1
  2784. raise NotImplementedError(
  2785. 'equal function with more than 1 argument')
  2786. else:
  2787. raise ValueError(
  2788. 'function with different numbers of args')
  2789. elif lhs.is_Mul and any(_ispow(a) for a in lhs.args):
  2790. lhs = powsimp(powdenest(lhs))
  2791. if lhs.is_Function:
  2792. if hasattr(lhs, 'inverse') and lhs.inverse() is not None and len(lhs.args) == 1:
  2793. # -1
  2794. # f(x) = g -> x = f (g)
  2795. #
  2796. # /!\ inverse should not be defined if there are multiple values
  2797. # for the function -- these are handled in _tsolve
  2798. #
  2799. rhs = lhs.inverse()(rhs)
  2800. lhs = lhs.args[0]
  2801. elif isinstance(lhs, atan2):
  2802. y, x = lhs.args
  2803. lhs = 2*atan(y/(sqrt(x**2 + y**2) + x))
  2804. elif lhs.func == rhs.func:
  2805. if len(lhs.args) == len(rhs.args) == 1:
  2806. lhs = lhs.args[0]
  2807. rhs = rhs.args[0]
  2808. elif len(lhs.args) == len(rhs.args):
  2809. # should be able to solve
  2810. # f(x, y) == f(2, 3) -> x == 2
  2811. # f(x, x + y) == f(2, 3) -> x == 2
  2812. raise NotImplementedError(
  2813. 'equal function with more than 1 argument')
  2814. else:
  2815. raise ValueError(
  2816. 'function with different numbers of args')
  2817. if rhs and lhs.is_Pow and lhs.exp.is_Integer and lhs.exp < 0:
  2818. lhs = 1/lhs
  2819. rhs = 1/rhs
  2820. # base**a = b -> base = b**(1/a) if
  2821. # a is an Integer and dointpow=True (this gives real branch of root)
  2822. # a is not an Integer and the equation is multivariate and the
  2823. # base has more than 1 symbol in it
  2824. # The rationale for this is that right now the multi-system solvers
  2825. # doesn't try to resolve generators to see, for example, if the whole
  2826. # system is written in terms of sqrt(x + y) so it will just fail, so we
  2827. # do that step here.
  2828. if lhs.is_Pow and (
  2829. lhs.exp.is_Integer and dointpow or not lhs.exp.is_Integer and
  2830. len(symbols) > 1 and len(lhs.base.free_symbols & set(symbols)) > 1):
  2831. rhs = rhs**(1/lhs.exp)
  2832. lhs = lhs.base
  2833. if lhs == was:
  2834. break
  2835. return rhs, lhs
  2836. def unrad(eq, *syms, **flags):
  2837. """
  2838. Remove radicals with symbolic arguments and return (eq, cov),
  2839. None, or raise an error.
  2840. Explanation
  2841. ===========
  2842. None is returned if there are no radicals to remove.
  2843. NotImplementedError is raised if there are radicals and they cannot be
  2844. removed or if the relationship between the original symbols and the
  2845. change of variable needed to rewrite the system as a polynomial cannot
  2846. be solved.
  2847. Otherwise the tuple, ``(eq, cov)``, is returned where:
  2848. *eq*, ``cov``
  2849. *eq* is an equation without radicals (in the symbol(s) of
  2850. interest) whose solutions are a superset of the solutions to the
  2851. original expression. *eq* might be rewritten in terms of a new
  2852. variable; the relationship to the original variables is given by
  2853. ``cov`` which is a list containing ``v`` and ``v**p - b`` where
  2854. ``p`` is the power needed to clear the radical and ``b`` is the
  2855. radical now expressed as a polynomial in the symbols of interest.
  2856. For example, for sqrt(2 - x) the tuple would be
  2857. ``(c, c**2 - 2 + x)``. The solutions of *eq* will contain
  2858. solutions to the original equation (if there are any).
  2859. *syms*
  2860. An iterable of symbols which, if provided, will limit the focus of
  2861. radical removal: only radicals with one or more of the symbols of
  2862. interest will be cleared. All free symbols are used if *syms* is not
  2863. set.
  2864. *flags* are used internally for communication during recursive calls.
  2865. Two options are also recognized:
  2866. ``take``, when defined, is interpreted as a single-argument function
  2867. that returns True if a given Pow should be handled.
  2868. Radicals can be removed from an expression if:
  2869. * All bases of the radicals are the same; a change of variables is
  2870. done in this case.
  2871. * If all radicals appear in one term of the expression.
  2872. * There are only four terms with sqrt() factors or there are less than
  2873. four terms having sqrt() factors.
  2874. * There are only two terms with radicals.
  2875. Examples
  2876. ========
  2877. >>> from sympy.solvers.solvers import unrad
  2878. >>> from sympy.abc import x
  2879. >>> from sympy import sqrt, Rational, root
  2880. >>> unrad(sqrt(x)*x**Rational(1, 3) + 2)
  2881. (x**5 - 64, [])
  2882. >>> unrad(sqrt(x) + root(x + 1, 3))
  2883. (-x**3 + x**2 + 2*x + 1, [])
  2884. >>> eq = sqrt(x) + root(x, 3) - 2
  2885. >>> unrad(eq)
  2886. (_p**3 + _p**2 - 2, [_p, _p**6 - x])
  2887. """
  2888. uflags = {"check": False, "simplify": False}
  2889. def _cov(p, e):
  2890. if cov:
  2891. # XXX - uncovered
  2892. oldp, olde = cov
  2893. if Poly(e, p).degree(p) in (1, 2):
  2894. cov[:] = [p, olde.subs(oldp, _vsolve(e, p, **uflags)[0])]
  2895. else:
  2896. raise NotImplementedError
  2897. else:
  2898. cov[:] = [p, e]
  2899. def _canonical(eq, cov):
  2900. if cov:
  2901. # change symbol to vanilla so no solutions are eliminated
  2902. p, e = cov
  2903. rep = {p: Dummy(p.name)}
  2904. eq = eq.xreplace(rep)
  2905. cov = [p.xreplace(rep), e.xreplace(rep)]
  2906. # remove constants and powers of factors since these don't change
  2907. # the location of the root; XXX should factor or factor_terms be used?
  2908. eq = factor_terms(_mexpand(eq.as_numer_denom()[0], recursive=True), clear=True)
  2909. if eq.is_Mul:
  2910. args = []
  2911. for f in eq.args:
  2912. if f.is_number:
  2913. continue
  2914. if f.is_Pow:
  2915. args.append(f.base)
  2916. else:
  2917. args.append(f)
  2918. eq = Mul(*args) # leave as Mul for more efficient solving
  2919. # make the sign canonical
  2920. margs = list(Mul.make_args(eq))
  2921. changed = False
  2922. for i, m in enumerate(margs):
  2923. if m.could_extract_minus_sign():
  2924. margs[i] = -m
  2925. changed = True
  2926. if changed:
  2927. eq = Mul(*margs, evaluate=False)
  2928. return eq, cov
  2929. def _Q(pow):
  2930. # return leading Rational of denominator of Pow's exponent
  2931. c = pow.as_base_exp()[1].as_coeff_Mul()[0]
  2932. if not c.is_Rational:
  2933. return S.One
  2934. return c.q
  2935. # define the _take method that will determine whether a term is of interest
  2936. def _take(d):
  2937. # return True if coefficient of any factor's exponent's den is not 1
  2938. for pow in Mul.make_args(d):
  2939. if not pow.is_Pow:
  2940. continue
  2941. if _Q(pow) == 1:
  2942. continue
  2943. if pow.free_symbols & syms:
  2944. return True
  2945. return False
  2946. _take = flags.setdefault('_take', _take)
  2947. if isinstance(eq, Eq):
  2948. eq = eq.lhs - eq.rhs # XXX legacy Eq as Eqn support
  2949. elif not isinstance(eq, Expr):
  2950. return
  2951. cov, nwas, rpt = [flags.setdefault(k, v) for k, v in
  2952. sorted({"cov": [], "n": None, "rpt": 0}.items())]
  2953. # preconditioning
  2954. eq = powdenest(factor_terms(eq, radical=True, clear=True))
  2955. eq = eq.as_numer_denom()[0]
  2956. eq = _mexpand(eq, recursive=True)
  2957. if eq.is_number:
  2958. return
  2959. # see if there are radicals in symbols of interest
  2960. syms = set(syms) or eq.free_symbols # _take uses this
  2961. poly = eq.as_poly()
  2962. gens = [g for g in poly.gens if _take(g)]
  2963. if not gens:
  2964. return
  2965. # recast poly in terms of eigen-gens
  2966. poly = eq.as_poly(*gens)
  2967. # not a polynomial e.g. 1 + sqrt(x)*exp(sqrt(x)) with gen sqrt(x)
  2968. if poly is None:
  2969. return
  2970. # - an exponent has a symbol of interest (don't handle)
  2971. if any(g.exp.has(*syms) for g in gens):
  2972. return
  2973. def _rads_bases_lcm(poly):
  2974. # if all the bases are the same or all the radicals are in one
  2975. # term, `lcm` will be the lcm of the denominators of the
  2976. # exponents of the radicals
  2977. lcm = 1
  2978. rads = set()
  2979. bases = set()
  2980. for g in poly.gens:
  2981. q = _Q(g)
  2982. if q != 1:
  2983. rads.add(g)
  2984. lcm = ilcm(lcm, q)
  2985. bases.add(g.base)
  2986. return rads, bases, lcm
  2987. rads, bases, lcm = _rads_bases_lcm(poly)
  2988. covsym = Dummy('p', nonnegative=True)
  2989. # only keep in syms symbols that actually appear in radicals;
  2990. # and update gens
  2991. newsyms = set()
  2992. for r in rads:
  2993. newsyms.update(syms & r.free_symbols)
  2994. if newsyms != syms:
  2995. syms = newsyms
  2996. # get terms together that have common generators
  2997. drad = dict(zip(rads, range(len(rads))))
  2998. rterms = {(): []}
  2999. args = Add.make_args(poly.as_expr())
  3000. for t in args:
  3001. if _take(t):
  3002. common = set(t.as_poly().gens).intersection(rads)
  3003. key = tuple(sorted([drad[i] for i in common]))
  3004. else:
  3005. key = ()
  3006. rterms.setdefault(key, []).append(t)
  3007. others = Add(*rterms.pop(()))
  3008. rterms = [Add(*rterms[k]) for k in rterms.keys()]
  3009. # the output will depend on the order terms are processed, so
  3010. # make it canonical quickly
  3011. rterms = list(reversed(list(ordered(rterms))))
  3012. ok = False # we don't have a solution yet
  3013. depth = sqrt_depth(eq)
  3014. if len(rterms) == 1 and not (rterms[0].is_Add and lcm > 2):
  3015. eq = rterms[0]**lcm - ((-others)**lcm)
  3016. ok = True
  3017. else:
  3018. if len(rterms) == 1 and rterms[0].is_Add:
  3019. rterms = list(rterms[0].args)
  3020. if len(bases) == 1:
  3021. b = bases.pop()
  3022. if len(syms) > 1:
  3023. x = b.free_symbols
  3024. else:
  3025. x = syms
  3026. x = list(ordered(x))[0]
  3027. try:
  3028. inv = _vsolve(covsym**lcm - b, x, **uflags)
  3029. if not inv:
  3030. raise NotImplementedError
  3031. eq = poly.as_expr().subs(b, covsym**lcm).subs(x, inv[0])
  3032. _cov(covsym, covsym**lcm - b)
  3033. return _canonical(eq, cov)
  3034. except NotImplementedError:
  3035. pass
  3036. if len(rterms) == 2:
  3037. if not others:
  3038. eq = rterms[0]**lcm - (-rterms[1])**lcm
  3039. ok = True
  3040. elif not log(lcm, 2).is_Integer:
  3041. # the lcm-is-power-of-two case is handled below
  3042. r0, r1 = rterms
  3043. if flags.get('_reverse', False):
  3044. r1, r0 = r0, r1
  3045. i0 = _rads0, _bases0, lcm0 = _rads_bases_lcm(r0.as_poly())
  3046. i1 = _rads1, _bases1, lcm1 = _rads_bases_lcm(r1.as_poly())
  3047. for reverse in range(2):
  3048. if reverse:
  3049. i0, i1 = i1, i0
  3050. r0, r1 = r1, r0
  3051. _rads1, _, lcm1 = i1
  3052. _rads1 = Mul(*_rads1)
  3053. t1 = _rads1**lcm1
  3054. c = covsym**lcm1 - t1
  3055. for x in syms:
  3056. try:
  3057. sol = _vsolve(c, x, **uflags)
  3058. if not sol:
  3059. raise NotImplementedError
  3060. neweq = r0.subs(x, sol[0]) + covsym*r1/_rads1 + \
  3061. others
  3062. tmp = unrad(neweq, covsym)
  3063. if tmp:
  3064. eq, newcov = tmp
  3065. if newcov:
  3066. newp, newc = newcov
  3067. _cov(newp, c.subs(covsym,
  3068. _vsolve(newc, covsym, **uflags)[0]))
  3069. else:
  3070. _cov(covsym, c)
  3071. else:
  3072. eq = neweq
  3073. _cov(covsym, c)
  3074. ok = True
  3075. break
  3076. except NotImplementedError:
  3077. if reverse:
  3078. raise NotImplementedError(
  3079. 'no successful change of variable found')
  3080. else:
  3081. pass
  3082. if ok:
  3083. break
  3084. elif len(rterms) == 3:
  3085. # two cube roots and another with order less than 5
  3086. # (so an analytical solution can be found) or a base
  3087. # that matches one of the cube root bases
  3088. info = [_rads_bases_lcm(i.as_poly()) for i in rterms]
  3089. RAD = 0
  3090. BASES = 1
  3091. LCM = 2
  3092. if info[0][LCM] != 3:
  3093. info.append(info.pop(0))
  3094. rterms.append(rterms.pop(0))
  3095. elif info[1][LCM] != 3:
  3096. info.append(info.pop(1))
  3097. rterms.append(rterms.pop(1))
  3098. if info[0][LCM] == info[1][LCM] == 3:
  3099. if info[1][BASES] != info[2][BASES]:
  3100. info[0], info[1] = info[1], info[0]
  3101. rterms[0], rterms[1] = rterms[1], rterms[0]
  3102. if info[1][BASES] == info[2][BASES]:
  3103. eq = rterms[0]**3 + (rterms[1] + rterms[2] + others)**3
  3104. ok = True
  3105. elif info[2][LCM] < 5:
  3106. # a*root(A, 3) + b*root(B, 3) + others = c
  3107. a, b, c, d, A, B = [Dummy(i) for i in 'abcdAB']
  3108. # zz represents the unraded expression into which the
  3109. # specifics for this case are substituted
  3110. zz = (c - d)*(A**3*a**9 + 3*A**2*B*a**6*b**3 -
  3111. 3*A**2*a**6*c**3 + 9*A**2*a**6*c**2*d - 9*A**2*a**6*c*d**2 +
  3112. 3*A**2*a**6*d**3 + 3*A*B**2*a**3*b**6 + 21*A*B*a**3*b**3*c**3 -
  3113. 63*A*B*a**3*b**3*c**2*d + 63*A*B*a**3*b**3*c*d**2 -
  3114. 21*A*B*a**3*b**3*d**3 + 3*A*a**3*c**6 - 18*A*a**3*c**5*d +
  3115. 45*A*a**3*c**4*d**2 - 60*A*a**3*c**3*d**3 + 45*A*a**3*c**2*d**4 -
  3116. 18*A*a**3*c*d**5 + 3*A*a**3*d**6 + B**3*b**9 - 3*B**2*b**6*c**3 +
  3117. 9*B**2*b**6*c**2*d - 9*B**2*b**6*c*d**2 + 3*B**2*b**6*d**3 +
  3118. 3*B*b**3*c**6 - 18*B*b**3*c**5*d + 45*B*b**3*c**4*d**2 -
  3119. 60*B*b**3*c**3*d**3 + 45*B*b**3*c**2*d**4 - 18*B*b**3*c*d**5 +
  3120. 3*B*b**3*d**6 - c**9 + 9*c**8*d - 36*c**7*d**2 + 84*c**6*d**3 -
  3121. 126*c**5*d**4 + 126*c**4*d**5 - 84*c**3*d**6 + 36*c**2*d**7 -
  3122. 9*c*d**8 + d**9)
  3123. def _t(i):
  3124. b = Mul(*info[i][RAD])
  3125. return cancel(rterms[i]/b), Mul(*info[i][BASES])
  3126. aa, AA = _t(0)
  3127. bb, BB = _t(1)
  3128. cc = -rterms[2]
  3129. dd = others
  3130. eq = zz.xreplace(dict(zip(
  3131. (a, A, b, B, c, d),
  3132. (aa, AA, bb, BB, cc, dd))))
  3133. ok = True
  3134. # handle power-of-2 cases
  3135. if not ok:
  3136. if log(lcm, 2).is_Integer and (not others and
  3137. len(rterms) == 4 or len(rterms) < 4):
  3138. def _norm2(a, b):
  3139. return a**2 + b**2 + 2*a*b
  3140. if len(rterms) == 4:
  3141. # (r0+r1)**2 - (r2+r3)**2
  3142. r0, r1, r2, r3 = rterms
  3143. eq = _norm2(r0, r1) - _norm2(r2, r3)
  3144. ok = True
  3145. elif len(rterms) == 3:
  3146. # (r1+r2)**2 - (r0+others)**2
  3147. r0, r1, r2 = rterms
  3148. eq = _norm2(r1, r2) - _norm2(r0, others)
  3149. ok = True
  3150. elif len(rterms) == 2:
  3151. # r0**2 - (r1+others)**2
  3152. r0, r1 = rterms
  3153. eq = r0**2 - _norm2(r1, others)
  3154. ok = True
  3155. new_depth = sqrt_depth(eq) if ok else depth
  3156. rpt += 1 # XXX how many repeats with others unchanging is enough?
  3157. if not ok or (
  3158. nwas is not None and len(rterms) == nwas and
  3159. new_depth is not None and new_depth == depth and
  3160. rpt > 3):
  3161. raise NotImplementedError('Cannot remove all radicals')
  3162. flags.update({"cov": cov, "n": len(rterms), "rpt": rpt})
  3163. neq = unrad(eq, *syms, **flags)
  3164. if neq:
  3165. eq, cov = neq
  3166. eq, cov = _canonical(eq, cov)
  3167. return eq, cov
  3168. # delayed imports
  3169. from sympy.solvers.bivariate import (
  3170. bivariate_type, _solve_lambert, _filtered_gens)