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
90
91
92
93
94
95
96
97
98
99
100
101
102
use ;
use ;
/// Common interface for all solvers.
///
/// All solvers implement a common interface defined by the [`Solver`] trait.
/// The essential method is [`next`](Solver::next) which takes variables *x* and
/// computes the next step. Thus it represents one iteration in the process.
/// Repeated call to this method should converge *x* to the solution in
/// successful cases.
///
/// If you implement a solver, please consider make it a contribution to this
/// library.
///
/// ## Implementing a solver
///
/// Here is an implementation of a random solver (if such a thing can be called
/// a solver) which randomly generates values in a hope that a solution can be
/// found with enough luck.
///
/// ```rust
/// use gomez::nalgebra as na;
/// use gomez::core::*;
/// use na::{storage::StorageMut, IsContiguous, Vector};
/// use rand::Rng;
/// use rand_distr::{uniform::SampleUniform, Distribution, Uniform};
///
/// struct Random<R> {
/// rng: R,
/// }
///
/// impl<R> Random<R> {
/// fn new(rng: R) -> Self {
/// Self { rng }
/// }
/// }
///
/// impl<F: System, R: Rng> Solver<F> for Random<R>
/// where
/// F::Scalar: SampleUniform,
/// {
/// const NAME: &'static str = "Random";
/// type Error = ProblemError;
///
/// fn next<Sx, Sfx>(
/// &mut self,
/// f: &F,
/// dom: &Domain<F::Scalar>,
/// x: &mut Vector<F::Scalar, F::Dim, Sx>,
/// fx: &mut Vector<F::Scalar, F::Dim, Sfx>,
/// ) -> Result<(), Self::Error>
/// where
/// Sx: StorageMut<F::Scalar, F::Dim> + IsContiguous,
/// Sfx: StorageMut<F::Scalar, F::Dim>,
/// {
/// // Randomly sample within the bounds.
/// x.iter_mut().zip(dom.vars().iter()).for_each(|(xi, vi)| {
/// *xi = Uniform::new_inclusive(vi.lower(), vi.upper()).sample(&mut self.rng)
/// });
///
/// // We must compute the residuals.
/// f.eval(x, fx)?;
///
/// Ok(())
/// }
/// }
/// ```