pops-core  0.9
PoPS (Pest or Pathogen Spread) Model Core C++ library
gamma_kernel.hpp
Go to the documentation of this file.
1 /*
2  * PoPS model - gamma dispersal kernel
3  *
4  * Copyright (C) 2015-2020 by the authors.
5  *
6  * Authors: Margaret Lawrimore malawrim ncsu edu
7  *
8  * The code contained herein is licensed under the GNU General Public
9  * License. You may obtain a copy of the GNU General Public License
10  * Version 2 or later at the following locations:
11  *
12  * http://www.opensource.org/licenses/gpl-license.html
13  * http://www.gnu.org/copyleft/gpl.html
14  */
15 
16 #ifndef POPS_GAMMA_KERNEL_HPP
17 #define POPS_GAMMA_KERNEL_HPP
18 
19 #include "kernel_types.hpp"
20 #include "raster.hpp"
21 #include "lognormal_kernel.hpp"
22 
23 #include <random>
24 
25 namespace pops {
26 
27 using std::pow;
28 using std::exp;
29 
34 {
35 protected:
36  double alpha;
37  double theta;
38  std::gamma_distribution<double> gamma_distribution;
39 
40 public:
41  GammaKernel(double a, double t)
42  : alpha(a), theta(t), gamma_distribution(alpha, 1.0 / theta)
43  {
44  if (alpha <= 0 || theta <= 0) {
45  throw std::invalid_argument(
46  "alpha and theta must greater than or equal to 0");
47  }
48  }
49 
56  template<class Generator>
57  double random(Generator& generator)
58  {
59  return std::abs(gamma_distribution(generator));
60  }
61 
68  double pdf(double x)
69  {
70  if (x < 0) {
71  throw std::invalid_argument("x must greater than or equal to 0");
72  }
73  return 1.0 / (std::tgamma(alpha) * pow(theta, alpha)) * pow(x, (alpha - 1))
74  * exp(-x / theta);
75  }
76 
82  double cdf(double x)
83  {
84  double sum = 0.0;
85  double beta = 1.0 / theta;
86  for (int i = 0; i < alpha; i++) {
87  // tgamma = (i-1)! used since c++ has no factorial in std lib
88  sum += (1.0 / std::tgamma(i + 1)) * exp(-beta * x) * pow(beta * x, i);
89  }
90  return 1 - sum;
91  }
92 
104  double icdf(double x)
105  {
106  if (x <= 0 || x >= 1) {
107  throw std::invalid_argument("icdf: x must be between 0.0 and 1.0");
108  }
109  // pick starting approximation using lognormal icdf
110  LogNormalKernel lognormal(1);
111  double guess = lognormal.icdf(x);
112  double check = cdf(guess);
113  double numiterations = 1000; // will need to adjust this
114  double precision = 0.001; // will need to adjust this
115  for (int i = 0; i < numiterations; i++) {
116  if (check < (x - precision) || check > (x + precision)) {
117  double dif = check - x;
118  // if dif is positive guess is greater than needed
119  // if dif is negative guess is less than needed
120  double past_guess = guess;
121  double derivative = dif / pdf(guess);
122  // limit size of next guess
123  guess = std::max(guess / 10, std::min(guess * 10, guess - derivative));
124  check = cdf(guess);
125  // Check if we went to far and need to backtrack
126  int count = 0;
127  bool run = true;
128  while ((std::abs(dif) < std::abs(check - x)) && run) {
129  guess = (guess + past_guess) / 2.0;
130  check = cdf(guess);
131  count++;
132  if (count > 20) {
133  run = false;
134  }
135  }
136  }
137  else {
138  return guess;
139  }
140  }
141  throw std::invalid_argument("unable to find solution to gamma icdf ");
142  return -1;
143  }
144 };
145 
146 } // namespace pops
147 
148 #endif // POPS_GAMMA_KERNEL_HPP
raster.hpp
pops::GammaKernel::cdf
double cdf(double x)
Gamma cumulative distribution function used by gamma icdf.
Definition: gamma_kernel.hpp:82
pops::GammaKernel::gamma_distribution
std::gamma_distribution< double > gamma_distribution
Definition: gamma_kernel.hpp:38
pops::GammaKernel::random
double random(Generator &generator)
Returns random value from gamma distribution Used by RadialKernel to determine location of spread.
Definition: gamma_kernel.hpp:57
pops::GammaKernel::pdf
double pdf(double x)
Gamma probability density function Used by DeterministicKernel to determine location of spread.
Definition: gamma_kernel.hpp:68
pops::GammaKernel::alpha
double alpha
Definition: gamma_kernel.hpp:36
pops
Definition: cauchy_kernel.hpp:25
pops::GammaKernel::theta
double theta
Definition: gamma_kernel.hpp:37
pops::GammaKernel::GammaKernel
GammaKernel(double a, double t)
Definition: gamma_kernel.hpp:41
pops::LogNormalKernel
Dispersal kernel for log normal distribution class utilized by RadialKernel and DeterministicKernel.
Definition: lognormal_kernel.hpp:35
pops::LogNormalKernel::icdf
double icdf(double x)
Log normal inverse cumulative distribution (quantile) function Used by DeterministicKernel to determi...
Definition: lognormal_kernel.hpp:87
lognormal_kernel.hpp
kernel_types.hpp
Kernel types enum and helper functions.
pops::GammaKernel
Dispersal kernel for gamma distribution class utilized by RadialKernel and DeterministicKernel.
Definition: gamma_kernel.hpp:33
pops::GammaKernel::icdf
double icdf(double x)
Gamma inverse cumulative distribution (quantile) function Used by DeterministicKernel to determine ma...
Definition: gamma_kernel.hpp:104