1 #include "GaussianProcess.hpp"
2 #include "math.h"
3 #include <iostream>
4 #include <iomanip>
5 #include <cassert>
6 #include <boost/random.hpp>
7
8 //--------------------------------------------------------------------------------
GaussianProcess(int n,double & delta_input,BlackBoxBaseClass * blackbox_input)9 GaussianProcess::GaussianProcess ( int n, double &delta_input, BlackBoxBaseClass* blackbox_input) :
10 TriangularMatrixOperations ( n ),
11 dim( n )
12 {
13 lb.reserve( n+1 );
14 ub.reserve( n+1 );
15 gp_parameters.reserve(n+1);
16 for (int i = 0; i < n+1; i++) {
17 lb.push_back( 0e0 );
18 ub.push_back( 10e0 );
19 gp_parameters.push_back( 1e0 );
20 }
21 nb_gp_nodes = 0;
22 gp_pointer = NULL;
23 delta = &delta_input;
24 blackbox = blackbox_input;
25 }
26 //--------------------------------------------------------------------------------
27
28 //--------------------------------------------------------------------------------
GaussianProcess(int n,double & delta_input,BlackBoxBaseClass * blackbox_input,std::vector<double> gp_parameters_input)29 GaussianProcess::GaussianProcess ( int n, double &delta_input, BlackBoxBaseClass* blackbox_input, std::vector<double> gp_parameters_input ) :
30 TriangularMatrixOperations ( n ),
31 dim( n )
32 {
33 if(gp_parameters_input.size() != n+1){
34 std::cout << "gp_parameters_input wrong size! Should be: " << n+1 << ", is: " << gp_parameters_input.size() << std::endl;
35 exit(-1);
36 }
37
38 lb.reserve( n+1 );
39 ub.reserve( n+1 );
40 gp_parameters.reserve(n+1);
41 for (int i = 0; i < n+1; i++) {
42 lb.push_back( 0e0 );
43 ub.push_back( 10e0 );
44 gp_parameters.push_back( gp_parameters_input[i] );
45 }
46 nb_gp_nodes = 0;
47 gp_pointer = NULL;
48 delta = &delta_input;
49 blackbox = blackbox_input;
50 }
51 //--------------------------------------------------------------------------------
52
53
54 //--------------------------------------------------------------------------------
evaluate_kernel(std::vector<double> const & x,std::vector<double> const & y)55 double GaussianProcess::evaluate_kernel ( std::vector<double> const &x,
56 std::vector<double> const &y )
57 {
58 return evaluate_kernel ( x, y, gp_parameters );
59 /*
60 dist = 0e0;
61 for ( int i = 0; i < dim; ++i )
62 dist += pow( (x.at(i) - y.at(i)), 2e0) / gp_parameters.at( i+1 );
63 kernel_evaluation = exp(-dist / 2e0 );
64
65 return kernel_evaluation * gp_parameters.at( 0 ) ;
66 */
67 }
68 //--------------------------------------------------------------------------------
69 //--------------------------------------------------------------------------------
evaluate_kernel(std::vector<double> const & x,std::vector<double> const & y,std::vector<double> const & p)70 double GaussianProcess::evaluate_kernel ( std::vector<double> const &x,
71 std::vector<double> const &y,
72 std::vector<double> const &p )
73 {
74 dist = 0e0;
75 for ( int i = 0; i < dim; ++i )
76 dist += pow( (x.at(i) - y.at(i)), 2e0) / p.at( i+1 );
77 kernel_evaluation = exp(-dist / 2e0 );
78
79 return kernel_evaluation * p.at( 0 ) ;
80 }
81 //--------------------------------------------------------------------------------
82
83 //--------------------------------------------------------------------------------
d_evaluate_kernel(std::vector<double> const & x,std::vector<double> const & y,std::vector<double> const & p,int j)84 double GaussianProcess::d_evaluate_kernel ( std::vector<double> const &x,
85 std::vector<double> const &y,
86 std::vector<double> const &p, int j )
87 {
88 dist = 0e0;
89 for ( int i = 0; i < dim; ++i )
90 dist += pow( (x.at(i) - y.at(i)), 2e0) / p.at(i+1);
91 kernel_evaluation = exp(-dist / 2e0 );
92 if ( j == 0 ) {
93 return kernel_evaluation;
94 } else {
95 kernel_evaluation *= 2e0*pow( (x.at(j-1) - y.at(j-1)), 2e0) / pow( p.at(j-1), 2e0);
96 return kernel_evaluation * p.at(0) ;
97 }
98
99 }
100 //--------------------------------------------------------------------------------
101
test_for_parameter_estimation(const int & nb_values,const int & update_interval_length,const int & next_update,const std::vector<int> & update_at_evaluations)102 bool GaussianProcess::test_for_parameter_estimation(const int& nb_values,
103 const int& update_interval_length,
104 const int& next_update,
105 const std::vector<int>& update_at_evaluations){
106 bool do_parameter_estimation = false;
107
108 if ( nb_values >= next_update && update_interval_length > 0 ) {
109 do_parameter_estimation = true;
110 return do_parameter_estimation;
111 }
112 if ( update_at_evaluations.size( ) > 0 ) {
113 if ( nb_values >= update_at_evaluations[0] ) {
114 do_parameter_estimation = true;
115 }
116 }
117
118 return do_parameter_estimation;
119 }
120
121
122 //--------------------------------------------------------------------------------
build(std::vector<std::vector<double>> const & nodes,std::vector<double> const & values,std::vector<double> const & noise)123 void GaussianProcess::build ( std::vector< std::vector<double> > const &nodes,
124 std::vector<double> const &values,
125 std::vector<double> const &noise )
126 {
127 //std::cout << "GP build [" << nodes.size() << "]" << std::endl;
128 //std::cout << "With Parameters: " << std::endl;
129 //for ( int i = 0; i < dim+1; ++i )
130 // std::cout << "gp_param = " << gp_parameters[i] << std::endl;
131 //std::cout << std::endl;
132
133 nb_gp_nodes = nodes.size();
134 gp_nodes.clear();
135 //gp_noise.clear();
136 for ( int i = 0; i < nb_gp_nodes; ++i ) {
137 gp_nodes.push_back ( nodes.at(i) );
138 //gp_noise.push_back( noise.at(i) );
139 }
140
141 // auto minmax = std::minmax_element(values.begin(), values.end());
142 // min_function_value = values.at((minmax.first - values.begin()));
143 // max_function_value = values.at((minmax.second - values.begin()));
144
145 // std::cout << "[ " << min_function_value << ", " << max_function_value << " ]" << std::endl;
146
147 L.clear();
148 L.resize( nb_gp_nodes );
149
150 for (int i = 0; i < nb_gp_nodes; i++) {
151 for (int j = 0; j <= i; j++){
152 L.at(i).push_back (evaluate_kernel( gp_nodes[i], gp_nodes[j] ) );
153 }
154 L.at(i).at(i) += pow( noise.at(i) / 2e0 + noise_regularization, 2e0 );
155 }
156
157 /*
158 for (int i = 0; i < nb_gp_nodes; i++) {
159 for (int j = 0; j <=i; j++){
160 std::cout << std::setprecision(16) << L[i][j] << ' ';
161 }
162 for (int j = i+1; j < nb_gp_nodes; j++){
163 std::cout << std::setprecision(16) << L[j][i] << ' ';
164 }
165
166 std::cout << ';' << std::endl;
167 }
168 */
169
170 CholeskyFactorization::compute( L, pos, rho, nb_gp_nodes );
171 assert( pos == 0 );
172
173 scaled_function_values.resize(nb_gp_nodes);
174 for (int i = 0; i < nb_gp_nodes; i++) {
175 scaled_function_values.at(i) = values.at(i);
176 // scaled_function_values.at(i) = values.at(i) - min_function_value;
177 // scaled_function_values.at(i) /= 5e-1*( max_function_value-min_function_value );
178 // scaled_function_values.at(i) -= 1e0;
179 }
180
181 alpha = scaled_function_values;
182 forward_substitution( L, alpha );
183 backward_substitution( L, alpha );
184
185 return;
186 }
187 //--------------------------------------------------------------------------------
188
189 //--------------------------------------------------------------------------------
update(std::vector<double> const & x,double & value,double & noise)190 void GaussianProcess::update ( std::vector<double> const &x,
191 double &value,
192 double &noise )
193 {
194 //std::cout << "GP update [" << nb_gp_nodes+1 << "]" << std::endl;
195 K0.resize( nb_gp_nodes );
196 nb_gp_nodes += 1;
197 gp_nodes.push_back( x );
198 //gp_noise.push_back( noise );
199 scaled_function_values.push_back ( value );
200 // scaled_function_values.push_back ( ( value - min_function_value ) /
201 // ( 5e-1*( max_function_value-min_function_value ) ) - 1e0 );
202
203 for (int i = 0; i < nb_gp_nodes-1; i++)
204 K0.at(i) = evaluate_kernel( gp_nodes[i], x );
205
206 forward_substitution( L, K0 );
207
208 L.push_back ( K0 );
209
210 L.at(L.size()-1).push_back(
211 sqrt( evaluate_kernel( x, x ) + pow( noise / 2e0 + noise_regularization, 2e0 ) -
212 VectorOperations::dot_product(K0, K0) ) );
213
214 alpha = scaled_function_values;
215 forward_substitution( L, alpha );
216 backward_substitution( L, alpha );
217
218 return;
219 }
220 //--------------------------------------------------------------------------------
221
222 //--------------------------------------------------------------------------------
evaluate(std::vector<double> const & x,double & mean,double & variance)223 void GaussianProcess::evaluate ( std::vector<double> const &x,
224 double &mean, double &variance )
225 {
226 K0.resize( nb_gp_nodes );
227
228 for (int i = 0; i < nb_gp_nodes; i++)
229 K0.at(i) = evaluate_kernel( gp_nodes[i], x );
230
231 mean = VectorOperations::dot_product(K0, alpha);
232 // mean = VectorOperations::dot_product(K0, alpha) + 1e0;
233 // mean *= 5e-1*( max_function_value-min_function_value );
234 // mean += min_function_value;
235
236 forward_substitution( L, K0 );
237
238 variance = evaluate_kernel( x, x ) - VectorOperations::dot_product(K0, K0);
239
240 //std::cout << "GP evalute [" << gp_nodes.size() <<"] mean,variance " << mean << ", " << variance << std::endl;
241 return;
242 }
243 //--------------------------------------------------------------------------------
244
245 //--------------------------------------------------------------------------------
evaluate(std::vector<double> const & x,double & mean)246 void GaussianProcess::evaluate ( std::vector<double> const &x,
247 double &mean)
248 {
249 K0.resize( nb_gp_nodes );
250
251 for (int i = 0; i < nb_gp_nodes; i++)
252 K0.at(i) = evaluate_kernel( gp_nodes[i], x );
253
254 mean = VectorOperations::dot_product(K0, alpha);
255 // mean = VectorOperations::dot_product(K0, alpha) + 1e0;
256 // mean *= 5e-1*( max_function_value-min_function_value );
257 // mean += min_function_value;
258
259 //std::cout << "GP evalute [" << gp_nodes.size() <<"] mean,variance " << mean << ", " << variance << std::endl;
260 return;
261 }
262 //--------------------------------------------------------------------------------
263
264 //--------------------------------------------------------------------------------
evaluate(std::vector<double> const & x,std::vector<double> const & f_train,double & mean)265 void GaussianProcess::evaluate ( std::vector<double> const &x,
266 std::vector<double> const &f_train,
267 double &mean)
268 {
269 assert(f_train.size() == nb_gp_nodes);
270
271 K0.resize( nb_gp_nodes );
272
273 for (int i = 0; i < nb_gp_nodes; i++)
274 K0.at(i) = evaluate_kernel( gp_nodes[i], x );
275
276 std::vector<double> local_f_train;
277 local_f_train.resize(nb_gp_nodes);
278 for (int i = 0; i < nb_gp_nodes; i++) {
279 local_f_train[i] = f_train[i];
280 }
281
282 forward_substitution( L, local_f_train );
283 backward_substitution( L, local_f_train );
284
285 mean = VectorOperations::dot_product(K0, local_f_train);
286
287 return;
288 }
289 //--------------------------------------------------------------------------------
290
291
292 //--------------------------------------------------------------------------------
build_inverse()293 void GaussianProcess::build_inverse ()
294 {
295 L_inverse.resize(nb_gp_nodes);
296 for (int i = 0; i < nb_gp_nodes; i++){
297 L_inverse[i].resize(nb_gp_nodes);
298 for (int j = 0; j < nb_gp_nodes; j++){
299 if(i==j)
300 L_inverse[i][j] = 1;
301 else
302 L_inverse[i][j] = 0;
303 }
304 }
305 for (int i = 0; i < nb_gp_nodes; i++){
306 forward_substitution( L, L_inverse[i]);
307 }
308 for (int i = 0; i < nb_gp_nodes; i++){
309 backward_substitution( L, L_inverse[i]);
310 }
311 return;
312 }
313 //--------------------------------------------------------------------------------
314
315 //--------------------------------------------------------------------------------
compute_var_meanGP(std::vector<double> const & xstar,std::vector<double> const & noise)316 double GaussianProcess::compute_var_meanGP ( std::vector<double>const& xstar, std::vector<double> const& noise)
317 {
318 std::vector<double> k_xstar_X(nb_gp_nodes);
319 std::vector<double> k_xstar_X_Kinv(nb_gp_nodes);
320 std::vector<double> k_xstar_X_Kinv_squared(nb_gp_nodes);
321 std::vector<double> gp_noise_squared(nb_gp_nodes);
322 double var_meanGP = 0;
323
324 for(int i = 0; i < nb_gp_nodes; ++i){
325 k_xstar_X[i] = evaluate_kernel(xstar, gp_nodes[i]);
326 }
327
328 VectorOperations::vec_mat_product(L_inverse, k_xstar_X, k_xstar_X_Kinv);
329
330 for(int i = 0; i < nb_gp_nodes; ++i){
331 k_xstar_X_Kinv_squared[i] = k_xstar_X_Kinv[i]*k_xstar_X_Kinv[i];
332 gp_noise_squared[i] = noise[i]*noise[i];
333 }
334
335 var_meanGP = VectorOperations::dot_product(k_xstar_X_Kinv_squared, gp_noise_squared);
336
337 return var_meanGP;
338 }
339 //--------------------------------------------------------------------------------
340
341
342 //--------------------------------------------------------------------------------
compute_cov_meanGPMC(std::vector<double> const & xstar,int const & xstar_idx,double const & noise)343 double GaussianProcess::compute_cov_meanGPMC ( std::vector<double>const& xstar, int const& xstar_idx, double const& noise)
344 {
345 //std::vector<double> k_xstar_X(nb_gp_nodes);
346 double cov_meanGPMC = 0.;
347 double cov_term = 0.;
348 double L_inverse_term = 0.;
349 double kernel_term = 0.;
350 //std::cout << "Cov terms (idx, kernel, KK_inv, Prod): " << std::endl;
351 assert(xstar_idx < nb_gp_nodes);
352 for(int i = 0; i < nb_gp_nodes; ++i){
353 //k_xstar_X[i] = evaluate_kernel(xstar, gp_nodes[i]);
354 L_inverse_term = L_inverse[i][xstar_idx];
355 kernel_term = evaluate_kernel(xstar, gp_nodes[i]);
356 cov_term = kernel_term*L_inverse_term;
357 cov_meanGPMC += cov_term;
358 //std::cout << "(" << xstar_idx << ", "<< kernel_term << ", " << L_inverse_term << ", " << cov_term << ")" << std::endl;
359 }
360 cov_meanGPMC *= noise*noise;
361 return cov_meanGPMC;
362 }
363 //--------------------------------------------------------------------------------
364
365 //--------------------------------------------------------------------------------
bootstrap_diffGPMC(std::vector<double> const & xstar,std::vector<std::vector<double>> const & samples,const unsigned int index,int max_bootstrap_samples,int inp_seed)366 double GaussianProcess::bootstrap_diffGPMC ( std::vector<double>const& xstar, std::vector<std::vector<double>>const& samples, const unsigned int index, int max_bootstrap_samples, int inp_seed)
367 {
368 double mean_xstar = 0.0;
369 double mean_bootstrap = 0.0;
370 double mean_bootstrap_eval = 0.0;
371 double bootstrap_estimate = 0.0;
372 int random_idx = -1;
373 std::vector<double> f_train_bootstrap(nb_gp_nodes);
374 std::vector<double> k_xstar_X_Kinv(nb_gp_nodes);
375 std::vector<double> k_xstar_X(nb_gp_nodes);
376 unsigned int nb_samples = samples[0].size();
377 std::vector<double> bootstrap_samples;
378 boost::random::uniform_int_distribution<> distr(0, nb_samples - 1);
379
380 std::random_device rd; // obtain a random number from hardware
381 if(inp_seed == -1) {
382 inp_seed = rd();
383 }
384 //std::mt19937_64 bootstrap_eng(inp_seed);
385 boost::random::mt19937 bootstrap_eng(inp_seed);
386
387 for(int i = 0; i < nb_gp_nodes; ++i){
388 k_xstar_X[i] = evaluate_kernel(xstar, gp_nodes[i]);
389 }
390
391 vec_mat_product(L_inverse, k_xstar_X, k_xstar_X_Kinv); //k_xstar_X (K_XX - sigma^2 I)^{-1}
392 assert(samples.size() == nb_gp_nodes);
393
394 bootstrap_samples.resize(nb_samples);
395 //#pragma omp parallel for private(bootstrap_samples, eng) reduction(+ : mean_bootstrap)
396 for(int i = 0; i < max_bootstrap_samples; ++i){
397 for(int j = 0; j < nb_gp_nodes; ++j){ //sample randomly from training data
398 for(int k = 0; k < nb_samples; ++k){
399 bootstrap_samples[k] = samples[j][distr(bootstrap_eng)];
400 }
401 f_train_bootstrap[j] = blackbox->evaluate_samples(bootstrap_samples, index, xstar);
402 }
403 mean_bootstrap += dot_product(k_xstar_X_Kinv, f_train_bootstrap); // k_xstar_X (K_XX - sigma^2 I)^{-1} f_train_bootstrap
404 }
405 mean_bootstrap /= max_bootstrap_samples;
406 evaluate(xstar, mean_xstar);
407 bootstrap_estimate = mean_bootstrap - mean_xstar;
408
409 return bootstrap_estimate;
410 }
411 //--------------------------------------------------------------------------------
412
413 //--------------------------------------------------------------------------------
estimate_hyper_parameters(std::vector<std::vector<double>> const & nodes,std::vector<double> const & values,std::vector<double> const & noise)414 void GaussianProcess::estimate_hyper_parameters ( std::vector< std::vector<double> > const &nodes,
415 std::vector<double> const &values,
416 std::vector<double> const &noise )
417 {
418 //std::cout << "GP Estimator" << std::endl;
419 nb_gp_nodes = nodes.size();
420 gp_nodes.clear();
421 gp_noise.clear();
422 for ( int i = 0; i < nb_gp_nodes; ++i ) {
423 gp_nodes.push_back ( nodes.at(i) );
424 gp_noise.push_back ( noise.at(i) );
425 }
426
427 gp_pointer = this;
428
429 // auto minmax = std::minmax_element(values.begin(), values.end());
430 // min_function_value = values.at((minmax.first - values.begin()));
431 // max_function_value = values.at((minmax.second - values.begin()));
432 /*
433 auto minmax = std::minmax_element(values.begin(), values.end());
434 min_function_value = values.at((minmax.first - values.begin()));
435 max_function_value = fabs(values.at((minmax.second - values.begin())));
436 if ( fabs(min_function_value) > max_function_value )
437 max_function_value = fabs( min_function_value );
438 */
439 L.clear();
440 L.resize( nb_gp_nodes );
441 for ( int i = 0; i < nb_gp_nodes; ++i)
442 L.at(i).resize( i+1 );
443
444 scaled_function_values.resize(nb_gp_nodes);
445 for ( int i = 0; i < nb_gp_nodes; ++i) {
446 scaled_function_values.at(i) = values.at(i);
447 // scaled_function_values.at(i) = values.at(i) - min_function_value;
448 // scaled_function_values.at(i) /= 5e-1*( max_function_value-min_function_value );
449 // scaled_function_values.at(i) -= 1e0;
450 }
451
452 double optval;
453 //adjust those settings to optimize GP approximation
454 //--------------------------------------------------
455 // double max_noise = 0e0;
456 // for (int i = 0; i < nb_gp_nodes; i++) {
457 // if (gp_noise.at( i ) > max_noise)
458 // max_noise = gp_noise.at( i );
459 // }
460
461 //My Version
462 /*lb[0] = 1e-3;
463 ub[0] = 1e3;
464 lb[0] = max_function_value - 1e2;
465 if ( lb[0] < 1e-3 ) lb[0] = 1e-3;
466 ub[0] = max_function_value + 1e2;
467 if ( ub[0] > 1e3 ) ub[0] = 1e3;
468 if ( ub[0] <= lb[0]) lb[0] = 1e-3;
469 double delta_threshold = *delta;
470 if (delta_threshold < 1e-2) delta_threshold = 1e-2;
471 for (int i = 0; i < dim; ++i) {
472 lb[i+1] = 1e-2 * delta_threshold; // 1e1
473 ub[i+1] = 2.0 * delta_threshold; // 1e2
474 }*/
475
476
477 //Florians old version1:
478 /*lb[0] = 1e-1;
479 ub[0] = 1e1;
480 lb[0] = max_function_value - 1e2;
481 if ( lb[0] < 1e-2 ) lb[0] = 1e-2;
482 ub[0] = max_function_value + 1e2;
483 double delta_threshold = *delta;
484 if (delta_threshold < 1e-2) delta_threshold = 1e-2;
485 for (int i = 0; i < dim; ++i) {
486 lb[i+1] = 1e-2 * delta_threshold; // 1e1
487 ub[i+1] = 2.0 * delta_threshold; // 1e2
488 }*/
489 //Florians old version2:
490 lb[0] = 1e-1; // * pow(1000e0 * max_noise / 2e0, 2e0);
491 ub[0] = 1e1;// * pow(1000e0 * max_noise / 2e0, 2e0);
492 double delta_threshold = *delta;
493 if (delta_threshold < 1e-2) delta_threshold = 1e-2;
494 for (int i = 0; i < dim; ++i) {
495 lb[i+1] = 1e1 * delta_threshold;
496 ub[i+1] = 1e2 * delta_threshold;
497 }
498
499 if (gp_parameters[0] < 0e0) {
500 //gp_parameters[0] = max_function_value;
501 gp_parameters[0] = lb[0]*5e-1 + 5e-1*ub[0];
502 for (int i = 1; i < dim+1; ++i) {
503 gp_parameters[i] = (lb[i]*5e-1 + 5e-1*ub[i]);
504 }
505 } else {
506 for (int i = 0; i < dim+1; ++i) {
507 if ( gp_parameters[i] <= lb[i] ) gp_parameters[i] = 1.1 * lb[i];
508 if ( gp_parameters[i] >= ub[i] ) gp_parameters[i] = 0.9 * ub[i];
509 }
510 }
511 //--------------------------------------------------
512
513 //initialize optimizer from NLopt library
514 int dimp1 = dim+1;
515 // nlopt::opt opt(nlopt::LD_CCSAQ, dimp1);
516 // nlopt::opt opt(nlopt::LN_BOBYQA, dimp1);
517 //
518 //nlopt::opt opt(nlopt::GN_DIRECT, dimp1); //Somehow GN_DIRECT is not deterministic, also nlopt::srand(seed) has no effect to fix that.
519 nlopt::opt opt(nlopt::LN_COBYLA, dimp1);
520
521 //opt = nlopt_create(NLOPT_LN_COBYLA, dim+1);
522 opt.set_lower_bounds( lb );
523 opt.set_upper_bounds( ub );
524
525 opt.set_max_objective( GaussianProcess::parameter_estimation_objective, gp_pointer);
526
527 // opt.set_xtol_abs(1e-2);
528 // opt.set_xtol_rel(1e-2);
529 //set timeout to NLOPT_TIMEOUT seconds
530 opt.set_maxtime(1.0);
531 //opt.set_maxeval(10000);
532 //perform optimization to get correction factors
533
534 int exitflag=-20;
535 try {
536 nlopt::srand(1);
537 exitflag = opt.optimize(gp_parameters, optval);
538 } catch (...) {
539 gp_parameters[0] = lb[0]*5e-1 + 5e-1*ub[0];
540 for (int i = 1; i < dim+1; ++i) {
541 gp_parameters[i] = (lb[i]*5e-1 + 5e-1*ub[i]);
542 }
543 }
544
545 //std::cout << "exitflag = "<< exitflag<<std::endl;
546 //std::cout << "OPTVAL .... " << optval << std::endl;
547 //for ( int i = 0; i < gp_parameters.size(); ++i )
548 // std::cout << "gp_param = " << gp_parameters[i] << std::endl;
549 //std::cout << std::endl;
550
551
552 return;
553 }
554 //--------------------------------------------------------------------------------
estimate_hyper_parameters_induced_only(std::vector<std::vector<double>> const & nodes,std::vector<double> const & values,std::vector<double> const & noise)555 void GaussianProcess::estimate_hyper_parameters_induced_only ( std::vector< std::vector<double> > const &nodes,
556 std::vector<double> const &values,
557 std::vector<double> const &noise )
558 { this->estimate_hyper_parameters(nodes, values, noise);}
559
estimate_hyper_parameters_ls_only(std::vector<std::vector<double>> const & nodes,std::vector<double> const & values,std::vector<double> const & noise)560 void GaussianProcess::estimate_hyper_parameters_ls_only ( std::vector< std::vector<double> > const &nodes,
561 std::vector<double> const &values,
562 std::vector<double> const &noise )
563 { this->estimate_hyper_parameters(nodes, values, noise);}
564
565 //--------------------------------------------------------------------------------
parameter_estimation_objective(std::vector<double> const & x,std::vector<double> & grad,void * data)566 double GaussianProcess::parameter_estimation_objective(std::vector<double> const &x,
567 std::vector<double> &grad,
568 void *data)
569 {
570
571 GaussianProcess *d = reinterpret_cast<GaussianProcess*>(data);
572
573
574
575 for (int i = 0; i < d->nb_gp_nodes; ++i) {
576 for (int j = 0; j <= i; ++j)
577 d->L.at(i).at(j) = d->evaluate_kernel( d->gp_nodes[i], d->gp_nodes[j], x );
578 d->L.at(i).at(i) += pow( d->gp_noise.at(i) / 2e0 + d->noise_regularization, 2e0 );
579 }
580
581
582 d->CholeskyFactorization::compute( d->L, d->pos, d->rho, d->nb_gp_nodes );
583 //assert(d->pos == 0);
584 double result = 0;
585 if(d->pos == 0){ //result stays 0 if L is not spd
586 d->alpha = d->scaled_function_values;
587 d->forward_substitution( d->L, d->alpha );
588 d->backward_substitution( d->L, d->alpha );
589 result = -0.5*d->VectorOperations::dot_product(d->scaled_function_values, d->alpha) +
590 -0.5*((double)d->nb_gp_nodes)*log( 2. * M_PI );
591 for (int i = 0; i < d->nb_gp_nodes; ++i)
592 result -= 0.5*log(d->L.at(i).at(i));
593 }
594
595
596 /*
597 //Eigen::ColPivHouseholderQR<Eigen::MatrixXd> S;
598 d->S = (d->L).fullPivHouseholderQr();
599 //d->S = (d->L).colPivHouseholderQr();
600 d->K0 = (d->S).solve(d->scaled_function_values);
601
602
603 double result = -0.5*(d->scaled_function_values).dot(d->K0) -
604 0.5*log((d->S).absDeterminant() + 1e-16) -
605 0.5*((double)d->nb_gp_nodes)*log(6.28);
606
607
608 if ( !grad.empty() ) {
609 for (int k = 0; k < d->dim+1; ++k) {
610 for (int i = 0; i < d->nb_gp_nodes; i++) {
611 for (int j = 0; j <= i; j++) {
612 d->dK(i, j) = d->d_evaluate_kernel( d->gp_nodes[i], d->gp_nodes[j], x, k);
613 if (i != j) d->dK(j, i) = d->dK(i, j);
614 }
615 }
616 grad[k] = 0.5*((d->K0*(d->K0.transpose()))*d->dK - d->S.solve(d->dK)).trace() -
617 0.5*((double)d->nb_gp_nodes)*0e-6;
618 }
619 }
620 */
621 return result;
622
623 }
624
getGp_nodes() const625 const std::vector<std::vector<double>> &GaussianProcess::getGp_nodes() const {
626 return gp_nodes;
627 }
628
get_induced_nodes(std::vector<std::vector<double>> &) const629 void GaussianProcess::get_induced_nodes(std::vector<std::vector<double> > &) const {
630 return;
631 }
632
get_hyperparameters()633 std::vector<double> GaussianProcess::get_hyperparameters(){
634 return this->gp_parameters;
635 }
decrease_nugget()636 void GaussianProcess::decrease_nugget(){
637 return;
638 }
increase_nugget()639 bool GaussianProcess::increase_nugget(){
640 return true;
641 }
642
get_gp_parameters() const643 const std::vector<double> &GaussianProcess::get_gp_parameters() const {
644 return gp_parameters;
645 }
646 //--------------------------------------------------------------------------------
647