This documentation is automatically generated by online-judge-tools/verification-helper
#include "heuristic/exponential_dist_sampler.hpp"
母数 $\lambda = 1$ の指数分布を模擬するサンプラー.
典型的な用途として,擬似焼きなまし法 (simulated annealing, SA) の遷移判定を(指数関数や対数関数の計算を毎回行うことなく)高速に行える.
constexpr int D = 18;
const ExponentialDistSampler<D> eds; // 2^D 個のサンプルを前計算
// 下位 D bit がランダムに分布した mask を与えると x ~ Ex(1) をサンプル
uint32_t mask;
double x = eds.sample(mask);
double dx;
double T;
// コストの変化が abs(dx), 温度 T のとき焼きなまし法の遷移を受理するか確率的に判定
bool upd = eds.check_sa(abs(dx), T, mask);
#pragma once
#include <cmath>
#include <cstdint>
#include <array>
template <int D> struct ExponentialDistSampler {
std::array<double, (1 << D)> minuslogps;
constexpr ExponentialDistSampler() {
for (int i = 0; i < (1 << D); ++i) minuslogps.at(i) = -log((0.5 + i) / (1 << D));
}
double sample(uint32_t random_mask) const {
return minuslogps.at(random_mask & ((1 << D) - 1));
}
// p ~ U(0, 1) => -log(p) ~ Ex(1)
// P[exp(-|dx| / T) >= p] = P[|dx| <= -log(p) * T]
bool check_sa(double abs_dx, double T, uint32_t random_mask) const {
return abs_dx <= minuslogps.at(random_mask & ((1 << D) - 1)) * T;
}
};
// const ExponentialDistSampler<16> log_ps;
#line 2 "heuristic/exponential_dist_sampler.hpp"
#include <cmath>
#include <cstdint>
#include <array>
template <int D> struct ExponentialDistSampler {
std::array<double, (1 << D)> minuslogps;
constexpr ExponentialDistSampler() {
for (int i = 0; i < (1 << D); ++i) minuslogps.at(i) = -log((0.5 + i) / (1 << D));
}
double sample(uint32_t random_mask) const {
return minuslogps.at(random_mask & ((1 << D) - 1));
}
// p ~ U(0, 1) => -log(p) ~ Ex(1)
// P[exp(-|dx| / T) >= p] = P[|dx| <= -log(p) * T]
bool check_sa(double abs_dx, double T, uint32_t random_mask) const {
return abs_dx <= minuslogps.at(random_mask & ((1 << D) - 1)) * T;
}
};
// const ExponentialDistSampler<16> log_ps;