K i5HddlmZmZmZmZmZddlmZmZddl m Z ddl m Z ddl mZmZmZddlmZmZddlmZmZdZd ZGd d eZy ) )FunctionSMulPowAdd)ordereddefault_sort_key) expand_func)Dummy)gammasqrtsin)factorcancel)siftuniqc|jt}|jt}|Dchc]}t |ts|}}|s|S||z}||j jtz}|rt t|Dcgc]?}t||j|jDcgc]}t|dc}fAc}}\}}}|jtt ||} t| djtt ||St|dScc}wcc}wcc}}w)a  Simplify expressions with gamma functions. Explanation =========== This function takes as input an expression containing gamma functions or functions that can be rewritten in terms of gamma functions and tries to minimize the number of those functions and reduce the size of their arguments. The algorithm works by rewriting all gamma functions as expressions involving rising factorials (Pochhammer symbols) and applies recurrence relations and other transformations applicable to rising factorials, to reduce their arguments, possibly letting the resulting rising factorial to cancel. Rising factorials with the second argument being an integer are expanded into polynomial forms and finally all other rising factorial are rewritten in terms of gamma functions. Then the following two steps are performed. 1. Reduce the number of gammas by applying the reflection theorem gamma(x)*gamma(1-x) == pi/sin(pi*x). 2. Reduce the number of gammas by applying the multiplication theorem gamma(x)*gamma(x+1/n)*...*gamma(x+(n-1)/n) == C*gamma(n*x). It then reduces the number of prefactors by absorbing them into gammas where possible and expands gammas with rational argument. All transformation rules can be found (or were derived from) here: .. [1] https://functions.wolfram.com/GammaBetaErf/Pochhammer/17/01/02/ .. [2] https://functions.wolfram.com/GammaBetaErf/Pochhammer/27/01/0005/ Examples ======== >>> from sympy.simplify import gammasimp >>> from sympy import gamma, Symbol >>> from sympy.abc import x >>> n = Symbol('n', integer = True) >>> gammasimp(gamma(x)/gamma(x - 3)) (x - 3)*(x - 2)*(x - 1) >>> gammasimp(gamma(n + 3)) gamma(n + 3) F)as_comb)rewriter atomsr isinstanceas_dummyziprr funcargs _gammasimpxreplacedict) exprfigammasfiadumfunsimpds ^/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/sympy/simplify/gammasimp.py gammasimpr* s,d << D 8A 3AjE2a 3F 3  KA DMMO ! !( ++Aaj"Wb'"''68gg$?12 1e,$?@ A"#S$ MM$s3}- .!U+44T#c4.5IJJ dE **4$?"s#D<D<)E 8E E E c|jtd}r|jtd}n|jtd}dfd t|}|}||k7r t|}|jtd}|S)a; Helper function for gammasimp and combsimp. Explanation =========== Simplifies expressions written in terms of gamma function. If as_comb is True, it tries to preserve integer arguments. See docstring of gammasimp for more information. This was part of combsimp() in combsimp.py. c<td|dz jSN)_rfexpandns r)z_gammasimp..as#a!a%)*ct|dzSr-r r$bs r)r3z_gammasimp..esq1ur4c6t||zt|z SNr6r7s r)r3z_gammasimp..hsq1ueAh.r4c  ()*+,-|jr|Sd}+fd+|dk(r6|j|jDcgc]}/||dzc}}|dz }|js|S|dk(rS|j \}}|s|S|r5/t j ||dzt j |zS|dz }|dk(r;t|j+d\}}t |}t |} | j\} } tdD]} ttt j| }t|D]r\} }|jst|jDcgc]}/||| z |dzc}j\}} ||| <| j!t"rrnt |} | dk(r +| sn| | } } || z| z }|jr+| s +| s|S|dz }|dk(r |}/|d }||k(r|Sg}g}g}g}d }tt|j}|r|j%j\}} ||\}}|r|j'|n|d ur|j'||| \}}|r|j'|n|d ur|j'||r.su|||f|||ffD]*\}}}g}|r|j%**j(r|j+*1t|D]\} }*|zdz }|j,s|j+t.j0|j+t3t.j0*z|j%| |dkDr$|j'*fd t|Dn)|dkr$|j'*fd t| Dn|j+*|r||dd-||||f||||ffD]\}} }!}" |D]!}| D]-|d-zz }|j,sn!n1|j5|| j5-|dkDr$|!j'-fdt|Dn)|dkr$|"j'-fdt| D|j+-t.j6z|!j+dd-zdz z|"j+t9t.j0d((fd}#|||f|||ffD]\}}}|#||||dk\r),fd}$i,,fd)),fd}%||z|z|zD] }|%| |||f|||ffD]\}}}g}|r|j%}&d}'|'rd }'|$||&--<|j5--|&k7r|j+-|&z |%-|&z |&dz }&d}'|$||&dz --E|j5--|&dz k7r%|j+|&dz -z |%|&dz -z |&dz}&d}'|'r|j+|&|r||ddt |D&cgc] }&t#|&c}&t |D&cgc] }&t#|&c}&z t |zt |z Scc}wcc}wcc}&wcc}&w)z/ Simplify products of gamma functions further. c|jt}|jtd}|jt|kr|}|S)Ncftd|dz jjtdS)Nr.c6t||zt|z Sr:r6r7s r)r3zU_gammasimp..rule_gamma..gamma_rat....tsE!a%Lq,Ar4)r/r0replacer1s r)r3zC_gammasimp..rule_gamma..gamma_rat..ss*CAE>>3C-'#ABr4)countr r?)xwasxxs r) gamma_ratz1_gammasimp..rule_gamma..gamma_ratps@''%.C5#CDBxx$Hr4c(t|try|js |jrt fd|j DS|j r>|jjs|jjr|jSy)NTc3.K|] }|ywr:).0xi gamma_factors r) zG_gammasimp..rule_gamma..gamma_factor..~s=<+=F) rr is_Addis_Mulanyris_Powexp is_integerbase is_positive)rArJs r)rJz4_gammasimp..rule_gamma..gamma_factorysc!U#xx188=aff===xxQUU--1C1C#AFF++r4rr.T)binaryc|tjurdgfS|j\}}|jr-t |t rd|j dg|zfSd|g|zfSd|gfS)NTrF)rOne as_base_exp is_Integerrr r)pr8es r) explicatez1_gammasimp..rule_gamma..explicateskAEEzRx==?DAq||a'!&&)Q.. 1#a%<'qcz!r4Fc3.K|] }dz |zyw)r.NrGrHkg1s r)rKz1_gammasimp..rule_gamma..s(FR!(FrLc3*K|] } |z  ywr:rGras r)rKz1_gammasimp..rule_gamma..s(DQ"q(DsNc3.K|] }dz|zyw)rUNrGrHrbys r)rKz1_gammasimp..rule_gamma.. s!.rule_gamma.. s!A!!A#'A+!Asctt|}tt|D]}t|dzt|Dcgc]}||||z dz|f}}|D]\}}|jdk(s|j dk7s&|j }|g}ttd|}|D]B\} }|| z} | j s| |vs|j| |j||rBnt|D] \}}||} |j| | ||<"|j |d|ddfccSycc}w)Nr.r) listrrangelenr]qr\removeappend enumerate) coeffsur!jdjoner2gotgetr(mcs r)_runz,_gammasimp..rule_gamma.._run"sHf&s1v:A;@QA;OPaQqTAaD[A-q1PBP"$:Q55A:#%%1* #A#$#C"&uQ{"3C(*)1$%aC#$<.rule_gamma.._mult_thm<s 9A ~~/HAuOOE2.55a89 d(89!DE#DK0FC"6l;!(+ 2u"'6A"'!)a-C%*3q2v;%76 % S1W 566  n af!a% %;%&#%6&78 3387="=519"="CDK?DD!%Ee$A%q #>s E c`|sy |\}}|D]} |\}}||k7s+|j|s|tk7s |tk7r.rule_gamma..find_fuzzy{s#AB !A VFBRx(;%'35[B#%K F1Q3K445AANN+AANN+AAv1q5AE  !r4c|vr|S|j|jtj|jtDchc]}|j c}fScc}wr:)rrrunionrrQ)rr^rs r)rz2_gammasimp..rule_gamma..compute_STsZ3;t9$))4::h+?+E+E(, 3818,:;;8s A& c||<yr:rG)rrrs r) update_STz1_gammasimp..rule_gamma..update_STs&t,D r4)is_AtomrrrNargs_cncr _from_argsras_numer_denomrkrjr make_argsrprMrhasr popextendrRror\rrrrnrr )0rlevelrDrArncTF gamma_indr(ndddipassr!nir$rB numer_gammas denom_gammas numer_others denom_othersr_newargsr2isgrr"rrrg2ngdgnodorrrrcontrzrrcrJrrgr rule_gammas0 @@@@@@r)rz_gammasimp..rule_gammajs$ <<K   A:499KAz!UQY7KLD QJE{{K A:}}HD" !#.."6 B3>>RTCUUU QJE A: <=DAqQIQA%%'FBq GCMM"$567&t_"EAryy!$LNGG'UGHJy2 B'U",n.B#%Q!vve}!"$ZQ;|B'7RB R<?DKK\"%5b9I QJE A:!$*3;K       "wtyy)*;;=//1DAqq\FC##A&##A&q\FC##A&##A&lL*:!<>)@ $uB}} 2 !*6!2 '2GaK ||$ QTT* Sb\2 1 q5!LL(FU1X(FFU!LL(D%)(DD ' 2%( q 1 >%1, $0$2$0, $0$2#3 *BB  !#%A !AaCA || %% % IIaLIIaL1u !<58!<<Q !AuaRy!AAIIa!&&j)IIa!A#'l+IId144j)'  *T :42 h&2<$N%1<$N$P +5%!UE* + A:  !0C ;  -$|3lB\Q $ lL*:!<>)@ $u AD$&ua0=!LLO Av % QqS 1 )!A#FA#'D&ua!e4=!LLO AEz % a!eQY 7 )1q5!) 4FA#'D#$JJqM+. q 7 >|4!U1X45l3E!H345< !#& #56 6u L4'U@ 53sZ-)Z2 %Z7Z< cX|jrtt|St|Sr:) is_Rationalr r r1s r)r3z_gammasimp..s1==+eAh'eAhr4)r)r?r r/r)rrrBrs ` @r)rrTs <<* ,D||C %'||C .0W6r ,C c?D s{d| <<F HD Kr4ceZdZedZy)r/c|jrt|stjSt|}|dkDr"t t |Dcgc]}||z c}S|dkr*dt t d| dzDcgc]}||z  c}z Sy|j re|j\}}|jrF|dkDrt||t||z|zS|dkr t||t||z|z| z S|j r|j\}}|jre|dkDr)t||t||z|zt||z S|dkr1t||t||z| zt||z|z| z Syyycc}wcc}w)Nrr.) r\rrZrrrkrMr}r/)clsr$r8r2r!ry_b_as r)evalz_rf.evals <<uu AA1uE!H5qQU566QeArAv.>?q1u?@@@xx(2<<1u"1bz#a"fa.88Q"1bz#a"fqj1"*===xx(2<<1u"2qz#b1fa.8RCCQ"2qz#b1fqb/9#b1fqj1":MMM 6?s  F. F N)__name__ __module__ __qualname__ classmethodrrGr4r)r/r/sNNr4r/N) sympy.corerrrrrsympy.core.sortingrr sympy.core.functionr sympy.core.symbolr sympy.functionsr r r sympy.polysrrsympy.utilities.iterablesrrr*rr/rGr4r)rs<118+#,,&0G+Txv N(Nr4