

'''simple docstring'''







import argparse
import copy
def       UpperCAmelCase__    (      UpperCAmelCase__				)			->			int:
       A_						=      {}

       with open(UpperCAmelCase__				) as f:
              for line in f:
                     if line.split()[0] not in dict_of_neighbours:
                            A_						=      []
                            _list.append([line.split()[1], line.split()[2]]				)
                            A_						=      _list
                     else:
                            dict_of_neighbours[line.split()[0]].append(
                                [line.split()[1], line.split()[2]]				)
                     if line.split()[1] not in dict_of_neighbours:
                            A_						=      []
                            _list.append([line.split()[0], line.split()[2]]				)
                            A_						=      _list
                     else:
                            dict_of_neighbours[line.split()[1]].append(
                                [line.split()[0], line.split()[2]]				)

       return dict_of_neighbours
def       UpperCAmelCase__    (      UpperCAmelCase__,       UpperCAmelCase__				)			->			Tuple:

       with open(UpperCAmelCase__				) as f:
              A_						=      f.read(1				)
       A_						=      start_node

       A_						=      []

       A_						=      start_node

       A_						=      0
       while visiting not in first_solution:
              A_						=      1_00_00
              for k in dict_of_neighbours[visiting]:
                     if int(k[1]				) < int(UpperCAmelCase__				) and k[0] not in first_solution:
                            A_						=      k[1]
                            A_						=      k[0]

              first_solution.append(UpperCAmelCase__				)
              A_						=      distance_of_first_solution + int(UpperCAmelCase__				)
              A_						=      best_node

       first_solution.append(UpperCAmelCase__				)

       A_						=      0
       for k in dict_of_neighbours[first_solution[-2]]:
              if k[0] == start_node:
                     break
              position += 1

       A_						=      (
           distance_of_first_solution
           + int(dict_of_neighbours[first_solution[-2]][position][1]				)
           - 1_00_00
       )
       return first_solution, distance_of_first_solution
def       UpperCAmelCase__    (      UpperCAmelCase__,       UpperCAmelCase__				)			->			Dict:
       A_						=      []

       for n in solution[1:-1]:
              A_						=      solution.index(UpperCAmelCase__				)
              for kn in solution[1:-1]:
                     A_						=      solution.index(UpperCAmelCase__				)
                     if n == kn:
                            continue

                     A_						=      copy.deepcopy(UpperCAmelCase__				)
                     A_						=      kn
                     A_						=      n

                     A_						=      0

                     for k in _tmp[:-1]:
                            A_						=      _tmp[_tmp.index(UpperCAmelCase__				) + 1]
                            for i in dict_of_neighbours[k]:
                                   if i[0] == next_node:
                                          A_						=      distance + int(i[1]				)
                     _tmp.append(UpperCAmelCase__				)

                     if _tmp not in neighborhood_of_solution:
                            neighborhood_of_solution.append(_tmp				)

       A_						=      len(neighborhood_of_solution[0]				) - 1

       neighborhood_of_solution.sort(key=lambda UpperCAmelCase__				: x[index_of_last_item_in_the_list]				)
       return neighborhood_of_solution
def       UpperCAmelCase__    (      UpperCAmelCase__,       UpperCAmelCase__,       UpperCAmelCase__,       UpperCAmelCase__,       UpperCAmelCase__				)			->			Optional[Any]:
       A_						=      1
       A_						=      first_solution
       A_						=      []
       A_						=      distance_of_first_solution
       A_						=      solution

       while count <= iters:
              A_						=      find_neighborhood(UpperCAmelCase__,       UpperCAmelCase__				)
              A_						=      0
              A_						=      neighborhood[index_of_best_solution]
              A_						=      len(UpperCAmelCase__				) - 1

              A_						=      False
              while not found:
                     A_						=      0
                     while i < len(UpperCAmelCase__				):
                            if best_solution[i] != solution[i]:
                                   A_						=      best_solution[i]
                                   A_						=      solution[i]
                                   break
                            A_						=      i + 1

                     if [first_exchange_node, second_exchange_node] not in tabu_list and [
                         second_exchange_node,
                         first_exchange_node,
                     ] not in tabu_list:
                            tabu_list.append([first_exchange_node, second_exchange_node]				)
                            A_						=      True
                            A_						=      best_solution[:-1]
                            A_						=      neighborhood[index_of_best_solution][best_cost_index]
                            if cost < best_cost:
                                   A_						=      cost
                                   A_						=      solution
                     else:
                            A_						=      index_of_best_solution + 1
                            A_						=      neighborhood[index_of_best_solution]

              if len(UpperCAmelCase__				) >= size:
                     tabu_list.pop(0				)

              A_						=      count + 1

       return best_solution_ever, best_cost
def       UpperCAmelCase__    (      UpperCAmelCase__=None				)			->			Dict:
       A_						=      generate_neighbours(args.File				)

       A_					,			A_						=      generate_first_solution(
           args.File,       UpperCAmelCase__				)

       A_					,			A_						=      tabu_search(
           UpperCAmelCase__,       UpperCAmelCase__,       UpperCAmelCase__,       args.Iterations,       args.Size,       )

       print(F'''Best solution: {best_sol}, with total distance: {best_cost}.'''				)


