o
    8Vak                     @   s^  d Z ddlZddlZddlZddlmZmZmZmZ ddl	m
Z
 ddlmZ G dd de
Zdd	 Zedi d
ddddddddddddddddddddddd d!d d"d#d$d#d%d&d'd(d)d*d+d,d-d.d/d0d1d2d3d4d5d6d7d6d8d9d:d9d;d<d=d<d>d?d@dAdBdCdDdEdFdGdHdIdJdKdLdMdNdOdPdQdRdSdTdUdVdWdXdYdZd[d\d]d^d_d`dadbdcdddcdedfZdgdhdiZdjdkdlZg dmZdndo Zdpdq Zi fdrdsZi fdtduZg dfdvdwZddxdyZdzg dzfd{d|Zdd}d~Zdd Zdd Zdd Zdd Zdd Z dd Z!dd Z"dd Z#dddZ$dS )a  
Parser for FullForm[Downvalues[]] of Mathematica rules.

This parser is customised to parse the output in MatchPy rules format. Multiple
`Constraints` are divided into individual `Constraints` because it helps the
MatchPy's `ManyToOneReplacer` to backtrack earlier and improve the speed.

Parsed output is formatted into readable format by using `sympify` and print the
expression using `sstr`. This replaces `And`, `Mul`, 'Pow' by their respective
symbols.

Mathematica
===========

To get the full form from Wolfram Mathematica, type:
```
ShowSteps = False
Import["RubiLoader.m"]
Export["output.txt", ToString@FullForm@DownValues@Int]
```

The file ``output.txt`` will then contain the rules in parseable format.

References
==========
[1] http://reference.wolfram.com/language/ref/FullForm.html
[2] http://reference.wolfram.com/language/ref/DownValues.html
[3] https://gist.github.com/Upabjojr/bc07c49262944f9c1eb0
    N)sympifyFunctionSetSymbol)
StrPrinter)debugc                   @   s   e Zd Zdd ZdS )RubiStrPrinterc                 C   s   d|  |jd  S )NzNot(%s)r   )Z_printargs)selfexpr r   G/usr/lib/python3/dist-packages/sympy/integrals/rubi/parsetools/parse.py
_print_Not'   s   zRubiStrPrinter._print_NotN)__name__
__module____qualname__r   r   r   r   r   r   &   s    r   c                 K   s   t || S N)r   Zdoprint)r   Zsettingsr   r   r   rubi_printer+   s   r   TimesZMulPlusZAddPowerZPowZLoglogZExpZexpZSqrtZsqrtZCosZcosZSinZsinZTanZtanZCotz1/tanZcotZSecz1/cosZsecZCscz1/sinZcscZArcSinZasinZArcCosZacosZArcCotZacotZArcSecZasecZArcCscZacscZSinhZsinhZCoshZcoshZTanhZtanhZCothz1/tanhZcothZSechz1/coshZsechZCschz1/sinhZcschZArcSinhZasinhZArcCoshZacoshZArcTanhZatanhZArcCothZacothZArcSechZasechZArcCschZacschZExpandexpandZImZimZRereZFlattenZflattenZPolylogZpolylogZCancelZcancelZ
TrigExpandZexpand_trigZSignsignZSimplifyZsimplifyZDeferZUnevaluatedExprZIdentitySZSumZSum_doitModuleWithZBlockZNullNoneZ_gcdZ_jn)ZgcdZjnZ
ImaginaryIZ	_UseGamma)z\[ImaginaryI]z	$UseGamma)ZBinomialPartsZBinomialDegreeZTrinomialPartsZGeneralizedBinomialPartsZGeneralizedTrinomialPartsZPseudoBinomialPartsZPerfectPowerTestZSquareFreeFactorTest*SubstForFractionalPowerOfQuotientOfLinearsZ"FractionalPowerOfQuotientOfLinears"InverseFunctionOfQuotientOfLinearsZFractionalPowerOfSquareQZFunctionOfLinearZFunctionOfInverseLinearZFunctionOfTrigZFindTrigFactorZFunctionOfLogZPowerVariableExpnZFunctionOfSquareRootOfQuadraticZSubstForFractionalPowerOfLinearZFractionalPowerOfLinearZInverseFunctionOfLinearZDividesZDerivativeDividesZ
TrigSquareZSplitProductr   r    ZFunctionOfHyperbolicZSplitSumc                 C   sx   t | tr| D ]	}t|r dS qdS t| tdks#t| tdkr4tD ]}| t|r1 dS q%dS | tv r:dS dS )z
    This function returns whether an expression contains functions which have different return types in
    diiferent cases.
    Tr   r   F)
