
    shX                        S SK r S SKJrJr  S SKJrJrJrJr  S SK	r	S SK
Jr  S SK	Jr  S SKJr  S\4S jrS\\\\4   \\\\4      4   S	\\\\4   \\\\4      4   S\\\\   4   4S
 jrS\R*                  S\S\\\\4      4   S\\/\4   S\\\S4   \\S4   \\\\   4   4   4S jrS\R*                  S\\\S4   \\S4   \\\\   4   4   4S jrS\R*                  S\\\S4   \\S4   \\\\   4   4   4S jr S3S\R*                  S\\   S\\   S\SS4
S jjrS\R*                  S\\\\   4   S\\   S\\   4S jr S3S\R*                  S\\   S\\   S\SS4
S jjr  S4S\R*                  S\\   S\\   S\\   S\\   S\R*                  4S  jjrS\R*                  4S! jrS\R*                  4S" jr " S# S$\R*                  5      r  " S% S&\R*                  5      r! S3S\R*                  S'\S\\!\\S4   4   4S( jjr" S3S\R*                  S'\S\\ \\S4   \\S4   4   4S) jjr#S*\\\S4   S4   S\\S4   4S+ jr$S,\\R*                     S\\ \\S4   \\S4   4   4S- jr%  S5S.\&\R*                     S/\\S   \\'   4   S0\	RP                  RR                  4S1 jjr*  S5S.\&\R*                     S/\\S   \\'   4   S0\	RP                  RR                  4S2 jjr+g)6    N)IterableSequence)AnyCallableNoReturnUnion)Tensor)NamedMemberAccessorreturnc                      [        S5      e)Na$  make_functional(module): we don't yet support models that do parameter tying (also sometimes known as weight sharing). Please try to rewrite your model by replacing all instances of the tied parameter with another and/or comment your support in https://github.com/pytorch/functorch/issues/446)RuntimeError     t/Users/tiagomarins/Projetos/claudeai/copy_bank/venv/lib/python3.13/site-packages/torch/_functorch/make_functional.pyraise_parameter_tying_errorr      s    
	: r   named_paramstied_named_paramsc                    [        U 5      n [        U5      n[        U R                  5       5      n[        UR                  5       5      nUR                  U5      (       d   e0 nU R	                  5        H  u  pVU/ 4XF'   M     UR	                  5        H"  u  pVXd;   d   eXF   S   R                  U5        M$     [        UR                  5       5      $ )aC  
named_params is a dictionary of tensors: {'A': A, 'B': B}
tied_named_params is another dictionary of tensors {'A': A, 'B': B, 'B_tied': B}
with potentially tied (or 'duplicated') tensors

This function creates a mapping from the names in named_params to the
names in tied_named_params: {'A': ['A'], 'B': ['B', 'B_tied']}.
   )dictsetkeysissubsetitemsappendvalues)r   r   tensors_dict_keystied_tensors_dict_keystensor_to_mappingkeytensors          r   create_names_mapr"   !   s     %L./L--/0 !2!7!7!9:%%&<=====?#))+%("I! ,(..0***!!$++C0 1 !((*++r   modnamed_members.subclassc                 6   [        U" SS95      n[        U" SS95      n[        XC5      n0 n[        U 5      nU H<  u  pX;  a  U" [        R                  " U	SS95      Xi'   Xi   n
UR                  X5        M>     [        U5      S:X  a  Su  pO
[        U6 u  pXU4$ )NF)remove_duplicateTmeta)devicer   r   r   )tupler"   r
   torch
empty_like
set_tensorlenzip)r#   r$   r%   all_named_membersunique_named_members	names_mapmemoaccessornamepreplacementnamesparamss                r   _extract_membersr;   =   s    
 mUCD !EF !5II D"3'H$=u//&ABDGgD.	 %  A%v12)##r   c                 J    [        X R                  [        R                  5      $ )a>  
This function removes all the Parameters from the model and
return them as a tuple as well as their original attribute names.
The weights must be re-loaded with `load_weights` before the model
can be used again.
Note that this function modifies the model in place and after this
call, mod.parameters() will be empty.
)r;   named_parametersnn	Parameterr#   s    r   extract_weightsrA   V   s     C!5!5r||DDr   c                 0    [        X R                  S 5      $ )Nc                     U $ Nr   )xs    r   <lambda>!extract_buffers.<locals>.<lambda>g   s    ar   )r;   named_buffersr@   s    r   extract_buffersrI   d   s     C!2!2K@@r   r9   r:   	as_paramsc                     [        U 5      nU(       a&  U Vs/ s H  n[        R                  " U5      PM     nnUR                  X5        gs  snf )z
Reload a set of weights so that `mod` can be used again to perform a forward pass.
Note that the `params` are regular Tensors (that can have history) and so are left
as Tensors. This means that mod.parameters() will still be empty after this call.
N)r
   r>   r?   set_tensors)r#   r9   r:   rJ   r5   r7   s         r   load_weightsrM   j   s@     #3'H+126a",,q/62' 3s    Ar3   elemsc                    / n[        U 5      n[        UR                  5       U5       HU  u  u  pVn[        U5       H>  u  pUS:X  a"  UR	                  UR                  X5      5        M-  UR                  X5        M@     MW     U$ )Nr   )r
   r0   r   	enumerater   swap_tensorr.   )
r#   r3   rN   resultr5   _
attr_nameselemi	attr_names
             r   _swap_staterX   {   sv     F"3'H!$Y__%6!>%j1LAAvh229CD##I4	 2 "? Mr   buffersc                 <    [        U 5      nUR                  X5        g rD   )r
   rL   )r#   r9   rY   rJ   r5   s        r   load_buffersr[      s     #3'H(r   r   modelweightsweight_namesbuffer_namesc                     [        U5      [        U5      :X  d   e[        XU5        [        U5      S:  a&  [        U5      [        U5      :X  d   e[        XU5        U $ )zload_state(model, weights, weight_names, buffers=(), buffer_names=()) -> model

load_state takes `weights` and `buffers` and assigns them to the model.
This is the inverse operation of `make_functional_deprecated_v1`.
r   )r/   rM   r[   )r\   r]   r^   rY   r_   s        r   
load_statera      sW     |G,,,g.
7|a< CL000U'2Lr   c                    ^ ^ [        T R                  5       5      n[        U5      S:  a  [        S5      e[	        T 5      u  nmnUU 4S jnX$T4$ )a  make_functional_deprecated_v1(model) -> weights, func, weight_names

