
from typing import Optional, Tuple, Union

import flax
import flax.linen as nn
import jax
import jax.numpy as jnp
from flax.core.frozen_dict import FrozenDict

from ..configuration_utils import ConfigMixin, flax_register_to_config
from ..utils import BaseOutput
from .embeddings_flax import FlaxTimestepEmbedding, FlaxTimesteps
from .modeling_flax_utils import FlaxModelMixin
from .unet_ad_blocks_flax import (
    FlaxCrossAttnDownBlockaD,
    FlaxCrossAttnUpBlockaD,
    FlaxDownBlockaD,
    FlaxUNetMidBlockaDCrossAttn,
    FlaxUpBlockaD,
)




@flax.struct.dataclass
class    SCREAMING_SNAKE_CASE__     (	UpperCAmelCase					):





	'''simple docstring'''



	_UpperCAmelCase       :		jnp.ndarray




@flax_register_to_config
class    SCREAMING_SNAKE_CASE__     (	nn.Module							,UpperCAmelCase							,UpperCAmelCase					):





	'''simple docstring'''



	_UpperCAmelCase       :		int       =					3_2
	_UpperCAmelCase       :		int       =					4
	_UpperCAmelCase       :		int       =					4
	_UpperCAmelCase       :		Tuple[str]       =					(
	    "CrossAttnDownBlock2D",
	    "CrossAttnDownBlock2D",
	    "CrossAttnDownBlock2D",
	    "DownBlock2D",
	)
	_UpperCAmelCase       :		Tuple[str]       =					("UpBlock2D", "CrossAttnUpBlock2D", "CrossAttnUpBlock2D", "CrossAttnUpBlock2D")
	_UpperCAmelCase       :		Union[bool, Tuple[bool]]       =					False
	_UpperCAmelCase       :		Tuple[int]       =					(3_2_0, 6_4_0, 1_2_8_0, 1_2_8_0)
	_UpperCAmelCase       :		int       =					2
	_UpperCAmelCase       :		Union[int, Tuple[int]]       =					8
	_UpperCAmelCase       :		Optional[Union[int, Tuple[int]]]       =					None
	_UpperCAmelCase       :		int       =					1_2_8_0
	_UpperCAmelCase       :		float       =					0.0
	_UpperCAmelCase       :		bool       =					False
	_UpperCAmelCase       :		jnp.dtype       =					jnp.floataa
	_UpperCAmelCase       :		bool       =					True
	_UpperCAmelCase       :		int       =					0
	_UpperCAmelCase       :		bool       =					False



	def  A							(  self	:    List[Any]			,  lowercase	:    jax.random.KeyArray	):


				'''simple docstring'''


				_snake_case		=			(1, self.in_channels, self.sample_size, self.sample_size)
				_snake_case		=			jnp.zeros(lowercase			,  dtype=jnp.floataa	)
				_snake_case		=			jnp.ones((1,)			,  dtype=jnp.intaa	)
				_snake_case		=			jnp.zeros((1, 1, self.cross_attention_dim)			,  dtype=jnp.floataa	)

				_snake_case	,					_snake_case		=			jax.random.split(lowercase	)
				_snake_case		=			{'params': params_rng, 'dropout': dropout_rng}

				return self.init(lowercase			,  lowercase			,  lowercase			,  lowercase	)["params"]



	def  A							(  self	:    List[Any]	):


				'''simple docstring'''


				_snake_case		=			self.block_out_channels
				_snake_case		=			block_out_channels[0] * 4

				if self.num_attention_heads is not None:
							raise ValueError(
							    'At the moment it is not possible to define the number of attention heads via `num_attention_heads` because of a naming issue as described in https://github.com/huggingface/diffusers/issues/2011#issuecomment-1547958131. Passing `num_attention_heads` will only be supported in diffusers v0.19.'	)

				# If `num_attention_heads` is not defined (which is the case for most models)
				# it will default to `attention_head_dim`. This looks weird upon first reading it and it is.
				# The reason for this behavior is to correct for incorrectly named variables that were introduced
				# when this library was created. The incorrect naming was only discovered much later in https://github.com/huggingface/diffusers/issues/2011#issuecomment-1547958131
				# Changing `attention_head_dim` to `num_attention_heads` for 40,000+ configurations is too backwards breaking
				# which is why we correct for the naming here.
				_snake_case		=			self.num_attention_heads or self.attention_head_dim

				# input
				_snake_case		=			nn.Conv(
				    block_out_channels[0]			,  kernel_size=(3, 3)			,  strides=(1, 1)			,  padding=((1, 1), (1, 1))			,  dtype=self.dtype			,  )

				# time
				_snake_case		=			FlaxTimesteps(
				    block_out_channels[0]			,  flip_sin_to_cos=self.flip_sin_to_cos			,  freq_shift=self.config.freq_shift	)
				_snake_case		=			FlaxTimestepEmbedding(lowercase			,  dtype=self.dtype	)

				_snake_case		=			self.only_cross_attention
				if isinstance(lowercase			,  lowercase	):
							_snake_case		=			(only_cross_attention,) * len(self.down_block_types	)

				if isinstance(lowercase			,  lowercase	):
							_snake_case		=			(num_attention_heads,) * len(self.down_block_types	)

				# down
				_snake_case		=			[]
				_snake_case		=			block_out_channels[0]
				for i, down_block_type in enumerate(self.down_block_types	):
							_snake_case		=			output_channel
							_snake_case		=			block_out_channels[i]
							_snake_case		=			i == len(lowercase	) - 1

							if down_block_type == "CrossAttnDownBlock2D":
										_snake_case		=			FlaxCrossAttnDownBlockaD(
										    in_channels=lowercase			,  out_channels=lowercase			,  dropout=self.dropout			,  num_layers=self.layers_per_block			,  num_attention_heads=num_attention_heads[i]			,  add_downsample=not is_final_block			,  use_linear_projection=self.use_linear_projection			,  only_cross_attention=only_cross_attention[i]			,  use_memory_efficient_attention=self.use_memory_efficient_attention			,  dtype=self.dtype			,  )
							else:
										_snake_case		=			FlaxDownBlockaD(
										    in_channels=lowercase			,  out_channels=lowercase			,  dropout=self.dropout			,  num_layers=self.layers_per_block			,  add_downsample=not is_final_block			,  dtype=self.dtype			,  )

							down_blocks.append(lowercase	)
				_snake_case		=			down_blocks

				# mid
				_snake_case		=			FlaxUNetMidBlockaDCrossAttn(
				    in_channels=block_out_channels[-1]			,  dropout=self.dropout			,  num_attention_heads=num_attention_heads[-1]			,  use_linear_projection=self.use_linear_projection			,  use_memory_efficient_attention=self.use_memory_efficient_attention			,  dtype=self.dtype			,  )

				# up
				_snake_case		=			[]
				_snake_case		=			list(reversed(lowercase	)	)
				_snake_case		=			list(reversed(lowercase	)	)
				_snake_case		=			list(reversed(lowercase	)	)
				_snake_case		=			reversed_block_out_channels[0]
				for i, up_block_type in enumerate(self.up_block_types	):
							_snake_case		=			output_channel
							_snake_case		=			reversed_block_out_channels[i]
							_snake_case		=			reversed_block_out_channels[min(i + 1			,  len(lowercase	) - 1	)]

							_snake_case		=			i == len(lowercase	) - 1

							if up_block_type == "CrossAttnUpBlock2D":
										_snake_case		=			FlaxCrossAttnUpBlockaD(
										    in_channels=lowercase			,  out_channels=lowercase			,  prev_output_channel=lowercase			,  num_layers=self.layers_per_block + 1			,  num_attention_heads=reversed_num_attention_heads[i]			,  add_upsample=not is_final_block			,  dropout=self.dropout			,  use_linear_projection=self.use_linear_projection			,  only_cross_attention=only_cross_attention[i]			,  use_memory_efficient_attention=self.use_memory_efficient_attention			,  dtype=self.dtype			,  )
							else:
										_snake_case		=			FlaxUpBlockaD(
										    in_channels=lowercase			,  out_channels=lowercase			,  prev_output_channel=lowercase			,  num_layers=self.layers_per_block + 1			,  add_upsample=not is_final_block			,  dropout=self.dropout			,  dtype=self.dtype			,  )

							up_blocks.append(lowercase	)
							_snake_case		=			output_channel
				_snake_case		=			up_blocks

				# out
				_snake_case		=			nn.GroupNorm(num_groups=32			,  epsilon=1E-5	)
				_snake_case		=			nn.Conv(
				    self.out_channels			,  kernel_size=(3, 3)			,  strides=(1, 1)			,  padding=((1, 1), (1, 1))			,  dtype=self.dtype			,  )





	def __call__(  self	:    List[Any]			,  lowercase	:    List[Any]			,  lowercase	:    str			,  lowercase	:    Any			,  lowercase	:    Any=None			,  lowercase	:    Tuple=None			,  lowercase	:    bool = True			,  lowercase	:    bool = False			,  ):


				'''simple docstring'''


				if not isinstance(lowercase			,  jnp.ndarray	):
							_snake_case		=			jnp.array([timesteps]			,  dtype=jnp.intaa	)
				elif isinstance(lowercase			,  jnp.ndarray	) and len(timesteps.shape	) == 0:
							_snake_case		=			timesteps.astype(dtype=jnp.floataa	)
							_snake_case		=			jnp.expand_dims(lowercase			,  0	)

				_snake_case		=			self.time_proj(lowercase	)
				_snake_case		=			self.time_embedding(lowercase	)

				# 2. pre-process
				_snake_case		=			jnp.transpose(lowercase			,  (0, 2, 3, 1)	)
				_snake_case		=			self.conv_in(lowercase	)

				# 3. down
				_snake_case		=			(sample,)
				for down_block in self.down_blocks:
							if isinstance(lowercase			,  lowercase	):
										_snake_case	,					_snake_case		=			down_block(lowercase			,  lowercase			,  lowercase			,  deterministic=not train	)
							else:
										_snake_case	,					_snake_case		=			down_block(lowercase			,  lowercase			,  deterministic=not train	)
							down_block_res_samples += res_samples

				if down_block_additional_residuals is not None:
							_snake_case		=			()

							for down_block_res_sample, down_block_additional_residual in zip(
							    lowercase			,  lowercase	):
										down_block_res_sample += down_block_additional_residual
										new_down_block_res_samples += (down_block_res_sample,)

							_snake_case		=			new_down_block_res_samples

				# 4. mid
				_snake_case		=			self.mid_block(lowercase			,  lowercase			,  lowercase			,  deterministic=not train	)

				if mid_block_additional_residual is not None:
							sample += mid_block_additional_residual

				# 5. up
				for up_block in self.up_blocks:
							_snake_case		=			down_block_res_samples[-(self.layers_per_block + 1) :]
							_snake_case		=			down_block_res_samples[: -(self.layers_per_block + 1)]
							if isinstance(lowercase			,  lowercase	):
										_snake_case		=			up_block(
										    lowercase			,  temb=lowercase			,  encoder_hidden_states=lowercase			,  res_hidden_states_tuple=lowercase			,  deterministic=not train			,  )
							else:
										_snake_case		=			up_block(lowercase			,  temb=lowercase			,  res_hidden_states_tuple=lowercase			,  deterministic=not train	)

        # 6. post-process
				_snake_case		=			self.conv_norm_out(lowercase	)
				_snake_case		=			nn.silu(lowercase	)
				_snake_case		=			self.conv_out(lowercase	)
				_snake_case		=			jnp.transpose(lowercase			,  (0, 3, 1, 2)	)

				if not return_dict:
							return (sample,)

				return FlaxUNetaDConditionOutput(sample=lowercase	)

import numpy as np






def        a_		(       __lowercase   :	np.array ) ->  np.array:
			return 1 / (1 + np.exp(-vector ))


if __name__ == "__main__":
			import doctest

			doctest.testmod()