a
    kh&                     @   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	y   Y d S 0 |	S )Nr   )MatrixTZmark_dimensionlessc                    s   g | ]}t  |qS  )r   get_dimensional_expr).0x)unit_systemr   F/var/www/auris/lib/python3.9/site-packages/sympy/physics/units/util.py
<listcomp>       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       r   c                    s"   g | ]}| v s  |s|qS r   )addr   r    )seenr   r   r   '   r   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   )   r   z>_get_conversion_matrix_for_expr.<locals>.<listcomp>.<listcomp>r   )r   )r!   target_dims)r&   r   r   )   r   c                    s   g | ]}  |d qS r   )r%   )r   k)dim_dependenciesr   r   r   *   r   )
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$    r0   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
u 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.   r5   r   r   handle_Addsf   s    zconvert_to.<locals>.handle_Addsc                 S   s
   t | tS r2   )
isinstancer   r   r   r   r   <lambda>v   r   zconvert_to.<locals>.<lambda>c                    s   |   S r2   r3   r<   r5   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 r2   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   |   r   z>convert_to.<locals>.get_total_scale_factor.<locals>.<listcomp>)	r;   r   r   r8   r	   baseexpr   Zget_quantity_scale_factorr9   )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   r6      s   zconvert_to.<locals>.<genexpr>)sympy.physics.unitsr   get_unit_systemr;   r   r   r   r	   rA   rB   r   r   Ztogetherr   hasreplacer0   r   r7   zip)r.   r/   r   r   r:   ZdepmatZexpr_scale_factorr   )r@   r/   r   r   r4   4   s2    ,




r4   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u rtd	t|}| }|| }|j|d
d}	d}
|j D ]\}}||	kr|}
 qq|
du 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>   r   z%quantity_simplify.<locals>.<dictcomp>c                 S   s   | j S r2   )Z	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      r   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%   r4   )r.   rK   r   rE   dr)   vr!   Zdim_exprZdim_depsZtarget_dimensionZds_dimZds_dim_depsZtarget_unitr   rP   r   quantity_simplify   s:    
"


rZ   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rt||}|tr||||}qr|jrrd}
 qqr|	|  |
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   sP   i | |}|  D ](\}}|| v r||v 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      r   z5check_dimensions.<locals>.addDict.<locals>.<dictcomp>)rW   )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 r2   )r;   r   r#   r   r   r   r6     r   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   rR   r   r+   r   r,   r8   r_   r"   r   Z	make_argsrH   r   r   r   Zfree_symbolsextendrW   tuplesortedr   rT   rV   formatanyfuncrS   )r.   r   r   r^   ZaddsZDIM_OFaZdesetZaidimsskipZdimdictr    Zrepsmr   r   r   check_dimensions   sH    

	






rj   )r1   )FN)r1   ))__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   r0   r4   boolrZ   rj   r   r   r   r   <module>   s*   
YD