coco_rs/observer.rs
1//! COCO observer.
2
3use coco_sys::coco_observer_t;
4use std::ffi::{CStr, CString};
5
6/// Observers provided by COCO.
7///
8/// The observer name should match the [`suite::Name`](crate::suite::Name).
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum Name {
11 /// Observer for the BBOB suite.
12 Bbob,
13 /// Observer for the BBOB Bi-Objective suite.
14 BbobBiobj,
15 /// Observer for the toy suite.
16 Toy,
17 /// Dont use any observer.
18 None,
19}
20
21impl Name {
22 fn as_str(&self) -> &'static str {
23 match self {
24 Name::Bbob => "bbob",
25 Name::BbobBiobj => "bbob-biobj",
26 Name::Toy => "toy",
27 Name::None => "no-observer",
28 }
29 }
30}
31
32/// An observer to log results in COCO's data format.
33///
34/// Can be provided to [`Suite::next_problem`](crate::Suite::next_problem) and it will
35/// automatically be attached to the returned problem.
36pub struct Observer {
37 pub(crate) inner: *mut coco_observer_t,
38}
39
40impl Observer {
41 /// Creates a new observer.
42 ///
43 /// # observer_options
44 /// A string of pairs "key: value" used to pass the options to the observer. Some
45 /// observer options are general, while others are specific to some observers. Here we list only the general
46 /// options, see observer_bbob, observer_biobj and observer_toy for options of the specific observers.
47 /// - "result_folder: NAME" determines the folder within the "exdata" folder into which the results will be
48 /// output. If the folder with the given name already exists, first NAME_001 will be tried, then NAME_002 and
49 /// so on. The default value is "default".
50 /// - "algorithm_name: NAME", where NAME is a short name of the algorithm that will be used in plots (no
51 /// spaces are allowed). The default value is "ALG".
52 /// - "algorithm_info: STRING" stores the description of the algorithm. If it contains spaces, it must be
53 /// surrounded by double quotes. The default value is "" (no description).
54 /// - "number_target_triggers: VALUE" defines the number of targets between each 10^i and 10^(i+1)
55 /// (equally spaced in the logarithmic scale) that trigger logging. The default value is 100.
56 /// - "target_precision: VALUE" defines the precision used for targets (there are no targets for
57 /// abs(values) < target_precision). The default value is 1e-8.
58 /// - "number_evaluation_triggers: VALUE" defines the number of evaluations to be logged between each 10^i
59 /// and 10^(i+1). The default value is 20.
60 /// - "base_evaluation_triggers: VALUES" defines the base evaluations used to produce an additional
61 /// evaluation-based logging. The numbers of evaluations that trigger logging are every
62 /// base_evaluation * dimension * (10^i). For example, if base_evaluation_triggers = "1,2,5", the logger will
63 /// be triggered by evaluations dim*1, dim*2, dim*5, 10*dim*1, 10*dim*2, 10*dim*5, 100*dim*1, 100*dim*2,
64 /// 100*dim*5, ... The default value is "1,2,5".
65 /// - "precision_x: VALUE" defines the precision used when outputting variables and corresponds to the number
66 /// of digits to be printed after the decimal point. The default value is 8.
67 /// - "precision_f: VALUE" defines the precision used when outputting f values and corresponds to the number of
68 /// digits to be printed after the decimal point. The default value is 15.
69 /// - "precision_g: VALUE" defines the precision used when outputting constraints and corresponds to the number
70 /// of digits to be printed after the decimal point. The default value is 3.
71 /// - "log_discrete_as_int: VALUE" determines whether the values of integer variables (in mixed-integer problems)
72 /// are logged as integers (1) or not (0 - in this case they are logged as doubles). The default value is 0.
73 pub fn new(name: Name, options: &str) -> Option<Observer> {
74 let name = CString::new(name.as_str()).unwrap();
75 let options = CString::new(options).unwrap();
76
77 let inner = unsafe { coco_sys::coco_observer(name.as_ptr(), options.as_ptr()) };
78
79 if inner.is_null() {
80 None
81 } else {
82 Some(Observer { inner })
83 }
84 }
85
86 /// Prints where the result is written to.
87 pub fn result_folder(&self) -> &str {
88 unsafe {
89 CStr::from_ptr(coco_sys::coco_observer_get_result_folder(self.inner))
90 .to_str()
91 .unwrap()
92 }
93 }
94}
95
96impl Drop for Observer {
97 fn drop(&mut self) {
98 unsafe {
99 coco_sys::coco_observer_free(self.inner);
100 }
101 }
102}