U
    9%eE                     @   s&  d dl Z d dlZd dl mZ d dlmZmZmZmZmZm	Z	 d dl
mZmZmZmZ ddlmZ d dlmZ d dlZd dlZd dlmZmZmZmZmZ eeef Zeeeed	f f Zd
d Ze	ee  e	edddZeeeed	f f edddZeeeg e f edddZ!eeeeee	e e	e ef dddZ"e	e e	e eedddZ#dd Z$eeeed	f f eeeeedddZ%d d! Z&eedd"d#d$Z'ed%d&d'Z(d(a)da*d)d* Z+d+d, Z,d-d. Z-d/d0 Z.d1d2 Z/d3d4 Z0d5d6 Z1d7d8 Z2ed9d: Z3ed;d< Z4d=d> Z5d?d@ Z6dS )A    N)Tensor)AnyCallableOptionalTupleUnionList)tree_flattentree_unflatten_broadcast_to_and_flattenTreeSpec   )	tree_map_)partial)_add_batch_dim_remove_batch_dim_vmap_decrement_nesting_vmap_increment_nestingis_batchedtensor.c                    s    dt   fdd}|S )Nzdtorch.func transforms don't yet support saved tensor hooks. Please open an issue with your use case.c               
      s0   t jj  | |W  5 Q R  S Q R X d S N)torchZautogradgraphZdisable_saved_tensors_hooks)argskwargsfmessage T/var/www/html/Darija-Ai-API/env/lib/python3.8/site-packages/torch/_functorch/vmap.pyfn#   s    z.doesnt_support_saved_tensors_hooks.<locals>.fn)	functoolswraps)r   r   r   r   r   "doesnt_support_saved_tensors_hooks   s
    r"   )flat_in_dims	flat_argsreturnc                    sZ   dd t | |D  t dkr(td rRt fdd D rRtd  d d S )	Nc                 S   s"   g | ]\}}|d k	r| |qS r   )size.0in_dimargr   r   r   
<listcomp>.   s    z0_validate_and_get_batch_size.<locals>.<listcomp>r   z/vmap: Expected at least one Tensor to vmap overc                 3   s   | ]}| d  kV  qdS )r   Nr   )r(   r&   Zbatch_sizesr   r   	<genexpr>2   s     z/_validate_and_get_batch_size.<locals>.<genexpr>zTvmap: Expected all tensors to have the same size in the mapped dimension, got sizes z for the mapped dimension)ziplen
ValueErrorany)r#   r$   r   r,   r   _validate_and_get_batch_size+   s    
r2   )batched_outputsr%   c                 C   s   t | trt| S dS )Nr   )
isinstancetupler/   )r3   r   r   r   _num_outputs9   s    
r6   )valuenum_elementserror_message_lambdar%   c                 C   s.   t | ts| f| S t| |kr*t| | S r   )r4   r5   r/   r0   )r7   r8   r9   r   r   r   	_as_tupleB   s
    


r:   )in_dimsr   funcr%   c           	      C   s  t | ts8t | ts8tdt| d|  dt|  dt|dkrXtdt| dt|\}}t| |}|d krtdt| d|  dt| d  d	| d	t	t
||D ]\}\}}t |ts|d k	rtdt| d|  d
| dt |tr4t |ts4tdt| d|  d
| dt| d	|d k	r||  k s\|| krtdt| d|  d
| d|  d|  d|  d|d k	r|dk r||  ||< qt|||||fS )Nvmap(z
, in_dims=zv, ...)(<inputs>): expected `in_dims` to be int or a (potentially nested) tuple matching the structure of inputs, got: .r   z)(<inputs>): got no inputs. Maybe you forgot to add inputs, or you are trying to vmap over a function with no inputs. The latter is unsupported.zb, ...)(<inputs>): in_dims is not compatible with the structure of `inputs`. in_dims has structure r   z but inputs has structure z, ...)(<inputs>): Got in_dim=zE for an input but in_dim must be either an integer dimension or None.z' for an input but the input is of type zT. We cannot vmap over non-Tensor arguments, please use None as the respective in_dimz> for some input, but that input is a Tensor of dimensionality z  so expected in_dim to satisfy -z <= in_dim < )r4   intr5   r0   	_get_nametyper/   r	   r   	enumerater.   r   dimr2   )	r;   r   r<   r$   	args_specr#   ir*   r)   r   r   r   _process_batched_inputsJ   s<    
($(8rF   )r#   r$   
vmap_levelr%   c                    s"    fddt | |D }t||S )Nc                    s(   g | ] \}}|d kr|n
t || qS r   )r   r'   rG   r   r   r+      s   z*_create_batched_inputs.<locals>.<listcomp>)r.   r
   )r#   r$   rG   rD   batched_inputsr   rH   r   _create_batched_inputs|   s    
