o
    2hH*                     @  s  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 dZ&e'e( ddl)m&Z& W d   n1 sw   Y  	d?dddd@d!d"Z*e*Z+dAd)d*Z,dBd.d/Z-dCd0d1Z.dDd7d8Z/dEd=d>Z0dS )Fz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                   @  sR   e Zd ZU dZded< ded< ded< dddZdddZdddZdddZdS )HashablePartialz1A hashable version of :class:`functools.partial`.r   funcztuple[Any, ...]argszdict[str, Any]kwargsFunctionType | HashablePartialr   returnNonec                O  sz   t |std|dt|tr%|j| _|j| | _i |j|| _dS t|tr5|| _|| _|| _dS 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    r!   R/var/www/html/chatgem/venv/lib/python3.10/site-packages/optree/integrations/jax.py__init__G   s   


zHashablePartial.__init__otherobjectboolc                C  s4   t |tu o| jj|jjko| j| jf|j|jfkS N)typer   r   __code__r   r   )r    r$   r!   r!   r"   __eq__W   s
   zHashablePartial.__eq__intc                C  s*   t | jj| jtt| j tddfS )Nr   )key)	hashr   r)   r   tupler   r   itemsr   )r    r!   r!   r"   __hash__^   s   zHashablePartial.__hash__c                O  s*   i | j |}| jg | j|R i |S r'   )r   r   r   )r    r   r   r!   r!   r"   __call__g   s   zHashablePartial.__call__N)r   r   r   r   r   r   r   r   )r$   r%   r   r&   )r   r+   )r   r   r   r   r   r   )	__name__
__module____qualname____doc____annotations__r#   r*   r0   r1   r!   r!   r!   r"   r   @   s   
 


	r   )r   F )none_is_leaf	namespaceis_leafCallable[[Any], bool] | Nonetreer8   r&   r9   strr   *tuple[Array, Callable[[Array], ArrayTree]]c               C  s0   t | |||d\}}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.
    )r:   r8   r9   )r   _ravel_leavesr   _tree_unravel)r<   r:   r8   r9   leavestreespecflatunravel_flatr!   r!   r"   r   q   s   E
r   rB   r   rD   "Callable[[Array], list[ArrayLike]]rC   r   c                C  s   t | ||S r'   )r   )rB   rD   rC   r!   r!   r"   r@      s   r@   rA   list[ArrayLike]0tuple[Array, Callable[[Array], list[ArrayLike]]]c                  s   | s	t dtfS tdd | D }tj|  tdd | D }tdd | D }tt|}t fdd|D rMt 	dd | D }|t
t||fS t 	 fd	d| D }|t
t||| fS )
Nr   c                 s      | ]}t |V  qd S r'   )r
   dtype.0leafr!   r!   r"   	<genexpr>       z _ravel_leaves.<locals>.<genexpr>c                 s  rH   r'   )jnpsizerJ   r!   r!   r"   rM      rN   c                 s  rH   r'   )rO   shaperJ   r!   r!   r"   rM      rN   c                 3  s    | ]}| kV  qd S r'   r!   )rK   dtto_dtyper!   r"   rM      s    c                 S  s   g | ]}t |qS r!   )rO   ravelrJ   r!   r!   r"   
<listcomp>   s    z!_ravel_leaves.<locals>.<listcomp>c                   s   g | ]}t t| qS r!   )rO   rU   r	   convert_element_typerJ   rS   r!   r"   rV      s    )rO   zeros_unravel_emptyr.   r
   result_type	itertools
accumulateallconcatenater   _unravel_leaves_single_dtype_unravel_leaves)rA   from_dtypessizesshapesindicesraveledr!   rS   r"   r?      s$   

r?   c                C  s.   t | dkrtdd dt |  dg S )N)r   0The unravel function expected an array of shape , got shape r   )rO   rQ   
ValueError)rC   r!   r!   r"   rY      s
   rY   rd   tuple[int, ...]rc   tuple[tuple[int, ...], ...]list[Array]c                C  s^   t || d fkrtd| d f dt | dt || d d }dd t||D S )Nrf   rg   r   c                 S  s   g | ]	\}}| |qS r!   )reshape)rK   chunkrQ   r!   r!   r"   rV     s    z0_unravel_leaves_single_dtype.<locals>.<listcomp>)rO   rQ   rh   splitr   )rd   rc   rC   chunksr!   r!   r"   r_      s   r_   ra   tuple[jnp.dtype, ...]rT   	jnp.dtypec                C  s   t || d fkrtd| d f dt | dt|}||kr/td| d| dt || d d }t  td dd	 t	|||D W  d    S 1 sXw   Y  d S )
Nrl   rf   rg   r   z0The unravel function expected an array of dtype z, got dtype ignorec                 S  s$   g | ]\}}}t |||qS r!   )r	   rW   rm   )rK   rn   rQ   rI   r!   r!   r"   rV     s    z#_unravel_leaves.<locals>.<listcomp>)
rO   rQ   rh   r
   rI   ro   warningscatch_warningssimplefilterr   )rd   rc   ra   rT   rC   array_dtyperp   r!   r!   r"   r`   	  s$   



$r`   r'   )
r:   r;   r<   r   r8   r&   r9   r=   r   r>   )rB   r   rD   rE   rC   r   r   r   )rA   rF   r   rG   )rC   r   r   rF   )rd   ri   rc   rj   rC   r   r   rk   )rd   ri   rc   rj   ra   rq   rT   rr   rC   r   r   rk   )1r5   
__future__r   
contextlibr[   rt   operatorr   typesr   typingr   r   typing_extensionsr   	jax.numpynumpyrO   jaxr   r	   jax._srcr
   
jax.typingr   
optree.opsr   r   optree.typingr   r   optree.utilsr   r   __all__r   r6   r   r   suppressImportErrorjax._src.utilr   ravel_pytreer@   r?   rY   r_   r`   r!   r!   r!   r"   <module>   sD   ,O

	
$
	