gomez/core/
solver.rs

1use nalgebra::{storage::StorageMut, Dyn, IsContiguous, Vector};
2
3use super::{domain::Domain, system::System};
4
5/// Interface of a solver.
6///
7/// A solver is an iterative algorithm which takes a point _x_ and computes the
8/// next step in the solving process. Repeated calls to the next step should
9/// eventually converge into a solution _x'_ in successful cases.
10///
11/// If you implement a solver, please reach out to discuss if we could include
12/// it in gomez.
13///
14/// ## Implementing a solver
15///
16/// Here is an implementation of a random "solver" which randomly generates
17/// values in a hope that a solution can be found with enough luck.
18///
19/// ```rust
20/// use gomez::nalgebra as na;
21/// use gomez::{Domain, Sample, Solver, System};
22/// use na::{storage::StorageMut, Dyn, IsContiguous, Vector};
23/// use fastrand::Rng;
24///
25/// struct Random {
26///     rng: Rng,
27/// }
28///
29/// impl Random {
30///     fn new(rng: Rng) -> Self {
31///         Self { rng }
32///     }
33/// }
34///
35/// impl<R: System> Solver<R> for Random
36/// where
37///     R::Field: Sample,
38/// {
39///     const NAME: &'static str = "Random";
40///     type Error = std::convert::Infallible;
41///
42///     fn solve_next<Sx, Srx>(
43///         &mut self,
44///         r: &R,
45///         dom: &Domain<R::Field>,
46///         x: &mut Vector<R::Field, Dyn, Sx>,
47///         rx: &mut Vector<R::Field, Dyn, Srx>,
48///     ) -> Result<(), Self::Error>
49///     where
50///         Sx: StorageMut<R::Field, Dyn> + IsContiguous,
51///         Srx: StorageMut<R::Field, Dyn>,
52///     {
53///         // Randomly sample in the domain.
54///         dom.sample(x, &mut self.rng);
55///
56///         // We must compute the residuals.
57///         r.eval(x, rx);
58///
59///         Ok(())
60///     }
61/// }
62/// ```
63pub trait Solver<R: System> {
64    /// Name of the solver.
65    const NAME: &'static str;
66
67    /// Error while computing the next step.
68    type Error;
69
70    /// Computes the next step in the solving process.
71    ///
72    /// The value of `x` is the current point. After the method returns, `x`
73    /// should hold the variable values of the performed step and `rx` _must_
74    /// contain residuals of that step as computed by [`System::eval`].
75    ///
76    /// The implementations _can_ assume that subsequent calls to `solve_next`
77    /// pass the value of `x` as was returned in the previous iteration.
78    fn solve_next<Sx, Srx>(
79        &mut self,
80        r: &R,
81        dom: &Domain<R::Field>,
82        x: &mut Vector<R::Field, Dyn, Sx>,
83        rx: &mut Vector<R::Field, Dyn, Srx>,
84    ) -> Result<(), Self::Error>
85    where
86        Sx: StorageMut<R::Field, Dyn> + IsContiguous,
87        Srx: StorageMut<R::Field, Dyn>;
88}