diff --git a/src/apex/genetic_search.cpp b/src/apex/genetic_search.cpp new file mode 100644 index 00000000..40b18158 --- /dev/null +++ b/src/apex/genetic_search.cpp @@ -0,0 +1,85 @@ +#include "genetic_search.hpp" +#include +#include +#include +#include + +namespace apex { + +namespace random { + +double inline myrand() { + return ((double) rand() / (RAND_MAX)); +} + +size_t GeneticSearch::get_max_iterations() { + size_t max_iter{1}; + for (auto& v : vars) { + switch (v.second.vtype) { + case VariableType::doubletype: { + max_iter = max_iter * v.second.dvalues.size(); + break; + } + case VariableType::longtype: { + max_iter = max_iter * v.second.lvalues.size(); + break; + } + case VariableType::stringtype: { + max_iter = max_iter * v.second.svalues.size(); + break; + } + default: { + break; + } + } + } + // want to see multiple values of each one + //return max_iter; + return std::min(max_iterations, (std::max(min_iterations, max_iter))); +} + +class log_wrapper { + private: + std::ofstream myfile; + public: + log_wrapper(const std::map& vars) { + myfile.open("tuning.csv"); + myfile << "iter,"; + for (auto& v : vars) { myfile << v.first << ","; } + myfile << "time" << std::endl; + } + ~log_wrapper() { + myfile.close(); + } + std::ofstream& getstream() { + return myfile; + } +}; + +void GeneticSearch::evaluate(double new_cost) { + static log_wrapper log(vars); + static size_t count{0}; + if (++count % 10000 == 0) { std::cout << count << std::endl; } + log.getstream() << count << ","; + for (auto& v : vars) { log.getstream() << v.second.toString() << ","; } + log.getstream() << new_cost << std::endl; + if (new_cost < cost) { + if (new_cost < best_cost) { + best_cost = new_cost; + std::cout << "New best! " << new_cost << " k: " << k; + for (auto& v : vars) { v.second.save_best(); } + for (auto& v : vars) { std::cout << ", value: " << v.second.toString(); } + std::cout << std::endl; + } + cost = new_cost; + } + //for (auto& v : vars) { v.second.choose_neighbor(); } + k++; + return; +} + +} // random + +} // apex + + diff --git a/src/apex/genetic_search.hpp b/src/apex/genetic_search.hpp new file mode 100644 index 00000000..cde3beb3 --- /dev/null +++ b/src/apex/genetic_search.hpp @@ -0,0 +1,132 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "apex_types.h" +#include "apex_assert.h" + +namespace apex { + +namespace random { + +enum class VariableType { doubletype, longtype, stringtype } ; + +class Variable { +public: + std::vector dvalues; + std::vector lvalues; + std::vector svalues; + VariableType vtype; + size_t current_index; + size_t best_index; + void * value; // for the client to get the values + size_t maxlen; + Variable () = delete; + Variable (VariableType vtype, void * ptr) : vtype(vtype), current_index(0), + best_index(0), value(ptr), maxlen(0) { } + void set_current_value() { + if (vtype == VariableType::doubletype) { + *((double*)(value)) = dvalues[current_index]; + } + else if (vtype == VariableType::longtype) { + *((long*)(value)) = lvalues[current_index]; + } + else { + *((const char**)(value)) = svalues[current_index].c_str(); + } + } + size_t get_next_neighbor() { + current_index = (rand() % maxlen); + APEX_ASSERT(current_index < maxlen); + set_current_value(); + return current_index; + } + void save_best() { best_index = current_index; } + void set_init() { + maxlen = (std::max(std::max(dvalues.size(), + lvalues.size()), svalues.size())) - 1; + current_index = 0; + set_current_value(); + } + std::string getBest() { + if (vtype == VariableType::doubletype) { + *((double*)(value)) = dvalues[best_index]; + return std::to_string(dvalues[best_index]); + } + else if (vtype == VariableType::longtype) { + *((long*)(value)) = lvalues[best_index]; + return std::to_string(lvalues[best_index]); + } + //else if (vtype == VariableType::stringtype) { + *((const char**)(value)) = svalues[best_index].c_str(); + return svalues[best_index]; + } + std::string toString() { + if (vtype == VariableType::doubletype) { + return std::to_string(dvalues[current_index]); + } + else if (vtype == VariableType::longtype) { + return std::to_string(lvalues[current_index]); + } + //else if (vtype == VariableType::stringtype) { + return svalues[current_index]; + //} + } +}; + +class GeneticSearch { +private: + double cost; + double best_cost; + size_t kmax; + size_t k; + std::map vars; + const size_t max_iterations{1000}; + const size_t min_iterations{100}; +public: + void evaluate(double new_cost); + GeneticSearch() : + kmax(0), k(1) { + cost = std::numeric_limits::max(); + best_cost = cost; + //std::cout << "New Session!" << std::endl; + //srand (1); + srand (time(NULL)); + } + double getEnergy() { return best_cost; } + bool converged() { return (k > kmax); } + void getNewSettings() { + /* Increment neighbour */ + for (auto& v : vars) { v.second.get_next_neighbor(); } + } + void saveBestSettings() { + for (auto& v : vars) { v.second.getBest(); } + } + void printBestSettings() { + std::string d("["); + for (auto v : vars) { + std::cout << d << v.second.getBest(); + d = ","; + } + std::cout << "]" << std::endl; + } + size_t get_max_iterations(); + std::map& get_vars() { return vars; } + void add_var(std::string name, Variable var) { + vars.insert(std::make_pair(name, var)); + kmax = get_max_iterations(); + /* get max iterations */ + //std::cout << "Max iterations : " << kmax << std::endl; + } +}; + +} // random + +} // apex