def gvns(self, sol: Solution): """Perform general variable neighborhood search (GVNS) to given solution.""" sol2 = sol.copy() if self.vnd(sol2) or not self.meths_sh: return use_vnd = bool(self.meths_li) while True: for m in self.next_method(self.meths_sh, repeat=True): t_start = time.process_time() res = self.perform_method(m, sol2, delayed_success=use_vnd) terminate = res.terminate if not terminate and use_vnd: terminate = self.vnd(sol2) self.delayed_success_update(m, sol.obj(), t_start, sol2) if sol2.is_better(sol): sol.copy_from(sol2) if terminate or res.terminate: return break else: if terminate or res.terminate: return sol2.copy_from(sol) else: break
def copy_from(self, other: 'SubsetVectorSolution'): self.sel = other.sel if self.unselected_elems_in_x(): super().copy_from(other) else: self.x[:self.sel] = other.x[:self.sel] Solution.copy_from(self, other)
def update_after_destroy_and_repair_performed(self, destroy: Method, repair: Method, sol_new: Solution, sol_incumbent: Solution, sol: Solution): """Update current solution, incumbent, and all operator score data according to performed destroy+repair. :param destroy: applied destroy method :param repair: applied repair method :param sol_new: obtained new solution :param sol_incumbent: current incumbent solution :param sol: current (last accepted) solution """ destroy_data = self.score_data[destroy.name] repair_data = self.score_data[repair.name] destroy_data.applied += 1 repair_data.applied += 1 score = 0 if sol_new.is_better(sol_incumbent): score = self.own_settings.mh_alns_sigma1 # print('better than incumbent') sol_incumbent.copy_from(sol_new) sol.copy_from(sol_new) elif sol_new.is_better(sol): score = self.own_settings.mh_alns_sigma2 # print('better than current') sol.copy_from(sol_new) elif sol.is_better(sol_new) and self.metropolis_criterion(sol_new, sol): score = self.own_settings.mh_alns_sigma3 # print('accepted although worse') sol.copy_from(sol_new) elif sol_new != sol: sol_new.copy_from(sol) destroy_data.score += score repair_data.score += score
def alns(self, sol: Solution): """Perform adaptive large neighborhood search (ALNS) on given solution.""" self.next_segment = self.iteration + self.own_settings.mh_alns_segment_size sol_incumbent = sol.copy() sol_new = sol.copy() while True: destroy, repair = self.select_method_pair() res = self.perform_method_pair(destroy, repair, sol_new) self.update_after_destroy_and_repair_performed( destroy, repair, sol_new, sol_incumbent, sol) if res.terminate: sol.copy_from(sol_incumbent) return self.update_operator_weights()
def vnd(self, sol: Solution) -> bool: """Perform variable neighborhood descent (VND) on given solution. :returns: true if a global termination condition is fulfilled, else False. """ sol2 = sol.copy() while True: for m in self.next_method(self.meths_li): res = self.perform_method(m, sol2) if sol2.is_better(sol): sol.copy_from(sol2) if res.terminate: return True break if res.terminate: return True if res.changed: sol2.copy_from(sol) else: # local optimum reached return False
def alns(self, sol: Solution): """Perform adaptive large neighborhood search (ALNS) on given solution.""" self.next_segment = self.iteration + self.own_settings.mh_alns_segment_size sol_incumbent = sol.copy() sol_new = sol.copy() operators = self.operators_generator(sol_new) worker_seed = 0 if settings.mh_workers > 1 else settings.seed with mp.Pool(processes=settings.mh_workers, initializer=self.process_init, initargs=(settings, worker_seed)) as worker_pool: result_iter = worker_pool.imap_unordered( self.perform_method_pair_in_worker, operators) for result in result_iter: # print("Result:", result) destroy, repair, sol_result, res, obj_old, t_destroy, t_repair = result sol_new.copy_from(sol_result) self.update_stats_for_method_pair(destroy, repair, sol, res, obj_old, t_destroy, t_repair) self.update_after_destroy_and_repair_performed( destroy, repair, sol_new, sol_incumbent, sol) if res.terminate: sol.copy_from(sol_incumbent) return self.update_operator_weights()