



from dataclasses import dataclass
from typing import Optional

import numpy as np
import torch
import torch.nn as nn

from ..utils import BaseOutput, is_torch_version, randn_tensor
from .attention_processor import SpatialNorm
from .unet_ad_blocks import UNetMidBlockaD, get_down_block, get_up_block







@dataclass
class 		snake_case						(	SCREAMING_SNAKE_CASE_  ):



   '''simple docstring'''






   snake_case_					: torch.FloatTensor







class 		snake_case						(	nn.Module  ):



   '''simple docstring'''






   def __init__(					self							:			Optional[int]				,		lowerCAmelCase							:			List[Any]=3				,		lowerCAmelCase							:			Union[str, Any]=3				,		lowerCAmelCase							:			Optional[Any]=("DownEncoderBlock2D",)				,		lowerCAmelCase							:			Any=(64,)				,		lowerCAmelCase							:			Union[str, Any]=2				,		lowerCAmelCase							:			Dict=32				,		lowerCAmelCase							:			Dict="silu"				,		lowerCAmelCase							:			Dict=True				,		)				->				Dict:

    """simple docstring"""







    super().__init__()
    _snake_case    :  Any					=					layers_per_block

    _snake_case    :  int					=					torch.nn.Convad(
        lowerCAmelCase				,		block_out_channels[0]				,		kernel_size=3				,		stride=1				,		padding=1				,		)

    _snake_case    :  Optional[int]					=					None
    _snake_case    :  Any					=					nn.ModuleList([])

    # down
    _snake_case    :  Any					=					block_out_channels[0]
    for i, down_block_type in enumerate(lowerCAmelCase):
     _snake_case    :  Any					=					output_channel
     _snake_case    :  Dict					=					block_out_channels[i]
     _snake_case    :  List[str]					=					i == len(lowerCAmelCase) - 1

     _snake_case    :  Dict					=					get_down_block(
         lowerCAmelCase				,		num_layers=self.layers_per_block				,		in_channels=lowerCAmelCase				,		out_channels=lowerCAmelCase				,		add_downsample=not is_final_block				,		resnet_eps=1E-6				,		downsample_padding=0				,		resnet_act_fn=lowerCAmelCase				,		resnet_groups=lowerCAmelCase				,		attention_head_dim=lowerCAmelCase				,		temb_channels=lowerCAmelCase				,		)
     self.down_blocks.append(lowerCAmelCase)

    # mid
    _snake_case    :  Dict					=					UNetMidBlockaD(
        in_channels=block_out_channels[-1]				,		resnet_eps=1E-6				,		resnet_act_fn=lowerCAmelCase				,		output_scale_factor=1				,		resnet_time_scale_shift="""default"""				,		attention_head_dim=block_out_channels[-1]				,		resnet_groups=lowerCAmelCase				,		temb_channels=lowerCAmelCase				,		)

    # out
    _snake_case    :  str					=					nn.GroupNorm(num_channels=block_out_channels[-1]				,		num_groups=lowerCAmelCase				,		eps=1E-6)
    _snake_case    :  Any					=					nn.SiLU()

    _snake_case    :  Tuple					=					2 * out_channels if double_z else out_channels
    _snake_case    :  List[str]					=					nn.Convad(block_out_channels[-1]				,		lowerCAmelCase				,		3				,		padding=1)

    _snake_case    :  Any					=					False


   def      UpperCamelCase_  (					self							:			Any				,		lowerCAmelCase							:			str)				->				List[str]:

    """simple docstring"""







    _snake_case    :  Any					=					x
    _snake_case    :  Dict					=					self.conv_in(lowerCAmelCase)

    if self.training and self.gradient_checkpointing:

     def create_custom_forward(lowerCAmelCase							:			List[Any]):
      def custom_forward(*lowerCAmelCase							:			str):
       return module(*lowerCAmelCase)

      return custom_forward

     # down
     if is_torch_version(""">="""				,		"""1.11.0"""):
      for down_block in self.down_blocks:
       _snake_case    :  Optional[Any]					=					torch.utils.checkpoint.checkpoint(
           create_custom_forward(lowerCAmelCase)				,		lowerCAmelCase				,		use_reentrant=lowerCAmelCase)
      # middle
      _snake_case    :  Union[str, Any]					=					torch.utils.checkpoint.checkpoint(
          create_custom_forward(self.mid_block)				,		lowerCAmelCase				,		use_reentrant=lowerCAmelCase)
     else:
      for down_block in self.down_blocks:
       _snake_case    :  Tuple					=					torch.utils.checkpoint.checkpoint(create_custom_forward(lowerCAmelCase)				,		lowerCAmelCase)
      # middle
      _snake_case    :  Union[str, Any]					=					torch.utils.checkpoint.checkpoint(create_custom_forward(self.mid_block)				,		lowerCAmelCase)

    else:
     # down
     for down_block in self.down_blocks:
      _snake_case    :  str					=					down_block(lowerCAmelCase)

     # middle
     _snake_case    :  Optional[int]					=					self.mid_block(lowerCAmelCase)

    # post-process
    _snake_case    :  List[str]					=					self.conv_norm_out(lowerCAmelCase)
    _snake_case    :  Optional[Any]					=					self.conv_act(lowerCAmelCase)
    _snake_case    :  Any					=					self.conv_out(lowerCAmelCase)

    return sample







