
    9j_                    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     `/media/conek/DATA/Code/OCR/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    
 mUCD !EF !57HII D"3'H$ /aD=u//&ABDG1g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!5r||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!2K@@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2a",,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 	5LAyAvh229dCD##It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 )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`.
    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 33DS\NS
 	
 g.
7|a|G, $S%6$77HWW  	UL'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   zmake_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@]OW=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 &5U%;"G"1%"8G_a$#$#$ $ 
	$ GS"4o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~        &ME'N*
	
	M'4''88 ,,d.@.@)LK,,d.@.@)Ls   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CV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 4dnnfM		I'4''88 ,,dnniHK,,dnniHs   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     2Raqzz>2Rs   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tAw*$5s   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++s2R62R/R0
 	
 fQiJ5f55V
 	
 !;A	B%
&u
-	BE67 V$Fg&G8VW$$	 
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  +      
89K((++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     TE5e<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Kr   )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3F;E077#A&
?{:,nEFF 
=B:=N
 
 5[$5Q&5QR2uTVTTW&K7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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   r   r   rn   ztuple[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   zCallable[..., 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ryy #IN 9>EE15E0ER 9><<15<O<~=;%;%O;%@ 35!& /  S	> 35!&: :/: :
	:r   