
    0VhH*                       U d Z ddlmZ ddlZddlZddl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mZ dd	lmZ dd
lmZ ddlmZmZ ddlmZmZ ddlm Z m!Z! g dZ" ede      Z#de$d<    ede      Z%de$d<    G d d      Z& ejN                  e(      5  ddl)m&Z& ddd       	 dddd	 	 	 	 	 	 	 	 	 ddZ*e*Z+	 	 	 	 	 	 	 	 d dZ,	 	 	 	 d!dZ-d"dZ.	 	 	 	 	 	 	 	 d#dZ/	 	 	 	 	 	 	 	 	 	 	 	 d$dZ0y# 1 sw Y   SxY w)%zIntegration with JAX.    )annotationsN)
itemgetter)FunctionType)AnyCallable)	TypeAlias)Arraylax)dtypes)	ArrayLike)tree_flattentree_unflatten)
PyTreeSpecPyTreeTypeVar)safe_ziptotal_order_sorted)ArrayLikeTree	ArrayTree
tree_ravelr   r   r   c                  P    e Zd ZU dZded<   ded<   ded<   ddZdd	Zdd
ZddZy)HashablePartialz1A hashable version of :class:`functools.partial`.r   funcztuple[Any, ...]argszdict[str, Any]kwargsc               6   t        |      st        d|d      t        |t              r;|j                  | _        |j
                  |z   | _        i |j                  || _        yt        |t              r|| _        || _        || _        yt        d|d      )z.Construct a :class:`HashablePartial` instance.zExpected a callable, got .zExpected a function, got N)callable	TypeError
isinstancer   r   r   r   r   )selfr   r   r   s       G/home/dcms/DCMS/lib/python3.12/site-packages/optree/integrations/jax.py__init__zHashablePartial.__init__G   s    ~7xqABBdO,		DI		D(DI3T[[3F3DKl+DIDI DK7xqABB    c                   t        |      t        u xr` | j                  j                  |j                  j                  k(  xr1 | j                  | j
                  f|j                  |j
                  fk(  S N)typer   r   __code__r   r   )r    others     r!   __eq__zHashablePartial.__eq__W   s]    K?* G		""ejj&9&99GDKK(UZZ,FF	
r#   c                   t        | j                  j                  | j                  t	        t        | j                  j                         t        d                  f      S )Nr   )key)	hashr   r'   r   tupler   r   itemsr   )r    s    r!   __hash__zHashablePartial.__hash__^   sI    		""		():):)<*Q-PQ
 	
r#   c               d    i | j                   |} | j                  g | j                  |i |S r%   )r   r   r   )r    r   r   s      r!   __call__zHashablePartial.__call__g   s7    *DKK*6*tyy5$))5d5f55r#   N)r   zFunctionType | HashablePartialr   r   r   r   returnNone)r(   objectr2   bool)r2   int)r   r   r   r   r2   r   )	__name__
__module____qualname____doc____annotations__r"   r)   r/   r1    r#   r!   r   r   @   s,    ;

C 

6r#   r   )r   F )none_is_leaf	namespacec              h    t        | |||      \  }}t        |      \  }}|t        t        ||      fS )a/  Ravel (flatten) a pytree of arrays down to a 1D array.

    >>> tree = {
    ...     'layer1': {
    ...         'weight': jnp.arange(0, 6, dtype=jnp.float32).reshape((2, 3)),
    ...         'bias': jnp.arange(6, 8, dtype=jnp.float32).reshape((2,)),
    ...     },
    ...     'layer2': {
    ...         'weight': jnp.arange(8, 10, dtype=jnp.float32).reshape((1, 2)),
    ...         'bias': jnp.arange(10, 11, dtype=jnp.float32).reshape((1,)),
    ...     },
    ... }
    >>> tree  # doctest: +IGNORE_WHITESPACE
    {
        'layer1': {
            'weight': Array([[0., 1., 2.],
                             [3., 4., 5.]], dtype=float32),
            'bias': Array([6., 7.], dtype=float32)
        },
        'layer2': {
            'weight': Array([[8., 9.]], dtype=float32),
            'bias': Array([10.], dtype=float32)
        }
    }
    >>> flat, unravel_func = tree_ravel(tree)
    >>> flat
    Array([ 6.,  7.,  0.,  1.,  2.,  3.,  4.,  5., 10.,  8.,  9.], dtype=float32)
    >>> unravel_func(flat)  # doctest: +IGNORE_WHITESPACE
    {
        'layer1': {
            'weight': Array([[0., 1., 2.],
                             [3., 4., 5.]], dtype=float32),
            'bias': Array([6., 7.], dtype=float32)
        },
        'layer2': {
            'weight': Array([[8., 9.]], dtype=float32),
            'bias': Array([10.], dtype=float32)
        }
    }

    Args:
        tree (pytree): a pytree of arrays and scalars to ravel.
        is_leaf (callable, optional): An optionally specified function that will be called at each
            flattening step. It should return a boolean, with :data:`True` stopping the traversal
            and the whole subtree being treated as a leaf, and :data:`False` indicating the
            flattening should traverse the current object.
        none_is_leaf (bool, optional): Whether to treat :data:`None` as a leaf. If :data:`False`,
            :data:`None` is a non-leaf node with arity 0. Thus :data:`None` is contained in the
            treespec rather than in the leaves list and :data:`None` will be remain in the result
            pytree. (default: :data:`False`)
        namespace (str, optional): The registry namespace used for custom pytree node types.
            (default: :const:`''`, i.e., the global namespace)

    Returns:
        A pair ``(array, unravel_func)`` where the first element is a 1D array representing the
        flattened and concatenated leaf values, with ``dtype`` determined by promoting the
        ``dtype``\s of leaf values, and the second element is a callable for unflattening a 1D array
        of the same length back to a pytree of the same structure as the input ``tree``. If the
        input pytree is empty (i.e. has no leaves) then as a convention a 1D empty array of the
        default dtype is returned in the first component of the output.
    )is_leafr>   r?   )r   _ravel_leavesr   _tree_unravel)treerA   r>   r?   leavestreespecflatunravel_flats           r!   r   r   q   sE    J $!	FH 'v.D,,GGGr#   c               &    t        |  ||            S r%   )r   )rF   rH   rG   s      r!   rC   rC      s     (L$677r#   c                  | st        j                  d      t        fS t        d | D              }t	        j
                  | t        d | D              }t        d | D              }t        t        j                  |            }t        fd|D              rIt        j                  | D cg c]  }t        j                  |       c}      }|t        t        ||      fS t        j                  | D cg c]+  }t        j                  t        j                  |            - c}      }|t        t        |||      fS c c}w c c}w )Nr   c              3  F   K   | ]  }t        j                  |        y wr%   )r   dtype.0leafs     r!   	<genexpr>z _ravel_leaves.<locals>.<genexpr>   s     >tT*>   !c              3  F   K   | ]  }t        j                  |        y wr%   )jnpsizerM   s     r!   rP   z _ravel_leaves.<locals>.<genexpr>   s     4T#((4.4rQ   c              3  F   K   | ]  }t        j                  |        y wr%   )rS   shaperM   s     r!   rP   z _ravel_leaves.<locals>.<genexpr>   s     6t399T?6rQ   c              3  (   K   | ]	  }|k(    y wr%   r<   )rN   dtto_dtypes     r!   rP   z _ravel_leaves.<locals>.<genexpr>   s     
0b2>
0s   )rS   zeros_unravel_emptyr-   r   result_type	itertools
accumulateallconcatenateravelr   _unravel_leaves_single_dtyper
   convert_element_type_unravel_leaves)rE   from_dtypessizesshapesindicesrO   raveledrY   s          @r!   rB   rB      s    		!n-->v>>K!!;/H4V44E6v66FI((/0G

0K
00 //v"Ft399T?"FG8'6J
 	
 ooIOP3++D(;	<PG 	&+xP  #G 	Qs   ,E50Ec                   t        j                  |       dk7  r%t        dd dt        j                  |        d      g S )N)r   0The unravel function expected an array of shape , got shape r   )rS   rV   
ValueError)rG   s    r!   r[   r[      sG    
yy$>tfLQTQZQZ[_Q`Paabc
 	
 Ir#   c               &   t        j                  |      | d   fk7  r)t        d| d   f dt        j                  |       d      t        j                  || d d       }t	        ||      D cg c]  \  }}|j                  |       c}}S c c}}w )Nrk   rl   r   )rS   rV   rm   splitr   reshape)rh   rg   rG   chunkschunkrV   s         r!   rb   rb      s     yy72;.(>~>N O4),
 	

 YYtWSb\*F5=ff5MN\UEEMM% NNNs   .Bc               .   t        j                  |      | d   fk7  r)t        d| d   f dt        j                  |       d      t        j                  |      }||k7  rt        d| d| d      t        j
                  || d d       }t        j                         5  t        j                  d       t        |||      D 	cg c]+  \  }}}	t        j                  |j                  |      |	      - c}	}}cd d d        S c c}	}}w # 1 sw Y   y xY w)Nro   rk   rl   r   z0The unravel function expected an array of dtype z, got dtype ignore)rS   rV   rm   r   rL   rp   warningscatch_warningssimplefilterr   r
   rc   rq   )
