Source code for pyEpiabm.utility.inverse_cdf

#
# Class of inverse CDF as is done in Covidsim code.
#

import random
import pyEpiabm as pe
import math
import numpy as np


[docs] class InverseCdf: """Class of inverse cumulative distribution functions (icdf) and their associated methods, in a style similar to CovidSim. """ def __init__(self, mean, icdf_array): """Constructor Method Parameters ---------- mean : float Mean of the icdf icdf_array : np.ndarray Array of quantiles of the icdf_array, values in array must be evenly spaced with the final value being as close to one as possible """ # CDF_RES is the resolution of icdf taken as length of icdf array. # Time_steps_per_day is the number of time steps per day in # the simulation. self.mean = mean self.icdf_array = np.asarray(icdf_array) self.CDF_RES = len(icdf_array) - 1 self.time_steps_per_day = pe.Parameters.instance().time_steps_per_day
[docs] def icdf_choose_noexp(self) -> float: """Samples a value from the inverse cumulative distribution function, following what is done in CovidSim (without exponentiation), and returns the value as a float. Returns ------- float Mean scaled relative to given icdf """ rand_num = random.random() q = rand_num * self.CDF_RES i = math.floor(q) q -= float(i) ti = (self.mean * (q * self.icdf_array[i+1] + (1.0 - q) * self.icdf_array[i])) value = float(math.floor(0.5 + (ti * self.time_steps_per_day))) return value
[docs] def icdf_choose_exp(self) -> float: """Samples a value from the inverse cumulative distribution function, following what is done in CovidSim (with negative exponentiation), and returns the value as a float. Returns ------- float Mean scaled relative to given icdf """ exp_icdf_array = np.exp(-self.icdf_array) rand_num = random.random() q = rand_num * self.CDF_RES # We take the integer part of q because we require i to be an index. # By taking away the integer part of q we are left with a random # number i, on the unit interval that is used for weighted # average between icdf values. i = math.floor(q) q -= float(i) ti = -self.mean * \ np.log((q * exp_icdf_array[i+1] + (1.0 - q) * exp_icdf_array[i])) value = float(math.floor(0.5 + (ti * self.time_steps_per_day))) return value