<commit_before>#include "pass_bits/analyser/openmp.hpp"
#include "pass_bits/problem/space_mission/gtoc1.hpp"
#include "pass_bits/problem/optimisation_benchmark/de_jong_function.hpp"
#include "pass_bits/helper/evaluation_time_stall.hpp"
#include "pass_bits/optimiser/parallel_swarm_search.hpp"
#include "pass_bits/optimiser/particle_swarm_optimisation.hpp"
#include "pass_bits/analyser/problem_evaluation_time.hpp"
#include "pass_bits/helper/regression.hpp"
#include "pass_bits/helper/random.hpp"
#include <unistd.h>

bool pass::enable_openmp(const pass::problem &problem)
{
  // Output information
  std::cout << " =========================== Start openMP Analyse ========================= " << std::endl;
  std::cout << "                                                                            " << std::endl;
  std::cout << " Your Problem:                " << problem.name << std::endl;
  std::cout << " Dimension:                   " << problem.dimension() << std::endl;
  std::cout << " Number Threads:              " << pass::number_of_threads() << std::endl;
  std::cout << " Maximum Speedup:             " << pass::number_of_threads() << std::endl;
  std::cout << "                                                                            " << std::endl;

  std::cout << " ============================= Start Evaluation =========================== " << std::endl;

  double your_time = pass::problem_evaluation_time(problem);

  std::cout << "                                                                            " << std::endl;
  std::cout << " Evaluation time: " << your_time * 1e-3 << " microseconds." << std::endl;
  std::cout << "                                                                            " << std::endl;
  std::cout << " ============================= End Evaluation  ============================ " << std::endl;
  std::cout << "                                                                            " << std::endl;

  arma::mat summary;
  arma::rowvec model;

  // Check if the file exists
  bool ok = model.load("./openmp_model.pass");

  if (ok == false)
  {
    std::cout << " - Model does not exist                                                     " << std::endl;
    std::cout << "                                                                            " << std::endl;
    // Start training the data
    summary = train(30);
    model = build_model(summary);
  }
  else
  {
    std::cout << "                                                                            " << std::endl;
    std::cout << " - Model exists                                                             " << std::endl;
    std::cout << "                                                                            " << std::endl;
  }

  std::cout << " ========================= Start SpeedUp Prediction ======================= " << std::endl;

  // Generating a regression object
  pass::regression r;

  if (model.n_elem == 3)
  {
    double predict_linear = r.predict_linear(your_time, model);

    if (predict_linear > 0.9 * pass::number_of_threads())
    {
      predict_linear = 0.9 * pass::number_of_threads();
    }
    std::cout << "                                                                            " << std::endl;
    std::cout << " Your speedUp would be approximately: " << predict_linear << std::endl;

    std::cout << "                                                                            " << std::endl;
    std::cout << " ========================== Done SpeedUp Prediction ======================= " << std::endl;

    if (predict_linear > pass::number_of_threads() / 2) // efficienty is more than 50 %
    {
      std::cout << "                                                                            " << std::endl;
      std::cout << " You should activate openMP!                                                " << std::endl;
      std::cout << "                                                                            " << std::endl;
      std::cout << " =========================  Done openMP Analyse  ========================== " << std::endl;
      return true;
    }
    if (predict_linear < 1) // is efficienty is more than 50 %
    {
      std::cout << "                                                                            " << std::endl;
      std::cout << " You should NOT activate openMP!                                            " << std::endl;
      std::cout << "                                                                            " << std::endl;
      std::cout << " =========================  Done openMP Analyse  ========================== " << std::endl;
      return false;
    }
    if (predict_linear > 1 && predict_linear < pass::number_of_threads() / 2) // efficienty is less than 50 %
    {
      std::cout << "                                                                            " << std::endl;
      std::cout << " You should decide yourself if to activate openMP or not!                   " << std::endl;
      std::cout << "                                                                            " << std::endl;
    }
  }
  else
  {
    double predict_poly = r.predict_poly(your_time, model);

    if (predict_poly > 0.9 * pass::number_of_threads())
    {
      predict_poly = 0.9 * pass::number_of_threads();
    }
    std::cout << "                                                                            " << std::endl;
    std::cout << " Your speedUp would be approximately: " << predict_poly << std::endl;
    std::cout << "                                                                            " << std::endl;
    std::cout << " ========================== Done SpeedUp Prediction ======================= " << std::endl;

    if (predict_poly > pass::number_of_threads() / 2) // is efficienty is more than 50 %
    {
      std::cout << "                                                                            " << std::endl;
      std::cout << " You should activate openMP!                                                " << std::endl;
      std::cout << "                                                                            " << std::endl;
      std::cout << " =========================  Done openMP Analyse  ========================== " << std::endl;
      return true;
    }
    if (predict_poly < 1) // is efficienty is more than 50 %
    {
      std::cout << "                                                                            " << std::endl;
      std::cout << " You should NOT activate openMP!                                            " << std::endl;
      std::cout << "                                                                            " << std::endl;
      std::cout << " =========================  Done openMP Analyse  ========================== " << std::endl;
      return false;
    }
    if (predict_poly > 1 && predict_poly < pass::number_of_threads() / 2) // is efficienty is more than 50 %
    {
      std::cout << "                                                                            " << std::endl;
      std::cout << " You should decide yourself if to activate openMP or not!                   " << std::endl;
      std::cout << "                                                                            " << std::endl;
    }
  }

  std::cout << "                                                                            " << std::endl;
  std::cout << " =========================  Done openMP Analyse  ========================== " << std::endl;

  return true;
}

arma::mat pass::train(const int &examples)
{
  // define the maximum of runs
  arma::uword alg_runs = 2;

  // Array including all alg runtime, we want to test
  //std::array<int, 30> repetitions = {1, 2, 3, 80, 100, 140, 180, 190, 90, 100, 110, 120, 130, 160, 200, 240, 330, 333, 436,
  //                                   2, 45, 50, 60, 70, 80, 100, 120, 140, 160};

  arma::rowvec repetitions = pass::integers_uniform_in_range(1, 1000, examples);

  // Output information
  std::cout << " ============================= Start Trainining =========================== " << std::endl;
  std::cout << "                                                                            " << std::endl;

  arma::vec serial(alg_runs);
  arma::vec parallel(alg_runs);

  arma::mat summary(2, repetitions.size());

  std::srand(time(0));
  int count = 0;

  pass::particle_swarm_optimisation algorithm_serial;
  //algorithm_serial.maximal_duration = std::chrono::seconds(5);
  algorithm_serial.maximal_iterations = 200;

  pass::parallel_swarm_search algorithm_parallel;
  //algorithm_parallel.maximal_duration = std::chrono::seconds(5);
  algorithm_parallel.maximal_iterations = 200;

  repetitions = arma::sort(repetitions);

  for (int repetition : repetitions)
  {
    // Problem initialisation
    pass::de_jong_function test_problem(10);
    pass::evaluation_time_stall simulated_problem(test_problem);
    simulated_problem.repetitions = repetition;

    std::cout << "Repetion: " << repetition << std::endl;

    double ev_time = pass::problem_evaluation_time(simulated_problem);
    summary(0, count) = ev_time * 1e-3;

    // Do the evaluation for serial and parallel for all the evaluations values
    for (arma::uword serial_run = 0; serial_run < alg_runs; ++serial_run)
    {
      pass::optimise_result serial_alg = algorithm_serial.optimise(simulated_problem);
      //serial(serial_run) = serial_alg.evaluations;
      serial(serial_run) = serial_alg.duration.count();
      usleep(1000000);
    }

    std::cout << "Serial: " << arma::mean(serial) * 1e-3 << std::endl;

    for (arma::uword parallel_run = 0; parallel_run < alg_runs; ++parallel_run)
    {
      optimise_result parallel_alg = algorithm_parallel.optimise(simulated_problem);
      //parallel(parallel_run) = parallel_alg.evaluations;
      parallel(parallel_run) = parallel_alg.duration.count();
      usleep(1000000);
    }
    std::cout << "Parallel: " << arma::mean(parallel) * 1e-3 << std::endl;

    summary(1, count) = arma::mean(serial) / arma::mean(parallel);

    std::cout << "Summary: \n"
              << summary.col(count) << std::endl;

    count++;

    // load bar
    double temp_count = static_cast<double>(examples) / static_cast<double>(count);
    std::cout << " \r " << 100.0 / temp_count << " % completed." << std::flush;
  }

  std::cout << std::endl
            << std::endl
            << " Training completed successfully.\n"
            << std::flush;
  std::cout << "                                                                            " << std::endl;
  std::cout << " ===========================  End Training  =============================== " << std::endl;
  std::cout << "                                                                            " << std::endl;

  return summary;
}

