





'''simple docstring'''







import argparse
import copy






def  _lowerCamelCase				( lowercase						:      Dict						)	->	Optional[Any]:
				_a								= {}

				with open(lowercase						) 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  _lowerCamelCase				( lowercase						:      str    ,							lowercase						:      List[Any]						)	->	List[str]:

				with open(lowercase						) 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(lowercase						) and k[0] not in first_solution:
																_a								= k[1]
																_a								= k[0]

								first_solution.append(lowercase						)
								_a								= distance_of_first_solution + int(lowercase						)
								_a								= best_node

				first_solution.append(lowercase						)

				_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  _lowerCamelCase				( lowercase						:      Optional[int]    ,							lowercase						:      Optional[int]						)	->	Any:
				_a								= []

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

												_a								= copy.deepcopy(lowercase						)
												_a								= kn
												_a								= n

												_a								= 0

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

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






def  _lowerCamelCase				( lowercase						:      Union[str, Any]    ,							lowercase						:      Optional[Any]    ,							lowercase						:      str    ,							lowercase						:      List[Any]    ,							lowercase						:      int						)	->	Dict:
				_a								= 1
				_a								= first_solution
				_a								= []
				_a								= distance_of_first_solution
				_a								= solution

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

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

								_a								= count + 1

				return best_solution_ever, best_cost






def  _lowerCamelCase				( lowercase						:      Tuple=None						)	->	Tuple:
				_a								= generate_neighbours(args.File						)

				_a	,					_a								= generate_first_solution(
				    args.File    ,							lowercase						)

				_a	,					_a								= tabu_search(
				    lowercase    ,							lowercase    ,							lowercase    ,							args.Iterations    ,							args.Size    ,							)

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


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







'''simple docstring'''







def  _lowerCamelCase				( lowercase						:      bytes						)	->	str:
				return "".join([hex(lowercase						)[2:].zfill(2						).upper() for byte in list(lowercase						)]						)






def  _lowerCamelCase				( lowercase						:      str						)	->	bytes:
				# Check data validity, following RFC3548
				# https://www.ietf.org/rfc/rfc3548.txt
				if (len(lowercase						) % 2) != 0:
								raise ValueError(
								    "Base16 encoded data is invalid:\nData does not have an even number of hex digits."						)
				# Check the character set - the standard base16 alphabet
				# is uppercase according to RFC3548 section 6
				if not set(lowercase						) <= set("0123456789ABCDEF"						):
								raise ValueError(
								    "Base16 encoded data is invalid:\nData is not uppercase hex or it contains invalid characters."						)
				# For every two hexadecimal digits (= a byte), turn it into an integer.
				# Then, string the result together into bytes, and return it.
				return bytes(int(data[i] + data[i + 1]    ,							16						) for i in range(0    ,							len(lowercase						)    ,							2						)						)


if __name__ == "__main__":
					import doctest

					doctest.testmod()
