
import types
from typing import List, Optional, Tuple, Union

import torch
from transformers import CLIPTextModelWithProjection, CLIPTokenizer
from transformers.models.clip.modeling_clip import CLIPTextModelOutput

from diffusers.models import PriorTransformer
from diffusers.pipelines import DiffusionPipeline, StableDiffusionImageVariationPipeline
from diffusers.schedulers import UnCLIPScheduler
from diffusers.utils import logging, randn_tensor


snake_case__  							=							logging.get_logger(__name__)  # pylint: disable=invalid-name

def        lowerCamelCase_      (			self							:				Tuple							,			UpperCAmelCase_							:				List[str]							,			UpperCAmelCase_							:				List[Any]							,			UpperCAmelCase_							:				List[str]							,			UpperCAmelCase_							:				Any       ):
						lowercase       :    str											=  image.to(device=UpperCAmelCase_       )
						lowercase       :    List[str]											=  image  # take image as image_embeddings
						lowercase       :    Optional[Any]											=  image_embeddings.unsqueeze(1       )

						# duplicate image embeddings for each generation per prompt, using mps friendly method
						lowercase				,				lowercase				,				lowercase       :    Optional[Any]											=  image_embeddings.shape
						lowercase       :    Union[str, Any]											=  image_embeddings.repeat(1							,			UpperCAmelCase_							,			1       )
						lowercase       :    List[str]											=  image_embeddings.view(bs_embed * num_images_per_prompt							,			UpperCAmelCase_							,			-1       )

						if do_classifier_free_guidance:
												lowercase       :    Optional[Any]											=  torch.zeros_like(UpperCAmelCase_       )

												# For classifier free guidance, we need to do two forward passes.
												# Here we concatenate the unconditional and text embeddings into a single batch
												# to avoid doing two forward passes
												lowercase       :    Union[str, Any]											=  torch.cat([uncond_embeddings, image_embeddings]       )

						return image_embeddings