rJ   c                 C   sp   |d kr6t |tjr2t|r2td|  d|  d|S t |tjsbtd|  d|  dt| dt||||S )Nr=   z	, ...): `z5` can not return a BatchedTensor when out_dim is Nonez%` must only return Tensors, got type z2. Did you mean to set out_dim= to None for output?)r4   r   r   r   r0   rA   r   )namebatched_outputrG   
batch_sizeout_dimr   r   r   _maybe_remove_batch_dim   s     rO   )r3   out_dimsrG   rM   r<   r%   c           	         s   t | \}fdd}t| tjrnttr:g}qttrVtdkrV}qd krfg}q|  nt}|d kr|   fddt||D }t	|S )Nc                
      s2   t dt  d dtd  d d	d S )Nr=   , ..., out_dims=z`)(<inputs>): out_dims is not compatible with the structure of `outputs`. out_dims has structure r   z but outputs has structure r>   )r0   r@   r	   r   )r<   rP   output_specr   r   incompatible_error   s    (z+_unwrap_batched.<locals>.incompatible_errorr   c                    s$   g | ]\}}t t| |qS r   )rO   r@   )r(   rL   rN   )rM   r<   rG   r   r   r+      s   z#_unwrap_batched.<locals>.<listcomp>)
r	   r4   r   r   r?   r5   r/   r   r.   r
   )	r3   rP   rG   rM   r<   Zflat_batched_outputsrS   flat_out_dimsZflat_outputsr   )rM   r<   rP   rR   rG   r   _unwrap_batched   s"    

rU   c                 C   s8   t | trd S | d krd S tdt| d| dd S )Nr=   rQ   z): `out_dims` must be an int, None or a python collection of ints representing where in the outputs the vmapped dimension should appear.)r4   r?   r0   r@   )xr<   rP   r   r   r   _check_int_or_none   s    
rW   )rP   r<   r%   c                 C   s&   t | trd S ttt|| d|  d S )N)r<   rP   )r4   r?   r   r   rW   )rP   r<   r   r   r   $_check_out_dims_is_int_or_int_pytree   s    
rX   r<   c                 C   s   t | dr| jS t| S )N__name__)hasattrrZ   reprrY   r   r   r   r@      s    
r@   Fc                     s   t rd S da tjdddkr"ds&d S tjdddaddlm	   fd	d
} | tj
jjj | tj
jjj | tj
jjj | tj
jjj | tj
jjj | tj
jjj | tj
jjj | tj
jjj d S )NTZPYTORCH_JIT1atenZIMPLZFuncTorchBatchedr   decomposition_tablec                    s,   |  krt |  |   ntd|  d S )Nz!could not find decomposition for )VMAP_DECOMPOSITIONS_LIBimplRuntimeError)decompr_   r   r   #_register_python_decomposition_vmap   s    zElazy_load_decompositions.<locals>._register_python_decomposition_vmap)DECOMPOSITIONS_LOADEDosenvirongetr   ZlibraryLibraryra   Ztorch._decompr`   Zopsr^   Zmse_loss_backwarddefaultZsmooth_l1_loss_backwardZhuber_loss_backwardZnll_loss_forwardZnll_loss2d_forwardZnll_loss_backwardZnll_loss2d_backwardaddr)re   r   r_   r   lazy_load_decompositions   s     rm   c                 O   sh   t   t||  t||| \}}}	}
|d k	rPt|	|||}t| |||
||f|S t| |||	|
||f|S r   )rm   rX   rF   _get_chunked_inputs_chunked_vmap
_flat_vmap)r<   r;   rP   
randomness
chunk_sizer   r   rM   r#   r$   rD   chunks_flat_argsr   r   r   	vmap_impl   s.    
        rt   c                 C   s4   | |  }}|g| }| | }|dkr0| | |S )Nr   )append)Ztotal_elemsrr   Zn_chunkschunk_sizes	remainderr   r   r   get_chunk_sizes  s    

