<commit_before>#include <stdio.h>
#include <assert.h>
#include <limits.h>
#include <float.h>
#include <math.h>

#include "coco.h"

#include "coco_utilities.c"
#include "coco_problem.c"
#include "coco_strdup.c"

static const size_t nbpts_nbevals = 20;
static const size_t nbpts_fval = 5;

/*TODO: add possibility of adding a prefix to the index files*/

typedef struct {
    char *path;/*relative path to the data folder. Simply the Algname*/
    const char *alg_name;/*the alg name, for now, remporarly the same as the path*/
    char *current_data_file;/*relative path, starting from self.path, to the .dat of the current run. Needed by the .info*/
    FILE *index_file;/*index file*/
    FILE *fdata_file;/*function value aligned data file*/
    FILE *tdata_file;/*number of function evaluations aligned data file*/
    FILE *rdata_file;/*restart info data file*/
    double f_trigger; /* next upper bound on the fvalue to trigger a log in the .dat file*/
    long t_trigger; /* next lower bound on nb fun evals to trigger a log in the .tdat file*/
    long idx_f_trigger; /* allows to track the index i in logging target = {10**(i/nbpts_fval), i \in Z} */
    long idx_t_trigger; /* allows to track the index i in logging nbevals  = {int(10**(i/nbpts_nbevals)), i \in Z} */
    long idx_tdim_trigger; /* allows to track the index i in logging nbevals  = {dim * 10**i, i \in Z} */
    long number_of_evaluations;
    double best_fvalue;
    double last_fvalue;
    short written_last_eval; /*allows writing the the data of the final fun eval in the .tdat file if not already written by the t_trigger*/
    double *best_solution;
    /*the following are to only pass data as a parameter in the free function. The interface should probably be the same for all free functions so passing the problem as a second parameter is not an option even though we need info form it.*/
    int function_id;
    int instance_id;
    long number_of_variables;
    double optimal_fvalue;
} _bbob2009_logger_t;

static const char* _file_header_str = 
    "%% function evaluation |"
    "noise-free fitness - Fopt (%13.12e) |"
    "best noise-free fitness - Fopt |"
    "measured fitness |"
    "best measured fitness |"
    "x1 |"
    "x2...\n";

static void _bbob2009_logger_update_f_trigger(_bbob2009_logger_t *data, double fvalue) {
    /* "jump" directly to the next closest (but larger) target to the
     * current fvalue from the initial target
     */
    if (data->idx_f_trigger == INT_MAX)
        data->idx_f_trigger = ceil(log10(fvalue)) * nbpts_fval;
    else
        data->idx_f_trigger--;
    
    data->f_trigger = pow(10, data->idx_f_trigger * 1.0 / nbpts_fval);
    while (fvalue <= data->f_trigger) {
        data->idx_f_trigger--;
        data->f_trigger = pow(10, data->idx_f_trigger * 1.0 / nbpts_fval);
    }
}

static void _bbob2009_logger_update_t_trigger(_bbob2009_logger_t *data, 
                                              long number_of_variables) {
    while (data->number_of_evaluations >= floor(pow(10, (double)data->idx_t_trigger / (double) nbpts_nbevals)))
        data->idx_t_trigger++;
    
    while (data->number_of_evaluations >= number_of_variables * pow(10, (double) data->idx_tdim_trigger))
        data->idx_tdim_trigger++;

    data->t_trigger = fmin(floor(pow(10, (double)data->idx_t_trigger / (double)nbpts_nbevals)), number_of_variables * pow(10, (double) data->idx_tdim_trigger));
}

/**
 * adds a formated line to a data file
 */