isinstancelistcontains_diff_return_typetyper   f_diff_return_typehas)air   r   r   r#   y   s   
	 r#   c                 C   s   g }|g}t d| }d}|D ]f}|du r |d S | }| || dddddd }| dkrD|dkrC|d | n-| dkrZ|dkrU|d | |  n| dkrq|d |g ||d d  | }q|d S )	z@
    Parses FullForm[Downvalues[]] generated by Mathematica
    z[\[\],]r   N, ][)	r   finditerstartreplacestripgroupappendpopend)Zwmexproutstack	generatorZlast_posmatchZpositionZ	last_exprr   r   r   parse_full_form   s.   (

r:   c                 C   s   t | ts|S | d dkr$| dd D ]}|d dkr#d||d d < q| d dkrA| dd D ]}|d dkr@d||d d < q0| d dkr^| dd D ]}|d dkr]d||d d < qMt| dkrf|S | D ]}t||}qh|S )zD
    Returns Optional variables and their values in the pattern
    r   r      NZOptionalr   r   )r!   r"   lenget_default_values)parsedZdefault_valuesr(   r   r   r   r=      s,   
r=   c              
   C   s   g }d}t || }|D ]}| |d d|d ||d  } ||d  qd}t || }|D ]}| |d |d d } ||d  q2d}t || }|D ]}| |d |d d } ||d  qR| |fS )zu
    Replaces `Pattern(variable)` by `variable` in `string`.
    Returns the free symbols present in the string.
    z%(Optional\(Pattern\((\w+), Blank\)\))r   WC('{}', S({}))r;   z(Pattern\((\w+), Blank\))_z#(Pattern\((\w+), Blank\(Symbol\)\)))r   findallr0   formatr3   )stringoptionalsymbolspmatchesr(   r   r   r   add_wildcards   s"   $rH   c                 C   s|   | d dkr$t | d dkr| d g}n| d dd }| d }||fS | dd D ]}t|||\}}||f  S ||fS )z+
    Returns list of symbols in FreeQ.
    r   FreeQr;   N   )r<   seperate_freeq)sZ	variablesxr(   r   r   r   rK      s   rK   c                    s  g }d}| D ]}t |trOd||  | vr=|d7 }d|||}	|	 7 }	|	d|d|7 }	d|}
 ||
< ned}	t fdd	t| D }
nSt |trttt	||}d

|}dt||  | vr|d7 }d||}	|	 7 }	|	d|d|7 }	d|}
 ||
< nd}	t fdd	| D }
|
|vr||
 ||
 ||	7 }q|g krd
d

| ||fS d||fS )z<
    Converts FreeQ constraints into MatchPy constraint
    r*   z        return FreeQ({}, {})r;   z
    def cons_f{}({}, {}):
$

    cons{} = CustomConstraint({})
cons_f{}cons{}c                 3        | ]\}}| kr|V  qd S r   r   .0keyvaluerr   r   	<genexpr>      zparse_freeq.<locals>.<genexpr>, 
    def cons_f{}({}):