arma::rowvec pass::build_model(const arma::mat &training_points)
{
  // File to save the model
  std::string file_name;
  file_name = "openmp_model.pass";

  // Generating a regression object
  pass::regression r;

  // Getting the data for the model
  arma::rowvec x_values = training_points.row(0);
  arma::rowvec y_values = training_points.row(1);

  // Output information
  std::cout << " =========================== Start Building Models ======================== " << std::endl;
  std::cout << "                                                                            " << std::endl;
  std::cout << " Building linear model for the training data.                               " << std::endl;
  std::cout << "                                                                            " << std::endl;

  // Generating the linear model

  arma::rowvec linear_model = r.linear_model(x_values, y_values);

  if (linear_model(2) >= 0.9)
  {
    std::cout << " Finished building linear model.                                            " << std::endl;
    std::cout << "                                                                            " << std::endl;
    std::cout << " Linear Model is suitable.                                                  " << std::endl;
    std::cout << "                                                                            " << std::endl;
    std::cout << " ========================= Done Building Models  ========================== " << std::endl;
    std::cout << "                                                                            " << std::endl;

    linear_model.save("./" + file_name, arma::raw_ascii);

    return linear_model;
  }

  std::cout << " Finished building linear model.                                            " << std::endl;
  std::cout << "                                                                            " << std::endl;
  std::cout << " Linear Model is NOT suitable.                                              " << std::endl;
  std::cout << "                                                                            " << std::endl;
  std::cout << " Building polynomial model for the training data.                           " << std::endl;
  std::cout << "                                                                            " << std::endl;

  arma::rowvec poly_model = r.poly_model(x_values, y_values, 3);
  std::cout << " ========================= Done Building Models  ========================== " << std::endl;
  std::cout << "                                                                            " << std::endl;

  poly_model.save("./" + file_name, arma::raw_ascii);

  return poly_model;
}
<commit_msg>test<commit_after>#include "pass_bits/analyser/openmp.hpp"
#include "pass_bits/problem/space_mission/gtoc1.hpp"
#include "pass_bits/problem/optimisation_benchmark/de_jong_function.hpp"
#include "pass_bits/helper/evaluation_time_stall.hpp"
#include "pass_bits/optimiser/parallel_swarm_search.hpp"
#include "pass_bits/optimiser/particle_swarm_optimisation.hpp"
#include "pass_bits/analyser/problem_evaluation_time.hpp"
#include "pass_bits/helper/regression.hpp"
#include "pass_bits/helper/random.hpp"
#include <unistd.h>

bool pass::enable_openmp(const pass::problem &problem)
{
  // Output information
  std::cout << " =========================== Start openMP Analyse ========================= " << std::endl;
  std::cout << "                                                                            " << std::endl;
  std::cout << " Your Problem:                " << problem.name << std::endl;
  std::cout << " Dimension:                   " << problem.dimension() << std::endl;
  std::cout << " Number Threads:              " << pass::number_of_threads() << std::endl;
  std::cout << " Maximum Speedup:             " << pass::number_of_threads() << std::endl;
  std::cout << "                                                                            " << std::endl;

  std::cout << " ============================= Start Evaluation =========================== " << std::endl;

  double your_time = pass::problem_evaluation_time(problem);

  std::cout << "                                                                            " << std::endl;
  std::cout << " Evaluation time: " << your_time * 1e-3 << " microseconds." << std::endl;
  std::cout << "                                                                            " << std::endl;
  std::cout << " ============================= End Evaluation  ============================ " << std::endl;
  std::cout << "                                                                            " << std::endl;

  arma::mat summary;
  arma::rowvec model;

  // Check if the file exists
  bool ok = model.load("./openmp_model.pass");

  if (ok == false)
  {
    std::cout << " - Model does not exist                                                     " << std::endl;
    std::cout << "                                                                            " << std::endl;
    // Start training the data
    summary = train(30);
    model = build_model(summary);
  }
  else
  {
    std::cout << "                                                                            " << std::endl;
    std::cout << " - Model exists                                                             " << std::endl;
    std::cout << "                                                                            " << std::endl;
  }

  std::cout << " ========================= Start SpeedUp Prediction ======================= " << std::endl;

  // Generating a regression object
  pass::regression r;

  if (model.n_elem == 3)
  {
    double predict_linear = r.predict_linear(your_time, model);

    if (predict_linear > 0.9 * pass::number_of_threads())
    {
      predict_linear = 0.9 * pass::number_of_threads();
    }
    std::cout << "                                                                            " << std::endl;
    std::cout << " Your speedUp would be approximately: " << predict_linear << std::endl;

    std::cout << "                                                                            " << std::endl;
    std::cout << " ========================== Done SpeedUp Prediction ======================= " << std::endl;

    if (predict_linear > pass::number_of_threads() / 2) // efficienty is more than 50 %
    {
      std::cout << "                                                                            " << std::endl;
      std::cout << " You should activate openMP!                                                " << std::endl;
      std::cout << "                                                                            " << std::endl;
      std::cout << " =========================  Done openMP Analyse  ========================== " << std::endl;
      return true;
    }
    if (predict_linear < 1) // is efficienty is more than 50 %
    {
      std::cout << "                                                                            " << std::endl;
      std::cout << " You should NOT activate openMP!                                            " << std::endl;
      std::cout << "                                                                            " << std::endl;
      std::cout << " =========================  Done openMP Analyse  ========================== " << std::endl;
      return false;
    }
    if (predict_linear > 1 && predict_linear < pass::number_of_threads() / 2) // efficienty is less than 50 %
    {
      std::cout << "                                                                            " << std::endl;
      std::cout << " You should decide yourself if to activate openMP or not!                   " << std::endl;
      std::cout << "                                                                            " << std::endl;
    }
  }
  else
  {
    double predict_poly = r.predict_poly(your_time, model);

    if (predict_poly > 0.9 * pass::number_of_threads())
    {
      predict_poly = 0.9 * pass::number_of_threads();
    }
    std::cout << "                                                                            " << std::endl;
    std::cout << " Your speedUp would be approximately: " << predict_poly << std::endl;
    std::cout << "                                                                            " << std::endl;
    std::cout << " ========================== Done SpeedUp Prediction ======================= " << std::endl;

    if (predict_poly > pass::number_of_threads() / 2) // is efficienty is more than 50 %
    {
      std::cout << "                                                                            " << std::endl;
      std::cout << " You should activate openMP!                                                " << std::endl;
      std::cout << "                                                                            " << std::endl;
      std::cout << " =========================  Done openMP Analyse  ========================== " << std::endl;
      return true;
    }
    if (predict_poly < 1) // is efficienty is more than 50 %
    {
      std::cout << "                                                                            " << std::endl;
      std::cout << " You should NOT activate openMP!                                            " << std::endl;
      std::cout << "                                                                            " << std::endl;
      std::cout << " =========================  Done openMP Analyse  ========================== " << std::endl;
      return false;
    }
    if (predict_poly > 1 && predict_poly < pass::number_of_threads() / 2) // is efficienty is more than 50 %
    {
      std::cout << "                                                                            " << std::endl;
      std::cout << " You should decide yourself if to activate openMP or not!                   " << std::endl;
      std::cout << "                                                                            " << std::endl;
    }
  }

  std::cout << "                                                                            " << std::endl;
  std::cout << " =========================  Done openMP Analyse  ========================== " << std::endl;

  return true;
}

arma::mat pass::train(const int &examples)
{
  // define the maximum of runs
  arma::uword alg_runs = 2;

  // Array including all alg runtime, we want to test
  //std::array<int, 30> repetitions = {1, 2, 3, 80, 100, 140, 180, 190, 90, 100, 110, 120, 130, 160, 200, 240, 330, 333, 436,
  //                                   2, 45, 50, 60, 70, 80, 100, 120, 140, 160};

  arma::rowvec repetitions = pass::integers_uniform_in_range(1, 5000, examples);

  // Output information
  std::cout << " ============================= Start Trainining =========================== " << std::endl;
  std::cout << "                                                                            " << std::endl;

  arma::vec serial(alg_runs);
  arma::vec parallel(alg_runs);

  arma::mat summary(2, repetitions.size());

  std::srand(time(0));
  int count = 0;

  pass::particle_swarm_optimisation algorithm_serial;
  //algorithm_serial.maximal_duration = std::chrono::seconds(5);
  algorithm_serial.maximal_iterations = 200;

  pass::parallel_swarm_search algorithm_parallel;
  //algorithm_parallel.maximal_duration = std::chrono::seconds(5);
  algorithm_parallel.maximal_iterations = 200;

  repetitions = arma::sort(repetitions);

  for (int repetition : repetitions)
  {
    // Problem initialisation
    pass::de_jong_function test_problem(10);
    pass::evaluation_time_stall simulated_problem(test_problem);
    simulated_problem.repetitions = repetition;

    std::cout << "Repetion: " << repetition << std::endl;

    double ev_time = pass::problem_evaluation_time(simulated_problem);
    summary(0, count) = ev_time;

    // Do the evaluation for serial and parallel for all the evaluations values
    for (arma::uword serial_run = 0; serial_run < alg_runs; ++serial_run)
    {
      pass::optimise_result serial_alg = algorithm_serial.optimise(simulated_problem);
      //serial(serial_run) = serial_alg.evaluations;
      serial(serial_run) = serial_alg.duration.count();
      usleep(1000000);
    }

    for (arma::uword parallel_run = 0; parallel_run < alg_runs; ++parallel_run)
    {
      optimise_result parallel_alg = algorithm_parallel.optimise(simulated_problem);
      //parallel(parallel_run) = parallel_alg.evaluations;
      parallel(parallel_run) = parallel_alg.duration.count();
      usleep(1000000);
    }

    summary(1, count) = arma::mean(serial) / arma::mean(parallel);

    count++;

    // load bar
    double temp_count = static_cast<double>(examples) / static_cast<double>(count);
    std::cout << " \r " << 100.0 / temp_count << " % completed." << std::flush;
  }

  std::cout << std::endl
            << std::endl
            << " Training completed successfully.\n"
            << std::flush;
  std::cout << "                                                                            " << std::endl;
  std::cout << " ===========================  End Training  =============================== " << std::endl;
  std::cout << "                                                                            " << std::endl;

  std::cout << "Summary: \n"
            << summary << std::endl;
  return summary;
}

