Skip to content

Commit e7a7f86

Browse files
committed
Added scaling_function.h which provides a way of defining a
covariance term which acts as a deterministic transformation of some underlying variable.
1 parent 01ec598 commit e7a7f86

File tree

5 files changed

+319
-18
lines changed

5 files changed

+319
-18
lines changed

albatross/covariance_functions/covariance_functions.h

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,27 @@
1717
#include "noise.h"
1818
#include "polynomials.h"
1919
#include "radial.h"
20+
#include "scaling_function.h"
2021

2122
namespace albatross {
2223

2324
template <typename Term> struct CovarianceFunction {
24-
Term covariance_term;
25+
Term term;
2526

26-
CovarianceFunction() : covariance_term(){};
27-
CovarianceFunction(const Term &term) : covariance_term(term){};
27+
CovarianceFunction() : term(){};
28+
CovarianceFunction(const Term &term_) : term(term_){};
2829

2930
template <typename Other>
3031
inline auto operator+(CovarianceFunction<Other> &other) {
3132
using Sum = SumOfCovarianceTerms<Term, Other>;
32-
auto sum = Sum(covariance_term, other.covariance_term);
33+
auto sum = Sum(term, other.term);
3334
return CovarianceFunction<Sum>{sum};
3435
}
3536

3637
template <typename Other>
3738
inline auto operator*(CovarianceFunction<Other> &other) {
3839
using Prod = ProductOfCovarianceTerms<Term, Other>;
39-
auto prod = Prod(covariance_term, other.covariance_term);
40+
auto prod = Prod(term, other.term);
4041
return CovarianceFunction<Prod>{prod};
4142
}
4243

@@ -50,11 +51,11 @@ template <typename Term> struct CovarianceFunction {
5051
typename std::enable_if<(has_call_operator<Term, X &, Y &>::value),
5152
int>::type = 0>
5253
inline auto operator()(const X &x, const Y &y) const {
53-
return covariance_term(x, y);
54+
return term(x, y);
5455
}
5556

5657
/*
57-
* If neither have a valid call method we fail compilation.
58+
* If neither have a valid call method we fail.
5859
*/
5960
template <typename X, typename Y,
6061
typename std::enable_if<(!has_call_operator<Term, X &, Y &>::value),
@@ -67,23 +68,23 @@ template <typename Term> struct CovarianceFunction {
6768
* errors should give you an indication of which types were attempted.
6869
*/
6970

70-
inline auto get_name() const { return covariance_term.get_name(); };
71-
inline auto get_params() const { return covariance_term.get_params(); };
71+
inline auto get_name() const { return term.get_name(); };
72+
inline auto get_params() const { return term.get_params(); };
7273
inline auto set_params(const ParameterStore &params) {
73-
return covariance_term.set_params(params);
74+
return term.set_params(params);
7475
};
7576
inline auto set_param(const ParameterKey &key, const ParameterValue &value) {
76-
return covariance_term.set_param(key, value);
77+
return term.set_param(key, value);
7778
};
78-
inline auto pretty_string() const { return covariance_term.pretty_string(); };
79+
inline auto pretty_string() const { return term.pretty_string(); };
7980
inline auto get_params_as_vector() const {
80-
return covariance_term.get_params_as_vector();
81+
return term.get_params_as_vector();
8182
};
8283
inline auto set_params_from_vector(const std::vector<ParameterValue> &x) {
83-
return covariance_term.set_params_from_vector(x);
84+
return term.set_params_from_vector(x);
8485
};
8586
inline auto unchecked_set_param(const std::string &name, const double value) {
86-
return covariance_term.unchecked_set_param(name, value);
87+
return term.unchecked_set_param(name, value);
8788
};
8889
};
8990

albatross/covariance_functions/covariance_term.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,13 @@
2121
namespace albatross {
2222

2323
/*
24-
* An abstract class (though no purely abstract due to templating)
25-
* which holds anything all Covariance terms should have in common.
24+
* An abstract class which holds anything all Covariance
25+
* terms should have in common.
26+
*
27+
* In addition to these abstract methods one or many
28+
* methods with signature,
29+
* operator ()(const X &x, const Y &y)
30+
* should be defined.
2631
*/
2732
class CovarianceTerm : public ParameterHandlingMixin {
2833
public:
@@ -135,7 +140,7 @@ class ProductOfCovarianceTerms : public CombinationOfCovarianceTerms<LHS, RHS> {
135140

136141
/*
137142
* If both LHS and RHS have a valid call method for the types X and Y
138-
* this will return the sum of the two.
143+
* this will return the product of the two.
139144
*/
140145
template <typename X, typename Y,
141146
typename std::enable_if<(has_call_operator<LHS, X &, Y &>::value &&
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/*
2+
* Copyright (C) 2018 Swift Navigation Inc.
3+
* Contact: Swift Navigation <dev@swiftnav.com>
4+
*
5+
* This source is subject to the license found in the file 'LICENSE' which must
6+
* be distributed together with this source. All other rights reserved.
7+
*
8+
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
9+
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
10+
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
11+
*/
12+
13+
#ifndef ALBATROSS_COVARIANCE_FUNCTIONS_SCALING_FUNCTION_H
14+
#define ALBATROSS_COVARIANCE_FUNCTIONS_SCALING_FUNCTION_H
15+
16+
#include "covariance_term.h"
17+
#include <sstream>
18+
#include <utility>
19+
20+
namespace albatross {
21+
22+
class ScalingFunction : public ParameterHandlingMixin {
23+
public:
24+
virtual std::string get_name() const = 0;
25+
26+
// A scaling function should also implement operators
27+
// for whichever types it is intended to scale using
28+
// the signature:
29+
// double operator(const X &x) const;
30+
};
31+
32+
/*
33+
* A scaling term is not actually a covariance function
34+
* in the rigorous sense. It doesn't describe the uncertainty
35+
* between variables, but instead operates deterministically
36+
* on other uncertain variables. For instance, you may have
37+
* some random variable,
38+
* y ~ N(0, S) with S_ij = cov(y_i, y_j)
39+
* And you may then make observations of that random variable
40+
* but through a known transformation,
41+
* z = f(y) y
42+
* where f is a determinstic function of y that returns a scalar.
43+
* You might then ask what the covariance between two elements in
44+
* z is which is woudl be given by,
45+
* cov(z_i, z_j) = f(y_i) * cov(y_i, y_j) * f(y_j)
46+
* but you might also be interested in the covariance between
47+
* some y_i and an observation z_j,
48+
* cov(y_i, z_j) = cov(y_i, y_j) * f(y_j)
49+
* Here we see that for a typical covariance term, the covariance
50+
* is only defined for two pairs of the same type, in this case
51+
* operator()(Y &y, Y &y)
52+
* but by multiplying by a ScalingTerm we end up with definitions
53+
* for,
54+
* operator()(Y &y, Z &z)
55+
* which provides us with a way of computing the covariance between
56+
* some hidden representation of a variable (y) and the actual
57+
* observations (z) using a single determinstic mapping (f).
58+
*
59+
* This might be better explained by example which can be found
60+
* in the tests (test_scaling_function).
61+
*/
62+
template <typename ScalingFunction> class ScalingTerm : public CovarianceTerm {
63+
public:
64+
ScalingTerm() : CovarianceTerm(){};
65+
virtual ~ScalingTerm(){};
66+
67+
/*
68+
* The following methods forward any requests dealing with
69+
* the ParameterHandlingMixin to the ScalingFunction.
70+
*/
71+
std::string get_name() const override { return scaling_function_.get_name(); }
72+
73+
std::string pretty_string() const {
74+
return scaling_function_.pretty_string();
75+
}
76+
77+
void set_params(const ParameterStore &params) {
78+
scaling_function_.set_params(params);
79+
}
80+
81+
virtual ParameterStore get_params() const {
82+
return scaling_function_.get_params();
83+
}
84+
85+
template <class Archive> void save(Archive &archive) const {
86+
archive(cereal::make_nvp("base_class",
87+
cereal::base_class<CovarianceTerm>(this)));
88+
archive(cereal::make_nvp("scaling_function", scaling_function_));
89+
}
90+
91+
template <class Archive> void load(Archive &archive) {
92+
archive(cereal::make_nvp("base_class",
93+
cereal::base_class<CovarianceTerm>(this)));
94+
archive(cereal::make_nvp("scaling_function", scaling_function_));
95+
}
96+
97+
void unchecked_set_param(const std::string &name,
98+
const double value) override {
99+
scaling_function_.set_param(name, value);
100+
}
101+
102+
/*
103+
* If both Scaling and Covariance have a valid call method for the types X
104+
* and Y this will return the product of the two.
105+
*/
106+
template <
107+
typename X, typename Y,
108+
typename std::enable_if<(has_call_operator<ScalingFunction, X &>::value &&
109+
has_call_operator<ScalingFunction, Y &>::value),
110+
int>::type = 0>
111+
double operator()(X &x, Y &y) const {
112+
return this->scaling_function_(x) * this->scaling_function_(y);
113+
}
114+
115+
/*
116+
* If only one of the types has a scaling function we ignore the other.
117+
*/
118+
template <typename X, typename Y,
119+
typename std::enable_if<
120+
(!has_call_operator<ScalingFunction, X &>::value &&
121+
has_call_operator<ScalingFunction, Y &>::value),
122+
int>::type = 0>
123+
double operator()(X &x, Y &y) const {
124+
return this->scaling_function_(y);
125+
}
126+
127+
template <
128+
typename X, typename Y,
129+
typename std::enable_if<(has_call_operator<ScalingFunction, X &>::value &&
130+
!has_call_operator<ScalingFunction, Y &>::value),
131+
int>::type = 0>
132+
double operator()(X &x, Y &y) const {
133+
return this->scaling_function_(x);
134+
}
135+
136+
private:
137+
ScalingFunction scaling_function_;
138+
};
139+
}
140+
#endif

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ test_parameter_handling_mixin.cc
1414
test_models.cc
1515
test_core_distribution.cc
1616
test_tune.cc
17+
test_scaling_function.cc
1718
)
1819

1920
add_dependencies(albatross_unit_tests

0 commit comments

Comments
 (0)