B
    [ศ  ใ               @   s|   d Z ddlmZmZ ddlmZ ddlmZ efddZdd	 Z	efd
dZ
dd Zdd Zdd ZefddZdd ZdS )zP Generic Rules for SymPy

This file assumes knowledge of Basic and little else.
้    )ฺprint_functionฺdivision)ฺsift้   )ฺnewc                s    fdd}|S )a   Create a rule to remove identities

    isid - fn :: x -> Bool  --- whether or not this element is an identity

    >>> from sympy.strategies import rm_id
    >>> from sympy import Basic
    >>> remove_zeros = rm_id(lambda x: x==0)
    >>> remove_zeros(Basic(1, 0, 2))
    Basic(1, 2)
    >>> remove_zeros(Basic(0, 0)) # If only identites then we keep one
    Basic(0)

    See Also:
        unpack
    c                sh   t t | j}t|dkr | S t|t|krR| jfdd t| j|D  S | j| jd S dS )z Remove identities r   c             S   s   g | ]\}}|s|qS ฉ r   )ฺ.0ฺargฺxr   r   ๚2lib/python3.7/site-packages/sympy/strategies/rl.py๚
<listcomp>#   s    z/rm_id.<locals>.ident_remove.<locals>.<listcomp>N)ฺlistฺmapฺargsฺsumฺlenฺ	__class__ฺzip)ฺexprZids)ฺisidr   r   r   ฺident_remove   s    zrm_id.<locals>.ident_remover   )r   r   r   r   )r   r   r   ฺrm_id   s    r   c                s    fdd}|S )a   Create a rule to conglomerate identical args

    >>> from sympy.strategies import glom
    >>> from sympy import Add
    >>> from sympy.abc import x

    >>> key     = lambda x: x.as_coeff_Mul()[1]
    >>> count   = lambda x: x.as_coeff_Mul()[0]
    >>> combine = lambda cnt, arg: cnt * arg
    >>> rl = glom(key, count, combine)

    >>> rl(Add(x, -x, 3*x, 2, 3, evaluate=False))
    3*x + 5

    Wait, how are key, count and combine supposed to work?

    >>> key(2*x)
    x
    >>> count(2*x)
    2
    >>> combine(2, x)
    2*x
    c                sh   t | j}tfdd| ก D } fdd| ก D }t|t| jkr`tt| f| S | S dS )z2 Conglomerate together identical args x + x -> 2x c             3   s$   | ]\}}|t t |fV  qd S )N)r   r   )r   ฺkr   )ฺcountr   r   ๚	<genexpr>D   s    z-glom.<locals>.conglomerate.<locals>.<genexpr>c                s   g | ]\}} ||qS r   r   )r   ZmatZcnt)ฺcombiner   r   r   E   s    z.glom.<locals>.conglomerate.<locals>.<listcomp>N)r   r   ฺdictฺitemsฺsetr   ฺtype)r   ฺgroupsZcountsZnewargs)r   r   ฺkeyr   r   ฺconglomerateA   s    zglom.<locals>.conglomerater   )r!   r   r   r"   r   )r   r   r!   r   ฺglom)   s    
r#   c                s    fdd}|S )zว Create a rule to sort by a key function

    >>> from sympy.strategies import sort
    >>> from sympy import Basic
    >>> sort_rl = sort(str)
    >>> sort_rl(Basic(3, 1, 2))
    Basic(1, 2, 3)
    c                s   | j ft| j d S )N)r!   )r   ฺsortedr   )r   )r!   r   r   r   ฺsort_rlW   s    zsort.<locals>.sort_rlr   )r!   r   r%   r   )r!   r   r   ฺsortM   s    
r&   c                s    fdd}|S )aW   Turns an A containing Bs into a B of As

    where A, B are container types

    >>> from sympy.strategies import distribute
    >>> from sympy import Add, Mul, symbols
    >>> x, y = symbols('x,y')
    >>> dist = distribute(Mul, Add)
    >>> expr = Mul(2, x+y, evaluate=False)
    >>> expr
    2*(x + y)
    >>> dist(expr)
    2*x + 2*y
    c                sp   xjt | jD ]\\}}t|r| jd | | j| | j|d d     } fdd|jD  S qW | S )Nr   c                s   g | ]} |f   qS r   r   )r   r	   )ฺAฺfirstฺtailr   r   r   o   s    z5distribute.<locals>.distribute_rl.<locals>.<listcomp>)ฺ	enumerater   ฺ
isinstance)r   ฺir	   ฺb)r'   ฺB)r(   r)   r   ฺdistribute_rlk   s
    
. z!distribute.<locals>.distribute_rlr   )r'   r.   r/   r   )r'   r.   r   ฺ
distribute[   s    r0   c                s    fdd}|S )z Replace expressions exactly c                s   |  krS | S d S )Nr   )r   )ฺar-   r   r   ฺsubs_rlu   s    zsubs.<locals>.subs_rlr   )r1   r-   r2   r   )r1   r-   r   ฺsubss   s    r3   c             C   s    t | jdkr| jd S | S dS )z Rule to unpack singleton args

    >>> from sympy.strategies import unpack
    >>> from sympy import Basic
    >>> unpack(Basic(2))
    2
    r   r   N)r   r   )r   r   r   r   ฺunpack~   s    
r4   c             C   sL   | j }g }x0| jD ]&}|j |kr.| |jก q| |ก qW || j f| S )z9 Flatten T(a, b, T(c, d), T2(e)) to T(a, b, c, d, T2(e)) )r   r   ฺextendฺappend)r   r   ฺclsr   r	   r   r   r   ฺflatten   s    
r8   c             C   s2   yt | ttt| j S  tk
r,   | S X dS )zล Rebuild a SymPy tree

    This function recursively calls constructors in the expression tree.
    This forces canonicalization and removes ugliness introduced by the use of
    Basic.__new__
    N)r   r   r   ฺrebuildr   ฺ	Exception)r   r   r   r   r9      s    r9   N)ฺ__doc__Z
__future__r   r   Zsympy.utilities.iterablesr   ฺutilr   r   r#   r&   r0   r3   r4   r8   r9   r   r   r   r   ฺ<module>   s   $