Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/stan/optimization/lbfgs_update.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#define STAN_OPTIMIZATION_LBFGS_UPDATE_HPP

#include <stan/math/prim/fun/Eigen.hpp>
#include <boost/circular_buffer.hpp>
#include <stan/util/ring_buffer.hpp>
#include <tuple>
#include <vector>

Expand Down Expand Up @@ -72,8 +72,8 @@ class LBFGSUpdate {
**/
inline void search_direction(VectorT &pk, const VectorT &gk) const {
std::vector<Scalar> alphas(_buf.size());
typename boost::circular_buffer<UpdateT>::const_reverse_iterator buf_rit;
typename boost::circular_buffer<UpdateT>::const_iterator buf_it;
typename stan::util::ring_buffer<UpdateT>::const_reverse_iterator buf_rit;
typename stan::util::ring_buffer<UpdateT>::const_iterator buf_it;
typename std::vector<Scalar>::const_iterator alpha_it;
typename std::vector<Scalar>::reverse_iterator alpha_rit;

Expand Down Expand Up @@ -103,7 +103,7 @@ class LBFGSUpdate {
}

protected:
boost::circular_buffer<UpdateT> _buf;
stan::util::ring_buffer<UpdateT> _buf;
Scalar _gammak;
};
} // namespace optimization
Expand Down
6 changes: 3 additions & 3 deletions src/stan/services/pathfinder/single.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#include <stan/services/util/initialize.hpp>
#include <stan/services/util/create_rng.hpp>
#include <stan/services/util/duration_diff.hpp>
#include <boost/circular_buffer.hpp>
#include <stan/util/ring_buffer.hpp>
#include <tbb/parallel_for.h>
#include <tbb/concurrent_queue.h>
#include <tbb/task_group.h>
Expand Down Expand Up @@ -659,8 +659,8 @@ inline auto pathfinder_lbfgs_single(
+ std::to_string(lbfgs.logp()));
}
int ret = 0;
boost::circular_buffer<Eigen::VectorXd> param_buff(max_history_size);
boost::circular_buffer<Eigen::VectorXd> grad_buff(max_history_size);
stan::util::ring_buffer<Eigen::VectorXd> param_buff(max_history_size);
stan::util::ring_buffer<Eigen::VectorXd> grad_buff(max_history_size);
Eigen::VectorXd prev_params
= Eigen::Map<Eigen::VectorXd>(cont_vector.data(), cont_vector.size());
std::size_t history_size = 0;
Expand Down
130 changes: 130 additions & 0 deletions src/stan/util/ring_buffer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#ifndef STAN_UTIL_RING_BUFFER_HPP
#define STAN_UTIL_RING_BUFFER_HPP

#include <algorithm>
#include <cstddef>
#include <iterator>
#include <stdexcept>
#include <utility>
#include <vector>

namespace stan {
namespace util {

/** Fixed-capacity buffer that overwrites its oldest element when full. */
template <typename T>
class ring_buffer {
public:
explicit ring_buffer(size_t capacity) : buf_(capacity) {
if (capacity == 0) {
throw std::domain_error("ring_buffer capacity must be > 0");
}
}

size_t size() const { return size_; }
size_t capacity() const { return buf_.size(); }

void clear() {
start_ = 0;
size_ = 0;
}

void push_back() {
if (size_ < capacity()) {
++size_;
} else {
start_ = (start_ + 1) % capacity();
}
}

template <typename U>
void push_back(U&& value) {
push_back();
back() = std::forward<U>(value);
}

T& back() { return (*this)[size_ - 1]; }

T& operator[](size_t i) { return buf_[(start_ + i) % capacity()]; }
const T& operator[](size_t i) const {
return buf_[(start_ + i) % capacity()];
}

void rset_capacity(size_t new_capacity) {
if (new_capacity == 0) {
throw std::domain_error("ring_buffer capacity must be > 0");
}
if (new_capacity == capacity()) {
return;
}

std::vector<T> new_buf(new_capacity);
size_t keep = std::min(size_, new_capacity);
for (size_t i = 0; i < keep; ++i) {
new_buf[i] = std::move((*this)[size_ - keep + i]);
}
buf_ = std::move(new_buf);
start_ = 0;
size_ = keep;
}

class const_iterator {
public:
using iterator_category = std::bidirectional_iterator_tag;
using value_type = T;
using difference_type = std::ptrdiff_t;
using pointer = const T*;
using reference = const T&;

const_iterator() = default;
const_iterator(const ring_buffer* buffer, size_t pos)
: buffer_(buffer), pos_(pos) {}

reference operator*() const { return (*buffer_)[pos_]; }

const_iterator& operator++() {
++pos_;
return *this;
}
const_iterator operator++(int) {
const_iterator result = *this;
++*this;
return result;
}
const_iterator& operator--() {
--pos_;
return *this;
}

bool operator==(const const_iterator& other) const {
return buffer_ == other.buffer_ && pos_ == other.pos_;
}
bool operator!=(const const_iterator& other) const {
return !(*this == other);
}

private:
const ring_buffer* buffer_ = nullptr;
size_t pos_ = 0;
};

const_iterator begin() const { return const_iterator(this, 0); }
const_iterator end() const { return const_iterator(this, size_); }

using const_reverse_iterator = std::reverse_iterator<const_iterator>;
const_reverse_iterator rbegin() const {
return const_reverse_iterator(end());
}
const_reverse_iterator rend() const {
return const_reverse_iterator(begin());
}

private:
std::vector<T> buf_;
size_t start_ = 0;
size_t size_ = 0;
};

} // namespace util
} // namespace stan
#endif
8 changes: 4 additions & 4 deletions src/stan/variational/advi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#include <stan/variational/print_progress.hpp>
#include <stan/variational/families/normal_fullrank.hpp>
#include <stan/variational/families/normal_meanfield.hpp>
#include <boost/circular_buffer.hpp>
#include <stan/util/ring_buffer.hpp>
#include <algorithm>
#include <chrono>
#include <limits>
Expand Down Expand Up @@ -335,7 +335,7 @@ class advi {
// Heuristic to estimate how far to look back in rolling window
int cb_size
= static_cast<int>(std::max(0.1 * max_iterations / eval_elbo_, 2.0));
boost::circular_buffer<double> elbo_diff(cb_size);
stan::util::ring_buffer<double> elbo_diff(cb_size);

logger.info("Begin stochastic gradient ascent.");
logger.info(
Expand Down Expand Up @@ -528,10 +528,10 @@ class advi {
* @param[in] cb circular buffer with some number of values in it.
* @return median of values in circular buffer.
*/
double circ_buff_median(const boost::circular_buffer<double>& cb) const {
double circ_buff_median(const stan::util::ring_buffer<double>& cb) const {
// FIXME: naive implementation; creates a copy as a vector
std::vector<double> v;
for (boost::circular_buffer<double>::const_iterator i = cb.begin();
for (stan::util::ring_buffer<double>::const_iterator i = cb.begin();
i != cb.end(); ++i) {
v.push_back(*i);
}
Expand Down
Loading