```  1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
```
```// Copyright 2018 Stefan Kroboth
//
// copied, modified, or distributed except according to those terms.

//! TODO DOCUMENTATION
//!

use errors::*;
use prelude::*;
use parameter::ArgminParameter;

/// This struct hold all information that describes the optimization problem.
pub struct ArgminProblem<'a, T: ArgminParameter + 'a, U: ArgminCostValue + 'a, V: 'a> {
/// reference to a function which computes the cost/fitness for a given parameter vector
pub cost_function: &'a Fn(&T) -> U,
/// optional reference to a function which provides the gradient at a given point in parameter
/// space
pub gradient: Option<&'a Fn(&T) -> T>,
/// optional reference to a function which provides the Hessian at a given point in parameter
/// space
pub hessian: Option<&'a Fn(&T) -> V>,
/// lower bound of the parameter vector
pub lower_bound: Option<T>,
/// upper bound of the parameter vector
pub upper_bound: Option<T>,
/// (non)linear constraint which is `true` if a parameter vector lies within the bounds
pub constraint: &'a Fn(&T) -> bool,
/// Target cost function value. The optimization will stop once this value is reached.
pub target_cost: U,
}

impl<'a, T: ArgminParameter + 'a, U: ArgminCostValue + 'a, V: 'a> ArgminProblem<'a, T, U, V> {
/// Create a new `ArgminProblem` struct.
///
/// The field `gradient` is automatically set to `None`, but can be manually set by the
/// `gradient` function. The (non) linear constraint `constraint` is set to a closure which
/// evaluates to `true` everywhere. This can be overwritten with the `constraint` function.
///
/// `cost_function`: Reference to a cost function
pub fn new(cost_function: &'a Fn(&T) -> U) -> Self {
ArgminProblem {
cost_function: cost_function,
hessian: None,
lower_bound: None,
upper_bound: None,
constraint: &|_x: &T| true,
target_cost: U::min_value(),
}
}

/// Set lower and upper bounds
///
/// `lower_bound`: lower bound for the parameter vector
/// `upper_bound`: upper bound for the parameter vector
pub fn bounds(&mut self, lower_bound: &T, upper_bound: &T) -> &mut Self {
self.lower_bound = Some(lower_bound.clone());
self.upper_bound = Some(upper_bound.clone());
self
}

///
/// The function has to have the signature `&Fn(&T) -> T` where `T` is the type of
/// the parameter vector. The function returns the gradient for a given parameter vector.
pub fn gradient(&mut self, gradient: &'a Fn(&T) -> T) -> &mut Self {
self
}

/// Provide the Hessian
///
/// The function has to have the signature `&Fn(&T) -> T` where `T` is the type of
/// the parameter vector. The function returns the gradient for a given parameter vector.
pub fn hessian(&mut self, hessian: &'a Fn(&T) -> V) -> &mut Self {
self.hessian = Some(hessian);
self
}

/// Provide additional (non) linear constraint.
///
/// The function has to have the signature `&Fn(&T) -> bool` where `T` is the type of
/// the parameter vector. The function returns `true` if all constraints are satisfied and
/// `false` otherwise.
pub fn constraint(&mut self, constraint: &'a Fn(&T) -> bool) -> &mut Self {
self.constraint = constraint;
self
}

/// Set target cost function value
///
/// If the optimization reaches this value, it will be stopped.
pub fn target_cost(&mut self, target_cost: U) -> &mut Self {
self.target_cost = target_cost;
self
}

/// Create a random parameter vector
///
/// The parameter vector satisfies the `lower_bound` and `upper_bound`.
pub fn random_param(&self) -> Result<T> {
match (self.lower_bound.as_ref(), self.upper_bound.as_ref()) {
(Some(l), Some(u)) => Ok(T::random(l, u)),
_ => Err(ErrorKind::InvalidParameter(
"Parameter: lower_bound and upper_bound must be provided.".into(),
).into()),
}
}
}
```