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
use super::*;
use crate::vars::Vars;
use fire::fire;
use lbfgs::lbfgs_iter;
#[derive(Debug, Clone)]
pub struct OptimProgress<U> {
pub ncalls: usize,
pub fmax: f64,
pub energy: f64,
pub extra: U,
}
pub fn optimize<'a, U: 'a>(potential: &'a mut Dynamics<U>) -> Box<dyn Iterator<Item = OptimProgress<U>> + 'a>
where
U: Clone,
{
let vars = Vars::from_env();
if vars.algorithm == "FIRE" {
info!("Optimizing using FIRE algorithm ...");
let x_init = potential.position().to_vec();
let mut opt = fire()
.with_max_step(vars.max_step_size)
.with_max_cycles(vars.max_evaluations);
let steps = opt.minimize_iter(x_init, move |x: &[f64], o: &mut fire::Output| {
potential.set_position(x);
let energy = potential.get_energy()?;
let force = potential.get_force()?;
o.fx = energy;
o.gx.vecncpy(force);
let fmax = force.iter().map(|x| x.abs()).float_max();
let extra = potential.get_extra()?.clone();
let ncalls = potential.ncalls();
let progress = OptimProgress {
ncalls,
energy,
fmax,
extra,
};
Ok(progress)
});
Box::new(steps.map(|progress| progress.extra))
} else {
info!("Optimizing using L-BFGS algorithm ...");
let mut opt = lbfgs::lbfgs_iter()
.with_max_evaluations(vars.max_evaluations)
.with_initial_step_size(vars.initial_step_size)
.with_max_step_size(vars.max_step_size)
.with_max_linesearch(vars.max_linesearch)
.with_gradient_only()
.with_damping(true)
.with_linesearch_gtol(0.999);
let x_init = potential.position().to_vec();
let steps = opt
.minimize(x_init, move |x: &[f64], o: &mut lbfgs::Output| {
potential.set_position(x);
let energy = potential.get_energy()?;
let force = potential.get_force()?;
o.fx = energy;
o.gx.vecncpy(force);
let fmax = force.iter().map(|x| x.abs()).float_max();
let ncalls = potential.ncalls();
let extra = potential.get_extra()?.clone();
let progress = OptimProgress {
ncalls,
fmax,
energy,
extra,
};
Ok(progress)
})
.expect("optimize lbfgs");
Box::new(steps.map(|progress| progress.extra))
}
}