






'''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_     (    lowercase__):
 lowerCamelCase__  =     []
 if isinstance(lowercase__				,     lowercase__):
  for v in tree.values():
   shapes.extend(_fetch_dims(lowercase__))
 elif isinstance(lowercase__				,     (list, tuple)):
  for t in tree:
   shapes.extend(_fetch_dims(lowercase__))
 elif isinstance(lowercase__				,     torch.Tensor):
  shapes.append(tree.shape)
 else:
  raise ValueError("Not supported")

 return shapes






@torch.jit.ignore
def    lowerCamelCase_     (    lowercase__				,     lowercase__):
 lowerCamelCase__  =     []
 for d in reversed(lowercase__):
  idx.append(flat_idx % d)
  lowerCamelCase__  =     flat_idx // d

 return tuple(reversed(lowercase__))






@torch.jit.ignore
def    lowerCamelCase_     (    lowercase__				,     lowercase__				,     lowercase__				,     lowercase__ = None				,     lowercase__ = None				,     ):

 # 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(lowercase__) -> None:
  lowerCamelCase__  =     True
  for i in range(len(lowercase__)):
   lowerCamelCase__  =     -1 * (i + 1)
   l[reversed_idx] &= tally
   lowerCamelCase__  =     l[reversed_idx]

 if start_edges is None:
  lowerCamelCase__  =     [s == 0 for s in start]
  reduce_edge_list(lowercase__)
 if end_edges is None:
  lowerCamelCase__  =     [e == (d - 1) for e, d in zip(lowercase__				,     lowercase__)]
  reduce_edge_list(lowercase__)

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

 lowerCamelCase__  =     []
 lowerCamelCase__  =     []

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

 lowerCamelCase__  =     tuple(lowercase__)
 lowerCamelCase__  =     len(lowercase__)

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

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

  lowerCamelCase__  =     start[divergence_idx]
  return tuple(
      path + (slice(lowercase__				,     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

  lowerCamelCase__  =     end[divergence_idx]
  return tuple(
      path + (slice(lowercase__				,     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())
  lowerCamelCase__  =     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_     (    lowercase__				,     lowercase__				,     lowercase__				,     lowercase__):
 lowerCamelCase__  =     t.shape[:no_batch_dims]
 lowerCamelCase__  =     list(_flat_idx_to_idx(lowercase__				,     lowercase__))
 # _get_minimal_slice_set is inclusive
 lowerCamelCase__  =     list(_flat_idx_to_idx(flat_end - 1				,     lowercase__))

 # Get an ordered list of slices to perform
 lowerCamelCase__  =     _get_minimal_slice_set(
     lowercase__				,     lowercase__				,     lowercase__				,     )

 lowerCamelCase__  =     [t[s] for s in slices]

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






def    lowerCamelCase_     (    lowercase__				,     lowercase__				,     lowercase__				,     lowercase__				,     lowercase__ = False				,     lowercase__ = None				,     lowercase__ = False				,     ):
 if not (len(lowercase__) > 0):
  raise ValueError("Must provide at least one input")

 lowerCamelCase__  =     [shape[:no_batch_dims] for shape in _fetch_dims(lowercase__)]
 lowerCamelCase__  =     tuple([max(lowercase__) for s in zip(*lowercase__)])

 def _prep_inputs(lowercase__) -> torch.Tensor:
  if not low_mem:
   if not sum(t.shape[:no_batch_dims]) == no_batch_dims:
    lowerCamelCase__  =     t.expand(orig_batch_dims + t.shape[no_batch_dims:])
   lowerCamelCase__  =     t.reshape(-1				,     *t.shape[no_batch_dims:])
  else:
   lowerCamelCase__  =     t.expand(orig_batch_dims + t.shape[no_batch_dims:])
  return t

 lowerCamelCase__  =     tensor_tree_map(_prep_inputs				,     lowercase__)
 lowerCamelCase__  =     None
 if _out is not None:
  lowerCamelCase__  =     tensor_tree_map(lambda lowercase__: t.view([-1] + list(t.shape[no_batch_dims:]))				,     _out)

 lowerCamelCase__  =     1
 for d in orig_batch_dims:
  flat_batch_dim *= d

 lowerCamelCase__  =     flat_batch_dim // chunk_size + (flat_batch_dim % chunk_size != 0)

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

 lowerCamelCase__  =     0
 lowerCamelCase__  =     prepped_outputs
 for _ in range(lowercase__):
  # Chunk the input
  if not low_mem:
   lowerCamelCase__  =     _select_chunk
  else:
   lowerCamelCase__  =     partial(
       _chunk_slice				,     flat_start=lowercase__				,     flat_end=min(lowercase__				,     i + chunk_size)				,     no_batch_dims=len(lowercase__)				,     )

  lowerCamelCase__  =     tensor_tree_map(lowercase__				,     lowercase__)

  # Run the layer on the chunk
  lowerCamelCase__  =     layer(**lowercase__)

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

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

   def assign(lowercase__				,     lowercase__) -> None:
    for k, v in da.items():
     if isinstance(lowercase__				,     lowercase__):
      assign(lowercase__				,     da[k])
     else:
      if _add_into_out:
       v[i : i + chunk_size] += da[k]
      else:
       lowerCamelCase__  =     da[k]

   assign(lowercase__				,     lowercase__)
  elif isinstance(lowercase__				,     lowercase__):
   for xa, xa in zip(lowercase__				,     lowercase__):
    if _add_into_out:
     xa[i : i + chunk_size] += xa
    else:
     lowerCamelCase__  =     xa
  elif isinstance(lowercase__				,     torch.Tensor):
   if _add_into_out:
    out[i : i + chunk_size] += output_chunk
   else:
    lowerCamelCase__  =     output_chunk
  else:
   raise ValueError("Not supported")

  i += chunk_size

 lowerCamelCase__  =     tensor_tree_map(lambda lowercase__: t.view(orig_batch_dims + t.shape[1:])				,     lowercase__)

 return out
class 				lowercase       :


    '''simple docstring'''

    def __init__(					self     :     Any				,     __lowerCamelCase     :     int = 512				,     )							->							Union[str, Any]:

     '''simple docstring'''




     lowerCamelCase__  =     max_chunk_size
     lowerCamelCase__  =     None
     lowerCamelCase__  =     None

    def    a__				(					self     :     Dict				,     __lowerCamelCase     :     Callable				,     __lowerCamelCase     :     tuple				,     __lowerCamelCase     :     int     )							->							int:

     '''simple docstring'''




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

     if min_chunk_size >= self.max_chunk_size:
      return min_chunk_size

     lowerCamelCase__  =     [2**l for l in range(int(math.log(self.max_chunk_size				,     2     )     ) + 1     )]
     lowerCamelCase__  =     [c for c in candidates if c > min_chunk_size]
     lowerCamelCase__  =     [min_chunk_size] + candidates
     candidates[-1] += 4

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

     lowerCamelCase__  =     0
     lowerCamelCase__  =     len(__lowerCamelCase     ) - 1
     while i > min_viable_chunk_size_index:
      lowerCamelCase__  =     test_chunk_size(candidates[i]     )
      if not viable:
       lowerCamelCase__  =     (min_viable_chunk_size_index + i) // 2
      else:
       lowerCamelCase__  =     i
       lowerCamelCase__  =     (i + len(__lowerCamelCase     ) - 1) // 2

     return candidates[min_viable_chunk_size_index]

    def    a__				(					self     :     str				,     __lowerCamelCase     :     Iterable				,     __lowerCamelCase     :     Iterable     )							->							bool:

     '''simple docstring'''




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

     return consistent




    def    a__				(					self     :     Any				,     __lowerCamelCase     :     Callable				,     __lowerCamelCase     :     tuple				,     __lowerCamelCase     :     int				,     )							->							int:

     '''simple docstring'''




     lowerCamelCase__  =     True
     lowerCamelCase__  =     tree_map(lambda __lowerCamelCase     : a.shape if isinstance(__lowerCamelCase				,     torch.Tensor     ) else a				,     __lowerCamelCase				,     __lowerCamelCase     )
     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(__lowerCamelCase     )
      lowerCamelCase__  =     self._compare_arg_caches(self.cached_arg_data				,     __lowerCamelCase     )
     else:
      # Otherwise, we can reuse the precomputed value
      lowerCamelCase__  =     False

     if not consistent:
      lowerCamelCase__  =     self._determine_favorable_chunk_size(
          __lowerCamelCase				,     __lowerCamelCase				,     __lowerCamelCase				,     )
      lowerCamelCase__  =     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


__A							:							Optional[Any]  							=		logging.get_logger(__name__)

__A							:							int  							=		{
    """google/vit-base-patch16-224""": """https://huggingface.co/vit-base-patch16-224/resolve/main/config.json""",
    # See all ViT models at https://huggingface.co/models?filter=vit
}
class 				lowercase       (							_lowerCamelCase      ):


    '''simple docstring'''

    lowerCAmelCase__      				=							"vit"

    def __init__(					self     :     Optional[int]				,     __lowerCamelCase     :     Tuple=768				,     __lowerCamelCase     :     Tuple=12				,     __lowerCamelCase     :     Tuple=12				,     __lowerCamelCase     :     int=3072				,     __lowerCamelCase     :     Optional[Any]="gelu"				,     __lowerCamelCase     :     Optional[int]=0.0				,     __lowerCamelCase     :     Tuple=0.0				,     __lowerCamelCase     :     Optional[Any]=0.0_2				,     __lowerCamelCase     :     int=1E-12				,     __lowerCamelCase     :     Tuple=224				,     __lowerCamelCase     :     int=16				,     __lowerCamelCase     :     Optional[int]=3				,     __lowerCamelCase     :     List[str]=True				,     __lowerCamelCase     :     str=16				,     **__lowerCamelCase     :     Optional[int]				,     )							->							str:

     '''simple docstring'''




     super().__init__(**__lowerCamelCase     )

     lowerCamelCase__  =     hidden_size
     lowerCamelCase__  =     num_hidden_layers
     lowerCamelCase__  =     num_attention_heads
     lowerCamelCase__  =     intermediate_size
     lowerCamelCase__  =     hidden_act
     lowerCamelCase__  =     hidden_dropout_prob
     lowerCamelCase__  =     attention_probs_dropout_prob
     lowerCamelCase__  =     initializer_range
     lowerCamelCase__  =     layer_norm_eps
     lowerCamelCase__  =     image_size
     lowerCamelCase__  =     patch_size
     lowerCamelCase__  =     num_channels
     lowerCamelCase__  =     qkv_bias
     lowerCamelCase__  =     encoder_stride
class 				lowercase       (							_lowerCamelCase      ):


    '''simple docstring'''

    lowerCAmelCase__      				=							version.parse("1.11"      )

    @property
    def    a__				(					self     :     Optional[int]     )							->							Mapping[str, Mapping[int, str]]:

     '''simple docstring'''




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




    @property
    def    a__				(					self     :     Optional[int]     )							->							float:

     '''simple docstring'''




     return 1E-4

