1use coco_sys::coco_problem_t;
4use std::{ffi::CStr, marker::PhantomData, ops::RangeInclusive};
5
6use crate::{
7 suite::{self, Suite},
8 Observer,
9};
10
11pub struct Problem<'suite> {
16 pub(crate) inner: *mut coco_problem_t,
17 _phantom: PhantomData<&'suite Suite>,
18}
19
20unsafe impl Send for Problem<'_> {}
21
22impl<'suite> Problem<'suite> {
23 pub(crate) fn new(inner: *mut coco_problem_t, _suite: &'suite Suite) -> Self {
24 Problem {
25 inner,
26 _phantom: PhantomData,
27 }
28 }
29}
30
31impl Problem<'_> {
32 pub fn id(&self) -> &str {
40 unsafe {
41 CStr::from_ptr(coco_sys::coco_problem_get_id(self.inner))
42 .to_str()
43 .unwrap()
44 }
45 }
46
47 pub fn name(&self) -> &str {
49 unsafe {
50 CStr::from_ptr(coco_sys::coco_problem_get_name(self.inner))
51 .to_str()
52 .unwrap()
53 }
54 }
55
56 pub fn typ(&self) -> &str {
58 unsafe {
59 CStr::from_ptr(coco_sys::coco_problem_get_type(self.inner))
60 .to_str()
61 .unwrap()
62 }
63 }
64
65 pub fn add_observer(&mut self, observer: &Observer) {
67 self.inner = unsafe { coco_sys::coco_problem_add_observer(self.inner, observer.inner) };
69
70 assert!(!self.inner.is_null())
71 }
72
73 pub fn remove_observer(&mut self, observer: &Observer) {
75 self.inner = unsafe { coco_sys::coco_problem_remove_observer(self.inner, observer.inner) };
77
78 assert!(!self.inner.is_null())
79 }
80
81 pub fn suite_index(&self) -> suite::ProblemIdx {
83 let idx = unsafe { coco_sys::coco_problem_get_suite_dep_index(self.inner) };
84
85 suite::ProblemIdx(idx)
86 }
87
88 pub fn evaluate_function(&mut self, x: &[f64], y: &mut [f64]) {
93 assert_eq!(self.dimension(), x.len());
94 assert_eq!(self.number_of_objectives(), y.len());
95
96 unsafe {
97 coco_sys::coco_evaluate_function(self.inner, x.as_ptr(), y.as_mut_ptr());
98 }
99 }
100
101 pub fn evaluate_constraint(&mut self, x: &[f64], y: &mut [f64]) {
106 assert_eq!(self.dimension(), x.len());
107 assert_eq!(self.number_of_constraints(), y.len());
108
109 unsafe {
110 coco_sys::coco_evaluate_constraint(self.inner, x.as_ptr(), y.as_mut_ptr());
111 }
112 }
113
114 pub fn final_target_hit(&self) -> bool {
116 unsafe { coco_sys::coco_problem_final_target_hit(self.inner) == 1 }
117 }
118
119 pub fn final_target_value(&self) -> f64 {
121 unsafe { coco_sys::coco_problem_get_final_target_fvalue1(self.inner) }
122 }
123
124 pub fn best_value(&self) -> f64 {
129 unsafe { coco_sys::coco_problem_get_best_value(self.inner) }
130 }
131
132 pub fn best_observed_value(&self) -> f64 {
134 unsafe { coco_sys::coco_problem_get_best_observed_fvalue1(self.inner) }
135 }
136
137 pub fn dimension(&self) -> usize {
139 unsafe {
140 coco_sys::coco_problem_get_dimension(self.inner)
141 .try_into()
142 .unwrap()
143 }
144 }
145
146 pub fn number_of_objectives(&self) -> usize {
148 unsafe {
149 coco_sys::coco_problem_get_number_of_objectives(self.inner)
150 .try_into()
151 .unwrap()
152 }
153 }
154
155 pub fn number_of_constraints(&self) -> usize {
157 unsafe {
158 coco_sys::coco_problem_get_number_of_constraints(self.inner)
159 .try_into()
160 .unwrap()
161 }
162 }
163
164 pub fn number_of_integer_variables(&self) -> usize {
169 unsafe {
170 coco_sys::coco_problem_get_number_of_integer_variables(self.inner)
171 .try_into()
172 .unwrap()
173 }
174 }
175
176 pub fn ranges_of_interest(&self) -> Vec<RangeInclusive<f64>> {
178 let dimension = self.dimension() as isize;
179 unsafe {
180 let smallest = coco_sys::coco_problem_get_smallest_values_of_interest(self.inner);
181 let largest = coco_sys::coco_problem_get_largest_values_of_interest(self.inner);
182
183 (0..dimension)
184 .map(|i| (*smallest.offset(i))..=(*largest.offset(i)))
185 .collect()
186 }
187 }
188
189 pub fn evaluations(&self) -> u64 {
191 unsafe {
192 #[allow(clippy::useless_conversion)]
193 coco_sys::coco_problem_get_evaluations(self.inner)
194 .try_into()
195 .unwrap()
196 }
197 }
198
199 pub fn evaluations_constraints(&self) -> u64 {
201 unsafe {
202 #[allow(clippy::useless_conversion)]
203 coco_sys::coco_problem_get_evaluations_constraints(self.inner)
204 .try_into()
205 .unwrap()
206 }
207 }
208
209 pub fn initial_solution(&self, x: &mut [f64]) {
214 assert_eq!(self.dimension(), x.len());
215 unsafe {
216 coco_sys::coco_problem_get_initial_solution(self.inner, x.as_mut_ptr());
217 }
218 }
219}
220
221impl Drop for Problem<'_> {
222 fn drop(&mut self) {
223 unsafe {
224 coco_sys::coco_problem_free(self.inner);
225 }
226 }
227}