
"""simple docstring"""

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      _UpperCAmelCase							(		SCREAMING_SNAKE_CASE_							):
      __SCREAMING_SNAKE_CASE   :							torch.FloatTensor

class      _UpperCAmelCase							(		nn.Module							):




      def __init__(							self   ,       lowercase_=3   ,       lowercase_=3   ,       lowercase_=("DownEncoderBlock2D",)   ,       lowercase_=(6_4,)   ,       lowercase_=2   ,       lowercase_=3_2   ,       lowercase_="silu"   ,       lowercase_=True   ,       )						->					List[Any]:
          super().__init__()
          UpperCAmelCase									=					layers_per_block

          UpperCAmelCase									=					torch.nn.Convad(
              lowercase_   ,       block_out_channels[0]   ,       kernel_size=3   ,       stride=1   ,       padding=1   ,       )

          UpperCAmelCase									=					None
          UpperCAmelCase									=					nn.ModuleList([]							)

          # down
          UpperCAmelCase									=					block_out_channels[0]
          for i, down_block_type in enumerate(lowercase_							):
              UpperCAmelCase									=					output_channel
              UpperCAmelCase									=					block_out_channels[i]
              UpperCAmelCase									=					i == len(lowercase_							) - 1

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

          # mid
          UpperCAmelCase									=					UNetMidBlockaD(
              in_channels=block_out_channels[-1]   ,       resnet_eps=1E-6   ,       resnet_act_fn=lowercase_   ,       output_scale_factor=1   ,       resnet_time_scale_shift='default'   ,       attention_head_dim=block_out_channels[-1]   ,       resnet_groups=lowercase_   ,       temb_channels=lowercase_   ,       )

          # out
          UpperCAmelCase									=					nn.GroupNorm(num_channels=block_out_channels[-1]   ,       num_groups=lowercase_   ,       eps=1E-6							)
          UpperCAmelCase									=					nn.SiLU()

          UpperCAmelCase									=					2 * out_channels if double_z else out_channels
          UpperCAmelCase									=					nn.Convad(block_out_channels[-1]   ,       lowercase_   ,       3   ,       padding=1							)

          UpperCAmelCase									=					False




      def     a_      (							self   ,       lowercase_							)						->					Optional[Any]:
          UpperCAmelCase									=					x
          UpperCAmelCase									=					self.conv_in(lowercase_							)

          if self.training and self.gradient_checkpointing:

              def create_custom_forward(lowercase_							):
                  def custom_forward(*lowercase_							):
                      return module(*lowercase_							)

                  return custom_forward

              # down
              if is_torch_version('>='   ,       '1.11.0'							):
                  for down_block in self.down_blocks:
                      UpperCAmelCase									=					torch.utils.checkpoint.checkpoint(
                          create_custom_forward(lowercase_							)   ,       lowercase_   ,       use_reentrant=lowercase_							)
                  # middle
                  UpperCAmelCase									=					torch.utils.checkpoint.checkpoint(
                      create_custom_forward(self.mid_block							)   ,       lowercase_   ,       use_reentrant=lowercase_							)
              else:
                  for down_block in self.down_blocks:
                      UpperCAmelCase									=					torch.utils.checkpoint.checkpoint(create_custom_forward(lowercase_							)   ,       lowercase_							)
                  # middle
                  UpperCAmelCase									=					torch.utils.checkpoint.checkpoint(create_custom_forward(self.mid_block							)   ,       lowercase_							)

          else:
              # down
              for down_block in self.down_blocks:
                  UpperCAmelCase									=					down_block(lowercase_							)

              # middle
              UpperCAmelCase									=					self.mid_block(lowercase_							)

          # post-process
          UpperCAmelCase									=					self.conv_norm_out(lowercase_							)
          UpperCAmelCase									=					self.conv_act(lowercase_							)
          UpperCAmelCase									=					self.conv_out(lowercase_							)

          return sample