Given an nn.Module, make_functional_deprecated_v1 extracts the state (weights)
and returns a functional version of the model, `func`. This makes
it so that it is possible use transforms over the parameters of
`model`.

`func` can be invoked as follows:
```
x = torch.randn(4, 3)
model = nn.Linear(3, 3)
weights, func, _ = make_functional_deprecated_v1(model)
func(weights, (x,))
```

And here is an example of applying the grad transform:
```
x = torch.randn(4, 3)
model = nn.Linear(3, 3)
weights, _, func = make_functional_deprecated_v1(model)
grad_weights = grad(func)(weights, (x,))
```

To put the state back into a model, use `load_state`.
r   zmake_functional_deprecated_v1(model): `model` has buffers. Please use make_functional_with_buffers_deprecated_v1(model) instead.c                 T   > [         R                  " T5      n[        UTU 5        U" U6 $ rD   )copydeepcopyrM   )r]   datamutable_modeldescriptorsr\   s      r   fun*make_functional_deprecated_v1.<locals>.fun   s(    e,]K9d##r   )listrY   r/   r   rA   )r\   rY   r]   rS   ri   rh   s   `    @r   make_functional_deprecated_v1rl      sY    4 5==?#G
7|aI
 	
 .e4G[!$
 $$r   c                 `   ^ ^^ [        T 5      u  nmn[        T 5      u  nmnUU U4S jnXUTT4$ )a  make_functional_with_buffers_deprecated_v1(model) -> weights, buffers, func, weight_names, buffer_names

Given an nn.Module, make_functional_with_buffers_deprecated_v1 extracts the state (weights and buffers)
and returns a functional version of the model, `func`.

`func` can be invoked as follows:
```
x = torch.randn(4, 3)
model = nn.Linear(3, 3)
weights, buffers, func, _, _ = make_functional_with_buffers_deprecated_v1(model)
func(weights, buffers, (x,))
```

And here is an example of applying the grad transform:
```
x = torch.randn(4, 3)
model = nn.Linear(3, 3)
weights, buffers, func, _, _ = make_functional_with_buffers_deprecated_v1(model)
func(weights, buffers, (x,))
grad_weights = grad(func)(weights, buffers, (x,))
```

To put the state back into a model, use `load_state`.
c                 n   > [         R                  " T5      n[        UTU 5        [        UTU5        U" U6 $ rD   )rd   re   rM   r[   )r]   rY   rf   rg   buf_descriptorsr\   weight_descriptorss       r   ri   7make_functional_with_buffers_deprecated_v1.<locals>.fun   s5    e,]$6@]OW=d##r   )rA   rI   )r\   r]   rS   rY   ri   ro   rp   s   `    @@r   *make_functional_with_buffers_deprecated_v1rr      s?    2 &5U%;"G"1%"8G_a$ S"4oEEr   c                     ^  \ rS rSrSrS\R                  S\\S4   S\\S4   S\	\\
\   4   S\	\\
\   4   S	S
4U 4S jjr\ SS\R                  S\S	\S \\S4   \\S4   4   4S jj5       rS\\   S\\   S	\4S jrSrU =r$ )FunctionalModuleWithBuffers   zO
This is the callable object returned by :func:`make_functional_with_buffers`.
stateless_modelparam_names.r_   param_names_mapbuffer_names_mapr   Nc                    > [         TU ]  5         Xl        X l        X0l        [        U5      U l        U R                  R                  U5        g rD   )super__init__rv   rw   r_   r   all_names_mapupdate)selfrv   rw   r_   rx   ry   	__class__s         r   r|   $FunctionalModuleWithBuffers.__init__   sD     	.&(!/2!!"23r   r\   disable_autograd_trackingc                     [         R                  " U 5      n[        U5      u  p4n[        U5      u  pgnU(       a  U H  n	U	R	                  S5        M     [        X$XuU5      UU4$ NF)rd   re   rA   rI   requires_grad_rt   )
r\   r   
model_copyr:   rw   rx   rY   r_   ry   params
             r   _create_from(FunctionalModuleWithBuffers._create_from  sp    
 ]]5)
/>z/J,_2A*2M//$$$U+   (HX 
 	
r   r:   rY   c                 "   [        U R                  U R                  [        U5      [        U5      -   5      n U R                  " U0 UD6[        U R                  U R                  U5        $ ! [        U R                  U R                  U5        f = frD   )rX   rv   r}   r+   )r   r:   rY   argskwargs	old_states         r   forward#FunctionalModuleWithBuffers.forward  s|        &ME'N*
	
	M''88 ,,d.@.@)LK,,d.@.@)Ls   A+ +#B)r}   r_   rw   rv   F__name__
