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
//! Canonical problem-side constraint sets and checked evaluation capabilities.
//!
//! [`ProblemConstraints`] declares the complete constraint set. Solvers accept
//! only block combinations they support. Bounds, linear equalities and
//! inequalities, and nonlinear equalities and inequalities remain distinct.
//!
//! An unconstrained solver cannot discard a declared box:
//!
//! ```compile_fail
//! use basin::{BoxBounds, Constrained, Constraints, CostFunction, Executor,
//! NelderMead, NoConstraints, ProblemConstraints};
//! struct Sphere;
//! impl ProblemConstraints for Sphere {
//! type Constraints = NoConstraints;
//! fn constraint_set(&self) -> basin::NoConstraints { basin::NoConstraints::EMPTY }
//! }
//! impl CostFunction for Sphere {
//! type Param = Vec<f64>;
//! type Output = f64;
//! type Error = std::convert::Infallible;
//! fn cost(&self, x: &Vec<f64>) -> Result<f64, Self::Error> {
//! Ok(x.iter().map(|v| v * v).sum())
//! }
//! }
//! let constraints = Constraints::new()
//! .with_bounds(BoxBounds::new(Some(vec![-1.0]), Some(vec![1.0])));
//! let problem = Constrained::new(Sphere, constraints);
//! Executor::from_start(problem, NelderMead::new(), vec![0.5]).run();
//! ```
//!
//! A box-only solver also rejects an additional nonlinear block, even when
//! the problem supplies the required value callback:
//!
//! ```compile_fail
//! use basin::{BoxBounds, Constrained, ConstraintSolveError, Constraints,
//! CostFunction, Executor, NelderMead, NoConstraints,
//! NonlinearInequalityValues, ProblemConstraints};
//! struct Sphere;
//! impl ProblemConstraints for Sphere {
//! type Constraints = NoConstraints;
//! fn constraint_set(&self) -> basin::NoConstraints { basin::NoConstraints::EMPTY }
//! }
//! impl CostFunction for Sphere {
//! type Param = Vec<f64>;
//! type Output = f64;
//! type Error = std::convert::Infallible;
//! fn cost(&self, x: &Vec<f64>) -> Result<f64, Self::Error> {
//! Ok(x.iter().map(|v| v * v).sum())
//! }
//! }
//! impl NonlinearInequalityValues for Sphere {
//! type Param = Vec<f64>;
//! type Values = Vec<f64>;
//! type Error = std::convert::Infallible;
//! fn nonlinear_inequalities(&self, x: &Vec<f64>)
//! -> Result<Vec<f64>, ConstraintSolveError<Self::Error>> {
//! Ok(vec![x[0] - 0.25])
//! }
//! }
//! let constraints = Constraints::new()
//! .with_bounds(BoxBounds::new(Some(vec![-1.0]), Some(vec![1.0])))
//! .with_nonlinear_inequalities(1);
//! let problem = Constrained::new(Sphere, constraints);
//! Executor::from_start(problem, NelderMead::new().projected(), vec![0.5]).run();
//! ```
pub
pub use *;
pub
pub use *;
/// Analytic Jacobian of the declared nonlinear blocks.
///
/// Rows contain nonlinear equalities first, followed by nonlinear inequalities
/// in callback order. Columns correspond to parameters. Linear blocks supply
/// their own derivatives and are excluded. This storage is independent of the
/// linear matrices. Finite-difference adapters synthesize this capability.