Ë
    ÃÓ^j¬_  ã                  ó4  — d dl mZ d dlZd dlmZmZmZ d dlZd dlm	Z	 d dlm
Z
 d dlmZ er
d dlmZmZmZ dd„Z	 	 	 	 	 	 dd„Z	 	 	 	 	 	 	 	 dd	„Z	 	 	 	 dd
„Z	 	 	 	 dd„Z	 d 	 	 	 	 	 	 	 	 	 d!d„Z	 	 	 	 	 	 	 	 d"d„Z	 d 	 	 	 	 	 	 	 	 	 d#d„Z	 	 d$	 	 	 	 	 	 	 	 	 	 	 d%d„Z	 	 	 	 d&d„Z	 	 	 	 d'd„Z G d„ de	j8                  «      Z G d„ de	j8                  «      Z	 d 	 	 	 	 	 d(d„Z	 d 	 	 	 	 	 d)d„Z 	 	 	 	 d*d„Z!	 	 	 	 d+d„Z"	 	 d,	 	 	 	 	 	 	 d-d„Z#	 	 d,	 	 	 	 	 	 	 d.d„Z$y)/é    )ÚannotationsN)ÚAnyÚNoReturnÚTYPE_CHECKING)ÚTensor)ÚNamedMemberAccessor)ÚCallableÚIterableÚSequencec                 ó   — t        d«      ‚)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© ó    úk/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/torch/_functorch/make_functional.pyÚraise_parameter_tying_errorr      s   € Ü
ð	:óð r   c                óÎ  — t        | «      }t        |«      }t        |j                  «       «      }t        |j                  «       «      }|j                  |«      st	        d|› d|› �«      ‚i }|j                  «       D ]  \  }}|g f||<   Œ |j                  «       D ]/  \  }}||vrt	        d|› d�«      ‚||   d   j                  |«       Œ1 t        |j                  «       «      S )a[  
    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']}.
    ztensors_dict_keys z+ is not a subset of tied_tensors_dict_keys ztensor for key 'z ' not found in tensor_to_mappingé   )ÚdictÚsetÚkeysÚissubsetÚAssertionErrorÚitemsÚappendÚvalues)	Únamed_paramsÚtied_named_paramsÚnamed_params_dictÚtied_named_params_dictÚtensors_dict_keysÚtied_tensors_dict_keysÚtensor_to_mappingÚkeyÚtensors	            r   Úcreate_names_mapr%   $   s  € ô ˜\Ó*ÐÜ!Ð"3Ó4ÐäÐ-×2Ñ2Ó4Ó5ÐÜ Ð!7×!<Ñ!<Ó!>Ó?ÐØ×%Ñ%Ð&<Ô=ÜØ Ð!2Ð 3ð 4&Ø&<Ð%=ð?ó
