
"""simple docstring"""


import tensorflow as tf

from ...tf_utils import shape_list



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






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







              """simple docstring"""
              super().__init__(**UpperCAmelCase_      )

              UpperCamelCase       			=		vocab_size
              UpperCamelCase       			=		d_embed
              UpperCamelCase       			=		d_proj

              UpperCamelCase       			=		cutoffs + [vocab_size]
              UpperCamelCase       			=		[0] + self.cutoffs
              UpperCamelCase       			=		div_val

              UpperCamelCase       			=		self.cutoffs[0]
              UpperCamelCase       			=		len(self.cutoffs      ) - 1
              UpperCamelCase       			=		self.shortlist_size + self.n_clusters
              UpperCamelCase       			=		keep_order

              UpperCamelCase       			=		[]
              UpperCamelCase       			=		[]






       def 						_SCREAMING_SNAKE_CASE							(	self			:				List[Any]							,   UpperCAmelCase_			:				List[Any]      )->	Optional[int]:







              """simple docstring"""
              if self.n_clusters > 0:
                     UpperCamelCase       			=		self.add_weight(
                         shape=(self.n_clusters, self.d_embed)							,   initializer="zeros"							,   trainable=UpperCAmelCase_							,   name="cluster_weight"      )
                     UpperCamelCase       			=		self.add_weight(
                         shape=(self.n_clusters,)							,   initializer="zeros"							,   trainable=UpperCAmelCase_							,   name="cluster_bias"      )

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

                            UpperCamelCase       			=		self.add_weight(
                                shape=(d_emb_i, self.d_proj)							,   initializer="zeros"							,   trainable=UpperCAmelCase_							,   name=f"out_projs_._{i}"      )
                            self.out_projs.append(UpperCAmelCase_      )
                            UpperCamelCase       			=		self.add_weight(
                                shape=(r_idx - l_idx, d_emb_i)							,   initializer="zeros"							,   trainable=UpperCAmelCase_							,   name=f"out_layers_._{i}_._weight"							,   )
                            UpperCamelCase       			=		self.add_weight(
                                shape=(r_idx - l_idx,)							,   initializer="zeros"							,   trainable=UpperCAmelCase_							,   name=f"out_layers_._{i}_._bias"							,   )
                            self.out_layers.append((weight, bias)      )
              super().build(UpperCAmelCase_      )






       @staticmethod
       def 						_SCREAMING_SNAKE_CASE							(	UpperCAmelCase_			:				List[Any]							,   UpperCAmelCase_			:				Optional[Any]							,   UpperCAmelCase_			:				Optional[int]							,   UpperCAmelCase_			:				Union[str, Any]=None      )->	Union[str, Any]:







              """simple docstring"""
              UpperCamelCase       			=		x
              if proj is not None:
                     UpperCamelCase       			=		tf.einsum("ibd,ed->ibe"							,   UpperCAmelCase_							,   UpperCAmelCase_      )
              return tf.einsum("ibd,nd->ibn"							,   UpperCAmelCase_							,   UpperCAmelCase_      ) + b






       @staticmethod
       def 						_SCREAMING_SNAKE_CASE							(	UpperCAmelCase_			:				int							,   UpperCAmelCase_			:				List[str]      )->	Union[str, Any]:







              """simple docstring"""
              UpperCamelCase       			=		shape_list(UpperCAmelCase_      )
              UpperCamelCase       			=		tf.range(lp_size[0]							,   dtype=target.dtype      )
              UpperCamelCase       			=		tf.stack([r, target]							,   1      )
              return tf.gather_nd(UpperCAmelCase_							,   UpperCAmelCase_      )






       def 						_SCREAMING_SNAKE_CASE							(	self			:				List[Any]							,   UpperCAmelCase_			:				str							,   UpperCAmelCase_			:				List[str]							,   UpperCAmelCase_			:				Union[str, Any]=True							,   UpperCAmelCase_			:				List[str]=False      )->	Dict:







              """simple docstring"""
              UpperCamelCase       			=		0
              if self.n_clusters == 0:
                     UpperCamelCase       			=		self._logit(UpperCAmelCase_							,   self.out_layers[0][0]							,   self.out_layers[0][1]							,   self.out_projs[0]      )
                     if target is not None:
                            UpperCamelCase       			=		tf.nn.sparse_softmax_cross_entropy_with_logits(labels=UpperCAmelCase_							,   logits=UpperCAmelCase_      )
                     UpperCamelCase       			=		tf.nn.log_softmax(UpperCAmelCase_							,   axis=-1      )
              else:
                     UpperCamelCase       			=		shape_list(UpperCAmelCase_      )
                     UpperCamelCase       			=		[]
                     UpperCamelCase       			=		tf.zeros(hidden_sizes[:2]      )
                     for i in range(len(self.cutoffs      )      ):
                            UpperCamelCase			,							UpperCamelCase       			=		self.cutoff_ends[i], self.cutoff_ends[i + 1]
                            if target is not None:
                                   UpperCamelCase       			=		(target >= l_idx) & (target < r_idx)
                                   UpperCamelCase       			=		tf.where(UpperCAmelCase_      )
                                   UpperCamelCase       			=		tf.boolean_mask(UpperCAmelCase_							,   UpperCAmelCase_      ) - l_idx

                            if self.div_val == 1:
                                   UpperCamelCase       			=		self.out_layers[0][0][l_idx:r_idx]
                                   UpperCamelCase       			=		self.out_layers[0][1][l_idx:r_idx]
                            else:
                                   UpperCamelCase       			=		self.out_layers[i][0]
                                   UpperCamelCase       			=		self.out_layers[i][1]

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

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

              if target is not None:
                     if return_mean:
                            UpperCamelCase       			=		tf.reduce_mean(UpperCAmelCase_      )
                     # Add the training-time loss value to the layer using `self.add_loss()`.
                     self.add_loss(UpperCAmelCase_      )

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

              return out







