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);
}
Exemple #5
0
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);
}