__module____qualname____firstlineno____doc__r>   Moduler+   strr   rk   r|   staticmethodboolr	   r   r   r   r   __static_attributes____classcell__r   s   @r   rt   rt      s    44 38_4 CHo	4
 c49n-4 sDI~.4 
4  <A
yy
59
	,eFCK.@%PSBTT	U
 
$Mv&M19&1AM	M Mr   rt   c                      ^  \ rS rSrSrS\R                  S\\S4   S\	\\
\   4   SS4U 4S	 jjr\ SS
\R                  S\S\S \\S4   4   4S jj5       rS\\   S\4S jrSrU =r$ )FunctionalModulei.  zB
This is the callable object returned by :func:`make_functional`.
rv   rw   .r3   r   Nc                 F   > [         TU ]  5         Xl        X l        X0l        g rD   )r{   r|   rv   rw   r3   )r   rv   rw   r3   r   s       r   r|   FunctionalModule.__init__3  s!     	.&"r   r\   r   c                     [         R                  " U 5      n[        U5      u  p4nU(       a  U H  nUR                  S5        M     [	        X$U5      U4$ r   )rd   re   rA   r   r   )r\   r   r   r:   rw   r3   r   s          r   r   FunctionalModule._create_from>  sN    
 ]]5)
)8)D&Y$$$U+  
CVKKr   r:   c                     [        U R                  U R                  U5      n U R                  " U0 UD6[        U R                  U R                  U5        $ ! [        U R                  U R                  U5        f = frD   )rX   rv   r3   )r   r:   r   r   r   s        r   r   FunctionalModule.forwardJ  sb     4 4dnnfM		I''88 ,,dnniHK,,dnniHs   A #A9)r3   rw   rv   r   r   r   s   @r   r   r   .  s    	#	# 38_	# T#Y'		#
 
	# <A	Lyy	L59	L	!5#55	6	L 	LIhv. IC I Ir   r   r   c                     [        U R                  5       5      n[        U5      S:  a  [        S5      e[        R                  XS9$ )a  make_functional(model, disable_autograd_tracking=False) -> func, params

Given a ``torch.nn.Module``, :func:`make_functional` extracts the state
(params) and returns a functional version of the model, ``func``. This
makes it so that it is possible use transforms over the parameters of
``model``.

``func`` can be invoked as follows:

.. code-block:: python

    import torch
    import torch.nn as nn
    from functorch import make_functional

    x = torch.randn(4, 3)
    model = nn.Linear(3, 3)
    func, params = make_functional(model)
    func(params, x)

And here is an example of applying the grad transform over the parameters
of a model.

.. code-block:: python

    import torch
    import torch.nn as nn
    from functorch import make_functional, grad

    x = torch.randn(4, 3)
    t = torch.randn(4, 3)
    model = nn.Linear(3, 3)
    func, params = make_functional(model)

    def compute_loss(params, x, t):
        y = func(params, x)
        return nn.functional.mse_loss(y, t)

    grad_weights = grad(compute_loss)(params, x, t)

If the model has any buffers, please use :func:`make_functional_with_buffers` instead.

Args:
    model (torch.nn.Module): Input model.
    disable_autograd_tracking (bool): Flag to disable gradients tracking for output parameters.
        The returned params are unrelated to the set of params from the original model. If False (default),
        the params will have ``requires_grad=True`` on them (aka they will be trackable with regular
        PyTorch autograd), matching the requires_grad-ness of the params from the original model.
        Otherwise, the returned params will have ``requires_grad=False``. Default, False.
        If you plan on using regular PyTorch autograd (e.g., if you want to call ``.backward()`` or
        ``torch.autograd.grad()``, then set ``disable_autograd_tracking=False``.
        Otherwise, if you're only planning on using functorch's gradient transforms,
        then please set ``disable_autograd_tracking=True`` to avoid unnecessarily tracking
        history with PyTorch autograd.

r   zdmake_functional(model): `model` has buffers. Please use make_functional_with_buffers(model) instead.r   )rk   rY   r/   r   r   r   )r\   r   rY   s      r   make_functionalr   T  sP    v 5==?#G
7|a;
 	
 (( )  r   c                 (    [         R                  XS9$ )a"  make_functional_with_buffers(model, disable_autograd_tracking=False) -> func, params, buffers

Given a ``torch.nn.Module``, make_functional_with_buffers extracts the
state (params and buffers) and returns a functional version of the model
``func`` that can be invoked like a function.

``func`` can be invoked as follows:

.. code-block:: python

    import torch
    import torch.nn as nn
    from functorch import make_functional_with_buffers

    x = torch.randn(4, 3)
    model = nn.Linear(3, 3)
    func, params, buffers = make_functional_with_buffers(model)
    func(params, buffers, x)

And here is an example of applying the grad transform over the parameters
of a model:

.. code-block:: python

    import torch
    import torch.nn as nn
    from functorch import make_functional_with_buffers, grad

    x = torch.randn(4, 3)
    t = torch.randn(4, 3)
    model = nn.Linear(3, 3)
    func, params, buffers = make_functional_with_buffers(model)

    def compute_loss(params, buffers, x, t):
        y = func(params, buffers, x)
        return nn.functional.mse_loss(y, t)

    grad_weights = grad(compute_loss)(params, buffers, x, t)

Args:
    model (torch.nn.Module): Input model.
    disable_autograd_tracking (bool): Flag to disable gradients tracking for output parameters.
        The returned params are unrelated to the set of params from the original model. If False (default),
        the params will have ``requires_grad=True`` on them (aka they will be trackable with regular
        PyTorch autograd), matching the requires_grad-ness of the params from the original model.
        Otherwise, the returned params will have ``requires_grad=False``. Default, False.
        If you plan on using regular PyTorch autograd (e.g., if you want to call ``.backward()`` or
        ``torch.autograd.grad()``, then set ``disable_autograd_tracking=False``.
        Otherwise, if you're only planning on using functorch's gradient transforms,
        then please set ``disable_autograd_tracking=True`` to avoid unnecessarily tracking
        history with PyTorch autograd.

r   )rt   r   )r\   r   s     r   make_functional_with_buffersr     s     p '33 4  r   tuple_of_tuple_of_tensorsc                 L    [        [        U 6 5      n [        S U  5       5      nU$ )Nc              3   j   #    U  H)  n[         R                  " U5      R                  5       v   M+     g 7frD   r,   stackdetach.0shardss     r   	<genexpr>"transpose_stack.<locals>.<genexpr>  s)      3LF""$$3L   13)r+   r0   )r   resultss     r   transpose_stackr     s3     !&c+D&E F 3L G Nr   modelsc                   ^ [        U 5      S:X  a  [        S5      e[        S U  5       5      (       d"  [        S U  5       5      (       d  [        S5      e[        U S   5      m[        U4S jU  5       5      (       d  [        S5      e[	        U  Vs/ s H  n[        U5      PM     sn6 u  p#n[        U5      n[        U5      nUS   X44$ s  snf )a  combine_state_for_ensemble(models) -> func, params, buffers

Prepares a list of torch.nn.Modules for ensembling with :func:`vmap`.

Given a list of ``M`` ``nn.Modules`` of the same class, stacks all of their
parameters and buffers together to make ``params`` and ``buffers``.
Each parameter and buffer in the result will have an additional dimension
of size ``M``.

:func:`combine_state_for_ensemble` also returns ``func``, a functional
version of one of the models in :attr:`models`. One cannot directly run
``func(params, buffers, *args, **kwargs)`` directly, you probably want to
use ``vmap(func, ...)(params, buffers, *args, **kwargs)``

Here's an example of how to ensemble over a very simple model:

.. code-block:: python

    num_models = 5
    batch_size = 64
    in_features, out_features = 3, 3
    models = [torch.nn.Linear(in_features, out_features) for i in range(num_models)]
    data = torch.randn(batch_size, 3)

    fmodel, params, buffers = combine_state_for_ensemble(models)
    output = vmap(fmodel, (0, 0, None))(params, buffers, data)

    assert output.shape == (num_models, batch_size, out_features)

.. warning::
    All of the modules being stacked together must be the same (except for
    the values of their parameters/buffers). For example, they should be in the
    same mode (training vs eval).

    This API is subject to change -- we're investigating better ways to
    create ensembles and would love your feedback how to improve this.
r   z?combine_state_for_ensemble: Expected at least one model, got 0.c              3   8   #    U  H  oR                   v   M     g 7frD   trainingr   ms     r   r   -combine_state_for_ensemble.<locals>.<genexpr>  s     +Fq

Fs   c              3   B   #    U  H  oR                   (       + v   M     g 7frD   r   r   s     r   r   r     s     2R6azz>>6s   zTcombine_state_for_ensemble: Expected all models to have the same training/eval mode.c              3   @   >#    U  H  n[        U5      T:H  v   M     g 7frD   )type)r   r   
model0_typs     r   r   r     s     5ftAw*$fs   zHcombine_state_for_ensemble: Expected all models to be of the same class.)r/   r   allr   r0   r   r   )r   r\   funcsr:   rY   r   s        @r   combine_state_for_ensembler     s    P 6{aM
 	
 +F+++s2R62R/R/R0
 	
 fQiJ5f555V
 	
 !;A	B6%
&u
-6	BE7 V$Fg&G8V$$	 
Cs   C
model_classensemble_shaper)   c                    ^ ^^ UUU 4S jnU$ )Nc                    >^ ^ [        T
5      S:  a  [        S5      e[        T
5      S:X  a"  T" T 0 TD6R                  T	5      n[        U5      $ T
S   nUS::  a  [        SU S35      e[	        U U	UU4S j[        U5       5       5      n[        T" T 0 TD65      u  pVn[	        S U 5       5      n[	        [        U6 5      n[	        S U 5       5      nXU4$ )	N   ,NYI: ensemble_shape with more than 1 elementr   num_models  should be > 0c              3   R   >#    U  H  nT" T0 TD6R                  T5      v   M     g 7frD   tor   rS   r   r)   r   r   s     r   r   3functional_init.<locals>.wrapped.<locals>.<genexpr>.  -      
=NK((++F33=N   $'c              3   >   #    U  H  n[        U5      S    v   M     g7f)r   N)rl   r   r\   s     r   r   r   2  s     TVE5e<Q?V   c              3   j   #    U  H)  n[         R                  " U5      R                  5       v   M+     g 7frD   r   r   s     r   r   r   4  %     K7F+22447r   )r/   
ValueErrorr   rl   r+   ranger0   )r   r   r\   
num_modelsr   rS   fnr9   r]   r)   r   r   s   ``       r   wrapped functional_init.<locals>.wrapped$  s    ~!#KLL~!#0033F;E077#A&
?{:,nEFF 
=B:=N
 
 5[$5Q&5QRuTVTTW&K7KKE!!r   r   r   r   r)   r   s   ``` r   functional_initr     s    
"& Nr   c                    ^ ^^ UUU 4S jnU$ )Nc                    >^ ^ [        T5      S:  a  [        S5      e[        T5      S:X  a"  T" T 0 TD6R                  T5      n[        U5      $ TS   nUS::  a  [        SU S35      e[	        U UUU4S j[        U5       5       5      n[        T" T 0 TD65      u  nnnnn[        [	        S U 5       5      6 u  p[	        [        U	6 5      n	[	        S U	 5       5      n	[	        [        U
6 5      n
[	        S	 U
 5       5      n
XXgU4$ )
Nr   r   r   r   r   c              3   R   >#    U  H  nT" T0 TD6R                  T5      v   M     g 7frD   r   r   s     r   r   @functional_init_with_buffers.<locals>.wrapped.<locals>.<genexpr>I  r   r   c              3   >   #    U  H  n[        U5      S S v   M     g 7f)Nr   )rr   r   s     r   r   r   T  s#      #E ;5A"1E#r   c              3   j   #    U  H)  n[         R                  " U5      R                  5       v   M+     g 7frD   r   r   s     r   r   r   Z  r   r   c              3   j   #    U  H)  n[         R                  " U5      R                  5       v   M+     g 7frD   r   r   s     r   r   r   \  r   r   )r/   r   r   rl   r+   r   rr   r0   )r   r   r\   r   r   rS   r   r^   r_   r]   rY   r)   r   r   s   ``         r   r   -functional_init_with_buffers.<locals>.wrapped?  s$   ~!#KLL~!#0033F;E077#A&
?{:,nEFF 
=B:=N
 
 7{D7SF7ST	
 # 
 W&K7KKW&K7KK<??r   r   r   s   ``` r   functional_init_with_buffersr   :  s    
@@ Nr   r   r*   )r   cpu),rd   collections.abcr   r   typingr   r   r   r   r,   torch.nnr>   r	   %torch.nn.utils._named_member_accessorr
   r   r   r   r+   rk   r"   r   r;   rA   rI   r   rM   rX   r[   ra   rl   rr   rt   r   r   r   r   r   r   inttypesDevicer   r   r   r   r   <module>r      s    . 1 1    EX ,S&[)8E#v+4F+GGH,T#v+.sF{9K0LLM, 
#tCy.,8$	$C%V*<!==>$ x'($ 5uS#XS$s)^0DDE	$2E	E
5uS#XS$s)^0DDEEA	A
5uS#XS$s)^0DDEA 	(	(C=( V( 	(
 
("	#CcN3<DV<L	&\$ 	)	)C=) f) 	)
 
) !#"$99f 3- f	
 3- YY('% '%T"Fbii "FJ5M")) 5Mp#Iryy #IN 9>C99C15C
U63;//0CN 9>:99:15:
&fck(:E&#+<NNO:z$U63;%7%<=
63;;%RYY;%
&fck(:E&#+<NNO;%@ 46!&bii%)U3Z/0 KK: 46!&%bii%%)U3Z/0% KK%r   