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