
import re
from typing import Callable, List, Optional, Union

import tensorflow as tf


try:
							from tensorflow.keras.optimizers.legacy import Adam
except ImportError:
							from tensorflow.keras.optimizers import Adam







class 				lowercase		(					tf.keras.optimizers.schedules.LearningRateSchedule		):




							def __init__(				self   ,A__   ,A__   ,A__   ,A__ = 1.0   ,A__ = None   ,):
												super().__init__()
												lowercase							=						initial_learning_rate
												lowercase							=						warmup_steps
												lowercase							=						power
												lowercase							=						decay_schedule_fn
												lowercase							=						name




							def __call__(				self   ,A__):
												with tf.name_scope(self.name or '''WarmUp''') as name:
																	# Implements polynomial warmup. i.e., if global_step < warmup_steps, the
																	# learning rate will be `global_step/num_warmup_steps * init_lr`.
																	lowercase							=						tf.cast(A__   ,tf.floataa)
																	lowercase							=						tf.cast(self.warmup_steps   ,tf.floataa)
																	lowercase							=						global_step_float / warmup_steps_float
																	lowercase							=						self.initial_learning_rate * tf.math.pow(A__   ,self.power)
																	return tf.cond(
																	    global_step_float < warmup_steps_float   ,lambda: warmup_learning_rate   ,lambda: self.decay_schedule_fn(step - self.warmup_steps)   ,name=A__   ,)





							def  A__      (				self):
												return {
												    "initial_learning_rate": self.initial_learning_rate,
												    "decay_schedule_fn": self.decay_schedule_fn,
												    "warmup_steps": self.warmup_steps,
												    "power": self.power,
												    "name": self.name,
												}



def        UpperCamelCase    (							lowerCAmelCase__ ,			lowerCAmelCase__ ,			lowerCAmelCase__ ,			lowerCAmelCase__ = 0.0 ,			lowerCAmelCase__ = 0.9 ,			lowerCAmelCase__ = 0.9_99 ,			lowerCAmelCase__ = 1E-8 ,			lowerCAmelCase__ = None ,			lowerCAmelCase__ = None ,			lowerCAmelCase__ = 0.0 ,			lowerCAmelCase__ = 1.0 ,			lowerCAmelCase__ = None ,			):
					'''simple docstring'''
					lowercase							=						tf.keras.optimizers.schedules.PolynomialDecay(
					    initial_learning_rate=lowerCAmelCase__ ,			decay_steps=num_train_steps - num_warmup_steps ,			end_learning_rate=init_lr * min_lr_ratio ,			power=lowerCAmelCase__ ,			)
					if num_warmup_steps:
										lowercase							=						WarmUp(
										    initial_learning_rate=lowerCAmelCase__ ,			decay_schedule_fn=lowerCAmelCase__ ,			warmup_steps=lowerCAmelCase__ ,			)
					if weight_decay_rate > 0.0:
										lowercase							=						AdamWeightDecay(
										    learning_rate=lowerCAmelCase__ ,			weight_decay_rate=lowerCAmelCase__ ,			beta_a=lowerCAmelCase__ ,			beta_a=lowerCAmelCase__ ,			epsilon=lowerCAmelCase__ ,			clipnorm=lowerCAmelCase__ ,			global_clipnorm=lowerCAmelCase__ ,			exclude_from_weight_decay=['''LayerNorm''', '''layer_norm''', '''bias'''] ,			include_in_weight_decay=lowerCAmelCase__ ,			)
					else:
										lowercase							=						tf.keras.optimizers.Adam(
										    learning_rate=lowerCAmelCase__ ,			beta_a=lowerCAmelCase__ ,			beta_a=lowerCAmelCase__ ,			epsilon=lowerCAmelCase__ ,			clipnorm=lowerCAmelCase__ ,			global_clipnorm=lowerCAmelCase__ ,			)
					# We return the optimizer and the LR scheduler in order to better track the
					# evolution of the LR independently of the optimizer.
					return optimizer, lr_schedule







