DMP_BBO library
MetaParametersLWR.cpp
Go to the documentation of this file.
1 
24 #include <boost/serialization/export.hpp>
25 #include <boost/archive/text_iarchive.hpp>
26 #include <boost/archive/text_oarchive.hpp>
27 #include <boost/archive/xml_iarchive.hpp>
28 #include <boost/archive/xml_oarchive.hpp>
30 
33 
34 
37 
38 #include <iostream>
39 #include <unordered_map>
40 
41 #include <boost/serialization/base_object.hpp>
42 #include <boost/serialization/nvp.hpp>
43 #include <boost/serialization/vector.hpp>
44 
45 
46 
47 using namespace Eigen;
48 using namespace std;
49 
50 namespace DmpBbo {
51 
52 MetaParametersLWR::MetaParametersLWR(int expected_input_dim, const std::vector<Eigen::VectorXd>& centers_per_dim, double intersection_height, double regularization, bool asymmetric_kernels)
53 :
54  MetaParameters(expected_input_dim),
55  n_bfs_per_dim_(VectorXi::Zero(0)),
56  centers_per_dim_(centers_per_dim),
57  intersection_height_(intersection_height),
58  regularization_(regularization),
59  asymmetric_kernels_(asymmetric_kernels)
60 {
61  assert(expected_input_dim==(int)centers_per_dim_.size());
62  for (unsigned int dd=0; dd<centers_per_dim_.size(); dd++)
63  assert(centers_per_dim_[dd].size()>0);
64  assert(intersection_height_>0 && intersection_height_<1);
65  assert(regularization>=0.0);
66 }
67 
68 MetaParametersLWR::MetaParametersLWR(int expected_input_dim, const Eigen::VectorXi& n_bfs_per_dim, double intersection_height, double regularization, bool asymmetric_kernels)
69 :
70  MetaParameters(expected_input_dim),
71  n_bfs_per_dim_(n_bfs_per_dim),
72  centers_per_dim_(std::vector<Eigen::VectorXd>(0)),
73  intersection_height_(intersection_height),
74  regularization_(regularization),
75  asymmetric_kernels_(asymmetric_kernels)
76 {
77  assert(expected_input_dim==n_bfs_per_dim_.size());
78  for (int dd=0; dd<n_bfs_per_dim_.size(); dd++)
79  assert(n_bfs_per_dim_[dd]>0);
80  assert(intersection_height_>0 && intersection_height_<1);
81  assert(regularization>=0.0);
82 };
83 
84 MetaParametersLWR::MetaParametersLWR(int expected_input_dim, int n_bfs, double intersection_height, double regularization, bool asymmetric_kernels)
85 :
86  MetaParameters(expected_input_dim),
87  n_bfs_per_dim_(VectorXi::Constant(1,n_bfs)),
88  centers_per_dim_(std::vector<Eigen::VectorXd>(0)),
89  intersection_height_(intersection_height),
90  regularization_(regularization),
91  asymmetric_kernels_(asymmetric_kernels)
92 {
93  assert(expected_input_dim==n_bfs_per_dim_.size());
94  for (int dd=0; dd<n_bfs_per_dim_.size(); dd++)
95  assert(n_bfs_per_dim_[dd]>0);
96  assert(intersection_height_>0 && intersection_height_<1);
97  assert(regularization>=0.0);
98 };
99 
101 {
102  MetaParametersLWR* cloned;
103  if (centers_per_dim_.size()>0)
104  cloned = new MetaParametersLWR(getExpectedInputDim(),centers_per_dim_,intersection_height_,regularization_,asymmetric_kernels_);
105  else
106  cloned = new MetaParametersLWR(getExpectedInputDim(),n_bfs_per_dim_,intersection_height_,regularization_,asymmetric_kernels_);
107 
108  return cloned;
109 }
110 
112 void MetaParametersLWR::getCentersAndWidths(const VectorXd& min, const VectorXd& max, Eigen::MatrixXd& centers, Eigen::MatrixXd& widths) const
113 {
114  int n_dims = getExpectedInputDim();
115  assert(min.size()==n_dims);
116  assert(max.size()==n_dims);
117 
118  vector<VectorXd> centers_per_dim_local(n_dims);
119  if (!centers_per_dim_.empty())
120  {
121  centers_per_dim_local = centers_per_dim_;
122  }
123  else
124  {
125  // Centers are not know yet, compute them based on min and max
126  for (int i_dim=0; i_dim<n_dims; i_dim++)
127  centers_per_dim_local[i_dim] = VectorXd::LinSpaced(n_bfs_per_dim_[i_dim],min[i_dim],max[i_dim]);
128  }
129 
130  // Determine the widths from the centers (separately for each dimension)
131  vector<VectorXd> widths_per_dim_local(n_dims);
132  for (int i_dim=0; i_dim<n_dims; i_dim++)
133  {
134  VectorXd cur_centers = centers_per_dim_local[i_dim]; // Abbreviation for convenience
135  int n_centers = cur_centers.size();
136  VectorXd cur_widths(n_centers);
137 
138  if (n_centers==1)
139  {
140  cur_widths[0] = 1.0;
141  }
142  else
143  {
144  // Consider two neighbouring basis functions, exp(-0.5(x-c0)^2/w^2) and exp(-0.5(x-c1)^2/w^2)
145  // Assuming the widths are the same for both, they are certain to intersect at x = 0.5(c0+c1)
146  // And we want the activation at x to be 'intersection'. So
147  // y = exp(-0.5(x-c0)^2/w^2)
148  // intersection = exp(-0.5((0.5(c0+c1))-c0)^2/w^2)
149  // intersection = exp(-0.5((0.5*c1-0.5*c0)^2/w^2))
150  // intersection = exp(-0.5((0.5*(c1-c0))^2/w^2))
151  // intersection = exp(-0.5(0.25*(c1-c0)^2/w^2))
152  // intersection = exp(-0.125((c1-c0)^2/w^2))
153  // w = sqrt((c1-c0)^2/-8*ln(intersection))
154  for (int cc=0; cc<n_centers-1; cc++)
155  {
156  double w = sqrt(pow(cur_centers[cc+1]-cur_centers[cc],2)/(-8*log(intersection_height_)));
157  cur_widths[cc] = w;
158  }
159  cur_widths[n_centers-1] = cur_widths[n_centers-2];
160  }
161  widths_per_dim_local[i_dim] = cur_widths;
162  }
163 
164  VectorXd digit_max(n_dims);
165  int n_centers = 1;
166  for (int i_dim=0; i_dim<n_dims; i_dim++)
167  {
168  n_centers = n_centers*centers_per_dim_local[i_dim].size();
169  digit_max[i_dim] = centers_per_dim_local[i_dim].size();
170  }
171  VectorXi digit = VectorXi::Zero(n_dims);
172 
173  centers.resize(n_centers,n_dims);
174  widths.resize(n_centers,n_dims);
175  int i_center=0;
176 
177  while (digit[0]<digit_max(0))
178  {
179  for (int i_dim=0; i_dim<n_dims; i_dim++)
180  {
181  centers(i_center,i_dim) = centers_per_dim_local[i_dim][digit[i_dim]];
182  widths(i_center,i_dim) = widths_per_dim_local[i_dim][digit[i_dim]];
183  }
184  i_center++;
185 
186  // Increment last digit by one
187  digit[n_dims-1]++;
188  for (int i_dim=n_dims-1; i_dim>0; i_dim--)
189  {
190  if (digit[i_dim]>=digit_max[i_dim])
191  {
192  digit[i_dim] = 0;
193  digit[i_dim-1]++;
194  }
195  }
196  }
197 
198 }
199 
200 template<class Archive>
201 void MetaParametersLWR::serialize(Archive & ar, const unsigned int version)
202 {
203  // serialize base class information
204  ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(MetaParameters);
205 
206  ar & BOOST_SERIALIZATION_NVP(n_bfs_per_dim_);
207  ar & BOOST_SERIALIZATION_NVP(centers_per_dim_);
208  ar & BOOST_SERIALIZATION_NVP(intersection_height_);
209  ar & BOOST_SERIALIZATION_NVP(regularization_);
210  ar & BOOST_SERIALIZATION_NVP(asymmetric_kernels_);
211 }
212 
213 string MetaParametersLWR::toString(void) const
214 {
215  RETURN_STRING_FROM_BOOST_SERIALIZATION_XML("MetaParametersLWR");
216 }
217 
218 }
MetaParametersLWR * clone(void) const
Return a pointer to a deep copy of the MetaParameters object.
Meta-parameters for the Locally Weighted Regression (LWR) function approximator.
int getExpectedInputDim(void) const
The expected dimensionality of the input data.
double regularization(void) const
Accessor function for regularization.
BOOST_CLASS_EXPORT_IMPLEMENT(DmpBbo::MetaParametersLWR)
For boost::serialization.
MetaParametersLWR class header file.
#define RETURN_STRING_FROM_BOOST_SERIALIZATION_XML(name)
Macro to convert the boost XML serialization of an object into a string.
void getCentersAndWidths(const Eigen::VectorXd &min, const Eigen::VectorXd &max, Eigen::MatrixXd &centers, Eigen::MatrixXd &widths) const
Get the centers and widths of the basis functions.
Base class for all meta-parameters of function approximators.
bool asymmetric_kernels(void) const
Accessor function for asymmetric_kernels.
Header file to generate strings from boost serialized files.
Header file for serialization of Eigen matrices.
std::string toString(void) const
Returns a string representation of the object.