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}