



import argparse
import copy



def __lowerCAmelCase	(       SCREAMING_SNAKE_CASE_					):
			lowercase__   					=			{}

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

			return dict_of_neighbours



def __lowerCAmelCase	(       SCREAMING_SNAKE_CASE_  ,					SCREAMING_SNAKE_CASE_					):

			with open(SCREAMING_SNAKE_CASE_					) as f:
						lowercase__   					=			f.read(1					)
			lowercase__   					=			start_node

			lowercase__   					=			[]

			lowercase__   					=			start_node

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

						first_solution.append(SCREAMING_SNAKE_CASE_					)
						lowercase__   					=			distance_of_first_solution + int(SCREAMING_SNAKE_CASE_					)
						lowercase__   					=			best_node

			first_solution.append(SCREAMING_SNAKE_CASE_					)

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

			lowercase__   					=			(
			    distance_of_first_solution
			    + int(dict_of_neighbours[first_solution[-2]][position][1]					)
			    - 1_0000
			)
			return first_solution, distance_of_first_solution



def __lowerCAmelCase	(       SCREAMING_SNAKE_CASE_  ,					SCREAMING_SNAKE_CASE_					):
			lowercase__   					=			[]

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

									lowercase__   					=			copy.deepcopy(SCREAMING_SNAKE_CASE_					)
									lowercase__   					=			kn
									lowercase__   					=			n

									lowercase__   					=			0

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

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

			lowercase__   					=			len(neighborhood_of_solution[0]					) - 1

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



def __lowerCAmelCase	(       SCREAMING_SNAKE_CASE_  ,					SCREAMING_SNAKE_CASE_  ,					SCREAMING_SNAKE_CASE_  ,					SCREAMING_SNAKE_CASE_  ,					SCREAMING_SNAKE_CASE_					):
			lowercase__   					=			1
			lowercase__   					=			first_solution
			lowercase__   					=			[]
			lowercase__   					=			distance_of_first_solution
			lowercase__   					=			solution

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

						lowercase__   					=			False
						while not found:
									lowercase__   					=			0
									while i < len(SCREAMING_SNAKE_CASE_					):
												if best_solution[i] != solution[i]:
															lowercase__   					=			best_solution[i]
															lowercase__   					=			solution[i]
															break
												lowercase__   					=			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]					)
												lowercase__   					=			True
												lowercase__   					=			best_solution[:-1]
												lowercase__   					=			neighborhood[index_of_best_solution][best_cost_index]
												if cost < best_cost:
															lowercase__   					=			cost
															lowercase__   					=			solution
									else:
												lowercase__   					=			index_of_best_solution + 1
												lowercase__   					=			neighborhood[index_of_best_solution]

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

						lowercase__   					=			count + 1

			return best_solution_ever, best_cost



def __lowerCAmelCase	(       SCREAMING_SNAKE_CASE_=None					):
			lowercase__   					=			generate_neighbours(args.File					)

			lowercase__					,    lowercase__   					=			generate_first_solution(
			    args.File  ,					SCREAMING_SNAKE_CASE_					)

			lowercase__					,    lowercase__   					=			tabu_search(
			    SCREAMING_SNAKE_CASE_  ,					SCREAMING_SNAKE_CASE_  ,					SCREAMING_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())









def __lowerCAmelCase	(       SCREAMING_SNAKE_CASE_					):
			lowercase__   					=			int(SCREAMING_SNAKE_CASE_					)
			if decimal in (0, 1):  # Exit cases for the recursion
						return str(SCREAMING_SNAKE_CASE_					)
			lowercase__					,    lowercase__   					=			divmod(SCREAMING_SNAKE_CASE_  ,					2					)
			return binary_recursive(SCREAMING_SNAKE_CASE_					) + str(SCREAMING_SNAKE_CASE_					)



def __lowerCAmelCase	(       SCREAMING_SNAKE_CASE_					):
			lowercase__   					=			str(SCREAMING_SNAKE_CASE_					).strip()
			if not number:
						raise ValueError("No input value was provided"					)
			lowercase__   					=			"-" if number.startswith("-"					) else ""
			lowercase__   					=			number.lstrip("-"					)
			if not number.isnumeric():
						raise ValueError("Input value is not an integer"					)
			return f'''{negative}0b{binary_recursive(int(SCREAMING_SNAKE_CASE_					)					)}'''


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

							testmod()