c                 3   rQ   r   r   rR   rV   r   r   rX     rY   )r!   strrB   valuesnextsorteditemsr"   setget_free_symbolsjoingenerate_sympy_from_parsedr3   )lrM   
cons_index	cons_dictcons_importrE   resconsr(   c	cons_namerL   r   rV   r   parse_freeq   sD   


 







rm   Fc              	      s"  d}t | ts"z
t|  d| W S    Y | v r r | d S | S | d dkr>dt| d  dt| d	  dS | d tv rM|t| d  7 }n| d d
krZ rZ|d7 }n|| d 7 }t| dkrh|S  fdd| dd D }d|v r|d |d7 }|d|7 }|d7 }|S )a   
    Parses list into Python syntax.

    Parameters
    ==========
    wild : When set to True, the symbols are replaced as wild symbols.
    symbols : Symbols already present in the pattern.
    replace_Int: when set to True, `Int` is replaced by `Integral`(used to parse pattern).
    r*   zS({})r@   r   ZRationalzS({})/S({})r;   wildrE   replace_IntrJ   ZIntZIntegralc                    s   g | ]
}t | d qS )rn   )rd   rS   r(   rp   rE   ro   r   r   
<listcomp>G  s    z.generate_sympy_from_parsed.<locals>.<listcomp>N(rZ   ))	r!   r"   floatrB   rd   replacementsr<   removerc   )r>   ro   rE   rp   r6   resultr   rr   r   rd   #  s6   

,

rd   c                 C   sB   |pg }t | ts| |v r||  |S | D ]}t|||}q|S )z.
    Returns free_symbols present in `s`.
    )r!   r"   r3   rb   )rL   rE   free_symbolsr(   r   r   r   rb   R  s   

rb   c                 C   s@  g }d}t | tr| d dkr|| }t|i }t|dd}t||d\}}tt|}t|tdtdtd	d
d}|j	d j	d }|j	d j	d }	t
|dd}t|}d|d||	}|d||7 }|d||7 }|d|j	d 7 }d|fS | D ]}
t |
trt|
|}||d  |d }q~||
 q~||fS )z]
    Takes care of the case, when a pattern matching has to be done inside a constraint.
    r*   r   MatchQTrp   rD   OrAndNotr~   r   r   localsr;   Zsympy_integersz2        def _cons_f_{}({}):
            return {}
rZ   z0        _cons_{} = CustomConstraint(_cons_f_{})
z8        pat = Pattern(UtilityOperator({}, x), _cons_{})
z=        result_matchq = is_match(UtilityOperator({}, x), pat)Zresult_matchq)r!   r"   r=   rd   rH   r_   ra   r   r   r	   r   setWCrB   rc   set_matchq_in_constraintr3   )r'   rf   lstri   rL   rD   rW   rz   patternrj   r(   r   r   r   r   b  s4   

 


r   c           
   
      sh  t tt| |g }t| }t|tdtdtddd}|tdrLt| |}|d   dt	tt|d	 tdtdtdddd
d7  nt
| rZdt	|d
d n	dt	|d
d  | vr|d7 }d|d|}d|v r~|d7 }| 7 }|d|d|7 }d|}	 ||	< nd}t fdd| D }	|	|vr||	 |	||fS )Nr~   r   r   r   r   r{   r;   z
        return {}r   Tr   zg        try:
            return {}
        except (TypeError, AttributeError):
            return Falsez        return {}r[   rZ   rM   zQ        if isinstance(x, (int, Integer, float, Float)):
            return False
rN   rO   rP   r*   c                 3   rQ   r   r   rR   ri   r   r   rX     rY   z%_divide_constriant.<locals>.<genexpr>)r_   ra   rb   rd   r   r   r&   r   rB   r   r#   r]   rc   r^   r`   r3   )
rL   rE   rf   rg   rh   Zlambda_symbolsrW   Z	match_resrj   rl   r   r   r   _divide_constriant  s0    
<



r   c           
      C   s   g }d}| d dkr3| dd D ]!}|d dkr1t |||||}||d  ||d 7 }|d }qnt | ||||}||d  ||d 7 }|d }dg}	|D ]}|dkr\|	| qQd|	||fS )	z
    Divides multiple constraints into smaller constraints.

    Parameters
    ==========
    s : constraint as list
    symbols : all the symbols present in the expression
    r*   r   r   r;   NrI   rJ   rZ   )r   r3   rc   )