ð 	
ð
 >@ÐØ(×.Ñ.Ó0ò .‰ˆˆVØ%(¨" IÐ˜&Ò!ð.à-×3Ñ3Ó5ò 1‰ˆˆVØÐ*Ñ*Ü Ø" 3 %Ð'GÐHóð ð 	˜&Ñ! !Ñ$×+Ñ+¨CÕ0ð1ô Ð!×(Ñ(Ó*Ó+Ð+r   c                óN  — t         |d¬«      «      }t         |d¬«      «      }t        ||«      }i }t        | «      }|D ]@  \  }}	|	|vr  |t        j                  |	d¬«      «      ||	<   ||	   }
|j                  ||
«       ŒB t        |«      dk(  rd\  }}nt        |Ž \  }}|||fS )NF)Úremove_duplicateTÚmeta)Údevicer   ©r   r   )Útupler%   r   ÚtorchÚ
empty_likeÚ
set_tensorÚlenÚzip)ÚmodÚnamed_membersÚsubclassÚall_named_membersÚunique_named_membersÚ	names_mapÚmemoÚaccessorÚnameÚpÚreplacementÚnamesÚparamss                r   Ú_extract_membersr>   G   sÆ   € ô
 ™m¸UÔCÓDÐÜ ¡ÀÔ!EÓFÐÜ Ð!5Ð7HÓI€Ið €DÜ" 3Ó'€HØ$ò /‰ˆˆaØ�D‰=Ùœu×/Ñ/°¸&ÔAÓBˆD�‰GØ˜1‘gˆØ×Ñ˜D +Õ.ð	/ô ÐÓ  AÒ%Ø‰ˆ‰väÐ1Ð2‰ˆˆvØ�5˜)Ð#Ð#r   c                óL   — t        | | j                  t        j                  «      S )aZ  
    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©r1   s    r   Úextract_weightsrD   a   s   € ô ˜C ×!5Ñ!5´r·|±|ÓDÐDr   c                ó2   — t        | | j                  d„ «      S )Nc                ó   — | S ©Nr   )Úxs    r   ú<lambda>z!extract_buffers.<locals>.<lambda>r   s   € ¸a€ r   )r>   Únamed_buffersrC   s    r   Úextract_buffersrK   o   s   € ô ˜C ×!2Ñ!2±KÓ@Ð@r   c                ó�   — t        | «      }|r"|D �cg c]  }t        j                  |«      ‘Œ }}|j                  ||«       yc c}w )a	  
    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   rA   rB   Úset_tensors)r1   r<   r=   Ú	as_paramsr8   r:   s         r   Úload_weightsrO   u   sA   € ô # 3Ó'€HÙØ+1Ö2 a”"—,‘,˜q•/Ð2ˆÐ2Ø×Ñ˜ Õ'ùò 3s   ’Ac                ó  — g }t        | «      }t        |j                  «       |«      D ]T  \  \  }}}t        |«      D ]>  \  }}	|dk(  r"|j	                  |j                  |	|«      «       Œ-|j                  |	|«       Œ@ ŒV |S )Nr   )r   r0   r   Ú	enumerater   Úswap_tensorr.   )
r1   r6   ÚelemsÚresultr8   Ú_Ú
attr_namesÚelemÚiÚ	attr_names
             r   Ú_swap_staterZ   †   sˆ   € ð €FÜ" 3Ó'€HÜ!$ Y§_¡_Ó%6¸Ó!>ò 5Ñ‰ˆˆJ˜Ü% jÓ1ò 	5‰LˆAˆyØ�AŠvØ—‘˜h×2Ñ2°9¸dÓCÕDà×#Ñ# I¨tÕ4ñ		5ð5ð €Mr   c                ó>   — t        | «      }|j                  ||«       y rG   )r   rM   )r1   r<   ÚbuffersrN   r8   s        r   Úload_buffersr]   ”   s   € ô # 3Ó'€HØ×Ñ˜ Õ(r   c                ó>  — t        |«      t        |«      k7  r#t        dt        |«      › dt        |«      › �«      ‚t        | ||«       t        |«      dkD  rGt        |«      t        |«      k7  r#t        dt        |«      › dt        |«      › �«      ‚t        | ||«       | S )zæload_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`.
    zlen(weight_names)=z != len(weights)=r   zlen(buffer_names)=z != len(buffers)=)r/   r   rO   r]   )ÚmodelÚweightsÚweight_namesr\   Úbuffer_namess        r   Ú