if __name__ == "__main__":
      __lowerCamelCase		       =    argparse.ArgumentParser(description='''Tabu Search''')
      parser.add_argument(
          '''-f''',
          '''--File''',
          type=str,
          help='''Path to the file containing the data''',
          required=True,
      )
      parser.add_argument(
          '''-i''',
          '''--Iterations''',
          type=int,
          help='''How many iterations the algorithm should perform''',
          required=True,
      )
      parser.add_argument(
          '''-s''', '''--Size''', type=int, help='''Size of the tabu list''', required=True
      )

      # Pass the arguments to main method
      main(parser.parse_args())



'''simple docstring'''







import tensorflow as tf

from ...tf_utils import shape_list


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



    def __init__(					self		,				UpperCamelCase__		,				UpperCamelCase__		,				UpperCamelCase__		,				UpperCamelCase__		,				UpperCamelCase__=1		,				UpperCamelCase__=False		,				**UpperCamelCase__       )						->      Union[str, Any]:





           '''simple docstring'''
           super().__init__(**UpperCamelCase__       )

           A_						=      vocab_size
           A_						=      d_embed
           A_						=      d_proj

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

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

           A_						=      []
           A_						=      []



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





           '''simple docstring'''
           if self.n_clusters > 0:
                  A_						=      self.add_weight(
                      shape=(self.n_clusters, self.d_embed)		,				initializer="""zeros"""		,				trainable=UpperCamelCase__		,				name="""cluster_weight"""       )
                  A_						=      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:
                                A_						=      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__       )
                         A_						=      self.add_weight(
                             shape=(self.vocab_size, self.d_embed)		,				initializer="""zeros"""		,				trainable=UpperCamelCase__		,				name=f'''out_layers_._{i}_._weight'''		,				)
                         A_						=      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       )       ):
                         A_					,			A_						=      self.cutoff_ends[i], self.cutoff_ends[i + 1]
                         A_						=      self.d_embed // (self.div_val**i)

                         A_						=      self.add_weight(
                             shape=(d_emb_i, self.d_proj)		,				initializer="""zeros"""		,				trainable=UpperCamelCase__		,				name=f'''out_projs_._{i}'''       )
                         self.out_projs.append(UpperCamelCase__       )
                         A_						=      self.add_weight(
                             shape=(r_idx - l_idx, d_emb_i)		,				initializer="""zeros"""		,				trainable=UpperCamelCase__		,				name=f'''out_layers_._{i}_._weight'''		,				)
                         A_						=      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 					snake_case_			(					UpperCamelCase__		,				UpperCamelCase__		,				UpperCamelCase__		,				UpperCamelCase__=None       )						->      List[Any]:





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



    @staticmethod
    def 					snake_case_			(					UpperCamelCase__		,				UpperCamelCase__       )						->      List[str]:





           '''simple docstring'''
           A_						=      shape_list(UpperCamelCase__       )
           A_						=      tf.range(lp_size[0]		,				dtype=target.dtype       )
           A_						=      tf.stack([r, target]		,				1       )
           return tf.gather_nd(UpperCamelCase__		,				UpperCamelCase__       )







    def 					snake_case_			(					self		,				UpperCamelCase__		,				UpperCamelCase__		,				UpperCamelCase__=True		,				UpperCamelCase__=False       )						->      Optional[int]:





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

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

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

                                A_						=      self._logit(UpperCamelCase__		,				UpperCamelCase__		,				UpperCamelCase__		,				self.out_projs[0]       )
                                A_						=      tf.nn.log_softmax(UpperCamelCase__       )
                                out.append(head_logprob[..., : self.cutoffs[0]]       )
                                if target is not None:
                                       A_						=      tf.boolean_mask(UpperCamelCase__		,				UpperCamelCase__       )
                                       A_						=      self._gather_logprob(UpperCamelCase__		,				UpperCamelCase__       )
                         else:
                                A_						=      self._logit(UpperCamelCase__		,				UpperCamelCase__		,				UpperCamelCase__		,				self.out_projs[i]       )
                                A_						=      tf.nn.log_softmax(UpperCamelCase__       )
                                A_						=      self.cutoffs[0] + i - 1  # No probability for the head cluster
                                A_						=      head_logprob[..., cluster_prob_idx, None] + tail_logprob
                                out.append(UpperCamelCase__       )
                                if target is not None:
                                       A_						=      tf.boolean_mask(UpperCamelCase__		,				UpperCamelCase__       )
                                       A_						=      tf.boolean_mask(UpperCamelCase__		,				UpperCamelCase__       )
                                       A_						=      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__       )       )
                  A_						=      tf.concat(UpperCamelCase__		,				axis=-1       )

           if target is not None:
                  if return_mean:
                         A_						=      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
