def simulated_annealing(hyper_params : HyperParams, clusters : clt.Clusters) -> (float, float): current_temp : float = hyper_params.init_temp init_time : float = time.time() elapsed_time : float = time.time() clusters.initialize_state() smallest : float = clusters.sse while current_temp > hyper_params.final_temp: iterations : int = 0 while iterations < hyper_params.num_iter: # Disturbing the state: clusters.disturb() # Comparing the costs of the current state and the disturbed state: delta : float = clusters.disturbed_sse - clusters.sse if delta < 0 or random.random() < math.exp(-delta / current_temp): if clusters.disturbed_sse < smallest: smallest = clusters.disturbed_sse clusters.accept_disturbed() iterations += 1 elapsed_time = time.time() if elapsed_time - init_time >= 1: break # Updating the temperature: current_temp *= hyper_params.alpha elapsed_time = time.time() if elapsed_time - init_time >= 1: break return (smallest, elapsed_time - init_time)
def local_search(clusters : clt.Clusters, current_value : float) -> float: clusters.disturb() if (clusters.disturbed_sse <= current_value): return local_search(clusters, clusters.disturbed_sse) else: return current_value