static void _bbob2009_logger_write_data(FILE * target_file, 
                                        long number_of_evaluations, 
                                        double fvalue, 
                                        double best_fvalue, 
                                        double best_value, 
                                        double *x, 
                                        size_t number_of_variables) {
    /* for some reason, it's %.0f in the old code instead of the 10.9e
     * in the documentation
     */
    fprintf(target_file, "%ld %+10.9e %+10.9e %+10.9e %+10.9e", 
            number_of_evaluations, fvalue - best_value, 
            best_fvalue - best_value, fvalue, best_fvalue);
    if (number_of_variables < 22) {
        size_t i;
        for (i = 0; i < number_of_variables; i++) {
            fprintf(target_file, " %+5.4e", x[i]);
        }
    }
    fprintf(target_file, "\n");
}


/**
 * Error when trying to create the file "path"
 */
static void _bbob2009_logger_error_io(FILE *path) {
    char *buf;
    const char *error_format =
        "bbob2009_logger_prepare() failed to open log file '%s'.";
    size_t buffer_size = snprintf(NULL, 0, error_format, path);
    buf = (char *) coco_allocate_memory(buffer_size);
    snprintf(buf, buffer_size, error_format, path);
    coco_error(buf);
    coco_free_memory(buf);
}

/**
 * Creates the the file fileName_prefix+problem_id+file_extension in folde_path
 */
static void _bbob2009_logger_createFile(FILE ** target_file, 
                                        const char* folder_path, 
                                        const char* problem_id,
                                        const char* fileName_prefix, 
                                        const char* file_extension) {
    char file_name[NUMBBO_PATH_MAX];
    char file_path[NUMBBO_PATH_MAX] = {0};
    /*file name */
    strncpy(file_name, fileName_prefix, NUMBBO_PATH_MAX);
    strncat(file_name, problem_id, NUMBBO_PATH_MAX - strlen(file_name) - 1);
    strncat(file_name, file_extension, NUMBBO_PATH_MAX - strlen(file_name) - 1);
    coco_join_path(file_path, sizeof(file_path), folder_path, file_name, NULL);
    /*TODO: use the correct folder name (no dimension) once we can get
     * function type (sphere/F1...)
     */
    if (*target_file == NULL) {
        *target_file = fopen(file_path, "a+");
        if (target_file == NULL) {
            _bbob2009_logger_error_io(*target_file);
        }
    }
}

/**
 * Generates the different files and folder needed by the logger to store the data
 */
