U
    d                     @   st  U d dl mZmZmZmZmZmZmZmZm	Z	 d dl
mZ eZeZeegeeef f Zeeegef ZG dd deZi Zeee ef ed< eeedddd	Zeeef eee ef d
ddZee eeeef dddZee eee ef d
ddZee eee dddZeedf eee ef d
ddZee eeedf dddZeeee ef d
ddZee eedddZeeee eeee eeee eeee eedddZ eedd d!Z!eedd"d#Z"G d$d% d%Z#G d&d' d'e#Z$eeee e#f dd(d)Z%ee e#ed*d+d,Z&eeed-d.d/Z'ee#e	ee  d0d1d2Z(dS )3    )	
NamedTupleCallableAnyTupleListDictTypecastOptional)
namedtuplec                   @   s   e Zd ZU eed< eed< dS )NodeDef
flatten_fnunflatten_fnN)__name__
__module____qualname__FlattenFunc__annotations__UnflattenFunc r   r   7/tmp/pip-unpacked-wheel-ua33x9lu/torch/utils/_pytree.pyr   !   s   
r   SUPPORTED_NODESN)typr   r   returnc                 C   s   t ||t| < d S N)r   r   )r   r   r   r   r   r   _register_pytree_node'   s    r   )dr   c                 C   s   t |  t |  fS r   )listvalueskeysr   r   r   r   _dict_flatten*   s    r!   )r   contextr   c                 C   s   dd t || D S )Nc                 S   s   i | ]\}}||qS r   r   ).0keyvaluer   r   r   
<dictcomp>.   s      z#_dict_unflatten.<locals>.<dictcomp>)zipr   r"   r   r   r   _dict_unflatten-   s    r)   c                 C   s   | d fS r   r   r    r   r   r   _list_flatten0   s    r*   c                 C   s   t | S r   r   r(   r   r   r   _list_unflatten3   s    r,   .c                 C   s   t | d fS r   r+   r    r   r   r   _tuple_flatten6   s    r-   c                 C   s   t | S r   )tupler(   r   r   r   _tuple_unflatten9   s    r/   c                 C   s   t | t| fS r   )r   typer    r   r   r   _namedtuple_flatten<   s    r1   c                 C   s   t t||  S r   )r	   r   r(   r   r   r   _namedtuple_unflatten?   s    r2   )pytreer   c                 C   sV   t | }|j}t|dks&|d tkr*dS t|dd }t|tsDdS tdd |D S )N   r   F_fieldsc                 s   s   | ]}t |tkV  qd S r   )r0   str)r#   entryr   r   r   	<genexpr>Q   s     z*_is_namedtuple_instance.<locals>.<genexpr>)r0   	__bases__lenr.   getattr
isinstanceall)r3   r   basesfieldsr   r   r   _is_namedtuple_instanceI   s    
r@   c                 C   s   t | rtS t| S r   )r@   r   r0   r3   r   r   r   _get_node_typeS   s    rB   c                 C   s   t | t kS r   )rB   r   r   rA   r   r   r   _is_leafY   s    rC   c                   @   sR   e Zd Zeeed  ddddZedddZee	dd	d
Z
ee	dddZdS )TreeSpecN)r   r"   children_specsr   c                 C   s*   || _ || _|| _tdd |D | _d S )Nc                 S   s   g | ]
}|j qS r   )
num_leaves)r#   specr   r   r   
<listcomp>g   s     z%TreeSpec.__init__.<locals>.<listcomp>)r0   r"   rE   sumrF   )selfr   r"   rE   r   r   r   __init__c   s    zTreeSpec.__init__r   c                 C   s    d| j j d| j d| j dS )Nz	TreeSpec(z, ))r0   r   r"   rE   rJ   r   r   r   __repr__i   s    zTreeSpec.__repr__)otherr   c                 C   s:   | j |j ko.| j|jko.| j|jko.| j|jk}tt|S r   )r0   r"   rE   rF   r	   bool)rJ   rP   resultr   r   r   __eq__l   s    

zTreeSpec.__eq__c                 C   s   |  | S r   )rS   )rJ   rP   r   r   r   __ne__s   s    zTreeSpec.__ne__)r   r   r   r   Contextr   rK   r6   rO   rQ   rS   rT   r   r   r   r   rD   b   s   rD   c                       s0   e Zd Zdd fddZedddZ  ZS )LeafSpecNrL   c                    s   t  d d g  d| _d S )Nr4   )superrK   rF   rN   	__class__r   r   rK   w   s    zLeafSpec.__init__c                 C   s   dS )N*r   rN   r   r   r   rO   {   s    zLeafSpec.__repr__)r   r   r   rK   r6   rO   __classcell__r   r   rX   r   rV   v   s   rV   c           
      C   sr   t | r| gt fS t| }t| j}|| \}}g }g }|D ]"}t|\}}	||7 }||	 q>|t|||fS )zkFlattens a pytree into a list of values and a TreeSpec that can be used
    to reconstruct the pytree.
    )rC   rV   rB   r   r   tree_flattenappendrD   )
r3   	node_typer   child_pytreesr"   rR   rE   childflat
child_specr   r   r   r\   ~   s    
r\   )r   rG   r   c                 C   s   t |tstdt| dt| |jkrNtdt|  d|j d| dt |tr`| d S t|j j}d}d}g }|j	D ]*}||j7 }|
t| || | |}q~|||jS )zqGiven a list of values and a TreeSpec, builds a pytree.
    This is the inverse operation of `tree_flatten`.
    z^tree_unflatten(values, spec): Expected `spec` to be instance of TreeSpec but got item of type .z2tree_unflatten(values, spec): `values` has length z, but the spec refers to a pytree that holds z items (z).r   )r<   rD   
ValueErrorr0   r:   rF   rV   r   r   rE   r]   tree_unflattenr"   )r   rG   r   startendr_   rb   r   r   r   re      s&    



re   )fnr3   r   c                    s$   t |\}}t fdd|D |S )Nc                    s   g | ]} |qS r   r   )r#   irh   r   r   rH      s     ztree_map.<locals>.<listcomp>)r\   re   )rh   r3   Z	flat_argsrG   r   rj   r   tree_map   s    rk   )r3   rG   r   c           
      C   s   t |tstt| r"| g|j S t |tr0d S t| }||jkrFd S t| j	}|| \}}t
|t
|jksx||jkr|d S g }t||jD ]*\}}t||}	|	d k	r||	7 }q d S q|S r   )r<   rD   AssertionErrorrC   rF   rV   rB   r0   r   r   r:   rE   r"   r'   _broadcast_to_and_flatten)
r3   rG   r^   r   r_   ctxrR   r`   rb   ra   r   r   r   rm      s&    




rm   ))typingr   r   r   r   r   r   r   r	   r
   collectionsr   rU   ZPyTreer   r   r   r   r   r   r!   r)   r*   r,   r-   r/   r1   r2   dictr   r.   rQ   r@   rB   rC   rD   rV   r\   re   rk   rm   r   r   r   r   <module>   s<    ,$ $
	