class 		snake_case						(	nn.Module  ):



   '''simple docstring'''






   def __init__(					self							:			List[str]				,		lowerCAmelCase							:			Optional[int]=3				,		lowerCAmelCase							:			Union[str, Any]=3				,		lowerCAmelCase							:			str=("UpDecoderBlock2D",)				,		lowerCAmelCase							:			Tuple=(64,)				,		lowerCAmelCase							:			Dict=2				,		lowerCAmelCase							:			List[str]=32				,		lowerCAmelCase							:			Optional[int]="silu"				,		lowerCAmelCase							:			int="group"				,		)				->				int:

    """simple docstring"""







    super().__init__()
    _snake_case    :  Optional[Any]					=					layers_per_block

    _snake_case    :  Optional[Any]					=					nn.Convad(
        lowerCAmelCase				,		block_out_channels[-1]				,		kernel_size=3				,		stride=1				,		padding=1				,		)

    _snake_case    :  Optional[int]					=					None
    _snake_case    :  List[Any]					=					nn.ModuleList([])

    _snake_case    :  int					=					in_channels if norm_type == """spatial""" else None

    # mid
    _snake_case    :  str					=					UNetMidBlockaD(
        in_channels=block_out_channels[-1]				,		resnet_eps=1E-6				,		resnet_act_fn=lowerCAmelCase				,		output_scale_factor=1				,		resnet_time_scale_shift="""default""" if norm_type == """group""" else norm_type				,		attention_head_dim=block_out_channels[-1]				,		resnet_groups=lowerCAmelCase				,		temb_channels=lowerCAmelCase				,		)

    # up
    _snake_case    :  List[Any]					=					list(reversed(lowerCAmelCase))
    _snake_case    :  Optional[int]					=					reversed_block_out_channels[0]
    for i, up_block_type in enumerate(lowerCAmelCase):
     _snake_case    :  Tuple					=					output_channel
     _snake_case    :  Tuple					=					reversed_block_out_channels[i]

     _snake_case    :  List[str]					=					i == len(lowerCAmelCase) - 1

     _snake_case    :  List[Any]					=					get_up_block(
         lowerCAmelCase				,		num_layers=self.layers_per_block + 1				,		in_channels=lowerCAmelCase				,		out_channels=lowerCAmelCase				,		prev_output_channel=lowerCAmelCase				,		add_upsample=not is_final_block				,		resnet_eps=1E-6				,		resnet_act_fn=lowerCAmelCase				,		resnet_groups=lowerCAmelCase				,		attention_head_dim=lowerCAmelCase				,		temb_channels=lowerCAmelCase				,		resnet_time_scale_shift=lowerCAmelCase				,		)
     self.up_blocks.append(lowerCAmelCase)
     _snake_case    :  Optional[int]					=					output_channel

    # out
    if norm_type == "spatial":
     _snake_case    :  Dict					=					SpatialNorm(block_out_channels[0]				,		lowerCAmelCase)
    else:
     _snake_case    :  Any					=					nn.GroupNorm(num_channels=block_out_channels[0]				,		num_groups=lowerCAmelCase				,		eps=1E-6)
    _snake_case    :  Tuple					=					nn.SiLU()
    _snake_case    :  str					=					nn.Convad(block_out_channels[0]				,		lowerCAmelCase				,		3				,		padding=1)

    _snake_case    :  Any					=					False


   def      UpperCamelCase_  (					self							:			Optional[Any]				,		lowerCAmelCase							:			Tuple				,		lowerCAmelCase							:			Dict=None)				->				Optional[int]:

    """simple docstring"""







    _snake_case    :  str					=					z
    _snake_case    :  Any					=					self.conv_in(lowerCAmelCase)

    _snake_case    :  Optional[Any]					=					next(iter(self.up_blocks.parameters())).dtype
    if self.training and self.gradient_checkpointing:

     def create_custom_forward(lowerCAmelCase							:			Tuple):
      def custom_forward(*lowerCAmelCase							:			str):
       return module(*lowerCAmelCase)

      return custom_forward

     if is_torch_version(""">="""				,		"""1.11.0"""):
      # middle
      _snake_case    :  Union[str, Any]					=					torch.utils.checkpoint.checkpoint(
          create_custom_forward(self.mid_block)				,		lowerCAmelCase				,		lowerCAmelCase				,		use_reentrant=lowerCAmelCase)
      _snake_case    :  str					=					sample.to(lowerCAmelCase)

      # up
      for up_block in self.up_blocks:
       _snake_case    :  List[str]					=					torch.utils.checkpoint.checkpoint(
           create_custom_forward(lowerCAmelCase)				,		lowerCAmelCase				,		lowerCAmelCase				,		use_reentrant=lowerCAmelCase)
     else:
      # middle
      _snake_case    :  Any					=					torch.utils.checkpoint.checkpoint(
          create_custom_forward(self.mid_block)				,		lowerCAmelCase				,		lowerCAmelCase)
      _snake_case    :  str					=					sample.to(lowerCAmelCase)

      # up
      for up_block in self.up_blocks:
       _snake_case    :  List[Any]					=					torch.utils.checkpoint.checkpoint(create_custom_forward(lowerCAmelCase)				,		lowerCAmelCase				,		lowerCAmelCase)
    else:
     # middle
     _snake_case    :  Optional[Any]					=					self.mid_block(lowerCAmelCase				,		lowerCAmelCase)
     _snake_case    :  Optional[int]					=					sample.to(lowerCAmelCase)

     # up
     for up_block in self.up_blocks:
      _snake_case    :  Dict					=					up_block(lowerCAmelCase				,		lowerCAmelCase)

        # post-process
    if latent_embeds is None:
     _snake_case    :  int					=					self.conv_norm_out(lowerCAmelCase)
    else:
     _snake_case    :  Optional[int]					=					self.conv_norm_out(lowerCAmelCase				,		lowerCAmelCase)
    _snake_case    :  Optional[Any]					=					self.conv_act(lowerCAmelCase)
    _snake_case    :  Optional[Any]					=					self.conv_out(lowerCAmelCase)

    return sample