load_staterc   ž   s£   € ô ˆ<ÓœC ›LÒ(ÜØ ¤ \Ó!2Ð 3Ð3DÄSÈÃ\ÀNÐSó
ð 	
ô �˜ gÔ.Ü
ˆ7ƒ|�aÒÜˆ|Ó¤ G£Ò,Ü Ø$¤S¨Ó%6Ð$7Ð7HÌÈWËÈÐWóð ô 	�U˜L¨'Ô2Ø€Lr   c                ó    ‡ ‡— t        ‰ j                  «       «      }t        |«      dkD  rt        d«      ‚t	        ‰ «      \  }Š}dˆˆ fd„}||‰fS )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   z€make_functional_deprecated_v1(model): `model` has buffers. Please use make_functional_with_buffers_deprecated_v1(model) instead.c                óR   •— t        j                  ‰«      }t        |‰| «        ||Ž S rG   )ÚcopyÚdeepcopyrO   )r`   ÚdataÚmutable_modelÚdescriptorsr_   s      €€r   Úfunz*make_functional_deprecated_v1.<locals>.funÜ   s(   ø€ ÜŸ™ eÓ,ˆÜ�] K°Ô9Ù˜dÐ#Ð#r   )r`   útuple[Tensor, ...]rh   útuple[Any, ...]Úreturnr   )Úlistr\   r/   r   rD   )r_   r\   r`   rU   rk   rj   s   `    @r   Úmake_functional_deprecated_v1rp   ¸   s[   ù€ ô8 �5—=‘=“?Ó#€GÜ
ˆ7ƒ|�aÒÜðIó
ð 	
ô .¨eÓ4Ñ€Gˆ[˜!ö$ð
 �C˜Ð$Ð$r   c                ór   ‡ ‡‡— t        ‰ «      \  }Š}t        ‰ «      \  }Š}	 	 	 	 	 	 	 	 dˆˆ ˆfd„}|||‰‰fS )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                ól   •— t        j                  ‰«      }t        |‰| «       t        |‰|«        ||Ž S rG   )rf   rg   rO   r]   )r`   r\   rh   ri   Úbuf_descriptorsr_   Úweight_descriptorss       €€€r   rk   z7make_functional_with_buffers_deprecated_v1.<locals>.fun  s7   ø€ ô
 Ÿ™ eÓ,ˆÜ�]Ð$6¸Ô@Ü�] O°WÔ=Ù˜dÐ#Ð#r   )r`   rl   r\   rl   rh   rm   rn   r   )rD   rK   )r_   r`   rU   r\   rk   rs   rt   s   `    @@r   Ú*make_functional_with_buffers_deprecated_v1ru   ä   sf   ú€ ôB &5°UÓ%;Ñ"€GÐ Ü"1°%Ó"8Ñ€Gˆ_˜að$Ø#ð$à#ð$ð ð$ð 
÷	$ð �G˜SÐ"4°oÐEÐEr   c                  óx   ‡ — e Zd ZdZ	 	 	 	 	 	 	 	 	 	 	 	 dˆ fd„Ze	 d	 	 	 	 	 dd„«       Z	 	 	 	 	 	 	 	 	 	 dd„Zˆ xZS )	ÚFunctionalModuleWithBufferszW
    This is the callable object returned by :func:`make_functional_with_buffers`.
    c                ó¢   •— t         ‰| �  «        || _        || _        || _        t        |«      | _        | j                  j                  |«       y rG   )ÚsuperÚ__init__Ústateless_modelÚparam_namesrb   r   Úall_names_mapÚupdate)Úselfr{   r|   rb   Úparam_names_mapÚbuffer_names_mapÚ	__class__s         €r   rz   z$FunctionalModuleWithBuffers.__init__  sJ   ø€ ô 	‰ÑÔØ.ˆÔØ&ˆÔØ(ˆÔä! /Ó2ˆÔØ×Ñ×!Ñ!Ð"2Õ3r   c                óÀ   — t        j                  | «      }t        |«      \  }}}t        |«      \  }}}|r|D ]  }	|	j	                  d«       Œ t        |||||«      ||fS ©NF)rf   rg   rD   rK   Úrequires_grad_rw   )
r_   Údisable_autograd_trackingÚ
model_copyr=   r|   r€   r\   rb   r�   Úparams
             r   Ú_create_fromz(FunctionalModuleWithBuffers._create_from*  s}   € ô
 —]‘] 5Ó)ˆ
