U
    ZÊ¹j &  ã                   @   s  d Z ddlmZ ddlmZ ddlmZ ddlmZ ddl	m
Z
 ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZ ddlmZmZ ddlmZ ddlmZ ddl m!Z! ddl"m#Z# dd„ Z$ddd„Z%d e&dœdd„Z'd!dd„Z(dS )"zA
Several methods to simplify expressions involving unit objects.
é    )Úreduce)ÚIterable)ÚOptional)Údefault_sort_key)ÚAdd)ÚTuple)ÚMul)ÚPow)Úordered)Úsympify)ÚFunction)ÚNonInvertibleMatrixError)Ú	DimensionÚDimensionSystem)ÚPrefix)ÚQuantity©Ú
UnitSystem)Úsiftc           
         sÞ   ddl m} ˆ ¡ ‰tˆ | ¡ƒ}ˆj|dd�‰ ‡fdd„|D ƒ‰‡fdd„ˆD ƒ}tˆ ƒ}| t|ƒ¡snd S tƒ ‰‡fdd„|D ƒ}|‡‡fd	d„|D ƒƒ}|‡ fd
d„|D ƒƒ}z| |¡}	W n t	k
rØ   Y d S X |	S )Nr   )ÚMatrixT©Zmark_dimensionlessc                    s   g | ]}t ˆ  |¡ƒ‘qS © )r   Úget_dimensional_expr)Ú.0Úx)Úunit_systemr   úW/var/www/html/bwave/python/venv/lib/python3.8/site-packages/sympy/physics/units/util.pyÚ
<listcomp>   s     z3_get_conversion_matrix_for_expr.<locals>.<listcomp>c                    s$   g | ]}ˆ j |d d�D ]}|‘qqS )Tr   )Úget_dimensional_dependencies)r   r   Úi)Údimension_systemr   r   r       s       c                    s"   g | ]}|ˆ ksˆ   |¡s|‘qS r   )Úadd©r   r   )Úseenr   r   r   '   s      
 c                    s    g | ]‰ ‡‡ fd d„ˆD ƒ‘qS )c                    s"   g | ]}ˆ j |d d� ˆd¡‘qS )Tr   r   )r   Úgetr"   )r    Újr   r   r   )   s     z>_get_conversion_matrix_for_expr.<locals>.<listcomp>.<listcomp>r   )r   )r    Útarget_dims)r%   r   r   )   s     c                    s   g | ]}ˆ   |d ¡‘qS ©r   )r$   )r   Úk)Údim_dependenciesr   r   r   *   s     )
Zsympy.matrices.denser   Úget_dimension_systemr   r   r   ÚsetÚissubsetZsolver   )
ÚexprÚtarget_unitsr   r   Zexpr_dimZcanon_dim_unitsZcanon_expr_unitsZcamatZexprmatZres_exponentsr   )r)   r    r#   r&   r   r   Ú_get_conversion_matrix_for_expr   s$    r/   ÚSIc                    s  ddl m} | ˆ¡‰tˆttfƒs*ˆg‰‡‡fdd„}t| tƒrJ|| ƒS t| tƒrpt| jtƒrp|| jƒ| j	 S t
| ƒ} t
ˆƒ‰t| tƒr’|  ¡ } t| tƒsÀ|  t¡rÀ|  dd„ ‡‡fdd„¡} ‡ ‡fdd	„‰ t| ˆˆƒ}|d
kræ| S ˆ | ƒ}|t ‡ fdd„tˆ|ƒD ƒ¡ S )aÜ  
    Convert ``expr`` to the same expression with all of its units and quantities
    represented as factors of ``target_units``, whenever the dimension is compatible.

    ``target_units`` may be a single unit/quantity, or a collection of
    units/quantities.

    Examples
    ========

    >>> from sympy.physics.units import speed_of_light, meter, gram, second, day
    >>> from sympy.physics.units import mile, newton, kilogram, atomic_mass_constant
    >>> from sympy.physics.units import kilometer, centimeter
    >>> from sympy.physics.units import gravitational_constant, hbar
    >>> from sympy.physics.units import convert_to
    >>> convert_to(mile, kilometer)
    25146*kilometer/15625
    >>> convert_to(mile, kilometer).n()
    1.609344*kilometer
    >>> convert_to(speed_of_light, meter/second)
    299792458*meter/second
    >>> convert_to(day, second)
    86400*second
    >>> 3*newton
    3*newton
    >>> convert_to(3*newton, kilogram*meter/second**2)
    3*kilogram*meter/second**2
    >>> convert_to(atomic_mass_constant, gram)
    1.660539060e-24*gram

    Conversion to multiple units:

    >>> convert_to(speed_of_light, [meter, second])
    299792458*meter/second
    >>> convert_to(3*newton, [centimeter, gram, second])
    300000*centimeter*gram/second**2

    Conversion to Planck units:

    >>> convert_to(atomic_mass_constant, [gravitational_constant, speed_of_light, hbar]).n()
    7.62963087839509e-20*hbar**0.5*speed_of_light**0.5/gravitational_constant**0.5

    r   r   c                    s   t  ‡ ‡fdd„| jD ƒ¡S )Nc                 3   s   | ]}t |ˆ ˆƒV  qd S ©N©Ú
