Microsimulation API
/home/marcle/src/R/microsimulation/src/pqueue.cpp
Go to the documentation of this file.
1 #include<Rcpp.h>
2 namespace ssim {
3 
4  using namespace Rcpp;
5 
6  struct pqueueElement {
7  double priority;
8  long _order;
9  bool active;
10  SEXP event;
11  pqueueElement(double priority, long order, bool active, SEXP event)
12  : priority(priority), _order(order), active(active), event(event) { }
13  virtual ~pqueueElement() = default;
14  };
15 
17  bool smaller;
18  pqueueElementComparator(bool smaller = true) : smaller(smaller) {}
19  bool operator()(pqueueElement const& msg1, pqueueElement const& msg2) const {
20  return (smaller ? msg1.priority > msg2.priority : msg1.priority < msg2.priority) ||
21  (msg1.priority == msg2.priority && msg1._order > msg2._order);
22  }
23  };
24 
25  class pqueue {
26  private:
27  std::vector<pqueueElement> _elements;
31  using size_type = std::vector<pqueueElement>::size_type;
32  public:
33  explicit pqueue(bool smaller = true) {
34  _compare = pqueueElementComparator(smaller);
35  _entryOrder = 0;
36  _anyCancelled = false;
37  }
41  void pushElement(pqueueElement element)
42  {
43  _elements.push_back(std::move(element));
44  std::push_heap(_elements.begin(), _elements.end(), _compare);
45  }
46  void push(double priority, SEXP event)
47  {
48  pqueueElement element(priority, _entryOrder, true, event);
49  pushElement(std::move(element));
50  // _elements.push_back(std::move(element));
51  // std::push_heap(_elements.begin(), _elements.end(), _compare);
52  _entryOrder++;
53  }
59  {
60  try {
61  if (empty()) {
62  throw std::length_error("Empty priority queue");
63  }
64  while(!_elements.empty()) {
65  std::pop_heap(_elements.begin(), _elements.end(), _compare);
66  pqueueElement result = std::move(_elements.back());
67  _elements.pop_back();
68  if (result.active)
69  return result; // change: std::move *not* used here
70  }
71  } catch(std::exception &ex) {
72  forward_exception_to_r(ex);
73  } catch(...) {
74  ::Rf_error("c++ exception (unknown reason)");
75  }
76  return _elements[0]; // never called (prevents -Wreturn-type warning)
77  }
81  List pop() {
82  pqueueElement element = std::move(popElement());
83  return List::create(_["priority"]=element.priority, _["event"]=element.event);
84  }
88  bool empty() {
89  if (_elements.empty()) return true; // empty queue
90  else if (!_anyCancelled) return false; // queue not empty and no cancelled events
91  else { // loop through to see if any of the elements are active
92  for(size_type i=0; i<_elements.size(); i++)
93  if(_elements[i].active) return false; // at least one active events
94  return true; // no active events
95  }
96  }
100  void clear () {
101  _elements.clear(); // assumes that elements are safe pointers
102  }
106  void cancel(Rcpp::Function predicate) {
107  if (!empty())
108  for(size_type i=0; i<_elements.size(); i++) {
109  if (as<bool>(predicate(_elements[i].event)))
110  _elements[i].active = false;
111  }
112  _anyCancelled = true;
113  }
118  template<class F>
119  void for_each(F f, bool remake = false) {
120  std::for_each(_elements.begin(), _elements.end(), f);
121  if (remake)
122  std::make_heap(_elements.begin(), _elements.end(), _compare);
123  }
124  virtual ~pqueue() = default;
125  };
126 
127  RcppExport
128  SEXP pqueue__new(SEXP _lower) {
129  bool lower = as<bool>(_lower);
130  Rcpp::XPtr<pqueue> ptr(new pqueue(lower));
131  return wrap(ptr);
132  }
133  RcppExport
134  SEXP pqueue__push(SEXP _ptr, SEXP _priority, SEXP event) {
135  XPtr<pqueue> ptr = as<XPtr<pqueue> >(_ptr);
136  double priority = as<double>(_priority);
137  ptr->push(priority, event);
138  return R_NilValue;
139  }
140  RcppExport
141  SEXP pqueue__pop(SEXP _ptr) {
142  XPtr<pqueue> ptr = as<XPtr<pqueue> >(_ptr);
143  return wrap(ptr->pop());
144  }
145  RcppExport
146  SEXP pqueue__cancel(SEXP _ptr, SEXP _predicate) {
147  XPtr<pqueue> ptr = as<XPtr<pqueue> >(_ptr);
148  Function predicate = as<Function>(_predicate);
149  ptr->cancel(predicate);
150  return R_NilValue;
151  }
152  RcppExport
153  SEXP pqueue__empty(SEXP _ptr) {
154  XPtr<pqueue> ptr = as<XPtr<pqueue> >(_ptr);
155  return wrap(ptr->empty());
156  }
157  RcppExport
158  SEXP pqueue__clear(SEXP _ptr) {
159  XPtr<pqueue> ptr = as<XPtr<pqueue> >(_ptr);
160  ptr->clear();
161  return R_NilValue;
162  }
163 
164 } // namespace ssim
ssim::pqueue__clear
RcppExport SEXP pqueue__clear(SEXP _ptr)
Definition: pqueue.cpp:158
ssim::pqueue::pushElement
void pushElement(pqueueElement element)
Definition: pqueue.cpp:41
ssim::pqueue::for_each
void for_each(F f, bool remake=false)
Definition: pqueue.cpp:119
ssim::pqueue__cancel
RcppExport SEXP pqueue__cancel(SEXP _ptr, SEXP _predicate)
Definition: pqueue.cpp:146
ssim::pqueueElement::priority
double priority
Definition: pqueue.cpp:7
ssim::pqueueElementComparator::pqueueElementComparator
pqueueElementComparator(bool smaller=true)
Definition: pqueue.cpp:18
Rcpp::wrap
SEXP wrap(const std::vector< std::pair< T1, T2 > > v)
ssim::pqueueElement::pqueueElement
pqueueElement(double priority, long order, bool active, SEXP event)
Definition: pqueue.cpp:11
ssim::pqueueElement::_order
long _order
Definition: pqueue.cpp:8
ssim::pqueue::pop
List pop()
Definition: pqueue.cpp:81
ssim::pqueue::_entryOrder
long _entryOrder
Definition: pqueue.cpp:29
ssim::pqueue::push
void push(double priority, SEXP event)
Definition: pqueue.cpp:46
ssim::pqueue::popElement
pqueueElement popElement()
Definition: pqueue.cpp:58
ssim::pqueueElement::active
bool active
Definition: pqueue.cpp:9
ssim::pqueueElement::event
SEXP event
Definition: pqueue.cpp:10
ssim::pqueue__pop
RcppExport SEXP pqueue__pop(SEXP _ptr)
Definition: pqueue.cpp:141
ssim::pqueue::pqueue
pqueue(bool smaller=true)
Definition: pqueue.cpp:33
ssim::pqueueElementComparator::smaller
bool smaller
Definition: pqueue.cpp:17
ssim::pqueue::_compare
pqueueElementComparator _compare
Definition: pqueue.cpp:28
ssim::pqueue::cancel
void cancel(Rcpp::Function predicate)
Definition: pqueue.cpp:106
ssim::pqueue::empty
bool empty()
Definition: pqueue.cpp:88
ssim::pqueue__new
RcppExport SEXP pqueue__new(SEXP _lower)
Definition: pqueue.cpp:128
ssim::pqueueElementComparator
Definition: pqueue.cpp:16
ssim::pqueue::_anyCancelled
bool _anyCancelled
Definition: pqueue.cpp:30
ssim::pqueue::_elements
std::vector< pqueueElement > _elements
Definition: pqueue.cpp:27
ssim
name space for the Siena simulator.
Definition: microsimulation.cc:3
ssim::pqueue::size_type
std::vector< pqueueElement >::size_type size_type
Definition: pqueue.cpp:31
ssim::pqueueElement
Definition: pqueue.cpp:6
ssim::pqueue__push
RcppExport SEXP pqueue__push(SEXP _ptr, SEXP _priority, SEXP event)
Definition: pqueue.cpp:134
ssim::pqueue::clear
void clear()
Definition: pqueue.cpp:100
Rcpp
Definition: microsimulation.h:101
ssim::pqueue
Definition: pqueue.cpp:25
ssim::pqueueElementComparator::operator()
bool operator()(pqueueElement const &msg1, pqueueElement const &msg2) const
Definition: pqueue.cpp:19
ssim::pqueue__empty
RcppExport SEXP pqueue__empty(SEXP _ptr)
Definition: pqueue.cpp:153