DiSMEC++
objective.cpp
Go to the documentation of this file.
1 // Copyright (c) 2021, Aalto University, developed by Erik Schultheis
2 // All rights reserved.
3 //
4 // SPDX-License-Identifier: MIT
5 
6 #include "objective.h"
7 #include "utils/hash_vector.h"
8 #include "utils/throw_error.h"
9 #include "stats/timer.h"
10 
11 using namespace dismec;
12 using namespace dismec::objective;
13 
14 namespace {
15  constexpr const stats::stat_id_t STAT_PERF_VALUE{0};
19  constexpr const stats::stat_id_t STAT_PERF_HESSIAN{4};
22 }
23 
25  declare_stat(STAT_PERF_VALUE, {"perf_value", "µs"});
26  declare_stat(STAT_PERF_PRECONDITIONER, {"perf_preconditioner", "µs"});
27  declare_stat(STAT_PERF_GRAD_AT_ZERO, {"perf_grad_at_zero", "µs"});
28  declare_stat(STAT_PERF_GRADIENT, {"perf_gradient", "µs"});
29  declare_stat(STAT_PERF_HESSIAN, {"perf_hessian", "µs"});
30  declare_stat(STAT_PERF_GRAD_AND_PRE, {"perf_grad_and_pre", "µs"});
31  declare_stat(STAT_PERF_PROJ_TO_LINE, {"perf_proj_to_line", "µs"});
32 }
33 
34 
36  auto timer = make_timer(STAT_PERF_VALUE);
37  if(num_variables() > 0) {
38  ALWAYS_ASSERT_EQUAL(location->size(), num_variables(), "location size {} differs from num_variables {}");
39  }
40  return value_unchecked(location);
41 }
42 
43 void Objective::diag_preconditioner(const HashVector& location, Eigen::Ref<DenseRealVector> target) {
45  if(num_variables() > 0) {
46  ALWAYS_ASSERT_EQUAL(location->size(), num_variables(), "location size {} differs from num_variables {}");
47  ALWAYS_ASSERT_EQUAL(target.size(), num_variables(), "target size {} differs from num_variables {}");
48  } else {
49  ALWAYS_ASSERT_EQUAL(target.size(), location->size(), "target size {} differs from location size {}");
50  }
51  diag_preconditioner_unchecked(location, target);
52 }
53 
54 void Objective::diag_preconditioner_unchecked(const HashVector& location, Eigen::Ref<DenseRealVector> target) {
55  target.setOnes();
56 }
57 
59  Eigen::Ref<DenseRealVector> gradient,
60  Eigen::Ref<DenseRealVector> pre) {
61  auto timer = make_timer(STAT_PERF_GRAD_AND_PRE);
62  if(num_variables() > 0) {
63  ALWAYS_ASSERT_EQUAL(location->size(), num_variables(), "location size {} differs from num_variables {}");
64  ALWAYS_ASSERT_EQUAL(gradient.size(), num_variables(), "gradient size {} differs from num_variables {}");
65  ALWAYS_ASSERT_EQUAL(pre.size(), num_variables(), "pre size {} differs from num_variables {}");
66  } else {
67  ALWAYS_ASSERT_EQUAL(gradient.size(), location->size(), "gradient size {} differs from location size {}");
68  ALWAYS_ASSERT_EQUAL(pre.size(), location->size(), "pre size {} differs from location size {}");
69  }
70 
72 }
73 
75  const HashVector& location,
76  Eigen::Ref<DenseRealVector> gradient,
77  Eigen::Ref<DenseRealVector> pre) {
78  gradient_unchecked(location, gradient);
79  diag_preconditioner_unchecked(location, pre);
80 }
81 
82 void Objective::gradient_at_zero(Eigen::Ref<DenseRealVector> target) {
83  auto timer = make_timer(STAT_PERF_GRAD_AT_ZERO);
84  if(num_variables() > 0) {
85  ALWAYS_ASSERT_EQUAL(target.size(), num_variables(), "target size {} differs from num_variables {}");
86  }
88 }
89 
90 void Objective::gradient_at_zero_unchecked(Eigen::Ref<DenseRealVector> target) {
91  // we can call gradient_unchecked directly, because the first argument here is
92  // guaranteed to match the second, which has already been validated.
93  gradient_unchecked(HashVector(DenseRealVector::Zero(target.size())), target);
94 }
95 
96 void Objective::gradient(const HashVector& location, Eigen::Ref<DenseRealVector> target) {
97  auto timer = make_timer(STAT_PERF_GRADIENT);
98  if(num_variables() > 0) {
99  ALWAYS_ASSERT_EQUAL(location->size(), num_variables(), "location size {} differs from num_variables {}");
100  ALWAYS_ASSERT_EQUAL(target.size(), num_variables(), "target size {} differs from num_variables {}");
101  } else {
102  ALWAYS_ASSERT_EQUAL(target.size(), location->size(), "target size {} differs from location size {}");
103  }
104  gradient_unchecked(location, target);
105 }
106 
108  const HashVector& location,
109  const DenseRealVector& direction,
110  Eigen::Ref<DenseRealVector> target) {
111  auto timer = make_timer(STAT_PERF_HESSIAN);
112  if(num_variables() > 0) {
113  ALWAYS_ASSERT_EQUAL(location->size(), num_variables(), "location size {} differs from num_variables {}");
114  ALWAYS_ASSERT_EQUAL(target.size(), num_variables(), "target size {} differs from num_variables {}");
115  ALWAYS_ASSERT_EQUAL(direction.size(), num_variables(), "direction size {} differs from num_variables {}");
116  } else {
117  ALWAYS_ASSERT_EQUAL(target.size(), location->size(), "target size {} differs from location size {}");
118  ALWAYS_ASSERT_EQUAL(direction.size(), location->size(), "direction size {} differs from location size {}");
119  }
120 
121  hessian_times_direction_unchecked(location, direction, target);
122 }
123 
124 void Objective::project_to_line(const HashVector& location, const DenseRealVector& direction) {
125  auto timer = make_timer(STAT_PERF_PROJ_TO_LINE);
126  if(num_variables() > 0) {
127  ALWAYS_ASSERT_EQUAL(location->size(), num_variables(), "location size {} differs from num_variables {}");
128  ALWAYS_ASSERT_EQUAL(direction.size(), num_variables(), "direction size {} differs from num_variables {}");
129  } else {
130  ALWAYS_ASSERT_EQUAL(direction.size(), location->size(), "direction size {} differs from location size {}");
131  }
132  project_to_line_unchecked(location, direction);
133 }
An Eigen vector with versioning information, to implement simple caching of results.
Definition: hash_vector.h:43
virtual void gradient_and_pre_conditioner_unchecked(const HashVector &location, Eigen::Ref< DenseRealVector > gradient, Eigen::Ref< DenseRealVector > pre)
Definition: objective.cpp:74
virtual void gradient_at_zero_unchecked(Eigen::Ref< DenseRealVector > target)
Definition: objective.cpp:90
void hessian_times_direction(const HashVector &location, const DenseRealVector &direction, Eigen::Ref< DenseRealVector > target)
Calculates the product of the Hessian matrix at location with direction.
Definition: objective.cpp:107
void gradient_at_zero(Eigen::Ref< DenseRealVector > target)
Gets the gradient for location zero.
Definition: objective.cpp:82
virtual void gradient_unchecked(const HashVector &location, Eigen::Ref< DenseRealVector > target)=0
virtual long num_variables() const noexcept=0
void gradient(const HashVector &location, Eigen::Ref< DenseRealVector > target)
Evaluate the gradient at location.
Definition: objective.cpp:96
virtual real_t value_unchecked(const HashVector &location)=0
virtual void hessian_times_direction_unchecked(const HashVector &location, const DenseRealVector &direction, Eigen::Ref< DenseRealVector > target)=0
virtual void diag_preconditioner_unchecked(const HashVector &location, Eigen::Ref< DenseRealVector > target)
Definition: objective.cpp:54
virtual void project_to_line_unchecked(const HashVector &location, const DenseRealVector &direction)=0
void gradient_and_pre_conditioner(const HashVector &location, Eigen::Ref< DenseRealVector > gradient, Eigen::Ref< DenseRealVector > pre)
Combines the calculation of gradient and pre-conditioner, which may be more efficient in some cases.
Definition: objective.cpp:58
void project_to_line(const HashVector &location, const DenseRealVector &direction)
creates a function g such that g(a) = objective(location + a * direction) Use lookup_on_line() to eva...
Definition: objective.cpp:124
void diag_preconditioner(const HashVector &location, Eigen::Ref< DenseRealVector > target)
Get precondition to be used in CG optimization.
Definition: objective.cpp:43
real_t value(const HashVector &location)
Evaluate the objective at the given location.
Definition: objective.cpp:35
auto make_timer(stat_id_t id, Args... args)
Creates a new ScopeTimer using stats::record_scope_time.
Definition: tracked.h:130
void declare_stat(stat_id_t index, StatisticMetaData meta)
Declares a new statistics. This function just forwards all its arguments to the internal StatisticsCo...
Definition: tracked.cpp:16
constexpr const stats::stat_id_t STAT_PERF_PRECONDITIONER
Definition: objective.cpp:16
constexpr const stats::stat_id_t STAT_PERF_GRAD_AT_ZERO
Definition: objective.cpp:17
constexpr const stats::stat_id_t STAT_PERF_HESSIAN
Definition: objective.cpp:19
constexpr const stats::stat_id_t STAT_PERF_VALUE
Definition: objective.cpp:15
constexpr const stats::stat_id_t STAT_PERF_GRADIENT
Definition: objective.cpp:18
constexpr const stats::stat_id_t STAT_PERF_GRAD_AND_PRE
Definition: objective.cpp:20
constexpr const stats::stat_id_t STAT_PERF_PROJ_TO_LINE
Definition: objective.cpp:21
Main namespace in which all types, classes, and functions are defined.
Definition: app.h:15
types::DenseVector< real_t > DenseRealVector
Any dense, real values vector.
Definition: matrix_types.h:40
float real_t
The default type for floating point values.
Definition: config.h:17
#define ALWAYS_ASSERT_EQUAL(x, y, msg)
Definition: throw_error.h:24