convert_tor"   ©r.   r   r   r   Ú	<genexpr>g   s   ÿz2convert_to.<locals>.handle_Adds.<locals>.<genexpr>)r   ÚfromiterÚargs©r-   r4   r   r   Úhandle_Addsf   s    ÿzconvert_to.<locals>.handle_Addsc                 S   s
   t | tƒS r1   )Ú
isinstancer   ©r   r   r   r   Ú<lambda>v   ó    zconvert_to.<locals>.<lambda>c                    s   |   ˆ ˆ¡S r1   r2   r;   r4   r   r   r<   w   r=   c                    sZ   t | tƒr(tdd„ ‡ fdd„| jD ƒƒS t | tƒrBˆ | jƒ| j S t | tƒrVˆ | ¡S | S )Nc                 S   s   | | S r1   r   )r   Úyr   r   r   r<   {   r=   z<convert_to.<locals>.get_total_scale_factor.<locals>.<lambda>c                    s   g | ]}ˆ |ƒ‘qS r   r   r"   ©Úget_total_scale_factorr   r   r   |   s     z>convert_to.<locals>.get_total_scale_factor.<locals>.<listcomp>)	r:   r   r   r7   r	   ÚbaseÚexpr   Zget_quantity_scale_factorr8   )r@   r   r   r   r@   y   s    
ÿ


z*convert_to.<locals>.get_total_scale_factorNc                 3   s&   | ]\}}d ˆ |ƒ | | V  qdS )é   Nr   )r   ÚuÚpr?   r   r   r5   ˆ   s    zconvert_to.<locals>.<genexpr>)Úsympy.physics.unitsr   Úget_unit_systemr:   r   r   r   r	   rA   rB   r   r   Ztogetherr   ÚhasÚreplacer/   r   r6   Úzip)r-   r.   r   r   r9   ZdepmatZexpr_scale_factorr   )r@   r.   r   r   r3   4   s2    ,



ÿ
þr3   FN)Úacross_dimensionsc                    s@  | j s|  tt¡s| S |  t¡}|  dd„ |D ƒ¡} t|  t¡dd„ ƒ}|D ]X}t|| ƒdkrbqLtt	|| ƒƒ}|d |d j
 ‰ |  ‡ fdd„|dd… D ƒ¡} qL|�r<|dkr¼td	ƒ‚t |¡}| ¡ }| | ¡}|j|d
d�}	d}
|j ¡ D ]\}}||	krô|}
 �qqô|
dk�r| S |j |
¡}|�r<t| ||ƒ} | S )aû  Return an equivalent expression in which prefixes are replaced
    with numerical values and all units of a given dimension are the
    unified in a canonical manner by default. `across_dimensions` allows
    for units of different dimensions to be simplified together.

    `unit_system` must be specified if `across_dimensions` is True.

    Examples
    ========

    >>> from sympy.physics.units.util import quantity_simplify
    >>> from sympy.physics.units.prefixes import kilo
    >>> from sympy.physics.units import foot, inch, joule, coulomb
    >>> quantity_simplify(kilo*foot*inch)
    250*foot**2/3
    >>> quantity_simplify(foot - 6*inch)
    foot/2
    >>> quantity_simplify(5*joule/coulomb, across_dimensions=True, unit_system="SI")
    5*volt
    c                 S   s   i | ]}||j “qS r   ©Úscale_factor)r   rE   r   r   r   Ú
