LSLOpt  1.0
ProblemTraits.hpp
1 #pragma once
2 
3 #include <type_traits>
4 
5 #include "../Types.hpp"
6 #include "../ScalarTraits.hpp"
7 
8 
9 namespace LSLOpt {
10 
11 namespace Implementation {
12 
14 template<typename T>
15 struct remove_cvref {
17  using type = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
18 };
19 
30 template<typename Problem, typename Scalar>
32  static constexpr Vector<Scalar>* const dummy_vec = nullptr;
33  static constexpr Problem* const dummy_problem = nullptr;
34 
35  template<typename U>
36  static auto value_probe(U& u) -> decltype(u.value(*dummy_vec));
37  static void value_probe(...);
38 
39  template<typename U>
40  static auto gradient_probe(U& u) -> decltype(u.gradient(*dummy_vec));
41  static void gradient_probe(...);
42 
43  template<typename U>
44  static auto lower_bound_probe(U& u) -> decltype(u.lower_bounds());
45  static void lower_bound_probe(...);
46 
47  template<typename U>
48  static auto upper_bound_probe(U& u) -> decltype(u.upper_bounds());
49  static void upper_bound_probe(...);
50 
51  template<typename U>
52  static auto initial_step_length_probe(U& u)
53  -> decltype(u.initial_step_length(*dummy_vec, *dummy_vec));
54  static void initial_step_length_probe(...);
55 
56  template<typename U>
57  static auto change_acceptable_probe(U& u)
58  -> decltype(u.change_acceptable(*dummy_vec, *dummy_vec));
59  static void change_acceptable_probe(...);
60 
61  template<typename U>
62  static auto is_check_acceptable_first_probe(U& u) -> decltype(u.is_check_acceptable_first());
63  static void is_check_acceptable_first_probe(...);
64 
65  template<typename U>
66  static auto reparameterize_probe(U& u) -> decltype(u.reparameterize(*dummy_vec, *dummy_vec));
67  static void reparameterize_probe(...);
68 
69 public:
71  using value_type = decltype(value_probe(*dummy_problem));
73  static constexpr const bool has_value
74  = std::is_same<Scalar, typename remove_cvref<value_type>::type>::value;
75 
77  using gradient_type = decltype(gradient_probe(*dummy_problem));
79  static constexpr const bool has_gradient
80  = std::is_same<Vector<Scalar>,
81  typename remove_cvref<gradient_type>::type>::value;
82 
84  using lower_bound_type = decltype(lower_bound_probe(*dummy_problem));
86  static constexpr const bool has_lower_bound
87  = std::is_same<Vector<Scalar>,
88  typename remove_cvref<lower_bound_type>::type>::value;
89 
91  using upper_bound_type = decltype(upper_bound_probe(*dummy_problem));
93  static constexpr const bool has_upper_bound
94  = std::is_same<Vector<Scalar>,
95  typename remove_cvref<upper_bound_type>::type>::value;
96 
98  using initial_step_length_type = decltype(initial_step_length_probe(*dummy_problem));
100  static constexpr const bool has_initial_step_length
101  = std::is_same<Scalar,
103 
105  using change_acceptable_type = decltype(change_acceptable_probe(*dummy_problem));
107  static constexpr const bool has_change_acceptable
108  = std::is_same<Scalar,
110 
112  using is_check_acceptable_first_type = decltype(is_check_acceptable_first_probe(*dummy_problem));
114  static constexpr const bool has_is_check_acceptable_first
115  = std::is_same<bool,
117 
119  using reparameterize_type = decltype(reparameterize_probe(*dummy_problem));
121  static constexpr const bool has_reparameterize
122  = std::is_same<bool,
124 };
125 
126 template<typename Problem, typename Scalar>
138  static Scalar initial_step_length(
139  Problem& problem,
140  const Vector<Scalar>& x,
141  const Vector<Scalar>& p)
142  {
144  "Problem must provide initial step length function: Scalar initial_step_length(...)");
145 
146  return problem.initial_step_length(x, p);
147  }
148 
156  static Scalar change_acceptable(
157  Problem& problem,
158  const Vector<Scalar>& x0,
159  const Vector<Scalar>& x)
160  {
162  "Problem must provide change acceptable function: Scalar change_acceptable(...)");
163 
164  return problem.change_acceptable(x0, x);
165  }
166 
173  Problem& problem)
174  {
175  return _is_check_acceptable_first(problem);
176  }
177 
178  private:
179 
180  template<typename U,
181  typename std::enable_if<!problem_traits<U, Scalar>::has_is_check_acceptable_first,
182  U>::type* = nullptr>
183  static constexpr bool _is_check_acceptable_first(
184  U&)
185  {
186  return false;
187  }
188 
189  template<typename U,
190  typename std::enable_if<problem_traits<U, Scalar>::has_is_check_acceptable_first,
191  void>::type* = nullptr>
192  static bool _is_check_acceptable_first(
193  U& problem)
194  {
195  return problem.is_check_acceptable_first();
196  }
197 
198 };
199 
203 template<typename Problem, typename Scalar>
209  static constexpr Scalar initial_step_length(
210  Problem&,
211  const Vector<Scalar>&,
212  const Vector<Scalar>&)
213  {
215  }
216 
221  static constexpr Scalar change_acceptable(
222  Problem&,
223  const Vector<Scalar>&,
224  const Vector<Scalar>&)
225  {
226  return Scalar{0};
227  }
228 
233  static constexpr bool is_check_acceptable_first(
234  Problem&)
235  {
236  return false;
237  }
238 };
239 
240 template<typename Problem, typename Scalar>
252  static bool reparameterize(
253  Problem& problem,
254  Vector<Scalar>& x,
255  Vector<Scalar>& grad)
256  {
257  return _reparameterize(problem, x, grad);
258  }
259 
260  private:
261 
262  template<typename U,
263  typename std::enable_if<!problem_traits<U, Scalar>::has_reparameterize,
264  U>::type* = nullptr>
265  static constexpr bool _reparameterize(
266  U&,
267  Vector<Scalar>& x,
268  Vector<Scalar>& grad)
269  {
270  return false;
271  }
272 
273  template<typename U,
274  typename std::enable_if<problem_traits<U, Scalar>::has_reparameterize,
275  U>::type* = nullptr>
276  static constexpr bool _reparameterize(
277  U& problem,
278  Vector<Scalar>& x,
279  Vector<Scalar>& grad)
280  {
281  return problem.reparameterize(x, grad);
282  }
283 };
284 
285 }
286 
287 }
decltype(upper_bound_probe(*dummy_problem)) upper_bound_type
return type of the upper_bounds function; void if not provided
Definition: ProblemTraits.hpp:91
The no step length identifier.
Definition: ProblemTraits.hpp:204
static constexpr bool is_check_acceptable_first(Problem &)
Check if change acceptability should be checked first.
Definition: ProblemTraits.hpp:233
static constexpr Scalar initial_step_length(Problem &, const Vector< Scalar > &, const Vector< Scalar > &)
Get the intial step length from problem.
Definition: ProblemTraits.hpp:209
static Scalar initial_step_length(Problem &problem, const Vector< Scalar > &x, const Vector< Scalar > &p)
Get the initial step length from problem.
Definition: ProblemTraits.hpp:138
decltype(change_acceptable_probe(*dummy_problem)) change_acceptable_type
return type of the change_acceptable function; void if not provided
Definition: ProblemTraits.hpp:105
!
Definition: ProblemTraits.hpp:15
static bool reparameterize(Problem &problem, Vector< Scalar > &x, Vector< Scalar > &grad)
Reparemeterize x and recalculate the gradient.
Definition: ProblemTraits.hpp:252
Traits for scalar values.
Definition: ScalarTraits.hpp:16
static Scalar change_acceptable(Problem &problem, const Vector< Scalar > &x0, const Vector< Scalar > &x)
Check if suggested step is acceptable.
Definition: ProblemTraits.hpp:156
static constexpr Scalar change_acceptable(Problem &, const Vector< Scalar > &, const Vector< Scalar > &)
Check if change is acceptable.
Definition: ProblemTraits.hpp:221
static bool is_check_acceptable_first(Problem &problem)
Check if change acceptability should be checked first.
Definition: ProblemTraits.hpp:172
decltype(value_probe(*dummy_problem)) value_type
return type of the value function; void if not provided
Definition: ProblemTraits.hpp:71
decltype(is_check_acceptable_first_probe(*dummy_problem)) is_check_acceptable_first_type
return type of the check_acceptable_first function; void if not provided
Definition: ProblemTraits.hpp:112
Eigen::Matrix< Scalar, Eigen::Dynamic, 1 > Vector
Vector type used.
Definition: Types.hpp:15
decltype(initial_step_length_probe(*dummy_problem)) initial_step_length_type
return type of the initial_step_length function; void if not provided
Definition: ProblemTraits.hpp:98
typename std::remove_cv< typename std::remove_reference< T >::type >::type type
!
Definition: ProblemTraits.hpp:17
decltype(gradient_probe(*dummy_problem)) gradient_type
return type of the gradient function; void if not provided
Definition: ProblemTraits.hpp:77
Traits for the problem.
Definition: ProblemTraits.hpp:31
BFGS optimizations.
Definition: BFGS.hpp:24
The max step length identifier.
Definition: ProblemTraits.hpp:130
Reparameterizer.
Definition: ProblemTraits.hpp:244
decltype(reparameterize_probe(*dummy_problem)) reparameterize_type
return type of the reparameterize function; void if not provided
Definition: ProblemTraits.hpp:119
decltype(lower_bound_probe(*dummy_problem)) lower_bound_type
return type of the lower_bounds function; void if not provided
Definition: ProblemTraits.hpp:84