31 : relative_tolerance_(relative_tolerance), window_(window) {
32 if (!(relative_tolerance > 0.0)) {
33 throw std::invalid_argument(
34 "ConvergenceWindow: the relative tolerance must be positive, got " +
35 std::to_string(relative_tolerance));
38 throw std::invalid_argument(
"ConvergenceWindow: the window must be at least one "
40 std::to_string(window));
46 history_.push_back(value);
55 if (
static_cast<int>(history_.size()) <= window_) {
58 const Real current = history_.back();
61 for (
int step = 1; step <= window_; step++) {
62 const Real earlier = history_[history_.size() - 1 -
static_cast<std::size_t
>(step)];
63 if (std::abs(current - earlier) / scale >= relative_tolerance_) {
70 [[nodiscard]]
const std::vector<Real>&
history()
const {
75 return static_cast<int>(history_.size());
80 const std::size_t start = history_.size() >
static_cast<std::size_t
>(count)
81 ? history_.size() -
static_cast<std::size_t
>(count)
83 return std::vector<Real>(history_.begin() +
static_cast<std::ptrdiff_t
>(start),
96 [[nodiscard]]
static std::string
history_text(
const std::vector<Real>& values) {
98 for (std::size_t index = 0; index < values.size(); index++) {
99 text += (index == 0 ?
"" :
", ") + std::to_string(values[index]);
105 Real relative_tolerance_;
107 std::vector<Real> history_;
static std::string history_text(const std::vector< Real > &values)
std::string recent_history_text(int count=5) const
The last count values, oldest first, as "a, b, c" with six decimals each.
ConvergenceWindow(Real relative_tolerance, int window)
bool has_converged() const
void record(Real value)
The objective at the end of one more step.
std::vector< Real > recent_history(int count=5) const
The last count values, oldest first.
int number_of_steps() const
const std::vector< Real > & history() const
constexpr double relative_change_scale_floor