rh   rg   re   rY   rG   array_dtyperr   rs   rV   rL   s
             r!   rd   rd   	  s    yy72;.(>~>N O4),
 	
 ,,t$Kh>xjU`Taabc
 	
 YYtWSb\*F		 	 	" 
h' (0'L
 
#ue $$U]]5%95A

 


 
s   'D0D
6DDDr%   )
rA   zCallable[[Any], bool] | NonerD   r   r>   r5   r?   strr2   z*tuple[Array, Callable[[Array], ArrayTree]])rF   r   rH   z"Callable[[Array], list[ArrayLike]]rG   r	   r2   r   )rE   list[ArrayLike]r2   z0tuple[Array, Callable[[Array], list[ArrayLike]]])rG   r	   r2   r{   )rh   tuple[int, ...]rg   tuple[tuple[int, ...], ...]rG   r	   r2   list[Array])rh   r|   rg   r}   re   ztuple[jnp.dtype, ...]rY   z	jnp.dtyperG   r	   r2   r~   )1r:   
__future__r   
contextlibr]   rv   operatorr   typesr   typingr   r   typing_extensionsr   	jax.numpynumpyrS   jaxr	   r
   jax._srcr   
jax.typingr   
optree.opsr   r   optree.typingr   r   optree.utilsr   r   __all__r   r;   r   r   suppressImportErrorjax._src.utilr   ravel_pytreerC   rB   r[   rb   rd   r<   r#   r!   <module>r      s  @  #        '      3 3 5 7 ))Dy D$[%8	9 8)6 )6X Z% .-. -1LH
 LH *LH
LH
 LH LH 0LH^ 8848 8
 8!!!HOO'O O
 O 

'
 '
 	

 
 
{. .s   C77D 