


'''simple docstring'''

from dataclasses import dataclass
from typing import Dict, Optional, Tuple, Union

import torch
import torch.nn as nn

from ..configuration_utils import ConfigMixin, register_to_config
from ..utils import BaseOutput, apply_forward_hook
from .attention_processor import AttentionProcessor, AttnProcessor
from .modeling_utils import ModelMixin
from .vae import Decoder, DecoderOutput, DiagonalGaussianDistribution, Encoder





@dataclass
class   snake_case					(					lowercase    ):





  """simple docstring"""




  _lowerCamelCase						=						42





class   snake_case					(					lowercase    ,		lowercase    ):





  """simple docstring"""




  _lowerCamelCase						=						True






  @register_to_config
  def __init__(					self    ,						UpperCamelCase = 3    ,						UpperCamelCase = 3    ,						UpperCamelCase = ("DownEncoderBlock2D",)    ,						UpperCamelCase = ("UpDecoderBlock2D",)    ,						UpperCamelCase = (64,)    ,						UpperCamelCase = 1    ,						UpperCamelCase = "silu"    ,						UpperCamelCase = 4    ,						UpperCamelCase = 32    ,						UpperCamelCase = 32    ,						UpperCamelCase = 0.18_215    ,						):







   """simple docstring"""
   super().__init__()

   # pass init params to Encoder
   lowerCamelCase_  				=						Encoder(
       in_channels=UpperCamelCase    ,						out_channels=UpperCamelCase    ,						down_block_types=UpperCamelCase    ,						block_out_channels=UpperCamelCase    ,						layers_per_block=UpperCamelCase    ,						act_fn=UpperCamelCase    ,						norm_num_groups=UpperCamelCase    ,						double_z=UpperCamelCase    ,						)

   # pass init params to Decoder
   lowerCamelCase_  				=						Decoder(
       in_channels=UpperCamelCase    ,						out_channels=UpperCamelCase    ,						up_block_types=UpperCamelCase    ,						block_out_channels=UpperCamelCase    ,						layers_per_block=UpperCamelCase    ,						norm_num_groups=UpperCamelCase    ,						act_fn=UpperCamelCase    ,						)

   lowerCamelCase_  				=						nn.Convad(2 * latent_channels    ,						2 * latent_channels    ,						1  )
   lowerCamelCase_  				=						nn.Convad(UpperCamelCase    ,						UpperCamelCase    ,						1  )

   lowerCamelCase_  				=						False
   lowerCamelCase_  				=						False

   # only relevant if vae tiling is enabled
   lowerCamelCase_  				=						self.config.sample_size
   lowerCamelCase_  				=						(
       self.config.sample_size[0]
       if isinstance(self.config.sample_size    ,						(list, tuple)  )
       else self.config.sample_size
   )
   lowerCamelCase_  				=						int(sample_size / (2 ** (len(self.config.block_out_channels  ) - 1))  )
   lowerCamelCase_  				=						0.25






  def 						snake_case	(					self    ,						UpperCamelCase    ,						UpperCamelCase=False  ):







   """simple docstring"""
   if isinstance(UpperCamelCase    ,						(Encoder, Decoder)  ):
    lowerCamelCase_  				=						value






  def 						snake_case	(					self    ,						UpperCamelCase = True  ):







   """simple docstring"""
   lowerCamelCase_  				=						use_tiling






  def 						snake_case	(					self  ):







   """simple docstring"""
   self.enable_tiling(UpperCamelCase  )






  def 						snake_case	(					self  ):







   """simple docstring"""
   lowerCamelCase_  				=						True






  def 						snake_case	(					self  ):







   """simple docstring"""
   lowerCamelCase_  				=						False






  @property
  # Copied from diffusers.models.unet_2d_condition.UNet2DConditionModel.attn_processors
  def 						snake_case	(					self  ):







   """simple docstring"""
   lowerCamelCase_  				=						{}

   def fn_recursive_add_processors(UpperCamelCase    ,						UpperCamelCase    ,						UpperCamelCase  ):
    if hasattr(UpperCamelCase    ,						"set_processor"  ):
     lowerCamelCase_  				=						module.processor

    for sub_name, child in module.named_children():
     fn_recursive_add_processors(f'''{name}.{sub_name}'''    ,						UpperCamelCase    ,						UpperCamelCase  )

    return processors

   for name, module in self.named_children():
    fn_recursive_add_processors(UpperCamelCase    ,						UpperCamelCase    ,						UpperCamelCase  )

   return processors






  def 						snake_case	(					self    ,						UpperCamelCase  ):







   """simple docstring"""
   lowerCamelCase_  				=						len(self.attn_processors.keys()  )

   if isinstance(UpperCamelCase    ,						UpperCamelCase  ) and len(UpperCamelCase  ) != count:
    raise ValueError(
        f'''A dict of processors was passed, but the number of processors {len(UpperCamelCase  )} does not match the'''
        f''' number of attention layers: {count}. Please make sure to pass {count} processor classes.'''  )

   def fn_recursive_attn_processor(UpperCamelCase    ,						UpperCamelCase    ,						UpperCamelCase  ):
    if hasattr(UpperCamelCase    ,						"set_processor"  ):
     if not isinstance(UpperCamelCase    ,						UpperCamelCase  ):
      module.set_processor(UpperCamelCase  )
     else:
      module.set_processor(processor.pop(f'''{name}.processor'''  )  )

    for sub_name, child in module.named_children():
     fn_recursive_attn_processor(f'''{name}.{sub_name}'''    ,						UpperCamelCase    ,						UpperCamelCase  )

   for name, module in self.named_children():
    fn_recursive_attn_processor(UpperCamelCase    ,						UpperCamelCase    ,						UpperCamelCase  )






  def 						snake_case	(					self  ):







   """simple docstring"""
   self.set_attn_processor(AttnProcessor()  )






  @apply_forward_hook
  def 						snake_case	(					self    ,						UpperCamelCase    ,						UpperCamelCase = True  ):







   """simple docstring"""
   if self.use_tiling and (x.shape[-1] > self.tile_sample_min_size or x.shape[-2] > self.tile_sample_min_size):
    return self.tiled_encode(UpperCamelCase    ,						return_dict=UpperCamelCase  )

   if self.use_slicing and x.shape[0] > 1:
    lowerCamelCase_  				=						[self.encoder(UpperCamelCase  ) for x_slice in x.split(1  )]
    lowerCamelCase_  				=						torch.cat(UpperCamelCase  )
   else:
    lowerCamelCase_  				=						self.encoder(UpperCamelCase  )

   lowerCamelCase_  				=						self.quant_conv(UpperCamelCase  )
   lowerCamelCase_  				=						DiagonalGaussianDistribution(UpperCamelCase  )

   if not return_dict:
    return (posterior,)

   return AutoencoderKLOutput(latent_dist=UpperCamelCase  )






  def 						snake_case	(					self    ,						UpperCamelCase    ,						UpperCamelCase = True  ):







   """simple docstring"""
   if self.use_tiling and (z.shape[-1] > self.tile_latent_min_size or z.shape[-2] > self.tile_latent_min_size):
    return self.tiled_decode(UpperCamelCase    ,						return_dict=UpperCamelCase  )

   lowerCamelCase_  				=						self.post_quant_conv(UpperCamelCase  )
   lowerCamelCase_  				=						self.decoder(UpperCamelCase  )

   if not return_dict:
    return (dec,)

   return DecoderOutput(sample=UpperCamelCase  )






  @apply_forward_hook
  def 						snake_case	(					self    ,						UpperCamelCase    ,						UpperCamelCase = True  ):







   """simple docstring"""
   if self.use_slicing and z.shape[0] > 1:
    lowerCamelCase_  				=						[self._decode(UpperCamelCase  ).sample for z_slice in z.split(1  )]
    lowerCamelCase_  				=						torch.cat(UpperCamelCase  )
   else:
    lowerCamelCase_  				=						self._decode(UpperCamelCase  ).sample

   if not return_dict:
    return (decoded,)

   return DecoderOutput(sample=UpperCamelCase  )






  def 						snake_case	(					self    ,						UpperCamelCase    ,						UpperCamelCase    ,						UpperCamelCase  ):







   """simple docstring"""
   lowerCamelCase_  				=						min(a.shape[2]    ,						b.shape[2]    ,						UpperCamelCase  )
   for y in range(UpperCamelCase  ):
    lowerCamelCase_  				=						a[:, :, -blend_extent + y, :] * (1 - y / blend_extent) + b[:, :, y, :] * (y / blend_extent)
   return b






  def 						snake_case	(					self    ,						UpperCamelCase    ,						UpperCamelCase    ,						UpperCamelCase  ):







   """simple docstring"""
   lowerCamelCase_  				=						min(a.shape[3]    ,						b.shape[3]    ,						UpperCamelCase  )
   for x in range(UpperCamelCase  ):
    lowerCamelCase_  				=						a[:, :, :, -blend_extent + x] * (1 - x / blend_extent) + b[:, :, :, x] * (x / blend_extent)
   return b






  def 						snake_case	(					self    ,						UpperCamelCase    ,						UpperCamelCase = True  ):







   """simple docstring"""
   lowerCamelCase_  				=						int(self.tile_sample_min_size * (1 - self.tile_overlap_factor)  )
   lowerCamelCase_  				=						int(self.tile_latent_min_size * self.tile_overlap_factor  )
   lowerCamelCase_  				=						self.tile_latent_min_size - blend_extent

   # Split the image into 512x512 tiles and encode them separately.
   lowerCamelCase_  				=						[]
   for i in range(0    ,						x.shape[2]    ,						UpperCamelCase  ):
    lowerCamelCase_  				=						[]
    for j in range(0    ,						x.shape[3]    ,						UpperCamelCase  ):
     lowerCamelCase_  				=						x[:, :, i : i + self.tile_sample_min_size, j : j + self.tile_sample_min_size]
     lowerCamelCase_  				=						self.encoder(UpperCamelCase  )
     lowerCamelCase_  				=						self.quant_conv(UpperCamelCase  )
     row.append(UpperCamelCase  )
    rows.append(UpperCamelCase  )
   lowerCamelCase_  				=						[]
   for i, row in enumerate(UpperCamelCase  ):
    lowerCamelCase_  				=						[]
    for j, tile in enumerate(UpperCamelCase  ):
     # blend the above tile and the left tile
     # to the current tile and add the current tile to the result row
     if i > 0:
      lowerCamelCase_  				=						self.blend_v(rows[i - 1][j]    ,						UpperCamelCase    ,						UpperCamelCase  )
     if j > 0:
      lowerCamelCase_  				=						self.blend_h(row[j - 1]    ,						UpperCamelCase    ,						UpperCamelCase  )
     result_row.append(tile[:, :, :row_limit, :row_limit]  )
    result_rows.append(torch.cat(UpperCamelCase    ,						dim=3  )  )

   lowerCamelCase_  				=						torch.cat(UpperCamelCase    ,						dim=2  )
   lowerCamelCase_  				=						DiagonalGaussianDistribution(UpperCamelCase  )

   if not return_dict:
    return (posterior,)

   return AutoencoderKLOutput(latent_dist=UpperCamelCase  )






  def 						snake_case	(					self    ,						UpperCamelCase    ,						UpperCamelCase = True  ):







   """simple docstring"""
   lowerCamelCase_  				=						int(self.tile_latent_min_size * (1 - self.tile_overlap_factor)  )
   lowerCamelCase_  				=						int(self.tile_sample_min_size * self.tile_overlap_factor  )
   lowerCamelCase_  				=						self.tile_sample_min_size - blend_extent

   # Split z into overlapping 64x64 tiles and decode them separately.
   # The tiles have an overlap to avoid seams between tiles.
   lowerCamelCase_  				=						[]
   for i in range(0    ,						z.shape[2]    ,						UpperCamelCase  ):
    lowerCamelCase_  				=						[]
    for j in range(0    ,						z.shape[3]    ,						UpperCamelCase  ):
     lowerCamelCase_  				=						z[:, :, i : i + self.tile_latent_min_size, j : j + self.tile_latent_min_size]
     lowerCamelCase_  				=						self.post_quant_conv(UpperCamelCase  )
     lowerCamelCase_  				=						self.decoder(UpperCamelCase  )
     row.append(UpperCamelCase  )
    rows.append(UpperCamelCase  )
   lowerCamelCase_  				=						[]
   for i, row in enumerate(UpperCamelCase  ):
    lowerCamelCase_  				=						[]
    for j, tile in enumerate(UpperCamelCase  ):
     # blend the above tile and the left tile
     # to the current tile and add the current tile to the result row
     if i > 0:
      lowerCamelCase_  				=						self.blend_v(rows[i - 1][j]    ,						UpperCamelCase    ,						UpperCamelCase  )
     if j > 0:
      lowerCamelCase_  				=						self.blend_h(row[j - 1]    ,						UpperCamelCase    ,						UpperCamelCase  )
     result_row.append(tile[:, :, :row_limit, :row_limit]  )
    result_rows.append(torch.cat(UpperCamelCase    ,						dim=3  )  )

   lowerCamelCase_  				=						torch.cat(UpperCamelCase    ,						dim=2  )
   if not return_dict:
    return (dec,)

   return DecoderOutput(sample=UpperCamelCase  )







  def 						snake_case	(					self    ,						UpperCamelCase    ,						UpperCamelCase = False    ,						UpperCamelCase = True    ,						UpperCamelCase = None    ,						):







   """simple docstring"""
   lowerCamelCase_  				=						sample
   lowerCamelCase_  				=						self.encode(UpperCamelCase  ).latent_dist
   if sample_posterior:
    lowerCamelCase_  				=						posterior.sample(generator=UpperCamelCase  )
   else:
    lowerCamelCase_  				=						posterior.mode()
   lowerCamelCase_  				=						self.decode(UpperCamelCase  ).sample

   if not return_dict:
    return (dec,)

   return DecoderOutput(sample=UpperCamelCase  )







'''simple docstring'''

def __snake_case      (   UpperCAmelCase_		:		int = 1000	):
 return sum(2 * a * ((a - 1) // 2) for a in range(3      ,       n + 1	)	)


if __name__ == "__main__":
     print(solution())



