def _minimize(self, compute_covar=True): # Minimize with MIGRAD success = self.minimizer.Minimize() if not success: # Get status status = self.minimizer.Status() if status in _status_translation: msg = "MIGRAD did not converge. Reason: %s (status: %i)" % ( _status_translation[status], status) else: msg = "MIGRAD failed with status %i " \ "(see https://root.cern.ch/root/html/ROOT__Minuit2__Minuit2Minimizer.html)" % status raise FitFailed(msg) # Gather results minimum = self.minimizer.MinValue() best_fit_values = np.array( map(lambda x: x[0], zip(self.minimizer.X(), range(self.Npar)))) return best_fit_values, minimum
def _minimize(self): """ Minimize the function using MIGRAD :param compute_covar: whether to compute the covariance (and error estimates) or not :return: best_fit: a dictionary containing the parameters at their best fit values function_minimum : the value for the function at the minimum NOTE: if the minimization fails, the dictionary will be empty and the function_minimum will be set to minimization.FIT_FAILED """ # Try a maximum of 10 times and break as soon as the fit is ok self.minuit.reset() self._last_migrad_results = self.minuit.migrad() for i in range(9): if self.minuit.valid: break else: # Try again self._last_migrad_results = self.minuit.migrad() if not self.minuit.valid: self._print_current_status() raise FitFailed( "MIGRAD call failed. This is usually due to unconstrained parameters." ) else: # Gather the optimized values for all parameters from the internal # iminuit dictionary best_fit_values = [] for k, par in self.parameters.items(): minuit_name = self._parameter_name_to_minuit_name(k) best_fit_values.append(self.minuit.values[minuit_name]) return best_fit_values, self.minuit.fval
def _minimize(self): # Build initial point x0 = [] bounds = [] minima = [] maxima = [] for i, (par_name, (cur_value, cur_delta, cur_min, cur_max)) in enumerate(self._internal_parameters.items()): x0.append(cur_value) # scipy's algorithms will always try to evaluate the function exactly at the boundaries, which will # fail because the Jacobian is not defined there... let's fix this by using a slightly larger or smaller # minimum and maximum within the scipy algorithm than the real boundaries (saved in minima and maxima) minima.append(cur_min) maxima.append(cur_max) if cur_min is not None: cur_min = cur_min + 0.00005 * abs(cur_min) if cur_max is not None: cur_max = cur_max - 0.00005 * abs(cur_max) bounds.append((cur_min, cur_max)) def wrapper(x): if not self._check_bounds(x, minima, maxima): return np.inf return self.function(*x) def wrapper_2(*x): return wrapper(x) def jacobian(x): if not self._check_bounds(x, minima, maxima): return np.inf jacv = get_jacobian(wrapper_2, x, minima, maxima) return jacv res = scipy.optimize.minimize( wrapper, np.array(x0), method=self._setup_dict["algorithm"], bounds=bounds, jac=jacobian, tol=self._setup_dict["tol"], ) # Make sure the optimization worked if not res.success: raise FitFailed( "Could not converge. Message from solver: %s (status: %i)" % (res.message, res.status)) # Transform the result to numpy.array best_fit_values = np.array(res.x) return best_fit_values, float(res.fun)