16 #ifndef POPS_QUARANTINE_HPP
17 #define POPS_QUARANTINE_HPP
23 #include <type_traits>
33 os << static_cast<std::underlying_type<Direction>::type>(obj);
37 typedef std::tuple<double, Direction>
DistDir;
44 template<
typename IntegerRaster,
typename RasterIndex =
int>
51 double west_east_resolution_;
53 double north_south_resolution_;
55 std::vector<BBoxInt> boundaries;
57 std::map<int, int> boundary_id_idx_map;
58 std::vector<EscapeDistDir> escape_dist_dirs;
65 void quarantine_boundary(
66 const IntegerRaster& quarantine_areas,
67 const std::vector<std::vector<int>>& suitable_cells)
71 for (
auto indices : suitable_cells) {
74 auto value = quarantine_areas(i, j);
76 auto search = boundary_id_idx_map.find(value);
78 if (search == boundary_id_idx_map.end()) {
79 boundary_id_idx_map.insert(std::make_pair(value, idx));
81 std::make_tuple(height_ - 1, 0, 0, width_ - 1));
86 bidx = search->second;
87 std::tie(n, s, e, w) = boundaries.at(bidx);
96 boundaries.at(bidx) = std::make_tuple(n, s, e, w);
109 closest_direction(RasterIndex i, RasterIndex j,
const BBoxInt boundary)
const
112 int mindist = std::numeric_limits<int>::max();
113 std::tie(n, s, e, w) = boundary;
115 if ((i - n) * north_south_resolution_ < mindist) {
116 mindist = (i - n) * north_south_resolution_;
119 if ((s - i) * north_south_resolution_ < mindist) {
120 mindist = (s - i) * north_south_resolution_;
123 if ((e - j) * west_east_resolution_ < mindist) {
124 mindist = (e - j) * west_east_resolution_;
127 if ((j - w) * west_east_resolution_ < mindist) {
128 mindist = (j - w) * west_east_resolution_;
136 const IntegerRaster& quarantine_areas,
140 const std::vector<std::vector<int>>& suitable_cells)
141 : width_(quarantine_areas.cols()),
142 height_(quarantine_areas.rows()),
143 west_east_resolution_(ew_res),
144 north_south_resolution_(ns_res),
145 num_steps(num_steps),
150 std::make_tuple(std::numeric_limits<double>::max(),
Direction::
None)))
152 quarantine_boundary(quarantine_areas, suitable_cells);
163 const IntegerRaster& infected,
164 const IntegerRaster& quarantine_areas,
166 const std::vector<std::vector<int>>& suitable_cells)
171 for (
auto indices : suitable_cells) {
176 int area = quarantine_areas(i, j);
178 escape_dist_dirs.at(step) = std::make_tuple(
184 int bindex = boundary_id_idx_map[area];
185 std::tie(dist, dir) = closest_direction(i, j, boundaries.at(bindex));
186 if (dist < std::get<0>(min_dist_dir)) {
187 min_dist_dir = std::make_tuple(dist, dir);
190 escape_dist_dirs.at(step) = std::make_tuple(
false, min_dist_dir);
198 return escape_dist_dirs.at(step);
206 return std::get<0>(escape_dist_dirs.at(step));
216 auto dist_dir = std::get<1>(escape_dist_dirs.at(step));
217 return std::get<0>(dist_dir);
226 auto dist_dir = std::get<1>(escape_dist_dirs.at(step));
227 return std::get<1>(dist_dir);
235 template<
typename IntegerRaster>
242 for (
const auto& item : escape_infos) {
243 std::tie(escape, distdir) = item.escape_info(step);
246 return (
double)escapes / escape_infos.size();
255 template<
typename IntegerRaster>
261 std::vector<DistDir> distances_directions;
262 for (
const auto& item : escape_infos) {
263 std::tie(escape, distdir) = item.escape_info(step);
264 distances_directions.push_back(distdir);
267 return distances_directions;
277 template<
typename IntegerRaster>
281 std::stringstream ss;
282 ss << std::setprecision(1) << std::fixed;
283 ss <<
"step,escape_probability";
284 for (
unsigned i = 0; i < escape_infos.size(); i++)
285 ss <<
",dist" << i <<
",dir" << i;
287 for (
unsigned step = 0; step < num_steps; step++) {
290 std::vector<DistDir> dists_dirs =
294 for (
unsigned i = 0; i < dists_dirs.size(); i++) {
295 std::tie(dist, dir) = dists_dirs.at(i);
296 if (std::isnan(dist))
299 ss <<
"," << dist <<
"," << dir;
306 #endif // POPS_QUARANTINE_HPP