static void _bbob2009_logger_initialize(_bbob2009_logger_t *data, 
                                        coco_problem_t *inner_problem) {
    /*
      Creates/opens the data and index files
    */
    char folder_name[NUMBBO_PATH_MAX];
    char folder_path[NUMBBO_PATH_MAX]={0};
    char tmp_fun_id[2];/*servs to extract the function id a a char *. There should be a better way of doing this */
    assert(data != NULL);
    assert(inner_problem->problem_id != NULL);
    /*generate folder name and path for current function*/
    strncpy(folder_name,"data_f", NUMBBO_PATH_MAX);
    strncpy(tmp_fun_id,&(inner_problem->problem_id[10]), 2);
    strncat(folder_name, tmp_fun_id,//inner_problem->problem_id,
            NUMBBO_PATH_MAX - strlen(folder_name) - 1);
    coco_join_path(folder_path, sizeof(folder_path), data->path, folder_name, NULL);
    coco_create_path(folder_path);
    
    /* TODO: put the correct file path */
    data->current_data_file = coco_strdup(folder_path);
    _bbob2009_logger_createFile(&(data->index_file), data->path, 
                                inner_problem->problem_id, "bbobexp_", ".info");
    _bbob2009_logger_createFile(&(data->fdata_file), folder_path, 
                                inner_problem->problem_id, "bbobexp_", ".dat");
    fprintf(data->fdata_file,_file_header_str,*(inner_problem->best_value));

    _bbob2009_logger_createFile(&(data->tdata_file), folder_path, 
                                inner_problem->problem_id, "bbobexp_", ".tdat");<commit_msg>bbob2009_logger.c: small typo in comment<commit_after>#include <stdio.h>
#include <assert.h>
#include <limits.h>
#include <float.h>
#include <math.h>

#include "coco.h"

#include "coco_utilities.c"
#include "coco_problem.c"
#include "coco_strdup.c"

static const size_t nbpts_nbevals = 20;
static const size_t nbpts_fval = 5;

/*TODO: add possibility of adding a prefix to the index files*/

typedef struct {
    char *path;/*relative path to the data folder. Simply the Algname*/
    const char *alg_name;/*the alg name, for now, remporarly the same as the path*/
    char *current_data_file;/*relative path, starting from self.path, to the .dat of the current run. Needed by the .info*/
    FILE *index_file;/*index file*/
    FILE *fdata_file;/*function value aligned data file*/
    FILE *tdata_file;/*number of function evaluations aligned data file*/
    FILE *rdata_file;/*restart info data file*/
    double f_trigger; /* next upper bound on the fvalue to trigger a log in the .dat file*/
    long t_trigger; /* next lower bound on nb fun evals to trigger a log in the .tdat file*/
    long idx_f_trigger; /* allows to track the index i in logging target = {10**(i/nbpts_fval), i \in Z} */
    long idx_t_trigger; /* allows to track the index i in logging nbevals  = {int(10**(i/nbpts_nbevals)), i \in Z} */
    long idx_tdim_trigger; /* allows to track the index i in logging nbevals  = {dim * 10**i, i \in Z} */
    long number_of_evaluations;
    double best_fvalue;
    double last_fvalue;
    short written_last_eval; /*allows writing the the data of the final fun eval in the .tdat file if not already written by the t_trigger*/
    double *best_solution;
    /*the following are to only pass data as a parameter in the free function. The interface should probably be the same for all free functions so passing the problem as a second parameter is not an option even though we need info form it.*/
    int function_id;
    int instance_id;
    long number_of_variables;
    double optimal_fvalue;
} _bbob2009_logger_t;

static const char* _file_header_str = 
    "%% function evaluation |"
    "noise-free fitness - Fopt (%13.12e) |"
    "best noise-free fitness - Fopt |"
    "measured fitness |"
    "best measured fitness |"
    "x1 |"
    "x2...\n";

static void _bbob2009_logger_update_f_trigger(_bbob2009_logger_t *data, double fvalue) {
    /* "jump" directly to the next closest (but larger) target to the
     * current fvalue from the initial target
     */
    if (data->idx_f_trigger == INT_MAX)
        data->idx_f_trigger = ceil(log10(fvalue)) * nbpts_fval;
    else
        data->idx_f_trigger--;
    
    data->f_trigger = pow(10, data->idx_f_trigger * 1.0 / nbpts_fval);
    while (fvalue <= data->f_trigger) {
        data->idx_f_trigger--;
        data->f_trigger = pow(10, data->idx_f_trigger * 1.0 / nbpts_fval);
    }
}

static void _bbob2009_logger_update_t_trigger(_bbob2009_logger_t *data, 
                                              long number_of_variables) {
    while (data->number_of_evaluations >= floor(pow(10, (double)data->idx_t_trigger / (double) nbpts_nbevals)))
        data->idx_t_trigger++;
    
    while (data->number_of_evaluations >= number_of_variables * pow(10, (double) data->idx_tdim_trigger))
        data->idx_tdim_trigger++;

    data->t_trigger = fmin(floor(pow(10, (double)data->idx_t_trigger / (double)nbpts_nbevals)), number_of_variables * pow(10, (double) data->idx_tdim_trigger));
}

/**
 * adds a formated line to a data file
 */
static void _bbob2009_logger_write_data(FILE * target_file, 
                                        long number_of_evaluations, 
                                        double fvalue, 
                                        double best_fvalue, 
                                        double best_value, 
                                        double *x, 
                                        size_t number_of_variables) {
    /* for some reason, it's %.0f in the old code instead of the 10.9e
     * in the documentation
     */
    fprintf(target_file, "%ld %+10.9e %+10.9e %+10.9e %+10.9e", 
            number_of_evaluations, fvalue - best_value, 
            best_fvalue - best_value, fvalue, best_fvalue);
    if (number_of_variables < 22) {
        size_t i;
        for (i = 0; i < number_of_variables; i++) {
            fprintf(target_file, " %+5.4e", x[i]);
        }
    }
    fprintf(target_file, "\n");
}


/**
 * Error when trying to create the file "path"
 */
static void _bbob2009_logger_error_io(FILE *path) {
    char *buf;
    const char *error_format =
        "bbob2009_logger_prepare() failed to open log file '%s'.";
    size_t buffer_size = snprintf(NULL, 0, error_format, path);
    buf = (char *) coco_allocate_memory(buffer_size);
    snprintf(buf, buffer_size, error_format, path);
    coco_error(buf);
    coco_free_memory(buf);
}

/**
 * Creates the the file fileName_prefix+problem_id+file_extension in folde_path
 */
static void _bbob2009_logger_createFile(FILE ** target_file, 
                                        const char* folder_path, 
                                        const char* problem_id,
                                        const char* fileName_prefix, 
                                        const char* file_extension) {
    char file_name[NUMBBO_PATH_MAX];
    char file_path[NUMBBO_PATH_MAX] = {0};
    /*file name */
    strncpy(file_name, fileName_prefix, NUMBBO_PATH_MAX);
    strncat(file_name, problem_id, NUMBBO_PATH_MAX - strlen(file_name) - 1);
    strncat(file_name, file_extension, NUMBBO_PATH_MAX - strlen(file_name) - 1);
    coco_join_path(file_path, sizeof(file_path), folder_path, file_name, NULL);
    /*TODO: use the correct folder name (no dimension) once we can get
     * function type (sphere/F1...)
     */
    if (*target_file == NULL) {
        *target_file = fopen(file_path, "a+");
        if (target_file == NULL) {
            _bbob2009_logger_error_io(*target_file);
        }
    }
}

/**
 * Generates the different files and folder needed by the logger to store the data
 */
static void _bbob2009_logger_initialize(_bbob2009_logger_t *data, 
                                        coco_problem_t *inner_problem) {
    /*
      Creates/opens the data and index files
    */
    char folder_name[NUMBBO_PATH_MAX];
    char folder_path[NUMBBO_PATH_MAX]={0};
    char tmp_fun_id[2];/*servs to extract the function id as a char *. There should be a better way of doing this! */
    assert(data != NULL);
    assert(inner_problem->problem_id != NULL);
    /*generate folder name and path for current function*/
    strncpy(folder_name,"data_f", NUMBBO_PATH_MAX);
    strncpy(tmp_fun_id,&(inner_problem->problem_id[10]), 2);
    strncat(folder_name, tmp_fun_id,//inner_problem->problem_id,
            NUMBBO_PATH_MAX - strlen(folder_name) - 1);
    coco_join_path(folder_path, sizeof(folder_path), data->path, folder_name, NULL);
    coco_create_path(folder_path);
    
    /* TODO: put the correct file path */
    data->current_data_file = coco_strdup(folder_path);
    _bbob2009_logger_createFile(&(data->index_file), data->path, 
                                inner_problem->problem_id, "bbobexp_", ".info");
    _bbob2009_logger_createFile(&(data->fdata_file), folder_path, 
                                inner_problem->problem_id, "bbobexp_", ".dat");
    fprintf(data->fdata_file,_file_header_str,*(inner_problem->best_value));

    _bbob2009_logger_createFile(&(data->tdata_file), folder_path, 
                                inner_problem->problem_id, "bbobexp_", ".tdat");
{'fraction_non_alphanumeric': 0.10480089810473486, 'fraction_numerical': 0.01677342666578617, 'mean_word_length': 2.6562047320135203, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 81, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 28, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4081627', 'n_tokens_mistral': 5001, 'n_tokens_neox': 4731, 'n_words': 1285}