K iP dZddlmZddlmZmZmZmZmZm Z m Z m Z m Z ddl mZddlmZmZmZmZmZmZmZddlmZddlmZmZmZmZddlmZdd l m!Z!m"Z"m#Z#dd l$m%Z%m&Z&dd l'm(Z(m)Z)dd lm*Z*dd l+m,Z,ddl-m.Z/m0Z1ddl2m3Z3ddl4m5Z5ddl6m7Z7m8Z8m9Z9m:Z:ddl;mm?Z?m@Z@mAZAmBZBmCZCmDZDmEZEmFZFmGZGmHZHmIZImJZJmKZKmLZLmMZMmNZNddlOmPZPddlQmRZRmSZSmTZTmUZUddlVmWZWmXZXmYZYmZZZm[Z[m\Z\m]Z]m^Z^m_Z_m`Z`maZambZbmcZcddldmeZeddlfmgZgddlhmiZimjZjddlkmlZlmmZmmnZnmoZompZpmqZqmrZrmsZsmtZtddlumvZvmwZwddlxmyZymzZzm{Z{ddl|m}Z}ddl~mZmZddlmZmZmZmZmZmZmZm0Z0m.Z.dd lmZdd!lmZmZmZdd"lmZmZmZdd#l2mZdd$lmZmZmZmZmZdd%lmZdd&lmZdd'lmZmZmZmZdd(lmZmZmZdd)lmZGd*d+eZd,ZejXfd-ZeZd.Zd/Zd0ad0ad1Zd2Zd3Zd4Zd5Zd6ZejXfd7Zd8Zd9ZGd:d;eZd<Zd=Zd>ZejXfd?Zd@ZdAZdBZd`dDZdEZdFZdGZdHZdIZdJZdKZdLZdMZdNZd0ejXfdOZdPZdQZdRZdSZdCdTdUZdVZdWZdXZigggd0fdYZdZZd[Zd\Zd]Zd^Zd_Zy0)aa This module contains functions to: - solve a single equation for a single variable, in any domain either real or complex. - solve a single transcendental equation for a single variable in any domain either real or complex. (currently supports solving in real domain only) - solve a system of linear equations with N variables and M equations. - solve a system of Non Linear Equations with N variables and M equations )sympify) SPowDummypiExprWildMulAddBasic)Tuple)Lambdaexpand_complex AppliedUndef expand_log_mexpand expand_trignfloat)Mod)INumberRationaloo) integer_log)EqNe Relational)default_sort_keyordered)Symbol_uniquely_named_symbol)_sympify)preorder_traversal)gcdlcm)_linear_eq_to_dict)UnsolvableFactorError)simplifyfractiontrigsimp nsimplify) powdenest logcombine)logtancotsincosseccscexpacosasinatanacotacscasecpiecewise_fold Piecewise)totient)Absargreim) HyperbolicFunctionsinhcoshtanhcothsechcschasinhacoshatanhacothasechacsch) real_root)TrigonometricFunction)And BooleanTrue) FiniteSetimagesetInterval IntersectionUnion ConditionSetImageSet ComplementContains)Set ProductSet)zerosMatrix MatrixBase)divisors) discrete_log nthroot_mod) rootsPolydegreetogetherPolynomialErrorRootOffactorr%r$)CoercionFailed)invertgroebnerpoly)sympy_eqs_to_ring solve_lin_sysPolyNonlinearError) _linsolve)checksoldenomsunrad _simple_densrecast_to_symbols)solve_poly_system) filldedent)numbered_symbolshas_dups is_sequenceiterable) periodicitycontinuous_domainfunction_range) GeneratorTypeceZdZdZy)NonlinearErrorz9Raised when unexpectedly encountering nonlinear equationsN__name__ __module__ __qualname____doc__\/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/sympy/solvers/solveset.pyrrDsCrrcVtdtd}g}t|j|D]4}|D]}|j|}|j |t |f6t|D]!\}\}}|j ||}||f||<#tt|}||fS)a Return ``f``, with all objects given by ``atoms`` replaced with Dummy symbols, ``d``, and the list of replacements, ``(d, e)``, where ``e`` is an object of type given by ``atoms`` in which any other instances of atoms have been recursively replaced with Dummy symbols, too. The tuples are ordered so that if they are applied in sequence, the origin ``f`` will be restored. Examples ======== >>> from sympy import cos >>> from sympy.abc import x >>> from sympy.solvers.solveset import _masked >>> f = cos(cos(x) + 1) >>> f, reps = _masked(cos(1 + cos(x)), cos) >>> f _a1 >>> reps [(_a1, cos(_a0 + 1)), (_a0, cos(x))] >>> for d, e in reps: ... f = f.xreplace({d: e}) >>> f cos(cos(x) + 1) aT)clsreal) r{rratomsreplaceappendnext enumeratelistreversed)frsymmaskrions r_maskedrIs4 3E 5C D WQWWe_ %$ A 1 A  QS N#$t_ 6Aq IIaOa&Q  D d7NrcPt|}|js tdt|}||jvr tdt|}||jvr td|j t j rt|t||\}}nt|t||\}}||k7r||fS|t jur||fSt|tr||j|fS|t j ur||fS||j|fS)a  Reduce the complex valued equation $f(x) = y$ to a set of equations $$\left\{g(x) = h_1(y),\ g(x) = h_2(y),\ \dots,\ g(x) = h_n(y) \right\}$$ where $g(x)$ is a simpler function than $f(x)$. The return value is a tuple $(g(x), \mathrm{set}_h)$, where $g(x)$ is a function of $x$ and $\mathrm{set}_h$ is the set of function $\left\{h_1(y), h_2(y), \dots, h_n(y)\right\}$. Here, $y$ is not necessarily a symbol. $\mathrm{set}_h$ contains the functions, along with the information about the domain in which they are valid, through set operations. For instance, if :math:`y = |x| - n` is inverted in the real domain, then $\mathrm{set}_h$ is not simply $\{-n, n\}$ as the nature of `n` is unknown; rather, it is: $$ \left(\left[0, \infty\right) \cap \left\{n\right\}\right) \cup \left(\left(-\infty, 0\right] \cap \left\{- n\right\}\right)$$ By default, the complex domain is used which means that inverting even seemingly simple functions like $\exp(x)$ will give very different results from those obtained in the real domain. (In the case of $\exp(x)$, the inversion via $\log$ is multi-valued in the complex domain, having infinitely many branches.) If you are working with real values only (or you are not sure which function to use) you should probably set the domain to ``S.Reals`` (or use ``invert_real`` which does that automatically). Examples ======== >>> from sympy.solvers.solveset import invert_complex, invert_real >>> from sympy.abc import x, y >>> from sympy import exp When does exp(x) == y? >>> invert_complex(exp(x), y, x) (x, ImageSet(Lambda(_n, I*(2*_n*pi + arg(y)) + log(Abs(y))), Integers)) >>> invert_real(exp(x), y, x) (x, Intersection({log(y)}, Reals)) When does exp(x) == 1? >>> invert_complex(exp(x), 1, x) (x, ImageSet(Lambda(_n, 2*_n*I*pi), Integers)) >>> invert_real(exp(x), 1, x) (x, {0}) See Also ======== invert_real, invert_complex zx must be a symbolz*Inverse of constant function doesn't existzy should be independent of x ) r is_Symbol ValueError free_symbols is_subsetrReals _invert_realrT_invert_complex Complexes isinstance intersect)f_xyxdomainx1ss r_invertrpsp  A ;;-.. #,C   EFF AANN899  S)A,2AYq\15A a1u 1u !Y1;;v&&&1u 1;;v&&&rc:t|||tjS)z Inverts a real-valued function. Same as :func:`invert_complex`, but sets the domain to ``S.Reals`` before inverting. )rrr)rrrs r invert_realrs 31agg &&rc F ||k(s|tjur||fStdd}t|ts)|j rQ|j tjk(r4t|jtt|t|||St|dr|j{t|ttfset!|j"dkDr t%dt|j"dtt||j|||St|t&rt)|j"d||S|j*rJ|j-|\}}|tj.ur$t|tt|||z ||S|j0rJ|j-|\}}|tj2ur$t|tt|||z ||S|j rl|j"\}}|j5|}|j5|} | sC|j6r|j9\} } | dzdk(r_| dzdk(rW| j:d urIt|t=||} |t?dt@z} t| | }t|||\}}||fS| dzdk(rt|t=||} t| |}| dzdk(r'tt|| |}t|||z|S| dzdk(r\t|||S|jBrBt|t=||} |t?dt@z} t| | }t|||S |s|j"d}|jDr-t|tt|t||d ||S|jFr9tI||\}}|rt|tK||S|tjfS|j:rZtM|d}|tjNk(rt|tKd|S|tjPk(r|tjfSt|ttfr tS|||S||fS) Helper function for _invert.rTrinverse/Only functions with one argument are supported.rFevaluate)*rEmptySetrrr5is_PowbaseExp1rrUrr.hasattrrrQrClenargsrr? _invert_absis_Addas_independentZerois_MulOnehas is_rationalas_numer_denomis_zerorPrVr is_irrational is_positive is_negativerrTrtruefalse_invert_trig_hyp_real)rg_yssymbolrghrexpo base_has_sym expo_has_symnumdenrootg_ys_posres_inv_setneg_resrhsrbones rrrs F{dajj(~ cA!Sahh166QVV+;AEE$VAs1v%6="$ $q)!8A ! PB qvv;?NO OAFF1I$VA{qyy{1~%>E"$ $!S166!9dF33xx'1 AFF?8F1a!e,8F1acND#A6J JxxVV dxx' xx' ..0S7a+D#-HHQw!|+D#v>>##a1d!34(1b/1tX.#D#v66 ))A,C#DVAs1dU'CDdKVUU!!"3-1'ilFCC !**--aj!&&='ilFCCAGG^ !**--!+-?@A$Qf55 t9rNc 4 ttr tdd ttr.t j dt t |Sttr|jtdt}t|trt|tr|}n|fSt j dtt t |t t  |Stt r|jtj"dd}t|trt|tr|}n|fSt j dtt t% |t t%  |Stt&rz|jtj(dd}t|trt|tr|}n|fSt j dt t+ |Stt,rd|tddz }t|t.rt|tr|}n|fSt j dt t1 |Stt2rc|tdz }t|t.rt|tr|}n|fSt j dt t5 |Sy tt6r`t|trPd}|j8\ tdd  fd }t|Dcgc] }|| c}}|fS|fScc}w) aiHelper function for inverting trigonometric and hyperbolic functions. This helper only handles inversion over the reals. For trigonometric functions only finite `g_ys` sets are implemented. For hyperbolic functions the set `g_ys` is checked against the domain of the respective inverse functions. Infinite `g_ys` sets are also supported. rTrrrc"tttdfdtzt ddft t dfdtzt ddfttfttjfttfttjfttdfdtztt t dt dt ft"t$dfdtztt t dt dt fiat|S)Nc&tt|z SN)rr7rs rzC_invert_trig_hyp_real.._get_trig_inverses..BtAwJrrrrct| Sr)r6rs rrzC_invert_trig_hyp_real.._get_trig_inverses.. T!WHrct| Sr)r;rs rrzC_invert_trig_hyp_real.._get_trig_inverses..rrc&tt|z Sr)rr:rs rrzC_invert_trig_hyp_real.._get_trig_inverses..rr)_trig_inversesr1r7rrVr2r6r/r8rrr0r9r3r;rXrr4r:funcs r_get_trig_inversesz1_invert_trig_hyp_real.._get_trig_inversess%D"672xAOD"45qtXb!_MD7B0D7B0D"45qthsB/!RACD"672hsB/!RAC"D"$' 'rintegerc NtDcgc])}t z||ztj+c}}t j d| \}}| k(r j |}t ||St t|tjScc}wNr) rXrUrIntegersrrcontainsrYrr) rinvinvsimginv_finv_g_yscondsrinvsrperiodrngrs rcreate_return_setz0_invert_trig_hyp_real..create_return_setsFJL?BF1Hs1v-qzz:LMG*166!9gvFOE8 Q#FE8<<#FBq!Hagg>>Ls.B"N)rrCrrDrrrUrJrErrVrrWrTrXrKrHLopenrNrFopenrLrGr[rMrIrOrQr) rrrg_ys_domrrrretsetrrrrs ` ` @@@@rrrMs !'( #D ! a q 8AuQx+FO O a ~~hq"o6H(L1dI. $Ht9$q 5E!Hh/U1XIx0,239; ; a ~~hnnQ&:;H(L1dI.#Ht9$q 5E!Hh/U1XIx0,239; ; a ~~hmmB&:;H(L1dI.#Ht9$q E!Hh/9 9 a hr1o-H(J/dI.#Ht9$q E!Hh/9 9 a il*H(J/dI.#Ht9$q E!Hh/9 9  A, -*T92M (/qvv6fc #t $ ? ?t.inv..ac"fqtmrc<dztztz|z Sr r r s rrz7_invert_trig_hyp_complex..inv..sac"frkAaD0rc.dztz|zSr r r s rrz7_invert_trig_hyp_complex..inv..rrc.dztz|z Sr r r s rrz7_invert_trig_hyp_complex..inv..rrcDtzj|zSr)rr)rrtrigs rrz7_invert_trig_hyp_complex..inv..s!B$):":r) rr1r4r7r:r2r3r6r;r/r0)rrrs`@rrz%_invert_trig_hyp_complex..invs$c +&tS1Dt+022$c +&tS1Dt++--$c +:<<,rrTrrcxtttdfdtztzdft t dfdtztzdfttfttzdfttfttzdfttdfdtztzdfttdfdtztzdfiat|S) Nc4ttzt|z Sr)rrrJrs rrzE_invert_trig_hyp_complex.._get_hyp_inverses..ad58mrrrct| Sr)rKrs rrzE_invert_trig_hyp_complex.._get_hyp_inverses.. uQxir)rrct| Sr)rNrs rrzE_invert_trig_hyp_complex.._get_hyp_inverses..rr)rc4ttzt|z Sr)rrrOrs rrzE_invert_trig_hyp_complex.._get_hyp_inverses..rr) _hyp_inversesrDrJrrrErKrFrLrGrMrHrNrIrOrs r_get_hyp_inversesz3_invert_trig_hyp_complex.._get_hyp_inversess$U$;.create_return_setsFJL?BF1Hs1v-qzz:LMG-affQi&IOE851bAh56#FE8<<#FBq!HakkBBL6s .B1(B6)rrQrTrrrrXrUrrrrrCr) rrrrLrrrrr rrrs ` ` @@@@r_invert_trig_hyp_complexr"s!*+ 40K = #t $zzQ RA E4PaHVAqt_ajjAPQ QD Rqvvay$77 A) *z$ /J '/qvv6fd #t $ C Ct}|j<j@} tdjCt3| } | f| z} tEtt| ftFd| ztHztK|zztMtO|ztjPt3| zg} t |j0| |St+|t"rtE|D cgc]]} | dk7rVtt|tFd|ztHztK| zztMtO| ztjP_c} } t |j0| |St+|t,t.fr tS|||S||fScc} w)rrrrrrzk{}r)*rrrrrrrrUrrrNegativeInfinityComplexInfinityInfinityrr is_RationalrTrrrrrQrCr5rrrrrZlamdaexpr variablesformatrXrrr@r.r?rr")rrrrrrrr g_ys_expr g_ys_varsk g_ys_vars_1exp_invsg_ys rrrs@ F{dajj(~ c Axx'1 AFF?"1hvaQ/?&FO Oxx'1 AEE>Q''):):AJJGG1::&"1hva1~t&DfM MxxVV d    ! 4&tT6::q)!8 a. / a+ , a  qvv;?NO Oqvvay'q+!))+a.(A4H&R R!Sahh166QVV+; dH % I ,,Iell3y>23A$*Kx ~1Q3r6CPYNCZ@[+.s9~+>A?)ABC**sS^O_B` bcdH"155(F; ; i (*.<#&#( (q!QqSVc#h5F2G/23s8}3=)>?@zz K<=H#155(F; ;!+-?@A'488 t9|tjfcS|r/t|D cgc]} t| tdt c} } nd} t#dd} t |tt%t'| | |t%t'| | ||\} } | t)| | | fScc} w)aHelper function for inverting absolute value functions. Returns the complete result of inverting an absolute value function along with the conditions which must also be satisfied. If it is certain that all these conditions are met, a :class:`~.FiniteSet` of all possible solutions is returned. If any condition cannot be satisfied, an :class:`~.EmptySet` is returned. Otherwise, a :class:`~.ConditionSet` of the solutions, with all the required conditions specified, is returned. rrTrr) is_FiniteSetrWrVrr&rNotImplementedErrorrXr is_Numberis_nonnegativerrrrRr\rrrUrrY)rrrpospargnargunknownrokr conditionsrg_xvaluess rrrGsj    4!QZZ!89AsF+QBV, 7d1g % %Awd1gtAw///G YY&!"Q  !-- : NN1 1::% % & $Ax27   cAq%1t$A2%#'(.0KC  S*f5 55s !E'cbt|t|}}|jryt|||S)aXReturns False if point p is infinite or any subexpression of f is infinite or becomes so after replacing symbol with p. If none of these conditions is met then True will be returned. Examples ======== >>> from sympy import Mul, oo >>> from sympy.abc import x >>> from sympy.solvers.solveset import domain_check >>> g = 1/(1 + (1/(x + 1))**2) >>> domain_check(g, x, -1) False >>> domain_check(x**2, x, 0) True >>> domain_check(1/x, x, oo) False * The function relies on the assumption that the original form of the equation has not been changed by automatic simplification. >>> domain_check(x/x, x, 0) # x/x is automatically simplified to 1 True * To deal with automatic evaluations use evaluate=False: >>> domain_check(Mul(x, 1/x, evaluate=False), x, 0) False F)r is_infinite _domain_check)rrps r domain_checkrCxs.< 1:wqzqA}} FA &&rc|jr |jry|jjryt |t r\|j D]L\}}|j}|tjur+|tjurt|cSyytfd|j DS)NTFc38K|]}t|ywr)rA).0rrBrs r z _domain_check..s"$!FA.$) is_Atom is_finitesubsr@rr=rrrrrAall)rrrBr)condcondsubss `` rrArAsyyQ[[   & & Ay !&& JD$yy+H177"QVV#$T6155 "$FF$$ $rc fd}|jDcic]}|tdi||}}|j|jScc}w)a' Return True if the given expression is finite. For symbols that do not assign a value for `complex` and/or `real`, the domain will be used to assign a value; symbols that do not assign a value for `finite` will be made finite. All other assumptions are left unmodified. c|j}|jd|jddjtj r|jdd|S|jdd|S)NfiniteTrcomplex) assumptions0 setdefaultgetrrr)rArs r assumptionsz0_is_finite_with_finite_vars..assumptionssa NN XquuXt45   AGG $ LL &  LLD )rr)rrxreplacerJ)rrrWrrepss ` r_is_finite_with_finite_varsrZsM 12 ?1Au&{1~& & ?D ? ::d  % %% @sA c|js |jrtfd|jDS|jr3|j j st|jSy|j syt|r- t|jd}|jdkSy#t$rYywxYw)aq Tests whether the equation is an equation of the given function class. The given equation belongs to the given function class if it is comprised of functions of the function class which are multiplied by or added to expressions independent of the symbol. In addition, the arguments of all such functions must be linear in the symbol as well. Examples ======== >>> from sympy.solvers.solveset import _is_function_class_equation >>> from sympy import tan, sin, tanh, sinh, exp >>> from sympy.abc import x >>> from sympy.functions.elementary.trigonometric import TrigonometricFunction >>> from sympy.functions.elementary.hyperbolic import HyperbolicFunction >>> _is_function_class_equation(TrigonometricFunction, exp(x) + tan(x), x) False >>> _is_function_class_equation(TrigonometricFunction, tan(x) + sin(x), x) True >>> _is_function_class_equation(TrigonometricFunction, tan(x**2), x) False >>> _is_function_class_equation(TrigonometricFunction, tan(x + 2), x) True >>> _is_function_class_equation(HyperbolicFunction, tanh(x) + sinh(x), x) True c38K|]}t|ywr)_is_function_class_equation)rFr@ func_classrs rrGz._is_function_class_equation..s"&/z3G&rHFTrr) rrrLrrr5rr]rrrfrgri)r^rrrs` ` rr]r]s6 xx188&ff&& & xxuuyy .z1666J J 55=!Z  QVVAY'A88:? "  s+C CCcJtt|dd}t|\}}|j|s t |||St|||}t|||}||z S#t $rt |t|d|cYSt$rtjcYSwxYw)z solve rational functionsT) recursive)deepr) rhrr)r_solve_as_polyr4rYrrlrr _solveset)rrrrr valid_solns invalid_solnss r_solve_as_rationalrfs!t,48A A;DAq 55= !!VV4 4 662 !!VV4 ]**# : 1a&9 9 ::  s A%% B"B"!B"ceZdZdZy)_SolveTrig1Errorz0Raised when _solve_trig1 heuristics do not applyNrrrrrhrhs:rrhc d\}}t|D]C}t|ttfs|j |s,|s|d}}3||k(r|dz }>d\}}n|dk(rt |d||\}}||k(rd}|j |hz re|jdj|d\} } | j|d\} } | j\} } t| dt| dz}t|||St|t|d|S|r^td}|j||}t|||}t|t r$t#|Dcgc]}t%||z ||c}Sd } t'|||}|Scc}w#t($r3 t+|||}Y|S#t,$rt/t1d wxYwwxYw) z@Function to call other helpers to solve trigonometric equations rr)FrrTas_AddFrNzj Solution to this kind of trigonometric equations is yet to be implemented)r#rrQrCrrrrrrrrYrrrKsolvesetrTrX _solve_trig _solve_trig1rh _solve_trig2rr4rz)rrr trig_exprcountr)rsolrMrrmrrrf_covsol_covrs rrmrmsIu"1%  d2.0 159XXf5E#'5 " #+ 5  zAvv.3 ;D%%0 ~~a(77t7L1''u'=1++-S#qzBsAJ.c2 21a&9 9  #Jy!$5!V, gy )DKLq+ik66:LN N C .1ff- JM . .q&&1C J  .%j2,'-. . . .s$E?0 F G FF<<Gc td}tt|r7t|}|j t j rtnt}ntt|z}t}t|}|}|jtt}|Dcgc]}|jd} }tfd| Ds t||Sg} g} | D]} t!| } | j'dkDr t%d| j'dk(rB| j)d}| j+t-|d| j+t-|dt/| t1| z }|j3||z}|j5t}t7|}t-|\}}td}|j9|j9}}|j3|||j3||}}|j;|s|j;|r t%dt=||t=||z }t?|t@r t%d t?|tBrtd |Dr t%d |j3||z }tE|Dcgc]}|||dc}}|j;tFrn|jtF}t-|\}}|jH|d d id}|jH|d d id}tKtM|dtM|d}nd}|t jNur tA||StA|tQ||S|t jRurt jRSt%dcc}w#t"$r t%dwxYwcc}w)aPrimary solver for trigonometric and hyperbolic equations Returns either the solution set as a ConditionSet (auto-evaluated to a union of ImageSets if no variables besides 'symbol' are involved) or raises _SolveTrig1Error if f == 0 cannot be solved. Notes ===== Algorithm: 1. Do a change of variable x -> mu*x in arguments to trigonometric and hyperbolic functions, in order to reduce them to small integers. (This step is crucial to keep the degrees of the polynomials of step 4 low.) 2. Rewrite trigonometric/hyperbolic functions as exponentials. 3. Proceed to a 2nd change of variable, replacing exp(I*x) or exp(x) by y. 4. Solve the resulting rational equation. 5. Use invert_complex or invert_real to return to the original variable. 6. If the coefficients of 'symbol' were symbolic in nature, add the necessary consistency conditions in a ConditionSet. rrc3@K|]}|jywr)r)rFrrs rrGz_solve_trig1..|s5quuV}5z!trig argument is not a polynomialrz°ree of variable must not exceed onerzchange of variable not possiblez$polynomial has ConditionSet solutionc3<K|]}t|tywr)rrjrFrs rrGz_solve_trig1..s4z!V$4z#polynomial results in RootOf objectrkFTz(polynomial solutions must form FiniteSet)*rr]rCr5rrrrinvert_complexrr*rrQranyrlrfrirhrg all_coeffsrr)r%r$rKrewriterhexpandrsolveset_complexrrYrTrXr rrRrrrWr)rrrrcovinverter f_originaltrig_functionsrtrig_arguments denominators numeratorsarpoly_arcmurrrsolnsrresultsymsmunummudencondnumconddenrMs ` rrnrnXsq, c A"#5q&A!f"("2"2177";;!A#h! AJWW24FGN)78AaffQi8N8 5n5 5 FF33LJ , H2v&G >> a "#KL L >> q      #(1+a.)HQKN+ , \ 3z? *B vr!tA #A A A;DAq c A 88:qxxzqA 66#q>166#q>qAuuQx1558@AA Q "%5a%; ;E%&EFF%# 4e4 4"#HI Ihhq&)$eD#q&1!4DE 66&>::f%D#B O>OOc t|}|}|jtttt t t}|Dcgc]}|jd}}g}g}|st|t|d|S|D]} t| |} | jdkDr td| jdk(rB| jd} |j!t#| j$|j!t#| j&t+d} t#dt-|zt/|z } |j1|| | z}|j3t}t5|}t7|}t9|\}}t+d}|j;|j;}}|j1t | ||j1t | |}}|j=| s|j=| rt|t|d|St?||t@jBt?||t@jBz }tE|tFrtI|Dcgc]}tKt || z ||d c}}tKt || z tL|d}t|t|kDr tI||}tO||S|t@jPurt@jPSt|t|dt@jBScc}w#t$r tdwxYw#t($rt|t|d|cYcSwxYwcc}w)zVSecondary helper to solve trigonometric equations, called when first helper fails rz9give up, we cannot solve if this is not a polynomial in xrz:degree of variable inside polynomial should not exceed onerrr))r*rr1r2r/r3r0r4rrYrrfrirrgr~rrrBq TypeErrorr number_lcm number_gcdrKrrrhr)rrrlrrrrTrXrrrWr)rrrrrrrrrrrrrrrrrrrrdsols rroros  AJWWS#sCc:N)78AaffQi8N8LJ FBz1$5v>> C Z2v&G >> a YZ Z >> q      # C   hqkmm ,    .C c A !Z. .z:/F FB vr!tA #AAA A A;DAq c A 88:qxxzqA 66#a&! affSVQ/qAuuQx1558FBz1$5v>> Q177 #hq!QWW&= =E%# %'%S^Q?B'(3vby>2v6q9 !9vay 64(FFF++ !** zzFBz1$5qww??q9  ZXY Y Z C:q(96B B C*'s+L4; L9 AM7#M99M M65M6c d}|j|rt||dddd}t|j}t |||krt |j }nNt||}|j}|jt|kr t |}n t|t|d|}nt|}|t|t|d|}|jDcgc]}|j|s|}}t|dk(r|t||d}|j} |j} t|j|jd}t t|dddj } t| | krt|t|d|}| |k7rt!d } |j#t$j&rt(nt*} | | | |\}}||k(r|t-| Dcgc]}|j/| |c}}t1|t rut1| t2re| j4j6rOt |Dcgc] }t9|c}}n/t|t|d|}nt|t|d|}|t1|t rywr)rr rsetrrjrzs rrGz!_solve_as_poly..5s=$776<0CE9W*QPVBW>WW$sAAr)# is_polynomialresumr>rgrTkeysrf all_rootsrrYrgensrgenas_exprrrrrrr|rXrKrrrr'rrLrUrrr intersection)rrrrr num_rootsrorrrdeg poly_solnsrrlhsrhs_srrs rrbrbs Fvat#D2 ' !V  ) -F6?D"DNN$Et{{}E *"E*%fbAh?Aw <!&"Q(F;F996af 66 t9>d1g&D((C$++-C  DAD"E$td37%99=AJ:$%fbAh?f}#J*0*:*:177*C;%c1f5 U&="z$J!UZZ1%5$JKF!&)4C:"%(("6"6!*F,KqZ],K!L)&"Q(FCF!&"Q(F;F  fi ( $"$$#J!&N1,=">G fi (Vq{{-B((0F FBq!Hf55W7$%K-Ls4M MM-Mc |}|r|ngf\}}|s2||ttDcgc] }|| c}z }n|\} } || tz | s5tdd} | j | | i} |j | | i}| } || } ||| } t| Dcgc]}t t | || c}}fdfd|}|Scc}wcc}w)z2 Helper function to solve equations with radicals yrealTrcg}g}|D]2}t|r|j|"|j|4t|tt dt|zSr)rtrrTrYr) solutionsf_setc_setrrrs rcheck_finitesetz'_solve_radical..check_finitesetUsd A61% Q Q  % <1a)UBS#TTTrc\|tjur|St|tr|St|tr|St|t r!|j \}}t ||St|tr&t|j Dcgc] }| c}S|Scc}wr)rrrrYrTr[rrX)rrVBrr check_sets rrz!_solve_radical..check_set_s  "   < 0   9 -"9- -  : .>>DAqilA. .  5 )@A9Q<@A A  AsB))rXrurrrXrUr)runradfrsolveset_solverreqrrrryeqrg_y_sf_y_solsr1 solution_setrrs` ` @@r_solve_radicalrBs  Ccq"gGB  V, q&8IJ1OAv.J KL3q1ua('-E,,5z*CaZ(BAV,"2q)$)+ "&C.(;+,U$V$L WK+s C" +C'c|jtjstt dt dt dt d}}}|j |t|z|zxsi}|||fDcgc]"}|j|tj$c}\}} } |js| jst| ||}ddl m } | | dk\|d|d } | j|} t|| z| z|j!| }t|| z| z|j!| }t#||St%|t'|d|Scc}w) zE Helper function to solve equation involving absolute value function zR Absolute values cannot be inverted in the complex domain.rBrrrsolve_univariate_inequalityrFT) relationalr continuous)rrrrrzr matchr?rUrrr inequalitiesr complement solveset_realrrXrYr)rrrrBrr pattern_matchrf_pf_qf_rr q_pos_cond q_neg_cond sols_q_pos sols_q_negs r _solve_absrvsP   AGG $% ! !3icDI!qAGGAc!fHqL)/RM<=q!9Ea]&&q!&&1EMCc KK3;;"37=06>> from sympy import exp, sin, Symbol, pprint, S >>> from sympy.solvers.solveset import solve_decomposition as sd >>> x = Symbol('x') >>> f1 = exp(2*x) - 3*exp(x) + 2 >>> sd(f1, x, S.Reals) {0, log(2)} >>> f2 = sin(x)**2 + 2*sin(x) + 1 >>> pprint(sd(f2, x, S.Reals), use_unicode=False) 3*pi {2*n*pi + ---- | n in Integers} 2 >>> f3 = sin(x + 2) >>> pprint(sd(f3, x, S.Reals), use_unicode=False) {2*n*pi - 2 | n in Integers} U {2*n*pi - 2 + pi | n in Integers} r) decompogenr)sympy.solvers.decompogenrrTrrWrrrrlrrYrZrXrr(r)tupler base_setsr)rrrrg_sy_srfrangerrr iter_isetiset new_solutions dummy_varbase_set new_exprsnew_exprs rsolve_decompositionrs.4 Q C A,C '66263' c9 % ($R1Xvv> !)\:i'F ( #x( F C'HH  "zz!! N (DJJOOQ)? P !$**//">">?B "nn mY7 -I |<!-"4"4Q"7C$1$6$6q$9 )NHhvi'BHMMFN N QZZ 1a&9 9O'R JrFc  ddlm}t|trS|}|jrS|j |d\}}|t jt jt jhvrt|}n~|jrr|j |\}}|j |d\} }| t jt jt jt jhvr|| z |z}fd} fd} t j} |jjrS|j!|st jS|jrGt#fd|j$Dr)t'|j$D cgc] } | | | c} } n/t)t*||st)t,||rt/||} nt|t0rH|j$d}t3t5t7|dkD|t5t9||} n|j:rH|j=} | D]0\}}|j>r|jA}| |||}| |z } 2nRt|tBr-| tE|jF|jH d|} n|j>rd d l%m&} |||d } | StS||rtU||} n| |d|\}}||k(rDt|tVr0tW|Dcgc]}tY||j[ c}}|} nt|tVrI|Dcgc]}||z  c}D]1}||k(rt]||}|r| t_|||| z } *|j!t`r| tc||z } Pte||}t|tPs| |z } stg||}t|tPr|ji}|jrs||k7rn|j |\}}|jsNg}tYjj|D],}|j!|s|jm| ||.t'|}| |z } &| | ||z } 4n)|t jurtQ|tC|d} t| tPrct|tnrS|jq\}} | j!|r/t5||}!t|!tPst5| |}"|!|"z } |rt| tPr| St|tnr-|j |d d }#|#j |dd }#n|}#t| tVr3tW| D$cgc]!}$t|$trs tu|#||$r|$#c}$} | Scc} w#tN$rtQ||} Y| SwxYwcc}wcc}wcc}$w) zHelper for solveset to return a result from an expression that has already been sympify'ed and is known to contain the given symbol.r)signsimpFrjct|||Sr)rc)rrrs rrz_solveset..s1a)@rc t|||Sr)r)rrrrs rrz_solveset..sgaff&Erc36K|]}t|ywr)rZ)rFrsrs rrGz_solveset..s 6a@rrr)rrT);sympy.simplify.simplifyrrrSrrrr%r$r&rhrrrrrrrLrrXr]rQrCrmr@rWrcrArB is_Piecewiseas_expr_set_pairs is_Relationalas_setrr rrrrr4rY _is_modular_solve_modularrTr as_content_primitivervrr?rrf _transolverk make_argsrrrrjrC)%rrr_checkrorig_fcoeffrrrssolverrrexpr_set_pairsr)in_setrrrrrrequationuresult_rationalt_resultfactored_dep t_resultsfacrr_result singularitiesfxrs% ` rrcrcs 1![! Fxx##F5#9q Q&&(:(:AJJG G A '1u51 Q&& 002 2!aA"( @FEH ZZFxxz UU6]zz cVVAFF;q6*;< %&;Q G '(:Av FQ/ As  FF1Ii1 66B'1vv>@ ,,V4, NT6##40E eOF   Ar AEEAEE6E:FFK = 50 vf8F Q 662aF+ U &=%+!"$$%(QK446%8$$%F y )2783S3Y8% 7q=a(A.11717#99"c**Q"??*B""6%"8;BB fi (F!6q#Av.%b&!4"#!67F Mi<.# 5!&!V4F  5 $$ 9F!6s* W W"$#W?$ X1&X "W<;W<cT|jtsyt|jt}t |dk(xre|dj dj|xrB|dj dj xr$tdtt|DS)aA Helper function to check below mentioned types of modular equations. ``A - Mod(B, C) = 0`` A -> This can or cannot be a function of symbol. B -> This is surely a function of symbol. C -> It is an integer. Parameters ========== f : Expr The equation to be checked. symbol : Symbol The concerned variable for which the equation is to be checked. Examples ======== >>> from sympy import symbols, exp, Mod >>> from sympy.solvers.solveset import _is_modular as check >>> x, y = symbols('x y') >>> check(Mod(x, 3) - 1, x) True >>> check(Mod(x, 3) - 1, y) False >>> check(Mod(x, 3)**2 - 5, x) False >>> check(Mod(x, 3)**2 - y, x) False >>> check(exp(Mod(x, 3)) - 1, x) False >>> check(Mod(3, y) - 1, y) False Frrc3<K|]}t|tywr)rrrFterms rrGz_is_modular..s04%0r{) rrrrrr is_integerr} _term_factors)rrmodtermss rrr{sL 55:AGGCL!H MQ  0 QK  Q  # #F + 0 QK  Q  * * 0 0]1-.0 0rc F|j\}}|jdur|tjfS|jdus$t dt t|Dr||fSt|t|k\r|tjfS||k(r,|tt|||z|ztjfS|jrW|j|\}}|tjur1|t||z }t!t||t||||S|j"rW|j|\}}|tj$ur1|t'||z}t!t||t||||S|j(r|j\} } | j+|r-| j+|s|j,s&|j,r|j.j,r||fS|j0t3|j0|j0z} t5| |j0|j.j0} t9|} t;| D]K}t=|j.||t3|j0|j.j0z dk(sI|} n| tt|| |z| ztj>fS| j+|r| j+|sp tA|| |d}|gk(r|tjfS tj}|D]/}|tt|||z|ztjz }1| |fS||fS#t6$r||fcYSwxYw#t6tBf$r||fcYSwxYw)a Helper function to invert modular equation. ``Mod(a, m) - rhs = 0`` Generally it is inverted as (a, ImageSet(Lambda(n, m*n + rhs), S.Integers)). More simplified form will be returned if possible. If it is not invertible then (modterm, rhs) is returned. The following cases arise while inverting equation ``Mod(a, m) - rhs = 0``: 1. If a is symbol then m*n + rhs is the required solution. 2. If a is an instance of ``Add`` then we try to find two symbol independent parts of a and the symbol independent part gets transferred to the other side and again the ``_invert_modular`` is called on the symbol dependent part. 3. If a is an instance of ``Mul`` then same as we done in ``Add`` we separate out the symbol dependent and symbol independent parts and transfer the symbol independent part to the rhs with the help of invert and again the ``_invert_modular`` is called on the symbol dependent part. 4. If a is an instance of ``Pow`` then two cases arise as following: - If a is of type (symbol_indep)**(symbol_dep) then the remainder is evaluated with the help of discrete_log function and then the least period is being found out with the help of totient function. period*n + remainder is the required solution in this case. For reference: (https://en.wikipedia.org/wiki/Euler's_theorem) - If a is of type (symbol_dep)**(symbol_indep) then we try to find all primitive solutions list with the help of nthroot_mod function. m*n + rem is the general solution where rem belongs to solutions list from nthroot_mod function. Parameters ========== modterm, rhs : Expr The modular equation to be inverted, ``modterm - rhs = 0`` symbol : Symbol The variable in the equation to be inverted. n : Dummy Dummy variable for output g_n. Returns ======= A tuple (f_x, g_n) is being returned where f_x is modular independent function of symbol and g_n being set of values f_x can have. Examples ======== >>> from sympy import symbols, exp, Mod, Dummy, S >>> from sympy.solvers.solveset import _invert_modular as invert_modular >>> x, y = symbols('x y') >>> n = Dummy('n') >>> invert_modular(Mod(exp(x), 7), S(5), n, x) (Mod(exp(x), 7), 5) >>> invert_modular(Mod(x, 7), S(5), n, x) (x, ImageSet(Lambda(_n, 7*_n + 5), Integers)) >>> invert_modular(Mod(3*x + 8, 7), S(5), n, x) (x, ImageSet(Lambda(_n, 7*_n + 6), Integers)) >>> invert_modular(Mod(x**4, 7), S(5), n, x) (x, EmptySet) >>> invert_modular(Mod(2**(x**2 + x + 1), 7), S(2), n, x) (x**2 + x + 1, ImageSet(Lambda(_n, 3*_n + 1), Naturals0)) Fc38K|]}|jduyw)FN)is_realrs rrGz"_invert_modular..s!#0$(<<5#8#0srT)r)"rr rrrr}rr absrZrrrrrr_invert_modularrrrmrr is_IntegerrrBrrcrr>rbpow Naturals0rdr4)modtermrrrrrsrr x_indep_termrrmdiv remainderrrBremainder_listg_nrems rrrs4T <va|+L"3q!9c,.BAvN NxxVV d 88F DHHV$4<>> from sympy.solvers.solveset import _solve_modular as solve_modulo >>> from sympy import S, Symbol, sin, Intersection, Interval, Mod >>> x = Symbol('x') >>> solve_modulo(Mod(5*x - 8, 7) - 3, x, S.Integers) ImageSet(Lambda(_n, 7*_n + 5), Integers) >>> solve_modulo(Mod(5*x - 8, 7) - 3, x, S.Reals) # domain should be subset of integers. ConditionSet(x, Eq(Mod(5*x + 6, 7) - 3, 0), Reals) >>> solve_modulo(-7 + Mod(x, 5), x, S.Integers) EmptySet >>> solve_modulo(Mod(12**x, 21) - 18, x, S.Integers) ImageSet(Lambda(_n, 6*_n + 2), Naturals0) >>> solve_modulo(Mod(sin(x), 7) - 3, x, S.Integers) # not solvable ConditionSet(x, Eq(Mod(sin(x), 7) - 3, 0), Integers) >>> solve_modulo(3 - Mod(x, 5), x, Intersection(S.Integers, Interval(0, 100))) Intersection(ImageSet(Lambda(_n, 5*_n + 3), Integers), Range(0, 101, 1)) rrTr)rYrrrrrrrKras_coefficients_dictrrrrrrrrrZr(r)r*rrcrTrr)rrrunsolved_resultrrrrr lamda_expr lamda_varsrsol_settmp_solrrs rrrCs`#62a8V>> from sympy import symbols >>> from sympy.solvers.solveset import _term_factors >>> x = symbols('x') >>> list(_term_factors(-2 - x**2 + x*(x + 1))) [-2, -1, x**2, x, x + 1] N)r rr )radd_args rr r s5.==#*==)))*)s 1=;=c (t|t||z d|}t|}||k7r#t||z }|||z k7r t |||St |t rt|jdk(s|S|dk7r|Stt|j\}}|j|d} |j|d} | j\} } | j\} }|jtjr;t!| dkD| dkDtt#| dtt#|d}n t!t%| dt%| d}d|| fD\}}t ||z ||}t|||S)a Helper function for solving (supported) exponential equations. Exponential equations are the sum of (currently) at most two terms with one or both of them having a power with a symbol-dependent exponent. For example .. math:: 5^{2x + 3} - 5^{3x - 1} .. math:: 4^{5 - 9x} - e^{2 - x} Parameters ========== lhs, rhs : Expr The exponential equation to be solved, `lhs = rhs` symbol : Symbol The variable in which the equation is solved domain : Set A set over which the equation is solved. Returns ======= A set of solutions satisfying the given equation. A ``ConditionSet`` if the equation is unsolvable or if the assumptions are not properly defined, in that case a different style of ``ConditionSet`` is returned having the solution(s) of the equation with the desired assumptions. Examples ======== >>> from sympy.solvers.solveset import _solve_exponential as solve_expo >>> from sympy import symbols, S >>> x = symbols('x', real=True) >>> a, b = symbols('a b') >>> solve_expo(2**x + 3**x - 5**x, 0, x, S.Reals) # not solvable ConditionSet(x, Eq(2**x + 3**x - 5**x, 0), Reals) >>> solve_expo(a**x - b**x, 0, x, S.Reals) # solvable but incorrect assumptions ConditionSet(x, (a > 0) & (b > 0), {0}) >>> solve_expo(3**(2*x) - 2**(x + 3), 0, x, S.Reals) {-3*log(2)/(-2*log(3) + log(2))} >>> solve_expo(2**x - 4**x, 0, x, S.Reals) {0} * Proof of correctness of the method The logarithm function is the inverse of the exponential function. The defining relation between exponentiation and logarithm is: .. math:: {\log_b x} = y \enspace if \enspace b^y = x Therefore if we are given an equation with exponent terms, we can convert every term to its corresponding logarithmic form. This is achieved by taking logarithms and expanding the equation using logarithmic identities so that it can easily be handled by ``solveset``. For example: .. math:: 3^{2x} = 2^{x + 3} Taking log both sides will reduce the equation to .. math:: (2x)\log(3) = (x + 3)\log(2) This form can be easily handed by ``solveset``. rrrc3HK|]}tt|dyw)TforceN)rr.rFrs rrGz%_solve_exponential..$s >> from sympy import symbols, cos, exp >>> from sympy.solvers.solveset import _is_exponential as check >>> x, y = symbols('x y') >>> check(y, y) False >>> check(x**y - 1, y) True >>> check(x**y*2**y - 1, y) True >>> check(exp(x + 3) + 3**x, x) True >>> check(cos(2**x), x) False * Philosophy behind the helper The function extracts each term of the equation and checks if it is of exponential form w.r.t ``symbol``. FT)r rrrrr5)rrrvexpr_args r_is_exponentialr8*sdH B!!$ .. .  x % 33 3 h $B Irc@t|d}||z }t|||S)a1 Helper to solve logarithmic equations which are reducible to a single instance of `\log`. Logarithmic equations are (currently) the equations that contains `\log` terms which can be reduced to a single `\log` term or a constant using various logarithmic identities. For example: .. math:: \log(x) + \log(x - 4) can be reduced to: .. math:: \log(x(x - 4)) Parameters ========== lhs, rhs : Expr The logarithmic equation to be solved, `lhs = rhs` symbol : Symbol The variable in which the equation is solved domain : Set A set over which the equation is solved. Returns ======= A set of solutions satisfying the given equation. A ``ConditionSet`` if the equation is unsolvable. Examples ======== >>> from sympy import symbols, log, S >>> from sympy.solvers.solveset import _solve_logarithm as solve_log >>> x = symbols('x') >>> f = log(x - 3) + log(x + 3) >>> solve_log(f, 0, x, S.Reals) {-sqrt(10), sqrt(10)} * Proof of correctness A logarithm is another way to write exponent and is defined by .. math:: {\log_b x} = y \enspace if \enspace b^y = x When one side of the equation contains a single logarithm, the equation can be solved by rewriting the equation as an equivalent exponential equation as defined above. But if one side contains more than one logarithm, we need to use the properties of logarithm to condense it into a single logarithm. Take for example .. math:: \log(2x) - 15 = 0 contains single logarithm, therefore we can directly rewrite it to exponential form as .. math:: x = \frac{e^{15}}{2} But if the equation has more than one logarithm as .. math:: \log(x - 3) + \log(x + 3) = 0 we use logarithmic identities to convert it into a reduced form Using, .. math:: \log(a) + \log(b) = \log(ab) the equation becomes, .. math:: \log((x - 3)(x + 3)) This equation contains one logarithm and can be solved by rewriting to exponents. Tr')r-rc)rrrrnew_lhsnew_fs r_solve_logarithmr<[s)fD)G cME UFF ++rcd}tj|D]L}d}tj|D]+}||jvrt |t r|ryd}*y|sKd}N|S)ae Return ``True`` if the equation is in the form `a\log(f(x)) + b\log(g(x)) + ... + c` else ``False``. Parameters ========== f : Expr The equation to be checked symbol : Symbol The variable in which the equation is checked Returns ======= ``True`` if the equation is logarithmic otherwise ``False``. Examples ======== >>> from sympy import symbols, tan, log >>> from sympy.solvers.solveset import _is_logarithmic as check >>> x, y = symbols('x y') >>> check(log(x + 2) - log(x + 3), x) True >>> check(tan(log(2*x)), x) False >>> check(x*log(x), x) False >>> check(x + log(x), x) False >>> check(y + log(x), x) True * Philosophy behind the helper The function extracts each term and checks whether it is logarithmic w.r.t ``symbol``. FT)r rr rrr.)rrr6r saw_logterm_args r_is_logarithmicr@syR B a  d+ HX222(C(   B  Irc tt|j}t|Dcgc]}|js|c}}t|Dcgc]}|jt t r|!c}}|jrG|dk\rBtt t ftfd|Dr||kryytfd|Dryycc}wcc}w)a If this returns ``False`` then the Lambert solver (``_solve_lambert``) will not be called. Explanation =========== Quick check for cases that the Lambert solver might be able to handle. 1. Equations containing more than two operands and `symbol`s involving any of `Pow`, `exp`, `HyperbolicFunction`,`TrigonometricFunction`, `log` terms. 2. In `Pow`, `exp` the exponent should have `symbol` whereas for `HyperbolicFunction`,`TrigonometricFunction`, `log` should contain `symbol`. 3. For `HyperbolicFunction`,`TrigonometricFunction` the number of trigonometric functions in equation should be less than number of symbols. (since `A*cos(x) + B*sin(x) - c` is not the Lambert type). Some forms of lambert equations are: 1. X**X = C 2. X*(B*log(X) + D)**A = C 3. A*log(B*X + A) + d*X = C 4. (B*X + A)*exp(d*X + g) = C 5. g*exp(B*X + h) - B*X = C 6. A*D**(E*X + g) - B*X = C 7. A*cos(X) + B*sin(X) - D*X = C 8. A*cosh(X) + B*sinh(X) - D*X = C Where X is any variable, A, B, C, D, E are any constants, g, h are linear functions or log terms. Parameters ========== f : Expr The equation to be checked symbol : Symbol The variable in which the equation is checked Returns ======= If this returns ``False`` then the Lambert solver (``_solve_lambert``) will not be called. Examples ======== >>> from sympy.solvers.solveset import _is_lambert >>> from sympy import symbols, cosh, sinh, log >>> x = symbols('x') >>> _is_lambert(3*log(x) - x*log(3), x) True >>> _is_lambert(log(log(x - 3)) + log(x-3), x) True >>> _is_lambert(cosh(x) - sinh(x), x) False >>> _is_lambert((x**2 - 2*x + 1).subs(x, (log(x) + 3*x)**2 - 1), x) True See Also ======== _solve_lambert rc3ZK|]"}|jrt|$ywr)rr)rFr@ lambert_funcsrs rrGz_is_lambert..?s,8wswwv#}-8s(+Tc3K|]=}|jdjrt|ttf?yw)rN)r*rrrr5)rFr@rs rrGz_is_lambert..DsAK(9!(<'A'A&'IC#s,KsAAF) rr rrrrCrQrr.r})rr term_factorsr@ no_of_symbols no_of_trigrCs ` @r _is_lambertrHsJ ahhj12L HHIM\?c 377%'< =?@J xxMQ&02GH 8#8 8 - K#KK #I?sCC$Ccd}t|t|d|}t|d||\}}t|trBt |j dk(sJ|j d}|jr |||||}|S|}|S)ay Function to solve transcendental equations. It is a helper to ``solveset`` and should be used internally. ``_transolve`` currently supports the following class of equations: - Exponential equations - Logarithmic equations Parameters ========== f : Any transcendental equation that needs to be solved. This needs to be an expression, which is assumed to be equal to ``0``. symbol : The variable for which the equation is solved. This needs to be of class ``Symbol``. domain : A set over which the equation is solved. This needs to be of class ``Set``. Returns ======= Set A set of values for ``symbol`` for which ``f`` is equal to zero. An ``EmptySet`` is returned if ``f`` does not have solutions in respective domain. A ``ConditionSet`` is returned as unsolved object if algorithms to evaluate complete solution are not yet implemented. How to use ``_transolve`` ========================= ``_transolve`` should not be used as an independent function, because it assumes that the equation (``f``) and the ``symbol`` comes from ``solveset`` and might have undergone a few modification(s). To use ``_transolve`` as an independent function the equation (``f``) and the ``symbol`` should be passed as they would have been by ``solveset``. Examples ======== >>> from sympy.solvers.solveset import _transolve as transolve >>> from sympy.solvers.solvers import _tsolve as tsolve >>> from sympy import symbols, S, pprint >>> x = symbols('x', real=True) # assumption added >>> transolve(5**(x - 3) - 3**(2*x + 1), x, S.Reals) {-(log(3) + 3*log(5))/(-log(5) + 2*log(3))} How ``_transolve`` works ======================== ``_transolve`` uses two types of helper functions to solve equations of a particular class: Identifying helpers: To determine whether a given equation belongs to a certain class of equation or not. Returns either ``True`` or ``False``. Solving helpers: Once an equation is identified, a corresponding helper either solves the equation or returns a form of the equation that ``solveset`` might better be able to handle. * Philosophy behind the module The purpose of ``_transolve`` is to take equations which are not already polynomial in their generator(s) and to either recast them as such through a valid transformation or to solve them outright. A pair of helper functions for each class of supported transcendental functions are employed for this purpose. One identifies the transcendental form of an equation and the other either solves it or recasts it into a tractable form that can be solved by ``solveset``. For example, an equation in the form `ab^{f(x)} - cd^{g(x)} = 0` can be transformed to `\log(a) + f(x)\log(b) - \log(c) - g(x)\log(d) = 0` (under certain assumptions) and this can be solved with ``solveset`` if `f(x)` and `g(x)` are in polynomial form. How ``_transolve`` is better than ``_tsolve`` ============================================= 1) Better output ``_transolve`` provides expressions in a more simplified form. Consider a simple exponential equation >>> f = 3**(2*x) - 2**(x + 3) >>> pprint(transolve(f, x, S.Reals), use_unicode=False) -3*log(2) {------------------} -2*log(3) + log(2) >>> pprint(tsolve(f, x), use_unicode=False) / 3 \ | --------| | log(2/9)| [-log\2 /] 2) Extensible The API of ``_transolve`` is designed such that it is easily extensible, i.e. the code that solves a given class of equations is encapsulated in a helper and not mixed in with the code of ``_transolve`` itself. 3) Modular ``_transolve`` is designed to be modular i.e, for every class of equation a separate helper for identification and solving is implemented. This makes it easy to change or modify any of the method implemented directly in the helpers without interfering with the actual structure of the API. 4) Faster Computation Solving equation via ``_transolve`` is much faster as compared to ``_tsolve``. In ``solve``, attempts are made computing every possibility to get the solutions. This series of attempts makes solving a bit slow. In ``_transolve``, computation begins only after a particular type of equation is identified. How to add new class of equations ================================= Adding a new class of equation solver is a three-step procedure: - Identify the type of the equations Determine the type of the class of equations to which they belong: it could be of ``Add``, ``Pow``, etc. types. Separate internal functions are used for each type. Write identification and solving helpers and use them from within the routine for the given type of equation (after adding it, if necessary). Something like: .. code-block:: python def add_type(lhs, rhs, x): .... if _is_exponential(lhs, x): new_eq = _solve_exponential(lhs, rhs, x) .... rhs, lhs = eq.as_independent(x) if lhs.is_Add: result = add_type(lhs, rhs, x) - Define the identification helper. - Define the solving helper. Apart from this, a few other things needs to be taken care while adding an equation solver: - Naming conventions: Name of the identification helper should be as ``_is_class`` where class will be the name or abbreviation of the class of equation. The solving helper will be named as ``_solve_class``. For example: for exponential equations it becomes ``_is_exponential`` and ``_solve_expo``. - The identifying helpers should take two input parameters, the equation to be checked and the variable for which a solution is being sought, while solving helpers would require an additional domain parameter. - Be sure to consider corner cases. - Add tests for each helper. - Add a docstring to your helper that describes the method implemented. The documentation of the helpers should identify: - the purpose of the helper, - the method used to identify and solve the equation, - a proof of correctness - the return values of the helpers ct|t||z d|}t||rt||||}|St ||rt ||||}|S)z Helper for ``_transolve`` to handle equations of ``Add`` type, i.e. equations taking the form as ``a*f(x) + b*g(x) + .... = c``. For example: 4**x + 8**x = 0 r)rYrr8r4r@r<)rrrrrs radd_typez_transolve..add_typesafbsA&6? 3 ''S&&AF  S& )%c3?F rrr)rYrr|rrTrrr)rrrrKrrrrs rrrJsf$&"Q(F 3F 1ff5JC%#EJJA%%%jjm ::c37F M MrcJt|}t|}|tjur|S|tjurtjSt |t ttfstd|zt |t tfs|t|dt |tstd|z|j}|jtr t|}|[|sYt|d}|tjur|S|tjurtjSt!t#d|z|5t%|dk(r|j'}nZ|rXtt#dt |t(s4t+|g|g\}}}t-|d|d|j/|Sd}|j1tj2r|j4d d ik7rKt7d d }n=|j1tj8r|j4d d ik7r t7dd }|Gt-|j/||i||} |j/||i} |j=| r| }|St?|t@\}} |jCt}| D]I\} } | jE| jFdjCt} |j/| | i}Kt|}tI|||d S#t:$r|} YwxYw)a Solves a given inequality or equation with set as output Parameters ========== f : Expr or a relational. The target equation or inequality symbol : Symbol The variable for which the equation is solved domain : Set The domain over which the equation is solved Returns ======= Set A set of values for `symbol` for which `f` is True or is equal to zero. An :class:`~.EmptySet` is returned if `f` is False or nonzero. A :class:`~.ConditionSet` is returned as unsolved object if algorithms to evaluate complete solution are not yet implemented. ``solveset`` claims to be complete in the solution set that it returns. Raises ====== NotImplementedError The algorithms to solve inequalities in complex domain are not yet implemented. ValueError The input is not valid. RuntimeError It is a bug, please report to the github issue tracker. Notes ===== Python interprets 0 and 1 as False and True, respectively, but in this function they refer to solutions of an expression. So 0 and 1 return the domain and EmptySet, respectively, while True and False return the opposite (as they are assumed to be solutions of relational expressions). See Also ======== solveset_real: solver for real domain solveset_complex: solver for complex domain Examples ======== >>> from sympy import exp, sin, Symbol, pprint, S, Eq >>> from sympy.solvers.solveset import solveset, solveset_real * The default domain is complex. Not specifying a domain will lead to the solving of the equation in the complex domain (and this is not affected by the assumptions on the symbol): >>> x = Symbol('x') >>> pprint(solveset(exp(x) - 1, x), use_unicode=False) {2*n*I*pi | n in Integers} >>> x = Symbol('x', real=True) >>> pprint(solveset(exp(x) - 1, x), use_unicode=False) {2*n*I*pi | n in Integers} * If you want to use ``solveset`` to solve the equation in the real domain, provide a real domain. (Using ``solveset_real`` does this automatically.) >>> R = S.Reals >>> x = Symbol('x') >>> solveset(exp(x) - 1, x, R) {0} >>> solveset_real(exp(x) - 1, x) {0} The solution is unaffected by assumptions on the symbol: >>> p = Symbol('p', positive=True) >>> pprint(solveset(p**2 - 4)) {-2, 2} When a :class:`~.ConditionSet` is returned, symbols with assumptions that would alter the set are replaced with more generic symbols: >>> i = Symbol('i', imaginary=True) >>> solveset(Eq(i**2 + i*sin(i), 1), i, domain=S.Reals) ConditionSet(_R, Eq(_R**2 + _R*sin(_R) - 1, 0), Reals) * Inequalities can be solved over the real domain only. Use of a complex domain leads to a NotImplementedError. >>> solveset(exp(x) > 1, x, R) Interval.open(0, oo) z"%s is not a valid SymPy expressionNz is not a valid SymPy symbolz%s is not a valid domainrz@ relationship between value and 0 is unknown: %srzh The independent variable must be specified for a multivariate equation.rTr3rrRC)rR)r)%rrrrrrrrrrr]rrr=r<rr4rzrpopr rxrlrXrr_assumptions_origrrrdummy_eqrr?rrrrc) rrrrrrswapnewsymr6_rvrdrs rrlrl! sJ  A V_FAFF{ AGG|zz a$ F3 4=ABB ftZ0 1v7IVEFF fc "3f=>>>>LuuY 1  ~l q!H ;M !''\:: %j2CEF2G'HI I~ |  !!%%'F Z)*+, , '&sVH5 1d!adF+44T::F   # #~ 53T*F   !++ &  # # 4'8 83-F  ajj&&!12FF C ++vv./C ;;s B aoGAt )A1 FF166!9$$Y/ 0 JJ1v  qA Qt 44) C sL L"!L"c8t||tjSr)rlrrrrs rrr s Avqww ''rc8t||tjSr)rlrrrVs rrr s Avq{{ ++rc i}t|D]2\}}|tjust|jd||<4|Dcgc]}|j |}}Dcgc]}|j |c}t t|dk(rt|Stdk(rRd}|d}|Dcgc]}t|||}}t|} tt|f|f| jSt|fd}t|D]\} }g} d} D]}|j vrt|||j#|} t%| t&rj#|}d||dzdz}|d|||dzdz}|d| || dzdz}| D]q}|Dcgc]}|j ||}}t)|||}t|f|d||fz||dz}| j+t||jsd} | st-| cSycc}wcc}wcc}wcc}w) ziBasic implementation of a multivariate solveset. For internal use (not ready for public consumption)TrrrcFt|jtzSr)rrr)rrs rrz!_solveset_multi.. sS3t9)D%ErkeyNF)ziprrr namerKrrr^rlrWrZrdoitsortedrrindexrrT_solveset_multirrX)eqsrdomainsreprdomrrsolsetssolsetrsols all_handledrrrsymspdomainspeqspreqsp_sub sol_othersfuns ` rrara sn Cg&3S !''>chhT2CH3#& &B2773< &C &%) *cCHHSM *D ;D 3x1}7## 4yA~1g7:;8BV,;;w'vv.7<<>> E FC3 2  $C"//)2sGDJJsO$<=C#y)JJsORa4!:-"2A;162AwQqST*BA:>?BQ?H?!05(!KJ %5!9t+;eABi+GHCKKj 9 > > @A B $ ! $" $< + # ' *<( @s H2'H7?H<0I c Nt|||}d}|tjurg}|St|tr t dt|t r t|}|St||}|tj}d}t|tr|f}n8t|tr(td|jDr |j}|D]"}||jtd|ddz }$t|t r t|}|S|j|}t|tr[td|jDr>|jD cgc]%} | jD]} t| t r| '}} } |Syt|t r||z }|Scc} } w) aSolves an equation using solveset and returns the solution in accordance with the `solve` output API. Returns ======= We classify the output based on the type of solution returned by `solveset`. Solution | Output ---------------------------------------- FiniteSet | list ImageSet, | list (if `f` is periodic) Union | Union | list (with FiniteSet) EmptySet | empty list Others | None Raises ====== NotImplementedError A ConditionSet is the input. Examples ======== >>> from sympy.solvers.solveset import solvify >>> from sympy.abc import x >>> from sympy import S, tan, sin, exp >>> solvify(x**2 - 9, x, S.Reals) [-3, 3] >>> solvify(sin(x) - 1, x, S.Reals) [pi/2] >>> solvify(tan(x), x, S.Reals) [0] >>> solvify(exp(x) - 1, x, S.Complexes) >>> solvify(exp(x) - 1, x, S.Reals) [0] Nz*solveset is unable to solve this equation.rc3<K|]}t|tywrrrZr)s rrGzsolvify..T sJ1z!X.Jr{rFTc3<K|]}t|tywr)rrTr)s rrGzsolvify..b sGAz!Y/Gr{)rlrrrrYr4rTrrrZrXrLrrrVr}) rrrrrrriter_solutionssolutionsolnrrs rsolvifyrw s^Avv.L Fqzz!N MK L, /!"NOO L) ,l#B M=Q'   IN,1".L%0J 8I8IJJ%1%6%6N* RX//FE40PQQ  R)Y/i M$--f5H(E*GGG.6mmId $ IZY-G"IcIFI M  Hi0(" MIs*F!)dictc&t|}t|dk(r,t|drt|dts t dt |}t|t|k7r t d t|g|\}}|d}|d}|r|r||tj<|Stjgt|dzz}||d<t|D]\}} | |vr || ||<|S#t$r}tt|d}~wwxYw)aReturn a list whose elements are the coefficients of the corresponding symbols in the sum of terms in ``eq``. The additive constant is returned as the last element of the list. Raises ====== NonlinearError The equation contains a nonlinear term ValueError duplicate or unordered symbols are passed Parameters ========== dict - (default False) when True, return coefficients as a dictionary with coefficients keyed to syms that were present; key 1 gives the constant term Examples ======== >>> from sympy.solvers.solveset import linear_coeffs >>> from sympy.abc import x, y, z >>> linear_coeffs(3*x + 2*y - 1, x, y) [3, 2, -1] It is not necessary to expand the expression: >>> linear_coeffs(x + y*(z*(x*3 + 2) + 3), x) [3*y*z + 1, y*(2*z + 3)] When nonlinear is detected, an error will be raised: * even if they would cancel after expansion (so the situation does not pass silently past the caller's attention) >>> eq = 1/x*(x - 1) + 1/x >>> linear_coeffs(eq.expand(), x) [0, 1] >>> linear_coeffs(eq, x) Traceback (most recent call last): ... NonlinearError: nonlinear in given generators * when there are cross terms >>> linear_coeffs(x*(y + 1), x, y) Traceback (most recent call last): ... NonlinearError: symbol-dependent cross-terms encountered * when there are terms that contain an expression dependent on the symbols that is not linear >>> linear_coeffs(x**2, x) Traceback (most recent call last): ... NonlinearError: nonlinear in given generators rrz!expecting unpacked symbols, *symsduplicate symbols givenNr)r"rr~rr rrr&rrrstrrrrr) rrxrsymsetrTrerrr6rr.s r linear_coeffsr~s sD "B 4yA~(47+JtAw4N<== YF 6{c$i233'!2$/1 aD aD AaeeH &&3t9q= !B BrF$1 A: !1 I 'SX&&'s4C.. D7D  Dc|sttdt|dtr t dt |ddr|d}t |r tdt|}t|tr t|}n9t|ttfr|g}nt|sttd t||\}}t#|t#|fx\}}}t%t'|t)|}t+|} t-|D]\} } | D]} || } | | | | | f<t/|d|Dcgc]}| c}}| |fS#t$r}tt!|d}~wwxYwcc}w) a8 Converts a given System of Equations into Matrix form. Here ``equations`` must be a linear system of equations in ``symbols``. Element ``M[i, j]`` corresponds to the coefficient of the jth symbol in the ith equation. The Matrix form corresponds to the augmented matrix form. For example: .. math:: 4x + 2y + 3z & = 1 \\ 3x + y + z & = -6 \\ 2x + 4y + 9z & = 2 This system will return :math:`A` and :math:`b` as: .. math:: A = \left[\begin{array}{ccc} 4 & 2 & 3 \\ 3 & 1 & 1 \\ 2 & 4 & 9 \end{array}\right] \\ .. math:: b = \left[\begin{array}{c} 1 \\ -6 \\ 2 \end{array}\right] The only simplification performed is to convert ``Eq(a, b)`` :math:`\Rightarrow a - b`. Raises ====== NonlinearError The equations contain a nonlinear term. ValueError The symbols are not given or are not unique. Examples ======== >>> from sympy import linear_eq_to_matrix, symbols >>> c, x, y, z = symbols('c, x, y, z') The coefficients (numerical or symbolic) of the symbols will be returned as matrices: >>> eqns = [c*x + z - 1 - c, y + z, x - y] >>> A, b = linear_eq_to_matrix(eqns, [x, y, z]) >>> A Matrix([ [c, 0, 1], [0, 1, 1], [1, -1, 0]]) >>> b Matrix([ [c + 1], [ 0], [ 0]]) This routine does not simplify expressions and will raise an error if nonlinearity is encountered: >>> eqns = [ ... (x**2 - 3*x)/(x - 3) - 3, ... y**2 - 3*y - y*(y - 4) + x - 4] >>> linear_eq_to_matrix(eqns, [x, y]) Traceback (most recent call last): ... NonlinearError: symbol-dependent term can be ignored using `strict=False` Simplifying these equations will discard the removable singularity in the first and reveal the linear structure of the second: >>> [e.simplify() for e in eqns] [x - 3, x + y - 4] Any such simplification needed to eliminate nonlinear terms must be done *before* calling this routine. zd Symbols must be given, for which coefficients are to be found. rz;Unordered 'set' type is not supported as input for symbols.__iter__zSymbols must be uniquezb Equation(s) must be given as a sequence, Expr, Eq or Matrix. Nr)rrzrrrrr|rrarrrr}r&rrrr{rrxr\ranger_rr`) equationssymbolsrrr}rrsshapeixrVrowrTr.colrrs rlinear_eq_to_matrixr sj %  '!*c" IK Kwqz:&!*122 "I)Z(O Ibz *K  #%  '"9g6Ar7CL((DAq5 c'58$ %B u AB-Q AQ%CA$Ac3hK  q!!_Qqb_%A a4K 'SX&&'%sE E>  E;"E66E;ch|stjS|rt|ddr|d}t|t}d}d}t|drt |dk(rt|dt r|\}}t|dt s|s|sttdt t|t |k7r t||}|Dcgc] }t|}} t||tjStt!fd|DSt|t r;|r#t|tst|dt s|ddddf|ddddf}}| td |rt#j$D cgc] } t'|}} t|} t)| |j*|j*zzr3ttd |dj,j/d zt | t |k7r t||sQt#j$D cgc] } t1}} t3d ||fd j,} t5| } nd} g}j7}t9||D]R\}}t9||Dcgc] \}}|s ||z}}}|j;| |j;t=|Tt?||\}}tA||dtjStt!fd|D| ;j*}|Dcic]}||vs|t'| }}jC|Scc}w#t$r}tt|d}~wwxYwcc} wcc} wcc}}wcc}w)a Solve system of $N$ linear equations with $M$ variables; both underdetermined and overdetermined systems are supported. The possible number of solutions is zero, one or infinite. Zero solutions throws a ValueError, whereas infinite solutions are represented parametrically in terms of the given symbols. For unique solution a :class:`~.FiniteSet` of ordered tuples is returned. All standard input formats are supported: For the given set of equations, the respective input types are given below: .. math:: 3x + 2y - z = 1 .. math:: 2x - 2y + 4z = -2 .. math:: 2x - y + 2z = 0 * Augmented matrix form, ``system`` given below: $$ \text{system} = \left[{array}{cccc} 3 & 2 & -1 & 1\\ 2 & -2 & 4 & -2\\ 2 & -1 & 2 & 0 \end{array}\right] $$ :: system = Matrix([[3, 2, -1, 1], [2, -2, 4, -2], [2, -1, 2, 0]]) * List of equations form :: system = [3x + 2y - z - 1, 2x - 2y + 4z + 2, 2x - y + 2z] * Input $A$ and $b$ in matrix form (from $Ax = b$) are given as: $$ A = \left[\begin{array}{ccc} 3 & 2 & -1 \\ 2 & -2 & 4 \\ 2 & -1 & 2 \end{array}\right] \ \ b = \left[\begin{array}{c} 1 \\ -2 \\ 0 \end{array}\right] $$ :: A = Matrix([[3, 2, -1], [2, -2, 4], [2, -1, 2]]) b = Matrix([[1], [-2], [0]]) system = (A, b) Symbols can always be passed but are actually only needed when 1) a system of equations is being passed and 2) the system is passed as an underdetermined matrix and one wants to control the name of the free variables in the result. An error is raised if no symbols are used for case 1, but if no symbols are provided for case 2, internally generated symbols will be provided. When providing symbols for case 2, there should be at least as many symbols are there are columns in matrix A. The algorithm used here is Gauss-Jordan elimination, which results, after elimination, in a row echelon form matrix. Returns ======= A FiniteSet containing an ordered tuple of values for the unknowns for which the `system` has a solution. (Wrapping the tuple in FiniteSet is used to maintain a consistent output format throughout solveset.) Returns EmptySet, if the linear system is inconsistent. Raises ====== ValueError The input is not valid. The symbols are not given. Examples ======== >>> from sympy import Matrix, linsolve, symbols >>> x, y, z = symbols("x, y, z") >>> A = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 10]]) >>> b = Matrix([3, 6, 9]) >>> A Matrix([ [1, 2, 3], [4, 5, 6], [7, 8, 10]]) >>> b Matrix([ [3], [6], [9]]) >>> linsolve((A, b), [x, y, z]) {(-1, 2, 0)} * Parametric Solution: In case the system is underdetermined, the function will return a parametric solution in terms of the given symbols. Those that are free will be returned unchanged. e.g. in the system below, `z` is returned as the solution for variable z; it can take on any value. >>> A = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) >>> b = Matrix([3, 6, 9]) >>> linsolve((A, b), x, y, z) {(z - 1, 2 - 2*z, z)} If no symbols are given, internally generated symbols will be used. The ``tau0`` in the third position indicates (as before) that the third variable -- whatever it is named -- can take on any value: >>> linsolve((A, b)) {(tau0 - 1, 2 - 2*tau0, tau0)} * List of equations as input >>> Eqns = [3*x + 2*y - z - 1, 2*x - 2*y + 4*z + 2, - x + y/2 - z] >>> linsolve(Eqns, x, y, z) {(1, -2, -2)} * Augmented matrix as input >>> aug = Matrix([[2, 1, 3, 1], [2, 6, 8, 3], [6, 8, 18, 5]]) >>> aug Matrix([ [2, 1, 3, 1], [2, 6, 8, 3], [6, 8, 18, 5]]) >>> linsolve(aug, x, y, z) {(3/10, 2/5, 0)} * Solve for symbolic coefficients >>> a, b, c, d, e, f = symbols('a, b, c, d, e, f') >>> eqns = [a*x + b*y - c, d*x + e*y - f] >>> linsolve(eqns, x, y) {((-b*f + c*e)/(a*e - b*d), (a*f - c*d)/(a*e - b*d))} * A degenerate system returns solution as set of given symbols. >>> system = Matrix(([0, 0, 0], [0, 0, 0], [0, 0, 0])) >>> linsolve(system, x, y) {(x, y)} * For an empty system linsolve returns empty set >>> linsolve([], x) EmptySet * An error is raised if any nonlinearity is detected, even if it could be removed with expansion >>> linsolve([x*(1/x - 1)], x) Traceback (most recent call last): ... NonlinearError: nonlinear term: 1/x >>> linsolve([x*(y + 1)], x, y) Traceback (most recent call last): ... NonlinearError: nonlinear cross-term: x*(y + 1) >>> linsolve([x**2 - 1], x) Traceback (most recent call last): ... NonlinearError: nonlinear term: x**2 rrrzNrz When passing a system of equations, the explicit symbols for which a solution is being sought must be given as a sequence, too. c3BK|]}j||ywrrUrFrrrs rrGzlinsolve.., s#I#CGGC$5#IrzInvalid argumentsa At least one of the symbols provided already appears in the system to be solved. One way to avoid this is to use Dummy symbols in the generator, e.g. numbered_symbols('%s', cls=Dummy) 1234567890tauc6t|jdS)Nr)r{rstrip)rs rrzlinsolve..G sc!fmmL9r)compareF)_rawc3BK|]}j||ywrrrs rrGzlinsolve..Y sA#CGGC-Ar)"rrrrrrrarrzrrrsrrrr{rTr rcolsrr}rr]rrr!r{tolistr\rr rprqrK)systemrsym_gendup_msgrrVrbrexcrr|rr]rrowsrowibielemrtermsringsolsymrdrrs @rlinsolverP sZ zz771:z2!*-0G'G Avz" v;!  6!9j ADAq&)Z0g -" 3w< CL0 ))C),-272;-C- /W- {zz!E#I#IJKCJ FJ ' Jw > wqz: .a"f~vaf~1y,--*/-8Q4=88W v!..89 :Z) !*//((6 )789 9 [CL (W% % $)!&&M2q5722%eaV9;;?4 % C 88:DaL b-0w-?H c4HH bS 3; "#w/IC T .C {zz EAAB CC !!)0B#C6MsDI~BBhhsm J}.& /$SX.. /&93ICsB M5! M: N>N$- N)8N) N/N/: NNNc~d|D}tt|t|tjt |z}|S)Nc34K|]}t|dyw)rN)r)rFrs rrGz'_return_conditionset..j s %#2c1: %)rYr rRrrr)rbr condition_sets r_return_conditionsetrh s8 % %C  wcAKKW$=?M rc  !"#$%&'(|stjSt|D]2\}}t|ts|j |j z ||<4|sd}tt|t|s$d}tt|t||fzt|ddds*d}tt|t|d|dfz||} i%i'd} d} dfd $tt|$fd &d } %'fd "fd !d #dd d!#fd d} "$%&'fd}|| t\}}}|| t \}}}| ||zz } | ||zz } | | k(r| dk7r t#&Sg}t|D]}t|D]^}|j%|j%k7r%t'dt)|j+|j+Ds^n|j-|||z}g}g}|D]w}|st/|t/krE|j%(tt1(fd}|D]}|||< |j-|||vsg|j-|y|r|}'s%r | |'%}tj}|D]+}Dcgc]}|| }}|t3t5|z }-|Scc}w)a Solves the `system` using substitution method. It is used in :func:`~.nonlinsolve`. This will be called from :func:`~.nonlinsolve` when any equation(s) is non polynomial equation. Parameters ========== system : list of equations The target system of equations symbols : list of symbols to be solved. The variable(s) for which the system is solved known_symbols : list of solved symbols Values are known for these variable(s) result : An empty list or list of dict If No symbol values is known then empty list otherwise symbol as keys and corresponding value in dict. exclude : Set of expression. Mostly denominator expression(s) of the equations of the system. Final solution should not satisfy these expressions. all_symbols : known_symbols + symbols(unsolved). Returns ======= A FiniteSet of ordered tuple of values of `all_symbols` for which the `system` has solution. Order of values in the tuple is same as symbols present in the parameter `all_symbols`. If parameter `all_symbols` is None then same as symbols present in the parameter `symbols`. Please note that general FiniteSet is unordered, the solution returned here is not simply a FiniteSet of solutions, rather it is a FiniteSet of ordered tuple, i.e. the first & only argument to FiniteSet is a tuple of solutions, which is ordered, & hence the returned solution is ordered. Also note that solution could also have been returned as an ordered tuple, FiniteSet is just a wrapper `{}` around the tuple. It has no other significance except for the fact it is just used to maintain a consistent output format throughout the solveset. Raises ====== ValueError The input is not valid. The symbols are not given. AttributeError The input symbols are not :class:`~.Symbol` type. Examples ======== >>> from sympy import symbols, substitution >>> x, y = symbols('x, y', real=True) >>> substitution([x + y], [x], [{y: 1}], [y], set([]), [x, y]) {(-1, 1)} * When you want a soln not satisfying $x + 1 = 0$ >>> substitution([x + y], [x], [{y: 1}], [y], set([x + 1]), [y, x]) EmptySet >>> substitution([x + y], [x], [{y: 1}], [y], set([x - 1]), [y, x]) {(1, -1)} >>> substitution([x + y - 1, y - x**2 + 5], [x, y]) {(-3, 4), (2, -1)} * Returns both real and complex solution >>> x, y, z = symbols('x, y, z') >>> from sympy import exp, sin >>> substitution([exp(x) - sin(y), y**2 - 4], [x, y]) {(ImageSet(Lambda(_n, I*(2*_n*pi + pi) + log(sin(2))), Integers), -2), (ImageSet(Lambda(_n, 2*_n*I*pi + log(sin(2))), Integers), 2)} >>> eqs = [z**2 + exp(2*x) - sin(y), -3 + exp(-y)] >>> substitution(eqs, [y, z]) {(-log(3), -sqrt(-exp(2*x) - sin(log(3)))), (-log(3), sqrt(-exp(2*x) - sin(log(3)))), (ImageSet(Lambda(_n, 2*_n*I*pi - log(3)), Integers), ImageSet(Lambda(_n, -sqrt(-exp(2*x) + sin(2*_n*I*pi - log(3)))), Integers)), (ImageSet(Lambda(_n, 2*_n*I*pi - log(3)), Integers), ImageSet(Lambda(_n, sqrt(-exp(2*x) + sin(2*_n*I*pi - log(3)))), Integers))} GSymbols must be given, for which solution of the system is to be found.zBsymbols should be given as a sequence, e.g. a list.Not type %s: %srrFzEIterable of symbols must be given as second argument, not type %s: %src|j}|tz tz}|r!t|}|jt|S)zJReturns the unsolved symbol present in the equation `eq`. rZ)rrrsortr)rrfreeunsolved all_symbols known_symbolss r_unsolved_symsz$substitution.._unsolved_syms sG3}--[1AA H~H MM.M /rc&t|Sr)r)rrs rrzsubstitution.. s#nQ&7"8rc$g}|D]}|}|jD]\}}d\}} |jD] \} } | |k(s | }|jD] \} } | |k(s | } |s| sPt|} |r|tjk7r t | |} | r t | | } | tj urd}n>| jr+t| dk(rt| j||<| ||<||j| |S)N)NNr) itemsrTrrrWr[rr3rrrNr) rintersection_dictcomplement_dict final_resultrres_copykey_res value_res intersect_setcomplement_setkey_sym value_sym new_values radd_intersection_complementz1substitution..add_intersection_complement s8  .CH&)iik 6"0:- ~*;*A*A*C2&GY')(1 2+:*?*?*A3&GY'))23!N )) 4I$!++)E$0M$J %$.y.$I  AJJ.#'"//C Na4G,/ N,>,>,@),5)) 6,###H-3 .4rct|tr |j}t|tr!|jd|<|jd}t|t rG|j}t j}|D]&}t|tr||z }|t|z }(t|trP|jdt jt jfvr|jd|<|jd}t|tr(|}|jj}t|}|||<t|ts t|}||fS)aSeparate the Complements, Intersections, ImageSet lambda expr and its base_set. This function returns the unmasked sol from different classes of sets and also returns the appended ImageSet elements in a soln_imageset dict: `{unmasked element: ImageSet}`. rr)rrYrr[rrXrrrTrWrrrZr(r)) rrr soln_imagesetsol_argssol_arg2 soln_imagestexpr2 complements intersectionss r_extract_main_solnz(substitution.._extract_main_soln s. c< (,,C c: &"xx{K ((1+C c5 !xxH**C% /h 28OC9X..C  / c< (xx{177AKK"88&)XXa[ c"((1+C c8 $LIINNEE"C#/M% #y)C.CM!!rc||rD|j}|d}|jD]\}}|j|d||<| tfdD}|S#t$rd}Y|SwxYw)Nrc36K|]}t|ywrrt)rFrTrnew_s rrGz7substitution.._check_exclude..c s"5'(E""5r)copyrrKr}r) rnew imgset_yes rnew_copydummy_nrrsatisfy_excluderexcludes @r_check_excludez$substitution.._check_excludeR s  I mG&/oo&7 @"%.^^GQ%? '" @E # ""5,3"55O #"O #s A"" A10A1ct|jt|jz}|D] }||}|||<||vr|j|yyr)rrr)roriginal_imageset newresult restore_symrimgs r_restore_imgsetz%substitution.._restore_imgseti sh$))+& !&&( )* " G#G,CDM  y   T " !rctd}|r|j|d}|dvr|nt|||d}|durd}i}n|j||||fS)Nrr)TFT)minimalF)rrKrtr)rrr delete_solnrrsatisfys r _append_eqz substitution.._append_eqr sa #J ABm+"!QD1Q e KC MM# sK''rc||}d} |sd} |r|d} |d} |rx|rvt|jt} tdt | D cgc]} | }} t | |}t | |j|}t|| ||<|`|||| | \}}} nO||||| \}}} n=||jvr||||<|||n|j|n|rd} i}||||| fScc} w)aIf `rnew` (A dict ) contains valid soln append it to `newresult` list. `imgset_yes` is (base, dummy_var) if there was imageset in previously calculated result(otherwise empty tuple). `original_imageset` is dict of imageset expr and imageset from this result. `soln_imageset` dict of imageset expr and imageset of new soln. FNrrT) rrrrrr\rrKrZrr)rrrrrrrrrrrlocal_nr dummy_listr local_n_list dummy_ziplamrrrs r_append_new_solnz&substitution.._append_new_soln~ sO)z: G$Q-!!}3 "&cii&6!7J*/s:*0$1$%$1L$1!$J =I #((9*=>C (d 3DI>3=It['4C0It[/9 406, 4 **,,)#.S &7C  & KD/;+%%/$1s Dcg}g}|D]Z}td|jDr$|j|dk(r|j|J|j|\|s|r||zS|S)Nc3<K|]}t|tywrrr)rFvals rrGz:substitution.._new_order_result.. sISz#x0Ir{r)r}r>rKr)rrfirst_prioritysecond_priorityrs r_new_order_resultz'substitution.._new_order_result st 0CICJJLII773<1$"))#.#**3/  0 _!O3 3 rc i}d}d}t"D]7\}}g}d}|D]!} i} t} | jD]\} } t| trg| j j | | <| | | <| j j jtj}| j\}||f}t| tsJ|j| j}|r|j|dsd} |d}|s)| r%| dd||| ||\}}|r|j| |j |\}}|jt"s|jt"r |t$k(rdi}|D]}d} |||}|dz }t&j(}t|t*r!|j,d!|<|j,d}t|t.rI|j,dt1t2 t2k7r|j,d#|<||j,dz }|r|n|}|dkDr.|t4k(r%t|tt6fs|t%||z }t|t6rP|j<t&j>t&j@fvrt&j(}d}|dz }n |j<}|t&j(ur |||\}}|D]5}|||\}}t|j}|jB| rtEfd| DrM| jG}| jD]<\} } t| tHst|tHs(| j|||| <>||jKvrM||}|j tMdtO|j jPDcgc]}dc}||<n|||<|||||| |\}}|s%|j| 8|r| jS|$|s6|}:|||fS#t8t:f$rYwxYwcc}w)zSolves the system using already known solution (result contains the dict ). solver is :func:`~.solveset_complex` or :func:`~.solveset_real`. rFT)rNrc3&K|]}|v ywrr)rFssrs rrGzBsubstitution.._solve_using_known_values..-s.+-B$J.s)*rrrrrZr(r)rrrNrrTrKrrremoverr?rrrr[rrWrVrrrYr4rrrrrr}rrrrrr*add)$rrrtotal_solvest_calltotal_conditionstr`rrrrr got_symbolr.vrreq2 unsolved_syms delete_resdepen1depen2r not_solvablervsoln_newrrrimgstrrrrrreqs_in_better_orderrs$ @r_solve_using_known_valuesz/substitution.._solve_using_known_values s  ##67D #IE2IJ} ,$&! U IIK8DAq!!X.!"A/0)!,"#'',,"4"4U";"?"?"A"#++&-t_ )!Y7778ggcl))+cggjm&<"'J .s > $0@tZ-y#1?- :& #MM#.!3!3!3]!CJJsOvzz#FFVDI),DI0@ #sJ -y1:- :&#MM#.K%/N("s+gS,U} ,~"ID #J)+<<<}0<!!!Z"=sC!Q, Q*Q' &Q' c3K|]8\}}t|trt|ts|j|:ywr)rintrP)rFrrs rrGzsubstitution..hs8DTQ"1c*z!S/A::a=Ds>Ac |vSrr)rsolved_symbolss rrzsubstitution..|s !>1rFr)rrrrrrrrrzr}rtypegetattrrrrrrrrLr\r>rrfilterrTr))rrrrrrrrmsg old_resulttotal_conditionsettotal_solveset_callrrrnew_result_real solve_call1 cnd_call1new_result_complex solve_call2 cnd_call2filtered_complexjresult_all_variablesresult_infiniterr unsolved_symrsymbtemprrrrrrrrrrs) ``` @@@@@@@@@@r substitutionrp s\n zz&!&1 a  F1I& (C)) w ! 3$w-)A#ABCC 71:{E 22C4 +;WQZ*H$HIJJ JKM 89;@5"n.# (;?1&f Q=Q=f/HM/#+O[)1J$2&. Y 9y01K+56005HB5N#$7EE $ %'o& 'Avvx1668#DSQXXZ-HDD  '  # #A &'/ /FO-  s8c+& & XXZNF1;@AH ( 1 $0L! 1  " "3 ' * * ' ' ,-" / : - >ZZF !)$/0D$00)E$K(() M1s K)ct|d|d}t|trt|Dcgc]}|fc}}|Sttt|Scc}wr)rlrrTr)rrrvr_solns r_solveset_workrsU F1Iwqz *D$ "$/QQD/0 y/000s Acddlm}t|}|jt|||d}g}|D]!}|j |j #ig}t|||g|}|S)Nr)rnrZT)polys)sympy.polys.polytoolsrnrrrrrr) rrrrn_symbolsbasis new_systempoly_eqrs r_handle_positive_dimensionalr$sx.G}H MM&M' UHD 1EJ-'//+,-TF GVRF Mrc t|g|}tj}|D]C}tt t ||t fd|Ds6|t|z }E|S)Nc36K|]}t|ywrr)rFrdict_sym_values rrGz+_handle_zero_dimensional..s=xN+=r)ryrrrxrr\rLrT)rrrr result_updaterr's @r_handle_zero_dimensionalr)sf u /w /FJJM,d3w#456 =f= = Ys^ +M, rcVg}g}g}g}t}d}|D] }|jt||t|tr|j |j z }tt|g|} | r|j|| \} } | s| }t|tr&|jd}|j|ddi}nt|jr|2|j||j|j|j| |||||fS)Nr extensionT)rupdaterwrrrrrvr(rrras_poly is_numberr) rrr polys_exprnonpolys unrad_changedrrorwithout_radicalseq_unradrs r_separate_poly_nonpolyr4s" EJHM5L D LW56 b" "&&B "88    $,MHc b$ ""$Q'B2::w7$7D b\ # #    LL    ldlln - OOB - . *h m CCrc hig}g}g}td|D}|r#|Dcgc]}tt|d}}t||dd}d|vr|}|} || fS|jrc|j d}|r|Dcgc] }t |}} t|g|d di} | D cgc]} tt|| }} |} || fS|}tt||dd} |r| Dcgc] }t |} }|| fScc}wcc}wcc} w#t$r|}t|} Y|| fSwxYwcc}w) Nc3JK|]}|jj ywr)ris_Exact)rFrBs rrGz_handle_poly..s7Aahh'''7s!#T)rationalgrevlexF)orderrrlexstrict) r}ror+rnis_zero_dimensionalfglmrryrxr\r'r) rrno_information no_solutions no_equationsinexactrBr!poly_solpoly_eqsrrs r _handle_polyrEsTNLL777G=BBqiD12BB UG9E BE  Ez d X [  " " 5! (-.1VAY.E. $&uDwDtDF>> from sympy import symbols, nonlinsolve >>> x, y, z = symbols('x, y, z', real=True) >>> nonlinsolve([x*y - 1, 4*x**2 + y**2 - 5], [x, y]) {(-1, -1), (-1/2, -2), (1/2, 2), (1, 1)} 1. Positive dimensional system and complements: >>> from sympy import pprint >>> from sympy.polys.polytools import is_zero_dimensional >>> a, b, c, d = symbols('a, b, c, d', extended_real=True) >>> eq1 = a + b + c + d >>> eq2 = a*b + b*c + c*d + d*a >>> eq3 = a*b*c + b*c*d + c*d*a + d*a*b >>> eq4 = a*b*c*d - 1 >>> system = [eq1, eq2, eq3, eq4] >>> is_zero_dimensional(system) False >>> pprint(nonlinsolve(system, [a, b, c, d]), use_unicode=False) -1 1 1 -1 {(---, -d, -, {d} \ {0}), (-, -d, ---, {d} \ {0})} d d d d >>> nonlinsolve([(x+y)**2 - 4, x + y - 2], [x, y]) {(2 - y, y)} 2. If some of the equations are non-polynomial then `nonlinsolve` will call the ``substitution`` function and return real and complex solutions, if present. >>> from sympy import exp, sin >>> nonlinsolve([exp(x) - sin(y), y**2 - 4], [x, y]) {(ImageSet(Lambda(_n, I*(2*_n*pi + pi) + log(sin(2))), Integers), -2), (ImageSet(Lambda(_n, 2*_n*I*pi + log(sin(2))), Integers), 2)} 3. If system is non-linear polynomial and zero-dimensional then it returns both solution (real and complex solutions, if present) using :func:`~.solve_poly_system`: >>> from sympy import sqrt >>> nonlinsolve([x**2 - 2*y**2 -2, x*y - 2], [x, y]) {(-2, -1), (2, 1), (-sqrt(2)*I, sqrt(2)*I), (sqrt(2)*I, -sqrt(2)*I)} 4. ``nonlinsolve`` can solve some linear (zero or positive dimensional) system (because it uses the :func:`sympy.polys.polytools.groebner` function to get the groebner basis and then uses the ``substitution`` function basis as the new `system`). But it is not recommended to solve linear system using ``nonlinsolve``, because :func:`~.linsolve` is better for general linear systems. >>> nonlinsolve([x + 2*y -z - 3, x - y - 4*z + 9, y + z - 4], [x, y, z]) {(3*z - 5, 4 - z, z)} 5. System having polynomial equations and only real solution is solved using :func:`~.solve_poly_system`: >>> e1 = sqrt(x**2 + y**2) - 10 >>> e2 = sqrt(y**2 + (-x + 10)**2) - 3 >>> nonlinsolve((e1, e2), (x, y)) {(191/20, -3*sqrt(391)/20), (191/20, 3*sqrt(391)/20)} >>> nonlinsolve([x**2 + 2/y - 2, x + y - 3], [x, y]) {(1, 2), (1 - sqrt(5), 2 + sqrt(5)), (1 + sqrt(5), 2 - sqrt(5))} >>> nonlinsolve([x**2 + 2/y - 2, x + y - 3], [y, x]) {(2, 1), (2 - sqrt(5), 1 + sqrt(5)), (2 + sqrt(5), 1 - sqrt(5))} 6. It is better to use symbols instead of trigonometric functions or :class:`~.Function`. For example, replace $\sin(x)$ with a symbol, replace $f(x)$ with a symbol and so on. Get a solution from ``nonlinsolve`` and then use :func:`~.solveset` to get the value of $x$. How nonlinsolve is better than old solver ``_solve_system`` : ============================================================= 1. A positive dimensional system solver: nonlinsolve can return solution for positive dimensional system. It finds the Groebner Basis of the positive dimensional system(calling it as basis) then we can start solving equation(having least number of variable first in the basis) using solveset and substituting that solved solutions into other equation(of basis) to get solution in terms of minimum variables. Here the important thing is how we are substituting the known values and in which equations. 2. Real and complex solutions: nonlinsolve returns both real and complex solution. If all the equations in the system are polynomial then using :func:`~.solve_poly_system` both real and complex solution is returned. If all the equations in the system are not polynomial equation then goes to ``substitution`` method with this polynomial and non polynomial equation(s), to solve for unsolved variables. Here to solve for particular variable solveset_real and solveset_complex is used. For both real and complex solution ``_solve_using_known_values`` is used inside ``substitution`` (``substitution`` will be called when any non-polynomial equation is present). If a solution is valid its general solution is added to the final result. 3. :class:`~.Complement` and :class:`~.Intersection` will be added: nonlinsolve maintains dict for complements and intersections. If solveset find complements or/and intersections with any interval or set during the execution of ``substitution`` function, then complement or/and intersection for that variable is added before returning final solution. rrrc3@K|]}|jywr)rX)rFrrQs rrGznonlinsolve..s =aD!1 =rxrc34K|]}|jywrrrFrs rrGznonlinsolve..s%F"boo%Frc34K|]}|jywrrIrJs rrGznonlinsolve..s&O2r&Orc.tfdDS)Nc3(K|] }| ywrr)rFrrrs rrGz0nonlinsolve....s 9AQ 9s)r)rrrs`rrznonlinsolve..s5 9 99r)rrc3<K|]}t|tywr)rr])rFrs rrGznonlinsolve..s8YPQAs9K8Yr{F)rrrrzrr} IndexErrorrmapr"rx nonlinsolverTrrrr4rErunionrtrrrrxr\r})rrrrvrrr/r0rr1rDrC poly_syms unrad_symsrr remainingto_tuplesubs_resr correct_solsrQs ` @rrQrQ;sXv zz (C))wqz:&!* w w(C))3x)*G-fg>FGT 67+tL!5 =1 ==LMM 6{aCLA-fg.. vw/=E:x}HtH )%9(  # %F%FGI$&O&OPJY&=,4TCx s7SCTT8#I:H #h122 78\Z(I.O 9AG#d3w,-GFG+1FCS8YUX8Y5Y' s;uD FLFc(L9: :OsM*U>HFs$H*!H/3H/H4**H9r)rsympy.core.sympifyr sympy.corerrrrrr r r r sympy.core.containersr sympy.core.functionrrrrrrrsympy.core.modrsympy.core.numbersrrrrsympy.core.intfuncrsympy.core.relationalrrrsympy.core.sortingrrsympy.core.symbolr r!r"sympy.core.traversalr#sympy.external.gmpyr$rr%rsympy.polys.matrices.linsolver&sympy.polys.polyrootsr'rr(r)r*r+sympy.simplifyr,r-sympy.functionsr.r/r0r1r2r3r4r5r6r7r8r9r:r;r<r=%sympy.functions.combinatorial.numbersr>$sympy.functions.elementary.complexesr?r@rArB%sympy.functions.elementary.hyperbolicrCrDrErFrGrHrIrJrKrLrMrNrO(sympy.functions.elementary.miscellaneousrP(sympy.functions.elementary.trigonometricrQsympy.logic.boolalgrRrS sympy.setsrTrUrVrWrXrYrZr[r\sympy.sets.setsr]r^sympy.matricesr_r`rasympy.ntheory.factor_rbsympy.ntheory.residue_ntheoryrcrd sympy.polysrerfrgrhrirjrksympy.polys.polyerrorsrlrrmrnrosympy.polys.solversrprqrrrssympy.solvers.solversrtrurvrwrxsympy.solvers.polysysrysympy.utilitiesrzsympy.utilities.iterablesr{r|r}r~sympy.calculus.utilrrrtypesrrrrrrr|rrrrrr"rrrCrArZr]rf Exceptionrhrmrnrorbrrrrcrrrr r4r8r<r@rHrrlrrrarwr~rrrrrr$r)r4rErQrrrr~s '$$$'KKK66*448<'3D<7KK088888:AAFFFF?J0MMM+44*C3331883%%3&>>NN  Z $N kk['|'mb m`GT=@.6b!'H$>+,++&0/d+*;y;8vaKH>@B&'[[B6J1h64IX\~1hQhXv*6n7b.bV,r7tYxTnAKKt5n(,/ dYB#(XvDPp+-RaH1  !DHYxhr