<dictcomp>¨   s      z%quantity_simplify.<locals>.<dictcomp>c                 S   s   | j S r1   )Ú	dimension)r   r   r   r   r<   ¬   r=   z#quantity_simplify.<locals>.<lambda>rC   r   c                    s   i | ]}|ˆ |j  “qS r   rL   )r   Úvi©Úrefr   r   rN   ²   s      Nz:unit_system must be specified if across_dimensions is TrueTr   )Zis_AtomrH   r   r   ÚatomsÚxreplacer   ÚlenÚlistr
   rM   Ú
ValueErrorr   rG   r*   r   r   Zdimensional_dependenciesÚitemsZderived_unitsr$   r3   )r-   rK   r   rE   Údr(   Úvr    Zdim_exprZdim_depsZtarget_dimensionZds_dimZds_dim_depsZtarget_unitr   rQ   r   Úquantity_simplify�   s:    
"


r[   c              	   C   sN  ddl m} | |¡}dd„ }|  t¡}| ¡ j}|D ]Æ}tƒ }|jD ]´}|j	r\| 
d¡ qFg }	d}
i }t |¡D ]D}| t¡rŽt| |¡ƒ}| t¡r¨||||ƒƒ}qr|jrrd}
 q¸qr|	 | ¡ ¡ |
sF| 
tt|	td�ƒ¡ t|ƒd	krFtd
 |¡ƒ‚qFq6i }|  t¡D ]6}tdd„ |jD ƒƒ�r|jdd„ |jD ƒŽ ||< �q|  |¡S )z[Return expr if units in addends have the same
    base dimensions, else raise a ValueError.r   r   c                 S   sL   | |–}|  ¡ D ](\}}|| kr||kr|| |  ||< qdd„ |  ¡ D ƒS )z]Merge dictionaries by adding values of common keys and
        removing keys with value of 0.c                 S   s   i | ]\}}|d kr||“qS r'   r   )r   ÚkeyÚvalr   r   r   rN   å   s       z5check_dimensions.<locals>.addDict.<locals>.<dictcomp>)rX   )Zdict1Zdict2Zdict3r\   Úvaluer   r   r   ÚaddDictÞ   s
    z!check_dimensions.<locals>.addDictr   FT)r\   rC   z(addends have incompatible dimensions: {}c                 s   s   | ]}t |tƒV  qd S r1   )r:   r   r"   r   r   r   r5     s     z#check_dimensions.<locals>.<genexpr>c                 S   s   g | ]}|j s|‘qS r   )Ú	is_numberr"   r   r   r   r     s     z$check_dimensions.<locals>.<listcomp>)rF   r   rG   rS   r   r*   r   r+   r7   r`   r!   r   Z	make_argsrH   r   r   r   Zfree_symbolsÚextendrX   ÚtupleÚsortedr   rU   rW   ÚformatÚanyÚfuncrT   )r-   r   r   r_   ZaddsZDIM_OFÚaZdesetZaiZdimsÚskipZdimdictr   ZrepsÚmr   r   r   Úcheck_dimensionsÑ   sH    

	





ÿ
ÿrj   )r0   )FN)r0   ))Ú__doc__Ú	functoolsr   Úcollections.abcr   Útypingr   Zsympyr   Zsympy.core.addr   Zsympy.core.containersr   Zsympy.core.mulr   Zsympy.core.powerr	   Zsympy.core.sortingr
   Zsympy.core.sympifyr   Zsympy.core.functionr   Zsympy.matrices.exceptionsr   Zsympy.physics.units.dimensionsr   r   Zsympy.physics.units.prefixesr   Zsympy.physics.units.quantitiesr   Zsympy.physics.units.unitsystemr   Zsympy.utilities.iterablesr   r/   r3   Úboolr[   rj   r   r   r   r   Ú<module>   s*   
YD