MH-P1/src/local_search.py

61 lines
2.1 KiB
Python

from numpy.random import choice, seed
def get_first_random_solution(m, data):
seed(42)
random_indexes = choice(len(data.index), size=m, replace=False)
return data.loc[random_indexes]
def replace_worst_element(previous, data):
solution = previous.copy()
worst_index = solution["distance"].astype(float).idxmin()
random_element = data.sample().squeeze()
while solution.isin(random_element.values.ravel()).any().any():
random_element = data.sample().squeeze()
solution.loc[worst_index] = random_element
return solution, worst_index
def choose_best_solution(previous, current, index):
if previous.loc[index].distance >= current.loc[index].distance:
return previous
return current
def get_random_solution(previous, data):
candidates = []
candidates.append(previous)
solution, worst_index = replace_worst_element(previous, data)
previous_worst_distance = previous["distance"].loc[worst_index]
last_solution = candidates[-1]
while last_solution.distance.loc[worst_index] <= previous_worst_distance:
solution, _ = replace_worst_element(previous=solution, data=data)
if solution.equals(last_solution):
best_solution = choose_best_solution(
previous=previous, current=solution, index=worst_index
)
return best_solution
candidates.append(solution)
last_solution = candidates[-1]
return last_solution
def explore_neighbourhood(element, data, max_iterations=100000):
neighbourhood = []
neighbourhood.append(element)
for i in range(max_iterations):
print(f"Iteration {i}")
previous_solution = neighbourhood[-1]
neighbour = get_random_solution(previous=previous_solution, data=data)
if neighbour.equals(previous_solution):
break
neighbourhood.append(neighbour)
return neighbour
def local_search(m, data):
first_solution = get_first_random_solution(m=m, data=data)
best_solution = explore_neighbourhood(element=first_solution, data=data)
return best_solution