o
    2hx                     @  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mZ ddl	m
Z
 ddl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 g d
ZedeZded< edejZded< 	d7dddd8ddZeZd9d"d#Zd:d'd(Zd;d)d*Z d<d/d0Z!d=d5d6Z"dS )>zIntegration with NumPy.    )annotationsN)AnyCallable)	TypeAlias)	ArrayLike)tree_flattentree_unflatten)
PyTreeSpecPyTreeTypeVar)safe_zip)ArrayLikeTree	ArrayTree
tree_ravelr   r   r   F )none_is_leaf	namespaceis_leafCallable[[Any], bool] | Nonetreer   boolr   strreturn4tuple[np.ndarray, Callable[[np.ndarray], ArrayTree]]c               C  s2   t | |||d\}}t|\}}|tt||fS )a'  Ravel (flatten) a pytree of arrays down to a 1D array.

    >>> tree = {
    ...     'layer1': {
    ...         'weight': np.arange(0, 6, dtype=np.float32).reshape((2, 3)),
    ...         'bias': np.arange(6, 8, dtype=np.float32).reshape((2,)),
    ...     },
    ...     'layer2': {
    ...         'weight': np.arange(8, 10, dtype=np.float32).reshape((1, 2)),
    ...         'bias': np.arange(10, 11, dtype=np.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   r   r   )r   _ravel_leaves	functoolspartial_tree_unravel)r   r   r   r   leavestreespecflatunravel_flat r!   T/var/www/html/chatgem/venv/lib/python3.10/site-packages/optree/integrations/numpy.pyr   *   s   E
r   r   r	   r    (Callable[[np.ndarray], list[np.ndarray]]r   
np.ndarrayc                C  s   t | ||S N)r   )r   r    r   r!   r!   r"   r   |   s   r   r   list[np.ndarray];tuple[np.ndarray, Callable[[np.ndarray], list[np.ndarray]]]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 rNt 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%   )npresult_type.0leafr!   r!   r"   	<genexpr>       z _ravel_leaves.<locals>.<genexpr>c                 s  r(   r%   )r)   sizer+   r!   r!   r"   r.      r/   c                 s  r(   r%   )r)   shaper+   r!   r!   r"   r.      r/   c                 3  s    | ]}| kV  qd S r%   r!   )r,   dtto_dtyper!   r"   r.      s    c                 S  s   g | ]}t |qS r!   )r)   ravelr+   r!   r!   r"   
<listcomp>   s    z!_ravel_leaves.<locals>.<listcomp>c                   s   g | ]
}t | qS r!   )r)   r5   astyper+   r3   r!   r"   r6      s    )r)   zeros_unravel_emptytupler*   	itertools
accumulateallconcatenater   r   _unravel_leaves_single_dtype_unravel_leaves)r   from_dtypessizesshapesindicesraveledr!   r3   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)   r1   
ValueError)r   r!   r!   r"   r9      s
   r9   rD   tuple[int, ...]rC   tuple[tuple[int, ...], ...]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   rH   c                 S  s   g | ]	\}}| |qS r!   )reshape)r,   chunkr1   r!   r!   r"   r6      s    z0_unravel_leaves_single_dtype.<locals>.<listcomp>)r)   r1   rI   splitr   )rD   rC   r   chunksr!   r!   r"   r?      s   r?   rA   tuple[np.dtype, ...]r4   np.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   rH   z0The unravel function expected an array of dtype z, got dtype ignorec                 S  s"   g | ]\}}}| ||qS r!   )rM   r7   )r,   rN   r1   dtyper!   r!   r"   r6      s    z#_unravel_leaves.<locals>.<listcomp>)	r)   r1   rI   r*   rO   warningscatch_warningssimplefilterr   )rD   rC   rA   r4   r   array_dtyperP   r!   r!   r"   r@      s$   



$r@   r%   )
r   r   r   r   r   r   r   r   r   r   )r   r	   r    r#   r   r$   r   r   )r   r&   r   r'   )r   r$   r   r&   )rD   rJ   rC   rK   r   r$   r   r&   )rD   rJ   rC   rK   rA   rQ   r4   rR   r   r$   r   r&   )#__doc__
__future__r   r   r;   rU   typingr   r   typing_extensionsr   numpyr)   numpy.typingr   
optree.opsr   r   optree.typingr	   r
   optree.utilsr   __all__r   __annotations__ndarrayr   r   ravel_pytreer   r   r9   r?   r@   r!   r!   r!   r"   <module>   s4   O

	
!
