int main(int argc, char* argv[]) { // Number of threads unsigned int n_threads = boost::thread::hardware_concurrency(); std::cout << "Number of available threads " << n_threads << std::endl; likelihood l(5, 5, 9); double nexp[5][5] = {{1., 1.6, 0.6, 0.2, 0.0}, {0., 15.4, 2.3, 0.0, 0.0}, {0., 2.5, 4.1, 0.0, 0.0}, {0., 3.3, 0.0, 1.1, 0.0}, {0., 9.5, 10.0, 0.7, 39.2}}; std::cout << "n(regions) = " << l.nr() << ", n(processes) = " << l.np() << ", n(systematics) = " << l.ns() << std::endl; for (unsigned int ir = 0; ir < l.nr(); ir++) for (unsigned int ip = 0; ip < l.np(); ip++) { l.set_nexp(ir, ip, nexp[ir][ip]); for (unsigned int is = 0; is < l.ns(); is++) { double dsyst = 0.; if (is < 2 && ip != 4) // Jet/MET dsyst = (0.1 - 0.05 * is) * (1. + ir * 0.05); else if (is < 7 && (is - 2 == ip)) // Theory dsyst = (ip == 4) ? 1. : 0.5; else if (is == 7 && (ir == 1 || ir == 2)) // b-tagging dsyst = (-1. + (ir - 1) * 2.) * 0.1; else if (is == 8) // Photon id efficiency dsyst = 0.05; l.set_dsyst(ir, ip, is, dsyst); } } // Setup minimizer unsigned int nparams = l.np()+l.ns(); boost::scoped_array<double> p0(new double[nparams]); boost::scoped_array<double> popt(new double[nparams]); for (unsigned int i = 0; i < nparams; i++) p0[i] = (i < l.np()) ? 1. : 0.; boost::function<double (double * const)> feval; feval = boost::bind(&likelihood::eval, &l, _1); optimize::minimizer_nm mle_nm(feval, l.np()+l.ns()); optimize::minimizer_bfgs mle_bfgs(feval, l.np()+l.ns()); // Setup random generation of poisson distributed numbers boost::mt19937 gen; typedef boost::poisson_distribution<unsigned int> t_poisson; typedef boost::scoped_ptr< t_poisson > t_ptr_poisson; typedef boost::variate_generator< boost::mt19937&, t_poisson > t_gen; typedef boost::scoped_ptr< t_gen > t_ptr_gen; boost::scoped_array< t_ptr_poisson > pdist(new t_ptr_poisson[l.nr()]); boost::scoped_array< t_ptr_gen > rndgen(new t_ptr_gen[l.ns()]); for (unsigned int ir = 0; ir < l.nr(); ir++) { std::cout << "region" << ir << " nexp = " << l.nexp(ir, p0.get()) << std::endl; pdist[ir].reset(new t_poisson(l.nexp(ir, p0.get()))); rndgen[ir].reset(new t_gen(gen, *(pdist[ir]))); } boost::timer time_monitor; double dt[3] = {0., 0., 0.}; unsigned int ntoys = 10; for (unsigned int iexp = 0; iexp < ntoys; iexp++) { std::cout << "Starting experiment " << iexp << std::endl; // Generate pseudo-experiment random numbers for (unsigned int ir = 0; ir < l.nr(); ir++) { l.set_nobs(ir, (*(rndgen[ir]))()); std::cout << " region" << ir << " nobs = " << l.nobs(ir) << " nexp = " << l.nexp(ir, p0.get()) << std::endl; } std::cout << " Perform a minimization " << std::endl; // Minimize with Nelder-Mean without mt mle_nm.set_is_mt(false); time_monitor.restart(); mle_nm.minimize(p0.get()); dt[0] = time_monitor.elapsed(); std::cout << " min = ("; for (size_t i = 0; i < nparams; i++) popt[i] = mle_nm.get_opt_var(i).value(); for (size_t i = 0; i < nparams; i++) { if (i < l.nr()) std::cout << l.nexp(i, popt.get()); else std::cout << mle_nm.get_opt_var(i).value(); if (i < nparams - 1) std::cout << ", "; } std::cout << ") fmin = " << mle_nm.get_fmin() << std::endl; // Minimize with Nelder-Mean with mt mle_nm.set_is_mt(true); time_monitor.restart(); mle_nm.minimize(p0.get()); dt[1] = time_monitor.elapsed(); std::cout << " min = ("; for (size_t i = 0; i < nparams; i++) popt[i] = mle_nm.get_opt_var(i).value(); for (size_t i = 0; i < nparams; i++) { if (i < l.nr()) std::cout << l.nexp(i, popt.get()); else std::cout << mle_nm.get_opt_var(i).value(); if (i < nparams - 1) std::cout << ", "; } std::cout << ") fmin = " << mle_nm.get_fmin() << std::endl; // Minimize with BFGS time_monitor.restart(); mle_bfgs.minimize(p0.get()); dt[2] = time_monitor.elapsed(); std::cout << " min = ("; for (size_t i = 0; i < nparams; i++) popt[i] = mle_bfgs.get_opt_var(i).value(); for (size_t i = 0; i < nparams; i++) { if (i < l.nr()) std::cout << l.nexp(i, popt.get()); else std::cout << mle_bfgs.get_opt_var(i).value(); if (i < nparams - 1) std::cout << ", "; } std::cout << ") fmin = " << mle_bfgs.get_fmin() << std::endl; std::cout << " timing " << dt[0] << " " << dt[1] << " " << dt[2] << std::endl; std::cout << " ... done." << std::endl; } return 0; }
void test_mle_nm (void) { // These test cases have been verified with R. zinm_par_t *par = new_zinm_par(1); if (par == NULL) { fprintf(stderr, "test error line %d\n", __LINE__); return; } // 0:14, 1:5, 2:4, 3:1, 5:1 uint32_t x1[25] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1,1,1,1,1,2,2,2,2,3,5 }; test_assert(mle_nm(x1, 1, 25, par)); test_assert(fabs(par->alpha-0.9237) < 1e-3); test_assert(fabs(par->mu[0]-0.8400) < 1e-3); // 0:27, 1:12, 2:8, 3:1, 4:1, 5:1 uint32_t x2[50] = {3,0,1,2,0,0,1,0,0,0,0,1,1,0,0,1,2,2,0,0,0,1,2, 0, 0,0,0,0,4,0,0,0,1,5,1,0,1,2,1,2,2,2,0,0,0,1,0,1,0,0}; test_assert(mle_nm(x2, 1, 50, par)); test_assert(fabs(par->alpha-1.3436) < 1e-3); test_assert(fabs(par->mu[0]-0.8000) < 1e-3); // 0:12, 1:7, 2:13, 3:4, 4:6, 5:2, 6:1, 7:3, 8:1, 9:1 uint32_t x3[50] = {4,5,2,1,2,4,2,2,0,4,2,1,3,6,0,0,7,3,0,8,4,2,0, 0,2,3,2,3,7,9,2,4,0,4,2,0,0,2,5,1,1,2,1,0,0,0,1,2,1,7}; test_assert(mle_nm(x3, 1, 50, par)); test_assert(fabs(par->alpha-1.7969) < 1e-3); test_assert(fabs(par->mu[0]-2.4600) < 1e-3); // 0:39, 1:8, 2:2, 3:1 uint32_t x4[50] = {1,0,0,0,0,0,3,1,0,1,0,0,0,0,0,0,0,1,0,0,0,2,0, 2,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0}; test_assert(mle_nm(x4, 1, 50, par)); test_assert(fabs(par->alpha-0.7073) < 1e-3); test_assert(fabs(par->mu[0]-0.3000) < 1e-3); // 0:59, 1:83, 2:99, 3:67, 4:63, 5:49, 6:27, 7:22, 8:11, 9:6 // 10:6, 11:3, 12:2, 13:3 uint32_t x5[500] = {1,0,0,1,1,2,1,0,5,7,1,3,3,1,6,0,2,5,7,0,5,2,1, 10,5,3,4,5,7,0,8,6,3,0,2,1,1,0,2,3,7,2,3,2,2,1,0,4,4,2,4,2, 0,6,3,2,5,2,1,4,3,4,2,2,5,3,2,0,2,8,1,3,1,7,5,1,4,1,1,0,2, 2,4,1,1,1,4,1,3,4,4,10,5,2,0,7,1,6,1,3,6,4,0,2,4,1,12,2,5, 6,5,4,1,11,0,1,3,2,4,2,0,2,3,4,0,2,9,9,7,4,2,1,3,3,3,4,2,9, 2,4,3,2,2,4,2,5,3,0,1,3,2,0,3,3,4,1,3,3,5,7,3,3,2,1,5,5,4, 6,1,1,1,2,9,5,1,2,4,0,2,1,0,3,2,4,3,1,4,2,1,4,1,6,0,6,5,3, 5,2,0,1,2,1,0,5,3,2,7,6,4,3,2,5,7,5,5,1,1,3,10,2,0,5,0,1,2, 0,5,1,2,3,6,4,0,3,1,2,2,4,3,0,3,2,5,4,10,1,2,4,4,2,13,4,3, 1,5,4,8,5,6,2,3,4,3,1,5,5,1,8,2,0,5,7,3,2,2,4,2,3,1,5,3,7, 13,1,4,7,5,5,0,3,0,4,2,3,1,2,4,2,8,1,2,5,6,1,1,0,7,2,2,3,5, 12,2,2,2,0,3,3,4,0,2,5,1,10,0,7,6,5,0,11,2,3,7,3,5,4,2,1,2, 4,0,2,2,2,0,6,2,3,4,2,3,7,3,5,2,5,0,4,4,6,3,1,2,7,3,0,2,5, 7,2,2,0,0,0,6,3,0,1,1,5,5,2,6,2,4,6,0,1,2,3,2,2,2,3,4,1,1, 4,0,2,0,1,3,4,1,2,2,3,1,4,4,3,4,4,1,5,2,13,4,10,5,6,1,0,5, 0,0,5,6,0,1,8,5,1,3,1,8,1,8,1,6,7,2,8,2,2,3,3,0,4,2,1,9,6, 0,6,7,1,8,2,2,1,11,3,0,4,2,5,1,6,8,3,4,7,0,4,2,4,1,1,1,6,0, 4,4,6,2,1,3,1,0,4,9,3,1,4,2,2,0,1}; test_assert(mle_nm(x5, 1, 500, par)); test_assert(fabs(par->alpha-3.0057) < 1e-3); test_assert(fabs(par->mu[0]-3.1860) < 1e-3); free(par); par = NULL; // Run cases in two dimensions. par = new_zinm_par(2); if (par == NULL) { fprintf(stderr, "test error line %d\n", __LINE__); return; } // Data obtained with the R code shown below. // set.seed(123) // l = rgamma(200, shape=2.1) // x = rpois(200, lambda=l) // y = rpois(200, lambda=3.5*l) // as.vector(t(cbind(x,y))) // // The data is pasted below. uint32_t x6[400] = {1,2,3,15,0,0,2,0,3,25,3,4,0,2,0,0,2,12,3,4, 5,9,0,10,2,2,5,10,2,10,1,5,0,4,1,7,1,0,1,3,0,0,1,1,0,2,1,4, 0,5,0,3,5,7,4,8,1,10,2,6,2,11,0,3,2,6,1,7,6,8,0,1,4,8,1,4, 1,4,3,6,2,1,1,8,0,3,0,1,0,1,4,2,3,6,2,6,5,25,1,0,1,7,1,10, 2,5,7,6,6,15,1,1,0,0,3,2,1,15,0,5,1,1,1,4,1,7,4,3,0,5,0,2, 3,10,2,14,1,6,0,2,3,7,0,4,3,8,0,2,3,13,1,5,2,25,0,0,6,8,5, 15,3,7,6,12,2,4,4,4,0,4,4,14,3,6,2,4,2,5,0,5,2,6,1,10,3,1, 0,2,2,6,4,17,4,7,2,7,3,14,2,12,1,8,2,0,2,7,1,2,3,12,4,8,6, 15,4,4,1,5,1,11,0,1,3,3,0,6,2,13,1,5,2,2,6,16,1,3,2,10,2,7, 2,2,6,9,0,2,3,12,2,9,4,8,2,7,0,4,7,27,0,3,2,19,2,3,1,4,1,0, 0,0,0,6,2,7,1,9,1,6,2,8,1,3,4,12,1,4,3,12,1,4,6,19,3,9,1,0, 1,2,10,24,4,15,1,8,0,0,1,4,1,8,1,19,2,10,2,7,0,3,0,3,3,6,1, 5,4,22,2,7,1,3,2,7,0,0,0,8,2,8,1,5,1,1,3,8,0,1,0,5,1,3,1,4, 3,6,3,9,2,2,1,4,2,10,0,4,0,3,5,3,0,0,0,1,0,2,2,0,8,17,5,14, 2,9,2,5,2,8,4,12,0,2,1,4,6,12,7,16,7,15,0,6}; test_assert(mle_nm(x6, 2, 200, par)); // Real value of alpha is 2.1, and p is (.18, .18, .64). test_assert(fabs(par->alpha-1.9374) < 1e-3); test_assert(fabs(par->mu[0]-2.0150) < 1e-3); test_assert(fabs(par->mu[1]-6.7050) < 1e-3); free(par); return; }