arma::rowvec pass::build_model(const arma::mat &training_points)
{
  // File to save the model
  std::string file_name;
  file_name = "openmp_model.pass";

  // Generating a regression object
  pass::regression r;

  // Getting the data for the model
  arma::rowvec x_values = training_points.row(0);
  arma::rowvec y_values = training_points.row(1);

  // Output information
  std::cout << " =========================== Start Building Models ======================== " << std::endl;
  std::cout << "                                                                            " << std::endl;
  std::cout << " Building linear model for the training data.                               " << std::endl;
  std::cout << "                                                                            " << std::endl;

  // Generating the linear model

  arma::rowvec linear_model = r.linear_model(x_values, y_values);

  if (linear_model(2) >= 0.9)
  {
    std::cout << " Finished building linear model.                                            " << std::endl;
    std::cout << "                                                                            " << std::endl;
    std::cout << " Linear Model is suitable.                                                  " << std::endl;
    std::cout << "                                                                            " << std::endl;
    std::cout << " ========================= Done Building Models  ========================== " << std::endl;
    std::cout << "                                                                            " << std::endl;

    linear_model.save("./" + file_name, arma::raw_ascii);

    return linear_model;
  }

  std::cout << " Finished building linear model.                                            " << std::endl;
  std::cout << "                                                                            " << std::endl;
  std::cout << " Linear Model is NOT suitable.                                              " << std::endl;
  std::cout << "                                                                            " << std::endl;
  std::cout << " Building polynomial model for the training data.                           " << std::endl;
  std::cout << "                                                                            " << std::endl;

  arma::rowvec poly_model = r.poly_model(x_values, y_values, 3);
  std::cout << " ========================= Done Building Models  ========================== " << std::endl;
  std::cout << "                                                                            " << std::endl;

  poly_model.save("./" + file_name, arma::raw_ascii);

  return poly_model;
}
<|endoftext|>


<commit_before>#include "pass_bits/analyser/openmp.hpp"
#include "pass_bits/problem/space_mission/gtoc1.hpp"
#include "pass_bits/problem/optimisation_benchmark/de_jong_function.hpp"
#include "pass_bits/helper/evaluation_time_stall.hpp"
#include "pass_bits/optimiser/parallel_swarm_search.hpp"
#include "pass_bits/optimiser/particle_swarm_optimisation.hpp"
#include "pass_bits/analyser/problem_evaluation_time.hpp"
#include "pass_bits/helper/regression.hpp"
#include "pass_bits/helper/random.hpp"
#include <unistd.h> // usleep
#include <iomanip>  // setprecision, setfill

bool pass::enable_openmp(const pass::problem &problem)
{
  // Output information
  std::cout << " =========================== Start openMP Analyse ========================= " << std::endl;
  std::cout << "                                                                            " << std::endl;
  std::cout << " Your Problem:                " << problem.name << std::endl;
  std::cout << " Dimension:                   " << problem.dimension() << std::endl;
  std::cout << " Number of Threads:           " << pass::number_of_threads() << std::endl;
  std::cout << "                                                                            " << std::endl;

  std::cout << " ============================= Start Evaluation =========================== " << std::endl;

  double your_time = pass::problem_evaluation_time(problem);

  std::cout << "                                                                            " << std::endl;
  std::cout << " Evaluation time: " << your_time * 1e-3 << " microseconds." << std::endl;
  std::cout << "                                                                            " << std::endl;
  std::cout << " ============================= End Evaluation  ============================ " << std::endl;
  std::cout << "                                                                            " << std::endl;

  arma::mat summary;
  arma::rowvec model;

  // Check if the file exists
  bool ok = model.load("./openmp_model.pass");

  if (ok == false)
  {
    std::cout << " - Model does not exist                                                     " << std::endl;
    std::cout << "                                                                            " << std::endl;
    // Start training + build model
    summary = train(120);
    model = build_model(summary);
  }
  else
  {
    std::cout << " - Model exists                                                             " << std::endl;
    std::cout << "                                                                            " << std::endl;
  }

  std::cout << " ========================= Start SpeedUp Prediction ======================= " << std::endl;

  // Generating a regression object
  pass::regression r;

  if (model.n_elem == 3)
  {
    double predict_linear = r.predict_linear(your_time, model);

    if (predict_linear > 0.9 * pass::number_of_threads())
    {
      predict_linear = 0.9 * pass::number_of_threads();
    }
    std::cout << "                                                                            " << std::endl;
    std::cout << " Your speedUp will be approximately:  " << predict_linear << std::endl;

    std::cout << "                                                                            " << std::endl;
    std::cout << " ========================== Done SpeedUp Prediction ======================= " << std::endl;

    if (predict_linear >= pass::number_of_threads() * 0.5) // efficienty is more than 50 %
    {
      std::cout << "                                                                            " << std::endl;
      std::cout << " You should activate openMP!                                                " << std::endl;
      std::cout << "                                                                            " << std::endl;
      std::cout << " =========================  Done openMP Analyse  ========================== " << std::endl;
      return true;
    }
    if (predict_linear <= pass::number_of_threads() * 0.2) // efficienty is less than 20 %
    {
      std::cout << "                                                                            " << std::endl;
      std::cout << " You should NOT activate openMP!                                            " << std::endl;
      std::cout << "                                                                            " << std::endl;
      std::cout << " =========================  Done openMP Analyse  ========================== " << std::endl;
      return false;
    }
    if (predict_linear > pass::number_of_threads() * 0.2 && predict_linear < pass::number_of_threads() * 0.5)
    {
      std::cout << "                                                                            " << std::endl;
      std::cout << " Decide yourself if to activate openMP or not!                              " << std::endl;
      std::cout << "                                                                            " << std::endl;
    }
  }
  else
  {
    double predict_poly = r.predict_poly(your_time, model);

    if (predict_poly > 0.9 * pass::number_of_threads())
    {
      predict_poly = 0.9 * pass::number_of_threads();
    }
    std::cout << "                                                                            " << std::endl;
    std::cout << " Your speedUp will be approximately: " << predict_poly << std::endl;
    std::cout << "                                                                            " << std::endl;
    std::cout << " ========================== Done SpeedUp Prediction ======================= " << std::endl;

    if (predict_poly >= pass::number_of_threads() * 0.5) // is efficienty is more than 50 %
    {
      std::cout << "                                                                            " << std::endl;
      std::cout << " You should activate openMP!                                                " << std::endl;
      std::cout << "                                                                            " << std::endl;
      std::cout << " =========================  Done openMP Analyse  ========================== " << std::endl;
      return true;
    }
    if (predict_poly <= pass::number_of_threads() * 0.2) // efficienty is less than 20 %
    {
      std::cout << "                                                                            " << std::endl;
      std::cout << " You should NOT activate openMP!                                            " << std::endl;
      std::cout << "                                                                            " << std::endl;
      std::cout << " =========================  Done openMP Analyse  ========================== " << std::endl;
      return false;
    }
    if (predict_poly > pass::number_of_threads() * 0.2 && predict_poly < pass::number_of_threads() * 0.5)
    {
      std::cout << "                                                                            " << std::endl;
      std::cout << " Decide yourself if to activate openMP or not!                              " << std::endl;
    }
  }

  std::cout << "                                                                            " << std::endl;
  std::cout << " =========================  Done openMP Analyse  ========================== " << std::endl;
  std::cout << "                                                                            " << std::endl;
  std::cout << "                                                                            " << std::endl;

  return true;
}

arma::mat pass::train(const int &examples)
{
  // Output information
  std::cout << " ============================= Start Trainining =========================== " << std::endl;
  std::cout << "                                                                            " << std::endl;

  // define the maximum of runs
  arma::uword alg_runs = 2;
  int max_iter = 200;

  arma::rowvec repetitions = pass::integers_uniform_in_range(1, 20000, examples);

  arma::vec serial(alg_runs);
  arma::vec parallel(alg_runs);

  arma::mat summary(2, repetitions.size());

  pass::particle_swarm_optimisation algorithm_serial;
  algorithm_serial.maximal_iterations = max_iter;

  pass::parallel_swarm_search algorithm_parallel;
  algorithm_parallel.maximal_iterations = max_iter;

  repetitions = arma::sort(repetitions);

  arma::uword count = 0;
  for (arma::uword repetition : repetitions)
  {
    // Problem initialisation
    pass::de_jong_function test_problem(10);
    pass::evaluation_time_stall simulated_problem(test_problem);
    simulated_problem.repetitions = repetition;

    double ev_time = pass::problem_evaluation_time(simulated_problem);
    summary(0, count) = ev_time;

    // Do the evaluation for serial and parallel for all the evaluations values
    for (arma::uword serial_run = 0; serial_run < alg_runs; ++serial_run)
    {
      pass::optimise_result serial_alg = algorithm_serial.optimise(simulated_problem);
      serial(serial_run) = serial_alg.duration.count();
      usleep(1000000);
    }

    for (arma::uword parallel_run = 0; parallel_run < alg_runs; ++parallel_run)
    {
      optimise_result parallel_alg = algorithm_parallel.optimise(simulated_problem);
      parallel(parallel_run) = parallel_alg.duration.count();
      usleep(1000000);
    }

    summary(1, count) = arma::mean(serial) / arma::mean(parallel);

    count++;

    // load bar
    double temp_count = static_cast<double>(examples) / static_cast<double>(count);
    std::cout << std::fixed << std::setprecision(2) << std::setfill(' ');
    std::cout << " \r " << 100.0 / temp_count << " % completed." << std::flush;
  }

  std::cout << std::endl
            << std::endl
            << " Training completed successfully.\n"
            << std::flush;
  std::cout << "                                                                            " << std::endl;
  std::cout << " ===========================  End Training  =============================== " << std::endl;
  std::cout << "                                                                            " << std::endl;

  return summary;
}

