<commit_before>/**
 *  \file
 *  \remark This file is part of VITA.
 *
 *  \copyright Copyright (C) 2011-2018 <NAME>.
 *
 *  \license
 *  This Source Code Form is subject to the terms of the Mozilla Public
 *  License, v. 2.0. If a copy of the MPL was not distributed with this file,
 *  You can obtain one at http://mozilla.org/MPL/2.0/
 */

#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>

#include <boost/program_options.hpp>

#include "kernel/environment.h"
#include "kernel/log.h"
#include "kernel/src/evaluator.h"
#include "kernel/src/problem.h"
#include "kernel/src/primitive/factory.h"
#include "kernel/src/search.h"

#include "command_line_interpreter.h"

namespace po = boost::program_options;

namespace
{
const std::string vita_sr_version1(
  "Vita - Symbolic Regression and classification"
  );
const std::string vita_sr_version2(
  "Copyright 2011-2017 <NAME> (http://eosdev.it/)"
  );
const std::string vita_sr_defs(
#if defined(CLONE_SCALING)
  "(clone scaling enabled)"
#else
  ""
#endif
  );
}

///
/// Fixes conflicting parameters.
///
void fix_parameters(vita::src_problem *problem)
{
  using vita::log;
  using vita::trilean;
  using vita::fitness_t;
  using vita::with_size;

  vita::environment &env(problem->env);

  if (env.mep.code_length && env.mep.code_length <= problem->categories())
  {
    const decltype(env.mep.code_length) new_length(2 * problem->categories());
    vitaWARNING << "Adjusting code length (" << env.mep.code_length
                << " => " << new_length << ')';
    env.mep.code_length = new_length;
  }

  if (env.dss.value_or(0) > 0 && problem->data()->size() <= 30)
  {
    vitaWARNING << "Adjusting DSS (=> disabled)";
    env.dss = 0;
  }

  if (env.tournament_size)
  {
    if (env.tournament_size < 2)
    {
      vitaWARNING << "Adjusting tournament size (=> 2)";
      env.tournament_size = 2;
    }

    if (env.mate_zone && env.tournament_size > env.mate_zone)
    {
      vitaWARNING << "Adjusting tournament size ("
                  << env.tournament_size << " => " << env.mate_zone << ')';
      env.tournament_size = env.mate_zone;
    }

    if (env.individuals && env.tournament_size > env.individuals)
    {
      vitaWARNING << "Adjusting tournament size ("
                  << env.tournament_size << " => " << env.individuals  << ')';
      env.tournament_size = env.individuals;
    }
  }

  if (!env.threshold.fitness.size() && env.threshold.accuracy < 0.0)
  {
    if (problem->classification())
    {
      env.threshold.fitness = fitness_t(with_size(1));
      env.threshold.accuracy = 0.99;

      vitaINFO << "Accuracy threshold set to " << env.threshold.accuracy;
    }
    else  // symbolic regression
    {
      env.threshold.fitness = {-0.0001};

      vitaINFO << "Fitness threshold set to " << env.threshold.fitness;
    }
  }
}

///
/// \param[in] s a value to be interpreted as boolean
/// \return      `true` if `s` is not zero and not `"false"`
///
bool is_true(const std::string &s)
{
  return s != "0" && !vita::iequals(s, "false");
}

