use std::marker::PhantomData;
use rand_distr::Distribution;
#[cfg(feature = "serde-serialize")]
use serde::{Deserialize, Serialize};
use super::{
super::{
super::{error::MultiIntegrationError, integrator::SymplecticIntegrator, Real},
state::{
LatticeState, LatticeStateEFSyncDefault, SimulationStateLeap,
SimulationStateSynchronous,
},
},
MonteCarlo, MonteCarloDefault,
};
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
pub struct HybridMonteCarlo<State, Rng, I, const D: usize>
where
State: LatticeState<D> + Clone + ?Sized,
LatticeStateEFSyncDefault<State, D>: SimulationStateSynchronous<D>,
I: SymplecticIntegrator<
LatticeStateEFSyncDefault<State, D>,
SimulationStateLeap<LatticeStateEFSyncDefault<State, D>, D>,
D,
>,
Rng: rand::Rng,
{
internal: HybridMonteCarloInternal<LatticeStateEFSyncDefault<State, D>, I, D>,
rng: Rng,
}
impl<State, Rng, I, const D: usize> HybridMonteCarlo<State, Rng, I, D>
where
State: LatticeState<D> + Clone + ?Sized,
LatticeStateEFSyncDefault<State, D>: SimulationStateSynchronous<D>,
I: SymplecticIntegrator<
LatticeStateEFSyncDefault<State, D>,
SimulationStateLeap<LatticeStateEFSyncDefault<State, D>, D>,
D,
>,
Rng: rand::Rng,
{
getter!(
pub const rng() -> Rng
);
project!(
pub const internal.integrator() -> &I
);
project_mut!(
pub internal.integrator_mut() -> &mut I
);
project!(
pub const internal.delta_t() -> Real
);
project!(
pub const internal.number_of_steps() -> usize
);
pub const fn new(delta_t: Real, number_of_steps: usize, integrator: I, rng: Rng) -> Self {
Self {
internal: HybridMonteCarloInternal::<LatticeStateEFSyncDefault<State, D>, I, D>::new(
delta_t,
number_of_steps,
integrator,
),
rng,
}
}
pub fn rng_mut(&mut self) -> &mut Rng {
&mut self.rng
}
#[allow(clippy::missing_const_for_fn)] pub fn rng_owned(self) -> Rng {
self.rng
}
}
impl<State, Rng, I, const D: usize> AsRef<Rng> for HybridMonteCarlo<State, Rng, I, D>
where
State: LatticeState<D> + Clone + ?Sized,
LatticeStateEFSyncDefault<State, D>: SimulationStateSynchronous<D>,
I: SymplecticIntegrator<
LatticeStateEFSyncDefault<State, D>,
SimulationStateLeap<LatticeStateEFSyncDefault<State, D>, D>,
D,
>,
Rng: rand::Rng,
{
fn as_ref(&self) -> &Rng {
self.rng()
}
}
impl<State, Rng, I, const D: usize> AsMut<Rng> for HybridMonteCarlo<State, Rng, I, D>
where
State: LatticeState<D> + Clone + ?Sized,
LatticeStateEFSyncDefault<State, D>: SimulationStateSynchronous<D>,
I: SymplecticIntegrator<
LatticeStateEFSyncDefault<State, D>,
SimulationStateLeap<LatticeStateEFSyncDefault<State, D>, D>,
D,
>,
Rng: rand::Rng,
{
fn as_mut(&mut self) -> &mut Rng {
self.rng_mut()
}
}
impl<State, Rng, I, const D: usize> MonteCarlo<State, D> for HybridMonteCarlo<State, Rng, I, D>
where
State: LatticeState<D> + Clone + ?Sized,
LatticeStateEFSyncDefault<State, D>: SimulationStateSynchronous<D>,
I: SymplecticIntegrator<
LatticeStateEFSyncDefault<State, D>,
SimulationStateLeap<LatticeStateEFSyncDefault<State, D>, D>,
D,
>,
Rng: rand::Rng,
{
type Error = MultiIntegrationError<I::Error>;
fn next_element(&mut self, state: State) -> Result<State, Self::Error> {
let state_internal =
LatticeStateEFSyncDefault::<State, D>::new_random_e_state(state, self.rng_mut());
self.internal
.next_element_default(state_internal, &mut self.rng)
.map(|el| el.state_owned())
}
}
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
struct HybridMonteCarloInternal<State, I, const D: usize>
where
State: SimulationStateSynchronous<D> + ?Sized,
I: SymplecticIntegrator<State, SimulationStateLeap<State, D>, D>,
{
delta_t: Real,
number_of_steps: usize,
integrator: I,
#[cfg_attr(feature = "serde-serialize", serde(skip))]
_phantom: PhantomData<State>,
}
impl<State, I, const D: usize> HybridMonteCarloInternal<State, I, D>
where
State: SimulationStateSynchronous<D> + ?Sized,
I: SymplecticIntegrator<State, SimulationStateLeap<State, D>, D>,
{
getter!(
pub const,
integrator,
I
);
getter_copy!(
pub const,
delta_t,
Real
);
getter_copy!(
pub const,
number_of_steps,
usize
);
pub const fn new(delta_t: Real, number_of_steps: usize, integrator: I) -> Self {
Self {
delta_t,
number_of_steps,
integrator,
_phantom: PhantomData,
}
}
pub fn integrator_mut(&mut self) -> &mut I {
&mut self.integrator
}
}
impl<State, I, const D: usize> AsRef<I> for HybridMonteCarloInternal<State, I, D>
where
State: SimulationStateSynchronous<D> + ?Sized,
I: SymplecticIntegrator<State, SimulationStateLeap<State, D>, D>,
{
fn as_ref(&self) -> &I {
self.integrator()
}
}
impl<State, I, const D: usize> AsMut<I> for HybridMonteCarloInternal<State, I, D>
where
State: SimulationStateSynchronous<D> + ?Sized,
I: SymplecticIntegrator<State, SimulationStateLeap<State, D>, D>,
{
fn as_mut(&mut self) -> &mut I {
self.integrator_mut()
}
}
impl<State, I, const D: usize> MonteCarloDefault<State, D> for HybridMonteCarloInternal<State, I, D>
where
State: SimulationStateSynchronous<D> + ?Sized,
I: SymplecticIntegrator<State, SimulationStateLeap<State, D>, D>,
{
type Error = MultiIntegrationError<I::Error>;
fn potential_next_element<Rng>(
&mut self,
state: &State,
_rng: &mut Rng,
) -> Result<State, Self::Error>
where
Rng: rand::Rng + ?Sized,
{
state.simulate_symplectic_n_auto(&self.integrator, self.delta_t, self.number_of_steps)
}
fn probability_of_replacement(old_state: &State, new_state: &State) -> Real {
(old_state.hamiltonian_total() - new_state.hamiltonian_total())
.exp()
.min(1_f64)
.max(0_f64)
}
}
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
pub struct HybridMonteCarloDiagnostic<State, Rng, I, const D: usize>
where
State: LatticeState<D> + Clone + ?Sized,
LatticeStateEFSyncDefault<State, D>: SimulationStateSynchronous<D>,
I: SymplecticIntegrator<
LatticeStateEFSyncDefault<State, D>,
SimulationStateLeap<LatticeStateEFSyncDefault<State, D>, D>,
D,
>,
Rng: rand::Rng,
{
internal: HybridMonteCarloInternalDiagnostics<LatticeStateEFSyncDefault<State, D>, I, D>,
rng: Rng,
}
impl<State, Rng, I, const D: usize> HybridMonteCarloDiagnostic<State, Rng, I, D>
where
State: LatticeState<D> + Clone + ?Sized,
LatticeStateEFSyncDefault<State, D>: SimulationStateSynchronous<D>,
I: SymplecticIntegrator<
LatticeStateEFSyncDefault<State, D>,
SimulationStateLeap<LatticeStateEFSyncDefault<State, D>, D>,
D,
>,
Rng: rand::Rng,
{
getter!(
pub const,
rng,
Rng
);
project!(
pub const,
integrator,
internal,
&I
);
project_mut!(
pub,
integrator_mut,
internal,
&mut I
);
project!(
pub const,
delta_t,
internal,
Real
);
project!(
pub const,
number_of_steps,
internal,
usize
);
pub const fn new(delta_t: Real, number_of_steps: usize, integrator: I, rng: Rng) -> Self {
Self {
internal: HybridMonteCarloInternalDiagnostics::<
LatticeStateEFSyncDefault<State, D>,
I,
D,
>::new(delta_t, number_of_steps, integrator),
rng,
}
}
pub fn rng_mut(&mut self) -> &mut Rng {
&mut self.rng
}
pub const fn prob_replace_last(&self) -> Real {
self.internal.prob_replace_last()
}
pub const fn has_replace_last(&self) -> bool {
self.internal.has_replace_last()
}
#[allow(clippy::missing_const_for_fn)] pub fn rng_owned(self) -> Rng {
self.rng
}
}
impl<State, Rng, I, const D: usize> AsRef<Rng> for HybridMonteCarloDiagnostic<State, Rng, I, D>
where
State: LatticeState<D> + Clone + ?Sized,
LatticeStateEFSyncDefault<State, D>: SimulationStateSynchronous<D>,
I: SymplecticIntegrator<
LatticeStateEFSyncDefault<State, D>,
SimulationStateLeap<LatticeStateEFSyncDefault<State, D>, D>,
D,
>,
Rng: rand::Rng,
{
fn as_ref(&self) -> &Rng {
self.rng()
}
}
impl<State, Rng, I, const D: usize> AsMut<Rng> for HybridMonteCarloDiagnostic<State, Rng, I, D>
where
State: LatticeState<D> + Clone + ?Sized,
LatticeStateEFSyncDefault<State, D>: SimulationStateSynchronous<D>,
I: SymplecticIntegrator<
LatticeStateEFSyncDefault<State, D>,
SimulationStateLeap<LatticeStateEFSyncDefault<State, D>, D>,
D,
>,
Rng: rand::Rng,
{
fn as_mut(&mut self) -> &mut Rng {
self.rng_mut()
}
}
impl<State, Rng, I, const D: usize> MonteCarlo<State, D>
for HybridMonteCarloDiagnostic<State, Rng, I, D>
where
State: LatticeState<D> + Clone + ?Sized,
LatticeStateEFSyncDefault<State, D>: SimulationStateSynchronous<D>,
I: SymplecticIntegrator<
LatticeStateEFSyncDefault<State, D>,
SimulationStateLeap<LatticeStateEFSyncDefault<State, D>, D>,
D,
>,
Rng: rand::Rng,
{
type Error = MultiIntegrationError<I::Error>;
fn next_element(&mut self, state: State) -> Result<State, Self::Error> {
let state_internal =
LatticeStateEFSyncDefault::<State, D>::new_random_e_state(state, self.rng_mut());
self.internal
.next_element_default(state_internal, &mut self.rng)
.map(|el| el.state_owned())
}
}
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
struct HybridMonteCarloInternalDiagnostics<State, I, const D: usize>
where
State: SimulationStateSynchronous<D> + ?Sized,
I: SymplecticIntegrator<State, SimulationStateLeap<State, D>, D>,
{
delta_t: Real,
number_of_steps: usize,
integrator: I,
has_replace_last: bool,
prob_replace_last: Real,
#[cfg_attr(feature = "serde-serialize", serde(skip))]
_phantom: PhantomData<State>,
}
impl<State, I, const D: usize> HybridMonteCarloInternalDiagnostics<State, I, D>
where
State: SimulationStateSynchronous<D> + ?Sized,
I: SymplecticIntegrator<State, SimulationStateLeap<State, D>, D>,
{
getter!(
pub const,
integrator,
I
);
getter_copy!(
pub const,
delta_t,
Real
);
getter_copy!(
pub const,
number_of_steps,
usize
);
pub const fn new(delta_t: Real, number_of_steps: usize, integrator: I) -> Self {
Self {
delta_t,
number_of_steps,
integrator,
has_replace_last: false,
prob_replace_last: 0_f64,
_phantom: PhantomData,
}
}
pub const fn prob_replace_last(&self) -> Real {
self.prob_replace_last
}
pub const fn has_replace_last(&self) -> bool {
self.has_replace_last
}
pub fn integrator_mut(&mut self) -> &mut I {
&mut self.integrator
}
}
impl<State, I, const D: usize> AsRef<I> for HybridMonteCarloInternalDiagnostics<State, I, D>
where
State: SimulationStateSynchronous<D> + ?Sized,
I: SymplecticIntegrator<State, SimulationStateLeap<State, D>, D>,
{
fn as_ref(&self) -> &I {
self.integrator()
}
}
impl<State, I, const D: usize> AsMut<I> for HybridMonteCarloInternalDiagnostics<State, I, D>
where
State: SimulationStateSynchronous<D> + ?Sized,
I: SymplecticIntegrator<State, SimulationStateLeap<State, D>, D>,
{
fn as_mut(&mut self) -> &mut I {
self.integrator_mut()
}
}
impl<State, I, const D: usize> MonteCarloDefault<State, D>
for HybridMonteCarloInternalDiagnostics<State, I, D>
where
State: SimulationStateSynchronous<D> + ?Sized,
I: SymplecticIntegrator<State, SimulationStateLeap<State, D>, D>,
{
type Error = MultiIntegrationError<I::Error>;
fn potential_next_element<Rng>(
&mut self,
state: &State,
_rng: &mut Rng,
) -> Result<State, Self::Error>
where
Rng: rand::Rng + ?Sized,
{
state.simulate_symplectic_n_auto(&self.integrator, self.delta_t, self.number_of_steps)
}
fn probability_of_replacement(old_state: &State, new_state: &State) -> Real {
(old_state.hamiltonian_total() - new_state.hamiltonian_total())
.exp()
.min(1_f64)
.max(0_f64)
}
fn next_element_default<Rng>(
&mut self,
state: State,
rng: &mut Rng,
) -> Result<State, Self::Error>
where
Rng: rand::Rng + ?Sized,
{
let potential_next = self.potential_next_element(&state, rng)?;
let proba = Self::probability_of_replacement(&state, &potential_next)
.min(1_f64)
.max(0_f64);
self.prob_replace_last = proba;
let d = rand::distributions::Bernoulli::new(proba).unwrap();
if d.sample(rng) {
self.has_replace_last = true;
Ok(potential_next)
}
else {
self.has_replace_last = false;
Ok(state)
}
}
}