

'''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    a__       (  a__						):




     """simple docstring"""


     __SCREAMING_SNAKE_CASE     =      []
     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    a__       (  a__      ,    a__						):




     """simple docstring"""


     __SCREAMING_SNAKE_CASE     =      []
     for d in reversed(a__						):
          idx.append(flat_idx % d						)
          __SCREAMING_SNAKE_CASE     =      flat_idx // d

     return tuple(reversed(a__						)						)







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




     """simple docstring"""


     def reduce_edge_list(a__						) -> None:
          __SCREAMING_SNAKE_CASE     =      True
          for i in range(len(a__						)						):
               __SCREAMING_SNAKE_CASE     =      -1 * (i + 1)
               l[reversed_idx] &= tally
               __SCREAMING_SNAKE_CASE     =      l[reversed_idx]

     if start_edges is None:
          __SCREAMING_SNAKE_CASE     =      [s == 0 for s in start]
          reduce_edge_list(a__						)
     if end_edges is None:
          __SCREAMING_SNAKE_CASE     =      [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						),)]

     __SCREAMING_SNAKE_CASE     =      []
     __SCREAMING_SNAKE_CASE     =      []

     # 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

     __SCREAMING_SNAKE_CASE     =      tuple(a__						)
     __SCREAMING_SNAKE_CASE     =      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

          __SCREAMING_SNAKE_CASE     =      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

          __SCREAMING_SNAKE_CASE     =      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()						)
          __SCREAMING_SNAKE_CASE     =      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__       (  a__      ,    a__      ,    a__      ,    a__						):




     """simple docstring"""


     __SCREAMING_SNAKE_CASE     =      t.shape[:no_batch_dims]
     __SCREAMING_SNAKE_CASE     =      list(_flat_idx_to_idx(a__      ,    a__						)						)
     # _get_minimal_slice_set is inclusive
     __SCREAMING_SNAKE_CASE     =      list(_flat_idx_to_idx(flat_end - 1      ,    a__						)						)

     # Get an ordered list of slices to perform
     __SCREAMING_SNAKE_CASE     =      _get_minimal_slice_set(
         a__      ,    a__      ,    a__      ,    )

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

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







def    a__       (  a__      ,    a__      ,    a__      ,    a__      ,    a__ = False      ,    a__ = None      ,    a__ = False      ,    ):




     """simple docstring"""


     if not (len(a__						) > 0):
          raise ValueError("""Must provide at least one input"""						)

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

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

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

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

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

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

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

          __SCREAMING_SNAKE_CASE     =      tensor_tree_map(a__      ,    a__						)

          # Run the layer on the chunk
          __SCREAMING_SNAKE_CASE     =      layer(**a__						)

          # Allocate space for the output
          if out is None:
               __SCREAMING_SNAKE_CASE     =      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__      ,    a__						) -> 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:
                                   __SCREAMING_SNAKE_CASE     =      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:
                         __SCREAMING_SNAKE_CASE     =      xa
          elif isinstance(a__      ,    torch.Tensor						):
               if _add_into_out:
                    out[i : i + chunk_size] += output_chunk
               else:
                    __SCREAMING_SNAKE_CASE     =      output_chunk
          else:
               raise ValueError("""Not supported"""						)

          i += chunk_size

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

     return out







class 						lowerCAmelCase__   :



 """simple docstring"""



 def __init__(		self					:       str					,							__SCREAMING_SNAKE_CASE					:       int = 512					,							)  -> int:


      """simple docstring"""




      __SCREAMING_SNAKE_CASE     =      max_chunk_size
      __SCREAMING_SNAKE_CASE     =      None
      __SCREAMING_SNAKE_CASE     =      None
 def       UpperCAmelCase__		(		self					:       Optional[int]					,							__SCREAMING_SNAKE_CASE					:       Callable					,							__SCREAMING_SNAKE_CASE					:       tuple					,							__SCREAMING_SNAKE_CASE					:       int			)  -> int:


      """simple docstring"""




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

      if min_chunk_size >= self.max_chunk_size:
           return min_chunk_size

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

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

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

      return candidates[min_viable_chunk_size_index]
 def       UpperCAmelCase__		(		self					:       Any					,							__SCREAMING_SNAKE_CASE					:       Iterable					,							__SCREAMING_SNAKE_CASE					:       Iterable			)  -> bool:


      """simple docstring"""




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

      return consistent


 def       UpperCAmelCase__		(		self					:       List[Any]					,							__SCREAMING_SNAKE_CASE					:       Callable					,							__SCREAMING_SNAKE_CASE					:       tuple					,							__SCREAMING_SNAKE_CASE					:       int					,							)  -> int:


      """simple docstring"""




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

      if not consistent:
           __SCREAMING_SNAKE_CASE     =      self._determine_favorable_chunk_size(
               __SCREAMING_SNAKE_CASE					,							__SCREAMING_SNAKE_CASE					,							__SCREAMING_SNAKE_CASE					,							)
           __SCREAMING_SNAKE_CASE     =      arg_data

      assert self.cached_chunk_size is not None

      return self.cached_chunk_size









'''simple docstring'''



import unittest

from diffusers import FlaxAutoencoderKL
from diffusers.utils import is_flax_available
from diffusers.utils.testing_utils import require_flax

from .test_modeling_common_flax import FlaxModelTesterMixin


if is_flax_available():
  import jax







@require_flax
class 						lowerCAmelCase__   (      a ,					unittest.TestCase					):



 """simple docstring"""



 lowerCAmelCase__  					=      FlaxAutoencoderKL
 @property
 def       UpperCAmelCase__		(		self					:       Tuple			)  -> List[str]:


      """simple docstring"""




      __SCREAMING_SNAKE_CASE     =      4
      __SCREAMING_SNAKE_CASE     =      3
      __SCREAMING_SNAKE_CASE     =      (32, 32)

      __SCREAMING_SNAKE_CASE     =      jax.random.PRNGKey(0			)
      __SCREAMING_SNAKE_CASE     =      jax.random.uniform(__SCREAMING_SNAKE_CASE					,							((batch_size, num_channels) + sizes)			)

      return {"sample": image, "prng_key": prng_key}


 def       UpperCAmelCase__		(		self					:       Union[str, Any]			)  -> Any:


      """simple docstring"""




      __SCREAMING_SNAKE_CASE     =      {
          """block_out_channels""": [32, 64],
          """in_channels""": 3,
          """out_channels""": 3,
          """down_block_types""": ["""DownEncoderBlock2D""", """DownEncoderBlock2D"""],
          """up_block_types""": ["""UpDecoderBlock2D""", """UpDecoderBlock2D"""],
          """latent_channels""": 4,
      }
      __SCREAMING_SNAKE_CASE     =      self.dummy_input
      return init_dict, inputs_dict






