






"""simple docstring"""
import tensorflow as tf

from ...tf_utils import shape_list







class 			UpperCamelCase_       (tf.keras.layers.Layer     ):





	def __init__(      self					: Optional[Any]	,	lowerCAmelCase_					: Tuple	,	lowerCAmelCase_					: Union[str, Any]	,	lowerCAmelCase_					: Any	,	lowerCAmelCase_					: Optional[int]	,	lowerCAmelCase_					: Optional[int]=1	,	lowerCAmelCase_					: str=False	,	**lowerCAmelCase_					: Optional[int]						)						->			str:
				super().__init__(**lowerCAmelCase_						)

				UpperCAmelCase_     : Tuple			     =					vocab_size
				UpperCAmelCase_     : int			     =					d_embed
				UpperCAmelCase_     : List[Any]			     =					d_proj

				UpperCAmelCase_     : Tuple			     =					cutoffs + [vocab_size]
				UpperCAmelCase_     : Any			     =					[0] + self.cutoffs
				UpperCAmelCase_     : List[Any]			     =					div_val

				UpperCAmelCase_     : str			     =					self.cutoffs[0]
				UpperCAmelCase_     : List[str]			     =					len(self.cutoffs						) - 1
				UpperCAmelCase_     : Optional[int]			     =					self.shortlist_size + self.n_clusters
				UpperCAmelCase_     : List[Any]			     =					keep_order

				UpperCAmelCase_     : Any			     =					[]
				UpperCAmelCase_     : Any			     =					[]





	def      _SCREAMING_SNAKE_CASE      (      self					: Union[str, Any]	,	lowerCAmelCase_					: List[str]						)						->			Tuple:
				if self.n_clusters > 0:
							UpperCAmelCase_     : Optional[int]			     =					self.add_weight(
							    shape=(self.n_clusters, self.d_embed)	,	initializer="zeros"	,	trainable=lowerCAmelCase_	,	name="cluster_weight"						)
							UpperCAmelCase_     : int			     =					self.add_weight(
							    shape=(self.n_clusters,)	,	initializer="zeros"	,	trainable=lowerCAmelCase_	,	name="cluster_bias"						)

				if self.div_val == 1:
							for i in range(len(self.cutoffs						)						):
										if self.d_proj != self.d_embed:
													UpperCAmelCase_     : Union[str, Any]			     =					self.add_weight(
													    shape=(self.d_embed, self.d_proj)	,	initializer="zeros"	,	trainable=lowerCAmelCase_	,	name=f"""out_projs_._{i}"""	,	)
													self.out_projs.append(lowerCAmelCase_						)
										else:
													self.out_projs.append(lowerCAmelCase_						)
										UpperCAmelCase_     : Any			     =					self.add_weight(
										    shape=(self.vocab_size, self.d_embed)	,	initializer="zeros"	,	trainable=lowerCAmelCase_	,	name=f"""out_layers_._{i}_._weight"""	,	)
										UpperCAmelCase_     : str			     =					self.add_weight(
										    shape=(self.vocab_size,)	,	initializer="zeros"	,	trainable=lowerCAmelCase_	,	name=f"""out_layers_._{i}_._bias"""	,	)
										self.out_layers.append((weight, bias)						)
				else:
							for i in range(len(self.cutoffs						)						):
										UpperCAmelCase_     ,	UpperCAmelCase_     : Optional[int]			     =					self.cutoff_ends[i], self.cutoff_ends[i + 1]
										UpperCAmelCase_     : Optional[Any]			     =					self.d_embed // (self.div_val**i)

										UpperCAmelCase_     : str			     =					self.add_weight(
										    shape=(d_emb_i, self.d_proj)	,	initializer="zeros"	,	trainable=lowerCAmelCase_	,	name=f"""out_projs_._{i}"""						)
										self.out_projs.append(lowerCAmelCase_						)
										UpperCAmelCase_     : int			     =					self.add_weight(
										    shape=(r_idx - l_idx, d_emb_i)	,	initializer="zeros"	,	trainable=lowerCAmelCase_	,	name=f"""out_layers_._{i}_._weight"""	,	)
										UpperCAmelCase_     : Optional[Any]			     =					self.add_weight(
										    shape=(r_idx - l_idx,)	,	initializer="zeros"	,	trainable=lowerCAmelCase_	,	name=f"""out_layers_._{i}_._bias"""	,	)
										self.out_layers.append((weight, bias)						)
				super().build(lowerCAmelCase_						)





	@staticmethod
	def      _SCREAMING_SNAKE_CASE      (      lowerCAmelCase_					: Optional[Any]	,	lowerCAmelCase_					: Optional[int]	,	lowerCAmelCase_					: Tuple	,	lowerCAmelCase_					: List[Any]=None						)						->			List[Any]:
				UpperCAmelCase_     : List[Any]			     =					x
				if proj is not None:
							UpperCAmelCase_     : List[str]			     =					tf.einsum("ibd,ed->ibe"	,	lowerCAmelCase_	,	lowerCAmelCase_						)
				return tf.einsum("ibd,nd->ibn"	,	lowerCAmelCase_	,	lowerCAmelCase_						) + b





	@staticmethod
	def      _SCREAMING_SNAKE_CASE      (      lowerCAmelCase_					: Optional[int]	,	lowerCAmelCase_					: List[Any]						)						->			List[str]:
				UpperCAmelCase_     : Tuple			     =					shape_list(lowerCAmelCase_						)
				UpperCAmelCase_     : Union[str, Any]			     =					tf.range(lp_size[0]	,	dtype=target.dtype						)
				UpperCAmelCase_     : int			     =					tf.stack([r, target]	,	1						)
				return tf.gather_nd(lowerCAmelCase_	,	lowerCAmelCase_						)





	def      _SCREAMING_SNAKE_CASE      (      self					: Tuple	,	lowerCAmelCase_					: str	,	lowerCAmelCase_					: Dict	,	lowerCAmelCase_					: List[Any]=True	,	lowerCAmelCase_					: Optional[int]=False						)						->			List[Any]:
				UpperCAmelCase_     : str			     =					0
				if self.n_clusters == 0:
							UpperCAmelCase_     : Any			     =					self._logit(lowerCAmelCase_	,	self.out_layers[0][0]	,	self.out_layers[0][1]	,	self.out_projs[0]						)
							if target is not None:
										UpperCAmelCase_     : Union[str, Any]			     =					tf.nn.sparse_softmax_cross_entropy_with_logits(labels=lowerCAmelCase_	,	logits=lowerCAmelCase_						)
							UpperCAmelCase_     : List[str]			     =					tf.nn.log_softmax(lowerCAmelCase_	,	axis=-1						)
				else:
							UpperCAmelCase_     : str			     =					shape_list(lowerCAmelCase_						)
							UpperCAmelCase_     : str			     =					[]
							UpperCAmelCase_     : str			     =					tf.zeros(hidden_sizes[:2]						)
							for i in range(len(self.cutoffs						)						):
										UpperCAmelCase_     ,	UpperCAmelCase_     : str			     =					self.cutoff_ends[i], self.cutoff_ends[i + 1]
										if target is not None:
													UpperCAmelCase_     : List[Any]			     =					(target >= l_idx) & (target < r_idx)
													UpperCAmelCase_     : Dict			     =					tf.where(lowerCAmelCase_						)
													UpperCAmelCase_     : int			     =					tf.boolean_mask(lowerCAmelCase_	,	lowerCAmelCase_						) - l_idx

										if self.div_val == 1:
													UpperCAmelCase_     : Optional[int]			     =					self.out_layers[0][0][l_idx:r_idx]
													UpperCAmelCase_     : Tuple			     =					self.out_layers[0][1][l_idx:r_idx]
										else:
													UpperCAmelCase_     : Any			     =					self.out_layers[i][0]
													UpperCAmelCase_     : Tuple			     =					self.out_layers[i][1]

										if i == 0:
													UpperCAmelCase_     : Tuple			     =					tf.concat([cur_W, self.cluster_weight]	,	0						)
													UpperCAmelCase_     : Tuple			     =					tf.concat([cur_b, self.cluster_bias]	,	0						)

													UpperCAmelCase_     : Tuple			     =					self._logit(lowerCAmelCase_	,	lowerCAmelCase_	,	lowerCAmelCase_	,	self.out_projs[0]						)
													UpperCAmelCase_     : Dict			     =					tf.nn.log_softmax(lowerCAmelCase_						)
													out.append(head_logprob[..., : self.cutoffs[0]]						)
													if target is not None:
																UpperCAmelCase_     : str			     =					tf.boolean_mask(lowerCAmelCase_	,	lowerCAmelCase_						)
																UpperCAmelCase_     : List[str]			     =					self._gather_logprob(lowerCAmelCase_	,	lowerCAmelCase_						)
										else:
													UpperCAmelCase_     : Union[str, Any]			     =					self._logit(lowerCAmelCase_	,	lowerCAmelCase_	,	lowerCAmelCase_	,	self.out_projs[i]						)
													UpperCAmelCase_     : int			     =					tf.nn.log_softmax(lowerCAmelCase_						)
													UpperCAmelCase_     : int			     =					self.cutoffs[0] + i - 1  # No probability for the head cluster
													UpperCAmelCase_     : Optional[int]			     =					head_logprob[..., cluster_prob_idx, None] + tail_logprob
													out.append(lowerCAmelCase_						)
													if target is not None:
																UpperCAmelCase_     : List[Any]			     =					tf.boolean_mask(lowerCAmelCase_	,	lowerCAmelCase_						)
																UpperCAmelCase_     : str			     =					tf.boolean_mask(lowerCAmelCase_	,	lowerCAmelCase_						)
																UpperCAmelCase_     : List[str]			     =					self._gather_logprob(lowerCAmelCase_	,	lowerCAmelCase_						)
																cur_logprob += cur_head_logprob[:, self.cutoff_ends[1] + i - 1]
										if target is not None:
													loss += tf.scatter_nd(lowerCAmelCase_	,	-cur_logprob	,	shape_list(lowerCAmelCase_						)						)
							UpperCAmelCase_     : str			     =					tf.concat(lowerCAmelCase_	,	axis=-1						)

				if target is not None:
							if return_mean:
										UpperCAmelCase_     : Union[str, Any]			     =					tf.reduce_mean(lowerCAmelCase_						)
							# Add the training-time loss value to the layer using `self.add_loss()`.
							self.add_loss(lowerCAmelCase_						)

							# Log the loss as a metric (we could log arbitrary metrics,
							# including different metrics for training and inference.
							self.add_metric(lowerCAmelCase_	,	name=self.name	,	aggregation="mean" if return_mean else ""						)

				return out











