



import argparse
import copy






def 			lowerCAmelCase__	(					lowerCamelCase_	:	List[Any]):





				'''simple docstring'''

				lowerCAmelCase__  :       List[Any]				=  {}

				with open(__UpperCamelCase) as f:
								for line in f:
												if line.split()[0] not in dict_of_neighbours:
																lowerCAmelCase__  :       Dict				=  []
																_list.append([line.split()[1], line.split()[2]])
																lowerCAmelCase__  :       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:
																lowerCAmelCase__  :       Optional[Any]				=  []
																_list.append([line.split()[0], line.split()[2]])
																lowerCAmelCase__  :       Optional[Any]				=  _list
												else:
																dict_of_neighbours[line.split()[1]].append(
																    [line.split()[0], line.split()[2]])

				return dict_of_neighbours






def 			lowerCAmelCase__	(					lowerCamelCase_	:	str ,lowerCamelCase_	:	Dict):





				'''simple docstring'''

				with open(__UpperCamelCase) as f:
								lowerCAmelCase__  :       str				=  f.read(1)
				lowerCAmelCase__  :       Any				=  start_node

				lowerCAmelCase__  :       Dict				=  []

				lowerCAmelCase__  :       Union[str, Any]				=  start_node

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

								first_solution.append(__UpperCamelCase)
								lowerCAmelCase__  :       List[Any]				=  distance_of_first_solution + int(__UpperCamelCase)
								lowerCAmelCase__  :       Dict				=  best_node

				first_solution.append(__UpperCamelCase)

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

				lowerCAmelCase__  :       int				=  (
				    distance_of_first_solution
				    + int(dict_of_neighbours[first_solution[-2]][position][1])
				    - 10000
				)
				return first_solution, distance_of_first_solution






def 			lowerCAmelCase__	(					lowerCamelCase_	:	int ,lowerCamelCase_	:	str):





				'''simple docstring'''

				lowerCAmelCase__  :       List[Any]				=  []

				for n in solution[1:-1]:
								lowerCAmelCase__  :       Optional[int]				=  solution.index(__UpperCamelCase)
								for kn in solution[1:-1]:
												lowerCAmelCase__  :       Tuple				=  solution.index(__UpperCamelCase)
												if n == kn:
																continue

												lowerCAmelCase__  :       List[Any]				=  copy.deepcopy(__UpperCamelCase)
												lowerCAmelCase__  :       Union[str, Any]				=  kn
												lowerCAmelCase__  :       Dict				=  n

												lowerCAmelCase__  :       List[str]				=  0

												for k in _tmp[:-1]:
																lowerCAmelCase__  :       Any				=  _tmp[_tmp.index(__UpperCamelCase) + 1]
																for i in dict_of_neighbours[k]:
																				if i[0] == next_node:
																								lowerCAmelCase__  :       Dict				=  distance + int(i[1])
												_tmp.append(__UpperCamelCase)

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

				lowerCAmelCase__  :       Optional[int]				=  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_	:	Tuple ,lowerCamelCase_	:	int ,lowerCamelCase_	:	List[Any] ,lowerCamelCase_	:	List[str] ,lowerCamelCase_	:	List[Any]):





				'''simple docstring'''

				lowerCAmelCase__  :       List[Any]				=  1
				lowerCAmelCase__  :       int				=  first_solution
				lowerCAmelCase__  :       Tuple				=  []
				lowerCAmelCase__  :       Tuple				=  distance_of_first_solution
				lowerCAmelCase__  :       Dict				=  solution

				while count <= iters:
								lowerCAmelCase__  :       Dict				=  find_neighborhood(__UpperCamelCase ,__UpperCamelCase)
								lowerCAmelCase__  :       Dict				=  0
								lowerCAmelCase__  :       int				=  neighborhood[index_of_best_solution]
								lowerCAmelCase__  :       int				=  len(__UpperCamelCase) - 1

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

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

								lowerCAmelCase__  :       Optional[Any]				=  count + 1

				return best_solution_ever, best_cost






def 			lowerCAmelCase__	(					lowerCamelCase_	:	List[str]=None):





				'''simple docstring'''

				lowerCAmelCase__  :       str				=  generate_neighbours(args.File)

				lowerCAmelCase__  :       str				=  generate_first_solution(
				    args.File ,__UpperCamelCase)

				lowerCAmelCase__  :       Tuple				=  tabu_search(
				    __UpperCamelCase ,__UpperCamelCase ,__UpperCamelCase ,args.Iterations ,args.Size ,)

				print(f"""Best solution: {best_sol}, with total distance: {best_cost}.""")


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




from collections.abc import Callable

import numpy as np






def 			lowerCAmelCase__	(					lowerCamelCase_	:	Callable ,lowerCamelCase_	:	float ,lowerCamelCase_	:	float ,lowerCamelCase_	:	float ,lowerCamelCase_	:	float):





				'''simple docstring'''

				lowerCAmelCase__  :       Dict				=  int(np.ceil((x_end - xa) / step_size))
				lowerCAmelCase__  :       Any				=  np.zeros((n + 1,))
				lowerCAmelCase__  :       Union[str, Any]				=  ya
				lowerCAmelCase__  :       str				=  xa

				for k in range(lowerCamelCase_):
								lowerCAmelCase__  :       Tuple				=  y[k] + step_size * ode_func(lowerCamelCase_ ,y[k])
								lowerCAmelCase__  :       str				=  y[k] + (
								    (step_size / 2) * (ode_func(lowerCamelCase_ ,y[k]) + ode_func(x + step_size ,lowerCamelCase_))
								)
								x += step_size

				return y


if __name__ == "__main__":
							import doctest

							doctest.testmod()