class      _UpperCAmelCase							(		nn.Module							):




      def __init__(							self   ,       lowercase_=3   ,       lowercase_=3   ,       lowercase_=("UpDecoderBlock2D",)   ,       lowercase_=(6_4,)   ,       lowercase_=2   ,       lowercase_=3_2   ,       lowercase_="silu"   ,       lowercase_="group"   ,       )						->					Tuple:
          super().__init__()
          UpperCAmelCase									=					layers_per_block

          UpperCAmelCase									=					nn.Convad(
              lowercase_   ,       block_out_channels[-1]   ,       kernel_size=3   ,       stride=1   ,       padding=1   ,       )

          UpperCAmelCase									=					None
          UpperCAmelCase									=					nn.ModuleList([]							)

          UpperCAmelCase									=					in_channels if norm_type == 'spatial' else None

          # mid
          UpperCAmelCase									=					UNetMidBlockaD(
              in_channels=block_out_channels[-1]   ,       resnet_eps=1E-6   ,       resnet_act_fn=lowercase_   ,       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=lowercase_   ,       temb_channels=lowercase_   ,       )

          # up
          UpperCAmelCase									=					list(reversed(lowercase_							)							)
          UpperCAmelCase									=					reversed_block_out_channels[0]
          for i, up_block_type in enumerate(lowercase_							):
              UpperCAmelCase									=					output_channel
              UpperCAmelCase									=					reversed_block_out_channels[i]

              UpperCAmelCase									=					i == len(lowercase_							) - 1

              UpperCAmelCase									=					get_up_block(
                  lowercase_   ,       num_layers=self.layers_per_block + 1   ,       in_channels=lowercase_   ,       out_channels=lowercase_   ,       prev_output_channel=lowercase_   ,       add_upsample=not is_final_block   ,       resnet_eps=1E-6   ,       resnet_act_fn=lowercase_   ,       resnet_groups=lowercase_   ,       attention_head_dim=lowercase_   ,       temb_channels=lowercase_   ,       resnet_time_scale_shift=lowercase_   ,       )
              self.up_blocks.append(lowercase_							)
              UpperCAmelCase									=					output_channel

          # out
          if norm_type == "spatial":
              UpperCAmelCase									=					SpatialNorm(block_out_channels[0]   ,       lowercase_							)
          else:
              UpperCAmelCase									=					nn.GroupNorm(num_channels=block_out_channels[0]   ,       num_groups=lowercase_   ,       eps=1E-6							)
          UpperCAmelCase									=					nn.SiLU()
          UpperCAmelCase									=					nn.Convad(block_out_channels[0]   ,       lowercase_   ,       3   ,       padding=1							)

          UpperCAmelCase									=					False




      def     a_      (							self   ,       lowercase_   ,       lowercase_=None							)						->					List[Any]:
          UpperCAmelCase									=					z
          UpperCAmelCase									=					self.conv_in(lowercase_							)

          UpperCAmelCase									=					next(iter(self.up_blocks.parameters()							)							).dtype
          if self.training and self.gradient_checkpointing:

              def create_custom_forward(lowercase_							):
                  def custom_forward(*lowercase_							):
                      return module(*lowercase_							)

                  return custom_forward

              if is_torch_version('>='   ,       '1.11.0'							):
                  # middle
                  UpperCAmelCase									=					torch.utils.checkpoint.checkpoint(
                      create_custom_forward(self.mid_block							)   ,       lowercase_   ,       lowercase_   ,       use_reentrant=lowercase_							)
                  UpperCAmelCase									=					sample.to(lowercase_							)

                  # up
                  for up_block in self.up_blocks:
                      UpperCAmelCase									=					torch.utils.checkpoint.checkpoint(
                          create_custom_forward(lowercase_							)   ,       lowercase_   ,       lowercase_   ,       use_reentrant=lowercase_							)
              else:
                  # middle
                  UpperCAmelCase									=					torch.utils.checkpoint.checkpoint(
                      create_custom_forward(self.mid_block							)   ,       lowercase_   ,       lowercase_							)
                  UpperCAmelCase									=					sample.to(lowercase_							)

                  # up
                  for up_block in self.up_blocks:
                      UpperCAmelCase									=					torch.utils.checkpoint.checkpoint(create_custom_forward(lowercase_							)   ,       lowercase_   ,       lowercase_							)
          else:
              # middle
              UpperCAmelCase									=					self.mid_block(lowercase_   ,       lowercase_							)
              UpperCAmelCase									=					sample.to(lowercase_							)

              # up
              for up_block in self.up_blocks:
                  UpperCAmelCase									=					up_block(lowercase_   ,       lowercase_							)

        # post-process
          if latent_embeds is None:
              UpperCAmelCase									=					self.conv_norm_out(lowercase_							)
          else:
              UpperCAmelCase									=					self.conv_norm_out(lowercase_   ,       lowercase_							)
          UpperCAmelCase									=					self.conv_act(lowercase_							)
          UpperCAmelCase									=					self.conv_out(lowercase_							)

          return sample

