def update_stats_for_method_pair(self, destroy: Method, repair: Method, sol: Solution, res: Result, obj_old: TObj, t_destroy: float, t_repair: float): """Update statistics, incumbent and check termination condition after having performed a destroy+repair.""" if __debug__ and self.own_settings.mh_checkit: sol.check() ms_destroy = self.method_stats[destroy.name] ms_destroy.applications += 1 ms_destroy.netto_time += t_destroy ms_destroy.brutto_time += t_destroy ms_repair = self.method_stats[repair.name] ms_repair.applications += 1 ms_repair.netto_time += t_repair ms_repair.brutto_time += t_repair obj_new = sol.obj() if sol.is_better_obj(sol.obj(), obj_old): ms_destroy.successes += 1 ms_destroy.obj_gain += obj_new - obj_old ms_repair.successes += 1 ms_repair.obj_gain += obj_new - obj_old self.iteration += 1 new_incumbent = self.update_incumbent(sol, time.process_time() - self.time_start) terminate = self.check_termination() self.log_iteration(destroy.name+'+'+repair.name, obj_old, sol, new_incumbent, terminate, res.log_info) if terminate: self.run_time = time.process_time() - self.time_start res.terminate = True
def perform_method(self, method: Method, sol: Solution, delayed_success=False) -> Result: """Perform method on given solution and returns Results object. Also updates incumbent, iteration and the method's statistics in method_stats. Furthermore checks the termination condition and eventually sets terminate in the returned Results object. :param method: method to be performed :param sol: solution to which the method is applied :param delayed_success: if set the success is not immediately determined and updated but at some later call of delayed_success_update() :returns: Results object """ res = Result() obj_old = sol.obj() ##### logging for visualisation if self.step_logger.hasHandlers(): sol_str, inc_str = f'{sol}'.replace( '\n', ' '), f'{self.incumbent}'.replace('\n', ' ') step_info = f'START\nSOL: {sol_str}\nOBJ: {obj_old}\nM: {method.name}\n' + \ f'PAR: {method.par}\nINC: {inc_str}\nBEST: {self.incumbent.obj()}' self.step_logger.info(step_info) ################# t_start = time.process_time() method.func(sol, method.par, res) t_end = time.process_time() if __debug__ and self.own_settings.mh_checkit: sol.check() ms = self.method_stats[method.name] ms.applications += 1 ms.netto_time += t_end - t_start obj_new = sol.obj() if not delayed_success: ms.brutto_time += t_end - t_start if sol.is_better_obj(sol.obj(), obj_old): ms.successes += 1 ms.obj_gain += obj_new - obj_old self.iteration += 1 new_incumbent = self.update_incumbent(sol, t_end - self.time_start) ##### logging for visualisation if self.step_logger.hasHandlers(): sol_str, inc_str = f'{sol}'.replace( '\n', ' '), f'{self.incumbent}'.replace('\n', ' ') step_info = f'END\nSOL: {sol_str}\nOBJ: {sol.obj()}\nM: {method.name}\n' + \ f'PAR: {method.par}\nINC: {inc_str}\nBEST: {self.incumbent.obj()}\nBETTER: {new_incumbent}' self.step_logger.info(step_info) ################# terminate = self.check_termination() self.log_iteration(method.name, obj_old, sol, new_incumbent, terminate, res.log_info) if terminate: self.run_time = time.process_time() - self.time_start res.terminate = True return res
def delayed_success_update(self, method: Method, obj_old: TObj, t_start: float, sol: Solution): """Update an earlier performed method's success information in method_stats. :param method: earlier performed method :param obj_old: objective value of solution with which to compare to determine success :param t_start: time when the application of method had started :param sol: current solution considered the final result of the method """ t_end = time.process_time() ms = self.method_stats[method.name] ms.brutto_time += t_end - t_start obj_new = sol.obj() if sol.is_better_obj(sol.obj(), obj_old): ms.successes += 1 ms.obj_gain += obj_new - obj_old
def perform_method(self, method: Method, sol: Solution, delayed_success=False) -> Result: """Perform method on given solution and returns Results object. Also updates incumbent, iteration and the method's statistics in method_stats. Furthermore checks the termination condition and eventually sets terminate in the returned Results object. :param method: method to be performed :param sol: solution to which the method is applied :param delayed_success: if set the success is not immediately determined and updated but at some later call of delayed_success_update() :returns: Results object """ res = Result() obj_old = sol.obj() t_start = time.process_time() method.func(sol, method.par, res) t_end = time.process_time() if __debug__ and self.own_settings.mh_checkit: sol.check() ms = self.method_stats[method.name] ms.applications += 1 ms.netto_time += t_end - t_start obj_new = sol.obj() if not delayed_success: ms.brutto_time += t_end - t_start if sol.is_better_obj(sol.obj(), obj_old): ms.successes += 1 ms.obj_gain += obj_new - obj_old self.iteration += 1 new_incumbent = self.update_incumbent(sol, t_end - self.time_start) terminate = self.check_termination() self.log_iteration(method.name, obj_old, sol, new_incumbent, terminate, res.log_info) if terminate: self.run_time = time.process_time() - self.time_start res.terminate = True return res