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