


"""simple docstring"""



import logging
import math
from functools import partial
from typing import Any, Callable, Dict, Iterable, List, Optional, Sequence, Tuple, Union

import torch

from .tensor_utils import tensor_tree_map, tree_map






def       lowerCamelCase					(a_						:Union[dict, list, tuple, torch.Tensor])     ->							List[Tuple[int, ...]]:
       lowercase		:List[str]       							=				[]
       if isinstance(a_				,				a_):
              for v in tree.values():
                     shapes.extend(_fetch_dims(a_))
       elif isinstance(a_				,				(list, tuple)):
              for t in tree:
                     shapes.extend(_fetch_dims(a_))
       elif isinstance(a_				,				torch.Tensor):
              shapes.append(tree.shape)
       else:
              raise ValueError('''Not supported''')

       return shapes






@torch.jit.ignore
def       lowerCamelCase					(a_						:int				,				a_						:Tuple[int, ...])     ->							Tuple[int, ...]:
       lowercase		:Optional[Any]       							=				[]
       for d in reversed(a_):
              idx.append(flat_idx % d)
              lowercase		:Union[str, Any]       							=				flat_idx // d

       return tuple(reversed(a_))






@torch.jit.ignore
def       lowerCamelCase					(a_						:Sequence[int]				,				a_						:Sequence[int]				,				a_						:Sequence[int]				,				a_						:Optional[Sequence[bool]] = None				,				a_						:Optional[Sequence[bool]] = None				,				)     ->							List[Tuple[slice, ...]]:

       # start_edges and end_edges both indicate whether, starting from any given
       # dimension, the start/end index is at the top/bottom edge of the
       # corresponding tensor, modeled as a tree
       def reduce_edge_list(a_						:List[bool]) -> None:
              lowercase		:Optional[int]       							=				True
              for i in range(len(a_)):
                     lowercase		:Tuple       							=				-1 * (i + 1)
                     l[reversed_idx] &= tally
                     lowercase		:Optional[Any]       							=				l[reversed_idx]

       if start_edges is None:
              lowercase		:Optional[Any]       							=				[s == 0 for s in start]
              reduce_edge_list(a_)
       if end_edges is None:
              lowercase		:int       							=				[e == (d - 1) for e, d in zip(a_				,				a_)]
              reduce_edge_list(a_)

       # Base cases. Either start/end are empty and we're done, or the final,
       # one-dimensional tensor can be simply sliced
       if len(a_) == 0:
              return [()]
       elif len(a_) == 1:
              return [(slice(start[0]				,				end[0] + 1),)]

       lowercase		:List[Tuple[slice, ...]]       							=				[]
       lowercase		:List[slice]       							=				[]

       # Dimensions common to start and end can be selected directly
       for s, e in zip(a_				,				a_):
              if s == e:
                     path_list.append(slice(a_				,				s + 1))
              else:
                     break

       lowercase		:Tuple[slice, ...]       							=				tuple(a_)
       lowercase		:int       							=				len(a_)

       # start == end, and we're done
       if divergence_idx == len(a_):
              return [path]

       def upper() -> Tuple[Tuple[slice, ...], ...]:
              assert start_edges is not None
              assert end_edges is not None

              lowercase		:Any       							=				start[divergence_idx]
              return tuple(
                  path + (slice(a_				,				sdi + 1),) + s
                  for s in _get_minimal_slice_set(
                      start[divergence_idx + 1 :]				,				[d - 1 for d in dims[divergence_idx + 1 :]]				,				dims[divergence_idx + 1 :]				,				start_edges=start_edges[divergence_idx + 1 :]				,				end_edges=[True for _ in end_edges[divergence_idx + 1 :]]				,				))

       def lower() -> Tuple[Tuple[slice, ...], ...]:
              assert start_edges is not None
              assert end_edges is not None

              lowercase		:Tuple       							=				end[divergence_idx]
              return tuple(
                  path + (slice(a_				,				edi + 1),) + s
                  for s in _get_minimal_slice_set(
                      [0 for _ in start[divergence_idx + 1 :]]				,				end[divergence_idx + 1 :]				,				dims[divergence_idx + 1 :]				,				start_edges=[True for _ in start_edges[divergence_idx + 1 :]]				,				end_edges=end_edges[divergence_idx + 1 :]				,				))

       # If both start and end are at the edges of the subtree rooted at
       # divergence_idx, we can just select the whole subtree at once
       if start_edges[divergence_idx] and end_edges[divergence_idx]:
              slices.append(path + (slice(start[divergence_idx]				,				end[divergence_idx] + 1),))
       # If just start is at the edge, we can grab almost all of the subtree,
       # treating only the ragged bottom edge as an edge case
       elif start_edges[divergence_idx]:
              slices.append(path + (slice(start[divergence_idx]				,				end[divergence_idx]),))
              slices.extend(lower())
       # Analogous to the previous case, but the top is ragged this time
       elif end_edges[divergence_idx]:
              slices.extend(upper())
              slices.append(path + (slice(start[divergence_idx] + 1				,				end[divergence_idx] + 1),))
       # If both sides of the range are ragged, we need to handle both sides
       # separately. If there's contiguous meat in between them, we can index it
       # in one big chunk
       else:
              slices.extend(upper())
              lowercase		:Dict       							=				end[divergence_idx] - start[divergence_idx]
              if middle_ground > 1:
                     slices.append(path + (slice(start[divergence_idx] + 1				,				end[divergence_idx]),))
              slices.extend(lower())

       return slices






