Nyaan's Library

This documentation is automatically generated by online-judge-tools/verification-helper

View on GitHub

:heavy_check_mark: Simulated Annealing
(marathon/simulated-annealing.hpp)

テンプレート

using score_t = double;
struct Input {
  Input() = default;
  void scan() {}
};
struct State {
  struct Diff {
    const State *st;
    Diff() = default;
    Diff(const State &state) : st(&state) {}
    double diff() const {}
  };

  State() = default;
  State(const Input &input) {}
  void update(const Diff &b) {}
  void undo(const Diff &) {}
  score_t score() const {}
  bool operator>(const State &s) { return score() > s.score(); };
  void dump() {}
};
using SA = Simulated_Annealing<Input, State, typename State::Diff>;

Depends on

Verified with

Code

#pragma once

#include "../misc/timer.hpp"
#include "log_table.hpp"

template <typename Input, typename State, typename Diff>
struct Simulated_Annealing {
 private:
  log_table rand_log;
  double end_time, inv_time, cur_time;
  double start_temp, diff_temp, cur_temp;
  Timer *timer;

  void set_time(double start_time) {
    inv_time = 1.0 / (end_time - start_time);
    cur_time = start_time;
  }
  void set_temp() {
    cur_temp = max(0.0, start_temp - cur_time * diff_temp * inv_time);
  }

 public:
  Simulated_Annealing(double _end_time, double _start_temp, double _end_temp,
                      Timer *_timer = nullptr)
      : end_time(_end_time),
        start_temp(_start_temp),
        diff_temp(_start_temp - _end_temp),
        timer(_timer) {
    if (timer == nullptr) timer = new Timer;
    set_time(timer->elapsed());
    set_temp();
  }

  void reset() { timer->reset(); }

  State run(const Input &input) {
    State st(input);
    for (int iter = 0;; iter++) {
      if ((iter & 0xFF) == 0) {
        st.dump();
        if ((cur_time = timer->elapsed()) > end_time) break;
        set_temp();
      }
      Diff d(st);
      if (d.diff() > cur_temp * rand_log.l[iter & 0xFFFF]) {
        st.update(d);
      } else {
        st.undo(d);
      }
    }
    return st;
  }

  decltype(State().score()) test(const vector<string> &filenames) {
    decltype(State().score()) scores = 0.0;
    for (auto &filename : filenames) {
      timer->reset();
      ifstream is(filename);
      cin.rdbuf(is.rdbuf());
      Input input;
      input.scan();
      auto res = run(input);
      scores += res.score();
    }
    return scores;
  }
};

/**
 * @brief Simulated Annealing
 * @docs docs/marathon/simulated-annealing.md
 */
#line 2 "marathon/simulated-annealing.hpp"

#line 2 "misc/timer.hpp"

#include <chrono>
using namespace std;

struct Timer {
  chrono::high_resolution_clock::time_point st;

  Timer() { reset(); }
  void reset() { st = chrono::high_resolution_clock::now(); }

  long long elapsed() {
    auto ed = chrono::high_resolution_clock::now();
    return chrono::duration_cast<chrono::milliseconds>(ed - st).count();
  }
  long long operator()() { return elapsed(); }
};
#line 2 "marathon/log_table.hpp"

struct log_table {
  static constexpr int M = 65536;
  static constexpr int mask = M - 1;
  double l[M];
  log_table() : l() {
    unsigned long long x = 88172645463325252ULL;
    double log_u64max = log(2) * 64;
    for (int i = 0; i < M; i++) {
      x = x ^ (x << 7);
      x = x ^ (x >> 9);
      l[i] = log(double(x)) - log_u64max;
    }
  }
  double operator()(int i) const { return l[i & mask]; }
};
#line 5 "marathon/simulated-annealing.hpp"

template <typename Input, typename State, typename Diff>
struct Simulated_Annealing {
 private:
  log_table rand_log;
  double end_time, inv_time, cur_time;
  double start_temp, diff_temp, cur_temp;
  Timer *timer;

  void set_time(double start_time) {
    inv_time = 1.0 / (end_time - start_time);
    cur_time = start_time;
  }
  void set_temp() {
    cur_temp = max(0.0, start_temp - cur_time * diff_temp * inv_time);
  }

 public:
  Simulated_Annealing(double _end_time, double _start_temp, double _end_temp,
                      Timer *_timer = nullptr)
      : end_time(_end_time),
        start_temp(_start_temp),
        diff_temp(_start_temp - _end_temp),
        timer(_timer) {
    if (timer == nullptr) timer = new Timer;
    set_time(timer->elapsed());
    set_temp();
  }

  void reset() { timer->reset(); }

  State run(const Input &input) {
    State st(input);
    for (int iter = 0;; iter++) {
      if ((iter & 0xFF) == 0) {
        st.dump();
        if ((cur_time = timer->elapsed()) > end_time) break;
        set_temp();
      }
      Diff d(st);
      if (d.diff() > cur_temp * rand_log.l[iter & 0xFFFF]) {
        st.update(d);
      } else {
        st.undo(d);
      }
    }
    return st;
  }

  decltype(State().score()) test(const vector<string> &filenames) {
    decltype(State().score()) scores = 0.0;
    for (auto &filename : filenames) {
      timer->reset();
      ifstream is(filename);
      cin.rdbuf(is.rdbuf());
      Input input;
      input.scan();
      auto res = run(input);
      scores += res.score();
    }
    return scores;
  }
};

/**
 * @brief Simulated Annealing
 * @docs docs/marathon/simulated-annealing.md
 */
Back to top page