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(¶m));
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(¶m, 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(¶m))
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(¶m);
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![¶m1, ¶m2];
600 ///
601 /// let res = problem1.bulk_apply(¶ms);
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(¶m);
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![¶m1, ¶m2];
681 ///
682 /// let res = problem1.bulk_cost(¶ms);
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(¶m);
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![¶m1, ¶m2];
762 ///
763 /// let res = problem1.bulk_gradient(¶ms);
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(¶m);
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![¶m1, ¶m2];
842 ///
843 /// let res = problem1.bulk_hessian(¶ms);
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(¶m);
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(¶ms);
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}