
"""simple docstring"""


import argparse
import copy






def 					_snake_case (						snake_case__      :   Dict   ):
	A        =      {}

	with open(snake_case__   ) 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 					_snake_case (						snake_case__      :   List[Any]		,					snake_case__      :   List[Any]   ):

	with open(snake_case__   ) as f:
		A        =      f.read(1   )
	A        =      start_node

	A        =      []

	A        =      start_node

	A        =      0
	while visiting not in first_solution:
		A        =      1_0000
		for k in dict_of_neighbours[visiting]:
			if int(k[1]   ) < int(snake_case__   ) and k[0] not in first_solution:
				A        =      k[1]
				A        =      k[0]

		first_solution.append(snake_case__   )
		A        =      distance_of_first_solution + int(snake_case__   )
		A        =      best_node

	first_solution.append(snake_case__   )

	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_0000
	)
	return first_solution, distance_of_first_solution






def 					_snake_case (						snake_case__      :   Optional[Any]		,					snake_case__      :   Tuple   ):
	A        =      []

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

			A        =      copy.deepcopy(snake_case__   )
			A        =      kn
			A        =      n

			A        =      0

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

			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 snake_case__   : x[index_of_last_item_in_the_list]   )
	return neighborhood_of_solution






def 					_snake_case (						snake_case__      :   str		,					snake_case__      :   Any		,					snake_case__      :   Any		,					snake_case__      :   Dict		,					snake_case__      :   List[str]   ):
	A        =      1
	A        =      first_solution
	A        =      []
	A        =      distance_of_first_solution
	A        =      solution

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

		A        =      False
		while not found:
			A        =      0
			while i < len(snake_case__   ):
				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(snake_case__   ) >= size:
			tabu_list.pop(0   )

		A        =      count + 1

	return best_solution_ever, best_cost






def 					_snake_case (						snake_case__      :   Tuple=None   ):
	A        =      generate_neighbours(args.File   )

	A      ,					A        =      generate_first_solution(
	    args.File		,					snake_case__   )

	A      ,					A        =      tabu_search(
	    snake_case__		,					snake_case__		,					snake_case__		,					args.Iterations		,					args.Size		,					)

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


if __name__ == "__main__":
		_lowercase							      = 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())



class 			_lowercase :


       """simple docstring"""




       def __init__(   self							:			List[Any]					,      __lowerCamelCase							:			int       ):


             '''simple docstring'''



             lowerCamelCase__		:				Optional[Any]    =  size
             lowerCamelCase__		:				List[str]    =  [0] * size
             lowerCamelCase__		:				str    =  [0] * size





       @staticmethod
       def 						lowerCAmelCase     (   __lowerCamelCase							:			int       ):


             '''simple docstring'''



             return index | (index + 1)





       @staticmethod
       def 						lowerCAmelCase     (   __lowerCamelCase							:			int       ):


             '''simple docstring'''



             return (index & (index + 1)) - 1





       def 						lowerCAmelCase     (   self							:			int					,      __lowerCamelCase							:			int					,      __lowerCamelCase							:			int       ):


             '''simple docstring'''



             lowerCamelCase__		:				Union[str, Any]    =  value
             while index < self.size:
                   lowerCamelCase__		:				Tuple    =  self.get_prev(__lowerCamelCase       ) + 1
                   if current_left_border == index:
                         lowerCamelCase__		:				Optional[Any]    =  value
                   else:
                         lowerCamelCase__		:				str    =  max(__lowerCamelCase					,      __lowerCamelCase					,      __lowerCamelCase       )
                   lowerCamelCase__		:				Dict    =  self.get_next(__lowerCamelCase       )





       def 						lowerCAmelCase     (   self							:			List[Any]					,      __lowerCamelCase							:			int					,      __lowerCamelCase							:			int       ):


             '''simple docstring'''



             right -= 1  # Because of right is exclusive
             lowerCamelCase__		:				str    =  0
             while left <= right:
                   lowerCamelCase__		:				Optional[Any]    =  self.get_prev(__lowerCamelCase       )
                   if left <= current_left:
                         lowerCamelCase__		:				Optional[Any]    =  max(__lowerCamelCase					,      self.tree[right]       )
                         lowerCamelCase__		:				Any    =  current_left
                   else:
                         lowerCamelCase__		:				Optional[Any]    =  max(__lowerCamelCase					,      self.arr[right]       )
                         right -= 1
             return result


if __name__ == "__main__":
    import doctest

    doctest.testmod()