arma::rowvec pass::build_model(const arma::mat &training_points)
{
  // File to save the model
  std::string file_name;
  file_name = "openmp_model.pass";

  // Generating a regression object
  pass::regression r;

  // Getting the data for the model
  arma::rowvec x_values = training_points.row(0);
  arma::rowvec y_values = training_points.row(1);

  // Output information
  std::cout << " =========================== Start Building Models ======================== " << std::endl;
  std::cout << "                                                                            " << std::endl;
  std::cout << " Building linear model for the training data.                               " << std::endl;
  std::cout << "                                                                            " << std::endl;

  // Generating the linear model
  arma::rowvec linear_model = r.linear_model(x_values, y_values);

  if (linear_model(2) >= 0.9)
  {
    std::cout << " Finished building linear model.                                            " << std::endl;
    std::cout << "                                                                            " << std::endl;
    std::cout << " Linear Model is suitable.                                                  " << std::endl;
    std::cout << "                                                                            " << std::endl;
    std::cout << " ========================= Done Building Models  ========================== " << std::endl;
    std::cout << "                                                                            " << std::endl;

    linear_model.save("./" + file_name, arma::raw_ascii);

    return linear_model;
  }

  std::cout << " Finished building linear model.                                            " << std::endl;
  std::cout << "                                                                            " << std::endl;
  std::cout << " Linear Model is NOT suitable.                                              " << std::endl;
  std::cout << "                                                                            " << std::endl;
  std::cout << " Building polynomial model.                                                 " << std::endl;
  std::cout << "                                                                            " << std::endl;

  arma::rowvec poly_model = r.poly_model(x_values, y_values, 3);

  std::cout << " ========================= Done Building Models  ========================== " << std::endl;
  std::cout << "                                                                            " << std::endl;

  poly_model.save("./" + file_name, arma::raw_ascii);

  return poly_model;
}
<commit_msg>include special case<commit_after>#include "pass_bits/analyser/openmp.hpp"
#include "pass_bits/problem/space_mission/gtoc1.hpp"
#include "pass_bits/problem/optimisation_benchmark/de_jong_function.hpp"
#include "pass_bits/helper/evaluation_time_stall.hpp"
#include "pass_bits/optimiser/parallel_swarm_search.hpp"
#include "pass_bits/optimiser/particle_swarm_optimisation.hpp"
#include "pass_bits/analyser/problem_evaluation_time.hpp"
#include "pass_bits/helper/regression.hpp"
#include "pass_bits/helper/random.hpp"
#include <unistd.h> // usleep
#include <iomanip>  // setprecision, setfill

bool pass::enable_openmp(const pass::problem &problem)
{
  // Output information
  std::cout << " =========================== Start openMP Analyse ========================= " << std::endl;
  std::cout << "                                                                            " << std::endl;
  std::cout << " Your Problem:                " << problem.name << std::endl;
  std::cout << " Dimension:                   " << problem.dimension() << std::endl;
  std::cout << " Number of Threads:           " << pass::number_of_threads() << std::endl;
  std::cout << "                                                                            " << std::endl;

  if (pass::number_of_threads() == 1)
  {
    std::cout << " - You have only one thread! openMP is not possible! " << std::endl;
    std::cout << "                                                                            " << std::endl;
    std::cout << " =========================  Done openMP Analyse  ========================== " << std::endl;
    return false;
  }

  std::cout << " ============================= Start Evaluation =========================== " << std::endl;

  double your_time = pass::problem_evaluation_time(problem);

  std::cout << "                                                                            " << std::endl;
  std::cout << " Evaluation time: " << your_time * 1e-3 << " microseconds." << std::endl;
  std::cout << "                                                                            " << std::endl;
  std::cout << " ============================= End Evaluation  ============================ " << std::endl;
  std::cout << "                                                                            " << std::endl;

  arma::mat summary;
  arma::rowvec model;

  // Check if the file exists
  bool ok = model.load("./openmp_model.pass");

  if (ok == false)
  {
    std::cout << " - Model does not exist                                                     " << std::endl;
    std::cout << "                                                                            " << std::endl;
    // Start training + build model
    summary = train(120);
    model = build_model(summary);
  }
  else
  {
    std::cout << " - Model exists                                                             " << std::endl;
    std::cout << "                                                                            " << std::endl;
  }

  std::cout << " ========================= Start SpeedUp Prediction ======================= " << std::endl;

  // Generating a regression object
  pass::regression r;

  if (model.n_elem == 3)
  {
    double predict_linear = r.predict_linear(your_time, model);

    if (predict_linear > 0.9 * pass::number_of_threads())
    {
      predict_linear = 0.9 * pass::number_of_threads();
    }
    std::cout << "                                                                            " << std::endl;
    std::cout << " Your speedUp will be approximately:  " << predict_linear << std::endl;

    std::cout << "                                                                            " << std::endl;
    std::cout << " ========================== Done SpeedUp Prediction ======================= " << std::endl;

    if (predict_linear >= pass::number_of_threads() * 0.5) // efficienty is more than 50 %
    {
      std::cout << "                                                                            " << std::endl;
      std::cout << " You should activate openMP!                                                " << std::endl;
      std::cout << "                                                                            " << std::endl;
      std::cout << " =========================  Done openMP Analyse  ========================== " << std::endl;
      return true;
    }
    if (predict_linear <= pass::number_of_threads() * 0.2) // efficienty is less than 20 %
    {
      std::cout << "                                                                            " << std::endl;
      std::cout << " You should NOT activate openMP!                                            " << std::endl;
      std::cout << "                                                                            " << std::endl;
      std::cout << " =========================  Done openMP Analyse  ========================== " << std::endl;
      return false;
    }
    if (predict_linear > pass::number_of_threads() * 0.2 && predict_linear < pass::number_of_threads() * 0.5)
    {
      std::cout << "                                                                            " << std::endl;
      std::cout << " Decide yourself if to activate openMP or not!                              " << std::endl;
      std::cout << "                                                                            " << std::endl;
    }
  }
  else
  {
    double predict_poly = r.predict_poly(your_time, model);

    if (predict_poly > 0.9 * pass::number_of_threads())
    {
      predict_poly = 0.9 * pass::number_of_threads();
    }
    std::cout << "                                                                            " << std::endl;
    std::cout << " Your speedUp will be approximately: " << predict_poly << std::endl;
    std::cout << "                                                                            " << std::endl;
    std::cout << " ========================== Done SpeedUp Prediction ======================= " << std::endl;

    if (predict_poly >= pass::number_of_threads() * 0.5) // is efficienty is more than 50 %
    {
      std::cout << "                                                                            " << std::endl;
      std::cout << " You should activate openMP!                                                " << std::endl;
      std::cout << "                                                                            " << std::endl;
      std::cout << " =========================  Done openMP Analyse  ========================== " << std::endl;
      return true;
    }
    if (predict_poly <= pass::number_of_threads() * 0.2) // efficienty is less than 20 %
    {
      std::cout << "                                                                            " << std::endl;
      std::cout << " You should NOT activate openMP!                                            " << std::endl;
      std::cout << "                                                                            " << std::endl;
      std::cout << " =========================  Done openMP Analyse  ========================== " << std::endl;
      return false;
    }
    if (predict_poly > pass::number_of_threads() * 0.2 && predict_poly < pass::number_of_threads() * 0.5)
    {
      std::cout << "                                                                            " << std::endl;
      std::cout << " Decide yourself if to activate openMP or not!                              " << std::endl;
    }
  }

  std::cout << "                                                                            " << std::endl;
  std::cout << " =========================  Done openMP Analyse  ========================== " << std::endl;
  std::cout << "                                                                            " << std::endl;
  std::cout << "                                                                            " << std::endl;

  return true;
}

arma::mat pass::train(const int &examples)
{
  // Output information
  std::cout << " ============================= Start Trainining =========================== " << std::endl;
  std::cout << "                                                                            " << std::endl;

  // define the maximum of runs
  arma::uword alg_runs = 2;
  int max_iter = 200;

  arma::rowvec repetitions = pass::integers_uniform_in_range(1, 20000, examples);

  arma::vec serial(alg_runs);
  arma::vec parallel(alg_runs);

  arma::mat summary(2, repetitions.size());

  pass::particle_swarm_optimisation algorithm_serial;
  algorithm_serial.maximal_iterations = max_iter;

  pass::parallel_swarm_search algorithm_parallel;
  algorithm_parallel.maximal_iterations = max_iter;

  repetitions = arma::sort(repetitions);

  arma::uword count = 0;
  for (arma::uword repetition : repetitions)
  {
    // Problem initialisation
    pass::de_jong_function test_problem(10);
    pass::evaluation_time_stall simulated_problem(test_problem);
    simulated_problem.repetitions = repetition;

    double ev_time = pass::problem_evaluation_time(simulated_problem);
    summary(0, count) = ev_time;

    // Do the evaluation for serial and parallel for all the evaluations values
    for (arma::uword serial_run = 0; serial_run < alg_runs; ++serial_run)
    {
      pass::optimise_result serial_alg = algorithm_serial.optimise(simulated_problem);
      serial(serial_run) = serial_alg.duration.count();
      usleep(1000000);
    }

    for (arma::uword parallel_run = 0; parallel_run < alg_runs; ++parallel_run)
    {
      optimise_result parallel_alg = algorithm_parallel.optimise(simulated_problem);
      parallel(parallel_run) = parallel_alg.duration.count();
      usleep(1000000);
    }

    summary(1, count) = arma::mean(serial) / arma::mean(parallel);

    count++;

    // load bar
    double temp_count = static_cast<double>(examples) / static_cast<double>(count);
    std::cout << std::fixed << std::setprecision(2) << std::setfill(' ');
    std::cout << " \r " << 100.0 / temp_count << " % completed." << std::flush;
  }

  std::cout << std::endl
            << std::endl
            << " Training completed successfully.\n"
            << std::flush;
  std::cout << "                                                                            " << std::endl;
  std::cout << " ===========================  End Training  =============================== " << std::endl;
  std::cout << "                                                                            " << std::endl;

  return summary;
}

