cobyla_argmin/cobyla_state.rs
1use crate::cobyla::cobyla_context_t;
2/// Implementation of `argmin::IterState` for Cobyla optimizer
3use argmin::core::{Problem, State, TerminationReason, TerminationStatus};
4#[cfg(feature = "serde1")]
5use serde::{Deserialize, Serialize};
6use std::collections::HashMap;
7use std::mem::ManuallyDrop;
8
9/// Maintains the state from iteration to iteration of the [crate::CobylaSolver].
10///
11/// This struct is passed from one iteration of an algorithm to the next.
12///
13/// Keeps track of
14///
15/// * parameter vector of current and previous iteration
16/// * best parameter vector of current and previous iteration
17/// * cost function value (objective and constraint functions values) of current and previous iteration
18/// * current and previous best cost function value
19/// * target cost function value
20/// * current iteration number
21/// * iteration number where the last best parameter vector was found
22/// * maximum number of iterations that will be executed
23/// * problem function evaluation counts
24/// * elapsed time
25/// * termination status
26/// * COBYLA specific parameters: rhobeg, rhoend, iprint, maxfun
27///
28#[derive(Clone, Debug, Default)]
29#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
30pub struct CobylaState {
31 /// Current parameter vector
32 pub param: Option<Vec<f64>>,
33 /// Previous parameter vector
34 pub prev_param: Option<Vec<f64>>,
35 /// Current best parameter vector
36 pub best_param: Option<Vec<f64>>,
37 /// Previous best parameter vector
38 pub prev_best_param: Option<Vec<f64>>,
39
40 /// Current cost function value
41 pub cost: Option<Vec<f64>>,
42 /// Previous cost function value
43 pub prev_cost: Option<Vec<f64>>,
44 /// Current best cost function value
45 pub best_cost: Option<Vec<f64>>,
46 /// Previous best cost function value
47 pub prev_best_cost: Option<Vec<f64>>,
48 /// Target cost function value
49 pub target_cost: f64,
50
51 /// Current iteration
52 pub iter: u64,
53 /// Iteration number of last best cost
54 pub last_best_iter: u64,
55 /// Maximum number of iterations
56 pub max_iters: u64,
57 /// Evaluation counts
58 pub counts: HashMap<String, u64>,
59 /// Time required so far
60 pub time: Option<web_time::Duration>,
61 /// Status of optimization execution
62 pub termination_status: TerminationStatus,
63
64 /// Rho start value
65 pub rhobeg: f64,
66 /// Rho end value
67 pub rhoend: f64,
68 /// Control of traces
69 pub iprint: i32,
70 /// Cost function calls budget
71 pub maxfun: i32,
72
73 #[cfg_attr(feature = "serde1", serde(skip))]
74 pub cobyla_context: Option<ManuallyDrop<*mut cobyla_context_t>>,
75}
76
77impl CobylaState
78where
79 Self: State<Float = f64>,
80{
81 /// Set parameter vector. This shifts the stored parameter vector to the previous parameter
82 /// vector.
83 ///
84 /// # Example
85 ///
86 /// ```
87 /// # use argmin::core::{IterState, State};
88 /// # use cobyla_argmin::CobylaState;
89 /// # let state = CobylaState::new();
90 /// # let param_old = vec![1.0f64, 2.0f64];
91 /// # let state = state.param(param_old);
92 /// # assert!(state.prev_param.is_none());
93 /// # assert_eq!(state.param.as_ref().unwrap()[0].to_ne_bytes(), 1.0f64.to_ne_bytes());
94 /// # assert_eq!(state.param.as_ref().unwrap()[1].to_ne_bytes(), 2.0f64.to_ne_bytes());
95 /// # let param = vec![0.0f64, 3.0f64];
96 /// let state = state.param(param);
97 /// # assert_eq!(state.prev_param.as_ref().unwrap()[0].to_ne_bytes(), 1.0f64.to_ne_bytes());
98 /// # assert_eq!(state.prev_param.as_ref().unwrap()[1].to_ne_bytes(), 2.0f64.to_ne_bytes());
99 /// # assert_eq!(state.param.as_ref().unwrap()[0].to_ne_bytes(), 0.0f64.to_ne_bytes());
100 /// # assert_eq!(state.param.as_ref().unwrap()[1].to_ne_bytes(), 3.0f64.to_ne_bytes());
101 /// ```
102 #[must_use]
103 pub fn param(mut self, param: Vec<f64>) -> Self {
104 std::mem::swap(&mut self.prev_param, &mut self.param);
105 self.param = Some(param);
106 self
107 }
108
109 /// Set target cost.
110 ///
111 /// When this cost is reached, the algorithm will stop. The default is
112 /// `Self::Float::NEG_INFINITY`.
113 ///
114 /// # Example
115 ///
116 /// ```
117 /// # use cobyla_argmin::CobylaState;
118 /// # use argmin::core::{State, ArgminFloat};
119 /// # let state: CobylaState = CobylaState::new();
120 /// # assert_eq!(state.target_cost.to_ne_bytes(), f64::NEG_INFINITY.to_ne_bytes());
121 /// let state = state.target_cost(0.0);
122 /// # assert_eq!(state.target_cost.to_ne_bytes(), 0.0f64.to_ne_bytes());
123 /// ```
124 #[must_use]
125 pub fn target_cost(mut self, target_cost: f64) -> Self {
126 self.target_cost = target_cost;
127 self
128 }
129
130 /// Set maximum number of iterations
131 ///
132 /// # Example
133 ///
134 /// ```
135 /// # use cobyla_argmin::CobylaState;
136 /// # use argmin::core::{State, ArgminFloat};
137 /// # let state: CobylaState = CobylaState::new();
138 /// # assert_eq!(state.max_iters, std::u64::MAX);
139 /// let state = state.max_iters(1000);
140 /// # assert_eq!(state.max_iters, 1000);
141 /// ```
142 #[must_use]
143 pub fn max_iters(mut self, iters: u64) -> Self {
144 self.max_iters = iters;
145 self
146 }
147 /// Alias for max_iters using historic cobyla terminology
148 #[must_use]
149 pub fn maxfun(mut self, maxfun: u64) -> Self {
150 self.max_iters = maxfun;
151 self
152 }
153
154 /// Set maximum number of iterations
155 ///
156 /// # Example
157 ///
158 /// ```
159 /// # use cobyla_argmin::CobylaState;
160 /// # use argmin::core::{State, ArgminFloat};
161 /// # let state: CobylaState = CobylaState::new();
162 /// # assert_eq!(state.iprint, 1);
163 /// let state = state.iprint(0);
164 /// # assert_eq!(state.iprint, 0);
165 /// ```
166 #[must_use]
167 pub fn iprint(mut self, iprint: i32) -> Self {
168 self.iprint = iprint;
169 self
170 }
171
172 /// Set the current cost function value. This shifts the stored cost function value to the
173 /// previous cost function value.
174 ///
175 /// # Example
176 ///
177 /// ```
178 /// # use argmin::core::State;
179 /// # use cobyla_argmin::CobylaState;
180 /// # let state: CobylaState = CobylaState::new();
181 /// # let cost_old = 1.0f64;
182 /// # let state = state.cost(vec![cost_old]);
183 /// # assert!(state.prev_cost.is_none());
184 /// # assert_eq!(state.cost.as_ref().unwrap()[0].to_ne_bytes(), 1.0f64.to_ne_bytes());
185 /// # let cost = 0.0f64;
186 /// let state = state.cost(vec![cost]);
187 /// # assert_eq!(state.prev_cost.as_ref().unwrap()[0].to_ne_bytes(), 1.0f64.to_ne_bytes());
188 /// # assert_eq!(state.cost.as_ref().unwrap()[0].to_ne_bytes(), 0.0f64.to_ne_bytes());
189 /// ```
190 #[must_use]
191 pub fn cost(mut self, cost: Vec<f64>) -> Self {
192 std::mem::swap(&mut self.prev_cost, &mut self.cost);
193 self.cost = Some(cost);
194 self
195 }
196
197 /// Returns current cost (ie objective) function and constraint values.
198 ///
199 /// # Example
200 ///
201 /// ```
202 /// # use cobyla_argmin::CobylaState;
203 /// # use argmin::core::{State, ArgminFloat};
204 /// # let mut state: CobylaState = CobylaState::new();
205 /// # state.cost = Some(vec![12.0, 0.1]);
206 /// let cost = state.get_full_cost();
207 /// # assert_eq!(cost.unwrap()[0].to_ne_bytes(), 12.0f64.to_ne_bytes());
208 /// # assert_eq!(cost.unwrap()[1].to_ne_bytes(), 0.1f64.to_ne_bytes());
209 /// ```
210 pub fn get_full_cost(&self) -> Option<&Vec<f64>> {
211 self.cost.as_ref()
212 }
213
214 /// Returns current cost (ie objective) function and constraint values.
215 ///
216 /// # Example
217 ///
218 /// ```
219 /// # use cobyla_argmin::CobylaState;
220 /// # use argmin::core::{State, ArgminFloat};
221 /// # let mut state: CobylaState = CobylaState::new();
222 /// # state.best_cost = Some(vec![12.0, 0.1]);
223 /// let cost = state.get_full_best_cost();
224 /// # assert_eq!(cost.unwrap()[0].to_ne_bytes(), 12.0f64.to_ne_bytes());
225 /// # assert_eq!(cost.unwrap()[1].to_ne_bytes(), 0.1f64.to_ne_bytes());
226 /// ```
227 pub fn get_full_best_cost(&self) -> Option<&Vec<f64>> {
228 self.best_cost.as_ref()
229 }
230
231 /// Returns the rho start value
232 pub fn rhobeg(&self) -> f64 {
233 self.rhobeg
234 }
235
236 /// Returns the rho end value
237 pub fn get_rhoend(&self) -> f64 {
238 self.rhoend
239 }
240
241 /// Returns the level of printing
242 pub fn get_iprint(&self) -> i32 {
243 self.iprint
244 }
245
246 /// Returns cost function calls budget
247 pub fn get_maxfun(&self) -> i32 {
248 self.max_iters as i32
249 }
250}
251
252impl State for CobylaState {
253 /// Type of parameter vector
254 type Param = Vec<f64>;
255 /// Floating point precision
256 type Float = f64;
257
258 /// Create new `CobylaState` instance
259 ///
260 /// # Example
261 ///
262 /// ```
263 /// # extern crate web_time;
264 /// # use web_time;
265 /// # use std::collections::HashMap;
266 /// # use argmin::core::{State, TerminationStatus};
267 /// use cobyla_argmin::CobylaState;
268 /// let state: CobylaState = CobylaState::new();
269 ///
270 /// # assert!(state.param.is_none());
271 /// # assert!(state.prev_param.is_none());
272 /// # assert!(state.best_param.is_none());
273 /// # assert!(state.prev_best_param.is_none());
274 /// # assert!(state.cost.is_none());
275 /// # assert!(state.prev_cost.is_none());
276 /// # assert!(state.best_cost.is_none());
277 /// # assert!(state.prev_best_cost.is_none());
278 /// # assert_eq!(state.target_cost, f64::NEG_INFINITY);
279 /// # assert_eq!(state.iter, 0);
280 /// # assert_eq!(state.last_best_iter, 0);
281 /// # assert_eq!(state.max_iters, std::u64::MAX);
282 /// # assert_eq!(state.counts, HashMap::new());
283 /// # assert_eq!(state.time.unwrap(), web_time::Duration::new(0, 0));
284 /// # assert_eq!(state.termination_status, TerminationStatus::NotTerminated);
285 /// ```
286 fn new() -> Self {
287 CobylaState {
288 param: None,
289 prev_param: None,
290 best_param: None,
291 prev_best_param: None,
292
293 cost: None,
294 prev_cost: None,
295 best_cost: None,
296 prev_best_cost: None,
297 target_cost: f64::NEG_INFINITY,
298
299 iter: 0,
300 last_best_iter: 0,
301 max_iters: u64::MAX,
302 counts: HashMap::new(),
303 time: Some(web_time::Duration::new(0, 0)),
304 termination_status: TerminationStatus::NotTerminated,
305
306 rhobeg: 0.5,
307 rhoend: 1e-4,
308 iprint: 1,
309 maxfun: 2000,
310
311 cobyla_context: None,
312 }
313 }
314
315 /// Checks if the current parameter vector is better than the previous best parameter value. If
316 /// a new best parameter vector was found, the state is updated accordingly.
317 ///
318 /// # Example
319 ///
320 /// ```
321 /// # use argmin::core::{State, ArgminFloat};
322 /// # use cobyla_argmin::CobylaState;
323 ///
324 /// let mut state: CobylaState = CobylaState::new();
325 ///
326 /// // Simulating a new parameter vector
327 /// state.param = Some(vec![2.0f64]);
328 /// state.cost = Some(vec![5.0]);
329 ///
330 /// // Calling update
331 /// state.update();
332 ///
333 /// // Check if update was successful
334 /// assert_eq!(state.best_param.as_ref().unwrap()[0], 2.0f64);
335 /// assert_eq!(state.best_cost.as_ref().unwrap()[0], 5.0);
336 /// assert!(state.is_best());
337 /// ```
338 fn update(&mut self) {
339 if let Some(cost) = self.cost.as_ref() {
340 if let Some(param) = self.param.as_ref().cloned() {
341 std::mem::swap(&mut self.prev_best_param, &mut self.best_param);
342 self.best_param = Some(param);
343 }
344 std::mem::swap(&mut self.prev_best_cost, &mut self.best_cost);
345 self.best_cost = Some(cost.clone());
346 self.last_best_iter = self.iter;
347 }
348 }
349
350 /// Returns a reference to the current parameter vector
351 ///
352 /// # Example
353 ///
354 /// ```
355 /// # use cobyla_argmin::CobylaState;
356 /// # use argmin::core::{State, ArgminFloat};
357 /// # let mut state: CobylaState = CobylaState::new();
358 /// # assert!(state.param.is_none());
359 /// # state.param = Some(vec![1.0, 2.0]);
360 /// # assert_eq!(state.param.as_ref().unwrap()[0].to_ne_bytes(), 1.0f64.to_ne_bytes());
361 /// # assert_eq!(state.param.as_ref().unwrap()[1].to_ne_bytes(), 2.0f64.to_ne_bytes());
362 /// let param = state.get_param(); // Option<&P>
363 /// # assert_eq!(param.as_ref().unwrap()[0].to_ne_bytes(), 1.0f64.to_ne_bytes());
364 /// # assert_eq!(param.as_ref().unwrap()[1].to_ne_bytes(), 2.0f64.to_ne_bytes());
365 /// ```
366 fn get_param(&self) -> Option<&Vec<f64>> {
367 self.param.as_ref()
368 }
369
370 /// Returns a reference to the current best parameter vector
371 ///
372 /// # Example
373 ///
374 /// ```
375 /// # use cobyla_argmin::CobylaState;
376 /// # use argmin::core::{State, ArgminFloat};
377 ///
378 /// # let mut state: CobylaState = CobylaState::new();
379 ///
380 /// # assert!(state.best_param.is_none());
381 /// # state.best_param = Some(vec![1.0, 2.0]);
382 /// # assert_eq!(state.best_param.as_ref().unwrap()[0].to_ne_bytes(), 1.0f64.to_ne_bytes());
383 /// # assert_eq!(state.best_param.as_ref().unwrap()[1].to_ne_bytes(), 2.0f64.to_ne_bytes());
384 /// let best_param = state.get_best_param(); // Option<&P>
385 /// # assert_eq!(best_param.as_ref().unwrap()[0].to_ne_bytes(), 1.0f64.to_ne_bytes());
386 /// # assert_eq!(best_param.as_ref().unwrap()[1].to_ne_bytes(), 2.0f64.to_ne_bytes());
387 /// ```
388 fn get_best_param(&self) -> Option<&Vec<f64>> {
389 self.best_param.as_ref()
390 }
391
392 /// Sets the termination reason
393 ///
394 /// # Example
395 ///
396 /// ```
397 /// # use cobyla_argmin::CobylaState;
398 /// # use argmin::core::{State, ArgminFloat, TerminationReason, TerminationStatus};
399 /// # let mut state: CobylaState = CobylaState::new();
400 /// # assert_eq!(state.termination_status, TerminationStatus::NotTerminated);
401 /// let state = state.terminate_with(TerminationReason::SolverConverged);
402 /// # assert_eq!(state.termination_status, TerminationStatus::Terminated(TerminationReason::SolverConverged));
403 /// ```
404 fn terminate_with(mut self, reason: TerminationReason) -> Self {
405 self.termination_status = TerminationStatus::Terminated(reason);
406 self
407 }
408
409 /// Sets the time required so far.
410 ///
411 /// # Example
412 ///
413 /// ```
414 /// # extern crate web_time;
415 /// # use web_time;
416 /// # use cobyla_argmin::CobylaState;
417 /// # use argmin::core::{State, ArgminFloat, TerminationReason};
418 /// # let mut state: CobylaState = CobylaState::new();
419 /// let state = state.time(Some(web_time::Duration::new(0, 12)));
420 /// # assert_eq!(state.time.unwrap(), web_time::Duration::new(0, 12));
421 /// ```
422 fn time(&mut self, time: Option<web_time::Duration>) -> &mut Self {
423 self.time = time;
424 self
425 }
426
427 /// Returns current cost function value.
428 ///
429 /// # Example
430 ///
431 /// ```
432 /// # use cobyla_argmin::CobylaState;
433 /// # use argmin::core::{State, ArgminFloat};
434 /// # let mut state: CobylaState = CobylaState::new();
435 /// # state.cost = Some(vec![12.0]);
436 /// let cost = state.get_cost();
437 /// # assert_eq!(cost.to_ne_bytes(), 12.0f64.to_ne_bytes());
438 /// ```
439 fn get_cost(&self) -> Self::Float {
440 match self.cost.as_ref() {
441 Some(c) => *(c.first().unwrap_or(&f64::INFINITY)),
442 None => f64::INFINITY,
443 }
444 }
445
446 /// Returns current best cost function value.
447 ///
448 /// # Example
449 ///
450 /// ```
451 /// # use cobyla_argmin::CobylaState;
452 /// # use argmin::core::{State, ArgminFloat};
453 /// # let mut state: CobylaState = CobylaState::new();
454 /// # state.best_cost = Some(vec![12.0]);
455 /// let best_cost = state.get_best_cost();
456 /// # assert_eq!(best_cost.to_ne_bytes(), 12.0f64.to_ne_bytes());
457 /// ```
458 fn get_best_cost(&self) -> Self::Float {
459 match self.best_cost.as_ref() {
460 Some(c) => *(c.first().unwrap_or(&f64::INFINITY)),
461 None => f64::INFINITY,
462 }
463 }
464
465 /// Returns target cost function value.
466 ///
467 /// # Example
468 ///
469 /// ```
470 /// # use cobyla_argmin::CobylaState;
471 /// # use argmin::core::{State, ArgminFloat};
472 /// # let mut state: CobylaState = CobylaState::new();
473 /// # state.target_cost = 12.0;
474 /// let target_cost = state.get_target_cost();
475 /// # assert_eq!(target_cost.to_ne_bytes(), 12.0f64.to_ne_bytes());
476 /// ```
477 fn get_target_cost(&self) -> Self::Float {
478 self.target_cost
479 }
480
481 /// Returns current number of iterations.
482 ///
483 /// # Example
484 ///
485 /// ```
486 /// # use cobyla_argmin::CobylaState;
487 /// # use argmin::core::{State, ArgminFloat};
488 /// # let mut state: CobylaState = CobylaState::new();
489 /// # state.iter = 12;
490 /// let iter = state.get_iter();
491 /// # assert_eq!(iter, 12);
492 /// ```
493 fn get_iter(&self) -> u64 {
494 self.iter
495 }
496
497 /// Returns iteration number of last best parameter vector.
498 ///
499 /// # Example
500 ///
501 /// ```
502 /// # use cobyla_argmin::CobylaState;
503 /// # use argmin::core::{State, ArgminFloat};
504 /// # let mut state: CobylaState = CobylaState::new();
505 /// # state.last_best_iter = 12;
506 /// let last_best_iter = state.get_last_best_iter();
507 /// # assert_eq!(last_best_iter, 12);
508 /// ```
509 fn get_last_best_iter(&self) -> u64 {
510 self.last_best_iter
511 }
512
513 /// Returns the maximum number of iterations.
514 ///
515 /// # Example
516 ///
517 /// ```
518 /// # use cobyla_argmin::CobylaState;
519 /// # use argmin::core::{State, ArgminFloat};
520 /// # let mut state: CobylaState = CobylaState::new();
521 /// # state.max_iters = 12;
522 /// let max_iters = state.get_max_iters();
523 /// # assert_eq!(max_iters, 12);
524 /// ```
525 fn get_max_iters(&self) -> u64 {
526 self.max_iters
527 }
528
529 /// Returns the termination status.
530 ///
531 /// # Example
532 ///
533 /// ```
534 /// # use argmin::core::{State, ArgminFloat, TerminationStatus};
535 /// # use cobyla_argmin::CobylaState;
536 /// # let mut state = CobylaState::new();
537 /// let termination_status = state.get_termination_status();
538 /// # assert_eq!(*termination_status, TerminationStatus::NotTerminated);
539 /// ```
540 fn get_termination_status(&self) -> &TerminationStatus {
541 &self.termination_status
542 }
543
544 /// Returns the termination reason if terminated, otherwise None.
545 ///
546 /// # Example
547 ///
548 /// ```
549 /// # use argmin::core::{State, ArgminFloat, TerminationReason};
550 /// # use cobyla_argmin::CobylaState;
551 /// # let mut state = CobylaState::new();
552 /// let termination_reason = state.get_termination_reason();
553 /// # assert_eq!(termination_reason, None);
554 /// ```
555 fn get_termination_reason(&self) -> Option<&TerminationReason> {
556 match &self.termination_status {
557 TerminationStatus::Terminated(reason) => Some(reason),
558 TerminationStatus::NotTerminated => None,
559 }
560 }
561
562 /// Returns the time elapsed since the start of the optimization.
563 ///
564 /// # Example
565 ///
566 /// ```
567 /// # extern crate web_time;
568 /// # use web_time;
569 /// # use cobyla_argmin::CobylaState;
570 /// # use argmin::core::{State, ArgminFloat};
571 /// # let mut state: CobylaState = CobylaState::new();
572 /// let time = state.get_time();
573 /// # assert_eq!(time.unwrap(), web_time::Duration::new(0, 0));
574 /// ```
575 fn get_time(&self) -> Option<web_time::Duration> {
576 self.time
577 }
578
579 /// Increments the number of iterations by one
580 ///
581 /// # Example
582 ///
583 /// ```
584 /// # use cobyla_argmin::CobylaState;
585 /// # use argmin::core::{State, ArgminFloat};
586 /// # let mut state: CobylaState = CobylaState::new();
587 /// # assert_eq!(state.iter, 0);
588 /// state.increment_iter();
589 /// # assert_eq!(state.iter, 1);
590 /// ```
591 fn increment_iter(&mut self) {
592 self.iter += 1;
593 }
594
595 /// Set all function evaluation counts to the evaluation counts of another `Problem`.
596 ///
597 /// ```
598 /// # use std::collections::HashMap;
599 /// # use cobyla_argmin::CobylaState;
600 /// # use argmin::core::{Problem, State, ArgminFloat};
601 /// # let mut state: CobylaState = CobylaState::new();
602 /// # assert_eq!(state.counts, HashMap::new());
603 /// # state.counts.insert("test2".to_string(), 10u64);
604 /// #
605 /// # #[derive(Eq, PartialEq, Debug)]
606 /// # struct UserDefinedProblem {};
607 /// #
608 /// # let mut problem = Problem::new(UserDefinedProblem {});
609 /// # problem.counts.insert("test1", 10u64);
610 /// # problem.counts.insert("test2", 2);
611 /// state.func_counts(&problem);
612 /// # let mut hm = HashMap::new();
613 /// # hm.insert("test1".to_string(), 10u64);
614 /// # hm.insert("test2".to_string(), 2u64);
615 /// # assert_eq!(state.counts, hm);
616 /// ```
617 fn func_counts<O>(&mut self, problem: &Problem<O>) {
618 for (k, &v) in problem.counts.iter() {
619 let count = self.counts.entry(k.to_string()).or_insert(0);
620 *count = v
621 }
622 }
623
624 /// Returns function evaluation counts
625 ///
626 /// # Example
627 ///
628 /// ```
629 /// # use std::collections::HashMap;
630 /// # use cobyla_argmin::CobylaState;
631 /// # use argmin::core::{State, ArgminFloat};
632 /// # let mut state: CobylaState = CobylaState::new();
633 /// # assert_eq!(state.counts, HashMap::new());
634 /// # state.counts.insert("test2".to_string(), 10u64);
635 /// let counts = state.get_func_counts();
636 /// # let mut hm = HashMap::new();
637 /// # hm.insert("test2".to_string(), 10u64);
638 /// # assert_eq!(*counts, hm);
639 /// ```
640 fn get_func_counts(&self) -> &HashMap<String, u64> {
641 &self.counts
642 }
643
644 /// Returns whether the current parameter vector is also the best parameter vector found so
645 /// far.
646 ///
647 /// # Example
648 ///
649 /// ```
650 /// # use cobyla_argmin::CobylaState;
651 /// # use argmin::core::{State, ArgminFloat};
652 /// # let mut state: CobylaState = CobylaState::new();
653 /// # state.last_best_iter = 12;
654 /// # state.iter = 12;
655 /// let is_best = state.is_best();
656 /// # assert!(is_best);
657 /// # state.last_best_iter = 12;
658 /// # state.iter = 21;
659 /// # let is_best = state.is_best();
660 /// # assert!(!is_best);
661 /// ```
662 fn is_best(&self) -> bool {
663 self.last_best_iter == self.iter
664 }
665}