class      _UpperCAmelCase							(		nn.Module							):




      def __init__(							self   ,       lowercase_   ,       lowercase_   ,       lowercase_   ,       lowercase_=None   ,       lowercase_="random"   ,       lowercase_=False   ,       lowercase_=True							)						->					List[str]:
          super().__init__()
          UpperCAmelCase									=					n_e
          UpperCAmelCase									=					vq_embed_dim
          UpperCAmelCase									=					beta
          UpperCAmelCase									=					legacy

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

          UpperCAmelCase									=					remap
          if self.remap is not None:
              self.register_buffer('used'   ,       torch.tensor(np.load(self.remap							)							)							)
              UpperCAmelCase									=					self.used.shape[0]
              UpperCAmelCase									=					unknown_index  # "random" or "extra" or integer
              if self.unknown_index == "extra":
                  UpperCAmelCase									=					self.re_embed
                  UpperCAmelCase									=					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:
              UpperCAmelCase									=					n_e

          UpperCAmelCase									=					sane_index_shape




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




      def     a_      (							self   ,       lowercase_							)						->					str:
          UpperCAmelCase									=					inds.shape
          assert len(lowercase_							) > 1
          UpperCAmelCase									=					inds.reshape(ishape[0]   ,       -1							)
          UpperCAmelCase									=					self.used.to(lowercase_							)
          if self.re_embed > self.used.shape[0]:  # extra token
              UpperCAmelCase									=					0  # simply set to zero
          UpperCAmelCase									=					torch.gather(used[None, :][inds.shape[0] * [0], :]   ,       1   ,       lowercase_							)
          return back.reshape(lowercase_							)




      def     a_      (							self   ,       lowercase_							)						->					str:
          # reshape z -> (batch, height, width, channel) and flatten
          UpperCAmelCase									=					z.permute(0   ,       2   ,       3   ,       1							).contiguous()
          UpperCAmelCase									=					z.view(-1   ,       self.vq_embed_dim							)

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

          UpperCAmelCase									=					self.embedding(lowercase_							).view(z.shape							)
          UpperCAmelCase									=					None
          UpperCAmelCase									=					None

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

          # preserve gradients
          UpperCAmelCase									=					z + (z_q - z).detach()

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

          if self.remap is not None:
              UpperCAmelCase									=					min_encoding_indices.reshape(z.shape[0]   ,       -1							)  # add batch axis
              UpperCAmelCase									=					self.remap_to_used(lowercase_							)
              UpperCAmelCase									=					min_encoding_indices.reshape(-1   ,       1							)  # flatten

          if self.sane_index_shape:
              UpperCAmelCase									=					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     a_      (							self   ,       lowercase_   ,       lowercase_							)						->					str:
          # shape specifying (batch, height, width, channel)
          if self.remap is not None:
              UpperCAmelCase									=					indices.reshape(shape[0]   ,       -1							)  # add batch axis
              UpperCAmelCase									=					self.unmap_to_all(lowercase_							)
              UpperCAmelCase									=					indices.reshape(-1							)  # flatten again

          # get quantized latent vectors
          UpperCAmelCase									=					self.embedding(lowercase_							)

          if shape is not None:
              UpperCAmelCase									=					z_q.view(lowercase_							)
              # reshape back to match original input shape
              UpperCAmelCase									=					z_q.permute(0   ,       3   ,       1   ,       2							).contiguous()

          return z_q

class      _UpperCAmelCase							(		SCREAMING_SNAKE_CASE_							):




      def __init__(							self   ,       lowercase_   ,       lowercase_=False							)						->					Optional[int]:
          UpperCAmelCase									=					parameters
          UpperCAmelCase			,							UpperCAmelCase									=					torch.chunk(lowercase_   ,       2   ,       dim=1							)
          UpperCAmelCase									=					torch.clamp(self.logvar   ,       -3_0.0   ,       2_0.0							)
          UpperCAmelCase									=					deterministic
          UpperCAmelCase									=					torch.exp(0.5 * self.logvar							)
          UpperCAmelCase									=					torch.exp(self.logvar							)
          if self.deterministic:
              UpperCAmelCase									=					UpperCAmelCase									=					torch.zeros_like(
                  self.mean   ,       device=self.parameters.device   ,       dtype=self.parameters.dtype							)




      def     a_      (							self   ,       lowercase_ = None							)						->					torch.FloatTensor:
          # make sure sample is on the same device as the parameters and has same dtype
          UpperCAmelCase									=					randn_tensor(
              self.mean.shape   ,       generator=lowercase_   ,       device=self.parameters.device   ,       dtype=self.parameters.dtype							)
          UpperCAmelCase									=					self.mean + self.std * sample
          return x




      def     a_      (							self   ,       lowercase_=None							)						->					List[str]:
          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     a_      (							self   ,       lowercase_   ,       lowercase_=[1, 2, 3]							)						->					str:
          if self.deterministic:
              return torch.Tensor([0.0]							)
          UpperCAmelCase									=					np.log(2.0 * np.pi							)
          return 0.5 * torch.sum(logtwopi + self.logvar + torch.pow(sample - self.mean   ,       2							) / self.var   ,       dim=lowercase_							)




      def     a_      (							self							)						->					Any:
          return self.mean