rx   c                    sN   |f |d k	r&t ||}tt| t fddt| |D }t| }|S )Nc                 3   s6   | ].\}}|d k	r |j  |dn|gt  V  qd S N)rC   )Ztensor_splitr/   )r(   tr)   Z
split_idxsr   r   r-     s   z&_get_chunked_inputs.<locals>.<genexpr>)rx   r5   	itertools
accumulater.   )r$   r#   rM   rr   rv   Zflat_args_chunksrs   r   r{   r   rn     s    
rn   c                 C   sH   g }d }| D ]&}t |\}}|| |d kr|}qtt| }||fS r   )r	   ru   listr.   )Zchunks_output_Zflat_chunks_outputarg_specoutputflat_outputZ	arg_specsflat_output_chunksr   r   r   _flatten_chunks_output(  s    
r   c                 C   sX   t | |}t|t|kstg }t|D ](\}}|tj|| |d d ||< q*|S ry   )r   r/   AssertionErrorrB   ru   r   cat)rP   r   r   rT   r   idxrN   r   r   r   _concat_chunked_outputs9  s    

r   c                 K   s   g }|dkrt  nd }|D ]H}	t||	}
|
dkr4q|d k	rFt | |t| |
||	|||f| qt|\}}~t|||}t||S )Nsamer   )	r   Zget_rng_stater2   Zset_rng_stateru   rp   r   r   r
   )r<   r#   rs   rD   rP   rq   r   Zchunks_outputrsr$   rM   r   r   r   r   r   r   ro   G  s2    

      ro   c                 C   s   | dkrt d|  d S )N)errorZ	differentr   zLOnly allowed values for randomness are 'error', 'different', or 'same'. Got )rc   )rq   r   r   r   _check_randomness_argq  s    r   c                 K   sD   t ||}z,t||||}	| |	|}
t|
|||| W S t  X d S r   )r   r   rJ   rU   )r<   rM   r#   r$   rD   rP   rq   r   rG   rI   r3   r   r   r   rp   v  s    

rp   c                    s    fdd}|S )Nc                     s<   t  }z$t| |}||}t||W S t  X d S r   )r   r   wrap_batchedunwrap_batched)r   r   rG   rI   r3   rM   r<   r;   rq   r   r   inner  s    

zrestore_vmap.<locals>.innerr   )r<   r;   rM   rq   r   r   r   r   restore_vmap  s    r   c                 C   s4   t | \}}t||}|d k	s"tt||||}|S r   )r	   r   r   rJ   )r   bdimslevelr$   specZ
flat_bdimsresultr   r   r   r     s
    
r   c                    sR   t | \}}t|dkr | dfS  fdd|D }t| \}}t||t||fS )Nr   r   c                    s0   g | ](}t |tjr$tjj| n|d fqS r   )r4   r   r   Z_CZ
_functorchrU   )r(   r*   r   r   r   r+     s   z"unwrap_batched.<locals>.<listcomp>)r	   r/   r.   r
   )r   r   r$   r   r   r   r   r   r   r   r     s    
r   )7r   r    r   typingr   r   r   r   r   r   Ztorch.utils._pytreer	   r
   r   r   Zpytree_hacksr   r   rg   r|   Ztorch._C._functorchr   r   r   r   r   r?   Z	in_dims_tZ
out_dims_tr"   r2   r6   strr:   rF   rJ   rO   rU   rW   rX   r@   rf   ra   rm   rt   rx   rn   r   r   ro   r   rp   r   r   r   r   r   r   r   <module>   sn    
  		  3   	   $
"	*