arma::rowvec pass::build_model(const arma::mat &training_points)
{
  // File to save the model
  std::string file_name;
  file_name = "openmp_model.pass";

  // Generating a regression object
  pass::regression r;

  // Getting the data for the model
  arma::rowvec x_values = training_points.row(0);
  arma::rowvec y_values = training_points.row(1);

  // Output information
  std::cout << " =========================== Start Building Models ======================== " << std::endl;
  std::cout << "                                                                            " << std::endl;
  std::cout << " Building linear model for the training data.                               " << std::endl;
  std::cout << "                                                                            " << std::endl;

  // Generating the linear model
  arma::rowvec linear_model = r.linear_model(x_values, y_values);

  if (linear_model(2) >= 0.9)
  {
    std::cout << " Finished building linear model.                                            " << std::endl;
    std::cout << "                                                                            " << std::endl;
    std::cout << " Linear Model is suitable.                                                  " << std::endl;
    std::cout << "                                                                            " << std::endl;
    std::cout << " ========================= Done Building Models  ========================== " << std::endl;
    std::cout << "                                                                            " << std::endl;

    linear_model.save("./" + file_name, arma::raw_ascii);

    return linear_model;
  }

  std::cout << " Finished building linear model.                                            " << std::endl;
  std::cout << "                                                                            " << std::endl;
  std::cout << " Linear Model is NOT suitable.                                              " << std::endl;
  std::cout << "                                                                            " << std::endl;
  std::cout << " Building polynomial model.                                                 " << std::endl;
  std::cout << "                                                                            " << std::endl;

  arma::rowvec poly_model = r.poly_model(x_values, y_values, 3);

  std::cout << " ========================= Done Building Models  ========================== " << std::endl;
  std::cout << "                                                                            " << std::endl;

  poly_model.save("./" + file_name, arma::raw_ascii);

  return poly_model;
}
<|endoftext|>


<commit_before>#include <app/ParamWidget.hpp>
#include <ui/MenuOverlay.hpp>
#include <ui/TextField.hpp>
#include <app/Scene.hpp>
#include <app.hpp>
#include <engine/Engine.hpp>
#include <settings.hpp>
#include <history.hpp>
#include <helpers.hpp>

namespace rack {
namespace app {

struct ParamField : ui::TextField {
	ParamWidget* paramWidget;

	void step() override {
		// Keep selected
		APP->event->setSelected(this);
		TextField::step();
	}

	void setParamWidget(ParamWidget* paramWidget) {
		this->paramWidget = paramWidget;
		if (paramWidget->paramQuantity)
			text = paramWidget->paramQuantity->getDisplayValueString();
		selectAll();
	}

	void onSelectKey(const event::SelectKey& e) override {
		if (e.action == GLFW_PRESS && (e.key == GLFW_KEY_ENTER || e.key == GLFW_KEY_KP_ENTER)) {
			float oldValue = paramWidget->paramQuantity->getValue();
			if (paramWidget->paramQuantity)
				paramWidget->paramQuantity->setDisplayValueString(text);
			float newValue = paramWidget->paramQuantity->getValue();

			if (oldValue != newValue) {
				// Push ParamChange history action
				history::ParamChange* h = new history::ParamChange;
				h->moduleId = paramWidget->paramQuantity->module->id;
				h->paramId = paramWidget->paramQuantity->paramId;
				h->oldValue = oldValue;
				h->newValue = newValue;
				APP->history->push(h);
			}

			ui::MenuOverlay* overlay = getAncestorOfType<ui::MenuOverlay>();
			overlay->requestDelete();
			e.consume(this);
		}

		if (!e.getTarget())
			TextField::onSelectKey(e);
	}
};

struct ParamTooltip : ui::Tooltip {
	ParamWidget* paramWidget;

	void step() override {
		if (paramWidget->paramQuantity) {
			// Quantity string
			text = paramWidget->paramQuantity->getString();
			// Param description
			std::string description = paramWidget->paramQuantity->description;
			if (!description.empty())
				text += "\n" + description;
		}
		Tooltip::step();
		// Position at bottom-right of parameter
		box.pos = paramWidget->getAbsoluteOffset(paramWidget->box.size).round();
	}
};

struct ParamLabel : ui::MenuLabel {
	ParamWidget* paramWidget;
	void step() override {
		text = paramWidget->paramQuantity->getString();
		MenuLabel::step();
	}
};

struct ParamResetItem : ui::MenuItem {
	ParamWidget* paramWidget;
	void onAction(const event::Action& e) override {
		paramWidget->resetAction();
	}
};

struct ParamFineItem : ui::MenuItem {
};

struct ParamUnmapItem : ui::MenuItem {
	ParamWidget* paramWidget;
	void onAction(const event::Action& e) override {
		engine::ParamHandle* paramHandle = APP->engine->getParamHandle(paramWidget->paramQuantity->module->id, paramWidget->paramQuantity->paramId);
		if (paramHandle) {
			APP->engine->updateParamHandle(paramHandle, -1, 0);
		}
	}
};

void ParamWidget::step() {
	if (paramQuantity) {
		float value = paramQuantity->getValue();
		// Trigger change event when paramQuantity value changes
		if (value != dirtyValue) {
			dirtyValue = value;
			event::Change eChange;
			onChange(eChange);
		}
	}

	Widget::step();
}

void ParamWidget::draw(const DrawArgs& args) {
	Widget::draw(args);

	// Param map indicator
	engine::ParamHandle* paramHandle = paramQuantity ? APP->engine->getParamHandle(paramQuantity->module->id, paramQuantity->paramId) : NULL;
	if (paramHandle) {
		NVGcolor color = paramHandle->color;
		nvgBeginPath(args.vg);
		const float radius = 6;
		// nvgCircle(args.vg, box.size.x / 2, box.size.y / 2, radius);
		nvgRect(args.vg, box.size.x - radius, box.size.y - radius, radius, radius);
		nvgFillColor(args.vg, color);
		nvgFill(args.vg);
		nvgStrokeColor(args.vg, color::mult(color, 0.5));
		nvgStrokeWidth(args.vg, 1.0);
		nvgStroke(args.vg);
	}
}

void ParamWidget::onButton(const event::Button& e) {
	OpaqueWidget::onButton(e);

	// Touch parameter
	if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_LEFT && (e.mods & RACK_MOD_MASK) == 0) {
		if (paramQuantity) {
			APP->scene->rack->touchedParam = this;
		}
		e.consume(this);
	}

	// Right click to open context menu
	if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT && (e.mods & RACK_MOD_MASK) == 0) {
		createContextMenu();
		e.consume(this);
	}
}

void ParamWidget::onDoubleClick(const event::DoubleClick& e) {
	resetAction();
}

void ParamWidget::onEnter(const event::Enter& e) {
	if (settings::paramTooltip && !tooltip && paramQuantity) {
		ParamTooltip* paramTooltip = new ParamTooltip;
		paramTooltip->paramWidget = this;
		APP->scene->addChild(paramTooltip);
		tooltip = paramTooltip;
	}
}

void ParamWidget::onLeave(const event::Leave& e) {
	if (tooltip) {
		APP->scene->removeChild(tooltip);
		delete tooltip;
		tooltip = NULL;
	}
}

void ParamWidget::fromJson(json_t* rootJ) {
	json_t* valueJ = json_object_get(rootJ, "value");
	if (valueJ) {
		if (paramQuantity)
			paramQuantity->setValue(json_number_value(valueJ));
	}
}

void ParamWidget::createContextMenu() {
	ui::Menu* menu = createMenu();

	ParamLabel* paramLabel = new ParamLabel;
	paramLabel->paramWidget = this;
	menu->addChild(paramLabel);

	ParamField* paramField = new ParamField;
	paramField->box.size.x = 100;
	paramField->setParamWidget(this);
	menu->addChild(paramField);

	ParamResetItem* resetItem = new ParamResetItem;
	resetItem->text = "Initialize";
	resetItem->rightText = "Double-click";
	resetItem->paramWidget = this;
	menu->addChild(resetItem);

	// ParamFineItem *fineItem = new ParamFineItem;
	// fineItem->text = "Fine adjust";
	// fineItem->rightText = RACK_MOD_CTRL_NAME "+drag";
	// fineItem->disabled = true;
	// menu->addChild(fineItem);

	engine::ParamHandle* paramHandle = paramQuantity ? APP->engine->getParamHandle(paramQuantity->module->id, paramQuantity->paramId) : NULL;
	if (paramHandle) {
		ParamUnmapItem* unmapItem = new ParamUnmapItem;
		unmapItem->text = "Unmap";
		unmapItem->rightText = paramHandle->text;
		unmapItem->paramWidget = this;
		menu->addChild(unmapItem);
	}
}

void ParamWidget::resetAction() {
	if (paramQuantity && paramQuantity->isBounded()) {
		float oldValue = paramQuantity->getValue();
		reset();
		// Here's another way of doing it, but either works.
		// paramQuantity->getParam()->reset();
		float newValue = paramQuantity->getValue();

		if (oldValue != newValue) {
			// Push ParamChange history action
			history::ParamChange* h = new history::ParamChange;
			h->name = "reset parameter";
			h->moduleId = paramQuantity->module->id;
			h->paramId = paramQuantity->paramId;
			h->oldValue = oldValue;
			h->newValue = newValue;
			APP->history->push(h);
		}
	}
}

} // namespace app
} // namespace rack
<commit_msg>Nudge ParamTooltip inside parent.<commit_after>#include <app/ParamWidget.hpp>
#include <ui/MenuOverlay.hpp>
#include <ui/TextField.hpp>
#include <app/Scene.hpp>
#include <app.hpp>
#include <engine/Engine.hpp>
#include <settings.hpp>
#include <history.hpp>
#include <helpers.hpp>

namespace rack {
namespace app {

struct ParamField : ui::TextField {
	ParamWidget* paramWidget;

	void step() override {
		// Keep selected
		APP->event->setSelected(this);
		TextField::step();
	}

	void setParamWidget(ParamWidget* paramWidget) {
		this->paramWidget = paramWidget;
		if (paramWidget->paramQuantity)
			text = paramWidget->paramQuantity->getDisplayValueString();
		selectAll();
	}