@torch.jit.ignore
def       lowerCamelCase					(a_						:torch.Tensor				,				a_						:int				,				a_						:int				,				a_						:int)     ->							torch.Tensor:
       lowercase		:Union[str, Any]       							=				t.shape[:no_batch_dims]
       lowercase		:int       							=				list(_flat_idx_to_idx(a_				,				a_))
       # _get_minimal_slice_set is inclusive
       lowercase		:Union[str, Any]       							=				list(_flat_idx_to_idx(flat_end - 1				,				a_))

       # Get an ordered list of slices to perform
       lowercase		:Union[str, Any]       							=				_get_minimal_slice_set(
           a_				,				a_				,				a_				,				)

       lowercase		:Tuple       							=				[t[s] for s in slices]

       return torch.cat([s.view((-1,) + t.shape[no_batch_dims:]) for s in sliced_tensors])






def       lowerCamelCase					(a_						:Callable				,				a_						:Dict[str, Any]				,				a_						:int				,				a_						:int				,				a_						:bool = False				,				a_						:Any = None				,				a_						:bool = False				,				)     ->							Any:
       if not (len(a_) > 0):
              raise ValueError('''Must provide at least one input''')

       lowercase		:Any       							=				[shape[:no_batch_dims] for shape in _fetch_dims(a_)]
       lowercase		:List[str]       							=				tuple([max(a_) for s in zip(*a_)])

       def _prep_inputs(a_						:torch.Tensor) -> torch.Tensor:
              if not low_mem:
                     if not sum(t.shape[:no_batch_dims]) == no_batch_dims:
                            lowercase		:Optional[int]       							=				t.expand(orig_batch_dims + t.shape[no_batch_dims:])
                     lowercase		:Any       							=				t.reshape(-1				,				*t.shape[no_batch_dims:])
              else:
                     lowercase		:List[str]       							=				t.expand(orig_batch_dims + t.shape[no_batch_dims:])
              return t

       lowercase		:Dict[str, Any]       							=				tensor_tree_map(_prep_inputs				,				a_)
       lowercase		:Optional[Any]       							=				None
       if _out is not None:
              lowercase		:Optional[int]       							=				tensor_tree_map(lambda a_: t.view([-1] + list(t.shape[no_batch_dims:]))				,				_out)

       lowercase		:int       							=				1
       for d in orig_batch_dims:
              flat_batch_dim *= d

       lowercase		:List[str]       							=				flat_batch_dim // chunk_size + (flat_batch_dim % chunk_size != 0)

       def _select_chunk(a_						:torch.Tensor) -> torch.Tensor:
              return t[i : i + chunk_size] if t.shape[0] != 1 else t

       lowercase		:str       							=				0
       lowercase		:Optional[int]       							=				prepped_outputs
       for _ in range(a_):
              # Chunk the input
              if not low_mem:
                     lowercase		:List[Any]       							=				_select_chunk
              else:
                     lowercase		:Optional[Any]       							=				partial(
                         _chunk_slice				,				flat_start=a_				,				flat_end=min(a_				,				i + chunk_size)				,				no_batch_dims=len(a_)				,				)

              lowercase		:Dict[str, Any]       							=				tensor_tree_map(a_				,				a_)

              # Run the layer on the chunk
              lowercase		:Union[str, Any]       							=				layer(**a_)

              # Allocate space for the output
              if out is None:
                     lowercase		:str       							=				tensor_tree_map(lambda a_: t.new_zeros((flat_batch_dim,) + t.shape[1:])				,				a_)

              # Put the chunk in its pre-allocated space
              if isinstance(a_				,				a_):

                     def assign(a_						:dict				,				a_						:dict) -> None:
                            for k, v in da.items():
                                   if isinstance(a_				,				a_):
                                          assign(a_				,				da[k])
                                   else:
                                          if _add_into_out:
                                                 v[i : i + chunk_size] += da[k]
                                          else:
                                                 lowercase		:List[Any]       							=				da[k]

                     assign(a_				,				a_)
              elif isinstance(a_				,				a_):
                     for xa, xa in zip(a_				,				a_):
                            if _add_into_out:
                                   xa[i : i + chunk_size] += xa
                            else:
                                   lowercase		:List[Any]       							=				xa
              elif isinstance(a_				,				torch.Tensor):
                     if _add_into_out:
                            out[i : i + chunk_size] += output_chunk
                     else:
                            lowercase		:List[str]       							=				output_chunk
              else:
                     raise ValueError('''Not supported''')

              i += chunk_size

       lowercase		:Union[str, Any]       							=				tensor_tree_map(lambda a_: t.view(orig_batch_dims + t.shape[1:])				,				a_)

       return out