class 		snake_case						(	nn.Module  ):



   '''simple docstring'''






   def __init__(					self							:			List[str]				,		lowerCAmelCase							:			List[Any]				,		lowerCAmelCase							:			Union[str, Any]				,		lowerCAmelCase							:			Any				,		lowerCAmelCase							:			Union[str, Any]=None				,		lowerCAmelCase							:			Union[str, Any]="random"				,		lowerCAmelCase							:			Tuple=False				,		lowerCAmelCase							:			Tuple=True)				->				Any:

    """simple docstring"""







    super().__init__()
    _snake_case    :  str					=					n_e
    _snake_case    :  int					=					vq_embed_dim
    _snake_case    :  List[str]					=					beta
    _snake_case    :  str					=					legacy

    _snake_case    :  int					=					nn.Embedding(self.n_e				,		self.vq_embed_dim)
    self.embedding.weight.data.uniform_(-1.0 / self.n_e				,		1.0 / self.n_e)

    _snake_case    :  List[str]					=					remap
    if self.remap is not None:
     self.register_buffer("""used"""				,		torch.tensor(np.load(self.remap)))
     _snake_case    :  List[str]					=					self.used.shape[0]
     _snake_case    :  Union[str, Any]					=					unknown_index  # "random" or "extra" or integer
     if self.unknown_index == "extra":
      _snake_case    :  str					=					self.re_embed
      _snake_case    :  Union[str, Any]					=					self.re_embed + 1
     print(
         F'''Remapping {self.n_e} indices to {self.re_embed} indices. '''
         F'''Using {self.unknown_index} for unknown indices.''')
    else:
     _snake_case    :  List[Any]					=					n_e

    _snake_case    :  Optional[int]					=					sane_index_shape

   def      UpperCamelCase_  (					self							:			int				,		lowerCAmelCase							:			Any)				->				List[Any]:

    """simple docstring"""







    _snake_case    :  int					=					inds.shape
    assert len(lowerCAmelCase) > 1
    _snake_case    :  str					=					inds.reshape(ishape[0]				,		-1)
    _snake_case    :  Dict					=					self.used.to(lowerCAmelCase)
    _snake_case    :  Tuple					=					(inds[:, :, None] == used[None, None, ...]).long()
    _snake_case    :  str					=					match.argmax(-1)
    _snake_case    :  str					=					match.sum(2) < 1
    if self.unknown_index == "random":
     _snake_case    :  Any					=					torch.randint(0				,		self.re_embed				,		size=new[unknown].shape).to(device=new.device)
    else:
     _snake_case    :  Dict					=					self.unknown_index
    return new.reshape(lowerCAmelCase)

   def      UpperCamelCase_  (					self							:			int				,		lowerCAmelCase							:			Union[str, Any])				->				List[str]:

    """simple docstring"""







    _snake_case    :  List[str]					=					inds.shape
    assert len(lowerCAmelCase) > 1
    _snake_case    :  Tuple					=					inds.reshape(ishape[0]				,		-1)
    _snake_case    :  List[Any]					=					self.used.to(lowerCAmelCase)
    if self.re_embed > self.used.shape[0]:  # extra token
     _snake_case    :  Optional[Any]					=					0  # simply set to zero
    _snake_case    :  Dict					=					torch.gather(used[None, :][inds.shape[0] * [0], :]				,		1				,		lowerCAmelCase)
    return back.reshape(lowerCAmelCase)

   def      UpperCamelCase_  (					self							:			Optional[Any]				,		lowerCAmelCase							:			Dict)				->				List[Any]:

    """simple docstring"""







    _snake_case    :  Union[str, Any]					=					z.permute(0				,		2				,		3				,		1).contiguous()
    _snake_case    :  List[str]					=					z.view(-1				,		self.vq_embed_dim)

    # distances from z to embeddings e_j (z - e)^2 = z^2 + e^2 - 2 e * z
    _snake_case    :  int					=					torch.argmin(torch.cdist(lowerCAmelCase				,		self.embedding.weight)				,		dim=1)

    _snake_case    :  List[Any]					=					self.embedding(lowerCAmelCase).view(z.shape)
    _snake_case    :  Optional[int]					=					None
    _snake_case    :  Optional[int]					=					None

    # compute loss for embedding
    if not self.legacy:
     _snake_case    :  Optional[Any]					=					self.beta * torch.mean((z_q.detach() - z) ** 2) + torch.mean((z_q - z.detach()) ** 2)
    else:
     _snake_case    :  Optional[Any]					=					torch.mean((z_q.detach() - z) ** 2) + self.beta * torch.mean((z_q - z.detach()) ** 2)

    # preserve gradients
    _snake_case    :  List[str]					=					z + (z_q - z).detach()

    # reshape back to match original input shape
    _snake_case    :  Tuple					=					z_q.permute(0				,		3				,		1				,		2).contiguous()

    if self.remap is not None:
     _snake_case    :  Any					=					min_encoding_indices.reshape(z.shape[0]				,		-1)  # add batch axis
     _snake_case    :  Any					=					self.remap_to_used(lowerCAmelCase)
     _snake_case    :  Union[str, Any]					=					min_encoding_indices.reshape(-1				,		1)  # flatten

    if self.sane_index_shape:
     _snake_case    :  Optional[int]					=					min_encoding_indices.reshape(z_q.shape[0]				,		z_q.shape[2]				,		z_q.shape[3])

    return z_q, loss, (perplexity, min_encodings, min_encoding_indices)


   def      UpperCamelCase_  (					self							:			str				,		lowerCAmelCase							:			Optional[Any]				,		lowerCAmelCase							:			List[str])				->				Dict:

    """simple docstring"""







    if self.remap is not None:
     _snake_case    :  List[str]					=					indices.reshape(shape[0]				,		-1)  # add batch axis
     _snake_case    :  Any					=					self.unmap_to_all(lowerCAmelCase)
     _snake_case    :  Dict					=					indices.reshape(-1)  # flatten again

    # get quantized latent vectors
    _snake_case    :  Tuple					=					self.embedding(lowerCAmelCase)

    if shape is not None:
     _snake_case    :  List[str]					=					z_q.view(lowerCAmelCase)
     # reshape back to match original input shape
     _snake_case    :  Any					=					z_q.permute(0				,		3				,		1				,		2).contiguous()

    return z_q







