K i-c dZddlmZddlmZddlmZddlmZm Z ddl m Z m Z m Z ddlmZddlmZdd lmZdd lmZdd lmZdd lmZmZmZdd lmZmZddlm Z m!Z!m"Z"m#Z#m$Z$m%Z%ddl&m'Z'm(Z(m)Z)m*Z*ddl+m,Z,m-Z-ddl.m/Z/ddZ0dZ1dZ2ddZ3y)a1 This module is intended for solving recurrences or, in other words, difference equations. Currently supported are linear, inhomogeneous equations with polynomial or rational coefficients. The solutions are obtained among polynomials, rational functions, hypergeometric terms, or combinations of hypergeometric term which are pairwise dissimilar. ``rsolve_X`` functions were meant as a low level interface for ``rsolve`` which would use Mathematica's syntax. Given a recurrence relation: .. math:: a_{k}(n) y(n+k) + a_{k-1}(n) y(n+k-1) + ... + a_{0}(n) y(n) = f(n) where `k > 0` and `a_{i}(n)` are polynomials in `n`. To use ``rsolve_X`` we need to put all coefficients in to a list ``L`` of `k+1` elements the following way: ``L = [a_{0}(n), ..., a_{k-1}(n), a_{k}(n)]`` where ``L[i]``, for `i=0, \ldots, k`, maps to `a_{i}(n) y(n+i)` (`y(n+i)` is implicit). For example if we would like to compute `m`-th Bernoulli polynomial up to a constant (example was taken from rsolve_poly docstring), then we would use `b(n+1) - b(n) = m n^{m-1}` recurrence, which has solution `b(n) = B_m + C`. Then ``L = [-1, 1]`` and `f(n) = m n^(m-1)` and finally for `m=4`: >>> from sympy import Symbol, bernoulli, rsolve_poly >>> n = Symbol('n', integer=True) >>> rsolve_poly([-1, 1], 4*n**3, n) C0 + n**4 - 2*n**3 + n**2 >>> bernoulli(4, n) n**4 - 2*n**3 + n**2 - 1/30 For the sake of completeness, `f(n)` can be: [1] a polynomial -> rsolve_poly [2] a rational function -> rsolve_ratio [3] a hypergeometric function -> rsolve_hyper ) defaultdict)product)S)RationalI)SymbolWildDummy)Equality)Add)Mul)default_sort_key)sympify)simplify hypersimp hypersimilar)solvesolve_undetermined_coeffs)Polyquogcdlcmroots resultant)binomial factorialFallingFactorialRisingFactorial)Matrix casoratian)numbered_symbolsc ,-./t|}|jsy|j}t|dz }|Dcgc]}t |}}t dg|dzz}t j t jfg|dzz} t|dzD]q} t| |dzD].} || xx|| t| | jzz cc<0|| jrS|| j\\} }|| f| | <s| ddx} }td|dzD]/} | | d| kDr| | d} | | d| z |kDs%| | d| z }1t| t|}} td}t j }t|dzD])} | | d| z |k(s|| | dt|| zz }+tt!||ddj#}|r t%|g}ng}|r || dz gz }n+||jj'|z | dz gz }tt%|}|dkr7|r4|j)dd rt j gfSt j Sy||krg,t j x}}t|dzD]9} ,j+t-d t/| |zz|,| | zzz };t|dzD].} ||| j1|j3| zzz }0t5||z ,}|*,},Dcgc] }||vs| c},|j3|}ny|}||z|zdz}tt!||dd j#}|gk7rt%|dz/nt j /d }d }/fd.i}t| | dzD]} || dz}td| dzD]}||dz || z|z dzz|z ||<t j || <t|dzD]T} t| dzD]A}t|| | z} .|| j1|}!|| xx||| z|!zz cc<CVt7||d}"|rt||D]} ||}#td||zdzD]O}| |z dkrnE|||z j3|| |z } t|D]} |#| xx| |"| |z | fzz cc<Q|| j3|| }$t|D]} |#|  |$z |"| | f<n||}%t||D]} ||}#t j }&td||zdzD]]}| |z dkrnS|||z j3|| |z } t|D]} |#| xx| |"| |z | fzz cc<|&| |%| |z zz }&_|| j3|| }$t|D]} |#|  |$z |"| | f<.|| |z |&z |$z |%| <||||c}'-td|D]*} |'| dz /z | z dzz| z j9|'| <,t|D]B} t;t=|"dd| f|'D#(cgc]\}#}(|#|(zj9c}(}#-| <D|s6t;t=%|'D&(cgc]\}&}(|&|(zj9c}(}&})t|D cgc]} t-d t/| |zzc} ,,-.fd}&|r#t|dz|D cgc] } |&|  }} n,t|dz|D cgc]} |&| .)| z}} |gk7rEt?|g,}|s9|r4|j)dd rt j gfSt j Syi}|rt j }n)},dd}tt=,-D];\}}*||vr|||*z}+,jA|n||*z}+||+j9z }=,|k7r2|jCtEt=,|}|dt,,|j)dd r|,fS|Scc}wcc}wcc}(}#wcc}(}&wcc} wcc} wcc} w)a. Given linear recurrence operator `\operatorname{L}` of order `k` with polynomial coefficients and inhomogeneous equation `\operatorname{L} y = f`, where `f` is a polynomial, we seek for all polynomial solutions over field `K` of characteristic zero. The algorithm performs two basic steps: (1) Compute degree `N` of the general polynomial solution. (2) Find all polynomials of degree `N` or less of `\operatorname{L} y = f`. There are two methods for computing the polynomial solutions. If the degree bound is relatively small, i.e. it's smaller than or equal to the order of the recurrence, then naive method of undetermined coefficients is being used. This gives a system of algebraic equations with `N+1` unknowns. In the other case, the algorithm performs transformation of the initial equation to an equivalent one for which the system of algebraic equations has only `r` indeterminates. This method is quite sophisticated (in comparison with the naive one) and was invented together by Abramov, Bronstein and Petkovsek. It is possible to generalize the algorithm implemented here to the case of linear q-difference and differential equations. Lets say that we would like to compute `m`-th Bernoulli polynomial up to a constant. For this we can use `b(n+1) - b(n) = m n^{m-1}` recurrence, which has solution `b(n) = B_m + C`. For example: >>> from sympy import Symbol, rsolve_poly >>> n = Symbol('n', integer=True) >>> rsolve_poly([-1, 1], 4*n**3, n) C0 + n**4 - 2*n**3 + n**2 References ========== .. [1] S. A. Abramov, M. Bronstein and M. Petkovsek, On polynomial solutions of linear operator equations, in: T. Levelt, ed., Proc. ISSAC '95, ACM Press, New York, 1995, 290-296. .. [2] M. Petkovsek, Hypergeometric solutions of linear recurrences with polynomial coefficients, J. Symbolic Computation, 14 (1992), 243-264. .. [3] M. Petkovsek, H. S. Wilf, D. Zeilberger, A = B, 1996. NrxZc |dk\SNrrs Z/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/sympy/solvers/recurr.pyzrsolve_poly.. AFfilter predicatesymbolsFCc |dk\Sr'r(r)s r+r,zrsolve_poly..s Qr.c*tjg|zSNrZeroks r+ _zero_vectorz!rsolve_poly.._zero_vectorsFF8a< r.c*tjg|zSr6)rOner9s r+ _one_vectorz rsolve_poly.._one_vectorsEE7Q; r.ctj}|j|z}td|dzD]5}|t ||z dz |z}|||j|z|z zz }7|S)Nr#)rr=subsranger)pr:BDians r+_deltazrsolve_poly.._deltas{Aq!a% A1a!e_ .Xa!eai++Q1q519--- .Hr.ct||k(Sr6)int)rEjs r+r,zrsolve_poly..sc!q&kr.c nttDcgc]\}}|||zc}}Scc}}wr6)r zip)rEcqr3QrHs r+r,zrsolve_poly..3s.cs1ayAtq!AfQlNABAs1 )#r is_polynomialis_zerolenrrr8NegativeInfinityrAras_polyLTrJr rlistrkeysmaxdegreegetappendrstras_exprr@rrexpandr rMrremovexreplacedict)0coeffsfrGshifthints homogeneousr*coeffpolystermsrErKexpdbr$ degree_poly nni_rootsNyE solutions_CrNresultAUr;r>alpharr:rCrDVvdenomGgPrBhrOsr3rPrHrFs0 ` @@@@r+ rsolve_polyrEst h  A ??1 ))K F aA*0 1d5!n 1F 1 !QZL!a% Effa(( ) *AE 2E 1q5\$q!a% >A !Hq 8Aq>#9#9!#<= =H >Qx!!HKKMMFSEs|E!H $ !HQKA 1a!e_  8A;?a A 8A;?Q a aA   q63q6qA c A&&K 1q5\> 8A;?a  58A;'71'== =K>U;#"$$(DF,I ^   qb1fX  aiil!!#a'!a 00 CF A1u yyE*|#vv Av Aq1u A HHVC#a%i.01 2 11 A q1u 6A ""$QVVAq1u%55 5A 6.a!eQ:  B6q!9"46AVVI&F  EAIMuQx&((,0  ?I"AA   r1q5! )AAE"A1a!e_ 4Qx1q519q=1!3! 4vvE!H1q5\ )q1u)A AE*AuQx//115A!H!Qq(H ) ) ) 1a1 2 1a[ , Oq!a%!),0A1uqya!e ))!QU3A"1X0!Aa!eQhK/0 0qb q!,q,A teemAadG, ,"QA1a[ 6 OFFq!a%!), &A1uqya!e ))!QU3A"1X0!Aa!eQhK/0Qq1uX%A &qb q!,q,A teemAadG,q!a%(1,5!) 6,1~|A1q! ;Aa!eHA A .q088:AaD ;q FAC!Q$ODDAq!A#DEAaD FQ;Aqslln;1q! $>A> 7a ! IyyE2 !|+ vv I VVFF qTQO !DAqI~aLN aC ahhj F ! Bwc!Rj!12 wAK yyE"{ {2N7FE< < 0>s0b& b+ b+6b0 3b6 "!b< ccc t|}|j|syttt|}t |dz }|||d}}|j |||z j }td}t||j |||z|}|j|s |j\} } t| | |}tt||ddj} | st|||fi|Stjtj g|dzz} } t#t%t'| ddD]}t)||j |||z|}t|||}t||j |||z |}| t+t#|dzDcgc]}|j |||z c}z} t#|dzDcgc]}| j |||z}}t#|dzD];}t)|||||}t||||| |<t||||||<=t#|dzD]!}| |xxt+|d|||dzdzzcc<#t| |t+|z|fi|}|6|j-d d rt/|d| z |dfSt/|| z Sycc}wcc}w) a Given linear recurrence operator `\operatorname{L}` of order `k` with polynomial coefficients and inhomogeneous equation `\operatorname{L} y = f`, where `f` is a polynomial, we seek for all rational solutions over field `K` of characteristic zero. This procedure accepts only polynomials, however if you are interested in solving recurrence with rational coefficients then use ``rsolve`` which will pre-process the given equation and run this procedure with polynomial arguments. The algorithm performs two basic steps: (1) Compute polynomial `v(n)` which can be used as universal denominator of any rational solution of equation `\operatorname{L} y = f`. (2) Construct new linear difference equation by substitution `y(n) = u(n)/v(n)` and solve it for `u(n)` finding all its polynomial solutions. Return ``None`` if none were found. The algorithm implemented here is a revised version of the original Abramov's algorithm, developed in 1989. The new approach is much simpler to implement and has better overall efficiency. This method can be easily adapted to the q-difference equations case. Besides finding rational solutions alone, this functions is an important part of Hyper algorithm where it is used to find a particular solution for the inhomogeneous part of a recurrence. Examples ======== >>> from sympy.abc import x >>> from sympy.solvers.recurr import rsolve_ratio >>> rsolve_ratio([-2*x**3 + x**2 + 2*x - 1, 2*x**3 + x**2 - 6*x, ... - 2*x**3 - 11*x**2 - 18*x - 9, 2*x**3 + 13*x**2 + 22*x + 8], 0, x) C0*(2*x - 3)/(2*(x**2 - 1)) References ========== .. [1] S. A. Abramov, Rational solutions of linear difference and q-difference equations with polynomial coefficients, in: T. Levelt, ed., Proc. ISSAC '95, ACM Press, New York, 1995, 285-289 See Also ======== rsolve_hyper Nr#rrr%c |dk\Sr'r(r)s r+r,zrsolve_ratio..r-r.r/r2F)rrQrWmaprSr@r_r ras_numer_denomrrrXrrr=r8rArJrYrr r[r)rcrdrGrfr*rvrCrresrBrOror3numersrErlrKdenomsr}rus r+ rsolve_ratiorbsj  A ??1  #gv& 'F F aA !9fQiqA q!a%!A c A AqvvaQ' +C   Q !!#1!QlU3#"$$(DF,I 61a1511EEAFF8QU+6s3y>*B3 @AAqvvaQ'+AAq! AAqvvaQ'+A q1u>AqvvaQ'>? ?A  @-2!a%L9q!&&AE"99q1u -AF1Ivay!,AF1Iq!,F1IF1Iq!,F1I  - q1u =A 1IvbqzF1q56N:< >> from sympy.solvers import rsolve_hyper >>> from sympy.abc import x >>> rsolve_hyper([-1, -1, 1], 0, x) C0*(1/2 - sqrt(5)/2)**x + C1*(1/2 + sqrt(5)/2)**x >>> rsolve_hyper([-1, 1], 1 + x, x) C0 + x*(x + 1)/2 References ========== .. [1] M. Petkovsek, Hypergeometric solutions of linear recurrences with polynomial coefficients, J. Symbolic Computation, 14 (1992), 243-264. .. [2] M. Petkovsek, H. S. Wilf, D. Zeilberger, A = B, 1996. r#NTr2rr%r3F)zero)keyr2)4rWrrrSsetrRis_Addr_argsis_hypergeometricrXrrr8items enumerater=rrAr@rr rrMrr rr r is_integerrr\rUrZrYnthr^rr]collectrhhasrrrrrr sortrr!r[)-rcrdrGrfr*kernelr2similarr}r inhomogeneousrErhrirrrKrBrORsymsrur% p_factors q_factorsfactorsrvrCdegreesrDrFrmpolyrlz recurr_coeffssolr3ration0n_rootKskkerr:s- r+ rsolve_hyperrsIn#gv& 'F AVq"cewvA 99 88GXXZ__ (**1- (A#Aq!, a ( "#GAJ (07}}?tq!QU?M?   #CMm," &DAq55&)5EeeWa!e_F!QA1a!e_ 1q519--++-1aA q  1q5\ @aC&!*va!ef~"=?? @ UCL!TBA}4s4!SY78AsF|Q7a A% -(Ff%FE" &H c A !9fQinnQA 2qAU1a[%%'(IU1a[%%'(Iquu~G , ,A|| aQUAEN++  ,,"++A!a%+A!*+A!%%Q+A'kAoG8%1Rw affQA " "q1u 2Aa91affQA&9:Aa <1affQA&<=Avay{1}a+D LLa )<<uQx01 2 'lAFFtAq1u %A!HLLOEAFF"1 $  % tQ$$& %Ayy>CAElKU1X--/14KMKAv!sq!a%$QA]1%5a%7$QRRcCG $5567' q!S\SWX Tkk$'-12syy|22 %Aq!a% 0014q8 #E$8$8$:1$=qAFFH(Fzz!}# +4#aZ ( EAr1q5>255$4oF  AfslAE:a?MM!$# % %38%t KK$K% c"3'0 1B3!c' yyE""%$!QA%%W && M@x ,+:<.L$Q3:&s6#]&?],"]1]6 ]; . ^,^^  ^Nc  t|tr|j|jz }|jdt df}|j j|jt dd}tt}g}tj|D]}|j|j\}}|s|j|5|D]} | jr]| j|jk(rD| jdj!|z} | !|t#| |j|lt%d|jd d | d|D]}t||||<d |_t|}|j)D]\}}t+|||<t,j.} |j0sW|j3sF|j4r,t7fd |j jDst%d |z|j9D]Q}|j;r1|j=r&t?| |jAd} Et%d|z|jA\} } | j=r t?| | } | t,j.urN|j)D]+\}}|jA\}}|tC| |z||<-| tC| | z}tE|jG}|dkrtI|}td}|jK|zj }| jK|zj } |j)D].\}}|jK|zj |||z<0n|}tM|jG}tO|dzDcgc]}|| }}tQ|| d} | y| \}}|igfvrd}|r|t|tr%tOtS|Dcic]}||| }}g}|j)D]k\}} t#|}|jK||z }|jWt,jXr|j[||z }|j|mt]|g|} | sy|jK| }|Scc}wcc}w#tT$rO|jr2|j|jk(rt#|jd}nt%d|zYwxYw)a Solve univariate recurrence with rational coefficients. Given `k`-th order linear recurrence `\operatorname{L} y = f`, or equivalently: .. math:: a_{k}(n) y(n+k) + a_{k-1}(n) y(n+k-1) + \cdots + a_{0}(n) y(n) = f(n) where `a_{i}(n)`, for `i=0, \ldots, k`, are polynomials or rational functions in `n`, and `f` is a hypergeometric function or a sum of a fixed number of pairwise dissimilar hypergeometric terms in `n`, finds all solutions or returns ``None``, if none were found. Initial conditions can be given as a dictionary in two forms: (1) ``{ n_0 : v_0, n_1 : v_1, ..., n_m : v_m}`` (2) ``{y(n_0) : v_0, y(n_1) : v_1, ..., y(n_m) : v_m}`` or as a list ``L`` of values: ``L = [v_0, v_1, ..., v_m]`` where ``L[i] = v_i``, for `i=0, \ldots, m`, maps to `y(n_i)`. Examples ======== Lets consider the following recurrence: .. math:: (n - 1) y(n + 2) - (n^2 + 3 n - 2) y(n + 1) + 2 n (n + 1) y(n) = 0 >>> from sympy import Function, rsolve >>> from sympy.abc import n >>> y = Function('y') >>> f = (n - 1)*y(n + 2) - (n**2 + 3*n - 2)*y(n + 1) + 2*n*(n + 1)*y(n) >>> rsolve(f, y(n)) 2**n*C0 + C1*factorial(n) >>> rsolve(f, y(n), {y(0):0, y(1):3}) 3*2**n - 3*factorial(n) See Also ======== rsolve_poly, rsolve_ratio, rsolve_hyper rr:)excludemT)integerN'(z + k)' expected, got 'cyr'r(r(r.r+r,zrsolve..sr.c3@K|]}|jywr6)r).0r$rGs r+ zrsolve..s"Xa1#6#6q#9"XszJThe independent term should be a sum of hypergeometric functions, got '%s'r#z2Polynomial or rational function expected, got '%s'c"tjSr6r7r(r.r+r,zrsolve..s QVVr.rz"Integer or term expected, got '%s')/ isinstancer lhsrhsrr r_rfuncrrWr make_args as_coeff_mulr\ is_FunctionmatchrJ ValueErrordefault_factoryrrrr=rRrrallvaluesis_rational_functionrQrrrminrXabsr@rYrArrS TypeErrorrNaNlimitr)rdrqinitr:h_parti_partr}rhdeprrucommoni_numeri_denomnumerr{K_minrH_partK_maxrErcsolutionr2 equationsrzeqrGs @r+rsolversh!X EEAEEM q A S1$A  166$sD"9:;A  F F ]]1  D^^AFF+ s MM%  DA}}166!1Q/%3vay>*11%856VVQBD D  D D$Oq $&F &\FLLN$5UOq $UUF >>&":":1"= MMc"X6==?CWCW"XYehnnooN  % %a (&&q)VU%9%9%;A%>BDuLN N N,,.GWQVWa( QUU  4HAu //1LE5c&%33F1I 4VWa00  E qy J^,QA&--/QA&--/  :HAu!JJq!a%0779F1q5M :  E!&uqy!1 2AfQi 2F 2 &6'1d ;F ~Hg Bx4# dD !(-c$i(891AtAwJ9D9 JJL !DAq OFq!$q(Bvvaee}^^Aq)A-   R  !y+7+}}V,H OO3: O==QVVqvv%5AFF1IA$%IA%MNN Os T T TAU21U2)rr6)4__doc__ collectionsrsympy.concretersympy.core.singletonrsympy.core.numbersrrsympy.core.symbolrr r sympy.core.relationalr sympy.core.addr sympy.core.mulr sympy.core.sortingrsympy.core.sympifyrsympy.simplifyrrr sympy.solversrr sympy.polysrrrrrrsympy.functionsrrrrsympy.matricesrr sympy.utilities.iterablesr!rrrrr(r.r+rsd/`$""*11*/&<<:==RR-6Zzl^Rjer.