void theta::fill_mode_support(theta::ParValues & mode, std::map<theta::ParId, std::pair<double, double> > & support, const theta::Distribution & d){ ParIds pids = d.get_parameters(); d.mode(mode); theta_assert(mode.contains_all(pids)); for(ParIds::const_iterator p_it=pids.begin(); p_it!=pids.end(); ++p_it){ support[*p_it] = d.support(*p_it); } }
double llvm_exp_function::operator()(const theta::ParValues & values) const{ double exponent_total = 0.0; const size_t n = v_pids.size(); for(size_t i=0; i<n; ++i){ double val = values.get_unchecked(v_pids[i]); double lambda = val < 0 ? lambdas_minus[i] : lambdas_plus[i]; exponent_total += lambda * val; } return exp(exponent_total); }
void deltanll_hypotest::set_parameter_values(const theta::ParValues & values){ if(restrict_poi){ poi_value = values.get(*restrict_poi); } }
double exp_function::operator()(const theta::ParValues & values) const{ double val = values.get(pid); double lambda = val < 0 ? lambda_minus: lambda_plus; return exp(lambda * val); }
MinimizationResult root_minuit::minimize(const theta::Function & f, const theta::ParValues & start, const theta::ParValues & steps, const std::map<theta::ParId, std::pair<double, double> > & ranges){ //I would like to re-use min. However, it horribly fails after very few uses with // unsigned int ROOT::Minuit2::MnUserTransformation::IntOfExt(unsigned int) const: Assertion `!fParameters[ext].IsFixed()' failed. // when calling SetFixedVariable(...). //Using a "new" one every time seems very wastefull, but it seems to work ... std::auto_ptr<ROOT::Minuit2::Minuit2Minimizer> min(new ROOT::Minuit2::Minuit2Minimizer(type)); //min->SetPrintLevel(0); if(max_function_calls > 0) min->SetMaxFunctionCalls(max_function_calls); if(max_iterations > 0) min->SetMaxIterations(max_iterations); MinimizationResult result; //1. setup parameters, limits and initial step sizes ParIds parameters = f.get_parameters(); int ivar=0; for(ParIds::const_iterator it=parameters.begin(); it!=parameters.end(); ++it, ++ivar){ std::map<theta::ParId, std::pair<double, double> >::const_iterator r_it = ranges.find(*it); if(r_it==ranges.end()) throw invalid_argument("root_minuit::minimize: range not set for a parameter"); pair<double, double> range = r_it->second; double def = start.get(*it); double step = steps.get(*it); stringstream ss; ss << "par" << ivar; string name = ss.str(); //use not the ranges directly, but a somewhat more narrow range (one permille of the respective border) // in order to avoid that the numerical evaluation of the numerical derivative at the boundaries pass these // boundaries ... if(step == 0.0){ min->SetFixedVariable(ivar, name, def); } else if(isinf(range.first)){ if(isinf(range.second)){ min->SetVariable(ivar, name, def, step); } else{ min->SetUpperLimitedVariable(ivar, name, def, step, range.second - fabs(range.second) * 0.001); } } else{ if(isinf(range.second)){ min->SetLowerLimitedVariable(ivar, name, def, step, range.first + fabs(range.first) * 0.001); } else{ // both ends are finite if(range.first==range.second){ min->SetFixedVariable(ivar, name, range.first); } else{ min->SetLimitedVariable(ivar, name, def, step, range.first + fabs(range.first) * 0.001, range.second - fabs(range.second) * 0.001); } } } } //2. setup the function RootMinuitFunctionAdapter minuit_f(f); min->SetFunction(minuit_f); //3. setup tolerance min->SetTolerance(tolerance_factor * min->Tolerance()); //3.a. error definition. Unfortunately, SetErrorDef in ROOT is not documented, so I had to guess. // 0.5 seems to work somehow. min->SetErrorDef(0.5); //4. minimize. In case of failure, try harder. Discard all output generated in min->Minimize. bool success; { theta::utils::discard_output d_o(true); success = min->Minimize(); if(!success){ for(int i=1; i<=n_retries; i++){ success = min->Minimize(); if(success) break; } } } // d_o is destroyed, output resumed. //5. do error handling if(not success){ int status = min->Status(); int status_1 = status % 10; //int status_2 = status / 10; stringstream s; s << "MINUIT returned status " << status; switch(status_1){ case 1: s << " (Covariance was made pos defined)"; break; case 2: s << " (Hesse is invalid)"; break; case 3: s << " (Edm is above max)"; break; case 4: s << " (Reached call limit)"; break; case 5: s << " (Some other failure)"; break; default: s << " [unexpected status code]"; } throw MinimizationException(s.str()); } //6. convert result result.fval = min->MinValue(); ivar = 0; const double * x = min->X(); const double * errors = 0; bool have_errors = min->ProvidesError(); if(have_errors) errors = min->Errors(); for(ParIds::const_iterator it=parameters.begin(); it!=parameters.end(); ++it, ++ivar){ result.values.set(*it, x[ivar]); if(have_errors){ result.errors_plus.set(*it, errors[ivar]); result.errors_minus.set(*it, errors[ivar]); } else{ result.errors_plus.set(*it, -1); result.errors_minus.set(*it, -1); } } result.covariance.reset(parameters.size(), parameters.size()); //I would use min->CovMatrixStatus here to check the validity of the covariance matrix, // if only it was documented ... if(min->ProvidesError()){ for(size_t i=0; i<parameters.size(); ++i){ for(size_t j=0; j<parameters.size(); ++j){ result.covariance(i,j) = min->CovMatrix(i,j); } } } else{ for(size_t i=0; i<parameters.size(); ++i){ result.covariance(i,i) = -1; } } return result; }
double anom_function::operator()(const theta::ParValues & values) const{ double fL = values.get(pid_fL); double fR = values.get(pid_fR); return 1./(fL*fL + fR*fR); }