o
    2h                     @  s   U d Z ddlm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mZ ddlmZmZ ddlmZ d	d
gZed	e
jZded	< 	d4dddd5dd
ZeZd6dd Zd7d$d%Zd8d&d'Zd9d,d-Zd:d2d3ZdS );zIntegration with PyTorch.    )annotationsN)AnyCallable)	TypeAlias)tree_flattentree_unflatten)
PyTreeSpecPyTreeTypeVar)safe_zip
TensorTree
tree_ravelr   F )none_is_leaf	namespaceis_leafCallable[[Any], bool] | Nonetreer   boolr   strreturn9tuple[torch.Tensor, Callable[[torch.Tensor], TensorTree]]c               C  s2   t | |||d\}}t|\}}|tt||fS )a{  Ravel (flatten) a pytree of tensors down to a 1D tensor.

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

    Args:
        tree (pytree): a pytree of tensors 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 ``(tensor, unravel_func)`` where the first element is a 1D tensor 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 tensor
        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 tensor 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/torch.pyr   '   s   E
r   r   r   ,Callable[[torch.Tensor], list[torch.Tensor]]r   torch.Tensorc                C  s   t | ||S N)r   )r   r   r   r   r   r    r   y   s   r   r   list[torch.Tensor]Atuple[torch.Tensor, Callable[[torch.Tensor], list[torch.Tensor]]]c                  s   | s	t dtfS tdd | D stdtdd | D }|d  |dd  D ]}t  | q)tdd | D }tdd | D }t fd	d|D rbt d
d | D }|t	t
||fS t  fdd| D }|t	t||| fS )Nr   c                 s  s    | ]}t |V  qd S r#   )torch	is_tensor.0leafr   r   r    	<genexpr>   s    z _ravel_leaves.<locals>.<genexpr>zAll leaves must be tensors.c                 s      | ]}|j V  qd S r#   )dtyper(   r   r   r    r+             c                 s  s    | ]}|  V  qd S r#   )numelr(   r   r   r    r+          c                 s  r,   r#   )shaper(   r   r   r    r+      r.   c                 3  s    | ]}| kV  qd S r#   r   )r)   dtto_dtyper   r    r+      r1   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&   r6   tor(   r4   r   r    r7      s    )r&   zeros_unravel_emptyall
ValueErrortuplepromote_typescatr   r   _unravel_leaves_single_dtype_unravel_leaves)r   from_dtypes
from_dtypesizesshapesraveledr   r4   r    r      s&   r   c                C  sD   t | stdt| d| jdkr tdd d| j dg S )N"Expected a tensor to unravel, got .)r   0The unravel function expected a tensor of shape , got shape )r&   r'   r<   typer2   )r   r   r   r    r:      s   

r:   rD   tuple[int, ...]rE   tuple[tuple[int, ...], ...]c                C  sp   t |stdt|d|jt| fkr&tdt| f d|j dt |t| }dd t||D S )NrG   rH   rI   rJ   c                 S  s   g | ]	\}}| |qS r   )reshape)r)   chunkr2   r   r   r    r7      s    z0_unravel_leaves_single_dtype.<locals>.<listcomp>)	r&   r'   r<   rK   r2   sumsplitlistr
   )rD   rE   r   chunksr   r   r    r@      s   
r@   rB   tuple[torch.dtype, ...]r5   torch.dtypec                C  s   t |stdt|d|jt| fkr&tdt| f d|j d|j|kr7td| d|j dt |t| }t	
  t	d dd	 t|||D W  d    S 1 s^w   Y  d S )
NrG   rH   rI   rJ   z0The unravel function expected a tensor of dtype z, got dtype ignorec                 S  s"   g | ]\}}}| ||qS r   )rN   r8   )r)   rO   r2   r-   r   r   r    r7      s    z#_unravel_leaves.<locals>.<listcomp>)r&   r'   r<   rK   r2   rP   r-   rQ   rR   warningscatch_warningssimplefilterr
   )rD   rE   rB   r5   r   rS   r   r   r    rA      s&   




$rA   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   rL   rE   rM   r   r"   r   r$   )rD   rL   rE   rM   rB   rT   r5   rU   r   r"   r   r$   )__doc__
__future__r   r   rW   typingr   r   typing_extensionsr   r&   
optree.opsr   r   optree.typingr   r	   optree.utilsr
   __all__Tensorr   __annotations__r   ravel_pytreer   r   r:   r@   rA   r   r   r   r    <module>   s.   O

	
$