class 							UpperCAmelCase	(   lowerCAmelCase__					):

					def __init__(			self      :					Optional[Any] ,      lowerCAmelCase      :					PriorTransformer ,      lowerCAmelCase      :					CLIPTokenizer ,      lowerCAmelCase      :					CLIPTextModelWithProjection ,      lowerCAmelCase      :					UnCLIPScheduler ,      lowerCAmelCase      :					Optional[dict] = None ,      ):
											super().__init__()

											lowercase       :    List[str]											=  {'''image_encoder''': None} if decoder_pipe_kwargs is None else decoder_pipe_kwargs

											lowercase       :    List[Any]											=  decoder_pipe_kwargs.get('''torch_dtype''' ,      lowerCAmelCase_					) or prior.dtype

											lowercase       :    List[Any]											=  StableDiffusionImageVariationPipeline.from_pretrained(
											    '''lambdalabs/sd-image-variations-diffusers''' ,      **lowerCAmelCase_					)

											# replace `_encode_image` method
											lowercase       :    Optional[int]											=  types.MethodType(_encode_image ,      self.decoder_pipe					)

											self.register_modules(
											    prior=lowerCAmelCase_ ,      tokenizer=lowerCAmelCase_ ,      text_encoder=lowerCAmelCase_ ,      prior_scheduler=lowerCAmelCase_ ,      )

					def        _lowerCAmelCase	(			self      :					List[Any] ,      lowerCAmelCase      :					str ,      lowerCAmelCase      :					List[Any] ,      lowerCAmelCase      :					List[str] ,      lowerCAmelCase      :					Union[str, Any] ,      lowerCAmelCase      :					Optional[Union[CLIPTextModelOutput, Tuple]] = None ,      lowerCAmelCase      :					Optional[torch.Tensor] = None ,      ):






											if text_model_output is None:
																	lowercase       :    Optional[int]											=  len(lowerCAmelCase_					) if isinstance(lowerCAmelCase_ ,      lowerCAmelCase_					) else 1
																	# get prompt text embeddings
																	lowercase       :    Union[str, Any]											=  self.tokenizer(
																	    lowerCAmelCase_ ,      padding='''max_length''' ,      max_length=self.tokenizer.model_max_length ,      return_tensors='''pt''' ,      )
																	lowercase       :    List[Any]											=  text_inputs.input_ids
																	lowercase       :    Optional[int]											=  text_inputs.attention_mask.bool().to(lowerCAmelCase_					)

																	if text_input_ids.shape[-1] > self.tokenizer.model_max_length:
																							lowercase       :    Optional[Any]											=  self.tokenizer.batch_decode(text_input_ids[:, self.tokenizer.model_max_length :]					)
																							logger.warning(
																							    '''The following part of your input was truncated because CLIP can only handle sequences up to'''
																							    f''' {self.tokenizer.model_max_length} tokens: {removed_text}'''					)
																							lowercase       :    Any											=  text_input_ids[:, : self.tokenizer.model_max_length]

																	lowercase       :    Dict											=  self.text_encoder(text_input_ids.to(lowerCAmelCase_					)					)

																	lowercase       :    Optional[Any]											=  text_encoder_output.text_embeds
																	lowercase       :    Union[str, Any]											=  text_encoder_output.last_hidden_state

											else:
																	lowercase       :    Any											=  text_model_output[0].shape[0]
																	lowercase				,				lowercase       :    int											=  text_model_output[0], text_model_output[1]
																	lowercase       :    Optional[int]											=  text_attention_mask

											lowercase       :    List[str]											=  text_embeddings.repeat_interleave(lowerCAmelCase_ ,      dim=0					)
											lowercase       :    Tuple											=  text_encoder_hidden_states.repeat_interleave(lowerCAmelCase_ ,      dim=0					)
											lowercase       :    Optional[Any]											=  text_mask.repeat_interleave(lowerCAmelCase_ ,      dim=0					)

											if do_classifier_free_guidance:
																	lowercase       :    Union[str, Any]											=  [''''''] * batch_size

																	lowercase       :    Union[str, Any]											=  self.tokenizer(
																	    lowerCAmelCase_ ,      padding='''max_length''' ,      max_length=self.tokenizer.model_max_length ,      truncation=lowerCAmelCase_ ,      return_tensors='''pt''' ,      )
																	lowercase       :    int											=  uncond_input.attention_mask.bool().to(lowerCAmelCase_					)
																	lowercase       :    int											=  self.text_encoder(uncond_input.input_ids.to(lowerCAmelCase_					)					)

																	lowercase       :    int											=  uncond_embeddings_text_encoder_output.text_embeds
																	lowercase       :    Dict											=  uncond_embeddings_text_encoder_output.last_hidden_state

																	# duplicate unconditional embeddings for each generation per prompt, using mps friendly method

																	lowercase       :    Dict											=  uncond_embeddings.shape[1]
																	lowercase       :    Any											=  uncond_embeddings.repeat(1 ,      lowerCAmelCase_					)
																	lowercase       :    Tuple											=  uncond_embeddings.view(batch_size * num_images_per_prompt ,      lowerCAmelCase_					)

																	lowercase       :    Tuple											=  uncond_text_encoder_hidden_states.shape[1]
																	lowercase       :    Union[str, Any]											=  uncond_text_encoder_hidden_states.repeat(1 ,      lowerCAmelCase_ ,      1					)
																	lowercase       :    Any											=  uncond_text_encoder_hidden_states.view(
																	    batch_size * num_images_per_prompt ,      lowerCAmelCase_ ,      -1					)
																	lowercase       :    Dict											=  uncond_text_mask.repeat_interleave(lowerCAmelCase_ ,      dim=0					)

																	# done duplicates

																	# For classifier free guidance, we need to do two forward passes.
																	# Here we concatenate the unconditional and text embeddings into a single batch
																	# to avoid doing two forward passes
																	lowercase       :    Dict											=  torch.cat([uncond_embeddings, text_embeddings]					)
																	lowercase       :    Any											=  torch.cat([uncond_text_encoder_hidden_states, text_encoder_hidden_states]					)

																	lowercase       :    Any											=  torch.cat([uncond_text_mask, text_mask]					)

											return text_embeddings, text_encoder_hidden_states, text_mask

					@property
					def        _lowerCAmelCase	(			self      :					Dict					):






											if self.device != torch.device('''meta'''					) or not hasattr(self.prior ,      '''_hf_hook'''					):
																	return self.device
											for module in self.prior.modules():
																	if (
																	    hasattr(lowerCAmelCase_ ,      '''_hf_hook'''					)
																	    and hasattr(module._hf_hook ,      '''execution_device'''					)
																	    and module._hf_hook.execution_device is not None
																	):
																							return torch.device(module._hf_hook.execution_device					)
											return self.device

					def        _lowerCAmelCase	(			self      :					Optional[int] ,      lowerCAmelCase      :					Tuple ,      lowerCAmelCase      :					str ,      lowerCAmelCase      :					Tuple ,      lowerCAmelCase      :					Dict ,      lowerCAmelCase      :					Tuple ,      lowerCAmelCase      :					Any					):






											if latents is None:
																	lowercase       :    Dict											=  randn_tensor(lowerCAmelCase_ ,      generator=lowerCAmelCase_ ,      device=lowerCAmelCase_ ,      dtype=lowerCAmelCase_					)
											else:
																	if latents.shape != shape:
																							raise ValueError(f'''Unexpected latents shape, got {latents.shape}, expected {shape}'''					)
																	lowercase       :    Dict											=  latents.to(lowerCAmelCase_					)

											lowercase       :    int											=  latents * scheduler.init_noise_sigma
											return latents

					def        _lowerCAmelCase	(			self      :					List[str] ,      lowerCAmelCase      :					Optional[Union[str, torch.device]] = None					):
											self.decoder_pipe.to(lowerCAmelCase_					)
											super().to(lowerCAmelCase_					)




					@torch.no_grad()
					def __call__(			self      :					int ,      lowerCAmelCase      :					Optional[Union[str, List[str]]] = None ,      lowerCAmelCase      :					Optional[int] = None ,      lowerCAmelCase      :					Optional[int] = None ,      lowerCAmelCase      :					int = 1 ,      lowerCAmelCase      :					int = 25 ,      lowerCAmelCase      :					Optional[torch.Generator] = None ,      lowerCAmelCase      :					Optional[torch.FloatTensor] = None ,      lowerCAmelCase      :					Optional[Union[CLIPTextModelOutput, Tuple]] = None ,      lowerCAmelCase      :					Optional[torch.Tensor] = None ,      lowerCAmelCase      :					float = 4.0 ,      lowerCAmelCase      :					float = 8.0 ,      lowerCAmelCase      :					int = 50 ,      lowerCAmelCase      :					Optional[int] = 1 ,      lowerCAmelCase      :					float = 0.0 ,      lowerCAmelCase      :					Optional[str] = "pil" ,      lowerCAmelCase      :					bool = True ,      ):






											if prompt is not None:
																	if isinstance(lowerCAmelCase_ ,      lowerCAmelCase_					):
																							lowercase       :    Tuple											=  1
																	elif isinstance(lowerCAmelCase_ ,      lowerCAmelCase_					):
																							lowercase       :    List[Any]											=  len(lowerCAmelCase_					)
																	else:
																							raise ValueError(f'''`prompt` has to be of type `str` or `list` but is {type(lowerCAmelCase_					)}'''					)
											else:
																	lowercase       :    List[str]											=  text_model_output[0].shape[0]

											lowercase       :    List[str]											=  self._execution_device

											lowercase       :    List[Any]											=  batch_size * num_images_per_prompt

											lowercase       :    Dict											=  prior_guidance_scale > 1.0 or decoder_guidance_scale > 1.0

											lowercase				,				lowercase				,				lowercase       :    List[str]											=  self._encode_prompt(
											    lowerCAmelCase_ ,      lowerCAmelCase_ ,      lowerCAmelCase_ ,      lowerCAmelCase_ ,      lowerCAmelCase_ ,      lowerCAmelCase_					)

											# prior

											self.prior_scheduler.set_timesteps(lowerCAmelCase_ ,      device=lowerCAmelCase_					)
											lowercase       :    str											=  self.prior_scheduler.timesteps

											lowercase       :    List[Any]											=  self.prior.config.embedding_dim

											lowercase       :    List[str]											=  self.prepare_latents(
											    (batch_size, embedding_dim) ,      text_embeddings.dtype ,      lowerCAmelCase_ ,      lowerCAmelCase_ ,      lowerCAmelCase_ ,      self.prior_scheduler ,      )

											for i, t in enumerate(self.progress_bar(lowerCAmelCase_					)					):
																	# expand the latents if we are doing classifier free guidance
																	lowercase       :    Union[str, Any]											=  torch.cat([prior_latents] * 2					) if do_classifier_free_guidance else prior_latents

																	lowercase       :    Any											=  self.prior(
																	    lowerCAmelCase_ ,      timestep=lowerCAmelCase_ ,      proj_embedding=lowerCAmelCase_ ,      encoder_hidden_states=lowerCAmelCase_ ,      attention_mask=lowerCAmelCase_ ,      ).predicted_image_embedding

																	if do_classifier_free_guidance:
																							lowercase				,				lowercase       :    int											=  predicted_image_embedding.chunk(2					)
																							lowercase       :    str											=  predicted_image_embedding_uncond + prior_guidance_scale * (
																							    predicted_image_embedding_text - predicted_image_embedding_uncond
																							)

																	if i + 1 == prior_timesteps_tensor.shape[0]:
																							lowercase       :    Any											=  None
																	else:
																							lowercase       :    Any											=  prior_timesteps_tensor[i + 1]

																	lowercase       :    List[Any]											=  self.prior_scheduler.step(
																	    lowerCAmelCase_ ,      timestep=lowerCAmelCase_ ,      sample=lowerCAmelCase_ ,      generator=lowerCAmelCase_ ,      prev_timestep=lowerCAmelCase_ ,      ).prev_sample

											lowercase       :    Optional[Any]											=  self.prior.post_process_latents(lowerCAmelCase_					)

											lowercase       :    Optional[Any]											=  prior_latents

											lowercase       :    Optional[Any]											=  self.decoder_pipe(
											    image=lowerCAmelCase_ ,      height=lowerCAmelCase_ ,      width=lowerCAmelCase_ ,      num_inference_steps=lowerCAmelCase_ ,      guidance_scale=lowerCAmelCase_ ,      generator=lowerCAmelCase_ ,      output_type=lowerCAmelCase_ ,      return_dict=lowerCAmelCase_ ,      num_images_per_prompt=lowerCAmelCase_ ,      eta=lowerCAmelCase_ ,      )
											return output




from itertools import combinations_with_replacement

def        lowerCamelCase_      (			UpperCAmelCase_							:				int = 1_00       ):
						lowercase       :    list[int]											=  [*list(range(1							,			21       )       ), 25]
						lowercase       :    list[int]											=  [2 * x for x in range(1							,			21       )] + [50]
						lowercase       :    list[int]											=  [3 * x for x in range(1							,			21       )]
						lowercase       :    list[int]											=  singles + doubles + triples + [0]

						lowercase       :    int											=  0
						lowercase       :    int
						lowercase       :    int
						lowercase       :    int
						lowercase       :    int

						for double in doubles:
												for throwa, throwa in combinations_with_replacement(UpperCAmelCase_							,			2       ):
																		lowercase       :    Union[str, Any]											=  double + throwa + throwa
																		if checkout_total < limit:
																								num_checkouts += 1

						return num_checkouts


if __name__ == "__main__":
				print(F'{solution() = }')