class 					__magic_name__		:






       def __init__(   self  :    Optional[Any]  ,     snake_case__  :    int = 5_1_2  ,     ):

              '''simple docstring'''






              lowercase		:Union[str, Any]       							=				max_chunk_size
              lowercase		:Optional[int]       							=				None
              lowercase		:Optional[tuple]       							=				None






       def  __snake_case						(   self  :    int  ,     snake_case__  :    Callable  ,     snake_case__  :    tuple  ,     snake_case__  :    int				):

              '''simple docstring'''






              logging.info('''Tuning chunk size...'''				)

              if min_chunk_size >= self.max_chunk_size:
                     return min_chunk_size

              lowercase		:List[int]       							=				[2**l for l in range(int(math.log(self.max_chunk_size  ,     2				)				) + 1				)]
              lowercase		:Optional[Any]       							=				[c for c in candidates if c > min_chunk_size]
              lowercase		:Union[str, Any]       							=				[min_chunk_size] + candidates
              candidates[-1] += 4

              def test_chunk_size(snake_case__  :    int				) -> bool:
                     try:
                            with torch.no_grad():
                                   fn(*snake_case__  ,     chunk_size=snake_case__				)
                            return True
                     except RuntimeError:
                            return False

              lowercase		:Union[str, Any]       							=				0
              lowercase		:Dict       							=				len(snake_case__				) - 1
              while i > min_viable_chunk_size_index:
                     lowercase		:str       							=				test_chunk_size(candidates[i]				)
                     if not viable:
                            lowercase		:Any       							=				(min_viable_chunk_size_index + i) // 2
                     else:
                            lowercase		:Optional[Any]       							=				i
                            lowercase		:Dict       							=				(i + len(snake_case__				) - 1) // 2

              return candidates[min_viable_chunk_size_index]






       def  __snake_case						(   self  :    Optional[Any]  ,     snake_case__  :    Iterable  ,     snake_case__  :    Iterable				):

              '''simple docstring'''






              lowercase		:Optional[int]       							=				True
              for aa, aa in zip(snake_case__  ,     snake_case__				):
                     assert type(snake_case__				) == type(snake_case__				)
                     if isinstance(snake_case__  ,     (list, tuple)				):
                            consistent &= self._compare_arg_caches(snake_case__  ,     snake_case__				)
                     elif isinstance(snake_case__  ,     snake_case__				):
                            lowercase		:Dict       							=				[v for _, v in sorted(aa.items()  ,     key=lambda snake_case__				: x[0]				)]
                            lowercase		:int       							=				[v for _, v in sorted(aa.items()  ,     key=lambda snake_case__				: x[0]				)]
                            consistent &= self._compare_arg_caches(snake_case__  ,     snake_case__				)
                     else:
                            consistent &= aa == aa

              return consistent







       def  __snake_case						(   self  :    Dict  ,     snake_case__  :    Callable  ,     snake_case__  :    tuple  ,     snake_case__  :    int  ,     ):

              '''simple docstring'''






              lowercase		:Union[str, Any]       							=				True
              lowercase		:tuple       							=				tree_map(lambda snake_case__				: a.shape if isinstance(snake_case__  ,     torch.Tensor				) else a  ,     snake_case__  ,     snake_case__				)
              if self.cached_arg_data is not None:
                     # If args have changed shape/value, we need to re-tune
                     assert len(self.cached_arg_data				) == len(snake_case__				)
                     lowercase		:str       							=				self._compare_arg_caches(self.cached_arg_data  ,     snake_case__				)
              else:
                     # Otherwise, we can reuse the precomputed value
                     lowercase		:Dict       							=				False

              if not consistent:
                     lowercase		:Optional[Any]       							=				self._determine_favorable_chunk_size(
                         snake_case__  ,     snake_case__  ,     snake_case__  ,     )
                     lowercase		:Optional[int]       							=				arg_data

              assert self.cached_chunk_size is not None

              return self.cached_chunk_size










