gosh_fire/
lib.rs

1// [[file:../fire.note::2310234c][2310234c]]
2//! Implementation of the Fast-Inertial-Relaxation-Engine (FIRE) algorithm
3//! 
4//! References
5//! ----------
6//! * Bitzek, E. et al. Structural Relaxation Made Simple. Phys. Rev. Lett. 2006, 97 (17), 170201.
7//! * http://users.jyu.fi/~pekkosk/resources/pdf/FIRE.pdf
8//! * https://github.com/siesta-project/flos/blob/master/flos/optima/fire.lua
9//! 
10//! Usage
11//! -----
12//! ```
13//! use gosh_fire::*;
14//! 
15//! let mut x = [0.0];
16//! fire().minimize(&mut x, |x, gx| {
17//!     let fx = (x[0] - 1.).powi(2);
18//!     gx[0] = 2.0 * (x[0] - 1.0);
19//!     fx
20//! });
21//! ```
22
23mod base;
24mod cache;
25
26pub mod lj;
27
28pub(crate) mod common {
29    pub use gut::prelude::*;
30}
31// 2310234c ends here
32
33// [[file:../fire.note::ba290941][ba290941]]
34/// Create FIRE optimization interface
35pub fn fire() -> fire::FIRE {
36    fire::FIRE::default()
37}
38
39/// Create user defined monitor or termination criteria with a closure
40pub fn monitor<G>(cb: G) -> Option<UserTermination<G>>
41where
42    G: FnMut(&Progress) -> bool,
43{
44    Some(UserTermination(cb))
45}
46
47mod fire;
48pub use crate::fire::FIRE;
49// ba290941 ends here
50
51// [[file:../fire.note::*progress][progress:1]]
52use vecfx::*;
53
54/// Important iteration data in minimization, useful for progress monitor or
55/// defining artificial termination criteria.
56#[derive(Debug, Clone)]
57pub struct Progress<'a> {
58    /// Cached value of gradient vector norm.
59    gnorm: f64,
60
61    /// The number of iteration in optimization loop.
62    niter: usize,
63
64    /// The actual number of function value/gradient calls. This number can be
65    /// larger than `niter`.
66    ncall: usize,
67
68    /// The line-search step used for this iteration.
69    step: f64,
70
71    /// displacement vector over input variables vector
72    displacement: &'a [f64],
73
74    /// Reference to current input variables vector
75    x: &'a [f64],
76
77    /// Reference to current gradient vector of f(x): 'f(x)
78    gx: &'a [f64],
79
80    /// The current value of the objective function.
81    fx: f64,
82}
83
84impl<'a> Progress<'a> {
85    /// Return a reference to gradient vector.
86    pub fn gradient(&self) -> &'a [f64] {
87        self.gx
88    }
89
90    /// Return current function value.
91    pub fn value(&self) -> f64 {
92        self.fx
93    }
94
95    /// Return the number of function calls
96    pub fn ncalls(&self) -> usize {
97        self.ncall
98    }
99
100    /// Return a reference to displacement vector.
101    pub fn displacement(&self) -> &'a [f64] {
102        self.displacement
103    }
104
105    /// Print a summary about progress.
106    pub fn report(&self) {
107        println!(
108            "niter = {:5}, ncall= {:5}: fx = {:-10.4}, gnorm = {:-10.4}, dnorm = {:-10.4} step = {:-10.4}",
109            self.niter,
110            self.ncall,
111            self.fx,
112            self.gnorm,
113            self.displacement.vec2norm(),
114            self.step,
115        );
116    }
117}
118// progress:1 ends here
119
120// [[file:../fire.note::*termination interface][termination interface:1]]
121/// Define termination conditions
122pub trait TerminationCriteria {
123    fn met(&mut self, progress: &Progress) -> bool;
124}
125
126/// For user defined termination criteria
127#[derive(Debug, Clone)]
128pub struct UserTermination<G>(pub G)
129where
130    G: FnMut(&Progress) -> bool;
131
132impl<G> TerminationCriteria for UserTermination<G>
133where
134    G: FnMut(&Progress) -> bool,
135{
136    fn met(&mut self, progress: &Progress) -> bool {
137        (self.0)(progress)
138    }
139}
140
141/// Termination criteria
142#[derive(Debug, Clone)]
143pub(crate) struct Termination {
144    /// The maximum number of optimization cycles.
145    pub max_cycles: usize,
146    /// The max allowed gradient norm
147    pub max_gradient_norm: f64,
148}
149
150impl Default for Termination {
151    fn default() -> Self {
152        Termination {
153            max_cycles: 0,
154            max_gradient_norm: 0.01,
155        }
156    }
157}
158
159impl TerminationCriteria for Termination {
160    fn met(&mut self, progress: &Progress) -> bool {
161        if self.max_cycles > 0 && progress.niter >= self.max_cycles {
162            return true;
163        }
164
165        if progress.gnorm <= self.max_gradient_norm {
166            return true;
167        }
168
169        false
170    }
171}
172// termination interface:1 ends here
173
174// [[file:../fire.note::*minimizing interface][minimizing interface:1]]
175/// Common interfaces for structure relaxation
176#[deprecated(note = "plan to be removed, please use minimize_iter method instead")]
177pub trait GradientBasedMinimizer: Sized {
178    fn minimize<E>(mut self, x: &mut [f64], mut f: E)
179    where
180        E: FnMut(&[f64], &mut [f64]) -> f64,
181    {
182        self.minimize_alt::<E, _>(x, f, monitor(|_| false))
183    }
184
185    fn minimize_alt<E, G>(mut self, x: &mut [f64], mut f: E, mut stopping: Option<G>)
186    where
187        E: FnMut(&[f64], &mut [f64]) -> f64,
188        G: TerminationCriteria,
189    {
190        unimplemented!()
191    }
192}
193// minimizing interface:1 ends here
194
195// [[file:../fire.note::*pub][pub:1]]
196pub use crate::base::Output;
197pub use crate::fire::*;
198// pub:1 ends here