Ü/>¸zÓ/JÑ,ˆ�˜_Ü2AÀ*Ó2MÑ/ˆ�Ð/Ù$Øò ,�Ø×$Ñ$ UÕ+ð,ô (Ø˜K¨°ÐHXóð Øð
ð 	
r   c                ó"  — t        | j                  | j                  t        |«      t        |«      z   «      }	  | j                  |i |¤Žt        | j                  | j                  |«       S # t        | j                  | j                  |«       w xY wrG   )rZ   r{   r}   r+   )r   r=   r\   ÚargsÚkwargsÚ	old_states         r   Úforwardz#FunctionalModuleWithBuffers.forward=  s~   € ô  Ø× Ñ Ø×ÑÜ�&‹MœE '›NÑ*ó
ˆ	ð
	MØ'�4×'Ñ'¨Ð8°Ñ8ô ˜×,Ñ,¨d×.@Ñ.@À)ÕLøŒK˜×,Ñ,¨d×.@Ñ.@À)ÕLús   ¸A+ Á+#B)r{   ú	nn.Moduler|   útuple[str, ...]rb   r�   r€   údict[str, list[str]]r�   r‘   rn   ÚNone©F©r_   r�   r†   Úboolrn   úJtuple[FunctionalModuleWithBuffers, tuple[Tensor, ...], tuple[Tensor, ...]])
r=   úIterable[Tensor]r\   r—   r‹   r   rŒ   r   rn   r   ©	Ú__name__Ú
__module__Ú__qualname__Ú__doc__rz   Ústaticmethodr‰   rŽ   Ú__classcell__©r‚   s   @r   rw   rw     s±   ø„ ñð4à"ð4ð %ð4ð &ð	4ð
 .ð4ð /ð4ð 
õ4ð  à<Að
Øð
Ø59ð
à	Sò
ó ð
ð$Mà ðMð "ðMð ð	Mð
 ðMð 
÷Mr   rw   c                  ó\   ‡ — e Zd ZdZ	 	 	 	 	 	 	 	 dˆ fd„Ze	 d	 	 	 	 	 dd„«       Zdd„Zˆ xZS )	ÚFunctionalModulezJ
    This is the callable object returned by :func:`make_functional`.
    c                óL   •— t         ‰| �  «        || _        || _        || _        y rG   )ry   rz   r{   r|   r6   )r   r{   r|   r6   r‚   s       €r   rz   zFunctionalModule.__init__V  s'   ø€ ô 	‰ÑÔØ.ˆÔØ&ˆÔØ"ˆ�r   c                óœ   — t        j                  | «      }t        |«      \  }}}|r|D ]  }|j                  d«       Œ t	        |||«      |fS r„   )rf   rg   rD   r…   r¡   )r_   r†   r‡   r=   r|   r6   rˆ   s          r   r‰   zFunctionalModule._create_froma  sW   € ô
 —]‘] 5Ó)ˆ
Ü)8¸Ó)DÑ&ˆ�˜YÙ$Øò ,�Ø×$Ñ$ UÕ+ð,ä 
¨K¸ÓCÀVÐKÐKr   c                óø   — t        | j                  | j                  |«      }	  | j                  |i |¤Žt        | j                  | j                  |«       S # t        | j                  | j                  |«       w xY wrG   )rZ   r{   r6   )r   r=   r‹   rŒ   r�   s        r   rŽ   zFunctionalModule.forwardm  sd   € ä × 4Ñ 4°d·n±nÀfÓMˆ	ð	IØ'�4×'Ñ'¨Ð8°Ñ8ô ˜×,Ñ,¨d¯n©n¸iÕHøŒK˜×,Ñ,¨d¯n©n¸iÕHús   £A Á#A9)r{   r�   r|   r�   r6   r‘   rn   r’   r“   ©r_   r�   r†   r•   rn   z+tuple[FunctionalModule, tuple[Tensor, ...]])r=   r—   r‹   r   rŒ   r   rn   r   r˜   rŸ   s   @r   r¡   r¡   Q  sm   ø„ ñð	#à"ð	#ð %ð	#ð (ð		#ð
 