"""simple docstring"""


class 	__a	:






       def __init__(	self			:				Any							,   UpperCAmelCase_			:				List[str]							,   UpperCAmelCase_			:				Optional[Any]							,   UpperCAmelCase_			:				Optional[Any]      )->	Optional[int]:







              """simple docstring"""
              UpperCamelCase       			=		name
              UpperCamelCase       			=		value
              UpperCamelCase       			=		weight






       def __repr__(	self			:				int      )->	Any:







              """simple docstring"""
              return f"{self.__class__.__name__}({self.name}, {self.value}, {self.weight})"






       def 						_SCREAMING_SNAKE_CASE							(	self			:				int      )->	Union[str, Any]:







              """simple docstring"""
              return self.value






       def 						_SCREAMING_SNAKE_CASE							(	self			:				Optional[int]      )->	int:







              """simple docstring"""
              return self.name






       def 						_SCREAMING_SNAKE_CASE							(	self			:				Tuple      )->	List[Any]:







              """simple docstring"""
              return self.weight






       def 						_SCREAMING_SNAKE_CASE							(	self			:				Any      )->	Union[str, Any]:







              """simple docstring"""
              return self.value / self.weight





def 						lowerCamelCase__      (				UpperCAmelCase_		,   UpperCAmelCase_		,   UpperCAmelCase_					)->				Union[str, Any]:







       """simple docstring"""
       UpperCamelCase       			=		[]
       for i in range(len(UpperCAmelCase_					)					):
              menu.append(Things(name[i]		,   value[i]		,   weight[i]					)					)
       return menu



def 						lowerCamelCase__      (				UpperCAmelCase_		,   UpperCAmelCase_		,   UpperCAmelCase_					)->				Dict:







       """simple docstring"""
       UpperCamelCase       			=		sorted(UpperCAmelCase_		,   key=UpperCAmelCase_		,   reverse=UpperCAmelCase_					)
       UpperCamelCase       			=		[]
       UpperCamelCase			,							UpperCamelCase       			=		0.0, 0.0
       for i in range(len(UpperCAmelCase_					)					):
              if (total_cost + items_copy[i].get_weight()) <= max_cost:
                     result.append(items_copy[i]					)
                     total_cost += items_copy[i].get_weight()
                     total_value += items_copy[i].get_value()
       return (result, total_value)



def 						lowerCamelCase__      (				)->				Dict:







       """simple docstring"""


if __name__ == "__main__":
      import doctest

      doctest.testmod()