class 				lowercase		(					SCREAMING_SNAKE_CASE__		):




							def __init__(				self   ,A__ = 0.001   ,A__ = 0.9   ,A__ = 0.999   ,A__ = 1E-7   ,A__ = False   ,A__ = 0.0   ,A__ = None   ,A__ = None   ,A__ = "AdamWeightDecay"   ,**A__   ,):
												super().__init__(A__   ,A__   ,A__   ,A__   ,A__   ,A__   ,**A__)
												lowercase							=						weight_decay_rate
												lowercase							=						include_in_weight_decay
												lowercase							=						exclude_from_weight_decay




							@classmethod
							def  A__      (				cls   ,A__):
												lowercase							=						{'''WarmUp''': WarmUp}
												return super(A__   ,cls).from_config(A__   ,custom_objects=A__)




							def  A__      (				self   ,A__   ,A__   ,A__):
												super(A__   ,self)._prepare_local(A__   ,A__   ,A__)
												lowercase							=						tf.constant(
												    self.weight_decay_rate   ,name='''adam_weight_decay_rate''')




							def  A__      (				self   ,A__   ,A__   ,A__):
												lowercase							=						self._do_use_weight_decay(var.name)
												if do_decay:
																	return var.assign_sub(
																	    learning_rate * var * apply_state[(var.device, var.dtype.base_dtype)]['''weight_decay_rate''']   ,use_locking=self._use_locking   ,)
												return tf.no_op()




							def  A__      (				self   ,A__   ,A__=None   ,**A__):
												lowercase	,						lowercase							=						list(zip(*A__))
												return super(A__   ,self).apply_gradients(zip(A__   ,A__)   ,name=A__   ,**A__)




							def  A__      (				self   ,A__   ,A__   ,A__):
												if apply_state is None:
																	return self._decayed_lr_t[var_dtype], {}

												lowercase							=						apply_state or {}
												lowercase							=						apply_state.get((var_device, var_dtype))
												if coefficients is None:
																	lowercase							=						self._fallback_apply_state(A__   ,A__)
																	lowercase							=						coefficients

												return coefficients["lr_t"], {"apply_state": apply_state}




							def  A__      (				self   ,A__   ,A__   ,A__=None):
												lowercase	,						lowercase							=						self._get_lr(var.device   ,var.dtype.base_dtype   ,A__)
												lowercase							=						self._decay_weights_op(A__   ,A__   ,A__)
												with tf.control_dependencies([decay]):
																	return super(A__   ,self)._resource_apply_dense(A__   ,A__   ,**A__)




							def  A__      (				self   ,A__   ,A__   ,A__   ,A__=None):
												lowercase	,						lowercase							=						self._get_lr(var.device   ,var.dtype.base_dtype   ,A__)
												lowercase							=						self._decay_weights_op(A__   ,A__   ,A__)
												with tf.control_dependencies([decay]):
																	return super(A__   ,self)._resource_apply_sparse(A__   ,A__   ,A__   ,**A__)




							def  A__      (				self):
												lowercase							=						super().get_config()
												config.update({'''weight_decay_rate''': self.weight_decay_rate})
												return config





							def  A__      (				self   ,A__):
												if self.weight_decay_rate == 0:
																	return False

												if self._include_in_weight_decay:
																	for r in self._include_in_weight_decay:
																						if re.search(A__   ,A__) is not None:
																											return True

												if self._exclude_from_weight_decay:
																	for r in self._exclude_from_weight_decay:
																						if re.search(A__   ,A__) is not None:
																											return False
												return True







class 				lowercase		(					SCREAMING_SNAKE_CASE__		):




							def __init__(				self):
												lowercase							=						[]
												lowercase							=						None




							@property
							def  A__      (				self):
												if self._accum_steps is None:
																	lowercase							=						tf.Variable(
																	    tf.constant(0   ,dtype=tf.intaa)   ,trainable=A__   ,synchronization=tf.VariableSynchronization.ON_READ   ,aggregation=tf.VariableAggregation.ONLY_FIRST_REPLICA   ,)

												return self._accum_steps.value()




							@property
							def  A__      (				self):
												if not self._gradients:
																	raise ValueError('''The accumulator should be called first to initialize the gradients''')
												return [gradient.value() if gradient is not None else gradient for gradient in self._gradients]




							def __call__(				self   ,A__):
												if not self._gradients:
																	lowercase							=						self.step  # Create the step variable.
																	self._gradients.extend(
																	    [
																	        tf.Variable(
																	            tf.zeros_like(A__)   ,trainable=A__   ,synchronization=tf.VariableSynchronization.ON_READ   ,aggregation=tf.VariableAggregation.ONLY_FIRST_REPLICA   ,)
																	        if gradient is not None
																	        else gradient
																	        for gradient in gradients
																	    ])
												if len(A__) != len(self._gradients):
																	raise ValueError(f'Expected {len(self._gradients)} gradients, but got {len(A__)}')

												for accum_gradient, gradient in zip(self._gradients   ,A__):
																	if accum_gradient is not None and gradient is not None:
																						accum_gradient.assign_add(A__)

												self._accum_steps.assign_add(1)





							def  A__      (				self):
												if not self._gradients:
																	return
												self._accum_steps.assign(0)
												for gradient in self._gradients:
																	if gradient is not None:
																						gradient.assign(tf.zeros_like(A__))