	void onSelectKey(const event::SelectKey& e) override {
		if (e.action == GLFW_PRESS && (e.key == GLFW_KEY_ENTER || e.key == GLFW_KEY_KP_ENTER)) {
			float oldValue = paramWidget->paramQuantity->getValue();
			if (paramWidget->paramQuantity)
				paramWidget->paramQuantity->setDisplayValueString(text);
			float newValue = paramWidget->paramQuantity->getValue();

			if (oldValue != newValue) {
				// Push ParamChange history action
				history::ParamChange* h = new history::ParamChange;
				h->moduleId = paramWidget->paramQuantity->module->id;
				h->paramId = paramWidget->paramQuantity->paramId;
				h->oldValue = oldValue;
				h->newValue = newValue;
				APP->history->push(h);
			}

			ui::MenuOverlay* overlay = getAncestorOfType<ui::MenuOverlay>();
			overlay->requestDelete();
			e.consume(this);
		}

		if (!e.getTarget())
			TextField::onSelectKey(e);
	}
};

struct ParamTooltip : ui::Tooltip {
	ParamWidget* paramWidget;

	void step() override {
		if (paramWidget->paramQuantity) {
			// Quantity string
			text = paramWidget->paramQuantity->getString();
			// Param description
			std::string description = paramWidget->paramQuantity->description;
			if (!description.empty())
				text += "\n" + description;
		}
		Tooltip::step();
		// Position at bottom-right of parameter
		box.pos = paramWidget->getAbsoluteOffset(paramWidget->box.size).round();
		// Fit inside parent (copied from Tooltip.cpp)
		assert(parent);
		box = box.nudge(parent->box.zeroPos());
	}
};

struct ParamLabel : ui::MenuLabel {
	ParamWidget* paramWidget;
	void step() override {
		text = paramWidget->paramQuantity->getString();
		MenuLabel::step();
	}
};

struct ParamResetItem : ui::MenuItem {
	ParamWidget* paramWidget;
	void onAction(const event::Action& e) override {
		paramWidget->resetAction();
	}
};

struct ParamFineItem : ui::MenuItem {
};

struct ParamUnmapItem : ui::MenuItem {
	ParamWidget* paramWidget;
	void onAction(const event::Action& e) override {
		engine::ParamHandle* paramHandle = APP->engine->getParamHandle(paramWidget->paramQuantity->module->id, paramWidget->paramQuantity->paramId);
		if (paramHandle) {
			APP->engine->updateParamHandle(paramHandle, -1, 0);
		}
	}
};

void ParamWidget::step() {
	if (paramQuantity) {
		float value = paramQuantity->getValue();
		// Trigger change event when paramQuantity value changes
		if (value != dirtyValue) {
			dirtyValue = value;
			event::Change eChange;
			onChange(eChange);
		}
	}

	Widget::step();
}

void ParamWidget::draw(const DrawArgs& args) {
	Widget::draw(args);

	// Param map indicator
	engine::ParamHandle* paramHandle = paramQuantity ? APP->engine->getParamHandle(paramQuantity->module->id, paramQuantity->paramId) : NULL;
	if (paramHandle) {
		NVGcolor color = paramHandle->color;
		nvgBeginPath(args.vg);
		const float radius = 6;
		// nvgCircle(args.vg, box.size.x / 2, box.size.y / 2, radius);
		nvgRect(args.vg, box.size.x - radius, box.size.y - radius, radius, radius);
		nvgFillColor(args.vg, color);
		nvgFill(args.vg);
		nvgStrokeColor(args.vg, color::mult(color, 0.5));
		nvgStrokeWidth(args.vg, 1.0);
		nvgStroke(args.vg);
	}
}

void ParamWidget::onButton(const event::Button& e) {
	OpaqueWidget::onButton(e);

	// Touch parameter
	if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_LEFT && (e.mods & RACK_MOD_MASK) == 0) {
		if (paramQuantity) {
			APP->scene->rack->touchedParam = this;
		}
		e.consume(this);
	}

	// Right click to open context menu
	if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT && (e.mods & RACK_MOD_MASK) == 0) {
		createContextMenu();
		e.consume(this);
	}
}

void ParamWidget::onDoubleClick(const event::DoubleClick& e) {
	resetAction();
}

void ParamWidget::onEnter(const event::Enter& e) {
	if (settings::paramTooltip && !tooltip && paramQuantity) {
		ParamTooltip* paramTooltip = new ParamTooltip;
		paramTooltip->paramWidget = this;
		APP->scene->addChild(paramTooltip);
		tooltip = paramTooltip;
	}
}

void ParamWidget::onLeave(const event::Leave& e) {
	if (tooltip) {
		APP->scene->removeChild(tooltip);
		delete tooltip;
		tooltip = NULL;
	}
}

void ParamWidget::fromJson(json_t* rootJ) {
	json_t* valueJ = json_object_get(rootJ, "value");
	if (valueJ) {
		if (paramQuantity)
			paramQuantity->setValue(json_number_value(valueJ));
	}
}

void ParamWidget::createContextMenu() {
	ui::Menu* menu = createMenu();

	ParamLabel* paramLabel = new ParamLabel;
	paramLabel->paramWidget = this;
	menu->addChild(paramLabel);

	ParamField* paramField = new ParamField;
	paramField->box.size.x = 100;
	paramField->setParamWidget(this);
	menu->addChild(paramField);

	ParamResetItem* resetItem = new ParamResetItem;
	resetItem->text = "Initialize";
	resetItem->rightText = "Double-click";
	resetItem->paramWidget = this;
	menu->addChild(resetItem);

	// ParamFineItem *fineItem = new ParamFineItem;
	// fineItem->text = "Fine adjust";
	// fineItem->rightText = RACK_MOD_CTRL_NAME "+drag";
	// fineItem->disabled = true;
	// menu->addChild(fineItem);

	engine::ParamHandle* paramHandle = paramQuantity ? APP->engine->getParamHandle(paramQuantity->module->id, paramQuantity->paramId) : NULL;
	if (paramHandle) {
		ParamUnmapItem* unmapItem = new ParamUnmapItem;
		unmapItem->text = "Unmap";
		unmapItem->rightText = paramHandle->text;
		unmapItem->paramWidget = this;
		menu->addChild(unmapItem);
	}
}

void ParamWidget::resetAction() {
	if (paramQuantity && paramQuantity->isBounded()) {
		float oldValue = paramQuantity->getValue();
		reset();
		// Here's another way of doing it, but either works.
		// paramQuantity->getParam()->reset();
		float newValue = paramQuantity->getValue();

		if (oldValue != newValue) {
			// Push ParamChange history action
			history::ParamChange* h = new history::ParamChange;
			h->name = "reset parameter";
			h->moduleId = paramQuantity->module->id;
			h->paramId = paramQuantity->paramId;
			h->oldValue = oldValue;
			h->newValue = newValue;
			APP->history->push(h);
		}
	}
}

} // namespace app
} // namespace rack
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "proxyobject_p.h"
#include "qmetaobjectbuilder_p.h"

#include <QDebug>

QTM_BEGIN_NAMESPACE

class QServiceProxyPrivate
{
public:
    QByteArray metadata;
    QMetaObject* meta;
    ObjectEndPoint* endPoint;
};

QServiceProxy::QServiceProxy(const QByteArray& metadata, ObjectEndPoint* endPoint, QObject* parent)
    : QObject(parent)
{
    Q_ASSERT(endPoint);
    d = new QServiceProxyPrivate();
    d->metadata = metadata;
    d->meta = 0;
    d->endPoint = endPoint;

    QDataStream stream(d->metadata);
    QMetaObjectBuilder builder;
    QMap<QByteArray, const QMetaObject*> refs;

    builder.deserialize(stream, refs);
    if (stream.status() != QDataStream::Ok) {
        qWarning() << "Invalid metaObject for service received";
    } else {
        QMetaMethodBuilder b = builder.addSignal("errorUnrecoverableIPCFault(QService::UnrecoverableIPCError)");

        // After all methods are filled in, otherwise qvector won't be big enough
        localSignals.fill(false, builder.methodCount());
        localSignals.replace(b.index(), true); // Call activate locally

        d->meta = builder.toMetaObject();
        qWarning() << "Proxy object for" << d->meta->className() << "created.";
    }
}

QServiceProxy::~QServiceProxy()
{
    if (d->meta)
        delete d->meta;
    delete d;
}

//provide custom Q_OBJECT implementation
const QMetaObject* QServiceProxy::metaObject() const
{
    return d->meta;
}

