o
    8Va=                     @   s   d Z ddlmZ ddlmZ ddlmZmZmZ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	lmZ dd
lmZ dd ZdddZdd ZdddZdS )zA
Several methods to simplify expressions involving unit objects.
    )reduce)Iterable)AddMulPowTuplesympify)ordered)NonInvertibleMatrixError)	Dimension)Prefix)Quantity)siftc           
         s   ddl m}  t| }j|dd fdd|D fddD }dd	  D }|t|s:d S t fd
d|D }|fdd|D }| fdd|D }z||}	W |	S  t	yo   Y d S w )Nr   )MatrixTZmark_dimensionlessc                    s   g | ]	}t  |qS  )r   get_dimensional_expr).0x)unit_systemr   :/usr/lib/python3/dist-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   s   h | ]}|qS r   r   r   r   r   r   r   	<setcomp>   s    z2_get_conversion_matrix_for_expr.<locals>.<setcomp>c                    s"   g | ]}| v s  |s|qS r   )addr   )seenr   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   !   s     c                    s   g | ]}  |d qS r   )r    )r   k)dim_dependenciesr   r   r   "       )
sympyr   get_dimension_systemr   r   r   issubsetsetZ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t| tr(tfdd| jD S t	| } t| t
sC| t
rC| dd fdd}  fdd	 t| }|d
u rV| 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   
UnitSystemc                 3   s    | ]	}t | V  qd S N
convert_tor   r,   r   r   r   	<genexpr>_   s    zconvert_to.<locals>.<genexpr>c                 S   s
   t | tS r1   )
isinstancer   r   r   r   r   <lambda>d   s   
 zconvert_to.<locals>.<lambda>c                    s   |   S r1   r2   r7   r4   r   r   r8   d   s    c                    sZ   t | trtdd  fdd| jD S t | tr! | j| j S t | tr+| S | S )Nc                 S   s   | | S r1   r   )r   yr   r   r   r8   h   s    z<convert_to.<locals>.get_total_scale_factor.<locals>.<lambda>c                    s   g | ]} |qS r   r   r   get_total_scale_factorr   r   r   h       z>convert_to.<locals>.get_total_scale_factor.<locals>.<listcomp>)	r6   r   r   argsr   baseZexpr   Zget_quantity_scale_factor)r+   )r;   r   r   r   r;   f   s   



z*convert_to.<locals>.get_total_scale_factorNc                 3   s(    | ]\}}d  | | | V  qdS )   Nr   )r   upr:   r   r   r5   t   s   & )sympy.physics.unitsr0   get_unit_systemr6   r   r   r   Zfromiterr=   r   r   hasreplacer-   r   zip)r+   r,   r   r0   ZdepmatZexpr_scale_factorr   )r;   r,   r   r   r3   ,   s   ,

	"r3   c                    s   | j s	| tts| S | t}| dd |D } t| tdd }|D ],}t|| dkr1q&tt	|| }|d |d j
  |  fdd|dd D } q&| 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.

    Examples
    ========

    >>> from sympy.physics.units.util import quantity_simplify
    >>> from sympy.physics.units.prefixes import kilo
    >>> from sympy.physics.units import foot, inch
    >>> quantity_simplify(kilo*foot*inch)
    250*foot**2/3
    >>> quantity_simplify(foot - 6*inch)
    foot/2
    c                 S   s   i | ]}||j qS r   scale_factor)r   rA   r   r   r   
<dictcomp>   r<   z%quantity_simplify.<locals>.<dictcomp>c                 S   s   | j S r1   )Z	dimension)r   r   r   r   r8      s    z#quantity_simplify.<locals>.<lambda>r?   r   c                    s   i | ]}| |j  qS r   rG   )r   virefr   r   rI      r&   N)Zis_AtomrD   r   r   atomsxreplacer   lenlistr	   rH   )r+   rA   dr$   vr   rK   r   quantity_simplifyw   s   
"rS   c                 C   sF  ddl m} ||}dd }| t}| j}|D ]a}t }|jD ]X}|j	r.|
d q#g }	d}
i }t|D ]"}|trGt||}|trT||||}q9|jr[d}
 nq9|	|  |
s{|
tt|	 t|dkr{td	|q#qi }| tD ]}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   rI      s    z5check_dimensions.<locals>.addDict.<locals>.<dictcomp>)items)Zdict1Zdict2Zdict3rT   valuer   r   r   addDict   s   z!check_dimensions.<locals>.addDictr   FTr?   z(addends have incompatible dimensions: {}c                 s   s    | ]}t |tV  qd S r1   )r6   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>)rB   r0   rC   rM   r   r(   r   r*   r=   rY   r   r   Z	make_argsrD   r   r   r   Zfree_symbolsextendrV   tuplesortedrO   
ValueErrorformatanyfuncrN   )r+   r   r0   rX   ZaddsZDIM_OFaZdesetZaiZdimsskipZdimdictr   Zrepsmr   r   r   check_dimensions   sP   


	






rd   N)r.   )__doc__	functoolsr   Zcollections.abcr   r'   r   r   r   r   r   Zsympy.core.compatibilityr	   Zsympy.matrices.commonr
   Zsympy.physics.units.dimensionsr   Zsympy.physics.units.prefixesr   Zsympy.physics.units.quantitiesr   Zsympy.utilities.iterablesr   r-   r3   rS   rd   r   r   r   r   <module>   s    
K%