
    0Vh                    @   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	<   	 dddd	 	 	 	 	 	 	 	 	 ddZeZ	 	 	 	 	 	 	 	 ddZ	 	 	 	 ddZddZ	 	 	 	 	 	 	 	 ddZ	 	 	 	 	 	 	 	 	 	 	 	 ddZy)zIntegration with PyTorch.    )annotationsN)AnyCallable)	TypeAlias)tree_flattentree_unflatten)
PyTreeSpecPyTreeTypeVar)safe_zip
TensorTree
tree_ravelr   F )none_is_leaf	namespacec              |    t        | |||      \  }}t        |      \  }}|t        j                  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.
    )is_leafr   r   )r   _ravel_leaves	functoolspartial_tree_unravel)treer   r   r   leavestreespecflatunravel_flats           I/home/dcms/DCMS/lib/python3.12/site-packages/optree/integrations/torch.pyr   r   '   sK    J $!	FH 'v.D,""=(LIII    c               &    t        |  ||            S N)r   )r   r   r   s      r   r   r   y   s     (L$677r   c                  | st        j                  d      t        fS t        d | D              st	        d      t        d | D              }|d   |dd  D ]  }t        j                  |       t        d | D              }t        d | D              }t        fd|D              rSt        j                  | D cg c]  }t        j                  |       c}      }|t        j                  t        ||      fS t        j                  | D cg c]&  }t        j                  |      j                        ( c}      }|t        j                  t        |||      fS c c}w c c}w )	Nr   c              3  F   K   | ]  }t        j                  |        y wr   )torch	is_tensor.0leafs     r   	<genexpr>z _ravel_leaves.<locals>.<genexpr>   s     8ut$8s   !zAll leaves must be tensors.c              3  4   K   | ]  }|j                     y wr   )dtyper$   s     r   r'   z _ravel_leaves.<locals>.<genexpr>   s     6t

6      c              3  <   K   | ]  }|j                           y wr   )numelr$   s     r   r'   z _ravel_leaves.<locals>.<genexpr>   s     24$**,2s   c              3  4   K   | ]  }|j                     y wr   )shaper$   s     r   r'   z _ravel_leaves.<locals>.<genexpr>   s     1$4::1r*   c              3  (   K   | ]	  }|k(    y wr    )r%   dtto_dtypes     r   r'   z _ravel_leaves.<locals>.<genexpr>   s     
0b2>
0s   )r"   zeros_unravel_emptyall
ValueErrortuplepromote_typescatravelr   r   _unravel_leaves_single_dtypeto_unravel_leaves)r   from_dtypes
from_dtypesizesshapesr&   raveledr3   s          @r   r   r      sC    A//8886776v66K1~H!!"o =
&&x<=2622E1&11F

0K
00))6B4U[[.BC:E6J
 	
 iiFKDT*--h7KLG/5&+xP  C Ls   >E"+E'c                   t        j                  |       st        dt        |       d      | j                  dk7  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#   r7   typer/   )r   s    r   r5   r5      sb    ??4 =d4j^1MNNzzT>tfLQUQ[Q[P\\]^
 	
 Ir   c                  t        j                  |      st        dt        |      d      |j                  t        |       fk7  r&t        dt        |       f d|j                   d      t        j                  |t        |             }t        ||      D cg c]  \  }}|j                  |       c}}S c c}}w )NrE   rF   rG   rH   )
r"   r#   r7   rI   r/   sumsplitlistr   reshape)rA   rB   r   chunkschunkr/   s         r   r<   r<      s     ??4 =d4j^1MNNzzc%j]">E
}o NA'
 	

 [[tE{+F5=ff5MN\UEEMM% NNNs   B:c          	     |   t        j                  |      st        dt        |      d      |j                  t        |       fk7  r&t        dt        |       f d|j                   d      |j                  |k7  rt        d| d|j                   d      t        j                  |t        |             }t        j                         5  t        j                  d       t        |||      D cg c]&  \  }}}|j                  |      j                  |      ( c}}}cd d d        S c c}}}w # 1 sw Y   y xY w)NrE   rF   rG   rH   z0The unravel function expected a tensor of dtype z, got dtype ignore)r"   r#   r7   rI   r/   rK   r)   rL   rM   warningscatch_warningssimplefilterr   rN   r=   )	rA   rB   r?   r3   r   rO   rP   r/   r)   s	            r   r>   r>      s0    ??4 =d4j^1MNNzzc%j]">E
}o NA'
 	
 zzX>xjUYU_U_T``ab
 	
 [[tE{+F		 	 	" 
h' (0'L
 
#ue MM% ##E*

 


 
s   'D22+D+
D2+D22D;r   )
r   zCallable[[Any], bool] | Noner   r   r   boolr   strreturnz9tuple[torch.Tensor, Callable[[torch.Tensor], TensorTree]])r   r	   r   z,Callable[[torch.Tensor], list[torch.Tensor]]r   torch.TensorrX   r   )r   list[torch.Tensor]rX   zAtuple[torch.Tensor, Callable[[torch.Tensor], list[torch.Tensor]]])r   rY   rX   rZ   )rA   tuple[int, ...]rB   tuple[tuple[int, ...], ...]r   rY   rX   rZ   )rA   r[   rB   r\   r?   ztuple[torch.dtype, ...]r3   ztorch.dtyper   rY   rX   rZ   )__doc__
__future__r   r   rS   typingr   r   typing_extensionsr   r"   
optree.opsr   r   optree.typingr	   r
   optree.utilsr   __all__Tensorr   __annotations__r   ravel_pytreer   r   r5   r<   r>   r1   r   r   <module>rh      sX     #     '  3 3 ! 
& &lELLA
I A -1LJ
 LJ *LJ
LJ
 LJ LJ ?LJ^ 88>8 8
 8!!!HOO'O O
 O$

'
 )
 	

 
 
r   