rL   rE   rf   rg   rh   ry   rj   r(   r'   rW   r   r   r   divide_constraint  s*   	
r   c              	   C   s>   d}t || }|D ]}| |d d|d |d } q
| S )z0
    Replaces `WC(a, b)` by `WC('a', S(b))`
    z(WC\((\w+), S\(([-+]?\d)\)\))r   r?   r;   rJ   )r   rA   r0   rB   )rC   rF   rG   r(   r   r   r   r     s
   "r   c           	   
   C   s   t | d }d}d}d}t|tdkst|tdkr|jD ]k}|jD ]}t|trA||vrA|d|jd t|jd dd	7 }q$t|td
tdfvrZ|tdsZ|}d}qt|tdkrj|jd }d}qt|jd tdkr|jd }d|j	|jd |jd }d}q|||fS )z]
    Functions like `Set`, `With` and `CompoundExpression` has to be taken special care.
    r;   r*   Fr   r   z
        {} = {}r   Tr   ListCompoundExpressionr-   z
{}({}, {}))
r   r$   r   r	   r!   r   rB   r   r&   func)	Za1Lr'   rM   Z	processedZreturn_valuer(   rL   Cr   r   r   process_return_type  s,    

$&


r   c                 C   sR   g }t | tr| |vr||  |S z| jD ]	}|t||7 }qW |S    Y |S )z4
    this function extracts all `Set` functions
    )r!   r   r3   r	   extract_set)rL   r   r   r(   r   r   r   r     s   

r   c              	      s`  d}d}t | tdkst | tdkr'd}d|d }t | jd td	kr4t| jd j}n| jd g}g }| jd
d D ]	}	|t|	|7 }qC||7 }|D ]'}	t|	trm|d|	jd t	|	jd
 dd7 }qSt|	t
rz|d|	|	7 }qSt | jd
 tdkr| jd
 }
||7 }t|
jd tr|d|
jd jd |
jd jd
 7 }|dt	|
jd
 dd7 }|||fS t | jd
 tdkrl| jd
 }
t|
jdkrbt fdddd |
jD D r||7 }|dt	|
jd dd7 }ngd v r|d7 }t| r'|dd}|d|t	|
jd
 dd7 }|d7 }|d7 }n||7 }|dt	|
jd
 dd7 }|t	|
jd ddf}t||}|d rZ||d  t	|d
 f}|d7 }|d 7 }d!|}|||fS t | jd
 tdkst | jd
 tdkr| jd
 }
||7 }|t	|
ddf}t||}|d r||d  t	|d
 f}||d 7 }|dt	|d
 7 }||dfS | jd
 tdr| jd
 jd }
||7 }t|
jd tr|d|
jd jd |
jd jd
 7 }|d"| jd
 j|
jd# | jd
 jd
 7 }||dfS ||7 }|dt	| jd
 dd7 }|||fS t	| ddd|fS )$z:
    Replaces `With` and `Module by python functions`
    Nr*   r   r    z


def With{}({}):rZ   r   r   r;   z
    {} = {}Tr   z
    {} = Symbol('{}')r   z
    return {}	ConditionrJ   c                 3   s    | ]}| v V  qd S r   r   )rS   jrE   r   r   rX   $  s    zreplaceWith.<locals>.<genexpr>c                 S   s   g | ]}t |qS r   )r\   rq   r   r   r   rs   $  s    zreplaceWith.<locals>.<listcomp>rM   zI
    if isinstance(x, (int, Integer, float, Float)):
        return False
z
    z
    try:{}
        res = {}z=
    except (TypeError, AttributeError):
        return Falsez
    if res:z
    if {}:z
        return Truez
    return Falsez, CustomConstraint(With{})z
    return {}({}, {})r-   )r$   r   rB   rc   r	   r"   r   r!   r   r   r   r<   allrz   r#   r0   r   r&   r   )rL   rE   indexreturn_typeZ
with_valueZconstraintsry   r   r   r(   r   Zn_with_valueZreturn_type1r   r   r   replaceWith   s   "
&

(

"






0



(,

r   c                 C   s  d}d}d}d}g }	| D ]}
t d| |
d  |
d d d dkr0|
d d d  }n|
d d  }t|i }t| dd	}t||d
\}}tt|}|
d d dkrt	|
d d ||||	\}}}t
|
d d  \}}t|
d d  |d}nd}d}g g }}t|
d  |d}t|||||	|\}}}t|tdtdtddd}t|dd}t|}t|tdtdtddd}|| }||7 }|d7 }t|tdkst|tdkrt|||\}}}|du r.|d|7 }|dt| d | d | d | d 7 }|dt| d d t|dd d| d 7 }n|d|7 }|dt| d | d | d | | d 7 }|d|d ||d  d!| |d  7 }|dt| d d t|dd d"| d 7 }nCt|dd}|dt| d | d | d | d 7 }|d#|d ||| 7 }|dt| d d t|dd d"| d 7 }|d$|7 }q|d%7 }|d&| d' 7 }|d(d d)d* |	D  7 }|| | }||||fS )+zp
    Function which generates parsed rules by substituting all possible
    combinations of default values.
    r,   z

r*   zparsing rule {}r;   r   r   Tr|   r}   rJ   r   r~   r   r   r   r   r   r   r   Nz{}z
    patternz = Pattern(ru   z	
    rulez = ReplacementRule(r   z, With{}z)
z


def replacement{}({}):
rZ   z
    return z, replacement{}z%


def replacement{}({}):
    return zrule{}, r+   z    return r   z1    from sympy.integrals.rubi.constraints import c                 s   s    | ]}|V  qd S r   r   )rS   Zwordr   r   r   rX     s    z#downvalues_rules.<locals>.<genexpr>)r   rB   r   copyr=   rd   rH   r_   ra   r   rK   rm   r   r   r   r   r$   r   r\   rc   )rW   headerrg   rf   r   rulesr>   Z
repl_funcsrj   rh   r(   rF   rD   r   rz   Z
constriantZconstraint_defZ
FreeQ_varsZFreeQ_xZtransformedZFreeQ_constraintZfree_cons_defZWith_constraintsr   r   r   r   downvalues_rulesX  st   


  "
,40
4,2r   rubi_objectc                 C   s0  |du r#t jt jtt }tt j|d	 }|
|}i }d}d}d}tD ]
}| |t| } q-tD ]
}| |t| } q:g }	t| D ]}|d dkrX|	| qKt|	||||}
|
d  d }||
d 7 }tD ]}|t| |}|t| |}qqd|ddd d | }||fS )	a  
    Parses rules in MatchPy format.

    Parameters
    ==========
    fullform : FullForm of the rule as string.
    header : Header imports for the file. Uses default imports if None.
    module_name : name of RUBI module

    References
    ==========
    [1] http://reference.wolfram.com/language/ref/FullForm.html
    [2] http://reference.wolfram.com/language/ref/DownValues.html
    [3] https://gist.github.com/Upabjojr/bc07c49262944f9c1eb0
    Nzheader.py.txtr   r*   ZRuleDelayedr   rJ   )ospathdirnameabspathinspectZgetfileZcurrentframeopenrc   readrB   temporary_variable_replacementr0   permanent_variable_replacementr:   r3   r   r1   split)Zfullformr   Zmodule_nameZpath_headerrg   rf   r   rj   r(   r   r>   ry   r   r   r   rubi_rule_parser  s2   

 r   r   r   )Nr   )%__doc__r   r   r   Zsympyr   r   r   r   Zsympy.printingr   Zsympy.utilities.miscr   r   r   dictrw   r   r   r%   r#   r:   r=   rH   rK   rm   rd   rb   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   s   	
 !"#$%&'()*,-./012348
/
/#" XG