///
/// Contains the text-based command line interface.
///
/// The interface is not intented to be human friendly (no code completion,
/// command history, submenu...). We just want a light interface for the
/// Python GUI and a simple way of debugging.
///
namespace ui
{
using vita::log;

const std::string header(
  "(==(     )==)\n"
  " `-.`. ,',-' \n"
  "    _,-'       " + vita_sr_version1 + "\n" \
  " ,-',' `.`-.   " + vita_sr_version2 + "\n" \
  "(==(     )==)\n"
  " `-.`. ,',-'   " + vita_sr_defs + "\n"     \
  "    _,-'\"   \n"
  " ,-',' `.`-. \n"
  "(==(     )==)\n");

po::options_description cmdl_opt(
  "sr [options] [data set]\n\nAllowed options");

/// Number of runs to be tried.
unsigned runs(1);

// Active evaluator.
vita::evaluator_id eva(vita::evaluator_id::undefined);
std::string eva_args;

/// Reference problem (the problem we will work on).
vita::src_problem *problem;

///
/// Sets Adaptive Representation through Learning.
///
/// \param[in] v a value for ARL (\see is_true)
///
void arl(const std::string &v)
{
  assign(problem->env.arl, is_true(v));

  vitaINFO << "Adaptive Representation through Learning is "
           << problem->env.arl;
}

///
/// Sets the brood size for recombination.
///
/// \param[in] size brood size for recombination (0 to disable)
///
void brood(unsigned size)
{
  problem->env.brood_recombination = size;

  vitaINFO << "Brood size for recombination set to " << size;
}

///
/// Sets the code/genome length of an individual.
///
/// \param[in] length code/genome length of an individual
///
void code_length(unsigned length)
{
  Expects(length);

  problem->env.mep.code_length = length;

  vitaINFO << "Code length set to " << length;
}

///
/// Sets the overall probability that crossover will occour between winners
/// in a tournament.
///
/// \param[in] r range is `[0,1]`
///
void crossover_rate(double r)
{
  if (r < 0.0)
  {
    r = 0.0;
    vitaWARNING << "Adjusting crossover probability (" << r << " => 0.0)";
  }
  else if (r > 1.0)
  {
    r = 1.0;
    vitaWARNING << "Adjusting crossover probability (" << r << " => 1.0)";
  }

  problem->env.p_cross = r;

  vitaINFO << "Crossover rate set to " << r;
}

///
/// \param[in] data_file guess what? This is the data file to be parsed
/// \return              `true` if data have been correctly read and parsed
///
bool data(const std::string &data_file)
{
  vitaINFO << "Reading data file " << data_file << "...";

  std::size_t parsed(0);
  try
  {
    parsed = problem->load(data_file).first;
  }
  catch(...)
  {
    parsed = 0;
  }

  if (parsed)
    vitaINFO << "Dataset read. Examples: " << parsed
             << ", categories: " << problem->categories()
             << ", features: " << problem->variables()
             << ", classes: " << problem->classes();
  else
    vitaERROR << "Dataset file format error";

  return parsed;
}

///
/// Turn on/off the Dynamic Subset Selection algorithm.
///
/// \param[in] s a value for DSS
///
void dss(const std::string &s)
{
  problem->env.dss = decltype(problem->env.dss){s};

  if (problem->env.dss.has_value())
    vitaINFO << "Dynamic Subset Selection is " << *problem->env.dss;
  else
    vitaINFO << "Auto-tuning the parameter";
}

///
/// Sets the elitism tendency.
///
/// \param[in] v a value for elitism
///
void elitism(const std::string &v)
{
  assign(problem->env.elitism, is_true(v));

  vitaINFO << "Elitism is " << problem->env.elitism;
}

///
/// Shows the environment.
///
void environment(bool)
{
  vitaINFO << "NOT IMPLEMENTED";
}

///
/// param[in] v the chosen evaluator
///
/// \note
/// The evaluator should fit the current problem kind (symbolic regression,
/// classification) or it won't be used.
///
void evaluator(const std::string &v)
{
  const auto sep(v.find(':'));
  const std::string keyword(v.substr(0, sep));

  eva_args = "";
  if (sep != std::string::npos && sep + 1 < v.size())
    eva_args = v.substr(sep + 1);

  bool ok(true);
  if (keyword == "count")
    eva = vita::evaluator_id::count;
  else if (keyword == "mae")
    eva = vita::evaluator_id::mae;
  else if (keyword == "rmae")
    eva = vita::evaluator_id::rmae;
  else if (keyword == "mse")
    eva = vita::evaluator_id::mse;
  else if (keyword == "binary")
    eva = vita::evaluator_id::bin;
  else if (keyword == "dynslot")
    eva = vita::evaluator_id::dyn_slot;
  else if (keyword == "gaussian")
    eva = vita::evaluator_id::gaussian;
  else
    ok = false;

  if (ok)
  {
    vitaINFO << "Evaluator is " << keyword;
    if (!eva_args.empty())
    {
      vitaINFO << " (parameters: " << eva_args << ')';
    }
  }
  else
    vitaERROR << "Wrong argument for evaluator command";
}

///
/// Quit program.
///
void exit(bool)
{
  vitaOUTPUT << "Bye";
}

///
/// Sets the maximum number of generations in a run.
///
/// \param[in] g maximum number of generations in a run
///
void generations(unsigned g)
{
  problem->env.generations = g;

  vitaERROR << "Generations set to " << g;
}

///
/// Starts the search.
///
void go(bool = true)<commit_msg>[FIX] Wrong warning level for diagnostic message in SR<commit_after>/**
 *  \file
 *  \remark This file is part of VITA.
 *
 *  \copyright Copyright (C) 2011-2018 <NAME>.
 *
 *  \license
 *  This Source Code Form is subject to the terms of the Mozilla Public
 *  License, v. 2.0. If a copy of the MPL was not distributed with this file,
 *  You can obtain one at http://mozilla.org/MPL/2.0/
 */

#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>

#include <boost/program_options.hpp>

#include "kernel/environment.h"
#include "kernel/log.h"
#include "kernel/src/evaluator.h"
#include "kernel/src/problem.h"
#include "kernel/src/primitive/factory.h"
#include "kernel/src/search.h"

#include "command_line_interpreter.h"

namespace po = boost::program_options;

namespace
{
const std::string vita_sr_version1(
  "Vita - Symbolic Regression and classification"
  );
const std::string vita_sr_version2(
  "Copyright 2011-2017 <NAME> (http://eosdev.it/)"
  );
const std::string vita_sr_defs(
#if defined(CLONE_SCALING)
  "(clone scaling enabled)"
#else
  ""
#endif
  );
}

///
/// Fixes conflicting parameters.
///
void fix_parameters(vita::src_problem *problem)
{
  using vita::log;
  using vita::trilean;
  using vita::fitness_t;
  using vita::with_size;

  vita::environment &env(problem->env);

  if (env.mep.code_length && env.mep.code_length <= problem->categories())
  {
    const decltype(env.mep.code_length) new_length(2 * problem->categories());
    vitaWARNING << "Adjusting code length (" << env.mep.code_length
                << " => " << new_length << ')';
    env.mep.code_length = new_length;
  }

  if (env.dss.value_or(0) > 0 && problem->data()->size() <= 30)
  {
    vitaWARNING << "Adjusting DSS (=> disabled)";
    env.dss = 0;
  }

  if (env.tournament_size)
  {
    if (env.tournament_size < 2)
    {
      vitaWARNING << "Adjusting tournament size (=> 2)";
      env.tournament_size = 2;
    }

    if (env.mate_zone && env.tournament_size > env.mate_zone)
    {
      vitaWARNING << "Adjusting tournament size ("
                  << env.tournament_size << " => " << env.mate_zone << ')';
      env.tournament_size = env.mate_zone;
    }

    if (env.individuals && env.tournament_size > env.individuals)
    {
      vitaWARNING << "Adjusting tournament size ("
                  << env.tournament_size << " => " << env.individuals  << ')';
      env.tournament_size = env.individuals;
    }
  }

  if (!env.threshold.fitness.size() && env.threshold.accuracy < 0.0)
  {
    if (problem->classification())
    {
      env.threshold.fitness = fitness_t(with_size(1));
      env.threshold.accuracy = 0.99;

      vitaINFO << "Accuracy threshold set to " << env.threshold.accuracy;
    }
    else  // symbolic regression
    {
      env.threshold.fitness = {-0.0001};

      vitaINFO << "Fitness threshold set to " << env.threshold.fitness;
    }
  }
}

///
/// \param[in] s a value to be interpreted as boolean
/// \return      `true` if `s` is not zero and not `"false"`
///
bool is_true(const std::string &s)
{
  return s != "0" && !vita::iequals(s, "false");
}

///
/// Contains the text-based command line interface.
///
/// The interface is not intented to be human friendly (no code completion,
/// command history, submenu...). We just want a light interface for the
/// Python GUI and a simple way of debugging.
///
namespace ui
{
using vita::log;

const std::string header(
  "(==(     )==)\n"
  " `-.`. ,',-' \n"
  "    _,-'       " + vita_sr_version1 + "\n" \
  " ,-',' `.`-.   " + vita_sr_version2 + "\n" \
  "(==(     )==)\n"
  " `-.`. ,',-'   " + vita_sr_defs + "\n"     \
  "    _,-'\"   \n"
  " ,-',' `.`-. \n"
  "(==(     )==)\n");

po::options_description cmdl_opt(
  "sr [options] [data set]\n\nAllowed options");

/// Number of runs to be tried.
unsigned runs(1);

// Active evaluator.
vita::evaluator_id eva(vita::evaluator_id::undefined);
std::string eva_args;

/// Reference problem (the problem we will work on).
vita::src_problem *problem;

///
/// Sets Adaptive Representation through Learning.
///
/// \param[in] v a value for ARL (\see is_true)
///
void arl(const std::string &v)
{
  assign(problem->env.arl, is_true(v));

  vitaINFO << "Adaptive Representation through Learning is "
           << problem->env.arl;
}

///
/// Sets the brood size for recombination.
///
/// \param[in] size brood size for recombination (0 to disable)
///
void brood(unsigned size)
{
  problem->env.brood_recombination = size;

  vitaINFO << "Brood size for recombination set to " << size;
}

///
/// Sets the code/genome length of an individual.
///
/// \param[in] length code/genome length of an individual
///
void code_length(unsigned length)
{
  Expects(length);

  problem->env.mep.code_length = length;

  vitaINFO << "Code length set to " << length;
}

///
/// Sets the overall probability that crossover will occour between winners
/// in a tournament.
///
/// \param[in] r range is `[0,1]`
///
void crossover_rate(double r)
{
  if (r < 0.0)
  {
    r = 0.0;
    vitaWARNING << "Adjusting crossover probability (" << r << " => 0.0)";
  }
  else if (r > 1.0)
  {
    r = 1.0;
    vitaWARNING << "Adjusting crossover probability (" << r << " => 1.0)";
  }

  problem->env.p_cross = r;

  vitaINFO << "Crossover rate set to " << r;
}

///
/// \param[in] data_file guess what? This is the data file to be parsed
/// \return              `true` if data have been correctly read and parsed
///
bool data(const std::string &data_file)
{
  vitaINFO << "Reading data file " << data_file << "...";

  std::size_t parsed(0);
  try
  {
    parsed = problem->load(data_file).first;
  }
  catch(...)
  {
    parsed = 0;
  }

  if (parsed)
    vitaINFO << "Dataset read. Examples: " << parsed
             << ", categories: " << problem->categories()
             << ", features: " << problem->variables()
             << ", classes: " << problem->classes();
  else
    vitaERROR << "Dataset file format error";

  return parsed;
}

///
/// Turn on/off the Dynamic Subset Selection algorithm.
///
/// \param[in] s a value for DSS
///
void dss(const std::string &s)
{
  problem->env.dss = decltype(problem->env.dss){s};

  if (problem->env.dss.has_value())
    vitaINFO << "Dynamic Subset Selection is " << *problem->env.dss;
  else
    vitaINFO << "Auto-tuning the parameter";
}

///
/// Sets the elitism tendency.
///
/// \param[in] v a value for elitism
///
void elitism(const std::string &v)
{
  assign(problem->env.elitism, is_true(v));

  vitaINFO << "Elitism is " << problem->env.elitism;
}

///
/// Shows the environment.
///
void environment(bool)
{
  vitaINFO << "NOT IMPLEMENTED";
}

///
/// param[in] v the chosen evaluator
///
/// \note
/// The evaluator should fit the current problem kind (symbolic regression,
/// classification) or it won't be used.
///
void evaluator(const std::string &v)
{
  const auto sep(v.find(':'));
  const std::string keyword(v.substr(0, sep));

  eva_args = "";
  if (sep != std::string::npos && sep + 1 < v.size())
    eva_args = v.substr(sep + 1);

  bool ok(true);
  if (keyword == "count")
    eva = vita::evaluator_id::count;
  else if (keyword == "mae")
    eva = vita::evaluator_id::mae;
  else if (keyword == "rmae")
    eva = vita::evaluator_id::rmae;
  else if (keyword == "mse")
    eva = vita::evaluator_id::mse;
  else if (keyword == "binary")
    eva = vita::evaluator_id::bin;
  else if (keyword == "dynslot")
    eva = vita::evaluator_id::dyn_slot;
  else if (keyword == "gaussian")
    eva = vita::evaluator_id::gaussian;
  else
    ok = false;

  if (ok)
  {
    vitaINFO << "Evaluator is " << keyword;
    if (!eva_args.empty())
    {
      vitaINFO << " (parameters: " << eva_args << ')';
    }
  }
  else
    vitaERROR << "Wrong argument for evaluator command";
}

///
/// Quit program.
///
void exit(bool)
{
  vitaOUTPUT << "Bye";
}

///
/// Sets the maximum number of generations in a run.
///
/// \param[in] g maximum number of generations in a run
///
void generations(unsigned g)
{
  problem->env.generations = g;

  vitaINFO << "Generations set to " << g;
}

///
/// Starts the search.
///
void go(bool = true)
{'fraction_non_alphanumeric': 0.17455621301775148, 'fraction_numerical': 0.008136094674556213, 'mean_word_length': 2.7618826802689544, 'pattern_counts': {'":': 0, '<': 277, '<?xml version=': 0, '>': 83, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3704006', 'n_tokens_mistral': 5808, 'n_tokens_neox': 5638, 'n_words': 1451}