õ	#ð à<Að	LØð	LØ59ð	Là	4ò	Ló ð	L÷Ir   r¡   c                ó”   — t        | j                  «       «      }t        |«      dkD  rt        d«      ‚t        j                  | |¬«      S )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†   )ro   r\   r/   r   r¡   r‰   )r_   r†   r\   s      r   Úmake_functionalr¨   w  sS   € ôz �5—=‘=“?Ó#€GÜ
ˆ7ƒ|�aÒÜð;ó
ð 	
ô ×(Ñ(ØÐ)Bð )ó ð r   c                ó0   — t         j                  | |¬«      S )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§   )rw   r‰   )r_   r†   s     r   Úmake_functional_with_buffersrª   ¿  s#   € ôt '×3Ñ3ØÐ)Bð 4ó ð r   c                óL   — t        t        | Ž «      } t        d„ | D «       «      }|S )Nc              3  ób   K  — | ]'  }t        j                  |«      j                  «       –— Œ) y ­wrG   ©r,   ÚstackÚdetach©Ú.0Úshardss     r   ú	<genexpr>z"transpose_stack.<locals>.<genexpr>  s'   è ø€ ò Ø)/Œ�‰�FÓ×"Ñ"×$ñùó   ‚-/)r+   r0   )Útuple_of_tuple_of_tensorsÚresultss     r   Útranspose_stackr·   þ  s3   € ô !&¤cÐ+DÐ&EÓ FÐÜñ Ø3Lôó €Gð €Nr   c                óz  ‡— t        | «      dk(  rt        d«      ‚t        d„ | D «       «      st        d„ | D «       «      st        d«      ‚t        | d   «      Št        ˆfd„| D «       «      st        d«      ‚t	        | D �cg c]  }t        |«      ‘Œ c}Ž \  }}}t        |«      }t        |«      }|d   ||fS c c}w )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  ó4   K  — | ]  }|j                   –— Œ y ­wrG   ©Útraining©r±   Úms     r   r³   z-combine_state_for_ensemble.<locals>.<genexpr>4  s   è ø€ Ò+˜q�—
•
Ñ+ùs   ‚c              3  ó6   K  — | ]  }|j                    –— Œ y ­wrG   rº   r¼   s     r   r³   z-combine_state_for_ensemble.<locals>.<genexpr>4  s   è ø€ Ò2RÀa°q·z±z´>Ñ2Rùs   ‚zTcombine_state_for_ensemble: Expected all models to have the same training/eval mode.c              3  ó8   •K  — | ]  }t        |«      ‰u –— Œ y ­wrG   )Útype)r±   r½   Ú
model0_typs     €r   r³   z-combine_state_for_ensemble.<locals>.<genexpr>:  s   øè ø€ Ò5¨Œt�A‹w˜*Ô$Ñ5ùs   ƒzHcombine_state_for_ensemble: Expected all models to be of the same class.)r/   r   ÚallrÀ   r0   rª   r·   )Úmodelsr_   Úfuncsr=   r\   rÁ   s        @r   Úcombine_state_for_ensemblerÅ     sÒ   ø€ ôP ˆ6ƒ{�aÒÜØMó
ð 	
ô Ñ+ FÔ+Ô+¬sÑ2RÈ6Ô2RÔ/RÜð0ó
ð 	
ô �f˜Q‘i“€JÜÓ5¨fÔ5Ô5ÜØVó
ð 	
ô !Ø;AÖ	B°%Ô
& uÕ
-Ò	BðÑ€Eˆ6�7ô ˜VÓ$€FÜ˜gÓ&€GØ�‰8�V˜WÐ$Ð$ùò	 
Cs   Â B8c                ó(   ‡ ‡‡— 	 	 	 	 	 	 dˆˆˆ fd„}|S )Nc                 óª  •‡ ‡— t        ‰
«      dk\  rt        d«      ‚t        ‰
«      dk(  r" ‰‰ i ‰¤Žj                  ‰	«      }t        |«      S ‰
d   }|dk  rt        d|› d�«      ‚t	        ˆ ˆ	ˆˆfd„t        |«      D «       «      }t         ‰‰ i ‰¤Ž«      \  }}}t	        d„ |D «       «      }t	        t        |Ž «      }t	        d„ |D «       «      }|||fS )	Né   ú,NYI: ensemble_shape with more than 1 elementr   únum_models ú should be > 0c              3  óL   •K  — | ]  } ‰‰i ‰¤Žj                  ‰«      –— Œ y ­wrG   ©Úto©r±   rU   r‹   r)   rŒ   Úmodel_classs     €€€€r   r³   z3functional_init.<locals>.wrapped.<locals>.<genexpr>W  ó+   øè ø€ ò 
Ø89‰K˜Ð( Ñ(×+Ñ+¨F×3ñ
ùó   ƒ!$c              3  ó8   K  — | ]  }t        |«      d    –— Œ y­w)r   N)rp   ©r±   r_   s     r   r³   z3functional_init.<locals>.wrapped.<locals>.<genexpr>[  s   è ø€ ÒTÀEÔ5°eÓ<¸QÕ?ÑTùó   ‚c              3  ób   K  — | ]'  }t        j                  |«      j                  «       –— Œ) y ­wrG   r­   r°   s     r   r³   z3functional_init.<locals>.wrapped.<locals>.<genexpr>]  ó"   è ø€ ÒK¸œŸ™ FÓ+×2Ñ2×4ÑKùr´   )r/   Ú
ValueErrorrÎ   rp   r+   Úranger0   )r‹   rŒ   r_   Ú
num_modelsrÃ   rU   Úfnr<   r`   r)   Úensemble_shaperÐ   s   ``       €€€r   Úwrappedz functional_init.<locals>.wrappedK  sè   ú€ ô ˆ~Ó !Ò#ÜÐKÓLÐLÜˆ~Ó !Ò#Ù Ð0¨Ñ0×3Ñ3°FÓ;ˆEÜ0°Ó7Ð7Ø# AÑ&ˆ
Ø˜Š?Ü˜{¨:¨,°nÐEÓFÐFäö 
Ü=BÀ:Ó=Nô
ó 
ˆô 5±[À$Ð5QÈ&Ñ5QÓR‰ˆˆ2ˆuÜÑTÈVÔTÓTˆÜœ˜W˜Ó&ˆÜÑKÀ7ÔKÓKˆØ˜˜EÐ!Ð!r   )r‹   r   rŒ   r   rn   ú>tuple[tuple[Tensor, ...], Callable[..., Any], tuple[str, ...]]r   ©rÐ   rÜ   r)   rÝ   s   ``` r   Úfunctional_initrà   F  s'   ú€ ð
"Øð"Ø!ð"à	G÷"ð* €Nr   c                ó(   ‡ ‡‡— 	 	 	 	 	 	 dˆˆˆ fd„}|S )Nc                 ó
  •‡ ‡— t        ‰«      dk\  rt        d«      ‚t        ‰«      dk(  r" ‰‰ i ‰¤Žj                  ‰«      }t        |«      S ‰d   }|dk  rt        d|› d�«      ‚t	        ˆ ˆˆˆfd„t        |«      D «       «      }t         ‰‰ i ‰¤Ž«      \  }}}}}t        t	        d„ |D «       «      Ž \  }	}
t	        t        |	Ž «      }	t	        d„ |	D «       «      }	t	        t        |
Ž «      }
t	        d	„ |
D «       «      }
|	|
|||fS )
NrÈ   rÉ   r   rÊ   rË   c              3  óL   •K  — | ]  } ‰‰i ‰¤Žj                  ‰«      –— Œ y ­wrG   rÍ   rÏ   s     €€€€r   r³   z@functional_init_with_buffers.<locals>.wrapped.<locals>.<genexpr>‡  rÑ   rÒ   c              3  ó8   K  — | ]  }t        |«      d d –— Œ y ­w)NrÈ   )ru   rÔ   s     r   r³   z@functional_init_with_buffers.<locals>.wrapped.<locals>.<genexpr>’  s$   è ø€ ò àô ;¸5ÓAÀ"À1ÔEñùrÕ   c              3  ób   K  — | ]'  }t        j                  |«      j                  «       –— Œ) y ­wrG   r­   r°   s     r   r³   z@functional_init_with_buffers.<locals>.wrapped.<locals>.<genexpr>˜  r×   r´   c              3  ób   K  — | ]'  }t        j                  |«      j                  «       –— Œ) y ­wrG   r­   r°   s     r   r³   z@functional_init_with_buffers.<locals>.wrapped.<locals>.<genexpr>š  r×   r´   )r/   rØ   rÎ   rp   r+   rÙ   ru   r0   )r‹   rŒ   r_   rÚ   rÃ   rU   rÛ   ra   rb   r`   r\   r)   rÜ   rÐ   s   ``         €€€r   rÝ   z-functional_init_with_buffers.<locals>.wrappedr  s,  ú€ ô ˆ~Ó !Ò#ÜÐKÓLÐLÜˆ~Ó !Ò#Ù Ð0¨Ñ0×3Ñ3°FÓ;ˆEÜ0°Ó7Ð7Ø# AÑ&ˆ
Ø˜Š?Ü˜{¨:¨,°nÐEÓFÐFäö 
Ü=BÀ:Ó=Nô
ó 
ˆô 7±{ÀDÐ7SÈFÑ7SÓTñ	
ØØØØØäÜñ à#ôó ð
Ñˆ�ô œ˜W˜Ó&ˆÜÑKÀ7ÔKÓKˆÜœ˜W˜Ó&ˆÜÑKÀ7ÔKÓKˆØ˜  \°<Ð?Ð?r   )r‹   r   rŒ   r   rn   z¤tuple[tuple[Tensor, ...], tuple[Tensor, ...], Callable[..., Any], tuple[str, ...], tuple[str, ...]] | tuple[tuple[Tensor, ...], Callable[..., Any], tuple[str, ...]]r   rß   s   ``` r   Úfunctional_init_with_buffersrç   c  s/   ú€ ð)@Øð)@Ø!ð)@ð	I÷)@ðV €Nr   )rn   r   )r   ú0dict[str, Tensor] | Iterable[tuple[str, Tensor]]r   rè   rn   r‘   )r1   r�   r2   z+Callable[..., Iterable[tuple[str, Tensor]]]r3   zCallable[[Tensor], Tensor]rn   ú@tuple[tuple[Tensor, ...], tuple[str, ...], dict[str, list[str]]])r1   r�   rn   ré   r“   )
r1   r�   r<   úSequence[str]r=   úSequence[Tensor]rN   r•   rn   r’   )r1   r�   r6   r‘   rS   r—   rn   zlist[Tensor])
r1   r�   r<   rê   r\   rë   rN   r•   rn   r’   r*   )r_   r�   r`   rë   ra   rê   r\   rë   rb   rê   rn   r�   )r_   r�   rn   rÞ   )r_   r�   rn   zctuple[tuple[Tensor, ...], tuple[Tensor, ...], Callable[..., Any], tuple[str, ...], tuple[str, ...]]r¥   r”   )rµ   ztuple[tuple[Tensor, ...], ...]rn   rl   )rÃ   zSequence[nn.Module]rn   r–   )r   Úcpu)rÐ   útype[nn.Module]rÜ   útuple[()] | tuple[int, ...]r)   útorch.types.Devicern   zMCallable[..., tuple[tuple[Tensor, ...], Callable[..., Any], tuple[str, ...]]])rÐ   rí   rÜ   rî   r)   rï   rn   z³Callable[..., tuple[tuple[Tensor, ...], tuple[Tensor, ...], Callable[..., Any], tuple[str, ...], tuple[str, ...]] | tuple[tuple[Tensor, ...], Callable[..., Any], tuple[str, ...]]])%Ú
__future__r   rf   Útypingr   r   r   r,   Útorch.nnrA   r   Ú%torch.nn.utils._named_member_accessorr   Úcollections.abcr	   r
   r   r   r%   r>   rD   rK   rO   rZ   r]   rc   rp   ru   ÚModulerw   r¡   r¨   rª   r·   rÅ   rà   rç   r   r   r   ú<module>rö      s²  ðõ #ã ß /Ñ /ã Ý Ý Ý Eñ ß<Ñ<óð ,ØBð ,àGð ,ð ó ,ðF$Ø	ð$à>ð$ð )ð$ð Fó	$ð4EØ	ðEàEóEðAØ	ðAàEóAð ð	(Ø	ð(àð(ð ð(ð ð	(ð
 
ó(ð"Ø	ðØ3ðØ<Lðàóð$ ð	)Ø	ð)àð)ð ð)ð ð	)ð
 
ó)ð !#Ø"$ðØðàðð  ðð ð	ð
  ðð óð4)%Øð)%àCó)%ðX.FØð.Fðó.Fôb9M "§)¡)ô 9Môx#I�r—y‘yô #IðN 9>ðEØðEØ15ðEà0óEðR 9>ð<Øð<Ø15ð<àOó<ð~Ø=ðàóð;%Øð;%àOó;%ð@ 35Ø!&ðØ ðà/ðð ðð Só	ð> 35Ø!&ð:Ø ð:à/ð:ð ð:ð
ô	:r   