pops-core  0.9
PoPS (Pest or Pathogen Spread) Model Core C++ library
network_kernel.hpp
Go to the documentation of this file.
1 /*
2  * PoPS model - network dispersal kernel
3  *
4  * Copyright (C) 2020-2021 by the authors.
5  *
6  * Authors: Vaclav Petras (wenzeslaus gmail com)
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_NETWORK_KERNEL_HPP
17 #define POPS_NETWORK_KERNEL_HPP
18 
19 #include "kernel_types.hpp"
20 #include "raster.hpp"
21 #include "utils.hpp"
22 
23 #include <algorithm>
24 #include <set>
25 #include <random>
26 #include <string>
27 #include <sstream>
28 #include <map>
29 #include <cmath>
30 #include <vector>
31 
32 namespace pops {
33 
50 template<typename RasterIndex>
51 class Network
52 {
53 public:
54  using NodeId = int;
55  using Statistics = std::map<std::string, int>;
56 
65  Network(BBox<double> bbox, double ew_res, double ns_res, double speed)
66  : bbox_(bbox),
67  ew_res_(ew_res),
68  ns_res_(ns_res),
69  cell_travel_time_(((ew_res + ns_res) / 2) / speed)
70  {}
71 
81  {
82  return Network(BBox<double>(), 0, 0, 0);
83  }
84 
92  std::pair<RasterIndex, RasterIndex> xy_to_row_col(double x, double y) const
93  {
94  double col = (x - bbox_.west) / ew_res_;
95  double row = (bbox_.north - y) / ns_res_;
96  return {std::floor(row), std::floor(col)};
97  }
98 
102  std::pair<RasterIndex, RasterIndex>
103  xy_to_row_col(const std::string& x, const std::string& y) const
104  {
105  return xy_to_row_col(std::stod(x), std::stod(y));
106  }
107 
114  bool out_of_bbox(double x, double y) const
115  {
116  return x > bbox_.east || x < bbox_.west || y > bbox_.north || y < bbox_.south;
117  }
118 
141  template<typename InputStream>
142  void load(
143  InputStream& node_stream, InputStream& segment_stream, bool allow_empty = false)
144  {
145  std::set<NodeId> node_ids;
146  load_nodes(node_stream, node_ids);
147  if (node_ids.empty()) {
148  if (allow_empty)
149  return;
150  else
151  throw std::runtime_error("Network: No nodes within the extend");
152  }
153  load_segments(segment_stream, node_ids);
154  }
155 
166  const std::set<NodeId>& get_nodes_at(RasterIndex row, RasterIndex col) const
167  {
168  auto it = nodes_by_row_col_.find(std::make_pair(row, col));
169  if (it != nodes_by_row_col_.end())
170  return it->second;
171  // If not found, return an empty set (const reference to local static).
172  static std::set<NodeId> empty;
173  return empty;
174  }
175 
188  template<typename Generator>
189  NodeId
190  get_random_node_at(RasterIndex row, RasterIndex col, Generator& generator) const
191  {
192  const auto& nodes = get_nodes_at(row, col);
193  auto num_nodes = nodes.size();
194  if (num_nodes == 1) {
195  return *nodes.begin();
196  }
197  else if (num_nodes > 1) {
198  return pick_random_node(nodes, generator);
199  }
200  else {
201  throw std::invalid_argument("No nodes at a given row and column");
202  }
203  }
204 
211  bool has_node_at(RasterIndex row, RasterIndex col) const
212  {
213  // Replace by contains in C++20.
214  // return nodes_by_row_col_.count(std::make_pair(row, col)) > 0;
215  auto it = nodes_by_row_col_.find(std::make_pair(row, col));
216  if (it == nodes_by_row_col_.end())
217  return false;
218  return true;
219  }
220 
226  std::pair<RasterIndex, RasterIndex> get_node_row_col(NodeId node) const
227  {
228  for (const auto& item : nodes_by_row_col_) {
229  if (container_contains(item.second, node))
230  return item.first;
231  }
232  throw std::invalid_argument("No node with a given id");
233  }
234 
243  template<typename Generator>
244  std::tuple<int, int>
245  travel(RasterIndex row, RasterIndex col, double time, Generator& generator) const
246  {
247  // We assume there is a node here, i.e., that we are made decision
248  // to use this kernel knowing there is a node.
249  auto node_id = get_random_node_at(row, col, generator);
250  std::set<NodeId> visited_nodes;
251  while (time >= 0) {
252  auto next_node_id = next_node(node_id, visited_nodes, generator);
253  visited_nodes.insert(node_id);
254  // If there is no segment from the node, return the start cell.
255  if (next_node_id == node_id)
256  return std::make_tuple(row, col);
257  auto segment = get_segment(node_id, next_node_id);
258  // nodes may need special handling
259  for (const auto& cell : segment) {
260  time -= cell_travel_time_;
261  if (time <= 0) {
262  return cell;
263  // Given the while condition, this subsequently ends the while loop
264  // as well.
265  // break;
266  }
267  }
268  node_id = next_node_id;
269  }
270  throw std::invalid_argument("Time must be greater than or equal to zero");
271  }
272 
283  std::vector<std::pair<NodeId, std::pair<RasterIndex, RasterIndex>>>
285  {
286  std::vector<std::pair<NodeId, std::pair<RasterIndex, RasterIndex>>> nodes;
287  nodes.reserve(nodes_by_row_col_.size()); // It will be at least this big.
288  for (const auto& item : nodes_by_row_col_) {
289  RasterIndex row = item.first.first;
290  RasterIndex col = item.first.second;
291  for (const auto node_id : item.second) {
292  nodes.emplace_back(node_id, std::make_pair(row, col));
293  }
294  }
295  return nodes;
296  }
297 
306  {
307  std::map<std::string, int> stats;
308  std::set<NodeId> node_ids;
309  for (const auto& item : nodes_by_row_col_) {
310  for (const auto node_id : item.second) {
311  node_ids.insert(node_id);
312  }
313  }
314  stats["num_nodes"] = node_ids.size();
315  // We store segements in both directions, so each segment is stored twice.
316  stats["num_segments"] = node_matrix_.size() / 2;
317  std::set<NodeId> nodes_with_segments;
318  for (const auto& item : node_matrix_) {
319  nodes_with_segments.insert(item.first);
320  }
321  stats["num_nodes_with_segments"] = nodes_with_segments.size();
322  // TODO: Only count the nodes here. Output them in the dump network output.
323  int num_standalone_nodes = 0;
324  for (NodeId node_id : node_ids) {
325  if (nodes_with_segments.find(node_id) == nodes_with_segments.end()) {
326  stats["standalone_node_" + std::to_string(++num_standalone_nodes)] =
327  node_id;
328  }
329  }
330  stats["num_standalone_nodes"] = num_standalone_nodes;
331  // TODO: This can be faster. The list is a ordered set and we iterate over
332  // elements above.
333  const auto minmax_node_id = minmax_element(node_ids.begin(), node_ids.end());
334  stats["min_node_id"] = *minmax_node_id.first;
335  stats["max_node_id"] = *minmax_node_id.second;
336  return stats;
337  }
338 
344  template<typename OutputStream>
345  void dump_yaml(OutputStream& stream) const
346  {
347  stream << "network:\n";
348  stream << " statistics:\n";
349  auto stats = collect_statistics();
350  for (const auto& item : stats) {
351  stream << " " << item.first << ": " << item.second << "\n";
352  }
353  stream << " extent:\n";
354  stream << " north: " << bbox_.north << "\n";
355  stream << " south: " << bbox_.south << "\n";
356  stream << " east: " << bbox_.east << "\n";
357  stream << " west: " << bbox_.west << "\n";
358  stream << " resolution:\n";
359  stream << " ns: " << ns_res_ << "\n";
360  stream << " ew: " << ew_res_ << "\n";
361  stream << " raster:\n";
362  RasterIndex min_row;
363  RasterIndex min_col;
364  RasterIndex max_row;
365  RasterIndex max_col;
366  std::tie(min_row, min_col) =
368  std::tie(max_row, max_col) =
370  stream << " min_row: " << min_row << "\n";
371  stream << " min_col: " << min_col << "\n";
372  stream << " max_row: " << max_row << "\n";
373  stream << " max_col: " << max_col << "\n";
374  stream << " num_rows: " << max_row - min_row + 1 << "\n";
375  stream << " num_cols: " << max_col - min_col + 1 << "\n";
376  stream << " cost:\n";
377  stream << " cell_travel_time: " << cell_travel_time_ << "\n";
378  std::set<std::pair<NodeId, NodeId>> edges;
379  for (const auto& item : node_matrix_) {
380  for (const auto& node_id : item.second) {
381  edges.emplace(item.first, node_id);
382  }
383  }
384  stream << " edges:\n";
385  for (const auto& item : edges) {
386  stream << " - [" << item.first << ", " << item.second << "]\n";
387  }
388  stream << " nodes:\n";
389  for (const auto& item : nodes_by_row_col_) {
390  auto row = item.first.first;
391  auto col = item.first.second;
392  for (const auto& node_id : item.second) {
393  stream << " - id: " << node_id << "\n";
394  stream << " row: " << row << "\n";
395  stream << " col: " << col << "\n";
396  }
397  }
398  stream << " segments:\n";
399  for (const auto& item : segments_by_nodes_) {
400  stream << " - start_node: " << item.first.first << "\n";
401  stream << " end_node: " << item.first.second << "\n";
402  stream << " cells: [";
403  for (const auto& cell : item.second) {
404  stream << "[" << cell.first << ", " << cell.second << "], ";
405  }
406  stream << "]\n";
407  }
408  }
409 
410 protected:
412  using NodeMatrix = std::map<NodeId, std::vector<NodeId>>;
414  using Segment = std::vector<std::pair<RasterIndex, RasterIndex>>;
416  using SegmentsByNodes = std::map<std::pair<NodeId, NodeId>, Segment>;
417 
424  static NodeId node_id_from_text(const std::string& text)
425  {
426  return std::stoi(text);
427  }
428 
436  template<typename Container>
438  {
439  public:
440  ConstEitherWayIterator(typename Container::const_iterator it)
441  : is_forward_(true), forward_it_(it)
442  {}
443  ConstEitherWayIterator(typename Container::const_reverse_iterator it)
444  : is_forward_(false), reverse_it_(it)
445  {}
447  {
448  if (is_forward_)
449  ++forward_it_;
450  else
451  ++reverse_it_;
452  return *this;
453  }
454  const typename Container::value_type& operator*() const
455  {
456  if (is_forward_)
457  return *forward_it_;
458  return *reverse_it_;
459  }
461  {
462  if (is_forward_)
463  return forward_it_ != other.forward_it_;
464  return reverse_it_ != other.reverse_it_;
465  }
466 
467  private:
468  // Can be improved by std::optional or any in C++17.
469  bool is_forward_;
470  typename Container::const_iterator forward_it_;
471  typename Container::const_reverse_iterator reverse_it_;
472  };
473 
482  {
483  public:
485  typename Segment::const_iterator first,
486  typename Segment::const_iterator last)
487  : begin_(first), end_(last)
488  {}
490  typename Segment::const_reverse_iterator first,
491  typename Segment::const_reverse_iterator last)
492  : begin_(first), end_(last)
493  {}
495  {
496  return begin_;
497  }
499  {
500  return end_;
501  }
502 
503  private:
506  };
507 
514  template<typename InputStream>
515  void load_nodes(InputStream& stream, std::set<NodeId>& node_ids)
516  {
517  std::string line;
518  while (std::getline(stream, line)) {
519  std::istringstream line_stream{line};
520  char delimeter{','};
521  std::string node_text;
522  std::getline(line_stream, node_text, delimeter);
523  std::string x_coord_text;
524  std::getline(line_stream, x_coord_text, delimeter);
525  std::string y_coord_text;
526  std::getline(line_stream, y_coord_text, delimeter);
527  RasterIndex row;
528  RasterIndex col;
529  double x = std::stod(x_coord_text);
530  double y = std::stod(y_coord_text);
531  // Cut to extend
532  if (out_of_bbox(x, y))
533  continue;
534  std::tie(row, col) = xy_to_row_col(x_coord_text, y_coord_text);
535  NodeId node_id = node_id_from_text(node_text);
536  if (node_id < 1) {
537  std::runtime_error("Node ID must be greater than zero");
538  }
539  nodes_by_row_col_[std::make_pair(row, col)].insert(node_id);
540  node_ids.insert(node_id);
541  }
542  }
543 
550  template<typename InputStream>
551  void load_segments(InputStream& stream, const std::set<NodeId>& node_ids)
552  {
553  std::set<std::pair<NodeId, NodeId>> node_pairs;
554  std::string line;
555  while (std::getline(stream, line)) {
556  std::istringstream line_stream{line};
557  char delimeter{','};
558  std::string node_1_text;
559  std::getline(line_stream, node_1_text, delimeter);
560  std::string node_2_text;
561  std::getline(line_stream, node_2_text, delimeter);
562  auto node_1_id = node_id_from_text(node_1_text);
563  auto node_2_id = node_id_from_text(node_2_text);
564  // If either end nodes of the segment is not in the extent, skip it.
565  // This means that a segment is ignored even if one of the nodes and
566  // significant portion of the segment is in the area of iterest.
567  // TODO: Part of the segment may still be out, so that needs to be checked.
568  // Replace find by contains for C++20.
569  if (node_ids.find(node_1_id) == node_ids.end()
570  || node_ids.find(node_2_id) == node_ids.end())
571  continue;
572  if (node_1_id == node_2_id) {
573  std::runtime_error(
574  std::string("Segment cannot begin and end with the same node: ")
575  + node_1_text + " " + node_2_text);
576  }
577  std::string segment_text;
578  std::getline(line_stream, segment_text, delimeter);
579  // We don't know which way the nodes are ordered, so instead of checking
580  // the order, we create a symmetric matrix since we allocated the memory
581  // anyway.
582  node_pairs.emplace(node_1_id, node_2_id);
583  std::istringstream segment_stream{segment_text};
584  char in_cell_delimeter{';'};
585  std::string x_coord_text;
586  std::string y_coord_text;
587  Segment segment;
588  while (std::getline(segment_stream, x_coord_text, in_cell_delimeter)
589  && std::getline(segment_stream, y_coord_text, in_cell_delimeter)) {
590  // The same cell is possibly repeated if raster resolution is lower than
591  // the detail ("resolution") of each segment, so we check if the last
592  // added coordinate pair converted to same cell.
593  auto new_point = xy_to_row_col(x_coord_text, y_coord_text);
594  if (segment.empty() || segment.back() != new_point)
595  segment.emplace_back(new_point);
596  }
597  segments_by_nodes_.emplace(
598  std::make_pair(node_1_id, node_2_id), std::move(segment));
599  }
600 
601  for (auto node_id : node_ids) {
602  std::vector<NodeId> nodes;
603  for (const auto& item : node_pairs) {
604  if (item.first == node_id)
605  nodes.push_back(item.second);
606  else if (item.second == node_id)
607  nodes.push_back(item.first);
608  }
609  node_matrix_[node_id] = std::move(nodes);
610  }
611  }
612 
625  {
626  for (const auto& item : segments_by_nodes_) {
627  const auto& key{item.first};
628  if (key.first == start && key.second == end)
629  return SegmentView(item.second.cbegin(), item.second.cend());
630  if (key.second == start && key.first == end) {
631  return SegmentView(item.second.crbegin(), item.second.crend());
632  }
633  }
634  throw std::invalid_argument("No segment for given nodes");
635  }
636 
643  const std::vector<NodeId>& nodes_connected_to(NodeId node) const
644  {
645  return node_matrix_.at(node);
646  }
647 
662  template<typename Generator>
663  NodeId
664  next_node(NodeId node, const std::set<NodeId>& ignore, Generator& generator) const
665  {
666  // Get all candidate nodes.
667  const auto& all_nodes = nodes_connected_to(node);
668 
669  // Resolve disconnected node and dead end cases.
670  auto num_nodes = all_nodes.size();
671  if (!num_nodes)
672  return node;
673  else if (num_nodes == 1)
674  return all_nodes[0];
675 
676  // Filter out the ignored nodes.
677  std::vector<int> nodes;
678  std::back_insert_iterator<std::vector<int>> back_it(nodes);
679  std::remove_copy_if(
680  all_nodes.begin(), all_nodes.end(), back_it, [&ignore](NodeId id) {
681  return container_contains(ignore, id);
682  });
683 
684  // Pick a random node. Fallback to all candidate nodes if all are in ignore.
685  num_nodes = nodes.size();
686  if (!num_nodes)
687  return pick_random_node(all_nodes, generator);
688  else if (num_nodes == 1)
689  return nodes[0];
690  return pick_random_node(nodes, generator);
691  }
692 
696  template<typename Container, typename Generator>
697  static NodeId pick_random_node(const Container& nodes, Generator& generator)
698  {
699  auto num_nodes = nodes.size(); // Replace by std::size in C++17.
700  std::uniform_int_distribution<size_t> dist(0, num_nodes - 1);
701  auto index = dist(generator);
702  // Our lists are expected to be short, so this is expected to be fast for
703  // both sets and vectors.
704  return *std::next(nodes.begin(), index);
705  }
706 
708  double ew_res_;
709  double ns_res_;
711 
712  std::map<std::pair<RasterIndex, RasterIndex>, std::set<NodeId>> nodes_by_row_col_;
715 };
716 
724 template<typename RasterIndex>
726 {
727 public:
743  const Network<RasterIndex>& network, double min_time, double max_time)
744  : network_(network), time_distribution_(min_time, max_time)
745  {}
746 
752  template<typename Generator>
753  std::tuple<int, int> operator()(Generator& generator, int row, int col)
754  {
755  double time = time_distribution_(generator);
756  std::tie(row, col) = network_.travel(row, col, time, generator);
757 
758  return std::make_tuple(row, col);
759  }
760 
768  bool is_cell_eligible(int row, int col)
769  {
770  return network_.has_node_at(row, col);
771  }
772 
775  static bool supports_kernel(const DispersalKernelType type)
776  {
777  return type == DispersalKernelType::Network;
778  }
779 
780 protected:
784  std::uniform_real_distribution<double> time_distribution_;
785 };
786 
787 } // namespace pops
788 
789 #endif // POPS_NETWORK_KERNEL_HPP
BBox::east
Number east
Definition: utils.hpp:71
pops::Network::load
void load(InputStream &node_stream, InputStream &segment_stream, bool allow_empty=false)
Load nodes and segments from input streams.
Definition: network_kernel.hpp:142
raster.hpp
pops::Network::next_node
NodeId next_node(NodeId node, const std::set< NodeId > &ignore, Generator &generator) const
Pick a next node from the given node.
Definition: network_kernel.hpp:664
utils.hpp
pops::Network::SegmentView::SegmentView
SegmentView(typename Segment::const_iterator first, typename Segment::const_iterator last)
Definition: network_kernel.hpp:484
pops::NetworkDispersalKernel::time_distribution_
std::uniform_real_distribution< double > time_distribution_
Travel Time distribnution.
Definition: network_kernel.hpp:784
pops::Network::ConstEitherWayIterator
A const iterator which encapsulates either forward or reverse iterator.
Definition: network_kernel.hpp:437
BBox::north
Number north
Definition: utils.hpp:69
pops::NetworkDispersalKernel::is_cell_eligible
bool is_cell_eligible(int row, int col)
Test if cell is eligible to be used with the kernel.
Definition: network_kernel.hpp:768
pops::Network::travel
std::tuple< int, int > travel(RasterIndex row, RasterIndex col, double time, Generator &generator) const
Travel in the network from given row and column for a given time.
Definition: network_kernel.hpp:245
pops::NetworkDispersalKernel::supports_kernel
static bool supports_kernel(const DispersalKernelType type)
Returns true if the kernel class support a given kernel type.
Definition: network_kernel.hpp:775
pops::Network::pick_random_node
static NodeId pick_random_node(const Container &nodes, Generator &generator)
Select a random node from a list of nodes.
Definition: network_kernel.hpp:697
pops::NetworkDispersalKernel::NetworkDispersalKernel
NetworkDispersalKernel(const Network< RasterIndex > &network, double min_time, double max_time)
Create kernel.
Definition: network_kernel.hpp:742
pops::Network::node_id_from_text
static NodeId node_id_from_text(const std::string &text)
Convert string to node ID.
Definition: network_kernel.hpp:424
pops::Network::ew_res_
double ew_res_
East-west resolution of the grid.
Definition: network_kernel.hpp:708
pops::Network::get_segment
SegmentView get_segment(NodeId start, NodeId end) const
Get a segment between the two given nodes.
Definition: network_kernel.hpp:624
pops::Network::get_all_nodes
std::vector< std::pair< NodeId, std::pair< RasterIndex, RasterIndex > > > get_all_nodes() const
Get all nodes as vector of all ids with their row and column.
Definition: network_kernel.hpp:284
pops::DispersalKernelType::Network
@ Network
Network spread.
pops::Network::out_of_bbox
bool out_of_bbox(double x, double y) const
Test if coordinates XY are in the bounding box.
Definition: network_kernel.hpp:114
container_contains
bool container_contains(const Container &container, const Value &value)
Return true if container contains value.
Definition: utils.hpp:46
pops::Network::Segment
std::vector< std::pair< RasterIndex, RasterIndex > > Segment
Cells connecting two nodes (segment between nodes)
Definition: network_kernel.hpp:414
pops::Network::load_segments
void load_segments(InputStream &stream, const std::set< NodeId > &node_ids)
Read segments from a stream.
Definition: network_kernel.hpp:551
pops::NetworkDispersalKernel
Dispersal kernel for dispersal over a network.
Definition: network_kernel.hpp:725
pops::Network::SegmentView
A const view of a Segment which can be iterated.
Definition: network_kernel.hpp:481
pops::DispersalKernelType
DispersalKernelType
Type of dispersal kernel.
Definition: kernel_types.hpp:53
pops::Network::nodes_by_row_col_
std::map< std::pair< RasterIndex, RasterIndex >, std::set< NodeId > > nodes_by_row_col_
Node IDs stored by row and column (multiple nodes per cell)
Definition: network_kernel.hpp:712
pops::Network::get_random_node_at
NodeId get_random_node_at(RasterIndex row, RasterIndex col, Generator &generator) const
Get a randomly selected node at a given cell.
Definition: network_kernel.hpp:190
pops::Network::cell_travel_time_
double cell_travel_time_
Time to travel through one cell.
Definition: network_kernel.hpp:710
pops::Network::segments_by_nodes_
SegmentsByNodes segments_by_nodes_
Lists of cells connecting nodes.
Definition: network_kernel.hpp:714
pops::Network::NodeMatrix
std::map< NodeId, std::vector< NodeId > > NodeMatrix
Node connections (edges)
Definition: network_kernel.hpp:412
pops
Definition: cauchy_kernel.hpp:25
pops::Network::has_node_at
bool has_node_at(RasterIndex row, RasterIndex col) const
Test if the network has a node at a given row and column.
Definition: network_kernel.hpp:211
pops::Network::NodeId
int NodeId
Type for node IDs.
Definition: network_kernel.hpp:54
pops::Network::ConstEitherWayIterator::operator*
const Container::value_type & operator*() const
Definition: network_kernel.hpp:454
pops::Network::null_network
static Network null_network()
Create an empty network not meant for futher use.
Definition: network_kernel.hpp:80
pops::NetworkDispersalKernel::operator()
std::tuple< int, int > operator()(Generator &generator, int row, int col)
Generates a new position for the spread.
Definition: network_kernel.hpp:753
pops::Network::get_node_row_col
std::pair< RasterIndex, RasterIndex > get_node_row_col(NodeId node) const
Get row and column for a node.
Definition: network_kernel.hpp:226
pops::Network::collect_statistics
Statistics collect_statistics() const
Collect statistics about the network.
Definition: network_kernel.hpp:305
pops::Network::SegmentView::end
ConstEitherWayIterator< Segment > end() const
Definition: network_kernel.hpp:498
pops::Network::Statistics
std::map< std::string, int > Statistics
Type for summary statistics.
Definition: network_kernel.hpp:55
pops::Network::dump_yaml
void dump_yaml(OutputStream &stream) const
Output network to a stream.
Definition: network_kernel.hpp:345
pops::Network::ConstEitherWayIterator::operator!=
bool operator!=(const ConstEitherWayIterator &other)
Definition: network_kernel.hpp:460
pops::Network::ConstEitherWayIterator::ConstEitherWayIterator
ConstEitherWayIterator(typename Container::const_iterator it)
Definition: network_kernel.hpp:440
pops::Network::ConstEitherWayIterator::ConstEitherWayIterator
ConstEitherWayIterator(typename Container::const_reverse_iterator it)
Definition: network_kernel.hpp:443
pops::Network::ConstEitherWayIterator::operator++
ConstEitherWayIterator & operator++()
Definition: network_kernel.hpp:446
pops::Network::SegmentView::SegmentView
SegmentView(typename Segment::const_reverse_iterator first, typename Segment::const_reverse_iterator last)
Definition: network_kernel.hpp:489
pops::Network::SegmentView::begin
ConstEitherWayIterator< Segment > begin() const
Definition: network_kernel.hpp:494
BBox::west
Number west
Definition: utils.hpp:72
pops::Network::xy_to_row_col
std::pair< RasterIndex, RasterIndex > xy_to_row_col(double x, double y) const
Convert real world coordinates to row and column in the raster grid.
Definition: network_kernel.hpp:92
pops::Network::bbox_
BBox< double > bbox_
Bounding box of the network grid in real world coordinates.
Definition: network_kernel.hpp:707
pops::Network
Network structure and algorithms.
Definition: network_kernel.hpp:51
pops::Network::SegmentsByNodes
std::map< std::pair< NodeId, NodeId >, Segment > SegmentsByNodes
Segments by nodes (edges)
Definition: network_kernel.hpp:416
BBox::south
Number south
Definition: utils.hpp:70
pops::Network::xy_to_row_col
std::pair< RasterIndex, RasterIndex > xy_to_row_col(const std::string &x, const std::string &y) const
Coverts coordinates as xy_to_row_col(double, double) but converts from strings.
Definition: network_kernel.hpp:103
pops::Network::ns_res_
double ns_res_
North-south resolution of the grid.
Definition: network_kernel.hpp:709
pops::NetworkDispersalKernel::network_
const Network< RasterIndex > & network_
Reference to the network.
Definition: network_kernel.hpp:782
pops::Network::load_nodes
void load_nodes(InputStream &stream, std::set< NodeId > &node_ids)
Read nodes from a stream.
Definition: network_kernel.hpp:515
kernel_types.hpp
Kernel types enum and helper functions.
pops::Network::Network
Network(BBox< double > bbox, double ew_res, double ns_res, double speed)
Construct empty network.
Definition: network_kernel.hpp:65
pops::Network::get_nodes_at
const std::set< NodeId > & get_nodes_at(RasterIndex row, RasterIndex col) const
Get a list of nodes at a given cell.
Definition: network_kernel.hpp:166
BBox< double >
pops::Network::node_matrix_
NodeMatrix node_matrix_
List of node neighbors by node ID (edges)
Definition: network_kernel.hpp:713
pops::Network::nodes_connected_to
const std::vector< NodeId > & nodes_connected_to(NodeId node) const
Get nodes connected by an edge to a given node.
Definition: network_kernel.hpp:643