1 /// \file IOHprofiler_csv_logger.cpp
2 /// \brief cpp file for the class IOHprofiler_csv_logger.
3 ///
4 /// A detailed file description.
5 ///
6 /// \author Furong Ye
7 
8 #include "IOHprofiler_csv_logger.h"
9 
IOHprofiler_csv_logger()10 IOHprofiler_csv_logger::IOHprofiler_csv_logger() {
11   this->output_directory = "./";
12   this->folder_name = "IOHprofiler_test";
13   this->algorithm_name =  "algorithm";
14   this->algorithm_info = "algorithm_info";
15 }
16 
IOHprofiler_csv_logger(std::string directory,std::string folder_name,std::string alg_name,std::string alg_info)17 IOHprofiler_csv_logger::IOHprofiler_csv_logger(std::string directory, std::string folder_name,
18                         std::string alg_name, std::string alg_info) {
19   this->output_directory = directory;
20   this->folder_name = folder_name;
21   this->algorithm_name =  alg_name;
22   this->algorithm_info = alg_info;
23 }
24 
~IOHprofiler_csv_logger()25 IOHprofiler_csv_logger::~IOHprofiler_csv_logger() {
26   this->clear_logger();
27 }
28 
folder_exist(std::string folder_name)29 bool IOHprofiler_csv_logger::folder_exist(std::string folder_name) {
30   // #if defined(_WIN32) || defined(_WIN64) || defined(__MINGW64__) || defined(__CYGWIN__)
31   //   DWORD ftyp = GetFileAttributesA(folder_name.c_str());
32   //   if (ftyp & FILE_ATTRIBUTE_DIRECTORY)
33   //     return true;
34   //   else
35   //     return false;
36   // #else
37   //   std::fstream _file;
38   //   _file.open(folder_name, std::ios::in);
39   //   if(!_file) {
40   //     return false;
41   //   } else {
42   //     return true;
43   //   }
44   // #endif
45 
46   // Check for existence.
47   #if defined(_WIN32) || defined(_WIN64) || defined(__MINGW64__) || defined(__CYGWIN__)
48     if( _access(folder_name.c_str(), 0 ) != -1 ) {
49       // Check for write permission.
50       // Assume file is read-only.
51       if( _access(folder_name.c_str(), 2 ) == -1 )
52         return false;
53       else
54         return true;
55     } else {
56       return false;
57     }
58   #else
59     if( access(folder_name.c_str(), F_OK ) == 0) {
60       if( access(folder_name.c_str(), W_OK ) == 0)
61         return true;
62       else
63         return false;
64     } else {
65       return false;
66     }
67   #endif
68 }
69 
activate_logger()70 void IOHprofiler_csv_logger::activate_logger() {
71   openIndex();
72 }
73 
openIndex()74 int IOHprofiler_csv_logger::openIndex() {
75   std::string experiment_folder_name = IOHprofiler_experiment_folder_name();
76   return IOHprofiler_create_folder(experiment_folder_name);
77 }
78 
IOHprofiler_create_folder(std::string folder_name)79 int IOHprofiler_csv_logger::IOHprofiler_create_folder(std::string folder_name) {
80 #if defined(_WIN32) || defined(_WIN64) || defined(__MINGW64__) || defined(__CYGWIN__)
81   if (mkdir(folder_name.c_str()) == 0) {
82 #else
83   if (mkdir(folder_name.c_str(),S_IRWXU) == 0) {
84 #endif
85     return 1;
86   } else {
87     IOH_error("Error on creating directory" + folder_name);
88     return 0;
89   }
90 }
91 
92 std::string IOHprofiler_csv_logger::IOHprofiler_experiment_folder_name() {
93   std::string renamed_directory = this->output_directory + IOHprofiler_path_separator + this->folder_name;
94   std::string temp_folder_name = this->folder_name;
95   int index = 0;
96   //while (fs::exists(renamed_directory.c_str())) {
97   while (folder_exist(renamed_directory) ) {
98     ++index;
99     temp_folder_name = this->folder_name  + '-' + _toString(index);
100     renamed_directory = this->output_directory + IOHprofiler_path_separator + temp_folder_name;
101   }
102   this->folder_name = temp_folder_name;
103   return renamed_directory;
104 }
105 
106 void IOHprofiler_csv_logger::write_header() {
107   std::string sub_directory_name = this->output_directory + IOHprofiler_path_separator
108                         + this->folder_name + IOHprofiler_path_separator
109                         + "data_f" + _toString(problem_id)
110                         + "_" + problem_name;
111 
112   std::string dat_header = "\"function evaluation\" \"current f(x)\" \"best-so-far f(x)\" \"current af(x)+b\"  \"best af(x)+b\"";
113   if(this->logging_parameters.size() != 0) {
114     for (std::map<std::string, std::shared_ptr<double> >::iterator iter = this->logging_parameters.begin(); iter != this->logging_parameters.end(); ++iter) {
115       dat_header = dat_header + " \"" + iter->first + "\"";
116     }
117   }
118 
119   // if (!fs::exists(sub_directory_name.c_str())) {
120   if (!folder_exist(sub_directory_name)) {
121     IOHprofiler_create_folder(sub_directory_name.c_str());
122   }
123 
124   if (complete_status()) {
125     std::string cdat_name = sub_directory_name + IOHprofiler_path_separator
126                           + "IOHprofiler_f" + _toString(problem_id) + "_DIM"
127                           + _toString(dimension) + ".cdat";
128 
129     if (this->cdat.is_open()) {
130       this->cdat.close();
131     }
132     this->cdat.open(cdat_name.c_str(),std::ofstream::out | std::ofstream::app);
133     //this->cdat << dat_header << '\n';
134     this->cdat_buffer = "";
135     this->write_in_buffer(dat_header+"\n",this->cdat_buffer,this->cdat);
136   }
137 
138   if (interval_status()) {
139     std::string idat_name = sub_directory_name + IOHprofiler_path_separator
140                           + "IOHprofiler_f" + _toString(problem_id) + "_DIM"
141                           + _toString(dimension) + ".idat";
142 
143     if (this->idat.is_open()) {
144       this->idat.close();
145     }
146     this->idat.open(idat_name.c_str(),std::ofstream::out | std::ofstream::app);
147     //this->idat << dat_header << '\n';
148     this->idat_buffer = "";
149     this->write_in_buffer(dat_header+"\n",this->idat_buffer,this->idat);
150   }
151 
152   if (update_status()) {
153     std::string dat_name = sub_directory_name + IOHprofiler_path_separator
154                             + "IOHprofiler_f" + _toString(problem_id) + "_DIM"
155                             + _toString(dimension) + ".dat";
156 
157     if (this->dat.is_open()) {
158       this->dat.close();
159     }
160     this->dat_buffer = "";
161     this->dat.open(dat_name.c_str(),std::ofstream::out | std::ofstream::app);
162     //this->dat << dat_header << '\n';
163     this->write_in_buffer(dat_header+"\n",this->dat_buffer,this->dat);
164   }
165 
166   if (time_points_status()) {
167     std::string tdat_name = sub_directory_name + IOHprofiler_path_separator
168                             + "IOHprofiler_f" + _toString(problem_id) + "_DIM"
169                             + _toString(dimension) + ".tdat";
170 
171     if (this->tdat.is_open()) {
172       this->tdat.close();
173     }
174     this->tdat_buffer = "";
175     this->tdat.open(tdat_name.c_str(),std::ofstream::out | std::ofstream::app);
176     //this->tdat << dat_header << '\n';
177      this->write_in_buffer(dat_header+"\n",this->tdat_buffer,this->tdat);
178   }
179 }
180 
181 void IOHprofiler_csv_logger::track_problem(const int problem_id, const int dimension, const int instance, const std::string problem_name, const IOH_optimization_type maximization_minimization_flag){
182   /// Handle info of the previous problem.
183   if (infoFile.is_open()) {
184     write_info(this->instance, this->best_y[0], this->best_transformed_y[0], this->optimal_evaluations,
185                                     this->last_y[0], this->last_transformed_y[0], this->last_evaluations);
186   }
187 
188   this->optimal_evaluations = 0;
189   this->last_evaluations = 0;
190 
191   /// TO DO: Update the method of initializing this value.
192 
193   if (maximization_minimization_flag == IOH_optimization_type::Maximization) {
194     this->best_y.clear();
195     this->best_y.push_back(-DBL_MAX);
196     this->best_transformed_y.clear();
197     this->best_transformed_y.push_back(-DBL_MAX);
198     this->last_y.clear();
199     this->last_y.push_back(-DBL_MAX);
200     this->last_transformed_y.clear();
201     this->last_transformed_y.push_back(-DBL_MAX);
202   } else {
203     this->best_y.clear();
204     this->best_y.push_back(DBL_MAX);
205     this->best_transformed_y.clear();
206     this->best_transformed_y.push_back(DBL_MAX);
207     this->last_y.clear();
208     this->last_y.push_back(DBL_MAX);
209     this->last_transformed_y.clear();
210     this->last_transformed_y.push_back(DBL_MAX);
211   }
212 
213   reset_observer(maximization_minimization_flag);
214 
215   this->problem_id = problem_id;
216   this->dimension = dimension;
217   this->instance = instance;
218   this->problem_name = problem_name;
219   this->maximization_minimization_flag = maximization_minimization_flag;
220 
221   openInfo(problem_id,dimension,problem_name);
222   header_flag = false;
223 }
224 
225 
226 void IOHprofiler_csv_logger::track_problem(const IOHprofiler_problem<int> & problem) {
227   // this->tracked_problem_int = nullptr;
228   // this->tracked_problem_double = nullptr;
229 
230   this->track_problem(
231     problem.IOHprofiler_get_problem_id(),
232     problem.IOHprofiler_get_number_of_variables(),
233     problem.IOHprofiler_get_instance_id(),
234     problem.IOHprofiler_get_problem_name(),
235     problem.IOHprofiler_get_optimization_type()
236   );
237 
238   // this->problem_type = problem.IOHprofiler_get_problem_type();
239   // this->tracked_problem_int = std::make_shared<IOHprofiler_problem<int> >(problem);
240 }
241 
242 void IOHprofiler_csv_logger::track_problem(const IOHprofiler_problem<double> & problem) {
243   // this->tracked_problem_int = nullptr;
244   // this->tracked_problem_double = nullptr;
245   this->track_problem(
246     problem.IOHprofiler_get_problem_id(),
247     problem.IOHprofiler_get_number_of_variables(),
248     problem.IOHprofiler_get_instance_id(),
249     problem.IOHprofiler_get_problem_name(),
250     problem.IOHprofiler_get_optimization_type()
251   );
252 
253   // this->problem_type = problem.IOHprofiler_get_problem_type();
254   // this->tracked_problem_double = std::make_shared<IOHprofiler_problem<double> >(problem);
255 }
256 
257 void IOHprofiler_csv_logger::track_suite(std::string suite_name){
258   this->suite_name = suite_name;
259 }
260 
261 void IOHprofiler_csv_logger::set_parameters(const std::vector<std::shared_ptr<double> > &parameters) {
262   if (this->logging_parameters.size() != 0) {
263     this->logging_parameters.clear();
264   }
265 
266   for (size_t i = 0; i != parameters.size(); i++) {
267     this->logging_parameters["parameter" + _toString(i+1)] = parameters[i];
268   }
269 }
270 
271 void IOHprofiler_csv_logger::set_parameters(const std::vector<std::shared_ptr<double> > &parameters, const std::vector<std::string> &parameters_name) {
272   if (parameters_name.size() != parameters.size()) {
273     IOH_error("Parameters and their names are given with different size.");
274   }
275   if (this->logging_parameters.size() != 0) {
276     this->logging_parameters.clear();
277   }
278   for (size_t i = 0; i != parameters.size(); i++) {
279     this->logging_parameters[parameters_name[i]] = parameters[i];
280   }
281 }
282 
283 
284 ///Only for python wrapper.
285 void IOHprofiler_csv_logger::set_parameters_name(const std::vector<std::string > &parameters_name) {
286   if (this->logging_parameters.size() != 0) {
287     this->logging_parameters.clear();
288   }
289   //default value set as -9999.
290   for (size_t i = 0; i != parameters_name.size(); i++) {
291     this->logging_parameters[parameters_name[i]] = std::make_shared<double>(-9999);
292   }
293 }
294 
295 ///Only for python wrapper.
296 void IOHprofiler_csv_logger::set_parameters_name(const std::vector<std::string > &parameters_name, const std::vector<double> &initial_parameters) {
297   if (parameters_name.size() != initial_parameters.size()) {
298     IOH_error("Parameters and their names are given with different size.");
299   }
300   //default value set as -9999.
301   for (size_t i = 0; i != parameters_name.size(); i++) {
302     this->logging_parameters[parameters_name[i]] = std::make_shared<double>(initial_parameters[i]);
303   }
304 }
305 
306 ///Only for python wrapper.
307 void IOHprofiler_csv_logger::set_parameters(const std::vector<std::string > &parameters_name, const std::vector<double> &parameters) {
308   if (parameters_name.size() != parameters.size()) {
309     IOH_error("Parameters and their names are given with different size.");
310   }
311   for (size_t i = 0; i != parameters_name.size(); ++i)
312   if(this->logging_parameters.find(parameters_name[i]) != this->logging_parameters.end()) {
313     *this->logging_parameters[parameters_name[i]] = parameters[i];
314   } else {
315     IOH_error("Parameter " + parameters_name[i] + " does not exist");
316   }
317 }
318 
319 void IOHprofiler_csv_logger::add_dynamic_attribute(const std::vector<std::shared_ptr<double> > &attributes) {
320   if (this->attr_per_run_name_value.size() != 0) {
321     this->attr_per_run_name_value.clear();
322   }
323 
324   for (size_t i = 0; i != attributes.size(); i++) {
325     this->attr_per_run_name_value["attr" + _toString(i+1)] = attributes[i];
326   }
327 }
328 
329 void IOHprofiler_csv_logger::add_dynamic_attribute(const std::vector<std::shared_ptr<double> > &attributes, const std::vector<std::string> &attributes_name) {
330   if (attributes_name.size() != attributes.size()) {
331     IOH_error("Attributes and their names are given with different size.");
332   }
333   if (this->attr_per_run_name_value.size() != 0) {
334     this->attr_per_run_name_value.clear();
335   }
336   for (size_t i = 0; i != attributes.size(); i++) {
337     this->attr_per_run_name_value[attributes_name[i]] = attributes[i];
338   }
339 }
340 
341 ///Only for python wrapper.
342 void IOHprofiler_csv_logger::set_dynamic_attributes_name(const std::vector<std::string > &attributes_name) {
343   if (this->attr_per_run_name_value.size() != 0) {
344     this->attr_per_run_name_value.clear();
345   }
346   //default value set as -9999.
347   for (size_t i = 0; i != attributes_name.size(); i++) {
348     this->attr_per_run_name_value[attributes_name[i]] = std::make_shared<double>(-9999);
349   }
350 }
351 
352 ///Only for python wrapper.
353 void IOHprofiler_csv_logger::set_dynamic_attributes_name(const std::vector<std::string > &attributes_name, const std::vector<double> &initial_attributes) {
354   if (attributes_name.size() != initial_attributes.size()) {
355     IOH_error("Attributes and their names are given with different size.");
356   }
357   //default value set as -9999.
358   for (size_t i = 0; i != attributes_name.size(); i++) {
359     this->attr_per_run_name_value[attributes_name[i]] = std::make_shared<double>(initial_attributes[i]);
360   }
361 }
362 
363 ///Only for python wrapper.
364 void IOHprofiler_csv_logger::set_dynamic_attributes(const std::vector<std::string > &attributes_name, const std::vector<double> &attributes) {
365   if (attributes_name.size() != attributes.size()) {
366     IOH_error("Attributes and their names are given with different size.");
367   }
368   for (size_t i = 0; i != attributes_name.size(); ++i)
369   if(this->attr_per_run_name_value.find(attributes_name[i]) != this->attr_per_run_name_value.end()) {
370     *this->attr_per_run_name_value[attributes_name[i]] = attributes[i];
371   } else {
372     IOH_error("Dynamic attributes " + attributes_name[i] + " does not exist");
373   }
374 }
375 
376 
377 void IOHprofiler_csv_logger::do_log(const std::vector<double> & log_info) {
378   this->write_line( (size_t)(log_info[0]),log_info[1],log_info[2],log_info[3],log_info[4]);
379 };
380 
381 void IOHprofiler_csv_logger::write_line(const std::vector<double> & log_info) {
382   this->write_line( (size_t)(log_info[0]),log_info[1],log_info[2],log_info[3],log_info[4]);
383 };
384 
385 /// \todo The precision of double values.
386 void IOHprofiler_csv_logger::write_line(const size_t evaluations, const double y, const double best_so_far_y,
387                  const double transformed_y, const double best_so_far_transformed_y) {
388   if (header_flag == false) {
389     this->write_header();
390     header_flag = true;
391   }
392 
393   this->last_evaluations = evaluations;
394   this->last_y[0] = y;
395   this->last_transformed_y[0] = transformed_y;
396 
397   bool cdat_flag = complete_trigger();
398   bool idat_flag = interval_trigger(evaluations);
399   bool dat_flag = update_trigger(transformed_y,maximization_minimization_flag);
400   bool tdat_flag = time_points_trigger(evaluations);
401 
402   bool need_write =  cdat_flag || idat_flag || dat_flag || tdat_flag;
403 
404   if (need_write) {
405     std::string written_line = _toString(evaluations) + " " + _toString(y) + " "
406                              + _toString(best_so_far_y) + " " + _toString(transformed_y) + " "
407                              + _toString(best_so_far_transformed_y);
408 
409     if (this->logging_parameters.size() != 0) {
410       for (std::map<std::string, std::shared_ptr<double> >::iterator iter = this->logging_parameters.begin(); iter != this->logging_parameters.end(); ++iter) {
411         written_line += " ";
412         written_line += _toString(*(iter->second));
413       }
414     }
415 
416     written_line += '\n';
417 
418     if (cdat_flag) {
419       if (!this->cdat.is_open()) {
420         IOH_error("*.cdat file is not open");
421       }
422       //this->cdat << written_line;
423       this->write_in_buffer(written_line,this->cdat_buffer,this->cdat);
424     }
425 
426     if (idat_flag) {
427       if (!this->idat.is_open()) {
428         IOH_error("*.idat file is not open");
429       }
430       //this->idat << written_line;
431       this->write_in_buffer(written_line,this->idat_buffer,this->idat);
432     }
433 
434     if (dat_flag) {
435       if (!this->dat.is_open()) {
436         IOH_error("*.dat file is not open");
437       }
438       //this->dat << written_line;
439       this->write_in_buffer(written_line,this->dat_buffer,this->dat);
440     }
441 
442     if (tdat_flag) {
443       if (!this->tdat.is_open()) {
444         IOH_error("*.tdat file is not open");
445       }
446       //this->tdat << written_line;
447       this->write_in_buffer(written_line,this->tdat_buffer,this->tdat);
448     }
449   }
450 
451   if (compareObjectives(transformed_y,this->best_transformed_y[0],this->maximization_minimization_flag)) {
452     this->update_logger_info(evaluations,y,transformed_y);
453   }
454 }
455 
456 void IOHprofiler_csv_logger::openInfo(int problem_id, int dimension, std::string problem_name) {
457   this->info_buffer = "";
458   std::string titleflag = "";
459   std::string optimization_type;
460   if (this->maximization_minimization_flag == IOH_optimization_type::Maximization) {
461     optimization_type = "T";
462   } else {
463     optimization_type = "F";
464   }
465 
466   if (problem_id != this->last_problem_id) {
467     this->infoFile.close();
468     std::string infoFile_name = this->output_directory + IOHprofiler_path_separator
469                           + this->folder_name + IOHprofiler_path_separator
470                           + "IOHprofiler_f" + _toString(problem_id)
471                           + "_" + problem_name
472                           + ".info";
473     // if (fs::exists(infoFile_name.c_str())) {
474     if (folder_exist(infoFile_name)) {
475       titleflag = "\n";
476     }
477     this->infoFile.open(infoFile_name.c_str(),std::ofstream::out | std::ofstream::app);
478     //this->infoFile << titleflag;
479     this->info_buffer += titleflag;
480     //this->infoFile << "suite = \"" << this->suite_name << "\", funcId = " <<  problem_id << ", funcName = \""<< problem_name << "\", DIM = "  << dimension << ", maximization = \"" << optimization_type << "\", algId = \"" << this->algorithm_name << "\", algInfo = \"" << this->algorithm_info << "\"";
481 	  this->info_buffer += ("suite = \"" + this->suite_name + "\", funcId = " + _toString(problem_id) + ", funcName = \"" + problem_name + "\", DIM = "  + _toString(dimension) + ", maximization = \"" + optimization_type + "\", algId = \"" + this->algorithm_name + "\", algInfo = \"" + this->algorithm_info + "\"");
482     if(this->attr_per_exp_name_value.size() != 0) {
483       for (std::map<std::string,std::string>::iterator iter = this->attr_per_exp_name_value.begin(); iter != this->attr_per_exp_name_value.end(); iter++) {
484 		    //this->infoFile << ", " << iter->first << " = \"" << iter->second << "\"";
485         this->info_buffer += (", " + iter->first + " = \"" + iter->second + "\"");
486       }
487 
488     }
489     if (this->attr_per_run_name_value.size() != 0) {
490       //this->infoFile << ", dynamicAttribute = \"";
491       this->info_buffer +=  ", dynamicAttribute = \"";
492       for (std::map<std::string,std::shared_ptr<double> >::iterator iter = this->attr_per_run_name_value.begin(); iter != this->attr_per_run_name_value.end();) {
493 		    //this->infoFile << "|" << iter->first;
494         this->info_buffer += (iter->first);
495         if (++iter != this->attr_per_run_name_value.end()) {
496           this->info_buffer += ("|");
497         }
498       }
499       //this->infoFile << "\"";
500       this->info_buffer += ("\"");
501     }
502     //this->infoFile << "\n%\n";
503     this->info_buffer += ("\n%\n");
504     //this->infoFile << "data_f" << problem_id << "_" << problem_name << "/IOHprofiler_f" << problem_id << "_DIM" << dimension << ".dat";
505     this->info_buffer += ("data_f" +  _toString(problem_id) + "_" + problem_name + "/IOHprofiler_f" + _toString(problem_id) + "_DIM" + _toString(dimension) + ".dat");
506     this->write_stream(this->info_buffer,this->infoFile);
507     this->info_buffer.clear();
508 
509     this->last_problem_id = problem_id;
510     this->last_dimension = dimension;
511   } else if (dimension != this->last_dimension) {
512     //this->infoFile << "\nsuite = \"" << this->suite_name << "\", funcId = " << problem_id << ", funcName = \""<< problem_name << "\", DIM = " << dimension << ", maximization = \"" << optimization_type << "\", algId = \"" << this->algorithm_name << "\", algInfo = \"" << this->algorithm_info << "\"";
513     this->info_buffer += ("\nsuite = \"" + this->suite_name + "\", funcId = " + _toString(problem_id) + ", funcName = \"" + problem_name + "\", DIM = " + _toString(dimension) + ", maximization = \"" + optimization_type + "\", algId = \"" + this->algorithm_name + "\", algInfo = \"" + this->algorithm_info + "\"");
514     if(this->attr_per_exp_name_value.size() != 0) {
515       for (std::map<std::string,std::string>::iterator iter = this->attr_per_exp_name_value.begin(); iter != this->attr_per_exp_name_value.end(); iter++) {
516 		    //this->infoFile << ", " << iter->first << " = \"" << iter->second << "\"";
517         this->info_buffer += (", " + iter->first + " = \"" + iter->second + "\"");
518       }
519     }
520 
521     if (this->attr_per_run_name_value.size() != 0) {
522       //this->infoFile << ", dynamicAttribute = \"";
523       this->info_buffer += (", dynamicAttribute = \"");
524       for (std::map<std::string,std::shared_ptr<double> >::iterator iter = this->attr_per_run_name_value.begin(); iter != this->attr_per_run_name_value.end();) {
525 		    //this->infoFile << "|" << iter->first;
526         this->info_buffer += (iter->first);
527         if (++iter != this->attr_per_run_name_value.end()) {
528           this->info_buffer += ("|");
529         }
530       }
531       //this->infoFile << "\"";
532       this->info_buffer += "\"";
533     }
534     //this->infoFile << "\n%\n";
535     this->info_buffer += "\n%\n";
536     //this->infoFile << "data_f" << problem_id << "_" << problem_name << "/IOHprofiler_f" << problem_id << "_DIM" << dimension << ".dat";
537     this->info_buffer += ("data_f" + _toString(problem_id) + "_" + problem_name + "/IOHprofiler_f" + _toString(problem_id) + "_DIM" + _toString(dimension) + ".dat");
538     this->write_stream(this->info_buffer,this->infoFile);
539     this->info_buffer.clear();
540 
541     this->last_problem_id = problem_id;
542     this->last_dimension = dimension;
543   }
544 }
545 
546 void IOHprofiler_csv_logger::write_info(int instance, double best_y, double best_transformed_y, int evaluations,
547                                         double last_y, double last_transformed_y, int last_evaluations) {
548   if (!infoFile.is_open()) {
549     IOH_error("write_info(): writing info into unopened infoFile");
550   }
551 
552   this->info_buffer = "";
553   //infoFile << ", " << instance << ":" << evaluations << "|" << best_y;
554   this->info_buffer += (", " + _toString(instance) + ":" + _toString(evaluations) + "|" + _toString(best_y));
555   if(this->attr_per_run_name_value.size() != 0) {
556     this->info_buffer += (";");
557     for (std::map<std::string,std::shared_ptr<double> >::iterator iter = this->attr_per_run_name_value.begin(); iter != this->attr_per_run_name_value.end(); ) {
558       //this->infoFile << "|" << *(iter->second);
559       this->info_buffer += (_toString(*(iter->second)));
560       if (++iter != this->attr_per_run_name_value.end()) {
561         this->info_buffer += ("|");
562       }
563     }
564   }
565   this->write_stream(this->info_buffer,this->infoFile);
566   this->info_buffer.clear();
567 
568   bool need_write = (evaluations != last_evaluations);
569   if (need_write) {
570     std::string written_line = _toString(last_evaluations) + " " + _toString(last_y) + " "
571                               + _toString(best_y) + " " + _toString(last_transformed_y) + " "
572                               + _toString(best_transformed_y);
573 
574     if (this->logging_parameters.size() != 0) {
575       for (std::map<std::string, std::shared_ptr<double> >::iterator iter = this->logging_parameters.begin(); iter != this->logging_parameters.end(); ++iter) {
576         written_line += " ";
577         written_line += _toString(*(iter->second));
578       }
579     }
580 
581     written_line += '\n';
582     if (this->cdat.is_open()) {
583       //this->cdat << written_line;
584       this->write_in_buffer(written_line,this->cdat_buffer,this->cdat);
585       this->write_stream(this->cdat_buffer,this->cdat);
586       this->cdat.flush();
587       this->cdat_buffer.clear();
588     }
589     if (this->idat.is_open()) {
590       //this->idat << written_line;
591       this->write_in_buffer(written_line,this->idat_buffer,this->idat);
592       this->write_stream(this->idat_buffer,this->idat);
593       this->idat.flush();
594       this->idat_buffer.clear();
595     }
596     if (this->dat.is_open()) {
597       //this->dat << written_line;
598       this->write_in_buffer(written_line,this->dat_buffer,this->dat);
599       this->write_stream(this->dat_buffer,this->dat);
600       this->dat.flush();
601       this->dat_buffer.clear();
602     }
603     if (this->tdat.is_open()) {
604       //this->tdat << written_line;
605       this->write_in_buffer(written_line,this->tdat_buffer,this->tdat);
606       this->write_stream(this->tdat_buffer,this->tdat);
607       this->tdat.flush();
608       this->tdat_buffer.clear();
609     }
610   }
611 
612   if (this->cdat.is_open()) {
613       this->write_stream(this->cdat_buffer,this->cdat);
614       this->cdat.flush();
615       this->cdat_buffer.clear();
616   }
617   if (this->idat.is_open()) {
618     this->write_stream(this->idat_buffer,this->idat);
619     this->idat.flush();
620     this->idat_buffer.clear();
621   }
622   if (this->dat.is_open()) {
623     this->write_stream(this->dat_buffer,this->dat);
624     this->dat.flush();
625     this->dat_buffer.clear();
626   }
627   if (this->tdat.is_open()) {
628     this->write_stream(this->tdat_buffer,this->tdat);
629     this->tdat.flush();
630     this->tdat_buffer.clear();
631   }
632 }
633 
634 /// \fn void IOHprofiler_csv_logger::write_in_buffer(const std::string add_string, std::string & buffer_string, std::fstream & dat_stream)
635 /// This functions is to add add_string to the buffer_string. If the length buffer string exceeds the limit, the bufferr_string will be
636 /// written through dat_stream.
637 void IOHprofiler_csv_logger::write_stream(const std::string buffer_string, std::fstream & dat_stream) {
638   dat_stream.write(buffer_string.c_str(),sizeof(char)*buffer_string.size());
639   //dat_stream << buffer_string;
640 }
641 
642 
643 /// \fn void IOHprofiler_csv_logger::write_in_buffer(const std::string add_string, std::string & buffer_string, std::fstream & dat_stream)
644 /// This functions is to add add_string to the buffer_string. If the length buffer string exceeds the limit, the bufferr_string will be
645 /// written through dat_stream.
646 void IOHprofiler_csv_logger::write_in_buffer(const std::string add_string, std::string & buffer_string, std::fstream & dat_stream) {
647   if (buffer_string.size() + add_string.size() < MAX_BUFFER_SIZE) {
648     buffer_string = buffer_string + add_string;
649   } else {
650     write_stream(buffer_string,dat_stream);
651     buffer_string.clear();
652     buffer_string = add_string;
653   }
654 }
655 
656 /// \fn void IOHprofiler_csv_logger::update_logger_info(size_t optimal_evaluations, std::vector<double> found_optimal)
657 /// This functions is to update infomation to be used in *.info files.
658 void IOHprofiler_csv_logger::update_logger_info(size_t optimal_evaluations, double y, double transformed_y) {
659   this->optimal_evaluations = optimal_evaluations;
660   this->best_y[0] =  y;
661   this->best_transformed_y[0] = transformed_y;
662 }
663 
664 
665 void IOHprofiler_csv_logger::add_attribute(std::string name, double value) {
666   this->attr_per_exp_name_value[name] = _toString(value);
667 }
668 
669 void IOHprofiler_csv_logger::add_attribute(std::string name, int value) {
670   this->attr_per_exp_name_value[name] = _toString(value);
671 }
672 
673 void IOHprofiler_csv_logger::add_attribute(std::string name, float value) {
674   this->attr_per_exp_name_value[name] = _toString(value);
675 }
676 
677 void IOHprofiler_csv_logger::add_attribute(std::string name, std::string value) {
678   this->attr_per_exp_name_value[name] = value;
679 }
680 
681 void IOHprofiler_csv_logger::delete_attribute(std::string name) {
682   this->attr_per_exp_name_value.erase(name);
683 }
684 
685 void IOHprofiler_csv_logger::clear_logger() {
686   if (infoFile.is_open()) {
687     write_info(this->instance, this->best_y[0], this->best_transformed_y[0], this->optimal_evaluations,
688               this->last_y[0], this->last_transformed_y[0], this->last_evaluations);
689     infoFile.close();
690   }
691 
692   /// Close .dat files after .info file to record evaluations of the last iteration.
693   if (cdat.is_open()) {
694     cdat.close();
695   }
696   if (idat.is_open()) {
697     idat.close();
698   }
699   if (dat.is_open()) {
700     dat.close();
701   }
702   if (tdat.is_open()) {
703     tdat.close();
704   }
705 
706   // if(this->tracked_problem_double != nullptr) {
707   //   this->tracked_problem_double = nullptr;
708   // }
709 
710   // if(this->tracked_problem_int != nullptr) {
711   //   this->tracked_problem_int = nullptr;
712   // }
713 }
714 
715