"""simple docstring"""

def     lowercase__						(					lowerCAmelCase				:					int ,				lowerCAmelCase				:					list ) ->      int:






    """simple docstring"""




    _enforce_args(lowerCAmelCase ,				lowerCAmelCase )
    if n == 0:
        return 0
    UpperCAmelCase									=					float('-inf' )
    for i in range(1 ,				n + 1 ):
        UpperCAmelCase									=					max(
            lowerCAmelCase ,				prices[i - 1] + naive_cut_rod_recursive(n - i ,				lowerCAmelCase ) )

    return max_revue




def     lowercase__						(					lowerCAmelCase				:					int ,				lowerCAmelCase				:					list ) ->      Dict:






    """simple docstring"""




    _enforce_args(lowerCAmelCase ,				lowerCAmelCase )
    UpperCAmelCase									=					[float('-inf' ) for _ in range(n + 1 )]
    return _top_down_cut_rod_recursive(lowerCAmelCase ,				lowerCAmelCase ,				lowerCAmelCase )




def     lowercase__						(					lowerCAmelCase				:					int ,				lowerCAmelCase				:					list ,				lowerCAmelCase				:					list ) ->      int:






    """simple docstring"""




    if max_rev[n] >= 0:
        return max_rev[n]
    elif n == 0:
        return 0
    else:
        UpperCAmelCase									=					float('-inf' )
        for i in range(1 ,				n + 1 ):
            UpperCAmelCase									=					max(
                lowerCAmelCase ,				prices[i - 1] + _top_down_cut_rod_recursive(n - i ,				lowerCAmelCase ,				lowerCAmelCase ) ,				)

        UpperCAmelCase									=					max_revenue

    return max_rev[n]




def     lowercase__						(					lowerCAmelCase				:					int ,				lowerCAmelCase				:					list ) ->      Optional[int]:






    """simple docstring"""




    _enforce_args(lowerCAmelCase ,				lowerCAmelCase )

    # length(max_rev) = n + 1, to accommodate for the revenue obtainable from a rod of
    # length 0.
    UpperCAmelCase									=					[float('-inf' ) for _ in range(n + 1 )]
    UpperCAmelCase									=					0

    for i in range(1 ,				n + 1 ):
        UpperCAmelCase									=					max_rev[i]
        for j in range(1 ,				i + 1 ):
            UpperCAmelCase									=					max(lowerCAmelCase ,				prices[j - 1] + max_rev[i - j] )

        UpperCAmelCase									=					max_revenue_i

    return max_rev[n]




def     lowercase__						(					lowerCAmelCase				:					int ,				lowerCAmelCase				:					list ) ->      Union[str, Any]:






    """simple docstring"""




    if n < 0:
        UpperCAmelCase									=					F"n must be greater than or equal to 0. Got n = {n}"
        raise ValueError(lowerCAmelCase )

    if n > len(lowerCAmelCase ):
        UpperCAmelCase									=					(
            'Each integral piece of rod must have a corresponding price. '
            F"Got n = {n} but length of prices = {len(lowerCAmelCase )}"
        )
        raise ValueError(lowerCAmelCase )




def     lowercase__						(					) ->      Optional[int]:






    """simple docstring"""




    UpperCAmelCase									=					[6, 10, 12, 15, 20, 23]
    UpperCAmelCase									=					len(lowerCAmelCase )

    # the best revenue comes from cutting the rod into 6 pieces, each
    # of length 1 resulting in a revenue of 6 * 6 = 36.
    UpperCAmelCase									=					36

    UpperCAmelCase									=					top_down_cut_rod(lowerCAmelCase ,				lowerCAmelCase )
    UpperCAmelCase									=					bottom_up_cut_rod(lowerCAmelCase ,				lowerCAmelCase )
    UpperCAmelCase									=					naive_cut_rod_recursive(lowerCAmelCase ,				lowerCAmelCase )

    assert expected_max_revenue == max_rev_top_down
    assert max_rev_top_down == max_rev_bottom_up
    assert max_rev_bottom_up == max_rev_naive


if __name__ == "__main__":
   main()



