solvers.py 133 KB

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