




from dataclasses import dataclass
from typing import 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 .modeling_utils import ModelMixin
from .vae import Decoder, DecoderOutput, Encoder, VectorQuantizer





@dataclass
class 	lowerCamelCase_							(				_SCREAMING_SNAKE_CASE ):


	'''simple docstring'''







	lowercase_       =   42





class 	lowerCamelCase_							(				_SCREAMING_SNAKE_CASE	,       _SCREAMING_SNAKE_CASE ):


	'''simple docstring'''







	@register_to_config
	def __init__(							self  :		str    ,    _lowerCAmelCase  :		int = 3    ,    _lowerCAmelCase  :		int = 3    ,    _lowerCAmelCase  :		Tuple[str] = ("DownEncoderBlock2D",)    ,    _lowerCAmelCase  :		Tuple[str] = ("UpDecoderBlock2D",)    ,    _lowerCAmelCase  :		Tuple[int] = (64,)    ,    _lowerCAmelCase  :		int = 1    ,    _lowerCAmelCase  :		str = "silu"    ,    _lowerCAmelCase  :		int = 3    ,    _lowerCAmelCase  :		int = 32    ,    _lowerCAmelCase  :		int = 256    ,    _lowerCAmelCase  :		int = 32    ,    _lowerCAmelCase  :		Optional[int] = None    ,    _lowerCAmelCase  :		float = 0.1_8215    ,    _lowerCAmelCase  :		str = "group"    ,    ):
							super().__init__()

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

							SCREAMING_SNAKE_CASE_     						=      vq_embed_dim if vq_embed_dim is not None else latent_channels

							SCREAMING_SNAKE_CASE_     						=      nn.Convad(_lowerCAmelCase    ,    _lowerCAmelCase    ,    1						)
							SCREAMING_SNAKE_CASE_     						=      VectorQuantizer(_lowerCAmelCase    ,    _lowerCAmelCase    ,    beta=0.25    ,    remap=_lowerCAmelCase    ,    sane_index_shape=_lowerCAmelCase						)
							SCREAMING_SNAKE_CASE_     						=      nn.Convad(_lowerCAmelCase    ,    _lowerCAmelCase    ,    1						)

							# pass init params to Decoder
							SCREAMING_SNAKE_CASE_     						=      Decoder(
							    in_channels=_lowerCAmelCase    ,    out_channels=_lowerCAmelCase    ,    up_block_types=_lowerCAmelCase    ,    block_out_channels=_lowerCAmelCase    ,    layers_per_block=_lowerCAmelCase    ,    act_fn=_lowerCAmelCase    ,    norm_num_groups=_lowerCAmelCase    ,    norm_type=_lowerCAmelCase    ,    )



	@apply_forward_hook
	def 				lowerCAmelCase_  (							self  :		List[str]    ,    _lowerCAmelCase  :		torch.FloatTensor    ,    _lowerCAmelCase  :		bool = True						):
							SCREAMING_SNAKE_CASE_     						=      self.encoder(_lowerCAmelCase						)
							SCREAMING_SNAKE_CASE_     						=      self.quant_conv(_lowerCAmelCase						)

							if not return_dict:
													return (h,)

							return VQEncoderOutput(latents=_lowerCAmelCase						)



	@apply_forward_hook
	def 				lowerCAmelCase_  (							self  :		Any    ,    _lowerCAmelCase  :		torch.FloatTensor    ,    _lowerCAmelCase  :		bool = False    ,    _lowerCAmelCase  :		bool = True						):
							# also go through quantization layer
							if not force_not_quantize:
													SCREAMING_SNAKE_CASE_						,			SCREAMING_SNAKE_CASE_						,			SCREAMING_SNAKE_CASE_     						=      self.quantize(_lowerCAmelCase						)
							else:
													SCREAMING_SNAKE_CASE_     						=      h
							SCREAMING_SNAKE_CASE_     						=      self.post_quant_conv(_lowerCAmelCase						)
							SCREAMING_SNAKE_CASE_     						=      self.decoder(_lowerCAmelCase    ,    quant if self.config.norm_type == 'spatial' else None						)

							if not return_dict:
													return (dec,)

							return DecoderOutput(sample=_lowerCAmelCase						)




	def 				lowerCAmelCase_  (							self  :		Optional[Any]    ,    _lowerCAmelCase  :		torch.FloatTensor    ,    _lowerCAmelCase  :		bool = True						):
							SCREAMING_SNAKE_CASE_     						=      sample
							SCREAMING_SNAKE_CASE_     						=      self.encode(_lowerCAmelCase						).latents
							SCREAMING_SNAKE_CASE_     						=      self.decode(_lowerCAmelCase						).sample

							if not return_dict:
													return (dec,)

							return DecoderOutput(sample=_lowerCAmelCase						)





def  UpperCAmelCase_							(				__UpperCAmelCase						:     int      ,      __UpperCAmelCase						:     int							) ->			int:
      return int((input_a, input_a).count(0							) != 0							)

def  UpperCAmelCase_							(				) ->			None:
      assert nand_gate(0      ,      0							) == 1
      assert nand_gate(0      ,      1							) == 1
      assert nand_gate(1      ,      0							) == 1
      assert nand_gate(1      ,      1							) == 0


if __name__ == "__main__":
   print(nand_gate(0, 0))
   print(nand_gate(0, 1))
   print(nand_gate(1, 0))
   print(nand_gate(1, 1))