K iBD\dZddlmZmZddlmZmZddlmZddl m Z m Z ddl m Z mZddlmZddlmZdd lmZdd lmZdd lmZdd lmZdd lmZddlmZedZ eede dfdZ!eddZ"ee dfdZ#ee ddgdfdZ$eddZ%y)zAVarious algorithms for helping identifying numbers and sequences.)Productproduct)FunctionS)Add)IntegerRational)Symbolsymbols)sympify)exp)floor) integrate)rational_interpolate)lcm)denom)publicc f dg}dg}dtdz c }t||kr dk(rw dz tk(r[d}|D]}t|t|}|d|zdkr| }tt|D]}t |||z||<|S dk(rwt j z }|g t dztD]5} jt fdt |D |z7 dgtt| t|zzc t|D] \}}||z |<t|D]\}} | zxx|z cc< ddk(r j ddk(r| dc}} t||krdgS)a This function is used internally by other functions from the sympy.concrete.guess module. While most users may want to rather use the function find_simple_recurrence when looking for recurrence relations among rational numbers, the current function may still be useful when some post-processing has to be done. Explanation =========== The function returns a vector of length n when a recurrence relation of order n is detected in the sequence of rational numbers v. If the returned vector has a length 1, then the returned value is always the list [0], which means that no relation has been found. While the functions is intended to be used with rational numbers, it should work for other kinds of real numbers except for some cases involving quadratic numbers; for that reason it should be used with some caution when the argument is not a list of rational numbers. Examples ======== >>> from sympy.concrete.guess import find_simple_recurrence_vector >>> from sympy import fibonacci >>> find_simple_recurrence_vector([fibonacci(k) for k in range(12)]) [1, -1, -1] See Also ======== See the function sympy.concrete.guess.find_simple_recurrence which is more user-friendly. rc3FK|]}|dz|z dz zywrN).0jblms Z/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/sympy/concrete/guess.py z0find_simple_recurrence_vector..Js)?a!AaC&1Q3q5/?s!) lenrrrangeintrOneappendsummax enumeratepop) rq1q2zcxkaqrrs ` @@rfind_simple_recurrence_vectorr2sL B B c!fkDAq b'Q,dAg FACF{)AAuQx(A)a57Q;QBs2w)A1aLBqE) dAg EE!A$J CqsCF# CA HHc?5A;???A B C1#CGQs2wY//1bM DAqQ3AaD bM DAq acFaKF eQhaeQh1 B+ b'Q,, 3Jr0nc t|}t|}|dkrtjSt t |Dcgc]}|||zdz |z ||zc}Scc}w)a Detects and returns a recurrence relation from a sequence of several integer (or rational) terms. The name of the function in the returned expression is 'a' by default; the main variable is 'n' by default. The smallest index in the returned expression is always n (and never n-1, n-2, etc.). Examples ======== >>> from sympy.concrete.guess import find_simple_recurrence >>> from sympy import fibonacci >>> find_simple_recurrence([fibonacci(k) for k in range(12)]) -a(n) - a(n + 1) + a(n + 2) >>> from sympy import Function, Symbol >>> a = [1, 1, 1] >>> for k in range(15): a.append(5*a[-1]-3*a[-2]+8*a[-3]) >>> find_simple_recurrence(a, A=Function('f'), N=Symbol('i')) -8*f(i) + 3*f(i + 1) - 5*f(i + 2) + f(i + 3) r)r2r!rZerorr")vANpr4r/s rfind_simple_recurrencer;Ts[. &a(A AAAvaff} %(3Q1Q3q57AaD3 443sA cd\}}d\}}t|}||ks|dk(r=||z|z}||z|z}||}}||}}||k(rnd||z z }t|}||kr7|dk(r=tz S)a Helps identifying a rational number from a float (or mpmath.mpf) value by using a continued fraction. The algorithm stops as soon as a large partial quotient is detected (greater than 10000 by default). Examples ======== >>> from sympy.concrete.guess import rationalize >>> from mpmath import cos, pi >>> rationalize(cos(pi/3)) 1/2 >>> from mpmath import mpf >>> rationalize(mpf("0.333333333333333")) 1/3 While the function is rather intended to help 'identifying' rational values, it may be used in some cases for approximating real numbers. (Though other functions may be more relevant in that case.) >>> rationalize(pi, maxcoeff = 250) 355/113 See Also ======== Several other methods can approximate a real number as a rational, like: * fractions.Fraction.from_decimal * fractions.Fraction.from_float * mpmath.identify * mpmath.pslq by using the following syntax: mpmath.pslq([x, 1]) * mpmath.findpoly by using the following syntax: mpmath.findpoly(x, 1) * sympy.simplify.nsimplify (which is a more general function) The main difference between the current function and all these variants is that control focuses on magnitude of partial quotients here rather than on global precision of the approximation. If the real is "known to be" a rational number, the current function should be able to detect it correctly with the default settings even when denominator is great (unless its expansion contains unusually big partial quotients) which may occur when studying sequences of increasing numbers. If the user cares more on getting simple fractions, other methods may be more convenient. )rr)rrrr)rr ) r.maxcoeffp0p1q0r*r0r:r1s r rationalizerArs`FB FB aA h,"a% bD2I bD2IQBQB a4 qsG !H h,"a% 1:>r3r.c ztt}|dkryttdz Dcgc].tfdtt dz|D0c}tfdttDtfdt|Dz Scc}w)a Tries to "guess" a rational generating function for a sequence of rational numbers v. Examples ======== >>> from sympy.concrete.guess import guess_generating_function_rational >>> from sympy import fibonacci >>> l = [fibonacci(k) for k in range(5,15)] >>> guess_generating_function_rational(l) (3*x + 5)/(-x**2 - x + 1) See Also ======== sympy.series.approximants mpmath.pade rNc3:K|]}|z |zywNr)rr/ir1r7s rrz5guess_generating_function_rational..s! 5QQqsVAaD[ 5c34K|]}||zzywrDr)rr/Xr:s rrz5guess_generating_function_rational..s1a!QT 1c34K|]}||zzywrDr)rr/rHr1s rrz5guess_generating_function_rational..s.!A$q!t).rI)r2r!r"r&min)r7rHr4rEr:r1s`` `@@r"guess_generating_function_rationalrLs. &a(A AAAvd3q619% ' 5%AaC "4 5 5 'A 15Q=1 1.U1X.. /0 's3B8allc .  d|vrd}i}d|vrdgdgtdz zz ttd|D]k}ttDcgc]$t fdtdzD&c} t |}|sV|t d|dzz|d<nd|vrgt jc }tD]"\} } || r| ndz} j| |z $dgdgt dz zz ttd|D]k}tt Dcgc]$t fd tdzD&c} t |}|sV|t d|dzz|d<nd |vrgt jc }tD]+\} } | } j|| zt| dzz -dgdgt dz zz ttd|D]k}tt Dcgc]$t fd tdzD&c} t |}|sV|t d|dzz|d <nd |vrg tD]%\} } j| t| dzz 'dgdgt dz zz ttd|D]k}tt Dcgc]$t fd tdzD&c} t |}|sV|t d|dzz|d <nddk7r2d|vs d|vr)d|vr$tdgc} ttdz D]A jdzdzzt fdtDz | z Cdgdgt dz zz ttd|D]}tt Dcgc]$t fdtdzD&c} t |}|sV|t d|dzz|d<d|vrtt|d||d<nddk7rmd|vs d|vrdd|vr_gt jc}tD]"\} } || r| ndz}j| |z $dgc} ttdz D]A jdzdzzt fdtDz | z Cdgdgt dz zz ttd|D]}tt Dcgc]$t fdtdzD&c} t |}|sV|t d|dzz|d<d|vrtt|d||d<|S|Scc}wcc}wcc}wcc}wcc}wcc}w)a@ Tries to "guess" a generating function for a sequence of rational numbers v. Only a few patterns are implemented yet. Explanation =========== The function returns a dictionary where keys are the name of a given type of generating function. Six types are currently implemented: type | formal definition -------+---------------------------------------------------------------- ogf | f(x) = Sum( a_k * x^k , k: 0..infinity ) egf | f(x) = Sum( a_k * x^k / k! , k: 0..infinity ) lgf | f(x) = Sum( (-1)^(k+1) a_k * x^k / k , k: 1..infinity ) | (with initial index being hold as 1 rather than 0) hlgf | f(x) = Sum( a_k * x^k / k , k: 1..infinity ) | (with initial index being hold as 1 rather than 0) lgdogf | f(x) = derivate( log(Sum( a_k * x^k, k: 0..infinity )), x) lgdegf | f(x) = derivate( log(Sum( a_k * x^k / k!, k: 0..infinity )), x) In order to spare time, the user can select only some types of generating functions (default being ['all']). While forgetting to use a list in the case of a single type may seem to work most of the time as in: types='ogf' this (convenient) syntax may lead to unexpected extra results in some cases. Discarding a type when calling the function does not mean that the type will not be present in the returned dictionary; it only means that no extra computation will be performed for that type, but the function may still add it in the result when it can be easily converted from another type. Two generating functions (lgdogf and lgdegf) are not even computed if the initial term of the sequence is 0; it may be useful in that case to try again after having removed the leading zeros. Examples ======== >>> from sympy.concrete.guess import guess_generating_function as ggf >>> ggf([k+1 for k in range(12)], types=['ogf', 'lgf', 'hlgf']) {'hlgf': 1/(1 - x), 'lgf': 1/(x + 1), 'ogf': 1/(x**2 - 2*x + 1)} >>> from sympy import sympify >>> l = sympify("[3/2, 11/2, 0, -121/2, -363/2, 121]") >>> ggf(l) {'ogf': (x + 3/2)/(11*x**2 - 3*x + 1)} >>> from sympy import fibonacci >>> ggf([fibonacci(k) for k in range(5, 15)], types=['ogf']) {'ogf': (3*x + 5)/(-x**2 - x + 1)} >>> from sympy import factorial >>> ggf([factorial(k) for k in range(12)], types=['ogf', 'egf', 'lgf']) {'egf': 1/(1 - x)} >>> ggf([k+1 for k in range(12)], types=['egf']) {'egf': (x + 1)*exp(x), 'lgdegf': (x + 2)/(x + 1)} N-th root of a rational function can also be detected (below is an example coming from the sequence A108626 from https://oeis.org). The greatest n-th root to be tested is specified as maxsqrtn (default 2). >>> ggf([1, 2, 5, 14, 41, 124, 383, 1200, 3799, 12122, 38919])['ogf'] sqrt(1/(x**4 + 2*x**2 - 4*x + 1)) References ========== .. [1] "Concrete Mathematics", R.L. Graham, D.E. Knuth, O. Patashnik .. [2] https://oeis.org/wiki/Generating_functions rM)ogfegflgfhlgflgdogflgdegfrPrrc3:K|]}|z |zywrDr)rrEr4tr7s rrz,guess_generating_function..&!5QQqsVAaD[5rFrHrQc3:K|]}|z |zywrDrrrEr4rWws rrz,guess_generating_function..6rXrFrRc3:K|]}|z |zywrDrr[s rrz,guess_generating_function..FrXrFrSc3:K|]}|z |zywrDrr[s rrz,guess_generating_function..UrXrFrTc3BK|]}| dz |dzzywrr)rrEr7r\s rrz,guess_generating_function..c'"Da1aRT71QqS6>"Dc3:K|]}|z |zywrDrr[s rrz,guess_generating_function..grXrFrUc3BK|]}| dz |dzzywrr)rrEr\r,s rrz,guess_generating_function..|r`rac3:K|]}|z |zywrDrr[s rrz,guess_generating_function..rXrF)r!r"r'r&rLr rr$r(r% NegativeOnerr r r)r7rHtypesmaxsqrtnresultdr4gfrEr/r0rWr\r,s` ` @@@rguess_generating_functionrlsV ~A F ~ C1#s1vz" "s1h'( A?DSV}M!5%!*55MA21:A !8Aqs#3 3u    ~1551aL DAq aQ A HHQqSM C1#s1vz" "s1h'( A?DSV}M!5%!*55MA21:A !8Aqs#3 3u    ~1==1aL 'DAqA HHQqS1% & 'C1#s1vz" "s1h'( A?DSV}M!5%!*55MA21:A !8Aqs#3 3u    aL %DAq HHQwqs|^ $ %C1#s1vz" "s1h'( A?DSV}M!5%!*55MA21:A!"HQ!$4!4v   tqyh%' E>e6.Aqt}b1s1vax IA HH!A#! s"D58"DDDaG I IC1#s1vz" "s1h'( A?DSV}M!5%!*55MA21:A#$hq!A#&6#6x &$' &2BA(F$GF5M  tqyh%' E>e6.A1551aL DAq aQ A HHQqSM  tR1s1vax IA HH!A#! s"D58"DDDaG I IC1#s1vz" "s1h'( A?DSV}M!5%!*55MA21:A#$hq!A#&6#6x &$' &2BA(F$GF5M M  MEN N NN$N2Ns$)W97)W> )X2)X)X )XNc Ztd|ddDrgSt|}t|dz |}|rtnt}g}g}|t dt |z} n|} t| D]2\} } |j|t|g} } t| dz dz ddD]w}tt|| ddd|| }t|j| | id k7sB|j| | i|| dz d k(sb|| vsg| j|y| rNt| dz ddD]0}| Dcgc]#}||d ||| |dzd| |dz fz%} }2|s| cS|| z }t|| z dz Dcgc]}t||dz||}}5|Scc}wcc}w) a This function is adapted from the Rate.m package for Mathematica written by Christian Krattenthaler. It tries to guess a formula from a given sequence of rational numbers. Explanation =========== In order to speed up the process, the 'all' variable is set to False by default, stopping the computation as some results are returned during an iteration; the variable can be set to True if more iterations are needed (other formulas may be found; however they may be equivalent to the first ones). Another option is the 'evaluate' variable (default is True); setting it to False will leave the involved products unevaluated. By default, the number of iterations is set to 2 but a greater value (up to len(l)-1) can be specified with the optional 'niter' variable. More and more convoluted results are found when the order of the iteration gets higher: * first iteration returns polynomial or rational functions; * second iteration returns products of rising factorials and their inverses; * third iteration returns products of products of rising factorials and their inverses; * etc. The returned formulas contain symbols i0, i1, i2, ... where the main variables is i0 (and auxiliary variables are i1, i2, ...). A list of other symbols can be provided in the 'variables' option; the length of the least should be the value of 'niter' (more is acceptable but only the first symbols will be used); in this case, the main variable will be the first symbol in the list. Examples ======== >>> from sympy.concrete.guess import guess >>> guess([1,2,6,24,120], evaluate=False) [Product(i1 + 1, (i1, 1, i0 - 1))] >>> from sympy import symbols >>> r = guess([1,2,7,42,429,7436,218348,10850216], niter=4) >>> i0 = symbols("i0") >>> [r[0].subs(i0,n).doit() for n in range(1,10)] [1, 2, 7, 42, 429, 7436, 218348, 10850216, 911835460] c3&K|] }|dk( yw)rNr)rr0s rrzguess..s A1a4 sNr rzi:rN)startrYr)anyr!rKrrr strr(r%r"rinterprsubsr )rrMevaluateniter variablesr9myprodrjressymbr/sr4rrErir7s rguessr}sf 3B    AA !UOE WgF A CtCJ'$;1  1vr1qs1ub"% A1Q49A6Q?Br1&!+!A!A$r(2a7!    1Q3B' IFGIABqT!Wq4!9aa";<=II Iq 1HC-21Q3q5\ :Xa!fad # : :; J I ;s 6(F#F()i')FTrNN)&__doc__sympy.concrete.productsrr sympy.corerrsympy.core.addrsympy.core.numbersrr sympy.core.symbolr r sympy.core.sympifyr &sympy.functions.elementary.exponentialr #sympy.functions.elementary.integersrsympy.integrals.integralsrsympy.polys.polyfuncsrrrsympy.polys.polytoolsrsympy.simplify.radsimprsympy.utilitiesrr2r;rArLrlr}rr3rrsG7"0-&65/A%(">>@ ( 55:::z,23K00@#)#;ugvvrMMr3