"""simple docstring"""



from collections import OrderedDict
from typing import Mapping

from packaging import version

from ...configuration_utils import PretrainedConfig
from ...onnx import OnnxConfig
from ...utils import logging


UpperCAmelCase      		=			logging.get_logger(__name__)

UpperCAmelCase      		=			{
    '''facebook/deit-base-distilled-patch16-224''': (
        '''https://huggingface.co/facebook/deit-base-patch16-224/resolve/main/config.json'''
    ),
    # See all DeiT models at https://huggingface.co/models?filter=deit
}
class 					__magic_name__		(			__UpperCAmelCase     ):
       __A			:      Tuple        =   "deit"






       def __init__(   self  :    List[str]  ,     snake_case__  :    int=7_6_8  ,     snake_case__  :    List[Any]=1_2  ,     snake_case__  :    Dict=1_2  ,     snake_case__  :    List[Any]=3_0_7_2  ,     snake_case__  :    Optional[int]="gelu"  ,     snake_case__  :    Dict=0.0  ,     snake_case__  :    str=0.0  ,     snake_case__  :    List[str]=0.02  ,     snake_case__  :    Optional[int]=1e-1_2  ,     snake_case__  :    Any=2_2_4  ,     snake_case__  :    Optional[int]=1_6  ,     snake_case__  :    int=3  ,     snake_case__  :    str=True  ,     snake_case__  :    Optional[int]=1_6  ,     **snake_case__  :    List[Any]  ,     ):

              '''simple docstring'''






              super().__init__(**snake_case__				)

              lowercase		:List[str]       							=				hidden_size
              lowercase		:Union[str, Any]       							=				num_hidden_layers
              lowercase		:Optional[Any]       							=				num_attention_heads
              lowercase		:Optional[Any]       							=				intermediate_size
              lowercase		:int       							=				hidden_act
              lowercase		:int       							=				hidden_dropout_prob
              lowercase		:Dict       							=				attention_probs_dropout_prob
              lowercase		:Optional[int]       							=				initializer_range
              lowercase		:Tuple       							=				layer_norm_eps
              lowercase		:Optional[int]       							=				image_size
              lowercase		:Union[str, Any]       							=				patch_size
              lowercase		:Optional[Any]       							=				num_channels
              lowercase		:Tuple       							=				qkv_bias
              lowercase		:Optional[Any]       							=				encoder_stride







class 					__magic_name__		(			__UpperCAmelCase     ):
       __A			:      Optional[int]        =   version.parse("1.11"     )






       @property
       def  __snake_case						(   self  :    int				):

              '''simple docstring'''






              return OrderedDict(
                  [
                      ('''pixel_values''', {0: '''batch''', 1: '''num_channels''', 2: '''height''', 3: '''width'''}),
                  ]				)







       @property
       def  __snake_case						(   self  :    Optional[int]				):

              '''simple docstring'''






              return 1e-4

