K iA- &dZddlmZddlmZddlmZddlmZddl m Z m Z ddl m Z mZddlmZmZmZdd lmZmZdd lmZmZmZmZdd lmZdd lmZdd lm Z ddl!m"Z"m#Z#ddl$m%Z%m&Z&ddl'm(Z(ddl)m*Z*ddl+m,Z,GddZ-Gdde-Z.dZ/e.ddZ0eddgZ1eddgZ2edZ3ed Z4ed!d"gZ5e.ee4e4z ee4Z6e.ee5e4ze4z e5ee5e4zzZ7e6e7fZ8e.e3e e4ze d#z e3ee4zd$%Z9e.e d#ee4ze e4Z:e.d&d'Z;Gd(d)e.Z<eee?fZIy1)2a Classes and functions useful for rewriting expressions for optimized code generation. Some languages (or standards thereof), e.g. C99, offer specialized math functions for better performance and/or precision. Using the ``optimize`` function in this module, together with a collection of rules (represented as instances of ``Optimization``), one can rewrite the expressions for this purpose:: >>> from sympy import Symbol, exp, log >>> from sympy.codegen.rewriting import optimize, optims_c99 >>> x = Symbol('x') >>> optimize(3*exp(2*x) - 3, optims_c99) 3*expm1(2*x) >>> optimize(exp(2*x) - 1 - exp(-33), optims_c99) expm1(2*x) - exp(-33) >>> optimize(log(3*x + 3), optims_c99) log1p(x) + log(3) >>> optimize(log(2*x + 3), optims_c99) log(2*x + 3) The ``optims_c99`` imported above is tuple containing the following instances (which may be imported from ``sympy.codegen.rewriting``): - ``expm1_opt`` - ``log1p_opt`` - ``exp2_opt`` - ``log2_opt`` - ``log2const_opt`` ) expand_log)S)Wild)sign)explog)MaxMin)cossinsinc)Qask)log1plog2exp2expm1) MatrixSolve)UnevaluatedExpr)Pow) logaddexp logaddexp2)cosm1powm1)Mul) MatrixSymbol)siftceZdZdZddZdZy) Optimizationz Abstract base class for rewriting optimization. Subclasses should implement ``__call__`` taking an expression as argument. Parameters ========== cost_function : callable returning number priority : number Nc ||_||_yN) cost_functionpriority)selfr"r#s ]/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/sympy/codegen/rewriting.py__init__zOptimization.__init__@s* c0t||jS)N)key)minr")r$argss r%cheapestzOptimization.cheapestDs4T//00r')N)__name__ __module__ __qualname____doc__r&r,r'r%rr4s 1r'rc(eZdZdZfdZdZxZS) ReplaceOptima Rewriting optimization calling replace on expressions. Explanation =========== The instance can be used as a function on expressions for which it will apply the ``replace`` method (see :meth:`sympy.core.basic.Basic.replace`). Parameters ========== query : First argument passed to replace. value : Second argument passed to replace. Examples ======== >>> from sympy import Symbol >>> from sympy.codegen.rewriting import ReplaceOptim >>> from sympy.codegen.cfunctions import exp2 >>> x = Symbol('x') >>> exp2_opt = ReplaceOptim(lambda p: p.is_Pow and p.base == 2, ... lambda p: exp2(p.exp)) >>> exp2_opt(2**x) exp2(x) c @t|di|||_||_y)Nr2)superr&queryvalue)r$r7r8kwargs __class__s r%r&zReplaceOptim.__init__hs! "6"  r'cN|j|j|jSr!)replacer7r8)r$exprs r%__call__zReplaceOptim.__call__ms||DJJ 33r')r.r/r0r1r&r> __classcell__r:s@r%r4r4Hs> 4r'r4ct|ddD]+}||}|j|}|j||}-|S)a Apply optimizations to an expression. Parameters ========== expr : expression optimizations : iterable of ``Optimization`` instances The optimizations will be sorted with respect to ``priority`` (highest first). Examples ======== >>> from sympy import log, Symbol >>> from sympy.codegen.rewriting import optims_c99, optimize >>> x = Symbol('x') >>> optimize(log(x+3)/log(2) + log(x**2 + 1), optims_c99) log1p(x**2) + log2(x + 3) c|jSr!)r#)opts r%zoptimize..s s||r'T)r)reverse)sortedr"r,)r= optimizationsoptimnew_exprs r%optimizerJqsN* +CTR2;    &D>>$1D 2 Kr'c<|jxr|jdk(S)N)is_Powbaseps r%rDrDsahh&166Q;r'c,t|jSr!)rrrOs r%rDrDsd155kr'dc|jSr!)is_Dummyxs r%rDrDs QZZr') propertiesuc:|j xr |j Sr!) is_numberis_AddrUs r%rDrDs_%EQXXr'vwnc|jSr!rZrUs r%rDrDs Q[[r'rLc&|jdS)Nc|jxr|jjxs2t|tt fxr|j dj SNr)rMr is_negative isinstancerrr+rZes r%rDz..sG &QUU&& D q3+ & Bqvvay/B/B+Br')count)r=s r%rDrDsSWS]S]ETr'r"ct|txrk|jdjxrPt |jdjdk(xr)t d|jdjDS)NrrLc3<K|]}t|tywr!)rer).0ts r% z..sBaz!S)Bs)rerr+r[lenallls r%rDrDshz!S!C66!9##Cqvvay~~&!+CB166!9>>BBr'c $t|jdjDcgc]}|jdc}ttt |jdjDcgc]}|jdc}zScc}wcc}wrc)r r+rrr )rrrgs r%rDrDsj  0AaffQi 01 c#166!9>>:aq :;<= > 0:s B$B c:eZdZdZdfd ZdZdZfdZxZS)FuncMinusOneOptimaSpecialization of ReplaceOptim for functions evaluating "f(x) - 1". Explanation =========== Numerical functions which go toward one as x go toward zero is often best implemented by a dedicated function in order to avoid catastrophic cancellation. One such example is ``expm1(x)`` in the C standard library which evaluates ``exp(x) - 1``. Such functions preserves many more significant digits when its argument is much smaller than one, compared to subtracting one afterwards. Parameters ========== func : The function which is subtracted by one. func_m_1 : The specialized function evaluating ``func(x) - 1``. opportunistic : bool When ``True``, apply the transformation as long as the magnitude of the remaining number terms decreases. When ``False``, only apply the transformation if it completely eliminates the number term. Examples ======== >>> from sympy import symbols, exp >>> from sympy.codegen.rewriting import FuncMinusOneOptim >>> from sympy.codegen.cfunctions import expm1 >>> x, y = symbols('x y') >>> expm1_opt = FuncMinusOneOptim(exp, expm1) >>> expm1_opt(exp(x) + 2*exp(5*y) - 3) expm1(x) + 2*expm1(5*y) czdt|d|jfd||_|_||_y)N c|jSr!)r[rfs r%rDz,FuncMinusOneOptim.__init__..s 188r'cN|j|jzz Sr!) count_opsrh)r=func_m_1weights r%rDz,FuncMinusOneOptim.__init__..s"DNN4DvdjjYaNbGb4br'ri)r6r&replace_in_Addfuncr{ opportunistic)r$r~r{rr|r:s ` @r%r&zFuncMinusOneOptim.__init__s? +T-@-@'b  d   *r'ct|jdd\}}t|}t|fdd\}}|||fS)Nc|jSr!r`args r%rDz4FuncMinusOneOptim._group_Add_terms..s cmmr'Tbinaryc:|jjSr!)hasr~rr$s r%rDz4FuncMinusOneOptim._group_Add_terms..s377499;Mr')rr+sum)r$addnumbersnon_numnumsumterms_with_funcothers` r%_group_Add_termsz"FuncMinusOneOptim._group_Add_termssF*CDQW!%g/MVZ![--r'cj|\}}}|dk(r|Sgg}}|D]}|jrHt|jfdd\}} t |dk(rt | dk(r |d| d} }n1d} n.|j j k(r|t j} }nd} | | jr{t| t| k(rcjrt| |zt|k} n| |zdk(} | r2|| z }|j| jjz|j|"|j |g|||S)z1 passed as second argument to Basic.replace(...) rc6|jjk(Sr!)r~rs r%rDz2FuncMinusOneOptim.replace_in_Add..ssxx499?Tr'Trr-N)ris_Mulrr+ror~rOnerZrrabsappendr{) r$rgrrother_non_num_terms substituted untouched with_funcr~coeff do_substitutes ` r%r}z FuncMinusOneOptim.replace_in_AddsZ7;7L7LQ7O4!4 Q;H!#RY ( (I"9>>3T]ab et9>c%jAo"&q'58%D E499,'e U__ef 9U%%$'f $5F $CM$)&LA$5M eOF&&u]T]]DII-F'FG   Y '- (0qvvfM{MYM9LMMr'ct||}t||j}|j||Sr!)r6r>factorr,)r$r=alt1alt2r:s r%r>zFuncMinusOneOptim.__call__ s8w%w .}}T4((r')T) r.r/r0r1r&rr}r>r?r@s@r%rurus$$L+. N@))r'ruc"t|tSr!)rerrfs r%rDrDs jC r'ct|jtdjttdzt tS)Nc4t|jSr!)rrrs r%rDz..sSZZ\*r'r-)rr<r_urrqs r%rDrDs7j *ws2a4y%)$r'c|jSr!) is_symbol)bs r%rDrDs  r')base_reqc(tfddS)a Creates an instance of :class:`ReplaceOptim` for expanding ``Pow``. Explanation =========== The requirements for expansions are that the base needs to be a symbol and the exponent needs to be an Integer (and be less than or equal to ``limit``). Parameters ========== limit : int The highest power which is expanded into multiplication. base_req : function returning bool Requirement on base for expansion to happen, default is to return the ``is_symbol`` attribute of the base. Examples ======== >>> from sympy import Symbol, sin >>> from sympy.codegen.rewriting import create_expand_pow_optimization >>> x = Symbol('x') >>> expand_opt = create_expand_pow_optimization(3) >>> expand_opt(x**5 + x**3) x**5 + x*x*x >>> expand_opt(x**5 + x**3 + sin(x)**3) x**5 + sin(x)**3 + x*x*x >>> opt2 = create_expand_pow_optimization(3, base_req=lambda b: not b.is_Function) >>> opt2((x+1)**2 + sin(x)**2) sin(x)**2 + (x + 1)*(x + 1) c|jxrD|jxr0|jjxrt |jkSr!)rMrNr is_Integerr)rgrlimits r%rDz0create_expand_pow_optimization..Bs;!((\x/\AEE4D4D\QUUW\I\r'c|jdkDr-tt|jg|jzddiSdtt|jg|j zddiz S)NrevaluateFr-)rrrrNrOs r%rDz0create_expand_pow_optimization..Cs`HIPQ OC166(AEE6/CUC D ocQVVHaeeVOEuEF Fr')r4)rrs``r%create_expand_pow_optimizationrsF \   r'c@|jrt|jdk(rz|j\}}|jr_|jddk(rM|j }t |tr1tttj|j Sy)NrLr-F) is_MatMulror+ is_Inverseshaperrerboolrrfullrankr=leftrightinv_args r%_matinv_predicaterIsn ~~#dii.A-ii e ??u{{1~2hhG'<0C 488 4566 r'cP|j\}}|j}t||Sr!)r+rrrs r%_matinv_transformrTs%))KD%hhG w &&r'N)Jr1sympy.core.functionrsympy.core.singletonrsympy.core.symbolr$sympy.functions.elementary.complexesr&sympy.functions.elementary.exponentialrr(sympy.functions.elementary.miscellaneousr r (sympy.functions.elementary.trigonometricr r r sympy.assumptionsrrsympy.codegen.cfunctionsrrrrsympy.codegen.matrix_nodesrsympy.core.exprrsympy.core.powerrsympy.codegen.numpy_nodesrrsympy.codegen.scipy_nodesrrsympy.core.mulr"sympy.matrices.expressions.matexprrsympy.utilities.iterablesrrr4rJexp2_opt_dr_v_w_n sinc_opt1 sinc_opt2 sinc_optslog2_opt log2const_optlogsumexp_2terms_optru expm1_opt cosm1_opt powm1_opt log1p_optrrr matinv_opt logaddexp_optlogaddexp2_opt optims_c99 optims_numpy optims_scipyr2r'r%rs_@+""5=?EE$==2+ ;2;*11(&4<&4R< &   #/01 #EFG #Y #Y #012 GBJR   2JrM2d2b5k>   " 3r7 3q6)2d2h;G SVDH_c"g6 #D X) X)v c5 ) c5 ) c5 )  %  7L( V ' +-> ? SRR19R3DE c#a*SBZ"78*R:LSQRV:STHh F ]N<