





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 	_a						(   UpperCAmelCase					)    ->    int:







   """simple docstring"""
   lowerCamelCase__       :						Union[str, Any]        =							[]
   if isinstance(lowerCamelCase__      ,  lowerCamelCase__					):
      for v in tree.values():
         shapes.extend(_fetch_dims(lowerCamelCase__					)					)
   elif isinstance(lowerCamelCase__      ,  (list, tuple)					):
      for t in tree:
         shapes.extend(_fetch_dims(lowerCamelCase__					)					)
   elif isinstance(lowerCamelCase__      ,  torch.Tensor					):
      shapes.append(tree.shape					)
   else:
      raise ValueError('''Not supported'''					)

   return shapes



@torch.jit.ignore
def 	_a						(   UpperCAmelCase      ,  UpperCAmelCase					)    ->    Dict:







   """simple docstring"""
   lowerCamelCase__       :						Union[str, Any]        =							[]
   for d in reversed(lowerCamelCase__					):
      idx.append(flat_idx % d					)
      lowerCamelCase__       :						str        =							flat_idx // d

   return tuple(reversed(lowerCamelCase__					)					)



@torch.jit.ignore
def 	_a						(   UpperCAmelCase      ,  UpperCAmelCase      ,  UpperCAmelCase      ,  UpperCAmelCase = None      ,  UpperCAmelCase = None      ,  )    ->    int:







   """simple docstring"""

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

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

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

   lowerCamelCase__       :						int        =							[]
   lowerCamelCase__       :						Union[str, Any]        =							[]

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

   lowerCamelCase__       :						List[Any]        =							tuple(lowerCamelCase__					)
   lowerCamelCase__       :						Union[str, Any]        =							len(lowerCamelCase__					)

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

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

      lowerCamelCase__       :						List[Any]        =							start[divergence_idx]
      return tuple(
          path + (slice(lowerCamelCase__      ,  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__       :						Dict        =							end[divergence_idx]
      return tuple(
          path + (slice(lowerCamelCase__      ,  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__       :						Tuple        =							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 	_a						(   UpperCAmelCase      ,  UpperCAmelCase      ,  UpperCAmelCase      ,  UpperCAmelCase					)    ->    Dict:







   """simple docstring"""
   lowerCamelCase__       :						str        =							t.shape[:no_batch_dims]
   lowerCamelCase__       :						Tuple        =							list(_flat_idx_to_idx(lowerCamelCase__      ,  lowerCamelCase__					)					)
   # _get_minimal_slice_set is inclusive
   lowerCamelCase__       :						Any        =							list(_flat_idx_to_idx(flat_end - 1      ,  lowerCamelCase__					)					)

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

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

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



def 	_a						(   UpperCAmelCase      ,  UpperCAmelCase      ,  UpperCAmelCase      ,  UpperCAmelCase      ,  UpperCAmelCase = False      ,  UpperCAmelCase = None      ,  UpperCAmelCase = False      ,  )    ->    Tuple:







   """simple docstring"""
   if not (len(lowerCamelCase__					) > 0):
      raise ValueError('''Must provide at least one input'''					)

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

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

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

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

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

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

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

      lowerCamelCase__       :						Tuple        =							tensor_tree_map(lowerCamelCase__      ,  lowerCamelCase__					)

      # Run the layer on the chunk
      lowerCamelCase__       :						Optional[int]        =							layer(**lowerCamelCase__					)

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

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

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

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

      i += chunk_size

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

   return out




class        __SCREAMING_SNAKE_CASE      :







       def __init__(				self					:     Optional[int]		, A					:     Optional[int] = 5_1_2		, )       ->str:
          lowerCamelCase__       :						Dict        =							max_chunk_size
          lowerCamelCase__       :						str        =							None
          lowerCamelCase__       :						Tuple        =							None







       def 						__lowerCamelCase   (				self					:     Union[str, Any]		, A					:     Optional[int]		, A					:     int		, A					:     int      )       ->int:
          logging.info('''Tuning chunk size...'''      )

          if min_chunk_size >= self.max_chunk_size:
             return min_chunk_size

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

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

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

          return candidates[min_viable_chunk_size_index]







       def 						__lowerCamelCase   (				self					:     List[str]		, A					:     List[Any]		, A					:     Optional[int]      )       ->bool:
          lowerCamelCase__       :						Tuple        =							True
          for aa, aa in zip(A		, A      ):
             assert type(A      ) == type(A      )
             if isinstance(A		, (list, tuple)      ):
                consistent &= self._compare_arg_caches(A		, A      )
             elif isinstance(A		, A      ):
                lowerCamelCase__       :						Tuple        =							[v for _, v in sorted(aa.items()		, key=lambda A      : x[0]      )]
                lowerCamelCase__       :						Any        =							[v for _, v in sorted(aa.items()		, key=lambda A      : x[0]      )]
                consistent &= self._compare_arg_caches(A		, A      )
             else:
                consistent &= aa == aa

          return consistent







       def 						__lowerCamelCase   (				self					:     Union[str, Any]		, A					:     Union[str, Any]		, A					:     Optional[int]		, A					:     str		, )       ->int:
          lowerCamelCase__       :						str        =							True
          lowerCamelCase__       :						Optional[int]        =							tree_map(lambda A      : a.shape if isinstance(A		, torch.Tensor      ) else a		, A		, A      )
          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(A      )
             lowerCamelCase__       :						List[Any]        =							self._compare_arg_caches(self.cached_arg_data		, A      )
          else:
             # Otherwise, we can reuse the precomputed value
             lowerCamelCase__       :						Optional[Any]        =							False

          if not consistent:
             lowerCamelCase__       :						Optional[int]        =							self._determine_favorable_chunk_size(
                 A		, A		, A		, )
             lowerCamelCase__       :						Union[str, Any]        =							arg_data

          assert self.cached_chunk_size is not None

          return self.cached_chunk_size













from ...configuration_utils import PretrainedConfig
from ...utils import logging


_A :   Any  			=  logging.get_logger(__name__)

_A :   int  			=  {
    'facebook/timesformer': 'https://huggingface.co/facebook/timesformer/resolve/main/config.json',
}


class        __SCREAMING_SNAKE_CASE      (			lowerCAmelCase_ ):
       _UpperCAmelCase				:  Dict			   =   "timesformer"







       def __init__(				self					:     List[str]		, A					:     int=2_2_4		, A					:     Optional[Any]=1_6		, A					:     str=3		, A					:     str=8		, A					:     Any=7_6_8		, A					:     Dict=1_2		, A					:     Optional[Any]=1_2		, A					:     Any=3_0_7_2		, A					:     str="gelu"		, A					:     Optional[int]=0.0		, A					:     Union[str, Any]=0.0		, A					:     List[Any]=0.02		, A					:     int=1e-6		, A					:     Tuple=True		, A					:     Any="divided_space_time"		, A					:     Optional[Any]=0		, **A					:     Tuple		, )       ->str:
          super().__init__(**A      )

          lowerCamelCase__       :						Optional[Any]        =							image_size
          lowerCamelCase__       :						int        =							patch_size
          lowerCamelCase__       :						Any        =							num_channels
          lowerCamelCase__       :						Optional[int]        =							num_frames

          lowerCamelCase__       :						Optional[Any]        =							hidden_size
          lowerCamelCase__       :						Optional[int]        =							num_hidden_layers
          lowerCamelCase__       :						Optional[int]        =							num_attention_heads
          lowerCamelCase__       :						Dict        =							intermediate_size
          lowerCamelCase__       :						Optional[Any]        =							hidden_act
          lowerCamelCase__       :						Union[str, Any]        =							hidden_dropout_prob
          lowerCamelCase__       :						Dict        =							attention_probs_dropout_prob
          lowerCamelCase__       :						List[Any]        =							initializer_range
          lowerCamelCase__       :						str        =							layer_norm_eps
          lowerCamelCase__       :						Union[str, Any]        =							qkv_bias

          lowerCamelCase__       :						str        =							attention_type
          lowerCamelCase__       :						List[str]        =							drop_path_rate