import gc
import unittest

import numpy as np
import torch
from transformers import CLIPTextConfig, CLIPTextModelWithProjection, CLIPTokenizer

from diffusers import HeunDiscreteScheduler, PriorTransformer, ShapEPipeline
from diffusers.pipelines.shap_e import ShapERenderer
from diffusers.utils import load_numpy, slow
from diffusers.utils.testing_utils import require_torch_gpu, torch_device

from ..test_pipelines_common import PipelineTesterMixin, assert_mean_pixel_difference







class 				lowercase		(					SCREAMING_SNAKE_CASE__       ,  unittest.TestCase		):
							lowercase_       :       Tuple       					=ShapEPipeline
							lowercase_       :       List[Any]       					=['''prompt''']
							lowercase_       :       int       					=['''prompt''']
							lowercase_       :       Union[str, Any]       					=[
							    '''num_images_per_prompt''',
							    '''num_inference_steps''',
							    '''generator''',
							    '''latents''',
							    '''guidance_scale''',
							    '''frame_size''',
							    '''output_type''',
							    '''return_dict''',
							]
							lowercase_       :       Optional[int]       					=False




							@property
							def  A__      (				self):
												return 3_2




							@property
							def  A__      (				self):
												return 3_2




							@property
							def  A__      (				self):
												return self.time_input_dim * 4




							@property
							def  A__      (				self):
												return 8




							@property
							def  A__      (				self):
												lowercase							=						CLIPTokenizer.from_pretrained('''hf-internal-testing/tiny-random-clip''')
												return tokenizer




							@property
							def  A__      (				self):
												torch.manual_seed(0)
												lowercase							=						CLIPTextConfig(
												    bos_token_id=0   ,eos_token_id=2   ,hidden_size=self.text_embedder_hidden_size   ,projection_dim=self.text_embedder_hidden_size   ,intermediate_size=3_7   ,layer_norm_eps=1E-05   ,num_attention_heads=4   ,num_hidden_layers=5   ,pad_token_id=1   ,vocab_size=1_0_0_0   ,)
												return CLIPTextModelWithProjection(A__)




							@property
							def  A__      (				self):
												torch.manual_seed(0)

												lowercase							=						{
												    '''num_attention_heads''': 2,
												    '''attention_head_dim''': 1_6,
												    '''embedding_dim''': self.time_input_dim,
												    '''num_embeddings''': 3_2,
												    '''embedding_proj_dim''': self.text_embedder_hidden_size,
												    '''time_embed_dim''': self.time_embed_dim,
												    '''num_layers''': 1,
												    '''clip_embed_dim''': self.time_input_dim * 2,
												    '''additional_embeddings''': 0,
												    '''time_embed_act_fn''': '''gelu''',
												    '''norm_in_type''': '''layer''',
												    '''encoder_hid_proj_type''': None,
												    '''added_emb_type''': None,
												}

												lowercase							=						PriorTransformer(**A__)
												return model




							@property
							def  A__      (				self):
												torch.manual_seed(0)

												lowercase							=						{
												    '''param_shapes''': (
												        (self.renderer_dim, 9_3),
												        (self.renderer_dim, 8),
												        (self.renderer_dim, 8),
												        (self.renderer_dim, 8),
												    ),
												    '''d_latent''': self.time_input_dim,
												    '''d_hidden''': self.renderer_dim,
												    '''n_output''': 1_2,
												    '''background''': (
												        0.1,
												        0.1,
												        0.1,
												    ),
												}
												lowercase							=						ShapERenderer(**A__)
												return model




							def  A__      (				self):
												lowercase							=						self.dummy_prior
												lowercase							=						self.dummy_text_encoder
												lowercase							=						self.dummy_tokenizer
												lowercase							=						self.dummy_renderer

												lowercase							=						HeunDiscreteScheduler(
												    beta_schedule='''exp'''   ,num_train_timesteps=1_0_2_4   ,prediction_type='''sample'''   ,use_karras_sigmas=A__   ,clip_sample=A__   ,clip_sample_range=1.0   ,)
												lowercase							=						{
												    '''prior''': prior,
												    '''text_encoder''': text_encoder,
												    '''tokenizer''': tokenizer,
												    '''renderer''': renderer,
												    '''scheduler''': scheduler,
												}

												return components




							def  A__      (				self   ,A__   ,A__=0):
												if str(A__).startswith('''mps'''):
																	lowercase							=						torch.manual_seed(A__)
												else:
																	lowercase							=						torch.Generator(device=A__).manual_seed(A__)
												lowercase							=						{
												    '''prompt''': '''horse''',
												    '''generator''': generator,
												    '''num_inference_steps''': 1,
												    '''frame_size''': 3_2,
												    '''output_type''': '''np''',
												}
												return inputs




							def  A__      (				self):
												lowercase							=						'''cpu'''

												lowercase							=						self.get_dummy_components()

												lowercase							=						self.pipeline_class(**A__)
												lowercase							=						pipe.to(A__)

												pipe.set_progress_bar_config(disable=A__)

												lowercase							=						pipe(**self.get_dummy_inputs(A__))
												lowercase							=						output.images[0]
												lowercase							=						image[0, -3:, -3:, -1]

												assert image.shape == (2_0, 3_2, 3_2, 3)

												lowercase							=						np.array(
												    [
												        0.00039216,
												        0.00039216,
												        0.00039216,
												        0.00039216,
												        0.00039216,
												        0.00039216,
												        0.00039216,
												        0.00039216,
												        0.00039216,
												    ])

												assert np.abs(image_slice.flatten() - expected_slice).max() < 1E-2




							def  A__      (				self):
												# NOTE: Larger batch sizes cause this test to timeout, only test on smaller batches
												self._test_inference_batch_consistent(batch_sizes=[1, 2])




							def  A__      (				self):
												lowercase							=						torch_device == '''cpu'''
												lowercase							=						True

												self._test_inference_batch_single_identical(
												    batch_size=2   ,test_max_difference=A__   ,relax_max_difference=A__   ,)





							def  A__      (				self):
												lowercase							=						self.get_dummy_components()
												lowercase							=						self.pipeline_class(**A__)
												lowercase							=						pipe.to(A__)
												pipe.set_progress_bar_config(disable=A__)

												lowercase							=						1
												lowercase							=						2

												lowercase							=						self.get_dummy_inputs(A__)

												for key in inputs.keys():
																	if key in self.batch_params:
																						lowercase							=						batch_size * [inputs[key]]

												lowercase							=						pipe(**A__   ,num_images_per_prompt=A__)[0]

												assert images.shape[0] == batch_size * num_images_per_prompt







@slow
@require_torch_gpu
class 				lowercase		(					unittest.TestCase		):




							def  A__      (				self):
												# clean up the VRAM after each test
												super().tearDown()
												gc.collect()
												torch.cuda.empty_cache()





							def  A__      (				self):
												lowercase							=						load_numpy(
												    '''https://huggingface.co/datasets/hf-internal-testing/diffusers-images/resolve/main'''
												    '''/shap_e/test_shap_e_np_out.npy''')
												lowercase							=						ShapEPipeline.from_pretrained('''openai/shap-e''')
												lowercase							=						pipe.to(A__)
												pipe.set_progress_bar_config(disable=A__)

												lowercase							=						torch.Generator(device=A__).manual_seed(0)

												lowercase							=						pipe(
												    '''a shark'''   ,generator=A__   ,guidance_scale=15.0   ,num_inference_steps=6_4   ,frame_size=6_4   ,output_type='''np'''   ,).images[0]

												assert images.shape == (2_0, 6_4, 6_4, 3)

												assert_mean_pixel_difference(A__   ,A__)




