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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
//! The [`Solver`] trait every concrete solver implements. See the trait
//! contract for the lifecycle (`init` once, then repeated `next_iter`,
//! with an optional `terminate` hook) and the
//! [`executor`](crate::core::executor) module for the canonical iteration
//! ordering.
use crateProblem;
use crateState;
use crateTermination;
/// Progress published by one solver step. Completion and termination are
/// independent: a finished step can also be the step that stops the run.
/// A continuing partial step publishes progress without an iteration callback.
///
/// Construct steps with [`Self::new`] or the named constructors. Fields remain
/// public for reading, moving, and assignment; destructuring must include `..`.
/// Future optional metadata must default to behavior compatible with existing
/// constructors.
// Tuple conversion preserves the 1.x convention that a stopping step is partial.
/// A concrete optimization algorithm. Implementations carry the
/// solver's configuration and any internal scratch state; the iterate
/// itself lives in `S: State`.
///
/// # Contract
///
/// - **Caller must:** drive the solver through
/// [`Executor`](crate::core::executor::Executor) (or
/// [`run_loop_with_control`](crate::core::executor::run_loop_with_control) for composed
/// solvers). The executor calls [`init`](Self::init) exactly once
/// before any [`next_iter`](Self::next_iter) call, and runs
/// termination checks before each iteration including iter 0. See the
/// [`executor`](crate::core::executor) module docs for the canonical
/// loop ordering.
/// - **Implementor must:** populate every state field termination
/// criteria might read before returning from
/// [`init`](Self::init): at minimum [`State::cost`] for any state
/// whose `cost()` panics on missing data, and
/// [`GradientState::gradient`](crate::core::state::GradientState::gradient)
/// for first-order solvers. After every successful
/// [`next_iter`](Self::next_iter), the same fields must again
/// correspond to the *current* [`State::param`].
/// - **Implementor must:** report mid-iteration failures
/// (line-search bailout, non-descent direction, etc.) via
/// [`SolverStep::termination`] field rather than panicking; and use [`terminate`](Self::terminate)
/// only for clean convergence tests on the current state.
///
/// # Eval counting
///
/// Solvers do **not** maintain eval counters by hand. Every cost/
/// gradient/residual/Jacobian/Hessian call goes through the
/// [`Problem`] wrapper, which bumps
/// [`EvalCounts`](crate::core::problem::EvalCounts) on the wrapper
/// before delegating to the user's problem. The
/// [`Executor`](crate::core::executor::Executor) mirrors those counts
/// onto the state's [`State::cost_evals`]/
/// [`GradientState::gradient_evals`](crate::core::state::GradientState::gradient_evals)
/// after every successful [`init`](Self::init)/
/// [`next_iter`](Self::next_iter); see
/// [`CountsMirror`](crate::core::state::CountsMirror) for the per-state
/// mapping.
///
/// # Error type
///
/// The associated [`Error`](Self::Error) is the **hard-abort** error
/// type the solver propagates out of [`init`](Self::init) and
/// [`next_iter`](Self::next_iter). Concrete impls set
/// `type Error = P::Error;` (or `<P as Residual>::Error` for NLLS
/// solvers) so the user's typed problem error flows untouched out of
/// [`Executor::run`](crate::core::executor::Executor::run). Soft per-point
/// rejection still travels through `Ok(f64::INFINITY)`; see the
/// [`problem`](crate::core::problem) module docs.