K i}c "dZddlmZddlmZddlmZmZmZm Z ddl m Z ddl m Z ddlmZddlmZmZdd lmZgd Zid d d ddddddddddddddddddd d!d"d#d$d%d&d'd(d)d*d+d,d-d.d/d0d1d2d3d4ZGd5d6eZd:d8Zd9Zy7);ai Octave (and Matlab) code printer The `OctaveCodePrinter` converts SymPy expressions into Octave expressions. It uses a subset of the Octave language for Matlab compatibility. A complete code generator, which uses `octave_code` extensively, can be found in `sympy.utilities.codegen`. The `codegen` module can be used to generate complete source code files. ) annotations)Any)MulPowSRational) _keep_coeff) equal_valued) CodePrinter) precedence PRECEDENCEsearch)1sincostancotseccscasinacosacotatanatan2asecacscsinhcoshtanhcothcschsechasinhacoshatanhacothasechacscherfcerfierferfinverfcinvbesselibesseljbesselkbessely bernoullibetaeulerexp factorialfloorfresnelcfresnelsgammaharmoniclogpolylogsignzetalegendreAbsabsarganglebinomialbincoeffceilingceil chebyshevu chebyshevU chebyshevt chebyshevTChicoshintCicosint conjugateconj DiracDeltadirac Heaviside heavisideimimaglaguerre laguerreLLambertWlambertwlilogintloggammagammalnMaxmaxminmodpsireal pochhammersinhintsinint)MinMod polygammareRisingFactorialShiSic eZdZUdZdZdZddddZeejfidid d d Z d e d <iffd Z dZ dZ dZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZd Zd!Zd"Z e Z!e Z"e Z#d#Z$d$Z%d%Z&d&Z'd'Z(d(Z)d)Z*d*Z+d+Z,d,Z-d-Z.d.Z/d/Z0d0Z1d1Z2d2Z3d3Z4d4Z5d5Z6d6Z7d7Z8d8Z9d9Z:d:Z;d;Zd<Z?e?xZ@ZAd=ZBd>ZCd?ZDxZES)@OctaveCodePrinterzL A printer to convert expressions to strings of Octave/Matlab code. _octaveOctave&|~)andornotT) precisionuser_functionscontractinlinezdict[str, Any]_default_settingsct||tttt|_|j j tt|jdi}|j j |y)Nr}) super__init__dictzipknown_fcns_src1known_functionsupdateknown_fcns_src2get)selfsettings userfuncs __class__s [/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/sympy/printing/octave.pyrzOctaveCodePrinter.__init__Ysb "#C$IJ ##D$9:LL!126  ##I.c |dzS)N)rps r_rate_index_positionz&OctaveCodePrinter._rate_index_positionas s rc d|zS)Nz%s;r)r codestrings r_get_statementz OctaveCodePrinter._get_statementes z!!rc$dj|S)Nz% {}format)rtexts r _get_commentzOctaveCodePrinter._get_commentis}}T""rc&dj||S)Nz{} = {};r)rnamevalues r_declare_number_constz'OctaveCodePrinter._declare_number_constms  u--rc$|j|SN) indent_code)rliness r _format_codezOctaveCodePrinter._format_codeqs&&rcJ|j\}fdt|DS)Nc3FK|]}tD]}||f ywr)range).0jirowss r z=OctaveCodePrinter._traverse_matrix_indices..xs%A1U4[AAAAs!)shaper)rmatcolsrs @r_traverse_matrix_indicesz*OctaveCodePrinter._traverse_matrix_indicesusYY dAd AArc g}g}|D]n}t|j|j|jdz|jdzg\}}}|j d|d|d||j dp||fS)Nzfor  = :end)map_printlabellowerupperappend)rindices open_lines close_linesrvarstartstops r_get_loop_opening_endingz*OctaveCodePrinter._get_loop_opening_ending{s   &A"4;;WWaggk177Q;7 9 C   #udC D   u %  & ;&&rc<|jrO|jrCtj|zjr&d|j tj |zzSt |}|j\}}|dkrt| |}d}nd}g}g}g}|jdvr|j} ntj|} | D]} | jr| jr| jj r| jj"r| jdk7r3|j%t'| j(| j dt+| j,dj,d k7r+t/| j(tr|j%| |j%t'| j(| j  | j r|| tj0urj| j2d k7r$|j%t5| j2| j6d k7sn|j%t5| j6|j%| |xstj8g}|D cgc]} |j;| |} } |D cgc]} |j;| |} } |D]N} | j(|vsd | |j=| j(z| |j=| j(<Pd }|s |||| zSt+|d k(r(|djrd nd }|||| z|z| dzSt?d|Drd nd }|||| z|zd ||| zzScc} wcc} w)Nz%sir-)oldnoneF)evaluaterz(%s)c|d}tdt|D]#}||dz jrdnd}||z||z}%|S)Nrr*.*)rlen is_number)aa_strrrmulsyms rmultjoinz.OctaveCodePrinter._print_Mul..multjoinsUaA1c!f% * !!A# 0 0dJq) *Hr/./c34K|]}|jywrr)rbis rrz/OctaveCodePrinter._print_Mul..s9 9) r is_imaginaryr ImaginaryUnit is_Integerrr as_coeff_Mulr orderas_ordered_factorsr make_argsis_commutativeis_Powr5 is_Rational is_negativerrbaserargs isinstanceInfinityrrqOne parenthesizeindexall)rexprpreccer>rb pow_parenritemxrb_strrdivsyms r _print_MulzOctaveCodePrinter._print_Muls NNt00%114;;'7'<== =$  "1 q5r1%DDD   ::_ ,**,D==&D D## 8L8L,,88r>HHSTXXIFG499Q<,,-2z$))S7Q!((.HHSTXXI67!!d!**&<66Q;HHXdff-.66Q;HHXdff-. " L!%%567""1d+77567""1d+77 ODyyA~,2U177499;M5N,Naggdii() O  (1e,, , Vq[aDNNSF(1e,,v5a@ @9q99StF8Au--#hq%&889 :187s N-Nc|j|j}|j|j}|j}dj |||S)Nz{} {} {})rlhsrhsrel_opr)rrlhs_coderhs_codeops r_print_Relationalz#OctaveCodePrinter._print_RelationalsD;;txx(;;txx( [[  2x88rctd|jDrdnd}t|}t|jdrd|j |j zS|jrt|jdr>|j jrdnd}d |zd|j |j zzSt|jd r?|j jrdnd}d |zd |j|j |zzS|j|j |||j|j|S) Nc34K|]}|jywrr)rrs rrz/OctaveCodePrinter._print_Pow..s>qq{{>r^z.^g?zsqrt(%s)grr1r%s) rrr r r5rrrrr)rr powsymbolPRECsyms r _print_PowzOctaveCodePrinter._print_Pows>DII>>CD $ # & DII 66 6   DHHd+!YY00cdSy: DII0F#FFFDHHb)!YY00cdSy4$*;*;DIIt*L#LLL,,TYY=y,,TXXt<> >rct|}|j|j|d|j|j|S)Nr)r rrr5rrr s r _print_MatPowzOctaveCodePrinter._print_MatPows>$++DIIt<++DHHd;= =rct|}|j|j|d|j|j|S)Nz \ )r rmatrixvectorr s r_print_MatrixSolvez$OctaveCodePrinter._print_MatrixSolves@$!..t{{DA!..t{{DAC Crcy)Npirrrs r _print_PizOctaveCodePrinter._print_Pircy)N1irrs r_print_ImaginaryUnitz&OctaveCodePrinter._print_ImaginaryUnitrrcy)Nzexp(1)rrs r _print_Exp1zOctaveCodePrinter._print_Exp1srcy)Nz (1+sqrt(5))/2rrs r_print_GoldenRatioz$OctaveCodePrinter._print_GoldenRatiosrcXddlm}ddlm}ddlm}|j }|j}|jdswt|j|rag}g}|jD].\} } |j||| |j| 0|t||} |j| S|jdr4|j|s|j|r|j||S|j|} |j|} |j!| d| S)Nr) Assignment) Piecewise) IndexedBaserr~r)sympy.codegen.astr $sympy.functions.elementary.piecewiser!sympy.tensor.indexedr"rr _settingsrrrrrhas_doprint_loopsr)rrr r!r"rr expressions conditionsrrtemprrs r_print_Assignmentz#OctaveCodePrinter._print_Assignments0B4hhhh~~h'Jtxx,KKJ(( %A"":c1#56!!!$ %c+z:;D;;t$ $ >>* %377;+? $&&sC0 0{{3'H{{3'H&&Hh'GH Hrcy)Ninfrrs r_print_Infinityz!OctaveCodePrinter._print_Infinity$rcy)Nz-infrrs r_print_NegativeInfinityz)OctaveCodePrinter._print_NegativeInfinity(rcy)NNaNrrs r _print_NaNzOctaveCodePrinter._print_NaN,r0rcDddjfd|DzdzS)N{, c3@K|]}j|ywrr)rrrs rrz0OctaveCodePrinter._print_list..1sr)rrrArs rrz6OctaveCodePrinter._print_MatrixBase..Ps@":&'#&((AadG+LqDKKN+L"M":+LsAA A)rrrZerorrr>r)rrMs``r_print_MatrixBasez#OctaveCodePrinter._print_MatrixBaseGs FFAFF v % VVqww &'ffaff5 5ffaff  ';;qw' ' ":+0="::: :rc ddlm}|j}||Dcgc] }|ddz c}g}||Dcgc] }|ddz c}g}||Dcgc]}|d c}g}d|j|d|j|d|j|d|jd|j d Scc}wcc}wcc}w)Nr)Matrixrzsparse(r9rJ)sympy.matricesrQcol_listrrr)rrMrQLkIJAIJs r_print_SparseRepMatrixz(OctaveCodePrinter._print_SparseRepMatrixTs) JJL q)!QqTAX)* + q)!QqTAX)* +Q'qt'()/3{{1~t{{1~,0KK,C Cc|j|jtddd|jdzd|jdzdzS)NAtomT)strict(rr9rJ)rparentr rrrs r_print_MatrixElementz&OctaveCodePrinter._print_MatrixElement_sB  j.@ N FFQJ 34 4rcfd}j|jdz||j|jjdzdz||j|jjdzdzS)Nc|ddz}|d}|d}j|}||k(rdnj|}|dk(r|dk(r||k(ry||k(r|S|dz|zSdj|j||fS)NrrrRrr)rr>)rlimlhsteplstrhstrrs rstrslicez6OctaveCodePrinter._print_MatrixSlice..strslicees!qA!AQ4D;;q>DH5$++a.Dqy6a3h6K#:,,xxt{{4'8$ ?@@rr^rr9rrJ)rr_rowslicercolslice)rrris` r_print_MatrixSlicez$OctaveCodePrinter._print_MatrixSliceds| A DKK(3. (9(9!(<=>@DE (9(9!(<=>@CD Erc|jDcgc]}|j|}}|j|jjddj |dScc}w)Nr^r9rJ)rrrrr>)rrrindss r_print_Indexedz OctaveCodePrinter._print_IndexedysJ)-7AQ77;;tyy74II8sA#c\tddtfd|jDzS)Nrzdouble(%s == %s)c3BK|]}j|ywr)r)rrrrs rrz:OctaveCodePrinter._print_KroneckerDelta..s&*>./+/*;*;At*D*>s)r tupler)rrrs` @r_print_KroneckerDeltaz'OctaveCodePrinter._print_KroneckerDelta~s2% !E*>3799*>%>> >rc dj|jDcgc]}|j|t|c}Scc}w)Nr)r>rrr )rrrCs r_print_HadamardProductz(OctaveCodePrinter._print_HadamardProductsDyy%)YY0!++CD1AB01 10s"Act|}dj|j|j||j|j|gS)Nz.**)r r>rrr5r s r_print_HadamardPowerz&OctaveCodePrinter._print_HadamardPowersJ$zz   dii .   dhh - rc|j}t|dk(r|d|dk(r|dg}djfd|D}d|zdzS)NrRrrr9c3@K|]}j|ywrr;)rnrs rrz4OctaveCodePrinter._print_Identity..s4dkk!n4r<zeye(rJ)rrr>)rrrss` r_print_Identityz!OctaveCodePrinter._print_IdentitysT  u:?uQx5831XJE II4e4 4zCrcdj|j|jd|j|jdS)Nz (gammainc({1}, {0}).*gamma({0}))rrrrrrs r_print_lowergammaz#OctaveCodePrinter._print_lowergammas>188 KK ! %t{{499Q<'@B Brcdj|j|jd|j|jdS)Nz)(gammainc({1}, {0}, 'upper').*gamma({0}))rrr~rs r_print_uppergammaz#OctaveCodePrinter._print_uppergammas>:AA KK ! %t{{499Q<'@B Brcfd|j|jdtjz zS)Nzsinc(%s)r)rrrPirs r _print_sinczOctaveCodePrinter._print_sincs'DKK ! QTT(9:::rcxd|j|jd|j|jdS)Nbesselh(z, 1, rJrrargumentrs r_print_hankel1z OctaveCodePrinter._print_hankel1.'+{{4::'>'+{{4=='AC Crcxd|j|jd|j|jdS)Nrz, 2, rJrrs r_print_hankel2z OctaveCodePrinter._print_hankel2rrcddlm}m}|j}|tj d|zz ||j tjz|z}|j|S)Nr)sqrtr/rR) sympy.functionsrr/rrrrHalfr)rrrr/rexpr2s r _print_jnzOctaveCodePrinter._print_jnL1 MMQTT1Q3Z aff)reversedr)rrrs r_one_or_two_reversed_argsz+OctaveCodePrinter._one_or_two_reversed_argsss499~"""&&%%dnn&=&=>HTYY4GHqDKKNHI'  Hs*Bc dj|j|jj|j |j d|j |j |j ddS)Nz{name}({arg1}, {arg2})rr)rarg1arg2)rrrrrrfuncrs r_nested_binary_math_funcz*OctaveCodePrinter._nested_binary_math_funcsg'..%%dnn&=&=>TYYq\*YTYY !" 67/ rc |jdjdk7r tdg}|jdr|jddDcgc]5\}}dj |j ||j |7}}}d|j |jdj z}dj||zdt|zz}d |zdzSt|jD]\}\}}|d k(r$|jd |j |znU|t|jd z k(r|dk(r|jd n#|jd|j |z|j |} |j| |t|jd z k(s|jddj|Scc}}w)NrTzAll Piecewise expressions must contain an (expr, True) statement to be used as a default condition. Without one, the generated expression may not evaluate to anything under some condition.rz({0}).*({1}) + (~({0})).*(rz ... rJr^rzif (%s)relsez elseif (%s)r ) rcond ValueErrorr&rrrr>r enumerater) rrrrrecpairselastpwrcode0s r_print_Piecewisez"OctaveCodePrinter._print_Piecewises 99R=   %/0 0  >>( # $(99Sb>31a4:: A A83G34;;tyy}'9'9::Ew'%/#c'l2BBB8c> !&tyy1 ( 6Aq6LLT[[^!;<#dii.1,,dLL(LLQ!?@ A U#DII**LL' (99U# #)3s :Gct|jdk(r!d|j|jdzS|j|S)Nrzzeta(%s)r)rrrrrs r _print_zetazOctaveCodePrinter._print_zetasA tyy>Q  DIIaL 99 9,,T2 2rc Ft|tr1|j|jd}dj |Sd}d}d}|Dcgc]}|j d}}|Dcgc]t tfd|D!}}|Dcgc]t tfd|D!}}g} d } t|D]C\} d vr| j| || z} | j|| z| || z } E| Scc}wcc}wcc}w) z0Accepts a string of code or a list of code linesTrz )z ^function z^if ^elseif ^else$z^for )z^end$rrz c36K|]}t|ywrrrrmlines rrz0OctaveCodePrinter.indent_code..&B"VB-Bc36K|]}t|ywrrrs rrz0OctaveCodePrinter.indent_code..(rrr)rr) rrGr splitlinesr>lstripintanyrr) rcode code_linestab inc_regex dec_regexrincreasedecreaseprettylevelrzs ` rrzOctaveCodePrinter.indent_codesC dC ))$//$*?@J77:& &I 3 156U#66"&(B BBC(("&(B BBC((  !GAtz! d# Xa[ E MMCIt4 5 Xa[ E  ! !7((s D,$D$D)Fr __module__ __qualname____doc__ printmethodlanguage _operatorsrr r__annotations__rrrrrrrrrrr rrrrrrr,r/r2r6r? _print_tuple _print_Tuple _print_ListrBrErHrOrZr`rlrorsrurwr|rrrrrrrrrrrrr_print_DiracDelta_print_LambertWr _print_Max _print_Minrrr __classcell__)rs@rrrrrAsKHJ )-[-J-J) O)~!#/"#.'B 'H:T9 >(= C  I:CLLK! :N4 E*J > 1 B B ; C C ""9999- +DC76J"$J3rrrNc 8t|j||S)aConverts `expr` to a string of Octave (or Matlab) code. The string uses a subset of the Octave language for Matlab compatibility. Parameters ========== expr : Expr A SymPy expression to be converted. assign_to : optional When given, the argument is used as the name of the variable to which the expression is assigned. Can be a string, ``Symbol``, ``MatrixSymbol``, or ``Indexed`` type. This can be helpful for expressions that generate multi-line statements. precision : integer, optional The precision for numbers such as pi [default=16]. user_functions : dict, optional A dictionary where keys are ``FunctionClass`` instances and values are their string representations. Alternatively, the dictionary value can be a list of tuples i.e. [(argument_test, cfunction_string)]. See below for examples. human : bool, optional If True, the result is a single string that may contain some constant declarations for the number symbols. If False, the same information is returned in a tuple of (symbols_to_declare, not_supported_functions, code_text). [default=True]. contract: bool, optional If True, ``Indexed`` instances are assumed to obey tensor contraction rules and the corresponding nested loops over indices are generated. Setting contract=False will not generate loops, instead the user is responsible to provide values for the indices in the code. [default=True]. inline: bool, optional If True, we try to create single-statement code instead of multiple statements. [default=True]. Examples ======== >>> from sympy import octave_code, symbols, sin, pi >>> x = symbols('x') >>> octave_code(sin(x).series(x).removeO()) 'x.^5/120 - x.^3/6 + x' >>> from sympy import Rational, ceiling >>> x, y, tau = symbols("x, y, tau") >>> octave_code((2*tau)**Rational(7, 2)) '8*sqrt(2)*tau.^(7/2)' Note that element-wise (Hadamard) operations are used by default between symbols. This is because its very common in Octave to write "vectorized" code. It is harmless if the values are scalars. >>> octave_code(sin(pi*x*y), assign_to="s") 's = sin(pi*x.*y);' If you need a matrix product "*" or matrix power "^", you can specify the symbol as a ``MatrixSymbol``. >>> from sympy import Symbol, MatrixSymbol >>> n = Symbol('n', integer=True, positive=True) >>> A = MatrixSymbol('A', n, n) >>> octave_code(3*pi*A**3) '(3*pi)*A^3' This class uses several rules to decide which symbol to use a product. Pure numbers use "*", Symbols use ".*" and MatrixSymbols use "*". A HadamardProduct can be used to specify componentwise multiplication ".*" of two MatrixSymbols. There is currently there is no easy way to specify scalar symbols, so sometimes the code might have some minor cosmetic issues. For example, suppose x and y are scalars and A is a Matrix, then while a human programmer might write "(x^2*y)*A^3", we generate: >>> octave_code(x**2*y*A**3) '(x.^2.*y)*A^3' Matrices are supported using Octave inline notation. When using ``assign_to`` with matrices, the name can be specified either as a string or as a ``MatrixSymbol``. The dimensions must align in the latter case. >>> from sympy import Matrix, MatrixSymbol >>> mat = Matrix([[x**2, sin(x), ceiling(x)]]) >>> octave_code(mat, assign_to='A') 'A = [x.^2 sin(x) ceil(x)];' ``Piecewise`` expressions are implemented with logical masking by default. Alternatively, you can pass "inline=False" to use if-else conditionals. Note that if the ``Piecewise`` lacks a default term, represented by ``(expr, True)`` then an error will be thrown. This is to prevent generating an expression that may not evaluate to anything. >>> from sympy import Piecewise >>> pw = Piecewise((x + 1, x > 0), (x, True)) >>> octave_code(pw, assign_to=tau) 'tau = ((x > 0).*(x + 1) + (~(x > 0)).*(x));' Note that any expression that can be generated normally can also exist inside a Matrix: >>> mat = Matrix([[x**2, pw, sin(x)]]) >>> octave_code(mat, assign_to='A') 'A = [x.^2 ((x > 0).*(x + 1) + (~(x > 0)).*(x)) sin(x)];' Custom printing can be defined for certain types by passing a dictionary of "type" : "function" to the ``user_functions`` kwarg. Alternatively, the dictionary value can be a list of tuples i.e., [(argument_test, cfunction_string)]. This can be used to call a custom Octave function. >>> from sympy import Function >>> f = Function('f') >>> g = Function('g') >>> custom_functions = { ... "f": "existing_octave_fcn", ... "g": [(lambda x: x.is_Matrix, "my_mat_fcn"), ... (lambda x: not x.is_Matrix, "my_fcn")] ... } >>> mat = Matrix([[1, x]]) >>> octave_code(f(x) + g(x) + g(mat), user_functions=custom_functions) 'existing_octave_fcn(x) + my_fcn(x) + my_mat_fcn([1 x])' Support for loops is provided through ``Indexed`` types. With ``contract=True`` these expressions will be turned into loops, whereas ``contract=False`` will just print the assignment expression that should be looped over: >>> from sympy import Eq, IndexedBase, Idx >>> len_y = 5 >>> y = IndexedBase('y', shape=(len_y,)) >>> t = IndexedBase('t', shape=(len_y,)) >>> Dy = IndexedBase('Dy', shape=(len_y-1,)) >>> i = Idx('i', len_y-1) >>> e = Eq(Dy[i], (y[i+1]-y[i])/(t[i+1]-t[i])) >>> octave_code(e.rhs, assign_to=e.lhs, contract=False) 'Dy(i) = (y(i + 1) - y(i))./(t(i + 1) - t(i));' )rrdoprint)r assign_tors r octave_coder7sP X & . .tY ??rc .tt|fi|y)zPrints the Octave (or Matlab) representation of the given expression. See `octave_code` for the meaning of the optional arguments. N)printr)rrs rprint_octave_coders  +d 'h '(rr)r __future__rtypingr sympy.corerrrrsympy.core.mulr sympy.core.numbersr sympy.printing.codeprinterr sympy.printing.precedencer r rmrrrrrrrrrrrs5 #,,&+2<: 5 7 v  ,  ,  9 (' &   (  !" 5#$   #  18s slH@V)r