1use std::marker::PhantomData;
35
36use rand_distr::Distribution;
37#[cfg(feature = "serde-serialize")]
38use serde::{Deserialize, Serialize};
39
40use super::{
41 super::{
42 super::{error::MultiIntegrationError, integrator::SymplecticIntegrator, Real},
43 state::{
44 LatticeState, LatticeStateEFSyncDefault, SimulationStateLeap,
45 SimulationStateSynchronous,
46 },
47 },
48 MonteCarlo, MonteCarloDefault,
49};
50
51#[derive(Clone, Debug, PartialEq)]
63#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
64pub struct HybridMonteCarlo<State, Rng, I, const D: usize>
65where
66 State: LatticeState<D> + Clone + ?Sized,
67 LatticeStateEFSyncDefault<State, D>: SimulationStateSynchronous<D>,
68 I: SymplecticIntegrator<
69 LatticeStateEFSyncDefault<State, D>,
70 SimulationStateLeap<LatticeStateEFSyncDefault<State, D>, D>,
71 D,
72 >,
73 Rng: rand::Rng,
74{
75 internal: HybridMonteCarloInternal<LatticeStateEFSyncDefault<State, D>, I, D>,
76 rng: Rng,
77}
78
79impl<State, Rng, I, const D: usize> HybridMonteCarlo<State, Rng, I, D>
80where
81 State: LatticeState<D> + Clone + ?Sized,
82 LatticeStateEFSyncDefault<State, D>: SimulationStateSynchronous<D>,
83 I: SymplecticIntegrator<
84 LatticeStateEFSyncDefault<State, D>,
85 SimulationStateLeap<LatticeStateEFSyncDefault<State, D>, D>,
86 D,
87 >,
88 Rng: rand::Rng,
89{
90 getter!(
91 pub const rng() -> Rng
93 );
94
95 project!(
96 pub const internal.integrator() -> &I
98 );
99
100 project_mut!(
101 pub internal.integrator_mut() -> &mut I
103 );
104
105 project!(
106 pub const internal.delta_t() -> Real
108 );
109
110 project!(
111 pub const internal.number_of_steps() -> usize
113 );
114
115 pub const fn new(delta_t: Real, number_of_steps: usize, integrator: I, rng: Rng) -> Self {
121 Self {
122 internal: HybridMonteCarloInternal::<LatticeStateEFSyncDefault<State, D>, I, D>::new(
123 delta_t,
124 number_of_steps,
125 integrator,
126 ),
127 rng,
128 }
129 }
130
131 pub fn rng_mut(&mut self) -> &mut Rng {
133 &mut self.rng
134 }
135
136 #[allow(clippy::missing_const_for_fn)] pub fn rng_owned(self) -> Rng {
139 self.rng
140 }
141}
142
143impl<State, Rng, I, const D: usize> AsRef<Rng> for HybridMonteCarlo<State, Rng, I, D>
144where
145 State: LatticeState<D> + Clone + ?Sized,
146 LatticeStateEFSyncDefault<State, D>: SimulationStateSynchronous<D>,
147 I: SymplecticIntegrator<
148 LatticeStateEFSyncDefault<State, D>,
149 SimulationStateLeap<LatticeStateEFSyncDefault<State, D>, D>,
150 D,
151 >,
152 Rng: rand::Rng,
153{
154 fn as_ref(&self) -> &Rng {
155 self.rng()
156 }
157}
158
159impl<State, Rng, I, const D: usize> AsMut<Rng> for HybridMonteCarlo<State, Rng, I, D>
160where
161 State: LatticeState<D> + Clone + ?Sized,
162 LatticeStateEFSyncDefault<State, D>: SimulationStateSynchronous<D>,
163 I: SymplecticIntegrator<
164 LatticeStateEFSyncDefault<State, D>,
165 SimulationStateLeap<LatticeStateEFSyncDefault<State, D>, D>,
166 D,
167 >,
168 Rng: rand::Rng,
169{
170 fn as_mut(&mut self) -> &mut Rng {
171 self.rng_mut()
172 }
173}
174
175impl<State, Rng, I, const D: usize> MonteCarlo<State, D> for HybridMonteCarlo<State, Rng, I, D>
176where
177 State: LatticeState<D> + Clone + ?Sized,
178 LatticeStateEFSyncDefault<State, D>: SimulationStateSynchronous<D>,
179 I: SymplecticIntegrator<
180 LatticeStateEFSyncDefault<State, D>,
181 SimulationStateLeap<LatticeStateEFSyncDefault<State, D>, D>,
182 D,
183 >,
184 Rng: rand::Rng,
185{
186 type Error = MultiIntegrationError<I::Error>;
187
188 fn next_element(&mut self, state: State) -> Result<State, Self::Error> {
189 let state_internal =
190 LatticeStateEFSyncDefault::<State, D>::new_random_e_state(state, self.rng_mut());
191 self.internal
192 .next_element_default(state_internal, &mut self.rng)
193 .map(|el| el.state_owned())
194 }
195}
196
197#[derive(Clone, Debug, PartialEq)]
199#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
200struct HybridMonteCarloInternal<State, I, const D: usize>
201where
202 State: SimulationStateSynchronous<D> + ?Sized,
203 I: SymplecticIntegrator<State, SimulationStateLeap<State, D>, D>,
204{
205 delta_t: Real,
207 number_of_steps: usize,
209 integrator: I,
211 #[cfg_attr(feature = "serde-serialize", serde(skip))]
213 _phantom: PhantomData<State>,
214}
215
216impl<State, I, const D: usize> HybridMonteCarloInternal<State, I, D>
217where
218 State: SimulationStateSynchronous<D> + ?Sized,
219 I: SymplecticIntegrator<State, SimulationStateLeap<State, D>, D>,
220{
221 getter!(
222 pub const,
224 integrator,
225 I
226 );
227
228 getter_copy!(
229 pub const,
231 delta_t,
232 Real
233 );
234
235 getter_copy!(
236 pub const,
238 number_of_steps,
239 usize
240 );
241
242 pub const fn new(delta_t: Real, number_of_steps: usize, integrator: I) -> Self {
244 Self {
245 delta_t,
246 number_of_steps,
247 integrator,
248 _phantom: PhantomData,
249 }
250 }
251
252 pub fn integrator_mut(&mut self) -> &mut I {
253 &mut self.integrator
254 }
255}
256
257impl<State, I, const D: usize> AsRef<I> for HybridMonteCarloInternal<State, I, D>
258where
259 State: SimulationStateSynchronous<D> + ?Sized,
260 I: SymplecticIntegrator<State, SimulationStateLeap<State, D>, D>,
261{
262 fn as_ref(&self) -> &I {
263 self.integrator()
264 }
265}
266
267impl<State, I, const D: usize> AsMut<I> for HybridMonteCarloInternal<State, I, D>
268where
269 State: SimulationStateSynchronous<D> + ?Sized,
270 I: SymplecticIntegrator<State, SimulationStateLeap<State, D>, D>,
271{
272 fn as_mut(&mut self) -> &mut I {
273 self.integrator_mut()
274 }
275}
276
277impl<State, I, const D: usize> MonteCarloDefault<State, D> for HybridMonteCarloInternal<State, I, D>
278where
279 State: SimulationStateSynchronous<D> + ?Sized,
280 I: SymplecticIntegrator<State, SimulationStateLeap<State, D>, D>,
281{
282 type Error = MultiIntegrationError<I::Error>;
283
284 fn potential_next_element<Rng>(
285 &mut self,
286 state: &State,
287 _rng: &mut Rng,
288 ) -> Result<State, Self::Error>
289 where
290 Rng: rand::Rng + ?Sized,
291 {
292 state.simulate_symplectic_n_auto(&self.integrator, self.delta_t, self.number_of_steps)
293 }
294
295 fn probability_of_replacement(old_state: &State, new_state: &State) -> Real {
296 (old_state.hamiltonian_total() - new_state.hamiltonian_total())
297 .exp()
298 .min(1_f64)
299 .max(0_f64)
300 }
301}
302
303#[derive(Clone, Debug, PartialEq)]
315#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
316pub struct HybridMonteCarloDiagnostic<State, Rng, I, const D: usize>
317where
318 State: LatticeState<D> + Clone + ?Sized,
319 LatticeStateEFSyncDefault<State, D>: SimulationStateSynchronous<D>,
320 I: SymplecticIntegrator<
321 LatticeStateEFSyncDefault<State, D>,
322 SimulationStateLeap<LatticeStateEFSyncDefault<State, D>, D>,
323 D,
324 >,
325 Rng: rand::Rng,
326{
327 internal: HybridMonteCarloInternalDiagnostics<LatticeStateEFSyncDefault<State, D>, I, D>,
328 rng: Rng,
329}
330
331impl<State, Rng, I, const D: usize> HybridMonteCarloDiagnostic<State, Rng, I, D>
332where
333 State: LatticeState<D> + Clone + ?Sized,
334 LatticeStateEFSyncDefault<State, D>: SimulationStateSynchronous<D>,
335 I: SymplecticIntegrator<
336 LatticeStateEFSyncDefault<State, D>,
337 SimulationStateLeap<LatticeStateEFSyncDefault<State, D>, D>,
338 D,
339 >,
340 Rng: rand::Rng,
341{
342 getter!(
343 pub const,
345 rng,
346 Rng
347 );
348
349 project!(
350 pub const,
352 integrator,
353 internal,
354 &I
355 );
356
357 project_mut!(
358 pub,
360 integrator_mut,
361 internal,
362 &mut I
363 );
364
365 project!(
366 pub const,
368 delta_t,
369 internal,
370 Real
371 );
372
373 project!(
374 pub const,
376 number_of_steps,
377 internal,
378 usize
379 );
380
381 pub const fn new(delta_t: Real, number_of_steps: usize, integrator: I, rng: Rng) -> Self {
387 Self {
388 internal: HybridMonteCarloInternalDiagnostics::<
389 LatticeStateEFSyncDefault<State, D>,
390 I,
391 D,
392 >::new(delta_t, number_of_steps, integrator),
393 rng,
394 }
395 }
396
397 pub fn rng_mut(&mut self) -> &mut Rng {
399 &mut self.rng
400 }
401
402 pub const fn prob_replace_last(&self) -> Real {
404 self.internal.prob_replace_last()
405 }
406
407 pub const fn has_replace_last(&self) -> bool {
409 self.internal.has_replace_last()
410 }
411
412 #[allow(clippy::missing_const_for_fn)] pub fn rng_owned(self) -> Rng {
415 self.rng
416 }
417}
418
419impl<State, Rng, I, const D: usize> AsRef<Rng> for HybridMonteCarloDiagnostic<State, Rng, I, D>
420where
421 State: LatticeState<D> + Clone + ?Sized,
422 LatticeStateEFSyncDefault<State, D>: SimulationStateSynchronous<D>,
423 I: SymplecticIntegrator<
424 LatticeStateEFSyncDefault<State, D>,
425 SimulationStateLeap<LatticeStateEFSyncDefault<State, D>, D>,
426 D,
427 >,
428 Rng: rand::Rng,
429{
430 fn as_ref(&self) -> &Rng {
431 self.rng()
432 }
433}
434
435impl<State, Rng, I, const D: usize> AsMut<Rng> for HybridMonteCarloDiagnostic<State, Rng, I, D>
436where
437 State: LatticeState<D> + Clone + ?Sized,
438 LatticeStateEFSyncDefault<State, D>: SimulationStateSynchronous<D>,
439 I: SymplecticIntegrator<
440 LatticeStateEFSyncDefault<State, D>,
441 SimulationStateLeap<LatticeStateEFSyncDefault<State, D>, D>,
442 D,
443 >,
444 Rng: rand::Rng,
445{
446 fn as_mut(&mut self) -> &mut Rng {
447 self.rng_mut()
448 }
449}
450
451impl<State, Rng, I, const D: usize> MonteCarlo<State, D>
452 for HybridMonteCarloDiagnostic<State, Rng, I, D>
453where
454 State: LatticeState<D> + Clone + ?Sized,
455 LatticeStateEFSyncDefault<State, D>: SimulationStateSynchronous<D>,
456 I: SymplecticIntegrator<
457 LatticeStateEFSyncDefault<State, D>,
458 SimulationStateLeap<LatticeStateEFSyncDefault<State, D>, D>,
459 D,
460 >,
461 Rng: rand::Rng,
462{
463 type Error = MultiIntegrationError<I::Error>;
464
465 fn next_element(&mut self, state: State) -> Result<State, Self::Error> {
466 let state_internal =
467 LatticeStateEFSyncDefault::<State, D>::new_random_e_state(state, self.rng_mut());
468 self.internal
469 .next_element_default(state_internal, &mut self.rng)
470 .map(|el| el.state_owned())
471 }
472}
473
474#[derive(Clone, Debug, PartialEq)]
476#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
477struct HybridMonteCarloInternalDiagnostics<State, I, const D: usize>
478where
479 State: SimulationStateSynchronous<D> + ?Sized,
480 I: SymplecticIntegrator<State, SimulationStateLeap<State, D>, D>,
481{
482 delta_t: Real,
483 number_of_steps: usize,
484 integrator: I,
485 has_replace_last: bool,
486 prob_replace_last: Real,
487 #[cfg_attr(feature = "serde-serialize", serde(skip))]
488 _phantom: PhantomData<State>,
489}
490
491impl<State, I, const D: usize> HybridMonteCarloInternalDiagnostics<State, I, D>
492where
493 State: SimulationStateSynchronous<D> + ?Sized,
494 I: SymplecticIntegrator<State, SimulationStateLeap<State, D>, D>,
495{
496 getter!(
497 pub const,
499 integrator,
500 I
501 );
502
503 getter_copy!(
504 pub const,
506 delta_t,
507 Real
508 );
509
510 getter_copy!(
511 pub const,
513 number_of_steps,
514 usize
515 );
516
517 pub const fn new(delta_t: Real, number_of_steps: usize, integrator: I) -> Self {
519 Self {
520 delta_t,
521 number_of_steps,
522 integrator,
523 has_replace_last: false,
524 prob_replace_last: 0_f64,
525 _phantom: PhantomData,
526 }
527 }
528
529 pub const fn prob_replace_last(&self) -> Real {
531 self.prob_replace_last
532 }
533
534 pub const fn has_replace_last(&self) -> bool {
536 self.has_replace_last
537 }
538
539 pub fn integrator_mut(&mut self) -> &mut I {
541 &mut self.integrator
542 }
543}
544
545impl<State, I, const D: usize> AsRef<I> for HybridMonteCarloInternalDiagnostics<State, I, D>
546where
547 State: SimulationStateSynchronous<D> + ?Sized,
548 I: SymplecticIntegrator<State, SimulationStateLeap<State, D>, D>,
549{
550 fn as_ref(&self) -> &I {
551 self.integrator()
552 }
553}
554
555impl<State, I, const D: usize> AsMut<I> for HybridMonteCarloInternalDiagnostics<State, I, D>
556where
557 State: SimulationStateSynchronous<D> + ?Sized,
558 I: SymplecticIntegrator<State, SimulationStateLeap<State, D>, D>,
559{
560 fn as_mut(&mut self) -> &mut I {
561 self.integrator_mut()
562 }
563}
564
565impl<State, I, const D: usize> MonteCarloDefault<State, D>
566 for HybridMonteCarloInternalDiagnostics<State, I, D>
567where
568 State: SimulationStateSynchronous<D> + ?Sized,
569 I: SymplecticIntegrator<State, SimulationStateLeap<State, D>, D>,
570{
571 type Error = MultiIntegrationError<I::Error>;
572
573 fn potential_next_element<Rng>(
574 &mut self,
575 state: &State,
576 _rng: &mut Rng,
577 ) -> Result<State, Self::Error>
578 where
579 Rng: rand::Rng + ?Sized,
580 {
581 state.simulate_symplectic_n_auto(&self.integrator, self.delta_t, self.number_of_steps)
582 }
583
584 fn probability_of_replacement(old_state: &State, new_state: &State) -> Real {
585 (old_state.hamiltonian_total() - new_state.hamiltonian_total())
586 .exp()
587 .min(1_f64)
588 .max(0_f64)
589 }
590
591 fn next_element_default<Rng>(
592 &mut self,
593 state: State,
594 rng: &mut Rng,
595 ) -> Result<State, Self::Error>
596 where
597 Rng: rand::Rng + ?Sized,
598 {
599 let potential_next = self.potential_next_element(&state, rng)?;
600 let proba = Self::probability_of_replacement(&state, &potential_next)
601 .min(1_f64)
602 .max(0_f64);
603 self.prob_replace_last = proba;
604 let d = rand::distributions::Bernoulli::new(proba).unwrap();
605 if d.sample(rng) {
606 self.has_replace_last = true;
607 Ok(potential_next)
608 }
609 else {
610 self.has_replace_last = false;
611 Ok(state)
612 }
613 }
614}