use wanglandau::{flatness, prelude::*, rng, schedule};
#[derive(Clone)]
struct Harmonic(f64);
impl State for Harmonic {}
struct Displace;
impl<R: rand::RngCore> Move<Harmonic, R> for Displace {
fn propose(&mut self, s: &mut Harmonic, rng: &mut R) {
use rand::Rng;
s.0 += rng.random_range(-0.5..=0.5);
}
}
struct EnergyBins;
impl Macrospace<Harmonic> for EnergyBins {
type Bin = usize;
fn locate(&self, s: &Harmonic) -> usize {
let e = 0.5 * s.0 * s.0;
let idx = (e / 0.1).floor() as usize;
idx.min(99) }
fn bins(&self) -> &[usize] {
const B: &[usize] = &[
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
];
B
}
}
#[test]
fn harmonic_converges() {
let ln_f_tol = 1e-3;
let mut drv = WLDriver::new(
Harmonic(0.0), Displace, EnergyBins, Params {
..Default::default()
}, schedule::Geometric {
alpha: 0.5,
tol: ln_f_tol,
}, flatness::Fraction, rng::seeded(7), );
drv.run(100_000_000);
assert!(
drv.ln_f() < ln_f_tol,
"Algorithm failed to converge: ln_f = {}",
drv.ln_f()
);
}