int QServiceProxy::qt_metacall(QMetaObject::Call c, int id, void **a)
{
    id = QObject::qt_metacall(c, id, a);
    if (id < 0 || !d->meta)
        return id;

    if(localSignals.at(id)){
      QMetaObject::activate(this, d->meta, id, a);
      return;
    }

    if (c == QMetaObject::InvokeMetaMethod) {
        const int mcount = d->meta->methodCount() - d->meta->methodOffset();
        const int metaIndex = id + d->meta->methodOffset();

        QMetaMethod method = d->meta->method(metaIndex);

        const int returnType = QMetaType::type(method.typeName());

        //process arguments
        const QList<QByteArray> pTypes = method.parameterTypes();
        const int pTypesCount = pTypes.count();
        QVariantList args ;
        if (pTypesCount > 10) {
            qWarning() << "Cannot call" << method.signature() << ". More than 10 parameter.";
            return id;
        }
        for (int i=0; i < pTypesCount; i++) {
            const QByteArray& t = pTypes[i];

            int variantType = QVariant::nameToType(t);
            if (variantType == QVariant::UserType)
                variantType = QMetaType::type(t);

            if (t == "QVariant") {  //ignore whether QVariant is declared as metatype
                args << *reinterpret_cast<const QVariant(*)>(a[i+1]);
            } else if ( variantType == 0 ){
                qWarning("%s: argument %s has unknown type. Use qRegisterMetaType to register it.",
                        method.signature(), t.data());
                return id;
            } else {
                args << QVariant(variantType, a[i+1]);
            }
        }

        //QVariant looks the same as Void type. we need to distinguish them
        if (returnType == QMetaType::Void && strcmp(method.typeName(),"QVariant") ) {
            d->endPoint->invokeRemote(metaIndex, args, returnType);
        } else {
            //TODO: ugly but works
            //add +1 if we have a variant return type to avoid triggering of void
            //code path
            //invokeRemote() parameter list needs review
            QVariant result = d->endPoint->invokeRemote(metaIndex, args,
                    returnType==0 ? returnType+1: returnType);
            if (returnType != 0 && strcmp(method.typeName(),"QVariant")) {
                QByteArray buffer;
                QDataStream stream(&buffer, QIODevice::ReadWrite);
                QMetaType::save(stream, returnType, result.constData());
                stream.device()->seek(0);
                QMetaType::load(stream, returnType, a[0]);
            } else {
                if (a[0]) *reinterpret_cast< QVariant*>(a[0]) = result;
            }
        }
        id-=mcount;
    } else if ( c == QMetaObject::ReadProperty
            || c == QMetaObject::WriteProperty
            || c == QMetaObject::ResetProperty ) {
        const int pCount = d->meta->propertyCount() - d->meta->propertyOffset();
        const int metaIndex = id + d->meta->propertyOffset();
        QMetaProperty property = d->meta->property(metaIndex);
        if (property.isValid()) {
            int pType = property.type();
            if (pType == QVariant::UserType)
                pType = QMetaType::type(property.typeName());

            QVariant arg;
            if ( c == QMetaObject::WriteProperty ) {
                if (pType == QVariant::Invalid && QByteArray(property.typeName()) == "QVariant")
                    arg =  *reinterpret_cast<const QVariant(*)>(a[0]);
                else if (pType == 0) {
                    qWarning("%s: property %s has unkown type", property.name(), property.typeName());
                    return id;
                } else {
                    arg = QVariant(pType, a[0]);
                }
            }
            QVariant result;
            if (c == QMetaObject::ReadProperty) {
                result = d->endPoint->invokeRemoteProperty(metaIndex, arg, pType, c);
                //wrap result for client
                if (pType != 0) {
                    QByteArray buffer;
                    QDataStream stream(&buffer, QIODevice::ReadWrite);
                    QMetaType::save(stream, pType, result.constData());
                    stream.device()->seek(0);
                    QMetaType::load(stream, pType, a[0]);
                } else {
                    if (a[0]) *reinterpret_cast< QVariant*>(a[0]) = result;
                }
            } else {
                d->endPoint->invokeRemoteProperty(metaIndex, arg, pType, c);
            }
        }
        id-=pCount;
    } else if ( c == QMetaObject::QueryPropertyDesignable
            || c == QMetaObject::QueryPropertyScriptable
            || c == QMetaObject::QueryPropertyStored
            || c == QMetaObject::QueryPropertyEditable
            || c == QMetaObject::QueryPropertyUser )
    {
        //Nothing to do?
        //These values are part of the transferred meta object already
    } else {
        //TODO
        qWarning() << "MetaCall type" << c << "not yet handled";
    }
    return id;
}

void *QServiceProxy::qt_metacast(const char* className)
{
    if (!className) return 0;
    //this object should not be castable to anything but QObject
    return QObject::qt_metacast(className);
}
QTM_END_NAMESPACE
<commit_msg>Fix return typo<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "proxyobject_p.h"
#include "qmetaobjectbuilder_p.h"

#include <QDebug>

QTM_BEGIN_NAMESPACE

class QServiceProxyPrivate
{
public:
    QByteArray metadata;
    QMetaObject* meta;
    ObjectEndPoint* endPoint;
};

QServiceProxy::QServiceProxy(const QByteArray& metadata, ObjectEndPoint* endPoint, QObject* parent)
    : QObject(parent)
{
    Q_ASSERT(endPoint);
    d = new QServiceProxyPrivate();
    d->metadata = metadata;
    d->meta = 0;
    d->endPoint = endPoint;

    QDataStream stream(d->metadata);
    QMetaObjectBuilder builder;
    QMap<QByteArray, const QMetaObject*> refs;

    builder.deserialize(stream, refs);
    if (stream.status() != QDataStream::Ok) {
        qWarning() << "Invalid metaObject for service received";
    } else {
        QMetaMethodBuilder b = builder.addSignal("errorUnrecoverableIPCFault(QService::UnrecoverableIPCError)");

        // After all methods are filled in, otherwise qvector won't be big enough
        localSignals.fill(false, builder.methodCount());
        localSignals.replace(b.index(), true); // Call activate locally

        d->meta = builder.toMetaObject();
        qWarning() << "Proxy object for" << d->meta->className() << "created.";
    }
}

QServiceProxy::~QServiceProxy()
{
    if (d->meta)
        delete d->meta;
    delete d;
}

//provide custom Q_OBJECT implementation
const QMetaObject* QServiceProxy::metaObject() const
{
    return d->meta;
}

int QServiceProxy::qt_metacall(QMetaObject::Call c, int id, void **a)
{
    id = QObject::qt_metacall(c, id, a);
    if (id < 0 || !d->meta)
        return id;

    if(localSignals.at(id)){
      QMetaObject::activate(this, d->meta, id, a);
      return id;
    }

    if (c == QMetaObject::InvokeMetaMethod) {
        const int mcount = d->meta->methodCount() - d->meta->methodOffset();
        const int metaIndex = id + d->meta->methodOffset();

        QMetaMethod method = d->meta->method(metaIndex);

        const int returnType = QMetaType::type(method.typeName());

        //process arguments
        const QList<QByteArray> pTypes = method.parameterTypes();
        const int pTypesCount = pTypes.count();
        QVariantList args ;
        if (pTypesCount > 10) {
            qWarning() << "Cannot call" << method.signature() << ". More than 10 parameter.";
            return id;
        }
        for (int i=0; i < pTypesCount; i++) {
            const QByteArray& t = pTypes[i];

            int variantType = QVariant::nameToType(t);
            if (variantType == QVariant::UserType)
                variantType = QMetaType::type(t);

            if (t == "QVariant") {  //ignore whether QVariant is declared as metatype
                args << *reinterpret_cast<const QVariant(*)>(a[i+1]);
            } else if ( variantType == 0 ){
                qWarning("%s: argument %s has unknown type. Use qRegisterMetaType to register it.",
                        method.signature(), t.data());
                return id;
            } else {
                args << QVariant(variantType, a[i+1]);
            }
        }

        //QVariant looks the same as Void type. we need to distinguish them
        if (returnType == QMetaType::Void && strcmp(method.typeName(),"QVariant") ) {
            d->endPoint->invokeRemote(metaIndex, args, returnType);
        } else {
            //TODO: ugly but works
            //add +1 if we have a variant return type to avoid triggering of void
            //code path
            //invokeRemote() parameter list needs review
            QVariant result = d->endPoint->invokeRemote(metaIndex, args,
                    returnType==0 ? returnType+1: returnType);
            if (returnType != 0 && strcmp(method.typeName(),"QVariant")) {
                QByteArray buffer;
                QDataStream stream(&buffer, QIODevice::ReadWrite);
                QMetaType::save(stream, returnType, result.constData());
                stream.device()->seek(0);
                QMetaType::load(stream, returnType, a[0]);
            } else {
                if (a[0]) *reinterpret_cast< QVariant*>(a[0]) = result;
            }
        }
        id-=mcount;
    } else if ( c == QMetaObject::ReadProperty
            || c == QMetaObject::WriteProperty
            || c == QMetaObject::ResetProperty ) {
        const int pCount = d->meta->propertyCount() - d->meta->propertyOffset();
        const int metaIndex = id + d->meta->propertyOffset();
        QMetaProperty property = d->meta->property(metaIndex);
        if (property.isValid()) {
            int pType = property.type();
            if (pType == QVariant::UserType)
                pType = QMetaType::type(property.typeName());

            QVariant arg;
            if ( c == QMetaObject::WriteProperty ) {
                if (pType == QVariant::Invalid && QByteArray(property.typeName()) == "QVariant")
                    arg =  *reinterpret_cast<const QVariant(*)>(a[0]);
                else if (pType == 0) {
                    qWarning("%s: property %s has unkown type", property.name(), property.typeName());
                    return id;
                } else {
                    arg = QVariant(pType, a[0]);
                }
            }
            QVariant result;
            if (c == QMetaObject::ReadProperty) {
                result = d->endPoint->invokeRemoteProperty(metaIndex, arg, pType, c);
                //wrap result for client
                if (pType != 0) {
                    QByteArray buffer;
                    QDataStream stream(&buffer, QIODevice::ReadWrite);
                    QMetaType::save(stream, pType, result.constData());
                    stream.device()->seek(0);
                    QMetaType::load(stream, pType, a[0]);
                } else {
                    if (a[0]) *reinterpret_cast< QVariant*>(a[0]) = result;
                }
            } else {
                d->endPoint->invokeRemoteProperty(metaIndex, arg, pType, c);
            }
        }
        id-=pCount;
    } else if ( c == QMetaObject::QueryPropertyDesignable
            || c == QMetaObject::QueryPropertyScriptable
            || c == QMetaObject::QueryPropertyStored
            || c == QMetaObject::QueryPropertyEditable
            || c == QMetaObject::QueryPropertyUser )
    {
        //Nothing to do?
        //These values are part of the transferred meta object already
    } else {
        //TODO
        qWarning() << "MetaCall type" << c << "not yet handled";
    }
    return id;
}

void *QServiceProxy::qt_metacast(const char* className)
{
    if (!className) return 0;
    //this object should not be castable to anything but QObject
    return QObject::qt_metacast(className);
}
QTM_END_NAMESPACE
<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 1999-2011 Soeren Sonnenburg
 * Written (W) 2012 Fernando José Iglesias García and Sergey Lisitsyn
 * Copyright (C) 2012 Sergey Lisitsyn, Fernando José Iglesias Garcia
 */

#include <shogun/multiclass/MulticlassOneVsRestStrategy.h>
#include <shogun/machine/MulticlassMachine.h>
#include <shogun/base/Parameter.h>
#include <shogun/features/Labels.h>

