






"""simple docstring"""

import argparse
import copy






def _lowerCAmelCase	(  __lowerCamelCase:int   ):

						'''simple docstring'''






						__magic_name__     :   int            =     {}

						with open(__lowerCamelCase   ) as f:
												for line in f:
																		if line.split()[0] not in dict_of_neighbours:
																								__magic_name__     :   Dict            =     []
																								_list.append([line.split()[1], line.split()[2]]   )
																								__magic_name__     :   Optional[int]            =     _list
																		else:
																								dict_of_neighbours[line.split()[0]].append(
																								    [line.split()[1], line.split()[2]]   )
																		if line.split()[1] not in dict_of_neighbours:
																								__magic_name__     :   List[str]            =     []
																								_list.append([line.split()[0], line.split()[2]]   )
																								__magic_name__     :   str            =     _list
																		else:
																								dict_of_neighbours[line.split()[1]].append(
																								    [line.split()[0], line.split()[2]]   )

						return dict_of_neighbours






def _lowerCAmelCase	(  __lowerCamelCase:Any ,						__lowerCamelCase:Optional[int]   ):

						'''simple docstring'''






						with open(__lowerCamelCase   ) as f:
												__magic_name__     :   Dict            =     f.read(1   )
						__magic_name__     :   str            =     start_node

						__magic_name__     :   str            =     []

						__magic_name__     :   Optional[int]            =     start_node

						__magic_name__     :   int            =     0
						while visiting not in first_solution:
												__magic_name__     :   Optional[int]            =     1_0_0_0_0
												for k in dict_of_neighbours[visiting]:
																		if int(k[1]   ) < int(__lowerCamelCase   ) and k[0] not in first_solution:
																								__magic_name__     :   Dict            =     k[1]
																								__magic_name__     :   List[Any]            =     k[0]

												first_solution.append(__lowerCamelCase   )
												__magic_name__     :   Tuple            =     distance_of_first_solution + int(__lowerCamelCase   )
												__magic_name__     :   str            =     best_node

						first_solution.append(__lowerCamelCase   )

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

						__magic_name__     :   List[str]            =     (
						    distance_of_first_solution
						    + int(dict_of_neighbours[first_solution[-2]][position][1]   )
						    - 1_0_0_0_0
						)
						return first_solution, distance_of_first_solution






def _lowerCAmelCase	(  __lowerCamelCase:Any ,						__lowerCamelCase:Tuple   ):

						'''simple docstring'''






						__magic_name__     :   Union[str, Any]            =     []

						for n in solution[1:-1]:
												__magic_name__     :   Optional[int]            =     solution.index(__lowerCamelCase   )
												for kn in solution[1:-1]:
																		__magic_name__     :   Optional[Any]            =     solution.index(__lowerCamelCase   )
																		if n == kn:
																								continue

																		__magic_name__     :   Tuple            =     copy.deepcopy(__lowerCamelCase   )
																		__magic_name__     :   List[str]            =     kn
																		__magic_name__     :   Dict            =     n

																		__magic_name__     :   Dict            =     0

																		for k in _tmp[:-1]:
																								__magic_name__     :   List[str]            =     _tmp[_tmp.index(__lowerCamelCase   ) + 1]
																								for i in dict_of_neighbours[k]:
																														if i[0] == next_node:
																																				__magic_name__     :   Any            =     distance + int(i[1]   )
																		_tmp.append(__lowerCamelCase   )

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

						__magic_name__     :   Tuple            =     len(neighborhood_of_solution[0]   ) - 1

						neighborhood_of_solution.sort(key=lambda __lowerCamelCase   : x[index_of_last_item_in_the_list]   )
						return neighborhood_of_solution






def _lowerCAmelCase	(  __lowerCamelCase:Union[str, Any] ,						__lowerCamelCase:List[str] ,						__lowerCamelCase:List[Any] ,						__lowerCamelCase:Any ,						__lowerCamelCase:int   ):

						'''simple docstring'''






						__magic_name__     :   Tuple            =     1
						__magic_name__     :   Any            =     first_solution
						__magic_name__     :   Optional[Any]            =     []
						__magic_name__     :   Any            =     distance_of_first_solution
						__magic_name__     :   Optional[Any]            =     solution

						while count <= iters:
												__magic_name__     :   List[str]            =     find_neighborhood(__lowerCamelCase ,						__lowerCamelCase   )
												__magic_name__     :   Optional[int]            =     0
												__magic_name__     :   List[Any]            =     neighborhood[index_of_best_solution]
												__magic_name__     :   str            =     len(__lowerCamelCase   ) - 1

												__magic_name__     :   Optional[int]            =     False
												while not found:
																		__magic_name__     :   Optional[int]            =     0
																		while i < len(__lowerCamelCase   ):
																								if best_solution[i] != solution[i]:
																														__magic_name__     :   List[str]            =     best_solution[i]
																														__magic_name__     :   List[str]            =     solution[i]
																														break
																								__magic_name__     :   str            =     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]   )
																								__magic_name__     :   Union[str, Any]            =     True
																								__magic_name__     :   Dict            =     best_solution[:-1]
																								__magic_name__     :   List[Any]            =     neighborhood[index_of_best_solution][best_cost_index]
																								if cost < best_cost:
																														__magic_name__     :   List[str]            =     cost
																														__magic_name__     :   Optional[int]            =     solution
																		else:
																								__magic_name__     :   Any            =     index_of_best_solution + 1
																								__magic_name__     :   str            =     neighborhood[index_of_best_solution]

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

												__magic_name__     :   str            =     count + 1

						return best_solution_ever, best_cost






def _lowerCAmelCase	(  __lowerCamelCase:Optional[Any]=None   ):

						'''simple docstring'''






						__magic_name__     :   int            =     generate_neighbours(args.File   )

						__magic_name__      ,    __magic_name__     :   Any            =     generate_first_solution(
						    args.File ,						__lowerCamelCase   )

						__magic_name__      ,    __magic_name__     :   str            =     tabu_search(
						    __lowerCamelCase ,						__lowerCamelCase ,						__lowerCamelCase ,						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())











"""simple docstring"""

def _lowerCAmelCase	(  __lowerCamelCase:int   ):

						'''simple docstring'''






						__magic_name__            =     n ** (1 / 3)
						return (val * val * val) == n


if __name__ == "__main__":
			print(perfect_cube(27))
			print(perfect_cube(4))



