diff --git a/quickstats/components/extended_minimizer.py b/quickstats/components/extended_minimizer.py index 357ed050e137efd1e22eed3035de3e034d7a97dc..6c0b6d47894c4149071bc98824e23a2619c3e44f 100644 --- a/quickstats/components/extended_minimizer.py +++ b/quickstats/components/extended_minimizer.py @@ -54,7 +54,8 @@ class ExtendedMinimizer(AbstractObject): 'prefit_hesse': 0, 'postfit_hesse': 0, 'minuit2_storage_level': 0, - 'do_prefit': 0, + 'prefit_eps': 0, + 'retry_diff_eps': 0, # cms dedicated configs 'set_zero_point': 1, # change the reference point of the NLL to be zero during minimization # discrete nuisance configs @@ -620,12 +621,12 @@ class ExtendedMinimizer(AbstractObject): else: self.discrete_nuisance.freeze_discrete_params(True) - if self.config['do_prefit']: + if self.config['prefit_eps'] > 0: self.stdout.info('ExtendedMinimizer::minimize("{}") prefit minimization'.format(self.name)) # prefit minimization self.minimizer.setStrategy(0) - self.minimizer.setEps(self.config['eps']*10) - status = self.single_minimize(self.config['minimizer_type'], self.config['minimizer_algo']) + self.minimizer.setEps(self.config['prefit_eps']) + self.robust_minimize(cascade=cascade, is_prefit=True) self.minimizer.setStrategy(self.config['strategy']) self.minimizer.setEps(self.config['eps']) @@ -681,32 +682,54 @@ class ExtendedMinimizer(AbstractObject): self.status = status return status - def robust_minimize(self, cascade:bool=True): + def robust_minimize(self, cascade:bool=True, is_prefit:bool=False): self.stdout.debug('Begin robust minimization.') - strategy = self.config['strategy'] retry = self.config['retry'] minimizer_type = self.config['minimizer_type'] minimizer_algo = self.config['minimizer_algo'] - + + def require_cascade(fit_status:int): + return cascade and (fit_status not in [0, 1]) status = self.single_minimize(minimizer_type, minimizer_algo) # repeat if fit failed or poi(s) at boundary expanded_pois = self.expand_poi_bounds() - def require_cascade(fit_status:int): - return cascade and (fit_status not in [0, 1]) - while ((require_cascade(status) or expanded_pois) and (retry > 0)): - if (not expanded_pois) and (strategy < 2): - strategy += 1 - retry -= 1 - self.stdout.error(f'ExtendedMinimizer::robust_minimize("{self.name}") fit failed with status {status}. ' - f'Retrying with strategy {strategy}') - self.minimizer.setStrategy(strategy) - status = self.single_minimize(minimizer_type, minimizer_algo) - expanded_pois = self.expand_poi_bounds() - - if status not in [0, 1]: - self.stdout.error(f'ExtendedMinimizer::robust_minimize("{self.name}") fit failed with status {status}') - - self.minimizer.setStrategy(self.config['strategy']) + + if self.config['retry_diff_eps']: + eps_init = self.config['prefit_eps'] if is_prefit else self.config['eps'] + eps = eps_init + + while ((require_cascade(status) or expanded_pois) and (retry > 0)): + if (not expanded_pois): + eps *= 10 + retry -= 1 + self.stdout.error(f'ExtendedMinimizer::robust_minimize("{self.name}") fit failed with status {status}. ' + f'Retrying with eps {eps}') + self.minimizer.setEps(eps) + status = self.single_minimize(minimizer_type, minimizer_algo) + expanded_pois = self.expand_poi_bounds() + + if status not in [0, 1]: + self.stdout.error(f'ExtendedMinimizer::robust_minimize("{self.name}") fit failed with status {status}') + + self.minimizer.setEps(eps_init) + + else: + strategy = self.config['strategy'] + + while ((require_cascade(status) or expanded_pois) and (retry > 0)): + if (not expanded_pois) and (strategy < 2): + strategy += 1 + retry -= 1 + self.stdout.error(f'ExtendedMinimizer::robust_minimize("{self.name}") fit failed with status {status}. ' + f'Retrying with strategy {strategy}') + self.minimizer.setStrategy(strategy) + status = self.single_minimize(minimizer_type, minimizer_algo) + expanded_pois = self.expand_poi_bounds() + + if status not in [0, 1]: + self.stdout.error(f'ExtendedMinimizer::robust_minimize("{self.name}") fit failed with status {status}') + + self.minimizer.setStrategy(self.config['strategy']) return status