using namespace shogun;

CMulticlassMachine::CMulticlassMachine()
: CMachine(), m_multiclass_strategy(new CMulticlassOneVsRestStrategy()),
	m_machine(NULL), m_machines(new CDynamicObjectArray())
{
	SG_REF(m_multiclass_strategy);
	register_parameters();
}

CMulticlassMachine::CMulticlassMachine(
		CMulticlassStrategy *strategy,
		CMachine* machine, CLabels* labs)
: CMachine(), m_multiclass_strategy(strategy),
	m_machines(new CDynamicObjectArray())
{
	SG_REF(strategy);
	set_labels(labs);
	SG_REF(machine);
	m_machine = machine;
	register_parameters();

    if (labs)
        init_strategy();
}

CMulticlassMachine::~CMulticlassMachine()
{
	SG_UNREF(m_multiclass_strategy);
	SG_UNREF(m_machine);
	SG_UNREF(m_machines);
}

void CMulticlassMachine::set_labels(CLabels* lab)
{
    CMachine::set_labels(lab);
    if (lab)
        init_strategy();
}

void CMulticlassMachine::register_parameters()
{
	SG_ADD((CSGObject**)&m_multiclass_strategy,"m_multiclass_type", "Multiclass strategy", MS_NOT_AVAILABLE);
	SG_ADD((CSGObject**)&m_machine, "m_machine", "The base machine", MS_NOT_AVAILABLE);
	SG_ADD((CSGObject**)&m_machines, "machines", "Machines that jointly make up the multi-class machine.", MS_NOT_AVAILABLE);
}

void CMulticlassMachine::init_strategy()
{
    int32_t num_classes = m_labels->get_num_classes();
    m_multiclass_strategy->set_num_classes(num_classes);
}

CLabels* CMulticlassMachine::apply(CFeatures* features)
{
	init_machines_for_apply(features);
	return apply();
}

CLabels* CMulticlassMachine::apply()
{
	/** Ensure that m_machines have the features set */
	init_machines_for_apply(NULL);

	if (is_ready())
	{
		int32_t num_vectors=get_num_rhs_vectors();
		int32_t num_machines=m_machines->get_num_elements();
		if (num_machines <= 0)
			SG_ERROR("num_machines = %d, did you train your machine?", num_machines);

		CLabels *result=new CLabels(num_vectors);
		CLabels **outputs=SG_MALLOC(CLabels*, num_machines);

		for (int32_t i=0; i < num_machines; ++i)
		{
			CMachine *machine = (CMachine*)m_machines->get_element(i);
			ASSERT(machine);
			outputs[i]=machine->apply();
			SG_UNREF(machine);
		}

		SGVector<float64_t> output_for_i(num_machines);
		for (int32_t i=0; i<num_vectors; i++)
		{
			for (int32_t j=0; j<num_machines; j++)
				output_for_i[j] = outputs[j]->get_label(i);

			result->set_label(i, m_multiclass_strategy->decide_label(output_for_i));
		}

		for (int32_t i=0; i < num_machines; ++i)
			SG_UNREF(outputs[i]);

		SG_FREE(outputs);

		return result;
	}
	else
	{
		return NULL;
	}
}

bool CMulticlassMachine::train_machine(CFeatures* data)
{
	ASSERT(m_multiclass_strategy);

	if ( !data && !is_ready() )
		SG_ERROR("Please provide training data.\n");
	else
		init_machine_for_train(data);

	m_machines->clear_array();
	CLabels *train_labels = new CLabels(get_num_rhs_vectors());
	SG_REF(train_labels);
	m_machine->set_labels(train_labels);

	m_multiclass_strategy->train_start(m_labels, train_labels);
	while (m_multiclass_strategy->train_has_more())
	{
		SGVector<index_t> subset=m_multiclass_strategy->train_prepare_next();
		if (subset.vlen)
		{
			train_labels->add_subset(subset);
			add_machine_subset(subset);
		}

		m_machine->train();
		m_machines->push_back(get_machine_from_trained(m_machine));

		if (subset.vlen)
		{
			train_labels->remove_subset();
			remove_machine_subset();
		}
	}

	m_multiclass_strategy->train_stop();
	SG_UNREF(train_labels);

	return true;
}

float64_t CMulticlassMachine::apply(int32_t num)
{
	init_machines_for_apply(NULL);

	ASSERT(m_machines->get_num_elements()>0);
	SGVector<float64_t> outputs(m_machines->get_num_elements());

	for (int32_t i=0; i < m_machines->get_num_elements(); ++i)
	{
		CMachine *machine = get_machine(i);
		outputs[i]=machine->apply(num);
		SG_UNREF(machine);
	}

	float64_t result=m_multiclass_strategy->decide_label(outputs);

	return result;
}

<commit_msg>minor whitespace changes<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 1999-2011 Soeren Sonnenburg
 * Written (W) 2012 Fernando José Iglesias García and Sergey Lisitsyn
 * Copyright (C) 2012 Sergey Lisitsyn, Fernando José Iglesias Garcia
 */

#include <shogun/multiclass/MulticlassOneVsRestStrategy.h>
#include <shogun/machine/MulticlassMachine.h>
#include <shogun/base/Parameter.h>
#include <shogun/features/Labels.h>

using namespace shogun;

CMulticlassMachine::CMulticlassMachine()
: CMachine(), m_multiclass_strategy(new CMulticlassOneVsRestStrategy()),
	m_machine(NULL), m_machines(new CDynamicObjectArray())
{
	SG_REF(m_multiclass_strategy);
	register_parameters();
}

CMulticlassMachine::CMulticlassMachine(
		CMulticlassStrategy *strategy,
		CMachine* machine, CLabels* labs)
: CMachine(), m_multiclass_strategy(strategy),
	m_machines(new CDynamicObjectArray())
{
	SG_REF(strategy);
	set_labels(labs);
	SG_REF(machine);
	m_machine = machine;
	register_parameters();

    if (labs)
        init_strategy();
}

CMulticlassMachine::~CMulticlassMachine()
{
	SG_UNREF(m_multiclass_strategy);
	SG_UNREF(m_machine);
	SG_UNREF(m_machines);
}

void CMulticlassMachine::set_labels(CLabels* lab)
{
    CMachine::set_labels(lab);
    if (lab)
        init_strategy();
}

void CMulticlassMachine::register_parameters()
{
	SG_ADD((CSGObject**)&m_multiclass_strategy,"m_multiclass_type", "Multiclass strategy", MS_NOT_AVAILABLE);
	SG_ADD((CSGObject**)&m_machine, "m_machine", "The base machine", MS_NOT_AVAILABLE);
	SG_ADD((CSGObject**)&m_machines, "machines", "Machines that jointly make up the multi-class machine.", MS_NOT_AVAILABLE);
}

void CMulticlassMachine::init_strategy()
{
    int32_t num_classes = m_labels->get_num_classes();
    m_multiclass_strategy->set_num_classes(num_classes);
}

CLabels* CMulticlassMachine::apply(CFeatures* features)
{
	init_machines_for_apply(features);
	return apply();
}

CLabels* CMulticlassMachine::apply()
{
	/** Ensure that m_machines have the features set */
	init_machines_for_apply(NULL);

	if (is_ready())
	{
		int32_t num_vectors=get_num_rhs_vectors();
		int32_t num_machines=m_machines->get_num_elements();
		if (num_machines <= 0)
			SG_ERROR("num_machines = %d, did you train your machine?", num_machines);

		CLabels* result=new CLabels(num_vectors);
		CLabels** outputs=SG_MALLOC(CLabels*, num_machines);

		for (int32_t i=0; i < num_machines; ++i)
		{
			CMachine *machine = (CMachine*)m_machines->get_element(i);
			ASSERT(machine);
			outputs[i]=machine->apply();
			SG_UNREF(machine);
		}

		SGVector<float64_t> output_for_i(num_machines);
		for (int32_t i=0; i<num_vectors; i++)
		{
			for (int32_t j=0; j<num_machines; j++)
				output_for_i[j] = outputs[j]->get_label(i);

			result->set_label(i, m_multiclass_strategy->decide_label(output_for_i));
		}

		for (int32_t i=0; i < num_machines; ++i)
			SG_UNREF(outputs[i]);

		SG_FREE(outputs);

		return result;
	}
	else
	{
		return NULL;
	}
}

bool CMulticlassMachine::train_machine(CFeatures* data)
{
	ASSERT(m_multiclass_strategy);

	if ( !data && !is_ready() )
		SG_ERROR("Please provide training data.\n");
	else
		init_machine_for_train(data);

	m_machines->clear_array();
	CLabels *train_labels = new CLabels(get_num_rhs_vectors());
	SG_REF(train_labels);
	m_machine->set_labels(train_labels);

	m_multiclass_strategy->train_start(m_labels, train_labels);
	while (m_multiclass_strategy->train_has_more())
	{
		SGVector<index_t> subset=m_multiclass_strategy->train_prepare_next();
		if (subset.vlen)
		{
			train_labels->add_subset(subset);
			add_machine_subset(subset);
		}

		m_machine->train();
		m_machines->push_back(get_machine_from_trained(m_machine));

		if (subset.vlen)
		{
			train_labels->remove_subset();
			remove_machine_subset();
		}
	}

	m_multiclass_strategy->train_stop();
	SG_UNREF(train_labels);

	return true;
}

float64_t CMulticlassMachine::apply(int32_t num)
{
	init_machines_for_apply(NULL);

	ASSERT(m_machines->get_num_elements()>0);
	SGVector<float64_t> outputs(m_machines->get_num_elements());

	for (int32_t i=0; i < m_machines->get_num_elements(); ++i)
	{
		CMachine *machine = get_machine(i);
		outputs[i]=machine->apply(num);
		SG_UNREF(machine);
	}

	float64_t result=m_multiclass_strategy->decide_label(outputs);

	return result;
}

<|endoftext|>