Ejemplo n.º 1
0
    double pfilter(Model & sim_model, Parameter & model_params, MCMCoptions & options, Particle &particles, Trajectory & output_traj, TimeSeriesData &epi_data, TreeData &tree_data, MultiTreeData &multitree_data) {
        int thread_max = omp_get_max_threads();
        gsl_rng** rngs = new gsl_rng*[thread_max];
        for (int thread = 0; thread < thread_max; thread++) {
            rngs[thread] = gsl_rng_alloc(gsl_rng_mt19937);
            gsl_rng_set(rngs[thread], omp_get_thread_num() + thread);
        }
        
        double loglik = 0.0;
        int num_groups = options.num_groups;
        int num_particles = options.particles;
        int init_seed = options.seed;
        int total_dt = options.total_dt;
        double sim_dt = options.sim_dt;
        int total_steps = ceil((double)total_dt/(double)options.pfilter_every);
        int add_dt = 0;
        double ESS_threshold = options.pfilter_threshold*(double)num_particles;
        Likelihood likelihood_calc;
        //        std::vector <Parameter> values;// (options.num_threads, model_params);
        //        for (int i=0; i!=options.num_threads; ++i) values.push_back(model_params);
        //        for (int i=0; i!=model_params.get_total_params(); ++i) values.push_back(model_params.get(i));
        std::vector <std::vector<double> > values(options.num_threads, std::vector<double>(model_params.get_total_params(), 0.0));
        for (int i=0; i!=options.num_threads; ++i) {
            for (int j=0; j!=model_params.get_total_params(); ++j) {
                values[i][j] = model_params.get(j);
            }
        }
        //        printf("Size of values = %d\n",values.size());
        double reporting_rate = 1.0;
        if (model_params.param_exists("reporting")) {
            reporting_rate = model_params.get("reporting");
        }
        std::vector <std::string> param_names = model_params.get_names_vector();
        std::vector <std::vector<std::string> > param_names_threads (options.num_threads);
        if (model_params.param_exists("time_before_data")) {
            add_dt = model_params.get("time_before_data");
        }
        if (options.save_traj) {
            if (add_dt > 0) {
                particles.start_particle_tracing(add_dt+total_dt, num_groups);
            }
            else if (add_dt < 0) {
                particles.start_particle_tracing(add_dt+total_dt, num_groups);
                total_steps = ceil((double)(total_dt+add_dt)/(double)options.pfilter_every);
            }
            else {
                particles.start_particle_tracing(total_dt, num_groups);
            }
        }
        std::vector <Model> models;
        for (int i=0; i<options.num_threads; ++i) {
            models.push_back(sim_model);
        }
        std::vector <int> add_dt_threads (options.num_threads, add_dt);
        std::vector <int> start_dt_threads (options.num_threads, 0);
        std::vector <int> end_dt_threads (options.num_threads, add_dt);
        std::vector <double> dt_threads (options.num_threads, sim_dt);
        std::vector <int> total_dt_threads(options.num_threads, total_dt);
        std::vector <double> reporting_rate_threads(options.num_threads, reporting_rate);
        std::vector <int> num_groups_threads(options.num_threads, num_groups);
        // Simulate model and calculate likelihood assuming no observed data
        if (model_params.param_exists("time_before_data")) {
            if (add_dt > 0) {
                omp_set_num_threads(options.num_threads);
                //                std::vector <Trajectory *> curr_trajs;
                //                for (int i=0; i!=num_particles; ++i) {
                //                    curr_trajs.push_back(particles.get_traj(i));
                //                }
#pragma omp parallel for shared(particles, values) schedule(static,1)
                for (int tn = 0; tn < thread_max; tn++) {
                    for (int i = tn; i < num_particles; i += thread_max) {
                        // Adjust length of trajectory
                        particles.get_traj(i)->resize(add_dt, num_groups);
                        models[tn].simulate(values[tn], param_names_threads[tn], particles.get_traj(i), 0, add_dt_threads[tn], dt_threads[tn], total_dt_threads[tn], rngs[tn]);
                        if (options.which_likelihood < 2) {
                            double w = likelihood_calc.binomial_lik(reporting_rate_threads[tn], particles.get_traj(i)->get_total_traj(), add_dt_threads[tn] + total_dt_threads[tn], 0, add_dt_threads[tn], num_groups_threads[tn], false);
                            particles.set_weight(w, i, false);
                        }
                        if (options.save_traj) {
                            particles.save_traj_to_matrix(i, 0, add_dt);
                            particles.save_ancestry(i, 0, add_dt);
                        }
                    }
                }
            }
        }
        init_seed += num_particles;
        int t=0;
        int start_dt;
        int end_dt;
        for (t = 0; t != total_steps; ++t) {
            //            std::vector<double> we(options.particles, 0.0), wg(options.particles, 0.0);
            start_dt = t*options.pfilter_every;
            end_dt = std::min(total_dt, (t + 1)*options.pfilter_every);
            std::fill(start_dt_threads.begin(), start_dt_threads.end(), start_dt);
            std::fill(end_dt_threads.begin(), end_dt_threads.end(), end_dt);
            omp_set_num_threads(options.num_threads);
#pragma omp parallel for shared (particles, values) schedule(static,1)
            for (int tn = 0; tn < thread_max; tn++) {
                for (int i = tn; i < num_particles; i+=thread_max) {
                    // Adjust length of trajectory
                    //                    if (tn==0) std::cout << i << ' ' << std::endl;
                    particles.get_traj(i)->resize(end_dt - start_dt, options.num_groups);
                    models[tn].simulate(values[tn], param_names_threads[tn], particles.get_traj(i), start_dt_threads[tn], end_dt_threads[tn], dt_threads[tn], total_dt_threads[tn], rngs[tn]);
                    double w = 1.0;
                    double temp = 0.0;
                    if (options.which_likelihood < 2) {
                        double A = particles.get_traj(i)->get_total_traj();
                        temp = likelihood_calc.binomial_lik(reporting_rate_threads[tn], A, epi_data.get_data_ptr(0), add_dt_threads[tn] + total_dt_threads[tn], start_dt_threads[tn], end_dt_threads[tn], add_dt_threads[tn], num_groups_threads[tn], false);
                        w *= temp;
                        //                        we[i] = log(temp);
                    }
                    if (options.which_likelihood != 1) {
                        temp = likelihood_calc.coalescent_lik(particles.get_traj(i)->get_traj_ptr(0, 0), particles.get_traj(i)->get_traj_ptr(1, 0),
                                                              tree_data.get_binomial_ptr(0), tree_data.get_interval_ptr(0), tree_data.get_ends_ptr(0),
                                                              start_dt_threads[tn], end_dt_threads[tn], add_dt_threads[tn], false);
                        w *= temp;
                        //                        wg[i] = log(temp);
                    }
                    particles.set_weight(w, i, true);
                    if (options.save_traj) {
                        particles.save_traj_to_matrix(i, start_dt_threads[tn] + add_dt_threads[tn], end_dt_threads[tn] + add_dt_threads[tn]);
                        particles.save_ancestry(i, start_dt_threads[tn] + add_dt_threads[tn], end_dt_threads[tn] + add_dt_threads[tn]);
                    }
                }
            }
            //            std::cout << "Epi Weight: " << std::accumulate(we.begin(), we.end(), 0.0) << " Gen Weight: " << std::accumulate(wg.begin(), wg.end(), 0.0) << " Total: " << particles.get_total_weight() << std::endl;
            double curr_ESS = particles.get_ESS();
            if (curr_ESS < ESS_threshold) {
                double total_weight = particles.get_total_weight();
                if (total_weight == 0.0) {
                    loglik += -0.1*std::numeric_limits<double>::max();
                    //                    std::cout << std::accumulate(epi_data.get_data_ptr(0)+start_dt, epi_data.get_data_ptr(0)+end_dt, 0.0) << " : " << particles.get_traj(0)->get_traj(0) << std::endl;
                    std::cout << "stop time: " << end_dt << std::endl;
                    break;
                } else {
                    loglik += log(total_weight) - log(num_particles);
                }
                particles.resample(options.rng[0]);
            }
            else {
                particles.reset_parents();
            }
        }
        if (options.save_traj) {
            output_traj.resize((total_dt+add_dt), num_groups);
            //if (loglik > -0.1*std::numeric_limits<double>::max()) {
            particles.retrace_traj(output_traj, options.rng[0]);
            //}
        }
        for (int i=0; i!=num_particles; ++i) {
            particles.get_traj(i)->reset();
        }
        std::vector < std::vector<double> >().swap(values);
        
        for (int thread = 0; thread < thread_max; thread++) {
            gsl_rng_free(rngs[thread]);
        }
        delete[] rngs;
        
        return (loglik);
    }