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 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
use std::io::Write;
/// # Traits for quantities that all Entropic simulations have
pub trait Entropic
{
/// # Counter
/// how many Entropic steps were performed until now?
fn step_counter(&self) -> usize;
/// # Counter
/// * how many markov steps were performed until now?
/// * this includes steps, that were perfored to find the estimate, i.e., during wang landau
fn steps_total(&self) -> usize{
self.total_steps_accepted() + self.total_steps_rejected()
}
/// # How many steps were accepted until now?
/// * this includes steps, that were perfored to find the estimate, i.e., during wang landau
fn total_steps_accepted(&self) -> usize;
/// # How many steps were rejected until now?
/// * this includes steps, that were perfored to find the estimate, i.e., during wang landau
fn total_steps_rejected(&self) -> usize;
/// # Calculate, which fraction of steps were accepted
/// * this includes steps, that were perfored to find the estimate, i.e., during wang landau
/// * if no steps were performed, it returns `f64::NAN`
fn fraction_accepted_total(&self) -> f64 {
let total_acc = self.total_steps_accepted();
let total_steps = total_acc + self.total_steps_rejected();
if total_steps == 0 {
f64::NAN
} else {
total_acc as f64 / total_steps as f64
}
}
/// # Calculate, which fraction of steps were rejected
/// * this includes steps, that were perfored to find the estimate, i.e., during wang landau
/// * if no steps were performed, it returns `f64::NAN`
fn fraction_rejected_total(&self) -> f64 {
let total_rej = self.total_steps_rejected();
let total_steps = total_rej + self.total_steps_accepted();
if total_steps == 0 {
f64::NAN
} else {
total_rej as f64 / total_steps as f64
}
}
/// # What is the goal to reach?
fn step_goal(&self) -> usize;
/// # Checks wang landau threshold
/// * `log_f <= log_f_threshold`
fn is_finished(&self) -> bool{
self.step_counter() >= self.step_goal()
}
/// # Current (non normalized) estimate of ln(P(E))
/// * i.e., of the natural logarithm of the
/// probability density function
/// for the requested interval
/// * this is what we are doing the simulations for
fn log_density(&self) -> Vec<f64>;
/// # Current (non normalized) estimate of log10(P(E))
/// * i.e., of logarithm with base 10 of the
/// probability density function
/// for the requested interval
/// * this is what we are doing the simulations for
fn log_density_base10(&self) -> Vec<f64>{
let mut density = self.log_density();
density
.iter_mut()
.for_each(|val| *val *= std::f64::consts::LOG10_E);
density
}
/// # Current (non normalized) estimate of log_base(P(E))
/// * i.e., of logarithm with arbitrary base of the
/// probability density function
/// for the requested interval
/// * this is what we are doing the simulations for
fn log_density_base(&self, base: f64) -> Vec<f64>{
let factor = std::f64::consts::E.log(base);
let mut density = self.log_density();
density
.iter_mut()
.for_each(|val| *val *= factor);
density
}
/// Writes Information about the simulation to a file.
/// E.g. How many steps were performed.
fn write_log<W: Write>(&self, writer: W) -> Result<(), std::io::Error>;
}
/// # trait to request a reference to the current (state of the) ensemble
/// * See also [EntropicEEH](trait.EntropicEEH.html)
pub trait EntropicEnsemble<E> : Entropic
{
/// return reference to current state of ensemble
fn ensemble(&self) -> &E;
/// # returns mutable reference to ensemble
/// * If, whatever you do with the ensemble, changes the
/// energy of the current state,
/// you cannot trust the results of entropic sampling anymore
/// * use with care
unsafe fn ensemble_mut(&mut self) -> &mut E;
}
/// # trait to request the current histogram from a Entropic simulation
/// * Note: The histogram will likely be reset multiple times during a simulation
/// * See also [EntropicEEH](trait.EntropicEEH.html)
pub trait EntropicHist<Hist> : Entropic
{
/// # returns current histogram
/// * **Note**: histogram will be reset multiple times during the simulation
/// * please refere to the [papers](struct.EntropicAdaptive.html#adaptive-Entropic-1t)
fn hist(&self) -> &Hist;
}
/// # trait to request the current energy from a Entropic simulation
/// * `None` if the energy was not calculated yet
/// * See also [EntropicEEH](trait.EntropicEEH.html)
pub trait EntropicEnergy<Energy> : Entropic
{
/// returns the last accepted `Energy` calculated
/// `None` if no energy was calculated yet
fn energy(&self) -> &Energy;
}
/// Helper trait, so that you have to type less
pub trait EntropicEEH<E, Hist, Energy>
: EntropicEnergy<Energy> + EntropicEnsemble<E>
+ EntropicHist<Hist>{}
impl<A, E, Hist, Energy> EntropicEEH<E, Hist, Energy> for A
where
A: EntropicEnergy<Energy>
+ EntropicEnsemble<E>
+ EntropicHist<Hist>{}