"""simple docstring"""
from __future__ import annotations

import time
from collections.abc import Sequence
from random import randint

from matplotlib import pyplot as plt

def 				snake_case      (   A__	,A__	,A__						):
			if not arr:
						return None, None, 0
			if low == high:
						return low, high, arr[low]

			UpperCAmelCase_     : Dict			     =					(low + high) // 2
			UpperCAmelCase_     ,	UpperCAmelCase_     ,	UpperCAmelCase_     : Any			     =					max_subarray(A__	,A__	,A__						)
			UpperCAmelCase_     ,	UpperCAmelCase_     ,	UpperCAmelCase_     : Union[str, Any]			     =					max_subarray(A__	,mid + 1	,A__						)
			UpperCAmelCase_     ,	UpperCAmelCase_     ,	UpperCAmelCase_     : Optional[Any]			     =					max_cross_sum(A__	,A__	,A__	,A__						)
			if left_sum >= right_sum and left_sum >= cross_sum:
						return left_low, left_high, left_sum
			elif right_sum >= left_sum and right_sum >= cross_sum:
						return right_low, right_high, right_sum
			return cross_left, cross_right, cross_sum

def 				snake_case      (   A__	,A__	,A__	,A__						):
			UpperCAmelCase_     ,	UpperCAmelCase_     : str			     =					float("-inf"						), -1
			UpperCAmelCase_     ,	UpperCAmelCase_     : Optional[Any]			     =					float("-inf"						), -1

			UpperCAmelCase_     : int | float			     =					0
			for i in range(A__	,low - 1	,-1						):
						summ += arr[i]
						if summ > left_sum:
									UpperCAmelCase_     : str			     =					summ
									UpperCAmelCase_     : Any			     =					i

			UpperCAmelCase_     : Dict			     =					0
			for i in range(mid + 1	,high + 1						):
						summ += arr[i]
						if summ > right_sum:
									UpperCAmelCase_     : List[Any]			     =					summ
									UpperCAmelCase_     : Optional[Any]			     =					i

			return max_left, max_right, (left_sum + right_sum)

def 				snake_case      (   A__						):
			UpperCAmelCase_     : str			     =					[randint(1	,A__						) for _ in range(A__						)]
			UpperCAmelCase_     : str			     =					time.time()
			max_subarray(A__	,0	,input_size - 1						)
			UpperCAmelCase_     : int			     =					time.time()
			return end - start

def 				snake_case      (   ):
			UpperCAmelCase_     : int			     =					[10, 1_00, 10_00, 1_00_00, 5_00_00, 10_00_00, 20_00_00, 30_00_00, 40_00_00, 50_00_00]
			UpperCAmelCase_     : List[str]			     =					[time_max_subarray(A__						) for input_size in input_sizes]
			print("No of Inputs\t\tTime Taken"						)
			for input_size, runtime in zip(A__	,A__						):
						print(A__	,"\t\t"	,A__						)
			plt.plot(A__	,A__						)
			plt.xlabel("Number of Inputs"						)
			plt.ylabel("Time taken in seconds"						)
			plt.show()


if __name__ == "__main__":
			from doctest import testmod

			testmod()



