File diffnet.hpp¶
File List > epiworld > models > diffnet.hpp
Go to the documentation of this file
#ifndef EPIWORLD_DIFFNET_H
#define EPIWORLD_DIFFNET_H
#include <string>
#include <vector>
#include "../config.hpp"
#include "../model-bones.hpp"
template<typename TSeq = EPI_DEFAULT_TSEQ>
class ModelDiffNet : public Model<TSeq>
{
private:
public:
// Statuses
static const int NONADOPTER = 0;
static const int ADOPTER = 1;
ModelDiffNet() = delete;
ModelDiffNet(
const std::string & innovation_name,
epiworld_double prevalence,
epiworld_double prob_adopt,
bool normalize_exposure = true,
double * agents_data = nullptr,
size_t data_ncols = 0u,
std::vector< size_t > data_cols = {},
std::vector< double > params = {}
);
bool normalize_exposure = true;
std::vector< size_t > data_cols;
std::vector< double > params;
};
template<typename TSeq>
inline ModelDiffNet<TSeq>::ModelDiffNet(
const std::string & innovation_name,
epiworld_double prevalence,
epiworld_double prob_adopt,
bool normalize_exposure,
double * agents_data,
size_t data_ncols,
std::vector< size_t > data_cols,
std::vector< double > params
)
{
// Adding additional parameters
this->normalize_exposure = normalize_exposure;
this->data_cols = data_cols;
this->params = params;
UpdateFun<TSeq> update_non_adopters = [](
Agent<TSeq> * p, Model<TSeq> * m
) -> void {
// Measuring exposure
// If the neighbor is infected, then proceed
size_t nviruses = m->get_n_viruses();
std::vector< Virus<TSeq>* > innovations(nviruses, {});
std::vector< bool > stored(nviruses, false);
std::vector< double > exposure(nviruses, 0.0);
ModelDiffNet<TSeq> * diffmodel = model_cast<ModelDiffNet<TSeq>,TSeq>(m);
Agent<TSeq> & agent = *p;
// For each one of the possible innovations, we have to compute
// the adoption probability, which is a function of exposure
auto & m_ref = *m;
for (auto & neighbor: agent.get_neighbors(*m))
{
if (neighbor->get_state() == ModelDiffNet<TSeq>::ADOPTER)
{
auto & v = neighbor->get_virus();
if (v == nullptr)
continue;
/* And it is a function of susceptibility_reduction as well */
double p_i =
(1.0 - agent.get_susceptibility_reduction(v, m_ref)) *
(1.0 - agent.get_transmission_reduction(v, m_ref))
;
size_t vid = v->get_id();
if (!stored[vid])
{
stored[vid] = true;
innovations[vid] = &(*v);
}
exposure[vid] += p_i;
}
}
// Computing probability of adoption
for (size_t i = 0u; i < nviruses; ++i)
{
if (diffmodel->normalize_exposure)
exposure.at(i) /= agent.get_n_neighbors();
for (auto & j: diffmodel->data_cols)
exposure.at(i) += agent(j, m_ref) * diffmodel->params.at(j);
// Baseline probability of adoption
double p = m->get_viruses()[i]->get_prob_infecting(m);
exposure.at(i) += std::log(p) - std::log(1.0 - p);
// Computing as log
exposure.at(i) = 1.0/(1.0 + std::exp(-exposure.at(i)));
}
// Running the roulette to see is an innovation is adopted
int which = roulette<int>(exposure, m);
// No innovation was adopted
if (which < 0)
return;
// Otherwise, it is adopted from any of the neighbors
agent.set_virus(*m,
*innovations.at(which),
ADOPTER
);
return;
};
// Adding agents data
this->set_agents_data(agents_data, data_ncols);
// Adding statuses
this->add_state("Non adopters", update_non_adopters);
this->add_state("Adopters");
// Adding parameters
std::string parname = std::string("Prob. Adopting ") + innovation_name;
this->add_param(prob_adopt, parname);
// Preparing the virus -------------------------------------------
Virus<TSeq> innovation(innovation_name, prevalence, true);
innovation.set_state(1,1,1);
innovation.set_prob_infecting(parname);
this->add_virus(innovation);
this->set_name(
std::string("Diffusion of Innovations - ") + innovation_name);
return;
}
#endif