class 		snake_case						(	SCREAMING_SNAKE_CASE_  ):



   '''simple docstring'''






   def __init__(					self							:			Dict				,		lowerCAmelCase							:			Optional[int]				,		lowerCAmelCase							:			Optional[Any]=False)				->				Dict:

    """simple docstring"""







    _snake_case    :  List[str]					=					parameters
    _snake_case	,    _snake_case    :  str					=					torch.chunk(lowerCAmelCase				,		2				,		dim=1)
    _snake_case    :  Optional[int]					=					torch.clamp(self.logvar				,		-30.0				,		20.0)
    _snake_case    :  Dict					=					deterministic
    _snake_case    :  Union[str, Any]					=					torch.exp(0.5 * self.logvar)
    _snake_case    :  Optional[int]					=					torch.exp(self.logvar)
    if self.deterministic:
     _snake_case    :  Union[str, Any]					=					torch.zeros_like(
         self.mean				,		device=self.parameters.device				,		dtype=self.parameters.dtype)

   def      UpperCamelCase_  (					self							:			Optional[Any]				,		lowerCAmelCase							:			Optional[torch.Generator] = None)				->				torch.FloatTensor:

    """simple docstring"""







    _snake_case    :  str					=					randn_tensor(
        self.mean.shape				,		generator=lowerCAmelCase				,		device=self.parameters.device				,		dtype=self.parameters.dtype)
    _snake_case    :  Union[str, Any]					=					self.mean + self.std * sample
    return x

   def      UpperCamelCase_  (					self							:			Any				,		lowerCAmelCase							:			Tuple=None)				->				Tuple:

    """simple docstring"""







    if self.deterministic:
     return torch.Tensor([0.0])
    else:
     if other is None:
      return 0.5 * torch.sum(torch.pow(self.mean				,		2) + self.var - 1.0 - self.logvar				,		dim=[1, 2, 3])
     else:
      return 0.5 * torch.sum(
          torch.pow(self.mean - other.mean				,		2) / other.var
          + self.var / other.var
          - 1.0
          - self.logvar
          + other.logvar				,		dim=[1, 2, 3]				,		)

   def      UpperCamelCase_  (					self							:			Union[str, Any]				,		lowerCAmelCase							:			int				,		lowerCAmelCase							:			Tuple=[1, 2, 3])				->				Dict:

    """simple docstring"""







    if self.deterministic:
     return torch.Tensor([0.0])
    _snake_case    :  Union[str, Any]					=					np.log(2.0 * np.pi)
    return 0.5 * torch.sum(logtwopi + self.logvar + torch.pow(sample - self.mean				,		2) / self.var				,		dim=lowerCAmelCase)


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

    """simple docstring"""







    return self.mean





def       lowercase       (   SCREAMING_SNAKE_CASE__       :	int = 1_000				)  ->     int:
 _snake_case	,    _snake_case    :  str					=					1, 1
 _snake_case    :  List[Any]					=					2
 while True:
  _snake_case    :  Union[str, Any]					=					0
  _snake_case    :  int					=					fa + fa
  _snake_case	,    _snake_case    :  Union[str, Any]					=					fa, f
  index += 1
  for _ in str(SCREAMING_SNAKE_CASE__				):
   i += 1
  if i == n:
   break
 return index


if __name__ == "__main__":
  print(solution(int(str(input()).strip())))
