1 #include "GaussianProcessSupport.hpp"
2 #include <iostream>
3 #include <cassert>
4 #include <fstream>
5 #include <SubsetOfRegressors.hpp>
6 #include <DeterministicTrainingConditional.hpp>
7 #include <FullyIndependentTrainingConditional.hpp>
8 #include <AugmentedSubsetOfRegressors.hpp>
9 #include <algorithm>
10
11 //--------------------------------------------------------------------------------
initialize(const int dim,const int number_processes_input,double & delta_input,BlackBoxBaseClass * blackbox,std::vector<int> const & update_at_evaluations_input,int update_interval_length_input,const std::string gaussian_process_type,const int exitconst,const bool use_analytic_smoothing)12 void GaussianProcessSupport::initialize ( const int dim, const int number_processes_input, double &delta_input,
13 BlackBoxBaseClass *blackbox, std::vector<int> const &update_at_evaluations_input,
14 int update_interval_length_input, const std::string gaussian_process_type, const int exitconst, const bool use_analytic_smoothing)
15 {
16 nb_values = 0;
17 delta = &delta_input;
18 number_processes = number_processes_input;
19 update_interval_length = update_interval_length_input;
20 for (size_t i = 0; i < update_at_evaluations_input.size(); i++ ) {
21 update_at_evaluations.push_back(update_at_evaluations_input.at(i));
22 }
23 std::sort(update_at_evaluations.begin(), update_at_evaluations.end());
24 //GaussianProcess gp ( dim, *delta );
25 gaussian_process_nodes.resize( 0 );
26 for ( int i = 0; i < number_processes; i++) {
27 //std::cout << gaussian_process_type << std::endl;
28 if( gaussian_process_type.compare( "GP" ) == 0){
29 gaussian_processes.push_back ( std::shared_ptr<GaussianProcess> (new GaussianProcess(dim, *delta, blackbox)) );
30 use_approx_gaussian_process = false;
31 }else if( gaussian_process_type.compare( "SOR" ) == 0){
32 use_approx_gaussian_process = true;
33 gaussian_processes.push_back ( std::shared_ptr<SubsetOfRegressors> (new SubsetOfRegressors(dim, *delta)) );
34 }else if( gaussian_process_type.compare( "DTC" ) == 0){
35 use_approx_gaussian_process = true;
36 gaussian_processes.push_back ( std::shared_ptr<DeterministicTrainingConditional> (new DeterministicTrainingConditional(dim, *delta)) );
37 }else if( gaussian_process_type.compare( "FITC" ) == 0){
38 use_approx_gaussian_process = true;
39 gaussian_processes.push_back ( std::shared_ptr<FullyIndependentTrainingConditional> (new FullyIndependentTrainingConditional(dim, *delta)) );
40 }else{
41 std::cout << "GPSupport: No value set for GP type. Set to default Full Gaussian Process." << std::endl;
42 use_approx_gaussian_process = false;
43 gaussian_processes.push_back ( std::shared_ptr<GaussianProcess> (new GaussianProcess(dim, *delta, blackbox)) );
44 }
45 }
46 rescaled_node.resize( dim );
47 this->use_analytic_smoothing = use_analytic_smoothing;
48 NOEXIT = exitconst;
49 best_index_analytic_information.resize(number_processes);
50 for ( int i = 0; i < number_processes; i++) {
51 best_index_analytic_information[i].resize(25);
52 }
53 bootstrap_estimate.resize( 0 );
54 smoothing_ctr = 0;
55 return;
56 }
57 //--------------------------------------------------------------------------------
58
59 //--------------------------------------------------------------------------------
60
update_gaussian_processes_for_gp(BlackBoxData & evaluations)61 void GaussianProcessSupport::update_gaussian_processes_for_gp( BlackBoxData &evaluations){
62 do_parameter_estimation = false;
63 for(int i = 0; i < number_processes && !do_parameter_estimation; ++i){
64 do_parameter_estimation = gaussian_processes[i]->test_for_parameter_estimation(nb_values, update_interval_length, next_update, update_at_evaluations);
65 }
66
67 if ( nb_values >= next_update && update_interval_length > 0 ) {
68 next_update += update_interval_length;
69 }
70 if ( update_at_evaluations.size( ) > 0 ) {
71 if ( nb_values >= update_at_evaluations[0] ) {
72 update_at_evaluations.erase( update_at_evaluations.begin() );
73 }
74 }
75
76 if ( do_parameter_estimation ) {
77 gaussian_process_active_index.clear( );
78 gaussian_process_nodes.clear( );
79 delta_tmp = (*delta);// * 10e0;
80 // if (delta_tmp < 0.1) delta_tmp = 0.1;
81 best_index = evaluations.best_index;
82 for ( int i = 0; i < nb_values; ++i ) {
83 bool idx_is_active = false;
84 for(int j = 0; j < evaluations.active_index.size(); ++j){
85 if(i == evaluations.active_index[j]){
86 idx_is_active = true;
87 break;
88 }
89 }
90 if ( idx_is_active || diff_norm ( evaluations.nodes[ i ],
91 evaluations.nodes[ best_index ] ) <= gaussian_process_delta_factor * (delta_tmp) ) {
92 gaussian_process_active_index.push_back ( i );
93 // rescale ( 1e0/(delta_tmp), evaluations.nodes[i], evaluations.nodes[best_index],
94 // rescaled_node);
95 gaussian_process_nodes.push_back( evaluations.nodes[ i ] );
96 // gaussian_process_nodes.push_back( rescaled_node );
97 }
98 }
99
100 gaussian_process_values.resize(gaussian_process_active_index.size());
101 gaussian_process_noise.resize(gaussian_process_active_index.size());
102
103 //for (int j = 0; j < number_processes; ++j) {
104 // values[j].clear();
105 // noise[j].clear();
106 // for ( unsigned int i = 0; i < evaluations.values[j].size(); ++i) {
107 // values[j].push_back( evaluations.values[j][i] );
108 // noise[j].push_back( evaluations.noise[j][i] );
109 // }
110 // nb_values = values[0].size( );
111 // assert(noise[j].size() == nb_values);
112 // assert(values[j].size() == nb_values);
113 //}
114
115 //Since we rebuild the GP we update its values
116 for ( int j = 0; j < number_processes; ++j ) {
117 for ( unsigned int i = 0; i < gaussian_process_active_index.size(); ++i ) {
118 gaussian_process_values[i] = evaluations.values_MC[ j ][gaussian_process_active_index[i]];
119 gaussian_process_noise[i] = evaluations.noise_MC[ j ][gaussian_process_active_index[i]];
120 }
121
122 gaussian_processes[j]->estimate_hyper_parameters( gaussian_process_nodes,
123 gaussian_process_values,
124 gaussian_process_noise );
125
126 //std::cout << "Update Gaussian Process: " << j << std::endl;
127 gaussian_processes[j]->build( gaussian_process_nodes,
128 gaussian_process_values,
129 gaussian_process_noise );
130 }
131 } else {
132 for (unsigned int i = last_included; i < nb_values; ++i) {
133 gaussian_process_active_index.push_back(i);
134 // rescale ( 1e0/(delta_tmp), evaluations.nodes[i], evaluations.nodes[best_index],
135 // rescaled_node);
136 for (int j = 0; j < number_processes; ++j) {
137 gaussian_processes[j]->update(evaluations.nodes[i],
138 evaluations.values_MC[j][i],
139 evaluations.noise_MC[j][i]);
140 // gaussian_processes[j].update( rescaled_node,
141 // values[ j ].at( i ),
142 // noise[ j ].at( i ) );
143 }
144 }
145
146 }
147 return;
148 }
149
update_gaussian_processes_for_agp(BlackBoxData & evaluations)150 void GaussianProcessSupport::update_gaussian_processes_for_agp( BlackBoxData &evaluations ){
151
152 do_parameter_estimation = false;
153
154 gaussian_process_active_index.clear( );
155 gaussian_process_nodes.clear( );
156 delta_tmp = (*delta);// * 10e0;
157 // if (delta_tmp < 0.1) delta_tmp = 0.1;
158 best_index = evaluations.best_index;
159 for ( int i = 0; i < nb_values; ++i ) {
160 if ( diff_norm ( evaluations.nodes[ i ],
161 evaluations.nodes[ best_index ] ) <= 3e0 * (delta_tmp) ) {
162 gaussian_process_active_index.push_back ( i );
163 // rescale ( 1e0/(delta_tmp), evaluations.nodes[i], evaluations.nodes[best_index],
164 // rescaled_node);
165 gaussian_process_nodes.push_back( evaluations.nodes[ i ] );
166 // gaussian_process_nodes.push_back( rescaled_node );
167 }
168 }
169
170 gaussian_process_values.resize(gaussian_process_active_index.size());
171 gaussian_process_noise.resize(gaussian_process_active_index.size());
172
173 int nb_u_points = (int) (gaussian_process_nodes.size()*u_ratio);
174 //std::cout << "###Nb u nodes " << nb_u_points << " points###" << std::endl;
175
176 if(nb_u_points >= min_nb_u && !approx_gaussian_process_active){
177 cur_nb_u_points = nb_u_points;
178 approx_gaussian_process_active = true;
179 //std::cout << "###Activating Approximate Gaussian Processes with " << nb_u_points << " points###" << std::endl;
180 for(int i = 0; i < number_processes; ++i){
181 gaussian_processes[i]->sample_u(cur_nb_u_points);
182
183 gaussian_process_values.resize(gaussian_process_active_index.size());
184 gaussian_process_noise.resize(gaussian_process_active_index.size());
185 for ( unsigned int j = 0; j < gaussian_process_active_index.size(); ++j ) {
186 gaussian_process_values.at(j) = evaluations.values_MC[ i ].at( gaussian_process_active_index[j] );
187 gaussian_process_noise.at(j) = evaluations.noise_MC[ i ].at( gaussian_process_active_index[j] );
188 }
189 gaussian_processes[i]->build(gaussian_process_nodes,
190 gaussian_process_values,
191 gaussian_process_noise);
192 }
193 do_parameter_estimation = true;
194 }else if(nb_u_points < min_nb_u && approx_gaussian_process_active){
195 cur_nb_u_points = 0;
196 approx_gaussian_process_active = false;
197 //std::cout << "###Deactivatin Approximate Gaussian Processes with " << nb_u_points << " points###" << std::endl;
198 for(int i = 0; i < number_processes; ++i){
199 gaussian_processes[i]->clear_u();
200
201 gaussian_process_values.resize(gaussian_process_active_index.size());
202 gaussian_process_noise.resize(gaussian_process_active_index.size());
203 for ( unsigned int j = 0; j < gaussian_process_active_index.size(); ++j ) {
204 gaussian_process_values.at(j) = evaluations.values_MC[ i ].at( gaussian_process_active_index[j] );
205 gaussian_process_noise.at(j) = evaluations.noise_MC[ i ].at( gaussian_process_active_index[j] );
206 }
207 gaussian_processes[i]->build(gaussian_process_nodes,
208 gaussian_process_values,
209 gaussian_process_noise);
210 }
211 }else if(nb_u_points > min_nb_u && cur_nb_u_points != nb_u_points && approx_gaussian_process_active){
212 //std::cout << "###Nb u points has changed from " << cur_nb_u_points << " to " << nb_u_points << " points###" << std::endl;
213 cur_nb_u_points = nb_u_points;
214 for(int i = 0; i < number_processes; ++i){
215 gaussian_processes[i]->sample_u(cur_nb_u_points);
216
217 gaussian_process_values.resize(gaussian_process_active_index.size());
218 gaussian_process_noise.resize(gaussian_process_active_index.size());
219 for ( unsigned int j = 0; j < gaussian_process_active_index.size(); ++j ) {
220 gaussian_process_values.at(j) = evaluations.values_MC[ i ].at( gaussian_process_active_index[j] );
221 gaussian_process_noise.at(j) = evaluations.noise_MC[ i ].at( gaussian_process_active_index[j] );
222 }
223 gaussian_processes[i]->build(gaussian_process_nodes,
224 gaussian_process_values,
225 gaussian_process_noise);
226 }
227 do_parameter_estimation = true;
228 }else{
229 //std::cout << "###Nothing changed last update" << std::endl;
230 }
231
232 for(int i = 0; i < number_processes && !do_parameter_estimation; ++i){
233 do_parameter_estimation = gaussian_processes[i]->test_for_parameter_estimation(nb_values, update_interval_length, next_update, update_at_evaluations);
234 }
235
236 if ( nb_values >= next_update && update_interval_length > 0 ) {
237 next_update += update_interval_length;
238 }
239 if ( update_at_evaluations.size( ) > 0 ) {
240 if ( nb_values >= update_at_evaluations[0] ) {
241 update_at_evaluations.erase( update_at_evaluations.begin() );
242 }
243 }
244 //std::cout << "###Do parameter estimation: " << do_parameter_estimation << std::endl;
245
246
247 if ( do_parameter_estimation ) {
248
249 if(approx_gaussian_process_active){
250 gaussian_process_active_index.clear( );
251 gaussian_process_nodes.clear( );
252 delta_tmp = (*delta);// * 10e0;
253 // if (delta_tmp < 0.1) delta_tmp = 0.1;
254 best_index = evaluations.best_index;
255 for ( int i = 0; i < nb_values; ++i ) {
256 //if ( diff_norm ( evaluations.nodes[ i ],
257 // evaluations.nodes[ best_index ] ) <= 3e0 * (delta_tmp) ) {
258 gaussian_process_active_index.push_back ( i );
259 gaussian_process_nodes.push_back( evaluations.nodes[ i ] );
260 }
261
262 gaussian_process_values.resize(gaussian_process_active_index.size());
263 gaussian_process_noise.resize(gaussian_process_active_index.size());
264
265
266 for ( int j = 0; j < number_processes; ++j ) {
267 for ( unsigned int i = 0; i < gaussian_process_active_index.size(); ++i ) {
268 gaussian_process_values.at(i) = evaluations.values_MC[ j ].at( gaussian_process_active_index[i] );
269 gaussian_process_noise.at(i) = evaluations.noise_MC[ j ].at( gaussian_process_active_index[i] );
270 }
271 gaussian_processes[j]->estimate_hyper_parameters( gaussian_process_nodes,
272 gaussian_process_values,
273 gaussian_process_noise );
274 //std::cout << "Update Gaussian Process: " << j << std::endl;
275 gaussian_processes[j]->build( gaussian_process_nodes,
276 gaussian_process_values,
277 gaussian_process_noise );
278 }
279
280 }else{
281 gaussian_process_active_index.clear( );
282 gaussian_process_nodes.clear( );
283 delta_tmp = (*delta);// * 10e0;
284 // if (delta_tmp < 0.1) delta_tmp = 0.1;
285 best_index = evaluations.best_index;
286 for ( int i = 0; i < nb_values; ++i ) {
287 if ( diff_norm ( evaluations.nodes[ i ],
288 evaluations.nodes[ best_index ] ) <= gaussian_process_delta_factor * (delta_tmp) ) {
289 gaussian_process_active_index.push_back ( i );
290 // rescale ( 1e0/(delta_tmp), evaluations.nodes[i], evaluations.nodes[best_index],
291 // rescaled_node);
292 gaussian_process_nodes.push_back( evaluations.nodes[ i ] );
293 // gaussian_process_nodes.push_back( rescaled_node );
294 }
295 }
296
297 gaussian_process_values.resize(gaussian_process_active_index.size());
298 gaussian_process_noise.resize(gaussian_process_active_index.size());
299
300 for ( int j = 0; j < number_processes; ++j ) {
301 for ( unsigned int i = 0; i < gaussian_process_active_index.size(); ++i ) {
302 gaussian_process_values.at(i) = evaluations.values_MC[ j ].at( gaussian_process_active_index[i] );
303 gaussian_process_noise.at(i) = evaluations.noise_MC[ j ].at( gaussian_process_active_index[i] );
304 }
305 gaussian_processes[j]->estimate_hyper_parameters( gaussian_process_nodes,
306 gaussian_process_values,
307 gaussian_process_noise );
308 //std::cout << "Update Gaussian Process: " << j << std::endl;
309 gaussian_processes[j]->build( gaussian_process_nodes,
310 gaussian_process_values,
311 gaussian_process_noise );
312 }
313 }
314 } else {
315 for (unsigned int i = last_included; i < nb_values; ++i) {
316 gaussian_process_active_index.push_back(i);
317 // rescale ( 1e0/(delta_tmp), evaluations.nodes[i], evaluations.nodes[best_index],
318 // rescaled_node);
319 for (int j = 0; j < number_processes; ++j) {
320 gaussian_processes[j]->update(evaluations.nodes[i],
321 evaluations.values_MC[j].at(i),
322 evaluations.noise_MC[j].at(i));
323 // gaussian_processes[j].update( rescaled_node,
324 // values[ j ].at( i ),
325 // noise[ j ].at( i ) );
326 }
327 }
328
329 }
330
331 }
332
333 //--------------------------------------------------------------------------------
update_gaussian_processes(BlackBoxData & evaluations)334 void GaussianProcessSupport::update_gaussian_processes ( BlackBoxData &evaluations )
335 {
336
337 nb_values = evaluations.values[0].size();
338 assert(nb_values == evaluations.nodes.size());
339 assert(nb_values == evaluations.noise[0].size());
340
341 if(use_approx_gaussian_process){
342 update_gaussian_processes_for_agp(evaluations);
343 }else{
344 update_gaussian_processes_for_gp(evaluations);
345 }
346
347 last_included = evaluations.nodes.size();
348 return;
349 }
350 //--------------------------------------------------------------------------------
351
352
353 //--------------------------------------------------------------------------------
smooth_data(BlackBoxData & evaluations)354 int GaussianProcessSupport::smooth_data ( BlackBoxData &evaluations )
355 {
356 //update_data( evaluations );
357
358 update_gaussian_processes( evaluations );
359
360 /*
361 bool active_index_already_in_set = false;
362 for(int cur_active_index : evaluations.active_index ){
363 if(cur_active_index == evaluations.nodes.size()-1){
364 active_index_already_in_set = true;
365 break;
366 }
367 }
368 if(!active_index_already_in_set){
369 evaluations.active_index.push_back( evaluations.nodes.size()-1 );
370 }
371 */
372
373 bool negative_variance_found;
374
375 if (use_analytic_smoothing){
376 std::cout << "WE ARE IN PROTOTYPICAL NEW ERROR ESTIMATION MODE. HARDCODED!!!" << std::endl;
377 double var_R = 0;
378 double cov_RGP = 0;
379 double var_GP = 0;
380 double bootstrap_diffGPRf = 0;
381 double bootstrap_squared = 0;
382 double denominator = 0;
383 double numerator = 0;
384 double optimal_gamma = 0;
385 double optimal_gamma_squared = 0;
386 double MSE = 0;
387 double RMSE = 0;
388 double Rtilde = 0;
389 double cur_noise_xstar = 0;
390 double cur_noise_xstar_MC = 0;
391 double heuristic_RMSE = 0;
392 double heuristic_Rtilde = 0;
393 double heuristic_gamma = 0;
394 std::vector<std::vector<double>> active_index_samples;
395 std::vector<double> cur_xstar;
396 std::vector<double> cur_noise;
397 std::vector<double> cur_noise_MC;
398 int cur_xstar_idx = -1;
399 int cur_xstar_idx_in_gp_active_set = -1;
400 bool print_debug_information = false;
401
402 bool is_latest_index_active_index = false;
403 for(int i = 0; i < evaluations.active_index.size(); ++i){
404 if(evaluations.active_index[i] == evaluations.nodes.size()-1){
405 is_latest_index_active_index = true;
406 break;
407 }
408 }
409 if(!is_latest_index_active_index){
410 evaluations.active_index.push_back( evaluations.nodes.size()-1 );
411 }
412 bool is_best_index_active_index = false;
413 for(int i = 0; i < evaluations.active_index.size(); ++i){
414 if(evaluations.active_index[i] == evaluations.best_index){
415 is_best_index_active_index = true;
416 break;
417 }
418 }
419 if(!is_best_index_active_index){
420 evaluations.active_index.push_back( evaluations.best_index );
421 }
422
423 best_index_analytic_information.clear();
424 best_index_analytic_information.resize(number_processes);
425 for ( int i = 0; i < number_processes; i++) {
426 best_index_analytic_information[i].resize(25);
427 }
428
429 /////////////////
430 //double fill_width = compute_fill_width(evaluations);
431 bool do_bootstrap_estimation = false;
432 if ( (smoothing_ctr++) % 10 == 0){
433 bootstrap_estimate.resize(number_processes);
434 do_bootstrap_estimation = true;
435 }
436 assert(bootstrap_estimate.size() == number_processes);
437 for ( int j = 0; j < number_processes && do_bootstrap_estimation; ++j ) {
438 gaussian_processes[j]->build_inverse();
439 cur_xstar_idx = evaluations.best_index;
440 cur_xstar = evaluations.nodes[cur_xstar_idx];
441 //cur_noise_MC = evaluations.noise_MC[j];
442 //Var[R] is squared standard error: (SE[R])^2
443 //evaluations.noise however is 2 * SE
444 //Thus, divide by two
445 //for (double &noise_ctr : cur_noise_MC) {
446 // noise_ctr /= 2.;
447 //}
448 //cur_noise_xstar_MC = cur_noise_MC[cur_xstar_idx];
449 //var_GP = gaussian_processes[j]->compute_var_meanGP(cur_xstar, cur_noise_MC);
450
451 //Pick the samples for the active indices
452 active_index_samples.resize(gaussian_process_active_index.size( ));
453 for(int i = 0; i < gaussian_process_active_index.size( ); ++i){
454 active_index_samples[i].resize(evaluations.samples[j][gaussian_process_active_index[i]].size());
455 for(int k = 0; k < active_index_samples[i].size(); ++k){
456 active_index_samples[i][k] = evaluations.samples[j][gaussian_process_active_index[i]][k];
457 }
458 }
459 bootstrap_estimate[j] = gaussian_processes[j]->bootstrap_diffGPMC(cur_xstar, active_index_samples, j, 100);
460 //bootstrap_squared = bootstrap_diffGPRf*bootstrap_diffGPRf;
461 //upper_bound_constant_estimate[j] = (bootstrap_squared + var_GP)/fill_width;
462 }
463 //std::cout << "###FILLWIDTH " << fill_width << " #UpperBound: ";
464 //for ( int j = 0; j < number_processes; ++j ) {
465 // std::cout << upper_bound_constant_estimate[j] << " ";
466 //}
467 //std::cout << std::endl;
468 //////////////////
469
470 for ( int j = 0; j < number_processes; ++j ) {
471 if(!do_bootstrap_estimation) { //Otherwise we have built it already for the bootstrap estimation, see above
472 gaussian_processes[j]->build_inverse();
473 }
474
475 //Pick the samples for the active indices
476 //active_index_samples.resize(gaussian_process_active_index.size( ));
477 //for(int i = 0; i < gaussian_process_active_index.size( ); ++i){
478 // active_index_samples[i].resize(evaluations.samples[j][gaussian_process_active_index[i]].size());
479 // for(int k = 0; k < active_index_samples[i].size(); ++k){
480 // active_index_samples[i][k] = evaluations.samples[j][gaussian_process_active_index[i]][k];
481 // }
482 //}
483
484 for ( unsigned int i = 0; i < evaluations.active_index.size( ); ++i ) {
485 cur_xstar_idx = evaluations.active_index[i];
486
487 cur_xstar_idx_in_gp_active_set = -1;
488 for ( unsigned int k = 0; k < gaussian_process_active_index.size( ); ++k ) {
489 if (cur_xstar_idx == gaussian_process_active_index[k]){
490 cur_xstar_idx_in_gp_active_set = k;
491 break;
492 }
493 }
494 assert(cur_xstar_idx_in_gp_active_set != -1);
495
496 cur_xstar = evaluations.nodes[cur_xstar_idx];
497
498
499 cur_noise_MC = evaluations.noise_MC[j];
500 //Var[R] is squared standard error: (SE[R])^2
501 //evaluations.noise however stores the value (2 * SE[R])
502 //Thus, divide by two before squaring below
503 for (double &noise_ctr : cur_noise_MC) {
504 noise_ctr /= 2.;
505 }
506 cur_noise_xstar_MC = cur_noise_MC[cur_xstar_idx];
507
508 gaussian_processes[j]->evaluate( cur_xstar, mean, variance );
509
510 if(print_debug_information){
511 std::cout << "############################"
512 << "\ncur_xstar_idx: " << cur_xstar_idx
513 << "\ncur_value: (" << evaluations.values[ j ][ cur_xstar_idx ]
514 << ", " << evaluations.values[ j ][ evaluations.active_index [ i ] ] << ")";
515 std::cout << "]\ncur_noise_xstar: " << cur_noise_xstar
516 << "\ncur_xstar: [";
517 for(double n : cur_xstar) {
518 std::cout << n << ' ';
519 }
520 std::cout << "]"<< std::endl;
521 }
522 assert(!std::isnan(cur_noise_xstar));
523 var_R = cur_noise_xstar_MC * cur_noise_xstar_MC;
524 cov_RGP = gaussian_processes[j]->compute_cov_meanGPMC(cur_xstar, cur_xstar_idx_in_gp_active_set, cur_noise_xstar_MC);
525 var_GP = gaussian_processes[j]->compute_var_meanGP(cur_xstar, cur_noise_MC);
526 //bootstrap_diffGPRf = gaussian_processes[j]->bootstrap_diffGPMC(cur_xstar, active_index_samples, j, 100);
527 //bootstrap_squared = bootstrap_diffGPRf*bootstrap_diffGPRf;
528
529 bootstrap_squared = bootstrap_estimate[j]*bootstrap_estimate[j];
530 //bootstrap_squared = (mean - evaluations.values[ j ][cur_xstar_idx])*(mean - evaluations.values[ j ][cur_xstar_idx]);
531
532 double upper_bound_cov = sqrt(var_R * var_GP);
533 int set_upper_bound_cov_flag = 0;
534 if(abs(cov_RGP) > upper_bound_cov){
535 cov_RGP = cov_RGP >= 0 ? upper_bound_cov : -upper_bound_cov;
536 set_upper_bound_cov_flag = 1;
537 }
538
539 numerator = var_R - cov_RGP;
540 denominator = bootstrap_squared + var_GP + var_R - 2.0 * cov_RGP;
541 //denominator = upper_bound_constant_estimate[j] + var_R - 2.0 * cov_RGP;
542
543 if(evaluations.active_index[i] == evaluations.best_index){
544 best_index_analytic_information[j][0] = var_R;
545 best_index_analytic_information[j][1] = cov_RGP;
546 best_index_analytic_information[j][2] = var_GP;
547 best_index_analytic_information[j][3] = bootstrap_squared;
548 best_index_analytic_information[j][4] = numerator;
549 best_index_analytic_information[j][5] = denominator;
550 best_index_analytic_information[j][24] = set_upper_bound_cov_flag;
551 }
552
553 optimal_gamma = (std::fabs(denominator) <= DBL_MIN) ? 0.0 : numerator/denominator;
554 if(evaluations.active_index[i] == evaluations.best_index){
555 best_index_analytic_information[j][6] = optimal_gamma;
556 }
557 optimal_gamma = (optimal_gamma > 1.0) ? 1.0 : optimal_gamma;
558 if(evaluations.active_index[i] == evaluations.best_index){
559 best_index_analytic_information[j][7] = optimal_gamma;
560 }
561 optimal_gamma = (optimal_gamma < 0.0 || std::isnan(optimal_gamma)) ? 0.0 : optimal_gamma;
562 if(evaluations.active_index[i] == evaluations.best_index){
563 best_index_analytic_information[j][8] = optimal_gamma;
564 }
565
566 if(print_debug_information){
567 std::cout << "\nvar_R: " << var_R
568 << "\ncov_RGP: " << cov_RGP
569 << "\nvar_GP: " << var_GP
570 << "\nbootstrap_diffGPRf " << sqrt(bootstrap_squared)
571 << "\nR " << evaluations.values[ j ][ cur_xstar_idx ]
572 << "\nmean_GP " << mean
573 << "\noptimal_gamma " << optimal_gamma;
574 }
575
576 optimal_gamma_squared = optimal_gamma*optimal_gamma;
577 MSE = optimal_gamma_squared * bootstrap_squared +
578 optimal_gamma_squared * var_GP +
579 (1.0 - optimal_gamma) * (1.0 - optimal_gamma) * var_R +
580 2.0 * optimal_gamma * (1.0 - optimal_gamma) * cov_RGP;
581 if(evaluations.active_index[i] == evaluations.best_index){
582 best_index_analytic_information[j][9] = MSE;
583 }
584
585 if(std::isnan(MSE)){
586 if(evaluations.active_index[i] == evaluations.best_index){
587 best_index_analytic_information[j][10] = 1;
588 }
589 optimal_gamma = 0.0;
590 MSE = var_R;
591 }
592 if(!(MSE > 0 && MSE < var_R)){
593 if(evaluations.active_index[i] == evaluations.best_index){
594 best_index_analytic_information[j][11] = 1;
595 }
596 if(print_debug_information){
597 std::cout << "\nMSE: " << MSE;
598 std::cout << "\nMSE Reset" << std::endl;
599 }
600 optimal_gamma = 0.0;
601 MSE = var_R;
602 }
603 if(evaluations.active_index[i] == evaluations.best_index){
604 best_index_analytic_information[j][12] = MSE;
605 }
606
607 RMSE = sqrt(MSE);
608 Rtilde = optimal_gamma * mean + (1.0 - optimal_gamma) *
609 ( evaluations.values_MC[ j ][ cur_xstar_idx ] );
610
611 if(evaluations.active_index[i] == evaluations.best_index){
612 best_index_analytic_information[j][13] = mean;
613 }
614 if(evaluations.active_index[i] == evaluations.best_index){
615 best_index_analytic_information[j][14] = evaluations.values_MC[ j ][ cur_xstar_idx ];
616 }
617 if(evaluations.active_index[i] == evaluations.best_index){
618 best_index_analytic_information[j][15] = Rtilde;
619 }
620 if(evaluations.active_index[i] == evaluations.best_index){
621 best_index_analytic_information[j][16] = RMSE;
622 }
623
624 heuristic_gamma = exp( - 2e0*sqrt(variance) );
625 if(evaluations.active_index[i] == evaluations.best_index){
626 best_index_analytic_information[j][17] = heuristic_gamma;
627 }
628 heuristic_Rtilde =
629 heuristic_gamma * mean +
630 (1e0-heuristic_gamma) * ( evaluations.values_MC[ j ][evaluations.active_index [ i ] ] );
631 heuristic_RMSE =
632 heuristic_gamma * 2e0 * sqrt (variance) +
633 (1e0-heuristic_gamma) * ( evaluations.noise_MC[ j ][ evaluations.active_index [ i ] ] );
634
635 if(evaluations.active_index[i] == evaluations.best_index){
636 best_index_analytic_information[j][18] = heuristic_Rtilde;
637 }
638
639 if(evaluations.active_index[i] == evaluations.best_index){
640 best_index_analytic_information[j][19] = heuristic_RMSE;
641 }
642
643 if(evaluations.active_index[i] == evaluations.best_index){
644 best_index_analytic_information[j][20] = variance;
645 }
646
647 if(evaluations.active_index[i] == evaluations.best_index){
648 best_index_analytic_information[j][21] = evaluations.noise_MC[ j ][ evaluations.active_index [ i ] ];
649 }
650 if(evaluations.active_index[i] == evaluations.best_index){
651 best_index_analytic_information[j][22] = gaussian_processes[j]->get_gp_parameters()[1];
652 }
653
654 if(evaluations.active_index[i] == evaluations.best_index){
655 best_index_analytic_information[j][23] = gaussian_processes[j]->get_gp_parameters()[2];
656 }
657
658 if(print_debug_information){
659 std::cout << "\nRMSE: " << RMSE
660 << "\nHeuristic RMSE: " << heuristic_RMSE << std::endl;
661 }
662 evaluations.values[ j ][ cur_xstar_idx ] = Rtilde; // RMSE < heuristic_RMSE ? Rtilde : heuristic_Rtilde;
663
664 evaluations.noise[ j ][ cur_xstar_idx ] = 2 * RMSE;// RMSE < heuristic_RMSE ? RMSE : heuristic_RMSE;
665
666 if(print_debug_information){
667 std::cout << "\nMSE: " << MSE
668 << "\nRtilde: " << evaluations.values[ j ][ cur_xstar_idx ]
669 << "\nRtildeNoise: " << evaluations.noise[ j ][ cur_xstar_idx ]
670 << "\n############################" << std::endl;
671 }
672 assert(!std::isnan(evaluations.values[ j ][ cur_xstar_idx ]));
673 assert(!std::isnan(evaluations.noise[ j ][ cur_xstar_idx ]));
674 }
675 }
676 if(!is_latest_index_active_index){
677 evaluations.active_index.erase( evaluations.active_index.end()-1 );
678 }
679 if(!is_best_index_active_index){
680 evaluations.active_index.erase( evaluations.active_index.end()-1 );
681 }
682 }else{
683 do{
684 negative_variance_found = false;
685
686 bool is_latest_index_active_index = false;
687 for(int i = 0; i < evaluations.active_index.size(); ++i){
688 if(evaluations.active_index[i] == evaluations.nodes.size()-1){
689 is_latest_index_active_index = true;
690 break;
691 }
692 }
693 if(!is_latest_index_active_index){
694 evaluations.active_index.push_back( evaluations.nodes.size()-1 );
695 }
696 for ( unsigned int i = 0; i < evaluations.active_index.size( ); ++i ) {
697 // rescale ( 1e0/(delta_tmp), evaluations.nodes[evaluations.active_index[i]],
698 // evaluations.nodes[best_index], rescaled_node );
699 for ( int j = 0; j < number_processes; ++j ) {
700 // gaussian_processes[j].evaluate( rescaled_node, mean, variance );
701
702 // std::cout << "Smooth Gaussian Process: " << j << std::endl;
703 gaussian_processes[j]->evaluate( evaluations.nodes[evaluations.active_index[i]], mean, variance );
704
705 if (variance < 0e0){
706 negative_variance_found = true;
707 break;
708 }
709
710 weight = exp( - 2e0*sqrt(variance) );
711
712 evaluations.values[ j ][ evaluations.active_index [ i ] ] =
713 weight * mean +
714 (1e0-weight) * ( evaluations.values_MC[ j ][ evaluations.active_index [ i ] ]);
715 evaluations.noise[ j ][ evaluations.active_index [ i ] ] =
716 weight * 2e0 * sqrt (variance) +
717 (1e0-weight) * ( evaluations.noise_MC[ j ][ evaluations.active_index [ i ] ] );
718 //std::cout << "Smooth evaluate var: [" << noise[ j ].at( evaluations.active_index [ i ]) << ", " << 2e0 *sqrt(variance) << "]\n" << std::endl;
719 //std::cout << "Smooth evaluate [" << evaluations.active_index[i] << ", " << j <<"]: mean,variance " << evaluations.values[ j ].at( evaluations.active_index [ i ] ) << ", " << evaluations.noise[ j ].at( evaluations.active_index [ i ] ) << "\n" << std::endl;
720 }
721 if (variance < 0e0){
722 negative_variance_found = true;
723 break;
724 }
725 }
726
727 if(!is_latest_index_active_index){
728 evaluations.active_index.erase( evaluations.active_index.end()-1 );
729 }
730 if(!negative_variance_found){
731 for ( int j = 0; j < number_processes; ++j ) {
732 gaussian_processes[j]->decrease_nugget();
733 }
734 }
735 if(negative_variance_found){
736 for ( int j = 0; j < number_processes; ++j ) {
737 bool max_nugget_reached = gaussian_processes[j]->increase_nugget();
738 if(max_nugget_reached){
739 return -7;
740 }
741 }
742 }
743 }while(negative_variance_found);
744 }
745 /*
746 for ( unsigned int i = 0; i < evaluations.nodes.size( ); ++i ) {
747 // rescale ( 1e0/(delta_tmp), evaluations.nodes[ i ],
748 // evaluations.nodes[best_index], rescaled_node );
749 for ( unsigned int j = 0; j < number_processes; ++j ) {
750 gaussian_processes[j].evaluate( evaluations.nodes[ i ], mean, variance );
751 // gaussian_processes[j].evaluate( rescaled_node, mean, variance );
752 assert ( variance >= 0e0 );
753
754 weight = exp( - 2e0*sqrt(variance) );
755
756 evaluations.values[ j ].at( i ) =
757 weight * mean +
758 (1e0-weight) * ( values[ j ].at( i ) );
759 evaluations.noise[ j ].at( i ) =
760 weight * 2e0 * sqrt (variance) +
761 (1e0-weight) * ( noise[ j ].at( i ) );
762
763 }
764 }
765 */
766
767 do_parameter_estimation = false;
768
769 return NOEXIT;
770 }
771 //--------------------------------------------------------------------------------
772
773
774 //--------------------------------------------------------------------------------
evaluate_objective(BlackBoxData const & evaluations)775 double GaussianProcessSupport::evaluate_objective ( BlackBoxData const &evaluations)
776 {
777 // rescale ( 1e0/(delta_tmp), evaluations.nodes[evaluations.best_index],
778 // evaluations.nodes[best_index], rescaled_node );
779 // gaussian_processes[0].evaluate( rescaled_node, mean, variance );
780 gaussian_processes[0]->evaluate( evaluations.nodes[evaluations.best_index], mean, variance );
781 return mean;
782 }
783
evaluate_gaussian_process_at(const int & idx,std::vector<double> const & loc,double & mean,double & var)784 void GaussianProcessSupport::evaluate_gaussian_process_at(const int &idx, std::vector<double> const &loc, double &mean, double &var) {
785 gaussian_processes.at(idx)->evaluate(loc, mean, var);
786 return;
787 }
788
get_nodes_at(const int & idx) const789 const std::vector<std::vector<double>> &GaussianProcessSupport::get_nodes_at(const int &idx) const {
790 return gaussian_processes.at(idx)->getGp_nodes();
791 }
792
get_induced_nodes_at(const int idx,std::vector<std::vector<double>> & induced_nodes)793 void GaussianProcessSupport::get_induced_nodes_at(const int idx, std::vector<std::vector<double>> &induced_nodes) {
794 gaussian_processes.at(idx)->get_induced_nodes(induced_nodes);
795 return;
796 }
797
set_constraint_ball_center(const std::vector<double> & center)798 void GaussianProcessSupport::set_constraint_ball_center(const std::vector<double>& center){
799 for ( int j = 0; j < number_processes; ++j ) {
800 gaussian_processes[j]->set_constraint_ball_center(center);
801
802 }
803 }
804
set_constraint_ball_radius(const double & radius)805 void GaussianProcessSupport::set_constraint_ball_radius(const double& radius){
806 for ( int j = 0; j < number_processes; ++j ) {
807 gaussian_processes[j]->set_constraint_ball_radius(radius);
808
809 }
810 }
811
getBest_index_analytic_information() const812 const std::vector<std::vector<double>> &GaussianProcessSupport::getBest_index_analytic_information() const {
813 return best_index_analytic_information;
814 }
815
816 typedef struct {
817 const std::vector<double> cons_best_node;
818 const double cons_gaussian_process_delta;
819 } constraint_data;
820
821 typedef struct {
822 const std::vector<std::vector<double>> obj_gaussian_process_nodes;
823 } objective_data;
824
compute_fill_width(BlackBoxData & evaluations)825 double GaussianProcessSupport::compute_fill_width(BlackBoxData& evaluations){
826
827 assert(gaussian_process_nodes.size() > 0);
828 int dim = gaussian_process_nodes[0].size();
829 //initialize optimizer from NLopt library
830 std::vector<double> best_node = evaluations.nodes[evaluations.best_index];
831
832 constraint_data cons_data = { best_node, gaussian_process_delta_factor };
833 objective_data obj_data = { gaussian_process_nodes };
834
835 std::vector<double> lb(dim);
836 std::vector<double> ub(dim);
837 for(int i = 0; i < dim; ++i){
838 lb[i] = best_node[i] - 1.0001*gaussian_process_delta_factor*delta_tmp;
839 ub[i] = best_node[i] + 1.0001*gaussian_process_delta_factor*delta_tmp;
840 }
841
842 // nlopt::opt opt(nlopt::LD_CCSAQ, dimp1);
843 // nlopt::opt opt(nlopt::LN_BOBYQA, dimp1);
844 //
845 nlopt::opt opt(nlopt::GN_DIRECT, dim);
846
847 //opt = nlopt_create(NLOPT_LN_COBYLA, dim+1);
848 opt.set_lower_bounds( lb );
849 opt.set_upper_bounds( ub );
850
851 //std::vector<double> tol = {1};
852 //opt.add_inequality_mconstraint(GaussianProcessSupport::ball_constraint, &cons_data, tol);
853 opt.set_max_objective( GaussianProcessSupport::fill_width_objective, &obj_data);
854
855 // opt.set_xtol_abs(1e-2);
856 // opt.set_xtol_rel(1e-2);
857 //set timeout to NLOPT_TIMEOUT seconds
858 opt.set_maxtime(1.0);
859 opt.set_maxeval(1000);
860 //perform optimization to get correction factors
861
862 int exitflag=-20;
863 double optval;
864 try {
865 exitflag = opt.optimize(best_node, optval);
866 } catch (...) {
867 std::cout << "Something went wrong in fill width optimization: " << exitflag << std::endl;
868 }
869 return optval;
870 }
871
fill_width_objective(std::vector<double> const & x,std::vector<double> & grad,void * data)872 double GaussianProcessSupport::fill_width_objective(std::vector<double> const &x,
873 std::vector<double> &grad,
874 void *data){
875 auto obj_data = reinterpret_cast< objective_data* >(data);
876
877 std::vector<std::vector<double>> gp_nodes = obj_data->obj_gaussian_process_nodes;
878 double min_fill_width = DBL_MAX;
879 double cur_fill_width = 0.0;
880 for(int i = 0; i < gp_nodes.size(); ++i){
881 cur_fill_width = 0.0;
882 for(int j = 0; j < gp_nodes[i].size(); ++j){
883 cur_fill_width += (x[j] - gp_nodes[i][j]) * (x[j] - gp_nodes[i][j]);
884 }
885 if(cur_fill_width < min_fill_width){
886 min_fill_width = cur_fill_width;
887 }
888 }
889 return sqrt(min_fill_width);
890 }
891
ball_constraint(unsigned int m,double * c,unsigned n,const double * x,double * grad,void * data)892 void GaussianProcessSupport::ball_constraint(unsigned int m, double* c, unsigned n, const double *x, double *grad, void *data){
893 auto cons_data = reinterpret_cast<constraint_data*>(data);
894
895 double distance = 0.0;
896 for(int i = 0; i < n ; ++i){
897 distance += (x[i] - cons_data->cons_best_node[i])*(x[i] - cons_data->cons_best_node[i]);
898 }
899 distance = std::sqrt(distance);
900 c[0] = distance - cons_data->cons_gaussian_process_delta;
901 }
902
set_gaussian_process_delta(double gaussian_process_delta)903 void GaussianProcessSupport::set_gaussian_process_delta(double gaussian_process_delta) {
904 GaussianProcessSupport::gaussian_process_delta_factor = gaussian_process_delta;
905 }
906 /*
907 void GaussianProcessSupport::do_resample_u(){
908 for ( int j = 0; j < number_processes; ++j ) {
909 gaussian_processes[j]->do_resample_u();
910 }
911 }
912 */
913 //--------------------------------------------------------------------------------
914