argmin/core/
problem.rs

1// Copyright 2018-2024 argmin developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8use crate::core::{ArgminFloat, Error, SendAlias, SyncAlias};
9#[cfg(feature = "rayon")]
10use rayon::prelude::*;
11use std::collections::HashMap;
12
13/// Wrapper around problems defined by users.
14///
15/// Keeps track of how many times methods such as `apply`, `cost`, `gradient`, `jacobian`,
16/// `hessian`, `anneal` and so on are called. It is used to pass the problem from one iteration of
17/// a solver to the next.
18#[derive(Clone, Debug, Default)]
19pub struct Problem<O> {
20    /// Problem defined by user
21    pub problem: Option<O>,
22    /// Keeps track of how often methods of `problem` have been called.
23    pub counts: HashMap<&'static str, u64>,
24}
25
26impl<O> Problem<O> {
27    /// Wraps a problem into an instance of `Problem`.
28    ///
29    /// # Example
30    ///
31    /// ```
32    /// # use argmin::core::Problem;
33    /// # use std::collections::HashMap;
34    /// #
35    /// # #[derive(Eq, PartialEq, Debug)]
36    /// # struct UserDefinedProblem {};
37    /// #
38    /// let wrapped_problem = Problem::new(UserDefinedProblem {});
39    /// #
40    /// # assert_eq!(wrapped_problem.problem.unwrap(), UserDefinedProblem {});
41    /// # assert_eq!(wrapped_problem.counts, HashMap::new());
42    /// ```
43    pub fn new(problem: O) -> Self {
44        Problem {
45            problem: Some(problem),
46            counts: HashMap::new(),
47        }
48    }
49
50    /// Gives access to the stored `problem` via the closure `func` and keeps track of how many
51    /// times the function has been called. The function counts will be passed to observers labeled
52    /// with `counts_string`. Per convention, `counts_string` is chosen as `<something>_count`.
53    ///
54    /// # Example
55    ///
56    /// ```
57    /// # use argmin::core::{test_utils::TestProblem, Problem, CostFunction};
58    /// # let mut problem = Problem::new(TestProblem::new());
59    /// # let param = vec![1.0f64, 0.0];
60    /// let cost = problem.problem("cost_count", |problem| problem.cost(&param));
61    /// # assert_eq!(problem.counts["cost_count"], 1)
62    /// ```
63    ///
64    /// This is typically used when designing a trait which optimization problems need to implement
65    /// for certain solvers. For instance, for a trait `Anneal` used in Simulated Annealing, one
66    /// would write the following to enable the solver to call `.anneal(...)` on an `Problem`
67    /// directly:
68    ///
69    /// ```
70    /// # // needs to reimplement Problem because doctests run in dedicated crate where it is not
71    /// # // possible to `impl` a type from another crate.
72    /// # // Probably somewhat related to https://github.com/rust-lang/rust/issues/50784
73    /// # use argmin::core::Error;
74    /// # use std::collections::HashMap;
75    /// #
76    /// # pub struct Problem<O> {
77    /// #     pub problem: Option<O>,
78    /// #     pub counts: HashMap<&'static str, u64>,
79    /// # }
80    /// # impl<O> Problem<O> {
81    /// #     pub fn problem<T, F: FnOnce(&O) -> Result<T, Error>>(
82    /// #         &mut self,
83    /// #         counts_string: &'static str,
84    /// #         func: F,
85    /// #     ) -> Result<T, Error> {
86    /// #         let count = self.counts.entry(counts_string).or_insert(0);
87    /// #         *count += 1;
88    /// #         func(self.problem.as_ref().unwrap())
89    /// #     }
90    /// # }
91    /// pub trait Anneal {
92    ///     type Param;
93    ///     type Output;
94    ///     type Float;
95    ///
96    ///     fn anneal(&self, param: &Self::Param, extent: Self::Float) -> Result<Self::Output, Error>;
97    /// }
98    ///
99    /// impl<O: Anneal> Problem<O> {
100    ///     pub fn anneal(&mut self, param: &O::Param, extent: O::Float) -> Result<O::Output, Error> {
101    ///         self.problem("anneal_count", |problem| problem.anneal(param, extent))
102    ///     }
103    /// }
104    ///
105    /// // ...
106    ///
107    /// # struct TestProblem {}
108    /// # impl Anneal for TestProblem {
109    /// #     type Param = ();
110    /// #     type Output = ();
111    /// #     type Float = f64;
112    /// #
113    /// #     fn anneal(&self, param: &Self::Param, _extent: Self::Float) -> Result<Self::Output, Error> {
114    /// #         Ok(())
115    /// #     }
116    /// # }
117    /// # let mut problem = Problem { problem: Some(TestProblem {}), counts: HashMap::new() };
118    /// # let param = ();
119    /// let new_param = problem.anneal(&param, 1.0f64);
120    /// # assert_eq!(problem.counts["anneal_count"], 1)
121    /// ```
122    ///
123    /// Note that this will unfortunately only work inside the `argmin` crate itself due to the fact
124    /// that it is not possible to `impl` a type from another crate. Therefore if one implements a
125    /// solver outside of argmin, `.problem(...)` has to be called directly as shown in the first
126    /// example.
127    pub fn problem<T, F: FnOnce(&O) -> Result<T, Error>>(
128        &mut self,
129        counts_string: &'static str,
130        func: F,
131    ) -> Result<T, Error> {
132        let count = self.counts.entry(counts_string).or_insert(0);
133        *count += 1;
134        func(self.problem.as_ref().unwrap())
135    }
136
137    /// Gives access to the stored `problem` via the closure `func` and keeps track of how many
138    /// times the function has been called. In contrast to the `problem` method, this also allows
139    /// to pass the number of parameter vectors which will be processed by the underlying problem.
140    /// This is used by the `bulk_*` methods, which process multiple parameters at once.
141    /// The function counts will be passed to observers labeled with `counts_string`.
142    /// Per convention, `counts_string` is chosen as `<something>_count`.
143    pub fn bulk_problem<T, F: FnOnce(&O) -> Result<T, Error>>(
144        &mut self,
145        counts_string: &'static str,
146        num_param_vecs: usize,
147        func: F,
148    ) -> Result<T, Error> {
149        let count = self.counts.entry(counts_string).or_insert(0);
150        *count += num_param_vecs as u64;
151        func(self.problem.as_ref().unwrap())
152    }
153
154    /// Returns the internally stored problem and replaces it with `None`.
155    ///
156    /// # Example
157    ///
158    /// ```
159    /// # use argmin::core::Problem;
160    /// # use std::collections::HashMap;
161    /// #
162    /// # #[derive(Eq, PartialEq, Debug)]
163    /// # struct UserDefinedProblem {};
164    /// #
165    /// let mut problem = Problem::new(UserDefinedProblem {});
166    /// let user_problem: Option<UserDefinedProblem> = problem.take_problem();
167    ///
168    /// assert_eq!(user_problem.unwrap(), UserDefinedProblem {});
169    /// assert!(problem.problem.is_none());
170    /// # assert_eq!(problem.counts, HashMap::new());
171    /// ```
172    pub fn take_problem(&mut self) -> Option<O> {
173        self.problem.take()
174    }
175
176    /// Consumes another instance of `Problem`. The internally stored user defined problem of the
177    /// passed `Problem` instance is moved to `Self`. The function evaluation counts are
178    /// merged/summed up.
179    ///
180    /// # Example
181    ///
182    /// ```
183    /// # use argmin::core::Problem;
184    /// #
185    /// # #[derive(Eq, PartialEq, Debug, Clone)]
186    /// # struct UserDefinedProblem {};
187    /// #
188    /// let mut problem1 = Problem::new(UserDefinedProblem {});
189    ///
190    /// // Simulate function evaluation counts in `problem1`
191    /// problem1.counts.insert("cost_count", 2);
192    ///
193    /// // Take the internally stored problem such that `None` remains in its place.
194    /// let _ = problem1.take_problem();
195    /// assert!(problem1.problem.is_none());
196    ///
197    /// let mut problem2 = Problem::new(UserDefinedProblem {});
198    ///
199    /// // Simulate function evaluation counts in `problem2`
200    /// problem2.counts.insert("cost_count", 1);
201    /// problem2.counts.insert("gradient_count", 4);
202    ///
203    /// // `problem1` consumes `problem2` by moving its internally stored user defined problem and
204    /// // by merging the function evaluation counts
205    /// problem1.consume_problem(problem2);
206    ///
207    /// // `problem1` now holds a problem of type `UserDefinedProblem` (taken from `problem2`)
208    /// assert_eq!(problem1.problem.unwrap(), UserDefinedProblem {});
209    ///
210    /// // The function evaluation counts have been merged
211    /// assert_eq!(problem1.counts["cost_count"], 3);
212    /// assert_eq!(problem1.counts["gradient_count"], 4);
213    /// ```
214    pub fn consume_problem(&mut self, mut other: Problem<O>) {
215        self.problem = Some(other.take_problem().unwrap());
216        self.consume_func_counts(other);
217    }
218
219    /// Consumes another instance of `Problem` by summing ob the function evaluation counts.
220    /// In contrast to `consume_problem`, the internally stored `problem` remains untouched.
221    /// Therefore the two internally stored problems do not need to be of the same type.
222    ///
223    /// # Example
224    ///
225    /// ```
226    /// # use argmin::core::Problem;
227    /// #
228    /// # #[derive(Eq, PartialEq, Debug, Clone)]
229    /// # struct UserDefinedProblem1 {};
230    /// #
231    /// # #[derive(Eq, PartialEq, Debug, Clone)]
232    /// # struct UserDefinedProblem2 {};
233    /// #
234    /// let mut problem1 = Problem::new(UserDefinedProblem1 {});
235    ///
236    /// // Simulate function evaluation counts in `problem1`.
237    /// problem1.counts.insert("cost_count", 2);
238    ///
239    /// // Take the internally stored problem such that `None` remains in its place.
240    /// let _ = problem1.take_problem();
241    /// assert!(problem1.problem.is_none());
242    ///
243    /// let mut problem2 = Problem::new(UserDefinedProblem2 {});
244    ///
245    /// // Simulate function evaluation counts in `problem2`
246    /// problem2.counts.insert("cost_count", 1);
247    /// problem2.counts.insert("gradient_count", 4);
248    ///
249    /// // `problem1` consumes `problem2` by merging the function evaluation counts.
250    /// problem1.consume_func_counts(problem2);
251    ///
252    /// // The internally stored problem remains being `None` (in contrast to `consume_problem`).
253    /// assert!(problem1.problem.is_none());
254    ///
255    /// // The function evaluation counts have been merged.
256    /// assert_eq!(problem1.counts["cost_count"], 3);
257    /// assert_eq!(problem1.counts["gradient_count"], 4);
258    /// ```
259    pub fn consume_func_counts<O2>(&mut self, other: Problem<O2>) {
260        for (k, v) in other.counts.iter() {
261            let count = self.counts.entry(k).or_insert(0);
262            *count += v
263        }
264    }
265
266    /// Resets the function evaluation counts to zero.
267    ///
268    /// # Example
269    ///
270    /// ```
271    /// # use argmin::core::Problem;
272    /// #
273    /// # #[derive(Eq, PartialEq, Debug, Clone)]
274    /// # struct UserDefinedProblem {};
275    /// #
276    /// let mut problem = Problem::new(UserDefinedProblem {});
277    ///
278    /// // Simulate function evaluation counts in `problem1`.
279    /// problem.counts.insert("cost_count", 2);
280    /// problem.counts.insert("gradient_count", 4);
281    ///
282    /// assert_eq!(problem.counts["cost_count"], 2);
283    /// assert_eq!(problem.counts["gradient_count"], 4);
284    ///
285    /// // Set function evaluation counts to 0
286    /// problem.reset();
287    ///
288    /// assert_eq!(problem.counts["cost_count"], 0);
289    /// assert_eq!(problem.counts["gradient_count"], 0);
290    /// ```
291    pub fn reset(&mut self) {
292        for (_, v) in self.counts.iter_mut() {
293            *v = 0;
294        }
295    }
296
297    /// Returns the internally stored user defined problem by consuming `Self`.
298    ///
299    /// # Example
300    ///
301    /// ```
302    /// # use argmin::core::Problem;
303    /// #
304    /// # #[derive(Eq, PartialEq, Debug, Clone)]
305    /// # struct UserDefinedProblem {};
306    /// #
307    /// let problem = Problem::new(UserDefinedProblem {});
308    ///
309    /// let user_problem = problem.get_problem();
310    ///
311    /// assert_eq!(user_problem.unwrap(), UserDefinedProblem {});
312    /// ```
313    pub fn get_problem(self) -> Option<O> {
314        self.problem
315    }
316}
317
318/// Defines the application of an operator to a parameter vector.
319///
320/// # Example
321///
322/// ```
323/// use argmin::core::{Operator, Error};
324/// use argmin_math::ArgminDot;
325///
326/// struct Model {
327///     matrix: Vec<Vec<f64>>,
328/// }
329///
330/// impl Operator for Model {
331///     type Param = Vec<f64>;
332///     type Output = Vec<f64>;
333///
334///     /// Multiply matrix `self.matrix` with vector `param`
335///     fn apply(&self, param: &Self::Param) -> Result<Self::Output, Error> {
336///         Ok(self.matrix.dot(param))
337///     }
338/// }
339/// ```
340pub trait Operator {
341    /// Type of the parameter vector
342    type Param;
343    /// Type of the return value of the operator
344    type Output;
345
346    /// Applies the operator to parameters
347    fn apply(&self, param: &Self::Param) -> Result<Self::Output, Error>;
348
349    bulk!(apply, Self::Param, Self::Output);
350}
351
352/// Defines computation of a cost function value
353///
354/// # Example
355///
356/// ```
357/// use argmin::core::{CostFunction, Error};
358/// use argmin_testfunctions::rosenbrock;
359///
360/// struct Rosenbrock {}
361///
362/// impl CostFunction for Rosenbrock {
363///     type Param = Vec<f64>;
364///     type Output = f64;
365///
366///     /// Compute Rosenbrock function
367///     fn cost(&self, param: &Self::Param) -> Result<Self::Output, Error> {
368///         Ok(rosenbrock(param))
369///     }
370/// }
371/// ```
372pub trait CostFunction {
373    /// Type of the parameter vector
374    type Param;
375    /// Type of the return value of the cost function
376    type Output;
377
378    /// Compute cost function
379    fn cost(&self, param: &Self::Param) -> Result<Self::Output, Error>;
380
381    bulk!(cost, Self::Param, Self::Output);
382}
383
384/// Defines the computation of the gradient.
385///
386/// # Example
387///
388/// ```
389/// use argmin::core::{Gradient, Error};
390/// # fn compute_gradient(_a: &[f64]) -> Vec<f64> { vec![] }
391///
392/// struct Rosenbrock {}
393///
394/// impl Gradient for Rosenbrock {
395///     type Param = Vec<f64>;
396///     type Gradient = Vec<f64>;
397///
398///     /// Compute gradient of rosenbrock function
399///     fn gradient(&self, param: &Self::Param) -> Result<Self::Gradient, Error> {
400///         Ok(compute_gradient(param))
401///     }
402/// }
403/// ```
404pub trait Gradient {
405    /// Type of the parameter vector
406    type Param;
407    /// Type of the gradient
408    type Gradient;
409
410    /// Compute gradient
411    fn gradient(&self, param: &Self::Param) -> Result<Self::Gradient, Error>;
412
413    bulk!(gradient, Self::Param, Self::Gradient);
414}
415
416/// Defines the computation of the Hessian.
417///
418/// # Example
419///
420/// ```
421/// use argmin::core::{Hessian, Error};
422/// # fn compute_hessian(_a: &[f64]) -> Vec<f64> { vec![] }
423///
424/// struct Rosenbrock {}
425///
426/// impl Hessian for Rosenbrock {
427///     type Param = Vec<f64>;
428///     type Hessian = Vec<f64>;
429///
430///     /// Compute gradient of rosenbrock function
431///     fn hessian(&self, param: &Self::Param) -> Result<Self::Hessian, Error> {
432///         Ok(compute_hessian(&param))
433///     }
434/// }
435pub trait Hessian {
436    /// Type of the parameter vector
437    type Param;
438    /// Type of the Hessian
439    type Hessian;
440
441    /// Compute Hessian
442    fn hessian(&self, param: &Self::Param) -> Result<Self::Hessian, Error>;
443
444    bulk!(hessian, Self::Param, Self::Hessian);
445}
446
447/// Defines the computation of the Jacobian.
448///
449/// # Example
450///
451/// ```
452/// use argmin::core::{Jacobian, Error};
453///
454/// struct Problem {}
455///
456/// # fn problem_jacobian(p: &[f64]) -> Vec<Vec<f64>> {
457/// #     vec![vec![1.0f64, 2.0f64], vec![1.0f64, 2.0f64]]
458/// # }
459/// #
460/// impl Jacobian for Problem {
461///     type Param = Vec<f64>;
462///     type Jacobian = Vec<Vec<f64>>;
463///
464///     fn jacobian(&self, p: &Self::Param) -> Result<Self::Jacobian, Error> {
465///         Ok(problem_jacobian(p))
466///     }
467/// }
468/// ```
469pub trait Jacobian {
470    /// Type of the parameter vector
471    type Param;
472    /// Type of the Jacobian
473    type Jacobian;
474
475    /// Compute Jacobian
476    fn jacobian(&self, param: &Self::Param) -> Result<Self::Jacobian, Error>;
477
478    bulk!(jacobian, Self::Param, Self::Jacobian);
479}
480
481/// Defines a linear Program
482///
483/// # Example
484///
485/// ```
486/// use argmin::core::{LinearProgram, Error};
487///
488/// struct Problem {}
489///
490/// impl LinearProgram for Problem {
491///     type Param = Vec<f64>;
492///     type Float = f64;
493///
494///     fn c(&self) -> Result<Vec<Self::Float>, Error> {
495///         Ok(vec![1.0, 2.0])
496///     }
497///
498///     fn b(&self) -> Result<Vec<Self::Float>, Error> {
499///         Ok(vec![3.0, 4.0])
500///     }
501///
502///     fn A(&self) -> Result<Vec<Vec<Self::Float>>, Error> {
503///         Ok(vec![vec![5.0, 6.0], vec![7.0, 8.0]])
504///     }
505/// }
506/// ```
507pub trait LinearProgram {
508    /// Type of the parameter vector
509    type Param;
510    /// Precision of floats
511    type Float: ArgminFloat;
512
513    /// TODO c for linear programs
514    /// Those three could maybe be merged into a single function; name unclear
515    fn c(&self) -> Result<Vec<Self::Float>, Error> {
516        Err(argmin_error!(
517            NotImplemented,
518            "Method `c` of LinearProgram trait not implemented!"
519        ))
520    }
521
522    /// TODO b for linear programs
523    fn b(&self) -> Result<Vec<Self::Float>, Error> {
524        Err(argmin_error!(
525            NotImplemented,
526            "Method `b` of LinearProgram trait not implemented!"
527        ))
528    }
529
530    /// TODO A for linear programs
531    #[allow(non_snake_case)]
532    fn A(&self) -> Result<Vec<Vec<Self::Float>>, Error> {
533        Err(argmin_error!(
534            NotImplemented,
535            "Method `A` of LinearProgram trait not implemented!"
536        ))
537    }
538}
539
540/// Wraps a call to `apply` defined in the `Operator` trait and as such allows to call `apply` on
541/// an instance of `Problem`. Internally, the number of evaluations of `apply` is counted.
542impl<O: Operator> Problem<O> {
543    /// Calls `apply` defined in the `Operator` trait and keeps track of the number of evaluations.
544    ///
545    /// # Example
546    ///
547    /// ```
548    /// # use argmin::core::{Problem, Operator, Error};
549    /// #
550    /// # #[derive(Eq, PartialEq, Debug, Clone)]
551    /// # struct UserDefinedProblem {};
552    /// #
553    /// # impl Operator for UserDefinedProblem {
554    /// #     type Param = Vec<f64>;
555    /// #     type Output = Vec<f64>;
556    /// #
557    /// #     fn apply(&self, param: &Self::Param) -> Result<Self::Output, Error> {
558    /// #         Ok(vec![1.0f64, 1.0f64])
559    /// #     }
560    /// # }
561    /// // `UserDefinedProblem` implements `Operator`.
562    /// let mut problem1 = Problem::new(UserDefinedProblem {});
563    ///
564    /// let param = vec![2.0f64, 1.0f64];
565    ///
566    /// let res = problem1.apply(&param);
567    ///
568    /// assert_eq!(problem1.counts["operator_count"], 1);
569    /// # assert_eq!(res.unwrap(), vec![1.0f64, 1.0f64]);
570    /// ```
571    pub fn apply(&mut self, param: &O::Param) -> Result<O::Output, Error> {
572        self.problem("operator_count", |problem| problem.apply(param))
573    }
574
575    /// Calls `bulk_apply` defined in the `Operator` trait and keeps track of the number of
576    /// evaluations.
577    ///
578    /// # Example
579    ///
580    /// ```
581    /// # use argmin::core::{Problem, Operator, Error};
582    /// #
583    /// # #[derive(Eq, PartialEq, Debug, Clone)]
584    /// # struct UserDefinedProblem {};
585    /// #
586    /// # impl Operator for UserDefinedProblem {
587    /// #     type Param = Vec<f64>;
588    /// #     type Output = Vec<f64>;
589    /// #
590    /// #     fn apply(&self, param: &Self::Param) -> Result<Self::Output, Error> {
591    /// #         Ok(vec![1.0f64, 1.0f64])
592    /// #     }
593    /// # }
594    /// // `UserDefinedProblem` implements `Operator`.
595    /// let mut problem1 = Problem::new(UserDefinedProblem {});
596    ///
597    /// let param1 = vec![2.0f64, 1.0f64];
598    /// let param2 = vec![3.0f64, 5.0f64];
599    /// let params = vec![&param1, &param2];
600    ///
601    /// let res = problem1.bulk_apply(&params);
602    ///
603    /// assert_eq!(problem1.counts["operator_count"], 2);
604    /// # let res = res.unwrap();
605    /// # assert_eq!(res[0], vec![1.0f64, 1.0f64]);
606    /// # assert_eq!(res[1], vec![1.0f64, 1.0f64]);
607    /// ```
608    pub fn bulk_apply<P>(&mut self, params: &[P]) -> Result<Vec<O::Output>, Error>
609    where
610        P: std::borrow::Borrow<O::Param> + SyncAlias,
611        O::Output: SendAlias,
612        O: SyncAlias,
613    {
614        self.bulk_problem("operator_count", params.len(), |problem| {
615            problem.bulk_apply(params)
616        })
617    }
618}
619
620/// Wraps a call to `cost` defined in the `CostFunction` trait and as such allows to call `cost` on
621/// an instance of `Problem`. Internally, the number of evaluations of `cost` is counted.
622impl<O: CostFunction> Problem<O> {
623    /// Calls `cost` defined in the `CostFunction` trait and keeps track of the number of
624    /// evaluations.
625    ///
626    /// # Example
627    ///
628    /// ```
629    /// # use argmin::core::{Problem, CostFunction, Error};
630    /// #
631    /// # #[derive(Eq, PartialEq, Debug, Clone)]
632    /// # struct UserDefinedProblem {};
633    /// #
634    /// # impl CostFunction for UserDefinedProblem {
635    /// #     type Param = Vec<f64>;
636    /// #     type Output = f64;
637    /// #
638    /// #     fn cost(&self, param: &Self::Param) -> Result<Self::Output, Error> {
639    /// #         Ok(4.0f64)
640    /// #     }
641    /// # }
642    /// // `UserDefinedProblem` implements `CostFunction`.
643    /// let mut problem1 = Problem::new(UserDefinedProblem {});
644    ///
645    /// let param = vec![2.0f64, 1.0f64];
646    ///
647    /// let res = problem1.cost(&param);
648    ///
649    /// assert_eq!(problem1.counts["cost_count"], 1);
650    /// # assert_eq!(res.unwrap(), 4.0f64);
651    /// ```
652    pub fn cost(&mut self, param: &O::Param) -> Result<O::Output, Error> {
653        self.problem("cost_count", |problem| problem.cost(param))
654    }
655
656    /// Calls `bulk_cost` defined in the `CostFunction` trait and keeps track of the number of
657    /// evaluations.
658    ///
659    /// # Example
660    ///
661    /// ```
662    /// # use argmin::core::{Problem, CostFunction, Error};
663    /// #
664    /// # #[derive(Eq, PartialEq, Debug, Clone)]
665    /// # struct UserDefinedProblem {};
666    /// #
667    /// # impl CostFunction for UserDefinedProblem {
668    /// #     type Param = Vec<f64>;
669    /// #     type Output = f64;
670    /// #
671    /// #     fn cost(&self, param: &Self::Param) -> Result<Self::Output, Error> {
672    /// #         Ok(4.0f64)
673    /// #     }
674    /// # }
675    /// // `UserDefinedProblem` implements `CostFunction`.
676    /// let mut problem1 = Problem::new(UserDefinedProblem {});
677    ///
678    /// let param1 = vec![2.0f64, 1.0f64];
679    /// let param2 = vec![3.0f64, 5.0f64];
680    /// let params = vec![&param1, &param2];
681    ///
682    /// let res = problem1.bulk_cost(&params);
683    ///
684    /// assert_eq!(problem1.counts["cost_count"], 2);
685    /// # let res = res.unwrap();
686    /// # assert_eq!(res[0], 4.0f64);
687    /// # assert_eq!(res[1], 4.0f64);
688    /// ```
689    pub fn bulk_cost<P>(&mut self, params: &[P]) -> Result<Vec<O::Output>, Error>
690    where
691        P: std::borrow::Borrow<O::Param> + SyncAlias,
692        O::Output: SendAlias,
693        O: SyncAlias,
694    {
695        self.bulk_problem("cost_count", params.len(), |problem| {
696            problem.bulk_cost(params)
697        })
698    }
699}
700
701/// Wraps a call to `gradient` defined in the `Gradient` trait and as such allows to call `gradient` on
702/// an instance of `Problem`. Internally, the number of evaluations of `gradient` is counted.
703impl<O: Gradient> Problem<O> {
704    /// Calls `gradient` defined in the `Gradient` trait and keeps track of the number of
705    /// evaluations.
706    ///
707    /// # Example
708    ///
709    /// ```
710    /// # use argmin::core::{Problem, Gradient, Error};
711    /// #
712    /// # #[derive(Eq, PartialEq, Debug, Clone)]
713    /// # struct UserDefinedProblem {};
714    /// #
715    /// # impl Gradient for UserDefinedProblem {
716    /// #     type Param = Vec<f64>;
717    /// #     type Gradient = Vec<f64>;
718    /// #
719    /// #     fn gradient(&self, param: &Self::Param) -> Result<Self::Gradient, Error> {
720    /// #         Ok(vec![1.0f64, 1.0f64])
721    /// #     }
722    /// # }
723    /// // `UserDefinedProblem` implements `Gradient`.
724    /// let mut problem1 = Problem::new(UserDefinedProblem {});
725    ///
726    /// let param = vec![2.0f64, 1.0f64];
727    ///
728    /// let res = problem1.gradient(&param);
729    ///
730    /// assert_eq!(problem1.counts["gradient_count"], 1);
731    /// # assert_eq!(res.unwrap(), vec![1.0f64, 1.0f64]);
732    /// ```
733    pub fn gradient(&mut self, param: &O::Param) -> Result<O::Gradient, Error> {
734        self.problem("gradient_count", |problem| problem.gradient(param))
735    }
736
737    /// Calls `bulk_gradient` defined in the `Gradient` trait and keeps track of the number of
738    /// evaluations.
739    ///
740    /// # Example
741    ///
742    /// ```
743    /// # use argmin::core::{Problem, Gradient, Error};
744    /// #
745    /// # #[derive(Eq, PartialEq, Debug, Clone)]
746    /// # struct UserDefinedProblem {};
747    /// #
748    /// # impl Gradient for UserDefinedProblem {
749    /// #     type Param = Vec<f64>;
750    /// #     type Gradient = Vec<f64>;
751    /// #
752    /// #     fn gradient(&self, param: &Self::Param) -> Result<Self::Gradient, Error> {
753    /// #         Ok(vec![1.0f64, 1.0f64])
754    /// #     }
755    /// # }
756    /// // `UserDefinedProblem` implements `Gradient`.
757    /// let mut problem1 = Problem::new(UserDefinedProblem {});
758    ///
759    /// let param1 = vec![2.0f64, 1.0f64];
760    /// let param2 = vec![3.0f64, 5.0f64];
761    /// let params = vec![&param1, &param2];
762    ///
763    /// let res = problem1.bulk_gradient(&params);
764    ///
765    /// assert_eq!(problem1.counts["gradient_count"], 2);
766    /// # let res = res.unwrap();
767    /// # assert_eq!(res[0], vec![1.0f64, 1.0f64]);
768    /// # assert_eq!(res[1], vec![1.0f64, 1.0f64]);
769    /// ```
770    pub fn bulk_gradient<P>(&mut self, params: &[P]) -> Result<Vec<O::Gradient>, Error>
771    where
772        P: std::borrow::Borrow<O::Param> + SyncAlias,
773        O::Gradient: SendAlias,
774        O: SyncAlias,
775    {
776        self.bulk_problem("gradient_count", params.len(), |problem| {
777            problem.bulk_gradient(params)
778        })
779    }
780}
781
782/// Wraps a call to `hessian` defined in the `Hessian` trait and as such allows to call `hessian` on
783/// an instance of `Problem`. Internally, the number of evaluations of `hessian` is counted.
784impl<O: Hessian> Problem<O> {
785    /// Calls `hessian` defined in the `Hessian` trait and keeps track of the number of evaluations.
786    ///
787    /// # Example
788    ///
789    /// ```
790    /// # use argmin::core::{Problem, Hessian, Error};
791    /// #
792    /// # #[derive(Eq, PartialEq, Debug, Clone)]
793    /// # struct UserDefinedProblem {};
794    /// #
795    /// # impl Hessian for UserDefinedProblem {
796    /// #     type Param = Vec<f64>;
797    /// #     type Hessian = Vec<Vec<f64>>;
798    /// #
799    /// #     fn hessian(&self, param: &Self::Param) -> Result<Self::Hessian, Error> {
800    /// #         Ok(vec![vec![1.0f64, 0.0f64], vec![0.0f64, 1.0f64]])
801    /// #     }
802    /// # }
803    /// // `UserDefinedProblem` implements `Hessian`.
804    /// let mut problem1 = Problem::new(UserDefinedProblem {});
805    ///
806    /// let param = vec![2.0f64, 1.0f64];
807    ///
808    /// let res = problem1.hessian(&param);
809    ///
810    /// assert_eq!(problem1.counts["hessian_count"], 1);
811    /// # assert_eq!(res.unwrap(), vec![vec![1.0f64, 0.0f64], vec![0.0f64, 1.0f64]]);
812    /// ```
813    pub fn hessian(&mut self, param: &O::Param) -> Result<O::Hessian, Error> {
814        self.problem("hessian_count", |problem| problem.hessian(param))
815    }
816
817    /// Calls `bulk_hessian` defined in the `Hessian` trait and keeps track of the number of
818    /// evaluations.
819    ///
820    /// # Example
821    ///
822    /// ```
823    /// # use argmin::core::{Problem, Hessian, Error};
824    /// #
825    /// # #[derive(Eq, PartialEq, Debug, Clone)]
826    /// # struct UserDefinedProblem {};
827    /// #
828    /// # impl Hessian for UserDefinedProblem {
829    /// #     type Param = Vec<f64>;
830    /// #     type Hessian = Vec<Vec<f64>>;
831    /// #
832    /// #     fn hessian(&self, param: &Self::Param) -> Result<Self::Hessian, Error> {
833    /// #         Ok(vec![vec![1.0f64, 0.0f64], vec![0.0f64, 1.0f64]])
834    /// #     }
835    /// # }
836    /// // `UserDefinedProblem` implements `Hessian`.
837    /// let mut problem1 = Problem::new(UserDefinedProblem {});
838    ///
839    /// let param1 = vec![2.0f64, 1.0f64];
840    /// let param2 = vec![3.0f64, 5.0f64];
841    /// let params = vec![&param1, &param2];
842    ///
843    /// let res = problem1.bulk_hessian(&params);
844    ///
845    /// assert_eq!(problem1.counts["hessian_count"], 2);
846    /// # let res = res.unwrap();
847    /// # assert_eq!(res[0], vec![vec![1.0f64, 0.0f64], vec![0.0f64, 1.0f64]]);
848    /// # assert_eq!(res[1], vec![vec![1.0f64, 0.0f64], vec![0.0f64, 1.0f64]]);
849    /// ```
850    pub fn bulk_hessian<P>(&mut self, params: &[P]) -> Result<Vec<O::Hessian>, Error>
851    where
852        P: std::borrow::Borrow<O::Param> + SyncAlias,
853        O::Hessian: SendAlias,
854        O: SyncAlias,
855    {
856        self.bulk_problem("hessian_count", params.len(), |problem| {
857            problem.bulk_hessian(params)
858        })
859    }
860}
861
862/// Wraps a call to `jacobian` defined in the `Jacobian` trait and as such allows to call `jacobian`
863/// on an instance of `Problem`. Internally, the number of evaluations of `jacobian` is counted.
864impl<O: Jacobian> Problem<O> {
865    /// Calls `jacobian` defined in the `Jacobian` trait and keeps track of the number of
866    /// evaluations.
867    ///
868    /// # Example
869    ///
870    /// ```
871    /// # use argmin::core::{Problem, Jacobian, Error};
872    /// #
873    /// # #[derive(Eq, PartialEq, Debug, Clone)]
874    /// # struct UserDefinedProblem {};
875    /// #
876    /// # impl Jacobian for UserDefinedProblem {
877    /// #     type Param = Vec<f64>;
878    /// #     type Jacobian = Vec<Vec<f64>>;
879    /// #
880    /// #     fn jacobian(&self, param: &Self::Param) -> Result<Self::Jacobian, Error> {
881    /// #         Ok(vec![vec![1.0f64, 0.0f64], vec![0.0f64, 1.0f64]])
882    /// #     }
883    /// # }
884    /// // `UserDefinedProblem` implements `Jacobian`.
885    /// let mut problem1 = Problem::new(UserDefinedProblem {});
886    ///
887    /// let param = vec![2.0f64, 1.0f64];
888    ///
889    /// let res = problem1.jacobian(&param);
890    ///
891    /// assert_eq!(problem1.counts["jacobian_count"], 1);
892    /// # assert_eq!(res.unwrap(), vec![vec![1.0f64, 0.0f64], vec![0.0f64, 1.0f64]]);
893    /// ```
894    pub fn jacobian(&mut self, param: &O::Param) -> Result<O::Jacobian, Error> {
895        self.problem("jacobian_count", |problem| problem.jacobian(param))
896    }
897
898    /// Calls `bulk_jacobian` defined in the `Jacobian` trait and keeps track of the number of
899    /// evaluations.
900    ///
901    /// # Example
902    ///
903    /// ```
904    /// # use argmin::core::{Problem, Jacobian, Error};
905    /// #
906    /// # #[derive(Eq, PartialEq, Debug, Clone)]
907    /// # struct UserDefinedProblem {};
908    /// #
909    /// # impl Jacobian for UserDefinedProblem {
910    /// #     type Param = Vec<f64>;
911    /// #     type Jacobian = Vec<Vec<f64>>;
912    /// #
913    /// #     fn jacobian(&self, param: &Self::Param) -> Result<Self::Jacobian, Error> {
914    /// #         Ok(vec![vec![1.0f64, 0.0f64], vec![0.0f64, 1.0f64]])
915    /// #     }
916    /// # }
917    /// // `UserDefinedProblem` implements `Jacobian`.
918    /// let mut problem1 = Problem::new(UserDefinedProblem {});
919    ///
920    /// let params = vec![vec![2.0f64, 1.0f64], vec![3.0f64, 5.0f64]];
921    ///
922    /// let res = problem1.bulk_jacobian(&params);
923    ///
924    /// assert_eq!(problem1.counts["jacobian_count"], 2);
925    /// # let res = res.unwrap();
926    /// # assert_eq!(res[0], vec![vec![1.0f64, 0.0f64], vec![0.0f64, 1.0f64]]);
927    /// # assert_eq!(res[1], vec![vec![1.0f64, 0.0f64], vec![0.0f64, 1.0f64]]);
928    /// ```
929    pub fn bulk_jacobian<P>(&mut self, params: &[P]) -> Result<Vec<O::Jacobian>, Error>
930    where
931        P: std::borrow::Borrow<O::Param> + SyncAlias,
932        O::Jacobian: SendAlias,
933        O: SyncAlias,
934    {
935        self.bulk_problem("jacobian_count", params.len(), |problem| {
936            problem.bulk_jacobian(params)
937        })
938    }
939}
940
941/// Wraps a calls to `c`, `b` and `A` defined in the `LinearProgram` trait and as such allows to
942/// call those methods on an instance of `Problem`.
943impl<O: LinearProgram> Problem<O> {
944    /// Calls `c` defined in the `LinearProgram` trait.
945    ///
946    /// # Example
947    ///
948    /// ```
949    /// # use argmin::core::{Problem, LinearProgram, Error};
950    /// #
951    /// # #[derive(Eq, PartialEq, Debug, Clone)]
952    /// # struct UserDefinedProblem {};
953    /// #
954    /// # impl LinearProgram for UserDefinedProblem {
955    /// #     type Param = Vec<f64>;
956    /// #     type Float = f64;
957    /// #
958    /// #     fn c(&self) -> Result<Vec<Self::Float>, Error> {
959    /// #         Ok(vec![4.0f64, 3.0f64])
960    /// #     }
961    /// #
962    /// #     fn b(&self) -> Result<Vec<Self::Float>, Error> {
963    /// #         Ok(vec![3.0f64, 2.0f64])
964    /// #     }
965    /// #
966    /// #     fn A(&self) -> Result<Vec<Vec<Self::Float>>, Error> {
967    /// #         Ok(vec![vec![1.0f64, 2.0f64], vec![3.0f64, 2.0f64]])
968    /// #     }
969    /// # }
970    /// // `UserDefinedProblem` implements `LinearProgram`.
971    /// let mut problem1 = Problem::new(UserDefinedProblem {});
972    ///
973    /// let c = problem1.c();
974    /// let b = problem1.b();
975    ///
976    /// # assert_eq!(c.unwrap(), vec![4.0f64, 3.0f64]);
977    /// ```
978    pub fn c(&self) -> Result<Vec<O::Float>, Error> {
979        self.problem.as_ref().unwrap().c()
980    }
981
982    /// Calls `b` defined in the `LinearProgram` trait.
983    ///
984    /// # Example
985    ///
986    /// ```
987    /// # use argmin::core::{Problem, LinearProgram, Error};
988    /// #
989    /// # #[derive(Eq, PartialEq, Debug, Clone)]
990    /// # struct UserDefinedProblem {};
991    /// #
992    /// # impl LinearProgram for UserDefinedProblem {
993    /// #     type Param = Vec<f64>;
994    /// #     type Float = f64;
995    /// #
996    /// #     fn c(&self) -> Result<Vec<Self::Float>, Error> {
997    /// #         Ok(vec![4.0f64, 3.0f64])
998    /// #     }
999    /// #
1000    /// #     fn b(&self) -> Result<Vec<Self::Float>, Error> {
1001    /// #         Ok(vec![3.0f64, 2.0f64])
1002    /// #     }
1003    /// #
1004    /// #     fn A(&self) -> Result<Vec<Vec<Self::Float>>, Error> {
1005    /// #         Ok(vec![vec![1.0f64, 2.0f64], vec![3.0f64, 2.0f64]])
1006    /// #     }
1007    /// # }
1008    /// // `UserDefinedProblem` implements `LinearProgram`.
1009    /// let mut problem1 = Problem::new(UserDefinedProblem {});
1010    ///
1011    /// let b = problem1.b();
1012    ///
1013    /// # assert_eq!(b.unwrap(), vec![3.0f64, 2.0f64]);
1014    /// ```
1015    pub fn b(&self) -> Result<Vec<O::Float>, Error> {
1016        self.problem.as_ref().unwrap().b()
1017    }
1018
1019    /// Calls `A` defined in the `LinearProgram` trait.
1020    ///
1021    /// # Example
1022    ///
1023    /// ```
1024    /// # use argmin::core::{Problem, LinearProgram, Error};
1025    /// #
1026    /// # #[derive(Eq, PartialEq, Debug, Clone)]
1027    /// # struct UserDefinedProblem {};
1028    /// #
1029    /// # impl LinearProgram for UserDefinedProblem {
1030    /// #     type Param = Vec<f64>;
1031    /// #     type Float = f64;
1032    /// #
1033    /// #     fn c(&self) -> Result<Vec<Self::Float>, Error> {
1034    /// #         Ok(vec![4.0f64, 3.0f64])
1035    /// #     }
1036    /// #
1037    /// #     fn b(&self) -> Result<Vec<Self::Float>, Error> {
1038    /// #         Ok(vec![3.0f64, 2.0f64])
1039    /// #     }
1040    /// #
1041    /// #     fn A(&self) -> Result<Vec<Vec<Self::Float>>, Error> {
1042    /// #         Ok(vec![vec![1.0f64, 2.0f64], vec![3.0f64, 2.0f64]])
1043    /// #     }
1044    /// # }
1045    /// // `UserDefinedProblem` implements `LinearProgram`.
1046    /// let mut problem1 = Problem::new(UserDefinedProblem {});
1047    ///
1048    /// let a = problem1.A();
1049    ///
1050    /// # assert_eq!(a.unwrap(), vec![vec![1.0f64, 2.0f64], vec![3.0f64, 2.0f64]]);
1051    /// ```
1052    #[allow(non_snake_case)]
1053    pub fn A(&self) -> Result<Vec<Vec<O::Float>>, Error> {
1054        self.problem.as_ref().unwrap().A()
1055    }
1056}